Add all documented 6502 opcodes.

This commit is contained in:
edmccard 2012-04-09 23:32:24 -04:00
parent c5fb366184
commit 0e330f8285
2 changed files with 405 additions and 154 deletions

View File

@ -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; module cpu6502;
@ -78,12 +101,6 @@ static if (!__traits(compiles, { bool b = opArray; })) enum opArray = 0;
static assert (versionCheck); 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) final class Cpu(string chip, bool strict, bool cumulative)
{ {
static assert(chip == "6502" || chip == "65C02" || chip == "65c02"); 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; ubyte A, X, Y, S;
ushort PC; ushort PC;
// The status flags.
ubyte N, Z; ubyte N, Z;
bool V, D, I, C; bool V, D, I, C;
static if (opArray) static if (opArray) { mixin(OpArrayDef()); }
{
mixin(OpArrayDef());
}
// TODO: other methods for stopping cpu // TODO: other methods for stopping cpu
bool keepRunning; bool keepRunning;
@ -192,10 +207,6 @@ enum ushort IRQ_VECTOR = 0xFFFE;
private: private:
version(OpFunctions) mixin(OpBodies("6502", vStrict, vCumulative));
version(OpFunctions) mixin(OpBodies("65C02", vStrict, vCumulative));
string OpArrayDef() string OpArrayDef()
{ {
version(OpDelegates) version(OpDelegates)
@ -243,6 +254,18 @@ string OpBodies(string chip, bool strict, bool cumulative)
If!(cumulative)("int cycles = 1;\n") ~ If!(cumulative)("int cycles = 1;\n") ~
OpBody(op, chip, strict, cumulative) ~ "}\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; return ret;
} }
} }
@ -308,7 +331,8 @@ string OpBody(int op, string chip, bool s, bool c)
return Jump(op, chip, s, c) ~ return Jump(op, chip, s, c) ~
Done(c); Done(c);
case "KIL": case "KIL":
return ""; return Attr("PC") ~ "--;\n" ~
Done(c);
case "BPL": case "BPL":
return Branch("!(" ~ Attr("N") ~ " & 0x80)", nmos, s, c) ~ return Branch("!(" ~ Attr("N") ~ " & 0x80)", nmos, s, c) ~
Done(c); Done(c);
@ -337,82 +361,96 @@ string OpBody(int op, string chip, bool s, bool c)
return Branch("!" ~ Attr("Z"), nmos, s, c) ~ return Branch("!" ~ Attr("Z"), nmos, s, c) ~
Done(c); Done(c);
case "CLC": case "CLC":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
ClearFlag("C") ~ ClearFlag("C") ~
Done(c); Done(c);
case "SEC": case "SEC":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
SetFlag("C") ~ SetFlag("C") ~
Done(c); Done(c);
case "CLI": case "CLI":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
ClearFlag("I") ~ ClearFlag("I") ~
Done(c); Done(c);
case "SEI": case "SEI":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
SetFlag("I") ~ SetFlag("I") ~
Done(c); Done(c);
case "CLV": case "CLV":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
ClearFlag("V") ~ ClearFlag("V") ~
Done(c); Done(c);
case "CLD": case "CLD":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
ClearFlag("D") ~ ClearFlag("D") ~
Done(c); Done(c);
case "SED": case "SED":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
SetFlag("D") ~ SetFlag("D") ~
Done(c); Done(c);
case "NOP": case "NOP":
return ""; // address modes return Nop(op, chip, s, c) ~
Done(c);
case "TAX": case "TAX":
return ""; return Transfer(op, "A", "X", s, c) ~
Done(c);
case "TXA": case "TXA":
return ""; return Transfer(op, "X", "A", s, c) ~
Done(c);
case "TAY": case "TAY":
return ""; return Transfer(op, "A", "Y", s, c) ~
Done(c);
case "TYA": case "TYA":
return ""; return Transfer(op, "Y", "A", s, c) ~
Done(c);
case "TSX": case "TSX":
return ""; return Transfer(op, "S", "X", s, c) ~
Done(c);
case "TXS": case "TXS":
return ""; return Transfer(op, "X", "S", s, c) ~
Done(c);
case "DEX": case "DEX":
return DecReg("X", s, c) ~ return AddrIMP(s, c) ~
Dec(Attr("X")) ~
Done(c); Done(c);
case "DEY": case "DEY":
return DecReg("Y", s, c) ~ return AddrIMP(s, c) ~
Dec(Attr("Y")) ~
Done(c); Done(c);
case "INX": case "INX":
return IncReg("X", s, c) ~ return AddrIMP(s, c) ~
Inc(Attr("X")) ~
Done(c); Done(c);
case "INY": case "INY":
return IncReg("Y", s, c) ~ return AddrIMP(s, c) ~
Inc(Attr("Y")) ~
Done(c); Done(c);
case "PHP": case "PHP":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
Push(Attr("statusToByte()"), s, c) ~ Push(Attr("statusToByte()"), s, c) ~
Done(c); Done(c);
case "PLP": case "PLP":
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
PullStatus(s, c) ~ PullStatus(s, c) ~
Done(c); Done(c);
case "PLA": case "PLA":
return AddrImplied(s, c) ~ return PullReg("A", s, c) ~
PullInto(Attr("A"), s, c) ~
SetNZ(Attr("A")) ~
Done(c); Done(c);
case "PLX": case "PLX":
return ""; return PullReg("X", s, c) ~
Done(c);
case "PLY": case "PLY":
return ""; return PullReg("Y", s, c) ~
Done(c);
case "PHA": case "PHA":
return ""; return PushReg("A", s, c) ~
Done(c);
case "PHX": case "PHX":
return ""; return PushReg("X", s, c) ~
Done(c);
case "PHY": case "PHY":
return ""; return PushReg("Y", s, c) ~
Done(c);
case "LDA": case "LDA":
return Load(op, "A", chip, s, c) ~ return Load(op, "A", chip, s, c) ~
Done(c); Done(c);
@ -434,7 +472,8 @@ string OpBody(int op, string chip, bool s, bool c)
case "STZ": case "STZ":
return ""; return "";
case "BIT": case "BIT":
return ""; // address modes return Bit(op, chip, s, c) ~
Done(c);
case "CMP": case "CMP":
return Compare(op, "A", chip, s, c) ~ return Compare(op, "A", chip, s, c) ~
Done(c); Done(c);
@ -460,23 +499,35 @@ string OpBody(int op, string chip, bool s, bool c)
return Sub(op, chip, s, c) ~ return Sub(op, chip, s, c) ~
Done(c); Done(c);
case "ASL": 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": 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": 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": 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": case "INC":
if (op == 0x1a) if (op == 0x1a)
return IncReg("A", s, c) ~ Done(c); return AddrIMP(s, c) ~ Inc(Attr("A")) ~ Done(c);
else else
return RMW(op, "data++;\n", chip, s, c) ~ Done(c); return RMW(op, Inc("data"), chip, s, c) ~ Done(c);
case "DEC": case "DEC":
if (op == 0x3a) if (op == 0x3a)
return DecReg("A", s, c) ~ Done(c); return AddrIMP(s, c) ~ Dec(Attr("A")) ~ Done(c);
else else
return RMW(op, "data--;\n", chip, s, c) ~ Done(c); return RMW(op, Dec("data"), chip, s, c) ~ Done(c);
case "TRB": case "TRB":
return ""; return "";
case "TSB": 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); 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"); bool nmos = (chip == "6502");
int exCyc = opExCyc(op, chip); int exCyc = opExCyc(op, chip);
string IDX = Attr(reg); string IDX = Attr(reg);
return ReadWordOpLocal("ushort", "base", c) ~ return ReadWordOp("ushort", "base", c) ~
Local("ushort","address")~" = cast(ushort)(base + " ~ IDX ~ ");\n" ~ Local("ushort") ~ "address = cast(ushort)(base + " ~ IDX ~ ");\n" ~
"ushort guess = (base & 0xFF00) | cast(ubyte)address;\n" ~ CheckShortcut("address", Attr("PC"), exCyc, nmos, s, c);
"if (guess != address)\n{\n" ~ }
If!(nmos)(Peek("guess", s, c), Peek(Attr("PC"), 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" ~ "}\n" ~
If!(exCyc)("else\n{\n" ~ Peek("address", 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"); auto mode = opMode(op, chip);
return ReadInto(Local("ubyte", "op1"), PC, c) ~ if (mode == IMP || mode == NP1 || mode == NP8)
IncPC() ~ return Address(op, chip, s, c);
"if (" ~ check ~ ")\n{\n" ~ else
Peek(PC, s, c) ~ return Address(op, chip, s, c) ~
Local("ushort", "base") ~ " = " ~ PC ~ ";\n" ~ Peek("address", true, c);
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";
} }
string Break(bool s, bool c) string Break(bool s, bool c)
{ {
return AddrImplied(s, c) ~ return AddrIMP(s, c) ~
IncPC() ~ IncPC() ~
PushPC(s, c) ~ PushPC(s, c) ~
Push(Attr("statusToByte()"), s, c) ~ Push(Attr("statusToByte()"), s, c) ~
@ -577,11 +692,9 @@ string Break(bool s, bool c)
string RetSub(bool s, bool c) string RetSub(bool s, bool c)
{ {
string PC = Attr("PC"); return AddrIMP(s, c) ~
return AddrImplied(s, c) ~
PullPC(s, c) ~ PullPC(s, c) ~
Peek(PC, s, c) ~ Peek(Attr("PC"), s, c) ~
IncPC(); IncPC();
} }
@ -590,22 +703,149 @@ string JumpSub(bool s, bool c)
{ {
string PC = Attr("PC"); string PC = Attr("PC");
return ReadInto(Local("ushort", "address"), PC ~ "++", c) ~ return ReadOp(Local("ushort", "address"), c) ~
Peek("0x0100 + " ~ Attr("S"), s, c) ~ Peek("0x0100 + " ~ Attr("S"), s, c) ~
PushPC(s, c) ~ PushPC(s, c) ~
PreAccess(c) ~ PreAccess(c) ~ "address |= (" ~ ReadRaw(PC ~ "++") ~ " << 8);\n" ~
"address |= (" ~ ReadRaw(PC ~ "++") ~ " << 8);\n" ~
PC ~ " = address;\n"; PC ~ " = address;\n";
} }
string Jump(int op, string chip, bool s, bool c) string Jump(int op, string chip, bool s, bool c)
{ {
bool nmos = (chip == "6502");
string PC = Attr("PC");
if (op == 0x4c) if (op == 0x4c)
return Address(op, chip, s, c) ~ return Address(op, chip, s, c) ~
Attr("PC") ~ " = address;\n"; PC ~ " = address;\n";
else 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 ""; 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) string Logic(int op, string action, string chip, bool s, bool c)
{ {
return Address(op, chip, s, c) ~ return Address(op, chip, s, c) ~
ReadInto(Attr("A"), "address", c, action) ~ ReadInto(Attr("A"), action, "address", c) ~
SetNZ(Attr("A")); SetNZ(Attr("A"));
} }
@ -646,9 +899,9 @@ string Add(int op, string chip, bool s, bool c)
return Address(op, chip, s, c) ~ return Address(op, chip, s, c) ~
ReadInto(Local("ubyte", "data"), "address", c) ~ ReadInto(Local("ubyte", "data"), "address", c) ~
"if (" ~ Attr("D") ~ ")\n{\n" ~ "if (" ~ Attr("D") ~ ")\n{\n" ~
DecAdd(chip, s, c) ~ DecAdd(chip, s, c) ~
"}\nelse\n{\n" ~ "}\nelse\n{\n" ~
HexAdd(chip, s, c) ~ HexAdd(chip, s, c) ~
"}\n"; "}\n";
} }
@ -692,9 +945,9 @@ string Sub(int op, string chip, bool s, bool c)
return Address(op, chip, s, c) ~ return Address(op, chip, s, c) ~
ReadInto(Local("ubyte", "data"), "address", c) ~ ReadInto(Local("ubyte", "data"), "address", c) ~
"if (" ~ Attr("D") ~ ")\n{\n" ~ "if (" ~ Attr("D") ~ ")\n{\n" ~
DecSub(chip, s, c) ~ DecSub(chip, s, c) ~
"}\nelse\n{\n" ~ "}\nelse\n{\n" ~
HexSub(chip, s, c) ~ HexSub(chip, s, c) ~
"}\n"; "}\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) ~ return val ~ "++;\n" ~
Attr(reg) ~ "++;\n" ~ SetNZ(val);
SetNZ(Attr(reg));
} }
string DecReg(string reg, bool s, bool c) string Dec(string val)
{ {
return AddrImplied(s, c) ~ return val ~ "--;\n" ~
Attr(reg) ~ "--;\n" ~ SetNZ(val);
SetNZ(Attr(reg));
} }
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) string RMW(int op, string action, string chip, bool s, bool c)
{ {
bool nmos = (chip == "6502"); 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), If!(nmos)(Poke("address", "data", s, c),
Peek("address", s, c)) ~ Peek("address", s, c)) ~
action ~ action ~
SetNZ("data") ~
Write("address", "data", c); Write("address", "data", c);
} }
@ -789,35 +1069,35 @@ string Address(int op, string chip, bool s, bool c)
final switch (opMode(op, chip)) final switch (opMode(op, chip))
{ {
case IMP: case IMP:
return AddrImplied(s, c); return AddrIMP(s, c);
case IMM: case IMM:
return AddrImmediate(s, c); return AddrIMM(s, c);
case ZP: case ZP:
return Local("ushort", "address") ~ " = 0;"; return AddrZP(s, c);
case ZPX: case ZPX:
return Local("ushort", "address") ~ " = 0;"; return AddrZPXY("X", chip, s, c);
case ZPY: case ZPY:
return Local("ushort", "address") ~ " = 0;"; return AddrZPXY("Y", chip, s, c);
case IZX: case IZX:
return Local("ushort", "address") ~ " = 0;"; return AddrIZX(chip, s, c);
case IZY: case IZY:
return Local("ushort", "address") ~ " = 0;"; return AddrIZY(op, chip, s, c);
case ABS: case ABS:
return ReadWordOpLocal("ushort", "address", c); return AddrABS(s, c);
case ABX: case ABX:
return AddrAbsoluteIdx(op, "X", chip, s, c); return AddrABXY(op, "X", chip, s, c);
case ABY: case ABY:
return AddrAbsoluteIdx(op, "Y", chip, s, c); return AddrABXY(op, "Y", chip, s, c);
case IND: case IND:
return Local("ushort", "address") ~ " = 0;"; return Local("ushort", "address") ~ " = 0;";
case REL: case REL:
return Local("ushort", "address") ~ " = 0;"; return Local("ushort", "address") ~ " = 0;";
case ZPI: case ZPI:
return Local("ushort", "address") ~ " = 0;"; return AddrZPI(s, c);
case ABI: case ABI:
return Local("ushort", "address") ~ " = 0;"; return Local("ushort", "address") ~ " = 0;";
case NP1: case NP1:
return Local("ushort", "address") ~ " = 0;"; return "";
case NP8: case NP8:
return Local("ushort", "address") ~ " = 0;"; return Local("ushort", "address") ~ " = 0;";
case KIL: case KIL:
@ -845,44 +1125,12 @@ string Poke(string addr, string val, bool strict, bool cumulative)
Attr("memory") ~ ".write(" ~ addr ~ ", " ~ val ~ ");\n"); 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) string Write(string addr, string val, bool cumulative)
{ {
return PreAccess(cumulative) ~ return PreAccess(cumulative) ~
Attr("memory") ~ ".write(" ~ addr ~ ", " ~ val ~ ");\n"; 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() string IncPC()
{ {
return "++" ~ Attr("PC") ~ ";\n"; 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) string HiByte(string var)
{ {
return var ~ " >> 8"; return var ~ " >> 8";
@ -1103,6 +1340,9 @@ immutable OP_NAMES_65C02 = [
// Addressing modes. // Addressing modes.
enum { IMP, IMM, ZP, ZPX, ZPY, IZX, IZY, ABS, ABX, ABY, IND, REL,
ZPI, ABI, NP1, NP8, KIL }
immutable ADDR_MODES_6502 = [ immutable ADDR_MODES_6502 = [
IMP, IZX, KIL, IZX, ZP, ZP, ZP, ZP, IMP, IZX, KIL, IZX, ZP, ZP, ZP, ZP,
IMP, IMM, IMP, IMM, ABS, ABS, ABS, ABS, 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, false) T1;
//alias Cpu!("6502", false, true) T2; //alias Cpu!("6502", false, true) T2;
//alias Cpu!("6502", true, false) T3; //alias Cpu!("6502", true, false) T3;
@ -1265,6 +1509,6 @@ string Fmt(string f, string[] p ...)
void main() void main()
{ {
import std.stdio; import std.stdio;
writeln(OpBody(0x9d, "6502", true, false)); writeln(OpBody(0x11, "6502", true, false));
} }
+/ +/

View File

@ -46,5 +46,12 @@ void main()
0x4c, 0x09, 0x29, 0x49, 0x69, 0xe9, 0xc9, 0xe0, 0xc0, 0xa9, 0x4c, 0x09, 0x29, 0x49, 0x69, 0xe9, 0xc9, 0xe0, 0xc0, 0xa9,
0xa2, 0xa0, 0x1d, 0x19, 0x3d, 0x39, 0x5d, 0x59, 0x7d, 0x79, 0xa2, 0xa0, 0x1d, 0x19, 0x3d, 0x39, 0x5d, 0x59, 0x7d, 0x79,
0xfd, 0xf9, 0xdd, 0xd9, 0xde, 0xfe, 0xbd, 0xb9, 0x9d, 0x99, 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]);
} }