mirror of
https://github.com/fadden/6502bench.git
synced 2025-01-14 07:29:44 +00:00
Pass operand to extension script JSR/JSL handlers
Sort of silly to have every handler immediately pull the operand out of the file data. (This is arguably less efficient, since we now have to serialize the argument across the AppDomain boundary, but we should be okay spending a few extra nanoseconds here.)
This commit is contained in:
parent
c8dfa94ce2
commit
716dce5f28
@ -541,8 +541,8 @@ namespace Asm65 {
|
||||
/// </summary>
|
||||
/// <param name="data">65xx code.</param>
|
||||
/// <param name="offset">Offset of opcode.</param>
|
||||
/// <param name="flags">Current status flags.</param>
|
||||
/// <returns>Operand value.</returns>
|
||||
/// <param name="flags">Current status flags (need M/X).</param>
|
||||
/// <returns>Operand value, or -1 if the instruction doesn't have an operand.</returns>
|
||||
public int GetOperand(byte[] data, int offset, StatusFlags flags) {
|
||||
switch (GetLength(flags)) {
|
||||
case 1:
|
||||
|
@ -88,8 +88,9 @@ namespace PluginCommon {
|
||||
/// The file data is guaranteed to hold all bytes of the JSR (offset + 2).
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset of the JSR instruction.</param>
|
||||
/// <param name="operand">16-bit JSR operand.</param>
|
||||
/// <param name="noContinue">Set to true if the JSR doesn't actually return.</param>
|
||||
void CheckJsr(int offset, out bool noContinue);
|
||||
void CheckJsr(int offset, int operand, out bool noContinue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -102,8 +103,9 @@ namespace PluginCommon {
|
||||
/// The file data is guaranteed to hold all bytes of the JSL (offset + 3).
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset of the JSL instruction.</param>
|
||||
/// <param name="operand">24-bit JSL operand.</param>
|
||||
/// <param name="noContinue">Set to true if the JSL doesn't actually return.</param>
|
||||
void CheckJsl(int offset, out bool noContinue);
|
||||
void CheckJsl(int offset, int operand, out bool noContinue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -938,6 +938,7 @@ namespace SourceGen {
|
||||
/// <param name="noContinue">Set if any plugin declares the call to be no-continue.</param>
|
||||
/// <returns>Updated value for noContinue.</returns>
|
||||
private bool CheckForInlineCall(OpDef op, int offset, bool noContinue) {
|
||||
int operand = op.GetOperand(mFileData, offset, mAnattribs[offset].StatusFlags);
|
||||
for (int i = 0; i < mScriptArray.Length; i++) {
|
||||
try {
|
||||
IPlugin script = mScriptArray[i];
|
||||
@ -946,10 +947,10 @@ namespace SourceGen {
|
||||
// interface was implemented but a bit slow when it wasn't. For performance
|
||||
// we query the capability flags instead.
|
||||
if (op == OpDef.OpJSR_Abs && (mPluginCaps[i] & PluginCap.JSR) != 0) {
|
||||
((IPlugin_InlineJsr)script).CheckJsr(offset, out bool noCont);
|
||||
((IPlugin_InlineJsr)script).CheckJsr(offset, operand, out bool noCont);
|
||||
noContinue |= noCont;
|
||||
} else if (op == OpDef.OpJSR_AbsLong && (mPluginCaps[i] & PluginCap.JSL) != 0) {
|
||||
((IPlugin_InlineJsl)script).CheckJsl(offset, out bool noCont);
|
||||
((IPlugin_InlineJsl)script).CheckJsl(offset, operand, out bool noCont);
|
||||
noContinue |= noCont;
|
||||
} else if ((op == OpDef.OpBRK_Implied || op == OpDef.OpBRK_StackInt) &&
|
||||
(mPluginCaps[i] & PluginCap.BRK) != 0) {
|
||||
|
@ -49,10 +49,9 @@ namespace ExtensionScriptSample {
|
||||
return beforeLabel == CALL_LABEL || afterLabel == CALL_LABEL;
|
||||
}
|
||||
|
||||
public void CheckJsr(int offset, out bool noContinue) {
|
||||
public void CheckJsr(int offset, int operand, out bool noContinue) {
|
||||
noContinue = false;
|
||||
int target = Util.GetWord(mFileData, offset + 1, 2, false);
|
||||
if (target != mInlineL1StringAddr) {
|
||||
if (operand != mInlineL1StringAddr) {
|
||||
return;
|
||||
}
|
||||
if (offset + 3 >= mFileData.Length) {
|
||||
|
@ -47,10 +47,9 @@ namespace ExtensionScriptSample {
|
||||
return beforeLabel.StartsWith(LABEL_PREFIX) || afterLabel.StartsWith(LABEL_PREFIX);
|
||||
}
|
||||
|
||||
public void CheckJsr(int offset, out bool noContinue) {
|
||||
public void CheckJsr(int offset, int operand, out bool noContinue) {
|
||||
noContinue = false;
|
||||
int target = Util.GetWord(mFileData, offset + 1, 2, false);
|
||||
if (!mNullStringAddrs.ContainsKey(target)) {
|
||||
if (!mNullStringAddrs.ContainsKey(operand)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,11 @@ namespace RuntimeData.Apple {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CheckJsl(int offset, out bool noContinue) {
|
||||
public void CheckJsl(int offset, int operand, out bool noContinue) {
|
||||
const int INLINE_ENTRY = 0xe100a8;
|
||||
|
||||
noContinue = false;
|
||||
if (offset + 7 < mFileData.Length && mFileData[offset + 1] == 0xa8 &&
|
||||
mFileData[offset + 2] == 0x00 && mFileData[offset + 3] == 0xe1) {
|
||||
if (offset + 7 < mFileData.Length && operand == INLINE_ENTRY) {
|
||||
// match!
|
||||
|
||||
int req = Util.GetWord(mFileData, offset + 4, 2, false);
|
||||
|
@ -19,11 +19,10 @@ using System.Collections.Generic;
|
||||
using PluginCommon;
|
||||
|
||||
/*
|
||||
# toolbox equ $e10000
|
||||
# pea ...
|
||||
# pea ...
|
||||
# ldx #function
|
||||
# jsl toolbox
|
||||
# jsl $e10000
|
||||
*/
|
||||
|
||||
namespace RuntimeData.Apple {
|
||||
@ -56,15 +55,16 @@ namespace RuntimeData.Apple {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CheckJsl(int offset, out bool noContinue) {
|
||||
public void CheckJsl(int offset, int operand, out bool noContinue) {
|
||||
const int TOOLBOX = 0xe10000;
|
||||
|
||||
noContinue = false;
|
||||
if (offset < 3) {
|
||||
return;
|
||||
}
|
||||
// This only works if the LDX with the function comes right before the JSL.
|
||||
// Fortunately, the assembler macros all work that way.
|
||||
if (mFileData[offset + 1] == 0x00 && mFileData[offset + 2] == 0x00 &&
|
||||
mFileData[offset + 3] == 0xe1 && mFileData[offset - 3] == 0xa2 /*LDX imm*/) {
|
||||
if (operand == TOOLBOX && mFileData[offset - 3] == 0xa2 /*LDX imm*/) {
|
||||
// match!
|
||||
|
||||
int func = Util.GetWord(mFileData, offset - 2, 2, false);
|
||||
|
@ -178,10 +178,11 @@ namespace RuntimeData.Apple {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CheckJsr(int offset, out bool noContinue) {
|
||||
public void CheckJsr(int offset, int operand, out bool noContinue) {
|
||||
const int MLI_ENTRY = 0xbf00;
|
||||
|
||||
noContinue = false;
|
||||
if (offset + 6 < mFileData.Length &&
|
||||
mFileData[offset + 1] == 0x00 && mFileData[offset + 2] == 0xbf) {
|
||||
if (offset + 6 < mFileData.Length && operand == MLI_ENTRY) {
|
||||
// match!
|
||||
|
||||
byte req = mFileData[offset + 3];
|
||||
|
@ -24,10 +24,11 @@ namespace RuntimeData.Test2011 {
|
||||
mAppRef.DebugLog("Test2011(id=" + AppDomain.CurrentDomain.Id + "): prepare()");
|
||||
}
|
||||
|
||||
public void CheckJsr(int offset, out bool noContinue) {
|
||||
public void CheckJsr(int offset, int operand, out bool noContinue) {
|
||||
int ADDR = 0x2456;
|
||||
|
||||
noContinue = false;
|
||||
if (offset + 7 < mFileData.Length &&
|
||||
mFileData[offset + 1] == 0x56 && mFileData[offset + 2] == 0x24) {
|
||||
if (offset + 7 < mFileData.Length && operand == ADDR) {
|
||||
mAppRef.SetInlineDataFormat(offset + 3, 4, DataType.NumericLE,
|
||||
DataSubType.None, null);
|
||||
}
|
||||
|
@ -61,10 +61,9 @@ namespace RuntimeData.Test2022 {
|
||||
return (beforeLabel.StartsWith(PREFIX) || afterLabel.StartsWith(PREFIX));
|
||||
}
|
||||
|
||||
public void CheckJsr(int offset, out bool noContinue) {
|
||||
public void CheckJsr(int offset, int operand, out bool noContinue) {
|
||||
noContinue = false;
|
||||
int target = Util.GetWord(mFileData, offset + 1, 2, false);
|
||||
if (target == mInline8StringAddr) {
|
||||
if (operand == mInline8StringAddr) {
|
||||
if (offset + 3 + 8 > mFileData.Length) {
|
||||
mAppRef.DebugLog("8string ran off end at +" +
|
||||
(offset + 3).ToString("x6"));
|
||||
@ -72,7 +71,7 @@ namespace RuntimeData.Test2022 {
|
||||
}
|
||||
mAppRef.SetInlineDataFormat(offset + 3, 8,
|
||||
DataType.StringGeneric, DataSubType.Ascii, null);
|
||||
} else if (target == mInlineRev8StringAddr) {
|
||||
} else if (operand == mInlineRev8StringAddr) {
|
||||
if (offset + 3 + 8 > mFileData.Length) {
|
||||
mAppRef.DebugLog("rev8string ran off end at +" +
|
||||
(offset + 3).ToString("x6"));
|
||||
@ -80,7 +79,7 @@ namespace RuntimeData.Test2022 {
|
||||
}
|
||||
mAppRef.SetInlineDataFormat(offset + 3, 8,
|
||||
DataType.StringReverse, DataSubType.Ascii, null);
|
||||
} else if (target == mInlineNullStringAddr) {
|
||||
} else if (operand == mInlineNullStringAddr) {
|
||||
// look for the terminating null byte
|
||||
int nullOff = offset + 3;
|
||||
while (nullOff < mFileData.Length) {
|
||||
@ -99,10 +98,9 @@ namespace RuntimeData.Test2022 {
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckJsl(int offset, out bool noContinue) {
|
||||
public void CheckJsl(int offset, int operand, out bool noContinue) {
|
||||
noContinue = false;
|
||||
int target = Util.GetWord(mFileData, offset + 1, 3, false);
|
||||
if (target == mInlineL1StringAddr) {
|
||||
if (operand == mInlineL1StringAddr) {
|
||||
// 0 1 2 3 4 5
|
||||
// 22 00 10 01 01 66
|
||||
if (offset + 4 >= mFileData.Length) {
|
||||
@ -117,7 +115,7 @@ namespace RuntimeData.Test2022 {
|
||||
}
|
||||
mAppRef.SetInlineDataFormat(offset + 4, len + 1,
|
||||
DataType.StringL8, DataSubType.Ascii, null);
|
||||
} else if (target == mInlineL2StringAddr) {
|
||||
} else if (operand == mInlineL2StringAddr) {
|
||||
if (offset + 5 >= mFileData.Length) {
|
||||
return; // length word is off end
|
||||
}
|
||||
@ -130,7 +128,7 @@ namespace RuntimeData.Test2022 {
|
||||
}
|
||||
mAppRef.SetInlineDataFormat(offset + 4, len + 2,
|
||||
DataType.StringL16, DataSubType.Ascii, null);
|
||||
} else if (target == mInlineDciStringAddr) {
|
||||
} else if (operand == mInlineDciStringAddr) {
|
||||
// look for the first byte whose high bit doesn't match the first byte's bit
|
||||
// 0 1 2 3 4 5
|
||||
// 22 00 30 01 66 c1
|
||||
|
Loading…
x
Reference in New Issue
Block a user