mirror of
https://github.com/fadden/6502bench.git
synced 2024-06-11 17:29:29 +00:00
Optionally treat BRKs as two-byte instructions
Early data sheets listed BRK as one byte, but RTI after a BRK skips the following byte, effectively making BRK a 2-byte instruction. Sometimes, such as when diassembling Apple /// SOS code, it's handy to treat it that way explicitly. This change makes two-byte BRKs optional, controlled by a checkbox in the project settings. In the system definitions it defaults to true for Apple ///, false for all others. ACME doesn't allow BRK to have an arg, and cc65 only allows it for 65816 code (?), so it's emitted as a hex blob for those assemblers. Anyone wishing to target those assemblers should stick to 1-byte mode. Extension scripts have to switch between formatting one byte of inline data and formatting an instruction with a one-byte operand. A helper function has been added to the plugin Util class. To get some regression test coverage, 2022-extension-scripts has been configured to use two-byte BRK. Also, added/corrected some SOS constants. See also issue #44.
This commit is contained in:
parent
b8e11215fa
commit
dfd5bcab1b
|
@ -146,7 +146,8 @@ namespace Asm65 {
|
||||||
/// <param name="includeUndocumented">Set to true if "undocumented" opcodes should
|
/// <param name="includeUndocumented">Set to true if "undocumented" opcodes should
|
||||||
/// be included in the definition.</param>
|
/// be included in the definition.</param>
|
||||||
/// <returns>Best CpuDef.</returns>
|
/// <returns>Best CpuDef.</returns>
|
||||||
public static CpuDef GetBestMatch(CpuType type, bool includeUndocumented) {
|
public static CpuDef GetBestMatch(CpuType type, bool includeUndocumented,
|
||||||
|
bool twoByteBrk) {
|
||||||
// Many 65xx variants boil down to a 6502, 65C02, or 65816, at least as far as
|
// Many 65xx variants boil down to a 6502, 65C02, or 65816, at least as far as
|
||||||
// a disassembler needs to know. These do not, and would need full definitions:
|
// a disassembler needs to know. These do not, and would need full definitions:
|
||||||
//
|
//
|
||||||
|
@ -190,6 +191,16 @@ namespace Asm65 {
|
||||||
cpuDef = stripped;
|
cpuDef = stripped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we want two-byte BRKs, replace the entry with the StackInt form. Copy the rest.
|
||||||
|
if (twoByteBrk) {
|
||||||
|
CpuDef bigBrkDef = new CpuDef(cpuDef);
|
||||||
|
bigBrkDef.mOpDefs[0] = OpDef.OpBRK_StackInt;
|
||||||
|
for (int i = 1; i < 256; i++) {
|
||||||
|
bigBrkDef.mOpDefs[i] = cpuDef.mOpDefs[i];
|
||||||
|
}
|
||||||
|
cpuDef = bigBrkDef;
|
||||||
|
}
|
||||||
|
|
||||||
cpuDef.HasUndocumented = includeUndocumented;
|
cpuDef.HasUndocumented = includeUndocumented;
|
||||||
|
|
||||||
return cpuDef;
|
return cpuDef;
|
||||||
|
|
|
@ -733,7 +733,7 @@ namespace Asm65 {
|
||||||
case AddressMode.DP:
|
case AddressMode.DP:
|
||||||
case AddressMode.PCRel:
|
case AddressMode.PCRel:
|
||||||
case AddressMode.PCRelLong: // BRL
|
case AddressMode.PCRelLong: // BRL
|
||||||
case AddressMode.StackInt: // COP
|
case AddressMode.StackInt: // COP and two-byte BRK
|
||||||
case AddressMode.StackPCRelLong: // PER
|
case AddressMode.StackPCRelLong: // PER
|
||||||
case AddressMode.WDM:
|
case AddressMode.WDM:
|
||||||
fmt = wdisStr + "{0}";
|
fmt = wdisStr + "{0}";
|
||||||
|
|
|
@ -1478,15 +1478,16 @@ namespace Asm65 {
|
||||||
AddrMode = AddressMode.Unknown
|
AddrMode = AddressMode.Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly OpDef OpBRK_Implied = new OpDef(OpBRK) {
|
public static readonly OpDef OpBRK_Implied = new OpDef(OpBRK) { // 1-byte form
|
||||||
Opcode = 0x00,
|
Opcode = 0x00,
|
||||||
// There should arguably be OpBRK_Implied for 6502/65C02 and OpBRK_StackInt for
|
|
||||||
// 65816, but in practice hardly any assemblers prefer (or even allow) it to be
|
|
||||||
// a two-byte instruction. The BRK does *act* like a two-byte instruction, but
|
|
||||||
// code rarely reflects this usage.
|
|
||||||
AddrMode = AddressMode.Implied,
|
AddrMode = AddressMode.Implied,
|
||||||
CycDef = 7 | (int)(CycleMod.OneIfE0)
|
CycDef = 7 | (int)(CycleMod.OneIfE0)
|
||||||
};
|
};
|
||||||
|
public static readonly OpDef OpBRK_StackInt = new OpDef(OpBRK) { // 2-byte form
|
||||||
|
Opcode = 0x00,
|
||||||
|
AddrMode = AddressMode.StackInt,
|
||||||
|
CycDef = 7 | (int)(CycleMod.OneIfE0)
|
||||||
|
};
|
||||||
public static readonly OpDef OpORA_DPIndexXInd = new OpDef(OpORA) {
|
public static readonly OpDef OpORA_DPIndexXInd = new OpDef(OpORA) {
|
||||||
Opcode = 0x01,
|
Opcode = 0x01,
|
||||||
AddrMode = AddressMode.DPIndexXInd,
|
AddrMode = AddressMode.DPIndexXInd,
|
||||||
|
|
|
@ -83,8 +83,9 @@ namespace PluginCommon {
|
||||||
/// The file data is only guaranteed to hold the BRK opcode byte.
|
/// The file data is only guaranteed to hold the BRK opcode byte.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="offset">Offset of the BRK instruction.</param>
|
/// <param name="offset">Offset of the BRK instruction.</param>
|
||||||
|
/// <param name="isTwoBytes">True if the CPU is configured for two-byte BRKs.</param>
|
||||||
/// <param name="noContinue">Set to true if the BRK doesn't actually return.</param>
|
/// <param name="noContinue">Set to true if the BRK doesn't actually return.</param>
|
||||||
void CheckBrk(int offset, out bool noContinue);
|
void CheckBrk(int offset, bool isTwoBytes, out bool noContinue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -123,7 +123,8 @@ namespace PluginCommon {
|
||||||
dict.Add(ps.Value, ps);
|
dict.Add(ps.Value, ps);
|
||||||
} catch (ArgumentException) {
|
} catch (ArgumentException) {
|
||||||
appRef.DebugLog("WARNING: GenerateValueList: multiple entries with " +
|
appRef.DebugLog("WARNING: GenerateValueList: multiple entries with " +
|
||||||
"value " + ps.Value.ToString("x4"));
|
"value " + ps.Value.ToString("x4") + ": " + dict[ps.Value].Label +
|
||||||
|
" and " + ps.Label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,5 +58,31 @@ namespace PluginCommon {
|
||||||
public static uint ComputeBufferCRC(byte[] data) {
|
public static uint ComputeBufferCRC(byte[] data) {
|
||||||
return CRC32.OnBuffer(0, data, 0, data.Length);
|
return CRC32.OnBuffer(0, data, 0, data.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats the byte that follows a BRK instruction. How we do this depends on
|
||||||
|
/// whether the system is configured for two-byte BRKs.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// We can actually apply the format both ways and let the app ignore the one it
|
||||||
|
/// doesn't like, but this is cleaner.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="appRef">Reference to application object.</param>
|
||||||
|
/// <param name="twoByteBrk">True if BRKs are handled as two-byte instructions.</param>
|
||||||
|
/// <param name="brkOffset">Offset of BRK instruction.</param>
|
||||||
|
/// <param name="type">Data type to apply.</param>
|
||||||
|
/// <param name="subType">Data sub-type to apply.</param>
|
||||||
|
/// <param name="label">Label, for subType=Symbol.</param>
|
||||||
|
public static void FormatBrkByte(IApplication appRef, bool twoByteBrk, int brkOffset,
|
||||||
|
DataSubType subType, string label) {
|
||||||
|
if (twoByteBrk) {
|
||||||
|
// Two-byte BRK, so we want to apply the format to the instruction itself.
|
||||||
|
appRef.SetOperandFormat(brkOffset, subType, label);
|
||||||
|
} else {
|
||||||
|
// Single-byte BRK, so we want to format the byte that follows the
|
||||||
|
// instruction as inline data.
|
||||||
|
appRef.SetInlineDataFormat(brkOffset + 1, 1, DataType.NumericLE, subType, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,8 +314,8 @@ namespace SourceGen.AsmGen {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (op == OpDef.OpWDM_WDM) {
|
if (op == OpDef.OpWDM_WDM || op == OpDef.OpBRK_StackInt) {
|
||||||
// ACME doesn't like this to have an operand. Output as hex.
|
// ACME doesn't like these to have an operand. Output as hex.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return string.Empty; // indicate original is fine
|
return string.Empty; // indicate original is fine
|
||||||
|
|
|
@ -325,8 +325,9 @@ namespace SourceGen.AsmGen {
|
||||||
|
|
||||||
// IGenerator
|
// IGenerator
|
||||||
public string ModifyOpcode(int offset, OpDef op) {
|
public string ModifyOpcode(int offset, OpDef op) {
|
||||||
if ((op == OpDef.OpWDM_WDM) && mAsmVersion < V2_18) {
|
if (op == OpDef.OpBRK_StackInt || (op == OpDef.OpWDM_WDM && mAsmVersion < V2_18)) {
|
||||||
// cc65 v2.17 doesn't support WDM, and assembles BRK <arg> to opcode $05.
|
// cc65 v2.17 doesn't support WDM, and assembles BRK <arg> to opcode $05.
|
||||||
|
// cc65 v2.18 only supports two-byte BRK on 65816 code.
|
||||||
// https://github.com/cc65/cc65/issues/715
|
// https://github.com/cc65/cc65/issues/715
|
||||||
// https://github.com/cc65/cc65/issues/716
|
// https://github.com/cc65/cc65/issues/716
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -672,7 +672,7 @@ namespace SourceGen {
|
||||||
|
|
||||||
// On first visit, check for BRK inline call.
|
// On first visit, check for BRK inline call.
|
||||||
if (firstVisit) {
|
if (firstVisit) {
|
||||||
if (op == OpDef.OpBRK_Implied) {
|
if (op == OpDef.OpBRK_Implied || op == OpDef.OpBRK_StackInt) {
|
||||||
bool noContinue = CheckForInlineCall(op, offset, !doContinue);
|
bool noContinue = CheckForInlineCall(op, offset, !doContinue);
|
||||||
if (!noContinue) {
|
if (!noContinue) {
|
||||||
// We're expected to continue execution past the BRK.
|
// We're expected to continue execution past the BRK.
|
||||||
|
@ -951,8 +951,10 @@ namespace SourceGen {
|
||||||
} else if (op == OpDef.OpJSR_AbsLong && (mPluginCaps[i] & PluginCap.JSL) != 0) {
|
} else if (op == OpDef.OpJSR_AbsLong && (mPluginCaps[i] & PluginCap.JSL) != 0) {
|
||||||
((IPlugin_InlineJsl)script).CheckJsl(offset, out bool noCont);
|
((IPlugin_InlineJsl)script).CheckJsl(offset, out bool noCont);
|
||||||
noContinue |= noCont;
|
noContinue |= noCont;
|
||||||
} else if (op == OpDef.OpBRK_Implied && (mPluginCaps[i] & PluginCap.BRK) != 0) {
|
} else if ((op == OpDef.OpBRK_Implied || op == OpDef.OpBRK_StackInt) &&
|
||||||
((IPlugin_InlineBrk)script).CheckBrk(offset, out bool noCont);
|
(mPluginCaps[i] & PluginCap.BRK) != 0) {
|
||||||
|
((IPlugin_InlineBrk)script).CheckBrk(offset, op == OpDef.OpBRK_StackInt,
|
||||||
|
out bool noCont);
|
||||||
noContinue &= noCont;
|
noContinue &= noCont;
|
||||||
}
|
}
|
||||||
} catch (PluginException plex) {
|
} catch (PluginException plex) {
|
||||||
|
|
|
@ -239,6 +239,7 @@ namespace SourceGen {
|
||||||
// system definition.
|
// system definition.
|
||||||
ProjectProps.CpuType = CpuDef.CpuType.Cpu65816;
|
ProjectProps.CpuType = CpuDef.CpuType.Cpu65816;
|
||||||
ProjectProps.IncludeUndocumentedInstr = false;
|
ProjectProps.IncludeUndocumentedInstr = false;
|
||||||
|
ProjectProps.TwoByteBrk = false;
|
||||||
UpdateCpuDef();
|
UpdateCpuDef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +282,8 @@ namespace SourceGen {
|
||||||
public void ApplySystemDef(SystemDef sysDef) {
|
public void ApplySystemDef(SystemDef sysDef) {
|
||||||
CpuDef.CpuType cpuType = CpuDef.GetCpuTypeFromName(sysDef.Cpu);
|
CpuDef.CpuType cpuType = CpuDef.GetCpuTypeFromName(sysDef.Cpu);
|
||||||
bool includeUndoc = SystemDefaults.GetUndocumentedOpcodes(sysDef);
|
bool includeUndoc = SystemDefaults.GetUndocumentedOpcodes(sysDef);
|
||||||
CpuDef tmpDef = CpuDef.GetBestMatch(cpuType, includeUndoc);
|
bool twoByteBrk = SystemDefaults.GetTwoByteBrk(sysDef);
|
||||||
|
CpuDef tmpDef = CpuDef.GetBestMatch(cpuType, includeUndoc, twoByteBrk);
|
||||||
|
|
||||||
// Store the best-matched CPU in properties, rather than whichever was originally
|
// Store the best-matched CPU in properties, rather than whichever was originally
|
||||||
// requested. This way the behavior of the project is the same for everyone, even
|
// requested. This way the behavior of the project is the same for everyone, even
|
||||||
|
@ -289,6 +291,7 @@ namespace SourceGen {
|
||||||
// originally-specified CPU.
|
// originally-specified CPU.
|
||||||
ProjectProps.CpuType = tmpDef.Type;
|
ProjectProps.CpuType = tmpDef.Type;
|
||||||
ProjectProps.IncludeUndocumentedInstr = includeUndoc;
|
ProjectProps.IncludeUndocumentedInstr = includeUndoc;
|
||||||
|
ProjectProps.TwoByteBrk = twoByteBrk;
|
||||||
UpdateCpuDef();
|
UpdateCpuDef();
|
||||||
|
|
||||||
ProjectProps.AnalysisParams.DefaultTextScanMode =
|
ProjectProps.AnalysisParams.DefaultTextScanMode =
|
||||||
|
@ -325,7 +328,7 @@ namespace SourceGen {
|
||||||
|
|
||||||
public void UpdateCpuDef() {
|
public void UpdateCpuDef() {
|
||||||
CpuDef = CpuDef.GetBestMatch(ProjectProps.CpuType,
|
CpuDef = CpuDef.GetBestMatch(ProjectProps.CpuType,
|
||||||
ProjectProps.IncludeUndocumentedInstr);
|
ProjectProps.IncludeUndocumentedInstr, ProjectProps.TwoByteBrk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -188,6 +188,7 @@ namespace SourceGen {
|
||||||
public class SerProjectProperties {
|
public class SerProjectProperties {
|
||||||
public string CpuName { get; set; }
|
public string CpuName { get; set; }
|
||||||
public bool IncludeUndocumentedInstr { get; set; }
|
public bool IncludeUndocumentedInstr { get; set; }
|
||||||
|
public bool TwoByteBrk { get; set; }
|
||||||
public int EntryFlags { get; set; }
|
public int EntryFlags { get; set; }
|
||||||
public string AutoLabelStyle { get; set; }
|
public string AutoLabelStyle { get; set; }
|
||||||
public SerAnalysisParameters AnalysisParams { get; set; }
|
public SerAnalysisParameters AnalysisParams { get; set; }
|
||||||
|
@ -199,6 +200,7 @@ namespace SourceGen {
|
||||||
public SerProjectProperties(ProjectProperties props) {
|
public SerProjectProperties(ProjectProperties props) {
|
||||||
CpuName = Asm65.CpuDef.GetCpuNameFromType(props.CpuType);
|
CpuName = Asm65.CpuDef.GetCpuNameFromType(props.CpuType);
|
||||||
IncludeUndocumentedInstr = props.IncludeUndocumentedInstr;
|
IncludeUndocumentedInstr = props.IncludeUndocumentedInstr;
|
||||||
|
TwoByteBrk = props.TwoByteBrk;
|
||||||
EntryFlags = props.EntryFlags.AsInt;
|
EntryFlags = props.EntryFlags.AsInt;
|
||||||
AutoLabelStyle = props.AutoLabelStyle.ToString();
|
AutoLabelStyle = props.AutoLabelStyle.ToString();
|
||||||
AnalysisParams = new SerAnalysisParameters(props.AnalysisParams);
|
AnalysisParams = new SerAnalysisParameters(props.AnalysisParams);
|
||||||
|
@ -495,6 +497,7 @@ namespace SourceGen {
|
||||||
// Deserialize ProjectProperties: misc items.
|
// Deserialize ProjectProperties: misc items.
|
||||||
proj.ProjectProps.CpuType = Asm65.CpuDef.GetCpuTypeFromName(spf.ProjectProps.CpuName);
|
proj.ProjectProps.CpuType = Asm65.CpuDef.GetCpuTypeFromName(spf.ProjectProps.CpuName);
|
||||||
proj.ProjectProps.IncludeUndocumentedInstr = spf.ProjectProps.IncludeUndocumentedInstr;
|
proj.ProjectProps.IncludeUndocumentedInstr = spf.ProjectProps.IncludeUndocumentedInstr;
|
||||||
|
proj.ProjectProps.TwoByteBrk = spf.ProjectProps.TwoByteBrk;
|
||||||
proj.ProjectProps.EntryFlags = Asm65.StatusFlags.FromInt(spf.ProjectProps.EntryFlags);
|
proj.ProjectProps.EntryFlags = Asm65.StatusFlags.FromInt(spf.ProjectProps.EntryFlags);
|
||||||
if (Enum.TryParse<AutoLabel.Style>(spf.ProjectProps.AutoLabelStyle,
|
if (Enum.TryParse<AutoLabel.Style>(spf.ProjectProps.AutoLabelStyle,
|
||||||
out AutoLabel.Style als)) {
|
out AutoLabel.Style als)) {
|
||||||
|
|
|
@ -80,6 +80,11 @@ namespace SourceGen {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IncludeUndocumentedInstr { get; set; }
|
public bool IncludeUndocumentedInstr { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should we treat BRK instructions as 2 bytes?
|
||||||
|
/// </summary>
|
||||||
|
public bool TwoByteBrk { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initial status flags at entry points.
|
/// Initial status flags at entry points.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -129,6 +134,7 @@ namespace SourceGen {
|
||||||
public ProjectProperties(ProjectProperties src) : this() {
|
public ProjectProperties(ProjectProperties src) : this() {
|
||||||
CpuType = src.CpuType;
|
CpuType = src.CpuType;
|
||||||
IncludeUndocumentedInstr = src.IncludeUndocumentedInstr;
|
IncludeUndocumentedInstr = src.IncludeUndocumentedInstr;
|
||||||
|
TwoByteBrk = src.TwoByteBrk;
|
||||||
EntryFlags = src.EntryFlags;
|
EntryFlags = src.EntryFlags;
|
||||||
AutoLabelStyle = src.AutoLabelStyle;
|
AutoLabelStyle = src.AutoLabelStyle;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace RuntimeData.Apple {
|
||||||
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, SOS_MLI_TAG, appRef);
|
mFunctionList = PlSymbol.GeneratePlatformValueList(plSyms, SOS_MLI_TAG, appRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckBrk(int offset, out bool noContinue) {
|
public void CheckBrk(int offset, bool twoByteBrk, out bool noContinue) {
|
||||||
noContinue = true;
|
noContinue = true;
|
||||||
if (offset + 4 >= mFileData.Length) {
|
if (offset + 4 >= mFileData.Length) {
|
||||||
// ran off the end
|
// ran off the end
|
||||||
|
@ -75,8 +75,7 @@ namespace RuntimeData.Apple {
|
||||||
if (!mFunctionList.TryGetValue(req, out sym)) {
|
if (!mFunctionList.TryGetValue(req, out sym)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mAppRef.SetInlineDataFormat(offset + 1, 1, DataType.NumericLE,
|
Util.FormatBrkByte(mAppRef, twoByteBrk, offset, DataSubType.Symbol, sym.Label);
|
||||||
DataSubType.Symbol, sym.Label);
|
|
||||||
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
||||||
DataSubType.Address, null);
|
DataSubType.Address, null);
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
; See the LICENSE.txt file for distribution terms (Apache 2.0).
|
||||||
;
|
;
|
||||||
; Source: SOS programmer's guide
|
; Source: SOS programmer's guide
|
||||||
|
; SOS Reference Manual, Volume 2 (Apple 1982)
|
||||||
|
|
||||||
*SYNOPSIS SOS constants.
|
*SYNOPSIS Apple /// Sophisticated Operating System constants.
|
||||||
|
|
||||||
; SOS MLI function codes.
|
; SOS MLI function codes.
|
||||||
*TAG SOS-MLI-Functions
|
*TAG SOS-MLI-Functions
|
||||||
|
@ -15,11 +16,17 @@ SOS_GET_SEG_INFO = $43
|
||||||
SOS_GET_SEG_NUM = $44
|
SOS_GET_SEG_NUM = $44
|
||||||
SOS_RELEASE_SEG = $45
|
SOS_RELEASE_SEG = $45
|
||||||
|
|
||||||
|
SOS_SET_FENCE = $60
|
||||||
|
SOS_GET_FENCE = $61
|
||||||
|
SOS_SET_TIME = $62
|
||||||
|
SOS_GET_TIME = $63
|
||||||
|
SOS_GET_ANALOG = $64
|
||||||
|
; SOS ref: "TERMINATE"
|
||||||
|
; SOS ref: "No errors are possible. This is an excellent call for beginners."
|
||||||
SOS_QUIT = $65
|
SOS_QUIT = $65
|
||||||
|
|
||||||
SOS_READBLOCK = $80
|
SOS_READBLOCK = $80
|
||||||
SOS_WRITEBLOCK = $81
|
SOS_WRITEBLOCK = $81
|
||||||
SOS_GET_TIME = $82
|
|
||||||
SOS_D_STATUS = $82
|
SOS_D_STATUS = $82
|
||||||
SOS_D_CONTROL = $83
|
SOS_D_CONTROL = $83
|
||||||
SOS_GET_DEV_NUM = $84
|
SOS_GET_DEV_NUM = $84
|
||||||
|
@ -35,7 +42,9 @@ SOS_SET_PREFIX = $C6
|
||||||
SOS_GET_PREFIX = $C7
|
SOS_GET_PREFIX = $C7
|
||||||
SOS_OPEN = $C8
|
SOS_OPEN = $C8
|
||||||
SOS_NEWLINE = $C9
|
SOS_NEWLINE = $C9
|
||||||
|
; SOS ref: "READ"
|
||||||
SOS_READFILE = $CA
|
SOS_READFILE = $CA
|
||||||
|
; SOS ref: "WRITE"
|
||||||
SOS_WRITEFILE = $CB
|
SOS_WRITEFILE = $CB
|
||||||
SOS_CLOSE = $CC
|
SOS_CLOSE = $CC
|
||||||
SOS_FLUSH = $CD
|
SOS_FLUSH = $CD
|
||||||
|
|
|
@ -196,7 +196,7 @@ code, but also needs to know how to handle the corner cases.</p>
|
||||||
outside bank zero cannot be assembled. SourceGen currently deals with
|
outside bank zero cannot be assembled. SourceGen currently deals with
|
||||||
this by outputting the entire file as a hex dump.</li>
|
this by outputting the entire file as a hex dump.</li>
|
||||||
<li>Undocumented opcode $AB (<code>LAX #imm</code>) generates an error.</li>
|
<li>Undocumented opcode $AB (<code>LAX #imm</code>) generates an error.</li>
|
||||||
<li>WDM is not allowed to have an operand.</li>
|
<li>BRK and WDM are not allowed to have operands.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Quirks:</p>
|
<p>Quirks:</p>
|
||||||
|
@ -231,6 +231,7 @@ code, but also needs to know how to handle the corner cases.</p>
|
||||||
<p>Bugs:</p>
|
<p>Bugs:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>PC relative branches don't wrap around at bank boundaries.</li>
|
<li>PC relative branches don't wrap around at bank boundaries.</li>
|
||||||
|
<li>BRK can only be given an argument in 65816 mode.</li>
|
||||||
<li>[Fixed in v2.18] The arguments to <code>MVN</code>/<code>MVP</code> are reversed.</li>
|
<li>[Fixed in v2.18] The arguments to <code>MVN</code>/<code>MVP</code> are reversed.</li>
|
||||||
<li>[Fixed in v2.18] <code>BRK <arg></code> is assembled to opcode
|
<li>[Fixed in v2.18] <code>BRK <arg></code> is assembled to opcode
|
||||||
$05 rather than $00.</li>
|
$05 rather than $00.</li>
|
||||||
|
|
|
@ -93,7 +93,8 @@
|
||||||
"RT:Apple/SOS.cs"
|
"RT:Apple/SOS.cs"
|
||||||
],
|
],
|
||||||
"Parameters" : {
|
"Parameters" : {
|
||||||
"load-address":"0x2000"
|
"load-address":"0x2000",
|
||||||
|
"two-byte-brk":"true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace RuntimeData.Test2022 {
|
||||||
mAppRef.DebugLog("Test2022-B(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
mAppRef.DebugLog("Test2022-B(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckBrk(int offset, out bool noContinue) {
|
public void CheckBrk(int offset, bool twoByteBrk, out bool noContinue) {
|
||||||
noContinue = true;
|
noContinue = true;
|
||||||
|
|
||||||
// need BRK, function byte, and two-byte address
|
// need BRK, function byte, and two-byte address
|
||||||
|
@ -39,8 +39,7 @@ namespace RuntimeData.Test2022 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAppRef.SetInlineDataFormat(offset + 1, 1, DataType.NumericLE,
|
Util.FormatBrkByte(mAppRef, twoByteBrk, offset, DataSubType.Hex, null);
|
||||||
DataSubType.Hex, null);
|
|
||||||
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
mAppRef.SetInlineDataFormat(offset + 2, 2, DataType.NumericLE,
|
||||||
DataSubType.Address, null);
|
DataSubType.Address, null);
|
||||||
noContinue = false;
|
noContinue = false;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
### 6502bench SourceGen dis65 v1.0 ###
|
### 6502bench SourceGen dis65 v1.0 ###
|
||||||
{
|
{
|
||||||
"_ContentVersion":2,"FileDataLength":203,"FileDataCrc32":-1621468157,"ProjectProps":{
|
"_ContentVersion":2,"FileDataLength":203,"FileDataCrc32":-1621468157,"ProjectProps":{
|
||||||
"CpuName":"65816","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
|
"CpuName":"65816","IncludeUndocumentedInstr":false,"TwoByteBrk":true,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{
|
||||||
"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true},
|
"AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true},
|
||||||
"PlatformSymbolFileIdentifiers":["PROJ:2022-extension-scripts.sym65"],"ExtensionScriptFileIdentifiers":["PROJ:2022-extension-scripts-a.cs","PROJ:2022-extension-scripts-b.cs"],"ProjectSyms":{
|
"PlatformSymbolFileIdentifiers":["PROJ:2022-extension-scripts.sym65"],"ExtensionScriptFileIdentifiers":["PROJ:2022-extension-scripts-a.cs","PROJ:2022-extension-scripts-b.cs"],"ProjectSyms":{
|
||||||
"PrintInlineDciString":{
|
"PrintInlineDciString":{
|
||||||
|
|
|
@ -28,11 +28,9 @@ PrintInlineDciString = $013000
|
||||||
jsr L10AB
|
jsr L10AB
|
||||||
jsr L110F
|
jsr L110F
|
||||||
jsr L1108
|
jsr L1108
|
||||||
brk
|
brk #$01
|
||||||
.byte $01
|
|
||||||
.word data01
|
.word data01
|
||||||
brk
|
brk #$02
|
||||||
.byte $02
|
|
||||||
.word data02
|
.word data02
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -80,9 +78,7 @@ L10AB jsr PrintInlineNullString
|
||||||
|
|
||||||
L1108 jsl PrintInlineL2String
|
L1108 jsl PrintInlineL2String
|
||||||
asl a
|
asl a
|
||||||
brk
|
brk #$60
|
||||||
|
|
||||||
.byte $60
|
|
||||||
|
|
||||||
L110F jsr PrintInlineNullString
|
L110F jsr PrintInlineNullString
|
||||||
adc $6e
|
adc $6e
|
||||||
|
|
|
@ -21,11 +21,9 @@ PrintInlineDciString equ $013000
|
||||||
jsr L10AB
|
jsr L10AB
|
||||||
jsr L110F
|
jsr L110F
|
||||||
jsr L1108
|
jsr L1108
|
||||||
brk
|
brk $01
|
||||||
dfb $01
|
|
||||||
dw data01
|
dw data01
|
||||||
brk
|
brk $02
|
||||||
dfb $02
|
|
||||||
dw data02
|
dw data02
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -71,9 +69,7 @@ L10AB jsr PrintInlineNullString
|
||||||
|
|
||||||
L1108 jsl PrintInlineL2String
|
L1108 jsl PrintInlineL2String
|
||||||
asl A
|
asl A
|
||||||
brk
|
brk $60
|
||||||
|
|
||||||
dfb $60
|
|
||||||
|
|
||||||
L110F jsr PrintInlineNullString
|
L110F jsr PrintInlineNullString
|
||||||
adc $6e
|
adc $6e
|
||||||
|
|
|
@ -24,11 +24,9 @@ PrintInlineDciString = $013000
|
||||||
jsr L10AB
|
jsr L10AB
|
||||||
jsr L110F
|
jsr L110F
|
||||||
jsr L1108
|
jsr L1108
|
||||||
brk
|
!byte $00,$01
|
||||||
!byte $01
|
|
||||||
!word data01
|
!word data01
|
||||||
brk
|
!byte $00,$02
|
||||||
!byte $02
|
|
||||||
!word data02
|
!word data02
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -76,9 +74,7 @@ L10AB jsr PrintInlineNullString
|
||||||
|
|
||||||
L1108 jsl PrintInlineL2String
|
L1108 jsl PrintInlineL2String
|
||||||
asl
|
asl
|
||||||
brk
|
!byte $00,$60
|
||||||
|
|
||||||
!byte $60
|
|
||||||
|
|
||||||
L110F jsr PrintInlineNullString
|
L110F jsr PrintInlineNullString
|
||||||
adc $6e
|
adc $6e
|
||||||
|
|
|
@ -25,11 +25,9 @@ PrintInlineDciString = $013000
|
||||||
jsr L10AB
|
jsr L10AB
|
||||||
jsr L110F
|
jsr L110F
|
||||||
jsr L1108
|
jsr L1108
|
||||||
brk
|
.byte $00,$01
|
||||||
.byte $01
|
|
||||||
.word data01
|
.word data01
|
||||||
brk
|
.byte $00,$02
|
||||||
.byte $02
|
|
||||||
.word data02
|
.word data02
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -81,9 +79,7 @@ L10AB: jsr PrintInlineNullString
|
||||||
|
|
||||||
L1108: jsl PrintInlineL2String
|
L1108: jsl PrintInlineL2String
|
||||||
asl A
|
asl A
|
||||||
brk
|
.byte $00,$60
|
||||||
|
|
||||||
.byte $60
|
|
||||||
|
|
||||||
L110F: jsr PrintInlineNullString
|
L110F: jsr PrintInlineNullString
|
||||||
adc $6e
|
adc $6e
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace SourceGen {
|
||||||
private const string LOAD_ADDRESS = "load-address";
|
private const string LOAD_ADDRESS = "load-address";
|
||||||
private const string ENTRY_FLAGS = "entry-flags";
|
private const string ENTRY_FLAGS = "entry-flags";
|
||||||
private const string UNDOCUMENTED_OPCODES = "undocumented-opcodes";
|
private const string UNDOCUMENTED_OPCODES = "undocumented-opcodes";
|
||||||
|
private const string TWO_BYTE_BRK = "two-byte-brk";
|
||||||
private const string FIRST_WORD_IS_LOAD_ADDR = "first-word-is-load-addr";
|
private const string FIRST_WORD_IS_LOAD_ADDR = "first-word-is-load-addr";
|
||||||
private const string DEFAULT_TEXT_ENCODING = "default-text-encoding";
|
private const string DEFAULT_TEXT_ENCODING = "default-text-encoding";
|
||||||
|
|
||||||
|
@ -105,6 +106,15 @@ namespace SourceGen {
|
||||||
return GetBoolParam(sysDef, UNDOCUMENTED_OPCODES, false);
|
return GetBoolParam(sysDef, UNDOCUMENTED_OPCODES, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default setting for two-byte BRKs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sysDef">SystemDef instance.</param>
|
||||||
|
/// <returns>Enable/disable value.</returns>
|
||||||
|
public static bool GetTwoByteBrk(SystemDef sysDef) {
|
||||||
|
return GetBoolParam(sysDef, TWO_BYTE_BRK, false);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default setting for using the first two bytes of the file as the
|
/// Gets the default setting for using the first two bytes of the file as the
|
||||||
/// load address.
|
/// load address.
|
||||||
|
|
|
@ -76,6 +76,8 @@ limitations under the License.
|
||||||
SelectionChanged="CpuComboBox_SelectionChanged"/>
|
SelectionChanged="CpuComboBox_SelectionChanged"/>
|
||||||
<CheckBox Margin="0,4,0,0" Content="Enable undocumented instructions"
|
<CheckBox Margin="0,4,0,0" Content="Enable undocumented instructions"
|
||||||
IsChecked="{Binding IncludeUndocumentedInstr}"/>
|
IsChecked="{Binding IncludeUndocumentedInstr}"/>
|
||||||
|
<CheckBox Margin="0,4,0,0" Content="Treat BRK as two-byte instruction"
|
||||||
|
IsChecked="{Binding TwoByteBrk}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
<GroupBox Header="Entry Flags" Grid.Column="0" Grid.Row="1" Padding="2,4">
|
<GroupBox Header="Entry Flags" Grid.Column="0" Grid.Row="1" Padding="2,4">
|
||||||
|
|
|
@ -254,8 +254,9 @@ namespace SourceGen.WpfGui {
|
||||||
}
|
}
|
||||||
public AutoLabelItem[] AutoLabelItems { get; private set; }
|
public AutoLabelItem[] AutoLabelItems { get; private set; }
|
||||||
|
|
||||||
|
//
|
||||||
// properties for checkboxes
|
// properties for checkboxes
|
||||||
|
//
|
||||||
public bool IncludeUndocumentedInstr {
|
public bool IncludeUndocumentedInstr {
|
||||||
get { return mWorkProps.IncludeUndocumentedInstr; }
|
get { return mWorkProps.IncludeUndocumentedInstr; }
|
||||||
set {
|
set {
|
||||||
|
@ -264,6 +265,14 @@ namespace SourceGen.WpfGui {
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public bool TwoByteBrk {
|
||||||
|
get { return mWorkProps.TwoByteBrk; }
|
||||||
|
set {
|
||||||
|
mWorkProps.TwoByteBrk = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
public bool AnalyzeUncategorizedData {
|
public bool AnalyzeUncategorizedData {
|
||||||
get { return mWorkProps.AnalysisParams.AnalyzeUncategorizedData; }
|
get { return mWorkProps.AnalysisParams.AnalyzeUncategorizedData; }
|
||||||
set {
|
set {
|
||||||
|
@ -382,7 +391,7 @@ namespace SourceGen.WpfGui {
|
||||||
|
|
||||||
private void ChangeFlagButton_Click(object sender, RoutedEventArgs e) {
|
private void ChangeFlagButton_Click(object sender, RoutedEventArgs e) {
|
||||||
CpuDef cpuDef = CpuDef.GetBestMatch(mWorkProps.CpuType,
|
CpuDef cpuDef = CpuDef.GetBestMatch(mWorkProps.CpuType,
|
||||||
mWorkProps.IncludeUndocumentedInstr);
|
mWorkProps.IncludeUndocumentedInstr, mWorkProps.TwoByteBrk);
|
||||||
EditStatusFlags dlg =
|
EditStatusFlags dlg =
|
||||||
new EditStatusFlags(this, mWorkProps.EntryFlags, cpuDef.HasEmuFlag);
|
new EditStatusFlags(this, mWorkProps.EntryFlags, cpuDef.HasEmuFlag);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user