1
0
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:
Andy McFadden 2018-10-26 15:45:39 -07:00
parent 975ae1eb28
commit a8af7e8794
8 changed files with 92 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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