1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-11 17:29:29 +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:
Andy McFadden 2019-10-17 13:15:25 -07:00
parent c8dfa94ce2
commit 716dce5f28
10 changed files with 38 additions and 36 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}

View File

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