mirror of
https://github.com/fadden/6502bench.git
synced 2025-07-24 22:25:06 +00:00
Use relocation data to format instruction operands
This was a relatively lightweight change to confirm the usefulness of relocation data. The results were very positive. The relatively superficial integration of the data into the data analysis process causes some problems, e.g. the cross-reference table entries show an offset because the code analyzer's computed operand offset doesn't match the value of the label. The feature should be considered experimental The feature can be enabled or disabled with a project property. The results were sufficiently useful and non-annoying to make the setting enabled by default.
This commit is contained in:
@@ -174,6 +174,7 @@ namespace SourceGen {
|
|||||||
/// bytes.</param>
|
/// bytes.</param>
|
||||||
/// <param name="entryFlags">Status flags to use at code entry points.</param>
|
/// <param name="entryFlags">Status flags to use at code entry points.</param>
|
||||||
/// <param name="scriptMan">Extension script manager.</param>
|
/// <param name="scriptMan">Extension script manager.</param>
|
||||||
|
/// <param name="parms">Analysis parameters.</param>
|
||||||
/// <param name="debugLog">Object that receives debug log messages.</param>
|
/// <param name="debugLog">Object that receives debug log messages.</param>
|
||||||
public CodeAnalysis(byte[] data, CpuDef cpuDef, Anattrib[] anattribs,
|
public CodeAnalysis(byte[] data, CpuDef cpuDef, Anattrib[] anattribs,
|
||||||
AddressMap addrMap, TypeHint[] hints, StatusFlags[] statusFlagOverrides,
|
AddressMap addrMap, TypeHint[] hints, StatusFlags[] statusFlagOverrides,
|
||||||
|
@@ -80,6 +80,11 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="proj">Project to analyze.</param>
|
||||||
|
/// <param name="anattribs">Anattrib array.</param>
|
||||||
public DataAnalysis(DisasmProject proj, Anattrib[] anattribs) {
|
public DataAnalysis(DisasmProject proj, Anattrib[] anattribs) {
|
||||||
mProject = proj;
|
mProject = proj;
|
||||||
mAnattribs = anattribs;
|
mAnattribs = anattribs;
|
||||||
@@ -156,12 +161,42 @@ namespace SourceGen {
|
|||||||
FormatDescriptor.SubType.Address);
|
FormatDescriptor.SubType.Address);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for a relocation. It'll be at offset+1 because it's on the operand,
|
||||||
|
// not the opcode byte.
|
||||||
|
if (mAnalysisParams.UseRelocData && mProject.RelocList.TryGetValue(offset + 1,
|
||||||
|
out DisasmProject.RelocData reloc)) {
|
||||||
|
if (reloc.Value != attr.OperandAddress) {
|
||||||
|
// The relocation address differs from what the analyzer came up
|
||||||
|
// with. This may be because of incorrect assumptions about the
|
||||||
|
// bank (assuming B==K) or because the partial address refers to
|
||||||
|
// a location outside the file bounds. Whatever the case, if the
|
||||||
|
// address is different, attr.OperandOffset will also be different.
|
||||||
|
int relOperandOffset = mProject.AddrMap.AddressToOffset(offset,
|
||||||
|
reloc.Value);
|
||||||
|
if (relOperandOffset >= 0 && relOperandOffset != attr.OperandOffset) {
|
||||||
|
// Determined a different offset. Use that instead.
|
||||||
|
//Debug.WriteLine("REL +" + offset.ToString("x6") + " " +
|
||||||
|
// reloc.Value.ToString("x6") + " vs. " +
|
||||||
|
// attr.OperandAddress.ToString("x6"));
|
||||||
|
WeakSymbolRef.Part part = WeakSymbolRef.Part.Low;
|
||||||
|
if (reloc.Shift == -8) {
|
||||||
|
part = WeakSymbolRef.Part.High;
|
||||||
|
} else if (reloc.Shift == -16) {
|
||||||
|
part = WeakSymbolRef.Part.Bank;
|
||||||
|
}
|
||||||
|
SetDataTarget(offset, attr.Length, relOperandOffset, part);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int operandOffset = attr.OperandOffset;
|
int operandOffset = attr.OperandOffset;
|
||||||
if (operandOffset >= 0) {
|
if (operandOffset >= 0) {
|
||||||
// This is an offset reference: a branch or data access instruction whose
|
// This is an offset reference: a branch or data access instruction whose
|
||||||
// target is inside the file. Create a FormatDescriptor for it, and
|
// target is inside the file. Create a FormatDescriptor for it, and
|
||||||
// generate a label at the target if one is not already present.
|
// generate a label at the target if one is not already present.
|
||||||
SetDataTarget(offset, attr.Length, operandOffset);
|
SetDataTarget(offset, attr.Length, operandOffset, WeakSymbolRef.Part.Low);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We advance by a single byte, rather than .Length, in case there's
|
// We advance by a single byte, rather than .Length, in case there's
|
||||||
@@ -190,7 +225,8 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
int operandOffset = mProject.AddrMap.AddressToOffset(offset, address);
|
int operandOffset = mProject.AddrMap.AddressToOffset(offset, address);
|
||||||
if (operandOffset >= 0) {
|
if (operandOffset >= 0) {
|
||||||
SetDataTarget(offset, dfd.Length, operandOffset);
|
SetDataTarget(offset, dfd.Length, operandOffset,
|
||||||
|
WeakSymbolRef.Part.Low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +305,8 @@ namespace SourceGen {
|
|||||||
/// <param name="srcOffset">Offset of instruction or address data.</param>
|
/// <param name="srcOffset">Offset of instruction or address data.</param>
|
||||||
/// <param name="srcLen">Length of instruction or data item.</param>
|
/// <param name="srcLen">Length of instruction or data item.</param>
|
||||||
/// <param name="targetOffset">Offset of target.</param>
|
/// <param name="targetOffset">Offset of target.</param>
|
||||||
private void SetDataTarget(int srcOffset, int srcLen, int targetOffset) {
|
private void SetDataTarget(int srcOffset, int srcLen, int targetOffset,
|
||||||
|
WeakSymbolRef.Part part) {
|
||||||
// NOTE: don't try to cache mAnattribs[targetOffset] -- we may be changing
|
// NOTE: don't try to cache mAnattribs[targetOffset] -- we may be changing
|
||||||
// targetOffset and/or altering the Anattrib entry, so grabbing a copy of the
|
// targetOffset and/or altering the Anattrib entry, so grabbing a copy of the
|
||||||
// struct may lead to problems.
|
// struct may lead to problems.
|
||||||
@@ -359,8 +396,7 @@ namespace SourceGen {
|
|||||||
", adj=" + (origTargetOffset - targetOffset));
|
", adj=" + (origTargetOffset - targetOffset));
|
||||||
}
|
}
|
||||||
mAnattribs[srcOffset].DataDescriptor = FormatDescriptor.Create(srcLen,
|
mAnattribs[srcOffset].DataDescriptor = FormatDescriptor.Create(srcLen,
|
||||||
new WeakSymbolRef(mAnattribs[targetOffset].Symbol.Label, WeakSymbolRef.Part.Low),
|
new WeakSymbolRef(mAnattribs[targetOffset].Symbol.Label, part), isBigEndian);
|
||||||
isBigEndian);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -122,24 +122,26 @@ namespace SourceGen {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Cooked" form of relocation data (e.g. OmfReloc). This does not contain the file
|
/// "Cooked" form of relocation data (e.g. OmfReloc). This does not contain the file
|
||||||
/// offset, as that's expected to be used as the dictionary key.
|
/// offset, as that's expected to be used as the dictionary key.
|
||||||
///
|
|
||||||
/// Will be null unless the project was generated from a relocatable source.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class RelocData {
|
public class RelocData {
|
||||||
public byte Width; // width of area written by relocator
|
public byte Width; // width of area written by relocator (1-4 bytes)
|
||||||
public byte Shift; // amount to shift the value
|
public sbyte Shift; // amount to shift the value (usually 0 or -16)
|
||||||
public int Value; // value used (unshifted, full width)
|
public int Value; // value used (unshifted, full width)
|
||||||
|
|
||||||
public RelocData() { } // for deserialization
|
public RelocData() { } // for deserialization
|
||||||
|
|
||||||
public RelocData(byte width, byte shift, int value) {
|
public RelocData(byte width, sbyte shift, int value) {
|
||||||
Width = width;
|
Width = width;
|
||||||
Shift = shift;
|
Shift = shift;
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Dictionary<int, RelocData> RelocList { get; set; }
|
/// <summary>
|
||||||
|
/// List of relocation data. Will be empty unless file was generated from a
|
||||||
|
/// relocatable source.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<int, RelocData> RelocList { get; private set; }
|
||||||
|
|
||||||
#endregion // data to save & restore
|
#endregion // data to save & restore
|
||||||
|
|
||||||
@@ -280,6 +282,7 @@ namespace SourceGen {
|
|||||||
LvTables = new SortedList<int, LocalVariableTable>();
|
LvTables = new SortedList<int, LocalVariableTable>();
|
||||||
VisualizationSets = new SortedList<int, VisualizationSet>();
|
VisualizationSets = new SortedList<int, VisualizationSet>();
|
||||||
ProjectProps = new ProjectProperties();
|
ProjectProps = new ProjectProperties();
|
||||||
|
RelocList = new Dictionary<int, RelocData>();
|
||||||
|
|
||||||
SymbolTable = new SymbolTable();
|
SymbolTable = new SymbolTable();
|
||||||
PlatformSyms = new List<PlatformSymbols>();
|
PlatformSyms = new List<PlatformSymbols>();
|
||||||
|
@@ -1282,6 +1282,8 @@ namespace SourceGen {
|
|||||||
// This is necessary for 16-bit operands, like "LDA abs" and "PEA val",
|
// This is necessary for 16-bit operands, like "LDA abs" and "PEA val",
|
||||||
// when outside bank zero. The bank is included in the operand address,
|
// when outside bank zero. The bank is included in the operand address,
|
||||||
// but we don't want to show it here.
|
// but we don't want to show it here.
|
||||||
|
// (Some assemblers want the bank to be shown for JSR/JMP, but we don't
|
||||||
|
// do that here. See the corresponding code in AsmGen.GenCommon)
|
||||||
operandForSymbol &= 0xffff;
|
operandForSymbol &= 0xffff;
|
||||||
}
|
}
|
||||||
formattedOperand = mFormatter.FormatHexValue(operandForSymbol, operandLen * 2);
|
formattedOperand = mFormatter.FormatHexValue(operandForSymbol, operandLen * 2);
|
||||||
|
@@ -1597,17 +1597,10 @@ namespace SourceGen {
|
|||||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||||
FormatDescriptor dfd = attr.DataDescriptor;
|
FormatDescriptor dfd = attr.DataDescriptor;
|
||||||
|
|
||||||
// Does this have an operand with an in-file target offset?
|
if (dfd != null && dfd.HasSymbol) {
|
||||||
// (Resolve it as a numeric reference.)
|
// Operand has a symbol, do a symbol lookup. This is slower than a simple
|
||||||
if (attr.OperandOffset >= 0) {
|
// jump based on OperandOffset, but if we've incorporated reloc data then
|
||||||
// Yup, find the line for that offset and jump to it.
|
// the jump will be wrong.
|
||||||
if (!testOnly) {
|
|
||||||
GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false),
|
|
||||||
GoToMode.JumpToCodeData, true);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (dfd != null && dfd.HasSymbol) {
|
|
||||||
// Operand has a symbol, do a symbol lookup.
|
|
||||||
if (dfd.SymbolRef.IsVariable) {
|
if (dfd.SymbolRef.IsVariable) {
|
||||||
if (!testOnly) {
|
if (!testOnly) {
|
||||||
GoToVarDefinition(line.FileOffset, dfd.SymbolRef, true);
|
GoToVarDefinition(line.FileOffset, dfd.SymbolRef, true);
|
||||||
@@ -1646,6 +1639,14 @@ namespace SourceGen {
|
|||||||
Debug.WriteLine("Operand symbol not found: " + dfd.SymbolRef.Label);
|
Debug.WriteLine("Operand symbol not found: " + dfd.SymbolRef.Label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (attr.OperandOffset >= 0) {
|
||||||
|
// Operand has an in-file target offset. We can resolve it as a numeric reference.
|
||||||
|
// Find the line for that offset and jump to it.
|
||||||
|
if (!testOnly) {
|
||||||
|
GoToLocation(new NavStack.Location(attr.OperandOffset, 0, false),
|
||||||
|
GoToMode.JumpToCodeData, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
|
||||||
// If it's an Address or Symbol, we can try to resolve
|
// If it's an Address or Symbol, we can try to resolve
|
||||||
// the value. (Symbols should have been resolved by the
|
// the value. (Symbols should have been resolved by the
|
||||||
@@ -2198,7 +2199,7 @@ namespace SourceGen {
|
|||||||
if (!string.IsNullOrEmpty(mProjectPathName)) {
|
if (!string.IsNullOrEmpty(mProjectPathName)) {
|
||||||
projectDir = Path.GetDirectoryName(mProjectPathName);
|
projectDir = Path.GetDirectoryName(mProjectPathName);
|
||||||
}
|
}
|
||||||
EditProjectProperties dlg = new EditProjectProperties(mMainWin, mProject.ProjectProps,
|
EditProjectProperties dlg = new EditProjectProperties(mMainWin, mProject,
|
||||||
projectDir, mFormatter, initialTab);
|
projectDir, mFormatter, initialTab);
|
||||||
dlg.ShowDialog();
|
dlg.ShowDialog();
|
||||||
ProjectProperties newProps = dlg.NewProps;
|
ProjectProperties newProps = dlg.NewProps;
|
||||||
@@ -3201,6 +3202,7 @@ namespace SourceGen {
|
|||||||
Debug.Assert(line.FileOffset >= 0);
|
Debug.Assert(line.FileOffset >= 0);
|
||||||
|
|
||||||
// Does this have an operand with an in-file target offset?
|
// Does this have an operand with an in-file target offset?
|
||||||
|
// TODO: may not work correctly with reloc data?
|
||||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||||
if (attr.OperandOffset >= 0) {
|
if (attr.OperandOffset >= 0) {
|
||||||
return CodeLineList.FindCodeDataIndexByOffset(attr.OperandOffset);
|
return CodeLineList.FindCodeDataIndexByOffset(attr.OperandOffset);
|
||||||
|
@@ -223,6 +223,7 @@ namespace SourceGen {
|
|||||||
public string DefaultTextScanMode { get; set; }
|
public string DefaultTextScanMode { get; set; }
|
||||||
public int MinCharsForString { get; set; }
|
public int MinCharsForString { get; set; }
|
||||||
public bool SeekNearbyTargets { get; set; }
|
public bool SeekNearbyTargets { get; set; }
|
||||||
|
public bool UseRelocData { get; set; }
|
||||||
public bool SmartPlpHandling { get; set; }
|
public bool SmartPlpHandling { get; set; }
|
||||||
|
|
||||||
public SerAnalysisParameters() { }
|
public SerAnalysisParameters() { }
|
||||||
@@ -231,6 +232,7 @@ namespace SourceGen {
|
|||||||
DefaultTextScanMode = src.DefaultTextScanMode.ToString();
|
DefaultTextScanMode = src.DefaultTextScanMode.ToString();
|
||||||
MinCharsForString = src.MinCharsForString;
|
MinCharsForString = src.MinCharsForString;
|
||||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||||
|
UseRelocData = src.UseRelocData;
|
||||||
SmartPlpHandling = src.SmartPlpHandling;
|
SmartPlpHandling = src.SmartPlpHandling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -526,13 +528,10 @@ namespace SourceGen {
|
|||||||
|
|
||||||
spf.ProjectProps = new SerProjectProperties(proj.ProjectProps);
|
spf.ProjectProps = new SerProjectProperties(proj.ProjectProps);
|
||||||
|
|
||||||
if (proj.RelocList != null) {
|
// The objects are serializable, but the Dictionary key can't be an int.
|
||||||
// The objects can serialize directly, but the Dictionary key can't be an int.
|
spf.RelocList = new Dictionary<string, DisasmProject.RelocData>(proj.RelocList.Count);
|
||||||
spf.RelocList =
|
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in proj.RelocList) {
|
||||||
new Dictionary<string, DisasmProject.RelocData>(proj.RelocList.Count);
|
spf.RelocList.Add(kvp.Key.ToString(), kvp.Value);
|
||||||
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in proj.RelocList) {
|
|
||||||
spf.RelocList.Add(kvp.Key.ToString(), kvp.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaScriptSerializer ser = new JavaScriptSerializer();
|
JavaScriptSerializer ser = new JavaScriptSerializer();
|
||||||
@@ -610,6 +609,8 @@ namespace SourceGen {
|
|||||||
spf.ProjectProps.AnalysisParams.MinCharsForString;
|
spf.ProjectProps.AnalysisParams.MinCharsForString;
|
||||||
proj.ProjectProps.AnalysisParams.SeekNearbyTargets =
|
proj.ProjectProps.AnalysisParams.SeekNearbyTargets =
|
||||||
spf.ProjectProps.AnalysisParams.SeekNearbyTargets;
|
spf.ProjectProps.AnalysisParams.SeekNearbyTargets;
|
||||||
|
proj.ProjectProps.AnalysisParams.UseRelocData =
|
||||||
|
spf.ProjectProps.AnalysisParams.UseRelocData;
|
||||||
if (spf._ContentVersion < 2) {
|
if (spf._ContentVersion < 2) {
|
||||||
// This was made optional in v1.3. Default it to true for older projects.
|
// This was made optional in v1.3. Default it to true for older projects.
|
||||||
proj.ProjectProps.AnalysisParams.SmartPlpHandling = true;
|
proj.ProjectProps.AnalysisParams.SmartPlpHandling = true;
|
||||||
@@ -844,7 +845,6 @@ namespace SourceGen {
|
|||||||
|
|
||||||
// Deserialize relocation data. This was added in v1.7.
|
// Deserialize relocation data. This was added in v1.7.
|
||||||
if (spf.RelocList != null) {
|
if (spf.RelocList != null) {
|
||||||
proj.RelocList = new Dictionary<int, DisasmProject.RelocData>();
|
|
||||||
foreach (KeyValuePair<string, DisasmProject.RelocData> kvp in spf.RelocList) {
|
foreach (KeyValuePair<string, DisasmProject.RelocData> kvp in spf.RelocList) {
|
||||||
if (!ParseValidateKey(kvp.Key, spf.FileDataLength,
|
if (!ParseValidateKey(kvp.Key, spf.FileDataLength,
|
||||||
Res.Strings.PROJECT_FIELD_RELOC_DATA, report, out int intKey)) {
|
Res.Strings.PROJECT_FIELD_RELOC_DATA, report, out int intKey)) {
|
||||||
|
@@ -28,9 +28,10 @@ namespace SourceGen {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProjectProperties {
|
public class ProjectProperties {
|
||||||
//
|
//
|
||||||
// NOTE:
|
// *** NOTE ***
|
||||||
// If you add or modify a member, make sure to update the copy constructor and
|
// If you add or modify a member, make sure to update the copy constructor and
|
||||||
// add serialization code to ProjectFile.
|
// add serialization code to ProjectFile.
|
||||||
|
// *** NOTE ***
|
||||||
//
|
//
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,6 +52,7 @@ namespace SourceGen {
|
|||||||
public TextScanMode DefaultTextScanMode { get; set; }
|
public TextScanMode DefaultTextScanMode { get; set; }
|
||||||
public int MinCharsForString { get; set; }
|
public int MinCharsForString { get; set; }
|
||||||
public bool SeekNearbyTargets { get; set; }
|
public bool SeekNearbyTargets { get; set; }
|
||||||
|
public bool UseRelocData { get; set; }
|
||||||
public bool SmartPlpHandling { get; set; }
|
public bool SmartPlpHandling { get; set; }
|
||||||
|
|
||||||
public AnalysisParameters() {
|
public AnalysisParameters() {
|
||||||
@@ -59,6 +61,7 @@ namespace SourceGen {
|
|||||||
DefaultTextScanMode = TextScanMode.LowHighAscii;
|
DefaultTextScanMode = TextScanMode.LowHighAscii;
|
||||||
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
|
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
|
||||||
SeekNearbyTargets = true;
|
SeekNearbyTargets = true;
|
||||||
|
UseRelocData = true;
|
||||||
SmartPlpHandling = true;
|
SmartPlpHandling = true;
|
||||||
}
|
}
|
||||||
public AnalysisParameters(AnalysisParameters src) {
|
public AnalysisParameters(AnalysisParameters src) {
|
||||||
@@ -66,6 +69,7 @@ namespace SourceGen {
|
|||||||
DefaultTextScanMode = src.DefaultTextScanMode;
|
DefaultTextScanMode = src.DefaultTextScanMode;
|
||||||
MinCharsForString = src.MinCharsForString;
|
MinCharsForString = src.MinCharsForString;
|
||||||
SeekNearbyTargets = src.SeekNearbyTargets;
|
SeekNearbyTargets = src.SeekNearbyTargets;
|
||||||
|
UseRelocData = src.UseRelocData;
|
||||||
SmartPlpHandling = src.SmartPlpHandling;
|
SmartPlpHandling = src.SmartPlpHandling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -137,10 +137,12 @@ and 65816 code. The official web site is
|
|||||||
|
|
||||||
<li><a href="tools.html">Tools</a>
|
<li><a href="tools.html">Tools</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="tools.html#instruction-chart">Instruction Chart</a></li>
|
||||||
|
<li><a href="tools.html#ascii-chart">ASCII Chart</a></li>
|
||||||
<li><a href="tools.html#hexdump">Hex Dump Viewer</a></li>
|
<li><a href="tools.html#hexdump">Hex Dump Viewer</a></li>
|
||||||
<li><a href="tools.html#file-concat">File Concatenator</a></li>
|
<li><a href="tools.html#file-concat">File Concatenator</a></li>
|
||||||
<li><a href="tools.html#ascii-chart">ASCII Chart</a></li>
|
<li><a href="tools.html#file-slicer">File Slicer</a></li>
|
||||||
<li><a href="tools.html#instruction-chart">Instruction Chart</a></li>
|
<li><a href="tools.html#omf-converter">OMF Converter</a></li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
|
||||||
<li><a href="advanced.html">Advanced Topics</a>
|
<li><a href="advanced.html">Advanced Topics</a>
|
||||||
|
@@ -254,6 +254,10 @@ unless they match exactly. Note that references into the middle of an
|
|||||||
instruction or formatted data area are always adjusted, regardless of
|
instruction or formatted data area are always adjusted, regardless of
|
||||||
how this is set. This setting has no effect on local variables, and
|
how this is set. This setting has no effect on local variables, and
|
||||||
only enables a 1-byte backward search on project/platform symbols.</p>
|
only enables a 1-byte backward search on project/platform symbols.</p>
|
||||||
|
<p>The "use relocation data" checkbox is only available if the project
|
||||||
|
was created from a relocatable source, e.g. by the OMF Converter tool.
|
||||||
|
If checked, information from the relocation dictionary will be used to
|
||||||
|
improve automatic operand formatting.</p>
|
||||||
<p>If "smart PLP handling" is checked, the analyzer will try to use
|
<p>If "smart PLP handling" is checked, the analyzer will try to use
|
||||||
the processor status flags from a nearby <code>PHP</code> when a
|
the processor status flags from a nearby <code>PHP</code> when a
|
||||||
<code>PLP</code> is encountered. If not enabled, all flags are set to
|
<code>PLP</code> is encountered. If not enabled, all flags are set to
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
<h1>6502bench SourceGen: Tools</h1>
|
<h1>6502bench SourceGen: Tools</h1>
|
||||||
|
|
||||||
<h2><a name="instruction-chart">Instruction Chart</a></h2>
|
<h2><a name="instruction-chart">Instruction Chart</a></h2>
|
||||||
|
|
||||||
<p>This opens a window with a summary of all 256 opcodes. The CPU can
|
<p>This opens a window with a summary of all 256 opcodes. The CPU can
|
||||||
be chosen from the pop-up list at the bottom. Undocumented opcodes for
|
be chosen from the pop-up list at the bottom. Undocumented opcodes for
|
||||||
6502/65C02 are shown in italics, and can be excluded from the list
|
6502/65C02 are shown in italics, and can be excluded from the list
|
||||||
@@ -84,6 +85,20 @@ length of the file, respectively.</p>
|
|||||||
sliced, allowing you to confirm the placement.</p>
|
sliced, allowing you to confirm the placement.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a name="omf-converter">OMF Converter</a></h2>
|
||||||
|
|
||||||
|
<p>This tool allows you to view Apple IIgs Object Module Format
|
||||||
|
binaries, and convert them for disassembly. OMF files have multiple
|
||||||
|
segments with relocatable code. The conversion tool loads the OMF
|
||||||
|
file the same way the GS/OS System Loader would, and creates a
|
||||||
|
SourceGen project file for it with some basic attributes filled in.</p>
|
||||||
|
|
||||||
|
<p>Only Load files may be converted (S16, PIF, etc). Compiler object
|
||||||
|
files and libraries contain unresolved references and are not supported.</p>
|
||||||
|
|
||||||
|
<p>The generated binary file is not in OMF format and will not execute
|
||||||
|
on an Apple IIgs.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
|
@@ -344,7 +344,9 @@ namespace SourceGen.Tools.Omf {
|
|||||||
|
|
||||||
proj.PrepForNew(data, "new_proj");
|
proj.PrepForNew(data, "new_proj");
|
||||||
proj.ApplyChanges(cs, false, out _);
|
proj.ApplyChanges(cs, false, out _);
|
||||||
proj.RelocList = mRelocData;
|
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in mRelocData) {
|
||||||
|
proj.RelocList.Add(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
|
||||||
mLoadedData = data;
|
mLoadedData = data;
|
||||||
mNewProject = proj;
|
mNewProject = proj;
|
||||||
@@ -410,38 +412,39 @@ namespace SourceGen.Tools.Omf {
|
|||||||
Debug.WriteLine("Invalid reloc shift " + omfRel.Shift);
|
Debug.WriteLine("Invalid reloc shift " + omfRel.Shift);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int adjRelocAddr = relocAddr;
|
||||||
if (omfRel.Shift < 0) {
|
if (omfRel.Shift < 0) {
|
||||||
relocAddr >>= -omfRel.Shift;
|
adjRelocAddr >>= -omfRel.Shift;
|
||||||
} else if (omfRel.Shift > 0) {
|
} else if (omfRel.Shift > 0) {
|
||||||
relocAddr <<= omfRel.Shift;
|
adjRelocAddr <<= omfRel.Shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (omfRel.Width) {
|
switch (omfRel.Width) {
|
||||||
case 1:
|
case 1:
|
||||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||||
data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8);
|
data[bufOffset + omfRel.Offset + 1] = (byte)(adjRelocAddr >> 8);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||||
data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8);
|
data[bufOffset + omfRel.Offset + 1] = (byte)(adjRelocAddr >> 8);
|
||||||
data[bufOffset + omfRel.Offset + 2] = (byte)(relocAddr >> 16);
|
data[bufOffset + omfRel.Offset + 2] = (byte)(adjRelocAddr >> 16);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
data[bufOffset + omfRel.Offset] = (byte)(relocAddr);
|
data[bufOffset + omfRel.Offset] = (byte)(adjRelocAddr);
|
||||||
data[bufOffset + omfRel.Offset + 1] = (byte)(relocAddr >> 8);
|
data[bufOffset + omfRel.Offset + 1] = (byte)(adjRelocAddr >> 8);
|
||||||
data[bufOffset + omfRel.Offset + 2] = (byte)(relocAddr >> 16);
|
data[bufOffset + omfRel.Offset + 2] = (byte)(adjRelocAddr >> 16);
|
||||||
data[bufOffset + omfRel.Offset + 3] = (byte)(relocAddr >> 24);
|
data[bufOffset + omfRel.Offset + 3] = (byte)(adjRelocAddr >> 24);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.WriteLine("Invalid reloc width " + omfRel.Width);
|
Debug.WriteLine("Invalid reloc width " + omfRel.Width);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRelocData.Add(bufOffset + omfRel.Offset,
|
mRelocData.Add(bufOffset + omfRel.Offset, new DisasmProject.RelocData(
|
||||||
new DisasmProject.RelocData((byte)omfRel.Width, (byte)omfRel.Shift, relocAddr));
|
(byte)omfRel.Width, (sbyte)omfRel.Shift, relocAddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -103,6 +103,8 @@ limitations under the License.
|
|||||||
IsChecked="{Binding AnalyzeUncategorizedData}"/>
|
IsChecked="{Binding AnalyzeUncategorizedData}"/>
|
||||||
<CheckBox Margin="0,4,0,0" Content="Seek nearby targets"
|
<CheckBox Margin="0,4,0,0" Content="Seek nearby targets"
|
||||||
IsChecked="{Binding SeekNearbyTargets}"/>
|
IsChecked="{Binding SeekNearbyTargets}"/>
|
||||||
|
<CheckBox Margin="0,4,0,0" Content="Use relocation data (experimental)"
|
||||||
|
IsChecked="{Binding UseRelocData}" IsEnabled="{Binding IsRelocDataAvailable}"/>
|
||||||
<CheckBox Margin="0,4,0,0" Content="Smart PLP handling"
|
<CheckBox Margin="0,4,0,0" Content="Smart PLP handling"
|
||||||
IsChecked="{Binding SmartPlpHandling}"/>
|
IsChecked="{Binding SmartPlpHandling}"/>
|
||||||
|
|
||||||
|
@@ -105,21 +105,23 @@ namespace SourceGen.WpfGui {
|
|||||||
/// Constructor. Initial state is configured from an existing ProjectProperties object.
|
/// Constructor. Initial state is configured from an existing ProjectProperties object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="owner">Parent window.</param>
|
/// <param name="owner">Parent window.</param>
|
||||||
/// <param name="props">Property holder to clone.</param>
|
/// <param name="project">Project object.</param>
|
||||||
/// <param name="projectDir">Project directory, if known.</param>
|
/// <param name="projectDir">Project directory, if known.</param>
|
||||||
/// <param name="formatter">Text formatter.</param>
|
/// <param name="formatter">Text formatter.</param>
|
||||||
/// <param name="initialTab">Tab to open initially. Pass "Unknown" for default.</param>
|
/// <param name="initialTab">Tab to open initially. Pass "Unknown" for default.</param>
|
||||||
public EditProjectProperties(Window owner, ProjectProperties props, string projectDir,
|
public EditProjectProperties(Window owner, DisasmProject project, string projectDir,
|
||||||
Formatter formatter, Tab initialTab) {
|
Formatter formatter, Tab initialTab) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
DataContext = this;
|
DataContext = this;
|
||||||
|
|
||||||
mWorkProps = new ProjectProperties(props);
|
mWorkProps = new ProjectProperties(project.ProjectProps); // make a work copy
|
||||||
mProjectDir = projectDir;
|
mProjectDir = projectDir;
|
||||||
mFormatter = formatter;
|
mFormatter = formatter;
|
||||||
mInitialTab = initialTab;
|
mInitialTab = initialTab;
|
||||||
|
|
||||||
|
IsRelocDataAvailable = (project.RelocList.Count > 0);
|
||||||
|
|
||||||
// Construct arrays used as item sources for combo boxes.
|
// Construct arrays used as item sources for combo boxes.
|
||||||
CpuItems = new CpuItem[] {
|
CpuItems = new CpuItem[] {
|
||||||
new CpuItem((string)FindResource("str_6502"), CpuDef.CpuType.Cpu6502),
|
new CpuItem((string)FindResource("str_6502"), CpuDef.CpuType.Cpu6502),
|
||||||
@@ -341,6 +343,19 @@ namespace SourceGen.WpfGui {
|
|||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public bool UseRelocData {
|
||||||
|
get { return mWorkProps.AnalysisParams.UseRelocData; }
|
||||||
|
set {
|
||||||
|
mWorkProps.AnalysisParams.UseRelocData = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool mIsRelocDataAvailable;
|
||||||
|
public bool IsRelocDataAvailable {
|
||||||
|
get { return mIsRelocDataAvailable; }
|
||||||
|
set { mIsRelocDataAvailable = value; OnPropertyChanged(); }
|
||||||
|
}
|
||||||
public bool SmartPlpHandling {
|
public bool SmartPlpHandling {
|
||||||
get { return mWorkProps.AnalysisParams.SmartPlpHandling; }
|
get { return mWorkProps.AnalysisParams.SmartPlpHandling; }
|
||||||
set {
|
set {
|
||||||
|
Reference in New Issue
Block a user