mirror of
https://github.com/edmccard/twoapple-reboot.git
synced 2025-02-19 13:31:31 +00:00
Add all documented 6502 opcodes.
This commit is contained in:
parent
c5fb366184
commit
0e330f8285
550
src/cpu6502.d
550
src/cpu6502.d
@ -1,3 +1,26 @@
|
||||
/+
|
||||
+ cpu6502.d
|
||||
+
|
||||
+ Copyright: 2012 Ed McCardell, 2007 Gerald Stocker
|
||||
+
|
||||
+ This file is part of twoapple-reboot.
|
||||
+
|
||||
+ twoapple-reboot is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; either version 2 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ twoapple-reboot is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with twoapple-reboot; if not, write to the Free Software
|
||||
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
+/
|
||||
|
||||
|
||||
module cpu6502;
|
||||
|
||||
|
||||
@ -78,12 +101,6 @@ static if (!__traits(compiles, { bool b = opArray; })) enum opArray = 0;
|
||||
static assert (versionCheck);
|
||||
|
||||
|
||||
// This needs to be before any mixins which call any CTFE functions
|
||||
// that make use of these constants.
|
||||
enum { IMP, IMM, ZP, ZPX, ZPY, IZX, IZY, ABS, ABX, ABY, IND, REL,
|
||||
ZPI, ABI, NP1, NP8, KIL }
|
||||
|
||||
|
||||
final class Cpu(string chip, bool strict, bool cumulative)
|
||||
{
|
||||
static assert(chip == "6502" || chip == "65C02" || chip == "65c02");
|
||||
@ -122,13 +139,11 @@ final class Cpu(string chip, bool strict, bool cumulative)
|
||||
ubyte A, X, Y, S;
|
||||
ushort PC;
|
||||
|
||||
// The status flags.
|
||||
ubyte N, Z;
|
||||
bool V, D, I, C;
|
||||
|
||||
static if (opArray)
|
||||
{
|
||||
mixin(OpArrayDef());
|
||||
}
|
||||
static if (opArray) { mixin(OpArrayDef()); }
|
||||
|
||||
// TODO: other methods for stopping cpu
|
||||
bool keepRunning;
|
||||
@ -192,10 +207,6 @@ enum ushort IRQ_VECTOR = 0xFFFE;
|
||||
|
||||
private:
|
||||
|
||||
version(OpFunctions) mixin(OpBodies("6502", vStrict, vCumulative));
|
||||
version(OpFunctions) mixin(OpBodies("65C02", vStrict, vCumulative));
|
||||
|
||||
|
||||
string OpArrayDef()
|
||||
{
|
||||
version(OpDelegates)
|
||||
@ -243,6 +254,18 @@ string OpBodies(string chip, bool strict, bool cumulative)
|
||||
If!(cumulative)("int cycles = 1;\n") ~
|
||||
OpBody(op, chip, strict, cumulative) ~ "}\n";
|
||||
}
|
||||
/+
|
||||
foreach (op; 13..256)
|
||||
version(OpDelegates)
|
||||
ret ~= "final void opcode_" ~ Hex2(op) ~ "()\n{\n" ~
|
||||
If!(cumulative)("int cycles = 1;\n") ~
|
||||
"" ~ "}\n";
|
||||
version(OpFunctions)
|
||||
ret ~= "void opcode_" ~ Hex2(op) ~
|
||||
"(T)(T cpu) if (is" ~ chip ~ "!T)\n{\n" ~
|
||||
If!(cumulative)("int cycles = 1;\n") ~
|
||||
"" ~ "}\n";
|
||||
+/
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -308,7 +331,8 @@ string OpBody(int op, string chip, bool s, bool c)
|
||||
return Jump(op, chip, s, c) ~
|
||||
Done(c);
|
||||
case "KIL":
|
||||
return "";
|
||||
return Attr("PC") ~ "--;\n" ~
|
||||
Done(c);
|
||||
case "BPL":
|
||||
return Branch("!(" ~ Attr("N") ~ " & 0x80)", nmos, s, c) ~
|
||||
Done(c);
|
||||
@ -337,82 +361,96 @@ string OpBody(int op, string chip, bool s, bool c)
|
||||
return Branch("!" ~ Attr("Z"), nmos, s, c) ~
|
||||
Done(c);
|
||||
case "CLC":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
ClearFlag("C") ~
|
||||
Done(c);
|
||||
case "SEC":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
SetFlag("C") ~
|
||||
Done(c);
|
||||
case "CLI":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
ClearFlag("I") ~
|
||||
Done(c);
|
||||
case "SEI":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
SetFlag("I") ~
|
||||
Done(c);
|
||||
case "CLV":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
ClearFlag("V") ~
|
||||
Done(c);
|
||||
case "CLD":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
ClearFlag("D") ~
|
||||
Done(c);
|
||||
case "SED":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
SetFlag("D") ~
|
||||
Done(c);
|
||||
case "NOP":
|
||||
return ""; // address modes
|
||||
return Nop(op, chip, s, c) ~
|
||||
Done(c);
|
||||
case "TAX":
|
||||
return "";
|
||||
return Transfer(op, "A", "X", s, c) ~
|
||||
Done(c);
|
||||
case "TXA":
|
||||
return "";
|
||||
return Transfer(op, "X", "A", s, c) ~
|
||||
Done(c);
|
||||
case "TAY":
|
||||
return "";
|
||||
return Transfer(op, "A", "Y", s, c) ~
|
||||
Done(c);
|
||||
case "TYA":
|
||||
return "";
|
||||
return Transfer(op, "Y", "A", s, c) ~
|
||||
Done(c);
|
||||
case "TSX":
|
||||
return "";
|
||||
return Transfer(op, "S", "X", s, c) ~
|
||||
Done(c);
|
||||
case "TXS":
|
||||
return "";
|
||||
return Transfer(op, "X", "S", s, c) ~
|
||||
Done(c);
|
||||
case "DEX":
|
||||
return DecReg("X", s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
Dec(Attr("X")) ~
|
||||
Done(c);
|
||||
case "DEY":
|
||||
return DecReg("Y", s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
Dec(Attr("Y")) ~
|
||||
Done(c);
|
||||
case "INX":
|
||||
return IncReg("X", s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
Inc(Attr("X")) ~
|
||||
Done(c);
|
||||
case "INY":
|
||||
return IncReg("Y", s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
Inc(Attr("Y")) ~
|
||||
Done(c);
|
||||
case "PHP":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
Push(Attr("statusToByte()"), s, c) ~
|
||||
Done(c);
|
||||
case "PLP":
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
PullStatus(s, c) ~
|
||||
Done(c);
|
||||
case "PLA":
|
||||
return AddrImplied(s, c) ~
|
||||
PullInto(Attr("A"), s, c) ~
|
||||
SetNZ(Attr("A")) ~
|
||||
return PullReg("A", s, c) ~
|
||||
Done(c);
|
||||
case "PLX":
|
||||
return "";
|
||||
return PullReg("X", s, c) ~
|
||||
Done(c);
|
||||
case "PLY":
|
||||
return "";
|
||||
return PullReg("Y", s, c) ~
|
||||
Done(c);
|
||||
case "PHA":
|
||||
return "";
|
||||
return PushReg("A", s, c) ~
|
||||
Done(c);
|
||||
case "PHX":
|
||||
return "";
|
||||
return PushReg("X", s, c) ~
|
||||
Done(c);
|
||||
case "PHY":
|
||||
return "";
|
||||
return PushReg("Y", s, c) ~
|
||||
Done(c);
|
||||
case "LDA":
|
||||
return Load(op, "A", chip, s, c) ~
|
||||
Done(c);
|
||||
@ -434,7 +472,8 @@ string OpBody(int op, string chip, bool s, bool c)
|
||||
case "STZ":
|
||||
return "";
|
||||
case "BIT":
|
||||
return ""; // address modes
|
||||
return Bit(op, chip, s, c) ~
|
||||
Done(c);
|
||||
case "CMP":
|
||||
return Compare(op, "A", chip, s, c) ~
|
||||
Done(c);
|
||||
@ -460,23 +499,35 @@ string OpBody(int op, string chip, bool s, bool c)
|
||||
return Sub(op, chip, s, c) ~
|
||||
Done(c);
|
||||
case "ASL":
|
||||
return ""; // n/c (op, cyc)
|
||||
if (op == 0x0a)
|
||||
return AddrIMP(s, c) ~ ShiftLeft(Attr("A")) ~ Done(c);
|
||||
else
|
||||
return RMW(op, ShiftLeft("data"), chip, s, c) ~ Done(c);
|
||||
case "ROL":
|
||||
return ""; // n/c (op, cyc)
|
||||
if (op == 0x2a)
|
||||
return AddrIMP(s, c) ~ RotateLeft(Attr("A")) ~ Done(c);
|
||||
else
|
||||
return RMW(op, RotateLeft("data"), chip, s, c) ~ Done(c);
|
||||
case "LSR":
|
||||
return ""; // n/c (op, cyc)
|
||||
if (op == 0x4a)
|
||||
return AddrIMP(s, c) ~ ShiftRight(Attr("A")) ~ Done(c);
|
||||
else
|
||||
return RMW(op, ShiftRight("data"), chip, s, c) ~ Done(c);
|
||||
case "ROR":
|
||||
return ""; // n/c (op, cyc)
|
||||
if (op == 0x6a)
|
||||
return AddrIMP(s, c) ~ ShiftRight(Attr("A")) ~ Done(c);
|
||||
else
|
||||
return RMW(op, RotateRight("data"), chip, s, c) ~ Done(c);
|
||||
case "INC":
|
||||
if (op == 0x1a)
|
||||
return IncReg("A", s, c) ~ Done(c);
|
||||
return AddrIMP(s, c) ~ Inc(Attr("A")) ~ Done(c);
|
||||
else
|
||||
return RMW(op, "data++;\n", chip, s, c) ~ Done(c);
|
||||
return RMW(op, Inc("data"), chip, s, c) ~ Done(c);
|
||||
case "DEC":
|
||||
if (op == 0x3a)
|
||||
return DecReg("A", s, c) ~ Done(c);
|
||||
return AddrIMP(s, c) ~ Dec(Attr("A")) ~ Done(c);
|
||||
else
|
||||
return RMW(op, "data--;\n", chip, s, c) ~ Done(c);
|
||||
return RMW(op, Dec("data"), chip, s, c) ~ Done(c);
|
||||
case "TRB":
|
||||
return "";
|
||||
case "TSB":
|
||||
@ -521,52 +572,116 @@ string OpBody(int op, string chip, bool s, bool c)
|
||||
}
|
||||
|
||||
|
||||
string AddrImmediate(bool s, bool c)
|
||||
string AddrIMM(bool s, bool c)
|
||||
{
|
||||
return Local("ushort", "address") ~ " = " ~ Attr("PC") ~ "++;\n";
|
||||
return Local("ushort") ~ "address = " ~ Attr("PC") ~ "++;\n";
|
||||
}
|
||||
|
||||
string AddrImplied(bool s, bool c)
|
||||
string AddrIMP(bool s, bool c)
|
||||
{
|
||||
return Peek(Attr("PC"), s, c);
|
||||
}
|
||||
|
||||
string AddrZP(bool s, bool c)
|
||||
{
|
||||
return ReadOp(Local("ushort", "address"), c);
|
||||
}
|
||||
|
||||
string AddrAbsoluteIdx(int op, string reg, string chip, bool s, bool c)
|
||||
string AddrZPXY(string reg, string chip, bool s, bool c)
|
||||
{
|
||||
bool nmos = (chip == "6502");
|
||||
|
||||
return ReadOp(Local("ushort", "base"), c) ~
|
||||
If!(nmos)(
|
||||
Peek("base", s, c),
|
||||
Peek(Attr("PC"), s, c)) ~
|
||||
Local("ushort") ~
|
||||
"address = cast(ubyte)(base + " ~ Attr(reg) ~ ");\n";
|
||||
}
|
||||
|
||||
string AddrIZX(string chip, bool s, bool c)
|
||||
{
|
||||
bool nmos = (chip == "6502");
|
||||
return ReadOp(Local("ushort", "base"), c) ~
|
||||
If!(nmos)(
|
||||
Peek("base", s, c),
|
||||
Peek(Attr("PC"), s, c)) ~
|
||||
ReadWordZP("ushort", "address", "base + " ~ Attr("X"), c);
|
||||
}
|
||||
|
||||
string AddrIZY(int op, string chip, bool s, bool c)
|
||||
{
|
||||
int exCyc = opExCyc(op, chip);
|
||||
bool nmos = (chip == "6502");
|
||||
|
||||
return ReadOp("ubyte vector", c) ~
|
||||
ReadWordZP("ushort", "base", "vector", c) ~
|
||||
Local("ushort") ~
|
||||
"address = cast(ushort)(base + " ~ Attr("Y") ~ ");\n" ~
|
||||
CheckShortcut("address", Attr("PC"),
|
||||
exCyc, nmos, s, c);
|
||||
}
|
||||
|
||||
string AddrABS(bool s, bool c)
|
||||
{
|
||||
return ReadWordOp("ushort", "address", c);
|
||||
}
|
||||
|
||||
string AddrABXY(int op, string reg, string chip, bool s, bool c)
|
||||
{
|
||||
bool nmos = (chip == "6502");
|
||||
int exCyc = opExCyc(op, chip);
|
||||
string IDX = Attr(reg);
|
||||
|
||||
return ReadWordOpLocal("ushort", "base", c) ~
|
||||
Local("ushort","address")~" = cast(ushort)(base + " ~ IDX ~ ");\n" ~
|
||||
"ushort guess = (base & 0xFF00) | cast(ubyte)address;\n" ~
|
||||
"if (guess != address)\n{\n" ~
|
||||
If!(nmos)(Peek("guess", s, c), Peek(Attr("PC"), s, c)) ~
|
||||
return ReadWordOp("ushort", "base", c) ~
|
||||
Local("ushort") ~ "address = cast(ushort)(base + " ~ IDX ~ ");\n" ~
|
||||
CheckShortcut("address", Attr("PC"), exCyc, nmos, s, c);
|
||||
}
|
||||
|
||||
string AddrZPI(bool s, bool c)
|
||||
{
|
||||
return ReadOp(Local("ushort", "base"), c) ~
|
||||
ReadWordZP("ushort", "address", "base", c);
|
||||
}
|
||||
|
||||
string Branch(string check, bool nmos, bool s, bool c)
|
||||
{
|
||||
string PC = Attr("PC");
|
||||
return ReadOp(Local("ubyte", "op1"), c) ~
|
||||
"if (" ~ check ~ ")\n{\n" ~
|
||||
Peek(PC, s, c) ~
|
||||
Local("ushort", "base") ~ " = " ~ PC ~ ";\n" ~
|
||||
PC ~ " = cast(ushort)(" ~ PC ~ " + cast(byte)op1);\n" ~
|
||||
CheckShortcut(Attr("PC"), "base", 0, nmos, s, c) ~
|
||||
"}\n";
|
||||
}
|
||||
|
||||
string CheckShortcut(string addr, string pc, int exCyc, bool nmos, bool s,
|
||||
bool c)
|
||||
{
|
||||
return "ushort guess = (base & 0xFF00) | cast(ubyte)" ~ addr ~ ";\n" ~
|
||||
"if (guess != " ~ addr ~ ")\n{\n" ~
|
||||
If!(nmos)(Peek("guess", s, c),
|
||||
Peek(pc, s, c)) ~
|
||||
"}\n" ~
|
||||
If!(exCyc)("else\n{\n" ~ Peek("address", s, c) ~ "}\n");
|
||||
}
|
||||
|
||||
|
||||
string Branch(string check, bool nmos, bool s, bool c)
|
||||
string Nop(int op, string chip, bool s, bool c)
|
||||
{
|
||||
string PC = Attr("PC");
|
||||
return ReadInto(Local("ubyte", "op1"), PC, c) ~
|
||||
IncPC() ~
|
||||
"if (" ~ check ~ ")\n{\n" ~
|
||||
Peek(PC, s, c) ~
|
||||
Local("ushort", "base") ~ " = " ~ PC ~ ";\n" ~
|
||||
PC ~ " = cast(ushort)(" ~ PC ~ " + cast(byte)op1);\n" ~
|
||||
"ushort guess = (base & 0xFF00) | cast(ubyte)" ~ PC ~ ";\n" ~
|
||||
"if (guess != " ~ PC ~ ")\n{\n" ~
|
||||
If!(nmos)(Peek("guess", s, c), Peek("base", s, c)) ~
|
||||
"}\n}\n";
|
||||
auto mode = opMode(op, chip);
|
||||
if (mode == IMP || mode == NP1 || mode == NP8)
|
||||
return Address(op, chip, s, c);
|
||||
else
|
||||
return Address(op, chip, s, c) ~
|
||||
Peek("address", true, c);
|
||||
}
|
||||
|
||||
|
||||
string Break(bool s, bool c)
|
||||
{
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
IncPC() ~
|
||||
PushPC(s, c) ~
|
||||
Push(Attr("statusToByte()"), s, c) ~
|
||||
@ -577,11 +692,9 @@ string Break(bool s, bool c)
|
||||
|
||||
string RetSub(bool s, bool c)
|
||||
{
|
||||
string PC = Attr("PC");
|
||||
|
||||
return AddrImplied(s, c) ~
|
||||
return AddrIMP(s, c) ~
|
||||
PullPC(s, c) ~
|
||||
Peek(PC, s, c) ~
|
||||
Peek(Attr("PC"), s, c) ~
|
||||
IncPC();
|
||||
}
|
||||
|
||||
@ -590,22 +703,149 @@ string JumpSub(bool s, bool c)
|
||||
{
|
||||
string PC = Attr("PC");
|
||||
|
||||
return ReadInto(Local("ushort", "address"), PC ~ "++", c) ~
|
||||
return ReadOp(Local("ushort", "address"), c) ~
|
||||
Peek("0x0100 + " ~ Attr("S"), s, c) ~
|
||||
PushPC(s, c) ~
|
||||
PreAccess(c) ~
|
||||
"address |= (" ~ ReadRaw(PC ~ "++") ~ " << 8);\n" ~
|
||||
PreAccess(c) ~ "address |= (" ~ ReadRaw(PC ~ "++") ~ " << 8);\n" ~
|
||||
PC ~ " = address;\n";
|
||||
}
|
||||
|
||||
|
||||
string Jump(int op, string chip, bool s, bool c)
|
||||
{
|
||||
bool nmos = (chip == "6502");
|
||||
string PC = Attr("PC");
|
||||
|
||||
if (op == 0x4c)
|
||||
return Address(op, chip, s, c) ~
|
||||
Attr("PC") ~ " = address;\n";
|
||||
else
|
||||
PC ~ " = address;\n";
|
||||
else if (op == 0x6c)
|
||||
return ReadWordOp("ushort", "base", c) ~
|
||||
If!(nmos)(
|
||||
"",
|
||||
Peek(PC, s, c)) ~
|
||||
ReadWordBasic(PC, "base",
|
||||
If!(nmos)(
|
||||
"(base & 0xFF00) | cast(ubyte)(base + 1)",
|
||||
"cast(ushort)(base + 1)"), c);
|
||||
else if (op == 0x7c)
|
||||
return ReadWordOp("ushort", "base", c) ~
|
||||
Peek(PC, s, c) ~
|
||||
ReadWord(PC, "cast(ushort)(base + " ~ Attr("X") ~ ")", c);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
string ReadInto(string var, string action, string addr, bool c)
|
||||
{
|
||||
return PreAccess(c) ~
|
||||
var ~ " " ~ action ~ " " ~ ReadRaw("(" ~ addr ~ ")") ~ ";\n";
|
||||
}
|
||||
|
||||
string ReadInto(string var, string addr, bool c)
|
||||
{
|
||||
return ReadInto(var, "=", addr, c);
|
||||
}
|
||||
|
||||
string ReadOp(string var, bool c)
|
||||
{
|
||||
return ReadInto(var, Attr("PC") ~ "++", c);
|
||||
}
|
||||
|
||||
string ReadRaw(string addr)
|
||||
{
|
||||
return Attr("memory") ~ ".read(" ~ addr ~")";
|
||||
}
|
||||
|
||||
string ReadWordBasic(string type, string var, string addr1, string addr2,
|
||||
bool c)
|
||||
{
|
||||
return PreAccess(c) ~
|
||||
Local(type, var) ~ " = " ~ ReadRaw(addr1) ~ ";\n" ~
|
||||
PreAccess(c) ~
|
||||
var ~ " |= ((" ~ ReadRaw(addr2) ~ ") << 8);\n";
|
||||
}
|
||||
|
||||
string ReadWordBasic(string var, string addr1, string addr2, bool c)
|
||||
{
|
||||
return ReadWordBasic("", var, addr1, addr2, c);
|
||||
}
|
||||
|
||||
string ReadWord(string type, string var, string addr, bool c)
|
||||
{
|
||||
return ReadWordBasic(type, var, addr, "cast(ushort)(" ~ addr ~ " + 1)", c);
|
||||
}
|
||||
|
||||
string ReadWord(string var, string addr, bool c)
|
||||
{
|
||||
return ReadWord("", var, addr, c);
|
||||
}
|
||||
|
||||
string ReadWordZP(string type, string var, string addr, bool c)
|
||||
{
|
||||
return ReadWordBasic(type, var, "cast(ubyte)( " ~ addr ~ ")",
|
||||
"cast(ubyte)(" ~ addr ~ " + 1)", c);
|
||||
}
|
||||
|
||||
string ReadWordZP(string var, string addr, bool c)
|
||||
{
|
||||
return ReadWordZP("", var, addr, c);
|
||||
}
|
||||
|
||||
string ReadWordOp(string type, string var, bool c)
|
||||
{
|
||||
string PC = Attr("PC");
|
||||
|
||||
return ReadWordBasic(type, var, PC ~ "++", PC ~ "++", c);
|
||||
}
|
||||
|
||||
string ReadWordOp(string var, bool c)
|
||||
{
|
||||
return ReadWordOp("", var, c);
|
||||
}
|
||||
|
||||
|
||||
string Local(string type)
|
||||
{
|
||||
version(OpSwitch)
|
||||
return "";
|
||||
else version(OpNestedSwitch)
|
||||
return "";
|
||||
else
|
||||
return type ~ " ";
|
||||
}
|
||||
|
||||
string Local(string type, string var)
|
||||
{
|
||||
version(OpSwitch)
|
||||
return var;
|
||||
else version(OpNestedSwitch)
|
||||
return var;
|
||||
else
|
||||
return type ~ " " ~ var;
|
||||
}
|
||||
|
||||
|
||||
string Transfer(int op, string source, string dest, bool s, bool c)
|
||||
{
|
||||
return AddrIMP(s, c) ~
|
||||
Attr(dest) ~ " = " ~ Attr(source) ~ ";\n" ~
|
||||
((op != 0x9a) ? SetNZ(Attr(dest)) : "");
|
||||
}
|
||||
|
||||
|
||||
string PullReg(string reg, bool s, bool c)
|
||||
{
|
||||
return AddrIMP(s, c) ~
|
||||
PullInto(Attr(reg), s, c) ~
|
||||
SetNZ(Attr(reg));
|
||||
}
|
||||
|
||||
|
||||
string PushReg(string reg, bool s, bool c)
|
||||
{
|
||||
return AddrIMP(s, c) ~
|
||||
Push(Attr(reg), s, c);
|
||||
}
|
||||
|
||||
|
||||
@ -633,10 +873,23 @@ string Compare(int op, string reg, string chip, bool s, bool c)
|
||||
}
|
||||
|
||||
|
||||
string Bit(int op, string chip, bool s, bool c)
|
||||
{
|
||||
bool notImm = (opMode(op, chip) != IMM);
|
||||
|
||||
return Address(op, chip, s, c) ~
|
||||
ReadInto(Local("ubyte", "data"), "address", c) ~
|
||||
If!(notImm)(
|
||||
Attr("N") ~ " = data;\n" ~
|
||||
Attr("V") ~ " = ((data & 0x40) != 0);\n") ~
|
||||
Attr("Z") ~ " = (" ~ Attr("A") ~ " & data);\n";
|
||||
}
|
||||
|
||||
|
||||
string Logic(int op, string action, string chip, bool s, bool c)
|
||||
{
|
||||
return Address(op, chip, s, c) ~
|
||||
ReadInto(Attr("A"), "address", c, action) ~
|
||||
ReadInto(Attr("A"), action, "address", c) ~
|
||||
SetNZ(Attr("A"));
|
||||
}
|
||||
|
||||
@ -646,9 +899,9 @@ string Add(int op, string chip, bool s, bool c)
|
||||
return Address(op, chip, s, c) ~
|
||||
ReadInto(Local("ubyte", "data"), "address", c) ~
|
||||
"if (" ~ Attr("D") ~ ")\n{\n" ~
|
||||
DecAdd(chip, s, c) ~
|
||||
DecAdd(chip, s, c) ~
|
||||
"}\nelse\n{\n" ~
|
||||
HexAdd(chip, s, c) ~
|
||||
HexAdd(chip, s, c) ~
|
||||
"}\n";
|
||||
}
|
||||
|
||||
@ -692,9 +945,9 @@ string Sub(int op, string chip, bool s, bool c)
|
||||
return Address(op, chip, s, c) ~
|
||||
ReadInto(Local("ubyte", "data"), "address", c) ~
|
||||
"if (" ~ Attr("D") ~ ")\n{\n" ~
|
||||
DecSub(chip, s, c) ~
|
||||
DecSub(chip, s, c) ~
|
||||
"}\nelse\n{\n" ~
|
||||
HexSub(chip, s, c) ~
|
||||
HexSub(chip, s, c) ~
|
||||
"}\n";
|
||||
}
|
||||
|
||||
@ -751,22 +1004,50 @@ string DecSubCMOS(bool s, bool c)
|
||||
}
|
||||
|
||||
|
||||
string IncReg(string reg, bool s, bool c)
|
||||
string Inc(string val)
|
||||
{
|
||||
return AddrImplied(s, c) ~
|
||||
Attr(reg) ~ "++;\n" ~
|
||||
SetNZ(Attr(reg));
|
||||
return val ~ "++;\n" ~
|
||||
SetNZ(val);
|
||||
}
|
||||
|
||||
|
||||
string DecReg(string reg, bool s, bool c)
|
||||
string Dec(string val)
|
||||
{
|
||||
return AddrImplied(s, c) ~
|
||||
Attr(reg) ~ "--;\n" ~
|
||||
SetNZ(Attr(reg));
|
||||
return val ~ "--;\n" ~
|
||||
SetNZ(val);
|
||||
}
|
||||
|
||||
|
||||
string ShiftLeft(string val)
|
||||
{
|
||||
return Attr("C") ~ " = (" ~ val ~ " > 0x7F);\n" ~
|
||||
SetNZ(val ~ " = cast(ubyte)(" ~ val ~ " << 1)");
|
||||
}
|
||||
|
||||
string RotateLeft(string val)
|
||||
{
|
||||
string C = Attr("C");
|
||||
|
||||
return "auto oldC = " ~ C ~ ";\n" ~
|
||||
C ~ " = (" ~ val ~ " > 0x7f);\n" ~
|
||||
SetNZ(val ~ " = cast(ubyte)(" ~ val ~ " << 1 | (oldC ? 1 : 0))");
|
||||
}
|
||||
|
||||
string ShiftRight(string val)
|
||||
{
|
||||
return Attr("C") ~ " = ((" ~ val ~ " & 0x01) != 0);\n" ~
|
||||
SetNZ(val ~ " = " ~ val ~ " >> 1");
|
||||
}
|
||||
|
||||
string RotateRight(string val)
|
||||
{
|
||||
string C = Attr("C");
|
||||
|
||||
return "auto oldC = " ~ C ~ ";\n" ~
|
||||
C ~ " = ((" ~ val ~ " & 0x01) != 0);\n" ~
|
||||
SetNZ(val ~ " = (" ~ val ~ " >> 1 | (oldC ? 0x80 : 0))");
|
||||
}
|
||||
|
||||
string RMW(int op, string action, string chip, bool s, bool c)
|
||||
{
|
||||
bool nmos = (chip == "6502");
|
||||
@ -776,7 +1057,6 @@ string RMW(int op, string action, string chip, bool s, bool c)
|
||||
If!(nmos)(Poke("address", "data", s, c),
|
||||
Peek("address", s, c)) ~
|
||||
action ~
|
||||
SetNZ("data") ~
|
||||
Write("address", "data", c);
|
||||
}
|
||||
|
||||
@ -789,35 +1069,35 @@ string Address(int op, string chip, bool s, bool c)
|
||||
final switch (opMode(op, chip))
|
||||
{
|
||||
case IMP:
|
||||
return AddrImplied(s, c);
|
||||
return AddrIMP(s, c);
|
||||
case IMM:
|
||||
return AddrImmediate(s, c);
|
||||
return AddrIMM(s, c);
|
||||
case ZP:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return AddrZP(s, c);
|
||||
case ZPX:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return AddrZPXY("X", chip, s, c);
|
||||
case ZPY:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return AddrZPXY("Y", chip, s, c);
|
||||
case IZX:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return AddrIZX(chip, s, c);
|
||||
case IZY:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return AddrIZY(op, chip, s, c);
|
||||
case ABS:
|
||||
return ReadWordOpLocal("ushort", "address", c);
|
||||
return AddrABS(s, c);
|
||||
case ABX:
|
||||
return AddrAbsoluteIdx(op, "X", chip, s, c);
|
||||
return AddrABXY(op, "X", chip, s, c);
|
||||
case ABY:
|
||||
return AddrAbsoluteIdx(op, "Y", chip, s, c);
|
||||
return AddrABXY(op, "Y", chip, s, c);
|
||||
case IND:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
case REL:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
case ZPI:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return AddrZPI(s, c);
|
||||
case ABI:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
case NP1:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
return "";
|
||||
case NP8:
|
||||
return Local("ushort", "address") ~ " = 0;";
|
||||
case KIL:
|
||||
@ -845,44 +1125,12 @@ string Poke(string addr, string val, bool strict, bool cumulative)
|
||||
Attr("memory") ~ ".write(" ~ addr ~ ", " ~ val ~ ");\n");
|
||||
}
|
||||
|
||||
string ReadInto(string var, string addr, bool c, string action = "=")
|
||||
{
|
||||
return PreAccess(c) ~
|
||||
var ~ " " ~ action ~ " " ~ ReadRaw("(" ~ addr ~ ")") ~ ";\n";
|
||||
}
|
||||
|
||||
string ReadRaw(string addr)
|
||||
{
|
||||
return Attr("memory") ~ ".read(" ~ addr ~")";
|
||||
}
|
||||
|
||||
string Write(string addr, string val, bool cumulative)
|
||||
{
|
||||
return PreAccess(cumulative) ~
|
||||
Attr("memory") ~ ".write(" ~ addr ~ ", " ~ val ~ ");\n";
|
||||
}
|
||||
|
||||
string ReadWord(string var, string addr, bool c)
|
||||
{
|
||||
return PreAccess(c) ~
|
||||
var ~ " = " ~ ReadRaw(addr) ~ ";\n" ~
|
||||
PreAccess(c) ~
|
||||
var ~ " |= (" ~ ReadRaw("cast(ushort)((" ~ addr ~ ") + 1)") ~
|
||||
" << 8);\n";
|
||||
}
|
||||
|
||||
string ReadWordOpLocal(string type, string var, bool c)
|
||||
{
|
||||
string PC = Attr("PC");
|
||||
|
||||
return PreAccess(c) ~
|
||||
Local(type, var) ~ " = " ~ ReadRaw(PC ~ "++") ~ ";\n" ~
|
||||
PreAccess(c) ~
|
||||
var ~ " |= (" ~ ReadRaw(PC ~ "++") ~
|
||||
" << 8);\n";
|
||||
}
|
||||
|
||||
|
||||
string IncPC()
|
||||
{
|
||||
return "++" ~ Attr("PC") ~ ";\n";
|
||||
@ -973,17 +1221,6 @@ string Attr(string var)
|
||||
}
|
||||
|
||||
|
||||
string Local(string type, string var)
|
||||
{
|
||||
version(OpSwitch)
|
||||
return var;
|
||||
else version(OpNestedSwitch)
|
||||
return var;
|
||||
else
|
||||
return type ~ " " ~ var;
|
||||
}
|
||||
|
||||
|
||||
string HiByte(string var)
|
||||
{
|
||||
return var ~ " >> 8";
|
||||
@ -1103,6 +1340,9 @@ immutable OP_NAMES_65C02 = [
|
||||
|
||||
// Addressing modes.
|
||||
|
||||
enum { IMP, IMM, ZP, ZPX, ZPY, IZX, IZY, ABS, ABX, ABY, IND, REL,
|
||||
ZPI, ABI, NP1, NP8, KIL }
|
||||
|
||||
immutable ADDR_MODES_6502 = [
|
||||
IMP, IZX, KIL, IZX, ZP, ZP, ZP, ZP,
|
||||
IMP, IMM, IMP, IMM, ABS, ABS, ABS, ABS,
|
||||
@ -1252,6 +1492,10 @@ string Fmt(string f, string[] p ...)
|
||||
}
|
||||
|
||||
|
||||
version(OpFunctions) mixin(OpBodies("6502", vStrict, vCumulative));
|
||||
version(OpFunctions) mixin(OpBodies("65C02", vStrict, vCumulative));
|
||||
|
||||
|
||||
//alias Cpu!("6502", false, false) T1;
|
||||
//alias Cpu!("6502", false, true) T2;
|
||||
//alias Cpu!("6502", true, false) T3;
|
||||
@ -1265,6 +1509,6 @@ string Fmt(string f, string[] p ...)
|
||||
void main()
|
||||
{
|
||||
import std.stdio;
|
||||
writeln(OpBody(0x9d, "6502", true, false));
|
||||
writeln(OpBody(0x11, "6502", true, false));
|
||||
}
|
||||
+/
|
||||
|
@ -46,5 +46,12 @@ void main()
|
||||
0x4c, 0x09, 0x29, 0x49, 0x69, 0xe9, 0xc9, 0xe0, 0xc0, 0xa9,
|
||||
0xa2, 0xa0, 0x1d, 0x19, 0x3d, 0x39, 0x5d, 0x59, 0x7d, 0x79,
|
||||
0xfd, 0xf9, 0xdd, 0xd9, 0xde, 0xfe, 0xbd, 0xb9, 0x9d, 0x99,
|
||||
0xbe, 0xbc]);
|
||||
0xbe, 0xbc, 0x6c, 0x7c, 0xb2, 0x72, 0x32, 0xd2, 0x52, 0x12,
|
||||
0xf2, 0x92, 0xaa, 0x8a, 0xa8, 0x98, 0xba, 0x9a, 0x0a, 0x0e,
|
||||
0x1e, 0x48, 0x2c, 0x05, 0x25, 0x45, 0x65, 0xe5, 0xc5, 0xe4,
|
||||
0xc4, 0xc6, 0xe6, 0x06, 0x26, 0x46, 0x66, 0xa5, 0x85, 0xa6,
|
||||
0x86, 0xa4, 0x84, 0x24, 0x15, 0x35, 0x55, 0x75, 0xf5, 0xd5,
|
||||
0xd6, 0xf6, 0x16, 0x36, 0x56, 0x76, 0xb5, 0x95, 0xb6, 0x96,
|
||||
0xb4, 0x94, 0x01, 0x21, 0x41, 0x61, 0xe1, 0xc1, 0xa1, 0x81,
|
||||
0x11, 0x31, 0x51, 0x71, 0xf1, 0xd1, 0xb1, 0x91]);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user