mirror of
https://github.com/fadden/6502bench.git
synced 2024-07-07 07:28:57 +00:00
Improve the "common" expression formatter
To avoid confusing the assembler, expressions with a leading parenthesis like "(foo & $ffff) + 1" are prefixed with a "0+". This is not necessary if the operand begins with a '#'. (issue #16)
This commit is contained in:
parent
975ae1eb28
commit
a8af7e8794
@ -344,9 +344,17 @@ namespace SourceGen.AppForms {
|
|||||||
if (operandLen == 1 && mIsPcRelative) {
|
if (operandLen == 1 && mIsPcRelative) {
|
||||||
operandLen = 2;
|
operandLen = 2;
|
||||||
}
|
}
|
||||||
|
PseudoOp.FormatNumericOpFlags flags;
|
||||||
|
if (mIsPcRelative) {
|
||||||
|
flags = PseudoOp.FormatNumericOpFlags.IsPcRel;
|
||||||
|
} else if (mShowHashPrefix) {
|
||||||
|
flags = PseudoOp.FormatNumericOpFlags.HasHashPrefix;
|
||||||
|
} else {
|
||||||
|
flags = PseudoOp.FormatNumericOpFlags.None;
|
||||||
|
}
|
||||||
string str = PseudoOp.FormatNumericOperand(mFormatter,
|
string str = PseudoOp.FormatNumericOperand(mFormatter,
|
||||||
mProject.SymbolTable, null, dfd,
|
mProject.SymbolTable, null, dfd,
|
||||||
mOperandValue, operandLen, mIsPcRelative);
|
mOperandValue, operandLen, flags);
|
||||||
preview.Append(str);
|
preview.Append(str);
|
||||||
|
|
||||||
if (sym.SymbolSource == Symbol.Source.Auto) {
|
if (sym.SymbolSource == Symbol.Source.Auto) {
|
||||||
|
@ -364,7 +364,8 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = sDataOpNames.GetDefineData(length);
|
opcodeStr = sDataOpNames.GetDefineData(length);
|
||||||
operand = RawData.GetWord(data, offset, length, false);
|
operand = RawData.GetWord(data, offset, length, false);
|
||||||
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
||||||
mLocalizer.LabelMap, dfd, operand, length, false);
|
mLocalizer.LabelMap, dfd, operand, length,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.NumericBE:
|
case FormatDescriptor.Type.NumericBE:
|
||||||
opcodeStr = sDataOpNames.GetDefineBigData(length);
|
opcodeStr = sDataOpNames.GetDefineBigData(length);
|
||||||
@ -374,7 +375,8 @@ namespace SourceGen.AsmGen {
|
|||||||
} else {
|
} else {
|
||||||
operand = RawData.GetWord(data, offset, length, true);
|
operand = RawData.GetWord(data, offset, length, true);
|
||||||
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
||||||
mLocalizer.LabelMap, dfd, operand, length, false);
|
mLocalizer.LabelMap, dfd, operand, length,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.Fill:
|
case FormatDescriptor.Type.Fill:
|
||||||
|
@ -268,7 +268,8 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = sDataOpNames.GetDefineData(length);
|
opcodeStr = sDataOpNames.GetDefineData(length);
|
||||||
operand = RawData.GetWord(data, offset, length, false);
|
operand = RawData.GetWord(data, offset, length, false);
|
||||||
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
||||||
mLocalizer.LabelMap, dfd, operand, length, false);
|
mLocalizer.LabelMap, dfd, operand, length,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.NumericBE:
|
case FormatDescriptor.Type.NumericBE:
|
||||||
opcodeStr = sDataOpNames.GetDefineBigData(length);
|
opcodeStr = sDataOpNames.GetDefineBigData(length);
|
||||||
@ -278,7 +279,8 @@ namespace SourceGen.AsmGen {
|
|||||||
} else {
|
} else {
|
||||||
operand = RawData.GetWord(data, offset, length, true);
|
operand = RawData.GetWord(data, offset, length, true);
|
||||||
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
||||||
mLocalizer.LabelMap, dfd, operand, length, false);
|
mLocalizer.LabelMap, dfd, operand, length,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.Fill:
|
case FormatDescriptor.Type.Fill:
|
||||||
|
@ -336,7 +336,8 @@ namespace SourceGen.AsmGen {
|
|||||||
opcodeStr = sDataOpNames.GetDefineData(length);
|
opcodeStr = sDataOpNames.GetDefineData(length);
|
||||||
operand = RawData.GetWord(data, offset, length, false);
|
operand = RawData.GetWord(data, offset, length, false);
|
||||||
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
||||||
mLocalizer.LabelMap, dfd, operand, length, false);
|
mLocalizer.LabelMap, dfd, operand, length,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.NumericBE:
|
case FormatDescriptor.Type.NumericBE:
|
||||||
opcodeStr = sDataOpNames.GetDefineBigData(length);
|
opcodeStr = sDataOpNames.GetDefineBigData(length);
|
||||||
@ -346,7 +347,8 @@ namespace SourceGen.AsmGen {
|
|||||||
} else {
|
} else {
|
||||||
operand = RawData.GetWord(data, offset, length, true);
|
operand = RawData.GetWord(data, offset, length, true);
|
||||||
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
|
||||||
mLocalizer.LabelMap, dfd, operand, length, false);
|
mLocalizer.LabelMap, dfd, operand, length,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.Fill:
|
case FormatDescriptor.Type.Fill:
|
||||||
|
@ -141,7 +141,8 @@ namespace SourceGen.AsmGen {
|
|||||||
foreach (DefSymbol defSym in proj.ActiveDefSymbolList) {
|
foreach (DefSymbol defSym in proj.ActiveDefSymbolList) {
|
||||||
// Use an operand length of 1 so things are shown as concisely as possible.
|
// Use an operand length of 1 so things are shown as concisely as possible.
|
||||||
string valueStr = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
string valueStr = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
gen.Localizer.LabelMap, defSym.DataDescriptor, defSym.Value, 1, false);
|
gen.Localizer.LabelMap, defSym.DataDescriptor, defSym.Value, 1,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
gen.OutputEquDirective(defSym.Label, valueStr, defSym.Comment);
|
gen.OutputEquDirective(defSym.Label, valueStr, defSym.Comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +177,7 @@ namespace SourceGen.AsmGen {
|
|||||||
|
|
||||||
string formattedOperand = null;
|
string formattedOperand = null;
|
||||||
int operandLen = instrLen - 1;
|
int operandLen = instrLen - 1;
|
||||||
bool isPcRel = false;
|
PseudoOp.FormatNumericOpFlags opFlags = PseudoOp.FormatNumericOpFlags.None;
|
||||||
bool isPcRelBankWrap = false;
|
bool isPcRelBankWrap = false;
|
||||||
|
|
||||||
// Tweak branch instructions. We want to show the absolute address rather
|
// Tweak branch instructions. We want to show the absolute address rather
|
||||||
@ -185,12 +186,16 @@ namespace SourceGen.AsmGen {
|
|||||||
if (op.AddrMode == OpDef.AddressMode.PCRel) {
|
if (op.AddrMode == OpDef.AddressMode.PCRel) {
|
||||||
Debug.Assert(attr.OperandAddress >= 0);
|
Debug.Assert(attr.OperandAddress >= 0);
|
||||||
operandLen = 2;
|
operandLen = 2;
|
||||||
isPcRel = true;
|
opFlags = PseudoOp.FormatNumericOpFlags.IsPcRel;
|
||||||
} else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
|
} else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
|
||||||
op.AddrMode == OpDef.AddressMode.StackPCRelLong) {
|
op.AddrMode == OpDef.AddressMode.StackPCRelLong) {
|
||||||
isPcRel = true;
|
opFlags = PseudoOp.FormatNumericOpFlags.IsPcRel;
|
||||||
|
} else if (op.AddrMode == OpDef.AddressMode.Imm ||
|
||||||
|
op.AddrMode == OpDef.AddressMode.ImmLongA ||
|
||||||
|
op.AddrMode == OpDef.AddressMode.ImmLongXY) {
|
||||||
|
opFlags = PseudoOp.FormatNumericOpFlags.HasHashPrefix;
|
||||||
}
|
}
|
||||||
if (isPcRel) {
|
if (opFlags == PseudoOp.FormatNumericOpFlags.IsPcRel) {
|
||||||
int branchDist = attr.Address - attr.OperandAddress;
|
int branchDist = attr.Address - attr.OperandAddress;
|
||||||
isPcRelBankWrap = branchDist > 32767 || branchDist < -32768;
|
isPcRelBankWrap = branchDist > 32767 || branchDist < -32768;
|
||||||
}
|
}
|
||||||
@ -209,9 +214,11 @@ namespace SourceGen.AsmGen {
|
|||||||
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
|
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
|
||||||
// Special handling for the double-operand block move.
|
// Special handling for the double-operand block move.
|
||||||
string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
gen.Localizer.LabelMap, attr.DataDescriptor, operand >> 8, 1, false);
|
gen.Localizer.LabelMap, attr.DataDescriptor, operand >> 8, 1,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
gen.Localizer.LabelMap, attr.DataDescriptor, operand & 0xff, 1, false);
|
gen.Localizer.LabelMap, attr.DataDescriptor, operand & 0xff, 1,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
if (gen.Quirks.BlockMoveArgsReversed) {
|
if (gen.Quirks.BlockMoveArgsReversed) {
|
||||||
string tmp = opstr1;
|
string tmp = opstr1;
|
||||||
opstr1 = opstr2;
|
opstr1 = opstr2;
|
||||||
@ -221,7 +228,7 @@ namespace SourceGen.AsmGen {
|
|||||||
} else {
|
} else {
|
||||||
formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
gen.Localizer.LabelMap, attr.DataDescriptor,
|
gen.Localizer.LabelMap, attr.DataDescriptor,
|
||||||
operandForSymbol, operandLen, isPcRel);
|
operandForSymbol, operandLen, opFlags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Show operand value in hex.
|
// Show operand value in hex.
|
||||||
|
@ -813,7 +813,8 @@ namespace SourceGen {
|
|||||||
line = new Line(DefSymOffsetFromIndex(index), 0, Line.Type.EquDirective);
|
line = new Line(DefSymOffsetFromIndex(index), 0, Line.Type.EquDirective);
|
||||||
// Use an operand length of 1 so things are shown as concisely as possible.
|
// Use an operand length of 1 so things are shown as concisely as possible.
|
||||||
string valueStr = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
string valueStr = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
null, defSym.DataDescriptor, defSym.Value, 1, false);
|
null, defSym.DataDescriptor, defSym.Value, 1,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
string comment = formatter.FormatEolComment(defSym.Comment);
|
string comment = formatter.FormatEolComment(defSym.Comment);
|
||||||
parts = FormattedParts.CreateEquDirective(defSym.Label,
|
parts = FormattedParts.CreateEquDirective(defSym.Label,
|
||||||
formatter.FormatPseudoOp(opNames.EquDirective),
|
formatter.FormatPseudoOp(opNames.EquDirective),
|
||||||
@ -1099,7 +1100,7 @@ namespace SourceGen {
|
|||||||
|
|
||||||
string formattedOperand = null;
|
string formattedOperand = null;
|
||||||
int operandLen = instrLen - 1;
|
int operandLen = instrLen - 1;
|
||||||
bool isPcRel = false;
|
PseudoOp.FormatNumericOpFlags opFlags = PseudoOp.FormatNumericOpFlags.None;
|
||||||
|
|
||||||
// Tweak branch instructions. We want to show the absolute address rather
|
// Tweak branch instructions. We want to show the absolute address rather
|
||||||
// than the relative offset (which happens with the OperandAddress assignment
|
// than the relative offset (which happens with the OperandAddress assignment
|
||||||
@ -1107,10 +1108,14 @@ namespace SourceGen {
|
|||||||
if (op.AddrMode == OpDef.AddressMode.PCRel) {
|
if (op.AddrMode == OpDef.AddressMode.PCRel) {
|
||||||
Debug.Assert(attr.OperandAddress >= 0);
|
Debug.Assert(attr.OperandAddress >= 0);
|
||||||
operandLen = 2;
|
operandLen = 2;
|
||||||
isPcRel = true;
|
opFlags = PseudoOp.FormatNumericOpFlags.IsPcRel;
|
||||||
} else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
|
} else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
|
||||||
op.AddrMode == OpDef.AddressMode.StackPCRelLong) {
|
op.AddrMode == OpDef.AddressMode.StackPCRelLong) {
|
||||||
isPcRel = true;
|
opFlags = PseudoOp.FormatNumericOpFlags.IsPcRel;
|
||||||
|
} else if (op.AddrMode == OpDef.AddressMode.Imm ||
|
||||||
|
op.AddrMode == OpDef.AddressMode.ImmLongA ||
|
||||||
|
op.AddrMode == OpDef.AddressMode.ImmLongXY) {
|
||||||
|
opFlags = PseudoOp.FormatNumericOpFlags.HasHashPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the OperandAddress when available. This is important for relative branch
|
// Use the OperandAddress when available. This is important for relative branch
|
||||||
@ -1130,13 +1135,15 @@ namespace SourceGen {
|
|||||||
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
|
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
|
||||||
// Special handling for the double-operand block move.
|
// Special handling for the double-operand block move.
|
||||||
string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
null, attr.DataDescriptor, operand >> 8, 1, false);
|
null, attr.DataDescriptor, operand >> 8, 1,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
null, attr.DataDescriptor, operand & 0xff, 1, false);
|
null, attr.DataDescriptor, operand & 0xff, 1,
|
||||||
|
PseudoOp.FormatNumericOpFlags.None);
|
||||||
formattedOperand = opstr1 + "," + opstr2;
|
formattedOperand = opstr1 + "," + opstr2;
|
||||||
} else {
|
} else {
|
||||||
formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
|
||||||
null, attr.DataDescriptor, operandForSymbol, operandLen, isPcRel);
|
null, attr.DataDescriptor, operandForSymbol, operandLen, opFlags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Show operand value in hex.
|
// Show operand value in hex.
|
||||||
|
@ -289,13 +289,13 @@ namespace SourceGen {
|
|||||||
po.Opcode = opNames.GetDefineData(length);
|
po.Opcode = opNames.GetDefineData(length);
|
||||||
operand = RawData.GetWord(data, offset, length, false);
|
operand = RawData.GetWord(data, offset, length, false);
|
||||||
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
||||||
operand, length, false);
|
operand, length, FormatNumericOpFlags.None);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.NumericBE:
|
case FormatDescriptor.Type.NumericBE:
|
||||||
po.Opcode = opNames.GetDefineBigData(length);
|
po.Opcode = opNames.GetDefineBigData(length);
|
||||||
operand = RawData.GetWord(data, offset, length, true);
|
operand = RawData.GetWord(data, offset, length, true);
|
||||||
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
po.Operand = FormatNumericOperand(formatter, symbolTable, labelMap, dfd,
|
||||||
operand, length, false);
|
operand, length, FormatNumericOpFlags.None);
|
||||||
break;
|
break;
|
||||||
case FormatDescriptor.Type.Fill:
|
case FormatDescriptor.Type.Fill:
|
||||||
po.Opcode = opNames.Fill;
|
po.Opcode = opNames.Fill;
|
||||||
@ -509,6 +509,15 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Special formatting flags for the FormatNumericOperand() method.
|
||||||
|
/// </summary>
|
||||||
|
public enum FormatNumericOpFlags {
|
||||||
|
None = 0,
|
||||||
|
IsPcRel, // opcode is PC relative, e.g. branch or PER
|
||||||
|
HasHashPrefix, // operand has a leading '#', avoiding ambiguity in some cases
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Format a numeric operand value according to the specified sub-format.
|
/// Format a numeric operand value according to the specified sub-format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -521,11 +530,10 @@ namespace SourceGen {
|
|||||||
/// out of the code, for relative branches it's a 24-bit absolute address.</param>
|
/// out of the code, for relative branches it's a 24-bit absolute address.</param>
|
||||||
/// <param name="operandLen">Length of operand, in bytes. For an instruction, this
|
/// <param name="operandLen">Length of operand, in bytes. For an instruction, this
|
||||||
/// does not include the opcode byte. For a relative branch, this will be 2.</param>
|
/// does not include the opcode byte. For a relative branch, this will be 2.</param>
|
||||||
/// <param name="isPcRel">Set to true if the actual operand is a PC-relative value.
|
/// <param name="flags">Special handling.</param>
|
||||||
/// These get slightly different treatment.</param>
|
|
||||||
public static string FormatNumericOperand(Formatter formatter, SymbolTable symbolTable,
|
public static string FormatNumericOperand(Formatter formatter, SymbolTable symbolTable,
|
||||||
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
||||||
int operandValue, int operandLen, bool isPcRel) {
|
int operandValue, int operandLen, FormatNumericOpFlags flags) {
|
||||||
Debug.Assert(operandLen > 0);
|
Debug.Assert(operandLen > 0);
|
||||||
int hexMinLen = operandLen * 2;
|
int hexMinLen = operandLen * 2;
|
||||||
|
|
||||||
@ -547,15 +555,15 @@ namespace SourceGen {
|
|||||||
switch (formatter.ExpressionMode) {
|
switch (formatter.ExpressionMode) {
|
||||||
case Formatter.FormatConfig.ExpressionMode.Common:
|
case Formatter.FormatConfig.ExpressionMode.Common:
|
||||||
FormatNumericSymbolCommon(formatter, sym, labelMap,
|
FormatNumericSymbolCommon(formatter, sym, labelMap,
|
||||||
dfd, operandValue, operandLen, isPcRel, sb);
|
dfd, operandValue, operandLen, flags, sb);
|
||||||
break;
|
break;
|
||||||
case Formatter.FormatConfig.ExpressionMode.Cc65:
|
case Formatter.FormatConfig.ExpressionMode.Cc65:
|
||||||
FormatNumericSymbolCc65(formatter, sym, labelMap,
|
FormatNumericSymbolCc65(formatter, sym, labelMap,
|
||||||
dfd, operandValue, operandLen, isPcRel, sb);
|
dfd, operandValue, operandLen, flags, sb);
|
||||||
break;
|
break;
|
||||||
case Formatter.FormatConfig.ExpressionMode.Merlin:
|
case Formatter.FormatConfig.ExpressionMode.Merlin:
|
||||||
FormatNumericSymbolMerlin(formatter, sym, labelMap,
|
FormatNumericSymbolMerlin(formatter, sym, labelMap,
|
||||||
dfd, operandValue, operandLen, isPcRel, sb);
|
dfd, operandValue, operandLen, flags, sb);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "Unknown expression mode " +
|
Debug.Assert(false, "Unknown expression mode " +
|
||||||
@ -578,7 +586,7 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void FormatNumericSymbolCommon(Formatter formatter, Symbol sym,
|
private static void FormatNumericSymbolCommon(Formatter formatter, Symbol sym,
|
||||||
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
||||||
int operandValue, int operandLen, bool isPcRel, StringBuilder sb) {
|
int operandValue, int operandLen, FormatNumericOpFlags flags, StringBuilder sb) {
|
||||||
// We could have some simple code that generated correct output, shifting and
|
// We could have some simple code that generated correct output, shifting and
|
||||||
// masking every time, but that's ugly and annoying. For single-byte ops we can
|
// masking every time, but that's ugly and annoying. For single-byte ops we can
|
||||||
// just use the byte-select operators, for wider ops we get only as fancy as we
|
// just use the byte-select operators, for wider ops we get only as fancy as we
|
||||||
@ -645,7 +653,7 @@ namespace SourceGen {
|
|||||||
rightShift = 0;
|
rightShift = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPcRel) {
|
if (flags == FormatNumericOpFlags.IsPcRel) {
|
||||||
// PC-relative operands are funny, because an 8- or 16-bit value is always
|
// PC-relative operands are funny, because an 8- or 16-bit value is always
|
||||||
// expanded to 24 bits. We output a 16-bit value that the assembler will
|
// expanded to 24 bits. We output a 16-bit value that the assembler will
|
||||||
// convert back to 8-bit or 16-bit. In any event, the bank byte is never
|
// convert back to 8-bit or 16-bit. In any event, the bank byte is never
|
||||||
@ -670,10 +678,13 @@ namespace SourceGen {
|
|||||||
// ((label >> rightShift) & mask) [+ adj]
|
// ((label >> rightShift) & mask) [+ adj]
|
||||||
|
|
||||||
if (rightShift != 0 || needMask) {
|
if (rightShift != 0 || needMask) {
|
||||||
|
if (flags != FormatNumericOpFlags.HasHashPrefix) {
|
||||||
|
sb.Append("0+");
|
||||||
|
}
|
||||||
if (rightShift != 0 && needMask) {
|
if (rightShift != 0 && needMask) {
|
||||||
sb.Append("0+((");
|
sb.Append("((");
|
||||||
} else {
|
} else {
|
||||||
sb.Append("0+(");
|
sb.Append("(");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.Append(symLabel);
|
sb.Append(symLabel);
|
||||||
@ -705,7 +716,7 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void FormatNumericSymbolCc65(Formatter formatter, Symbol sym,
|
private static void FormatNumericSymbolCc65(Formatter formatter, Symbol sym,
|
||||||
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
||||||
int operandValue, int operandLen, bool isPcRel, StringBuilder sb) {
|
int operandValue, int operandLen, FormatNumericOpFlags flags, StringBuilder sb) {
|
||||||
// The key difference between cc65 and other assemblers with general expressions
|
// The key difference between cc65 and other assemblers with general expressions
|
||||||
// is that the bitwise shift and AND operators have higher precedence than the
|
// is that the bitwise shift and AND operators have higher precedence than the
|
||||||
// arithmetic ops like add and subtract. (The bitwise ops are equal to multiply
|
// arithmetic ops like add and subtract. (The bitwise ops are equal to multiply
|
||||||
@ -758,7 +769,7 @@ namespace SourceGen {
|
|||||||
shOp = "";
|
shOp = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPcRel) {
|
if (flags == FormatNumericOpFlags.IsPcRel) {
|
||||||
// PC-relative operands are funny, because an 8- or 16-bit value is always
|
// PC-relative operands are funny, because an 8- or 16-bit value is always
|
||||||
// expanded to 24 bits. We output a 16-bit value that the assembler will
|
// expanded to 24 bits. We output a 16-bit value that the assembler will
|
||||||
// convert back to 8-bit or 16-bit. In any event, the bank byte is never
|
// convert back to 8-bit or 16-bit. In any event, the bank byte is never
|
||||||
@ -796,7 +807,7 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void FormatNumericSymbolMerlin(Formatter formatter, Symbol sym,
|
private static void FormatNumericSymbolMerlin(Formatter formatter, Symbol sym,
|
||||||
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
Dictionary<string, string> labelMap, FormatDescriptor dfd,
|
||||||
int operandValue, int operandLen, bool isPcRel, StringBuilder sb) {
|
int operandValue, int operandLen, FormatNumericOpFlags flags, StringBuilder sb) {
|
||||||
// Merlin expressions are compatible with the original 8-bit Merlin. They're
|
// Merlin expressions are compatible with the original 8-bit Merlin. They're
|
||||||
// evaluated from left to right, with (almost) no regard for operator precedence.
|
// evaluated from left to right, with (almost) no regard for operator precedence.
|
||||||
//
|
//
|
||||||
|
@ -61,21 +61,21 @@ start clc
|
|||||||
lda #zip+16
|
lda #zip+16
|
||||||
lda #zip+64
|
lda #zip+64
|
||||||
lda #absl
|
lda #absl
|
||||||
lda #0+(absl >> 8)
|
lda #(absl >> 8)
|
||||||
lda #absl-4096
|
lda #absl-4096
|
||||||
lda #0+(absl >> 8)-16
|
lda #(absl >> 8)-16
|
||||||
lda #0+(absl >> 16)
|
lda #(absl >> 16)
|
||||||
lda #absh
|
lda #absh
|
||||||
lda #0+(absh >> 8)
|
lda #(absh >> 8)
|
||||||
lda #absh-61440
|
lda #absh-61440
|
||||||
lda #0+(absh >> 8)+16
|
lda #(absh >> 8)+16
|
||||||
lda #0+(absh >> 16)+1
|
lda #(absh >> 16)+1
|
||||||
lda #0+(start & $ffff)
|
lda #(start & $ffff)
|
||||||
lda #0+(start >> 8)
|
lda #(start >> 8)
|
||||||
lda #0+(start >> 16)
|
lda #(start >> 16)
|
||||||
lda #0+(biggie & $ffff)
|
lda #(biggie & $ffff)
|
||||||
lda #0+(biggie >> 8)
|
lda #(biggie >> 8)
|
||||||
lda #0+(biggie >> 16)
|
lda #(biggie >> 16)
|
||||||
bra skipdata
|
bra skipdata
|
||||||
|
|
||||||
.byte zip
|
.byte zip
|
||||||
@ -113,7 +113,7 @@ start clc
|
|||||||
.dword 0+(start >> 8)
|
.dword 0+(start >> 8)
|
||||||
.dword 0+(start >> 16)
|
.dword 0+(start >> 16)
|
||||||
|
|
||||||
skipdata lda #0+(biggie >> 16)-1
|
skipdata lda #(biggie >> 16)-1
|
||||||
mvn `biggie,(`biggie)-17
|
mvn `biggie,(`biggie)-17
|
||||||
mvp `start,(`start)+17
|
mvp `start,(`start)+17
|
||||||
mvn 18,1
|
mvn 18,1
|
||||||
@ -201,9 +201,9 @@ L118E lda #<thirty2+2
|
|||||||
rep #$30
|
rep #$30
|
||||||
.al
|
.al
|
||||||
.xl
|
.xl
|
||||||
lda #0+(thirty2 & $ffff)+3
|
lda #(thirty2 & $ffff)+3
|
||||||
lda #0+((thirty2 >> 8) & $ffff)+4
|
lda #((thirty2 >> 8) & $ffff)+4
|
||||||
lda #0+(thirty2 >> 16)
|
lda #(thirty2 >> 16)
|
||||||
rts
|
rts
|
||||||
|
|
||||||
.here
|
.here
|
||||||
|
Loading…
Reference in New Issue
Block a user