Implement stable undocumented opcodes

This commit is contained in:
edmccard 2012-04-11 22:05:29 -04:00
parent 8085dc61a0
commit 216ba9b6f3
3 changed files with 153 additions and 42 deletions

View File

@ -198,7 +198,8 @@ struct Env
string OpBody(int op, string chip, bool s, bool c)
{
auto env = Env(op, chip, s, c);
string ret = ((env.mode == IMP) ? AddrIMP(env) : "");
string ret = ((op == 0x20) ? "" : Address(env));
final switch (opName(op, chip))
{
case "BRK":
@ -415,19 +416,29 @@ string OpBody(int op, string chip, bool s, bool c)
ret ~= RMW(TestSet(), env);
break;
case "LAS":
return "";
ret ~= LAS_Undoc(env);
break;
case "LAX":
return ""; // address modes
if (op != 0xAB)
ret ~= Load(_A ~ " = " ~ _X, env);
else
return "";
break;
case "SAX":
return "";
ret ~= Store(_A ~ " & " ~ _X, env);
break;
case "ANC":
return "";
ret ~= ANC_Undoc(env);
break;
case "ALR":
return "";
ret ~= ALR_Undoc(env);
break;
case "ARR":
return "";
ret ~= ARR_Undoc(env);
break;
case "AXS":
return "";
ret ~= AXS_Undoc(env);
break;
case "AHX":
return "";
case "SHY":
@ -439,17 +450,26 @@ string OpBody(int op, string chip, bool s, bool c)
case "XAA":
return "";
case "SLO":
return "";
ret ~= RMW_Undoc(ShiftLeft("data"),
SetNZ(_A ~ " |= data"), env);
break;
case "RLA":
return "";
ret ~= RMW_Undoc(RotateLeft("data"),
SetNZ(_A ~ " &= data"), env);
break;
case "SRE":
return "";
ret ~= RMW_Undoc(ShiftRight("data"),
SetNZ(_A ~ " ^= data"), env);
break;
case "RRA":
return "";
ret ~= RMW_Undoc(RotateRight("data"), AddBase(env), env);
break;
case "DCP":
return "";
ret ~= RMW_Undoc(Dec("data"), CompareBase(_A, env), env);
break;
case "ISC":
return "";
ret ~= RMW_Undoc(Inc("data"), SubBase(env), env);
break;
}
return ret ~ Done(env);
}
@ -497,8 +517,7 @@ string Jump(Env env)
bool nmos = env.nmos;
if (env.op == 0x4c)
return Address(env) ~
_PC ~ " = address;\n";
return _PC ~ " = address;\n";
else if (env.op == 0x6c)
return ReadWordOp("ushort", "base", env) ~
If!(cmos)(
@ -531,10 +550,9 @@ string Branch(string check, Env env)
string Nop(Env env)
{
if (env.mode == IMP || env.mode == NP1 || env.mode == NP8)
return Address(env);
return ""; // XXX add np1/np8 stuff
else
return Address(env) ~
PreAccess(env) ~
return PreAccess(env) ~
ReadRaw("address") ~ ";\n";
}
@ -562,24 +580,26 @@ string PushReg(string reg, Env env)
string Load(string reg, Env env)
{
return Address(env) ~
ReadInto(reg, "address", env) ~
return ReadInto(reg, "address", env) ~
SetNZ(reg);
}
string Store(string reg, Env env)
{
return Address(env) ~
Write("address", reg, env);
return Write("address", reg, env);
}
string Compare(string reg, Env env)
{
return Address(env) ~
ReadInto(Local("ubyte", "data"), "address", env) ~
UpdateFlag(_C, reg ~ " >= data") ~
return ReadInto(Local("ubyte", "data"), "address", env) ~
CompareBase(reg, env);
}
string CompareBase(string reg, Env env)
{
return UpdateFlag(_C, reg ~ " >= data") ~
SetNZ("cast(ubyte)(" ~ reg ~ " - data)");
}
@ -588,8 +608,7 @@ string Bit(Env env)
{
bool notImm = (env.mode != IMM);
return Address(env) ~
ReadInto(Local("ubyte", "data"), "address", env) ~
return ReadInto(Local("ubyte", "data"), "address", env) ~
If!(notImm)(
_N ~ " = data;\n" ~
_V ~ " = ((data & 0x40) != 0);\n") ~
@ -599,17 +618,20 @@ string Bit(Env env)
string Logic(string action, Env env)
{
return Address(env) ~
ReadInto(_A, action, "address", env) ~
return ReadInto(_A, action, "address", env) ~
SetNZ(_A);
}
string Add(Env env)
{
return Address(env) ~
ReadInto(Local("ubyte", "data"), "address", env) ~
"if (" ~ _D ~ ")\n{\n" ~
return ReadInto(Local("ubyte", "data"), "address", env) ~
AddBase(env);
}
string AddBase(Env env)
{
return "if (" ~ _D ~ ")\n{\n" ~
DecAdd(env) ~
"}\nelse\n{\n" ~
HexAdd(env) ~
@ -649,12 +671,16 @@ string DecAdd(Env env)
string Sub(Env env)
{
return ReadInto(Local("ubyte", "data"), "address", env) ~
SubBase(env);
}
string SubBase(Env env)
{
bool nmos = env.nmos;
return Address(env) ~
ReadInto(Local("ubyte", "data"), "address", env) ~
"if (" ~ _D ~ ")\n{\n" ~
return "if (" ~ _D ~ ")\n{\n" ~
If!(nmos)(DecSubNMOS(), DecSubCMOS(env)) ~
"}\nelse\n{\n" ~
HexSub() ~
@ -768,8 +794,7 @@ string RMW(string action, Env env)
{
bool nmos = env.nmos;
return Address(env) ~
ReadInto(Local("ubyte", "data"), "address", env) ~
return ReadInto(Local("ubyte", "data"), "address", env) ~
If!(nmos)(Poke("address", "data", env),
Peek("address", env)) ~
action ~
@ -777,6 +802,74 @@ string RMW(string action, Env env)
}
string RMW_Undoc(string action1, string action2, Env env)
{
return ReadInto(Local("ubyte", "data"), "address", env) ~
Poke("address", "data", env) ~
action1 ~
Write("address", "data", env) ~
action2;
}
string LAS_Undoc(Env env)
{
return ReadInto(Local("ubyte", "data"), "address", env) ~
SetNZ(_X ~ " = " ~ _A ~ " = (" ~ _S ~ " & data)");
}
string ARR_Undoc(Env env)
{
return ReadInto(Local("ubyte", "data"), "address", env) ~
"ubyte tmp1 = data & " ~ _A ~ ";\n" ~
"if (" ~ _D ~ ")\n{\n" ~
"ubyte tmp2 = cast(ubyte)((tmp1 >> 1) + (" ~
_C ~ " ? 0x80 : 0));\n" ~
_N ~ " = " ~ _Z ~ " = tmp2;\n" ~
_V ~ " = (((tmp2 ^ tmp1) & 0x40) != 0);\n" ~
"if ((data & 0x0F) + (tmp1 & 0x01) > 5)\n" ~
"tmp2 = (tmp2 & 0xF0) + ((tmp2 + 0x6) & 0x0F);\n" ~
"if (tmp1 + (tmp1 & 0x10) >= 0x60)\n{\n" ~
"tmp2 += 0x60;\n" ~
SetFlag(_C) ~
"}\nelse\n" ~
ClearFlag(_C) ~
_A ~ " = tmp2;\n" ~
"}\nelse{\n" ~
_A ~ " = cast(ubyte)((tmp1 >> 1) + (" ~
_C ~ " ? 0x80 : 0));\n" ~
_N ~ " = " ~ _Z ~ " = " ~_A ~ ";\n" ~
"tmp1 >>= 7;\n" ~
_C ~ " = (tmp1 != 0);\n" ~
_V ~ " = ((tmp1 ^ ((" ~ _A ~ " >> 5) & 1)) != 0);\n}";
}
string ANC_Undoc(Env env)
{
return ReadInto(_A, "address", env) ~
SetNZ(_A) ~
_C ~ " = (" ~ _A ~ " > 0x7f);\n";
}
string ALR_Undoc(Env env)
{
return ReadInto(Local("ubyte", "data"), "address", env) ~
_A ~ " &= data;\n" ~
ShiftRight(_A);
}
string AXS_Undoc(Env env)
{
return ReadInto(Local("ubyte", "data"), "address", env) ~
_X ~ " &= " ~ _A ~ ";\n" ~
CompareBase(_X, env);
}
string Local(string type)
{
version(OpFunctions)
@ -823,7 +916,7 @@ string Address(Env env)
final switch (env.mode)
{
case IMP:
return "";
return AddrIMP(env);
case IMM:
return AddrIMM(env);
case ZP:
@ -853,7 +946,7 @@ string Address(Env env)
case NP1:
return "";
case NP8:
return Local("ushort", "address") ~ " = 0;";
return AddrNP8(env);
case KIL:
return "";
}
@ -926,6 +1019,18 @@ string AddrZPI(Env env)
ReadWordZP("ushort", "address", "base", env);
}
string AddrNP8(Env env)
{
return ReadOp(Local("ushort", "base"), env) ~
Peek(_PC, env) ~
IncPC() ~
Peek("0xff00 | base", env) ~
Peek("0xffff", env) ~
Peek("0xffff", env) ~
Peek("0xffff", env) ~
Peek("0xffff", env);
}
string CheckShortcut(string base, string addr, Env env)
{
bool nmos = env.nmos;

View File

@ -180,6 +180,6 @@ version(OpFunctions) mixin(OpBodies("65C02", vStrict, vCumulative));
void main()
{
import std.stdio;
writeln(OpBody(0x11, "65C02", true, false));
writeln(OpBody(0x11, "6502", true, false));
}
+/

View File

@ -55,5 +55,11 @@ void main()
0xb4, 0x94, 0x01, 0x21, 0x41, 0x61, 0xe1, 0xc1, 0xa1, 0x81,
0x11, 0x31, 0x51, 0x71, 0xf1, 0xd1, 0xb1, 0x91, 0xda, 0x5a,
0x7a, 0xfa, 0x89, 0x34, 0x3c, 0x1a, 0x3a, 0x80, 0x64, 0x74,
0x14, 0x1c, 0x04, 0x0c, 0x40]);
0x14, 0x1c, 0x04, 0x0c, 0x40, 0x03, 0x07, 0x0f, 0x13, 0x17,
0x1b, 0x1f, 0x23, 0x27, 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43,
0x47, 0x4f, 0x53, 0x57, 0x5b, 0x5f, 0x5c, 0x63, 0x67, 0x6f,
0x73, 0x77, 0x7b, 0x7f, 0xc3, 0xc7, 0xcf, 0xd3, 0xd7, 0xdb,
0xdf, 0xe3, 0xe7, 0xe7, 0xf3, 0xf7, 0xfb, 0xff, 0xbb, 0x83,
0x87, 0x8f, 0x97, 0xa3, 0xa7, 0xaf, 0xb3, 0xb7, 0xbf, 0x6b,
0x0b, 0x2b, 0x4b, 0xeb, 0xcb]);
}