diff --git a/src/cpu/ctfe_d6502.d b/src/cpu/ctfe_d6502.d index df3e97e..ffb8f2a 100644 --- a/src/cpu/ctfe_d6502.d +++ b/src/cpu/ctfe_d6502.d @@ -160,6 +160,20 @@ string Switch16x16(string chip, bool strict, bool cumulative) } +enum _PC = Attr("PC"); +enum _A = Attr("A"); +enum _X = Attr("X"); +enum _Y = Attr("Y"); +enum _N = Attr("N"); +enum _V = Attr("V"); +enum _D = Attr("D"); +enum _I = Attr("I"); +enum _Z = Attr("Z"); +enum _C = Attr("C"); +enum _S = Attr("S"); +enum STACK = "0x0100 + " ~ _S; + + string OpBody(int op, string chip, bool s, bool c) { bool nmos = (chip == "6502"); @@ -169,7 +183,8 @@ string OpBody(int op, string chip, bool s, bool c) return Break(s, c) ~ Done(c); case "RTI": - return ""; + return RetInt(s, c) ~ + Done(c); case "JSR": return JumpSub(s, c) ~ Done(c); @@ -180,99 +195,99 @@ string OpBody(int op, string chip, bool s, bool c) return Jump(op, chip, s, c) ~ Done(c); case "KIL": - return Attr("PC") ~ "--;\n" ~ + return _PC ~ "--;\n" ~ Done(c); case "BPL": - return Branch("!(" ~ Attr("N") ~ " & 0x80)", nmos, s, c) ~ + return Branch("!(" ~ _N ~ " & 0x80)", nmos, s, c) ~ Done(c); case "BMI": - return Branch("(" ~ Attr("N") ~ " & 0x80)", nmos, s, c) ~ + return Branch("(" ~ _N ~ " & 0x80)", nmos, s, c) ~ Done(c); case "BVC": - return Branch("!" ~ Attr("V"), nmos, s, c) ~ + return Branch("!" ~ _V, nmos, s, c) ~ Done(c); case "BVS": - return Branch(Attr("V"), nmos, s, c) ~ + return Branch(_V, nmos, s, c) ~ Done(c); case "BRA": return Branch("true", nmos, s, c) ~ Done(c); case "BCC": - return Branch("!" ~ Attr("C"), nmos, s, c) ~ + return Branch("!" ~ _C, nmos, s, c) ~ Done(c); case "BCS": - return Branch(Attr("C"), nmos, s, c) ~ + return Branch(_C, nmos, s, c) ~ Done(c); case "BNE": - return Branch(Attr("Z"), nmos, s, c) ~ + return Branch(_Z, nmos, s, c) ~ Done(c); case "BEQ": - return Branch("!" ~ Attr("Z"), nmos, s, c) ~ + return Branch("!" ~ _Z, nmos, s, c) ~ Done(c); case "CLC": return AddrIMP(s, c) ~ - ClearFlag("C") ~ + ClearFlag(_C) ~ Done(c); case "SEC": return AddrIMP(s, c) ~ - SetFlag("C") ~ + SetFlag(_C) ~ Done(c); case "CLI": return AddrIMP(s, c) ~ - ClearFlag("I") ~ + ClearFlag(_I) ~ Done(c); case "SEI": return AddrIMP(s, c) ~ - SetFlag("I") ~ + SetFlag(_I) ~ Done(c); case "CLV": return AddrIMP(s, c) ~ - ClearFlag("V") ~ + ClearFlag(_V) ~ Done(c); case "CLD": return AddrIMP(s, c) ~ - ClearFlag("D") ~ + ClearFlag(_D) ~ Done(c); case "SED": return AddrIMP(s, c) ~ - SetFlag("D") ~ + SetFlag(_D) ~ Done(c); case "NOP": return Nop(op, chip, s, c) ~ Done(c); case "TAX": - return Transfer(op, "A", "X", s, c) ~ + return Transfer(op, _A, _X, s, c) ~ Done(c); case "TXA": - return Transfer(op, "X", "A", s, c) ~ + return Transfer(op, _X, _A, s, c) ~ Done(c); case "TAY": - return Transfer(op, "A", "Y", s, c) ~ + return Transfer(op, _A, _Y, s, c) ~ Done(c); case "TYA": - return Transfer(op, "Y", "A", s, c) ~ + return Transfer(op, _Y, _A, s, c) ~ Done(c); case "TSX": - return Transfer(op, "S", "X", s, c) ~ + return Transfer(op, _S, _X, s, c) ~ Done(c); case "TXS": - return Transfer(op, "X", "S", s, c) ~ + return Transfer(op, _X, _S, s, c) ~ Done(c); case "DEX": return AddrIMP(s, c) ~ - Dec(Attr("X")) ~ + Dec(_X) ~ Done(c); case "DEY": return AddrIMP(s, c) ~ - Dec(Attr("Y")) ~ + Dec(_Y) ~ Done(c); case "INX": return AddrIMP(s, c) ~ - Inc(Attr("X")) ~ + Inc(_X) ~ Done(c); case "INY": return AddrIMP(s, c) ~ - Inc(Attr("Y")) ~ + Inc(_Y) ~ Done(c); case "PHP": return AddrIMP(s, c) ~ @@ -283,54 +298,55 @@ string OpBody(int op, string chip, bool s, bool c) PullStatus(s, c) ~ Done(c); case "PLA": - return PullReg("A", s, c) ~ + return PullReg(_A, s, c) ~ Done(c); case "PLX": - return PullReg("X", s, c) ~ + return PullReg(_X, s, c) ~ Done(c); case "PLY": - return PullReg("Y", s, c) ~ + return PullReg(_Y, s, c) ~ Done(c); case "PHA": - return PushReg("A", s, c) ~ + return PushReg(_A, s, c) ~ Done(c); case "PHX": - return PushReg("X", s, c) ~ + return PushReg(_X, s, c) ~ Done(c); case "PHY": - return PushReg("Y", s, c) ~ + return PushReg(_Y, s, c) ~ Done(c); case "LDA": - return Load(op, "A", chip, s, c) ~ + return Load(op, _A, chip, s, c) ~ Done(c); case "LDX": - return Load(op, "X", chip, s, c) ~ + return Load(op, _X, chip, s, c) ~ Done(c); case "LDY": - return Load(op, "Y", chip, s, c) ~ + return Load(op, _Y, chip, s, c) ~ Done(c); case "STA": - return Store(op, "A", chip, s, c) ~ + return Store(op, _A, chip, s, c) ~ Done(c); case "STX": - return Store(op, "X", chip, s, c) ~ + return Store(op, _X, chip, s, c) ~ Done(c); case "STY": - return Store(op, "Y", chip, s, c) ~ + return Store(op, _Y, chip, s, c) ~ Done(c); case "STZ": - return ""; - case "BIT": - return Bit(op, chip, s, c) ~ + return Store(op, "0", chip, s, c) ~ Done(c); case "CMP": - return Compare(op, "A", chip, s, c) ~ + return Compare(op, _A, chip, s, c) ~ Done(c); case "CPX": - return Compare(op, "X", chip, s, c) ~ + return Compare(op, _X, chip, s, c) ~ Done(c); case "CPY": - return Compare(op, "Y", chip, s, c) ~ + return Compare(op, _Y, chip, s, c) ~ + Done(c); + case "BIT": + return Bit(op, chip, s, c) ~ Done(c); case "ORA": return Logic(op, "|=", chip, s, c) ~ @@ -347,40 +363,40 @@ string OpBody(int op, string chip, bool s, bool c) case "SBC": return Sub(op, chip, s, c) ~ Done(c); - case "ASL": - 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": - 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": - 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": - 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 AddrIMP(s, c) ~ Inc(Attr("A")) ~ Done(c); + return AddrIMP(s, c) ~ Inc(_A) ~ Done(c); else return RMW(op, Inc("data"), chip, s, c) ~ Done(c); case "DEC": if (op == 0x3a) - return AddrIMP(s, c) ~ Dec(Attr("A")) ~ Done(c); + return AddrIMP(s, c) ~ Dec(_A) ~ Done(c); else return RMW(op, Dec("data"), chip, s, c) ~ Done(c); + case "ASL": + if (op == 0x0a) + return AddrIMP(s, c) ~ ShiftLeft(_A) ~ Done(c); + else + return RMW(op, ShiftLeft("data"), chip, s, c) ~ Done(c); + case "ROL": + if (op == 0x2a) + return AddrIMP(s, c) ~ RotateLeft(_A) ~ Done(c); + else + return RMW(op, RotateLeft("data"), chip, s, c) ~ Done(c); + case "LSR": + if (op == 0x4a) + return AddrIMP(s, c) ~ ShiftRight(_A) ~ Done(c); + else + return RMW(op, ShiftRight("data"), chip, s, c) ~ Done(c); + case "ROR": + if (op == 0x6a) + return AddrIMP(s, c) ~ ShiftRight(_A) ~ Done(c); + else + return RMW(op, RotateRight("data"), chip, s, c) ~ Done(c); case "TRB": - return ""; + return RMW(op, TestReset(), chip, s, c) ~ Done(c); case "TSB": - return ""; + return RMW(op, TestSet(), chip, s, c) ~ Done(c); case "LAS": return ""; case "LAX": @@ -421,101 +437,80 @@ string OpBody(int op, string chip, bool s, bool c) } -string AddrIMM(bool s, bool c) +string Break(bool s, bool c) { - return Local("ushort") ~ "address = " ~ Attr("PC") ~ "++;\n"; + return AddrIMP(s, c) ~ + IncPC() ~ + PushPC(s, c) ~ + Push(Attr("statusToByte()"), s, c) ~ + SetFlag(_I) ~ + ReadWord(_PC, "IRQ_VECTOR", c); } -string AddrIMP(bool s, bool c) + +string JumpSub(bool s, bool c) { - return Peek(Attr("PC"), s, c); + return ReadOp(Local("ushort", "address"), c) ~ + Peek(STACK, s, c) ~ + PushPC(s, c) ~ + LoadHiByte("address", _PC ~ "++", c) ~ + _PC ~ " = address;\n"; } -string AddrZP(bool s, bool c) + +string RetSub(bool s, bool c) { - return ReadOp(Local("ushort", "address"), c); + return AddrIMP(s, c) ~ + Peek(STACK, s, c) ~ + PullPC(s, c) ~ + Peek(_PC, s, c) ~ + IncPC(); } -string AddrZPXY(string reg, string chip, bool s, bool c) + +string RetInt(bool s, bool c) +{ + return AddrIMP(s, c) ~ + PullStatus(s, c) ~ + PullPC(s, c); +} + + +string Jump(int op, 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"; + if (op == 0x4c) + return Address(op, chip, s, c) ~ + _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 + " ~ _X ~ ")", c); + return ""; } -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 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) ~ + Peek(_PC, s, c) ~ + Local("ushort", "base") ~ " = " ~ _PC ~ ";\n" ~ + _PC ~ " = cast(ushort)(" ~ _PC ~ " + cast(byte)op1);\n" ~ + CheckShortcut(_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 Nop(int op, string chip, bool s, bool c) { @@ -528,63 +523,400 @@ string Nop(int op, string chip, bool s, bool c) } -string Break(bool s, bool c) +string Transfer(int op, string source, string dest, bool s, bool c) { return AddrIMP(s, c) ~ - IncPC() ~ - PushPC(s, c) ~ - Push(Attr("statusToByte()"), s, c) ~ - SetFlag("I") ~ - ReadWord(Attr("PC"), "IRQ_VECTOR", c); + dest ~ " = " ~ source ~ ";\n" ~ + ((op != 0x9a) ? SetNZ(dest) : ""); } -string RetSub(bool s, bool c) +string PullReg(string reg, bool s, bool c) { return AddrIMP(s, c) ~ - PullPC(s, c) ~ - Peek(Attr("PC"), s, c) ~ - IncPC(); + Peek(STACK, s, c) ~ + PullInto(reg, s, c) ~ + SetNZ(reg); } -string JumpSub(bool s, bool c) +string PushReg(string reg, bool s, bool c) { - string PC = Attr("PC"); - - return ReadOp(Local("ushort", "address"), c) ~ - Peek("0x0100 + " ~ Attr("S"), s, c) ~ - PushPC(s, c) ~ - PreAccess(c) ~ "address |= (" ~ ReadRaw(PC ~ "++") ~ " << 8);\n" ~ - PC ~ " = address;\n"; + return AddrIMP(s, c) ~ + Push(reg, s, c); } -string Jump(int op, string chip, bool s, bool c) +string Load(int op, string reg, string chip, bool s, bool c) +{ + return Address(op, chip, s, c) ~ + ReadInto(reg, "address", c) ~ + SetNZ(reg); +} + + +string Store(int op, string reg, string chip, bool s, bool c) +{ + return Address(op, chip, s, c) ~ + Write("address", reg, c); +} + + +string Compare(int op, string reg, string chip, bool s, bool c) +{ + return Address(op, chip, s, c) ~ + ReadInto(Local("ubyte", "data"), "address", c) ~ + UpdateFlag(_C, reg ~ " >= data") ~ + SetNZ("cast(ubyte)(" ~ reg ~ " - data)"); +} + + +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)( + _N ~ " = data;\n" ~ + _V ~ " = ((data & 0x40) != 0);\n") ~ + _Z ~ " = (" ~ _A ~ " & data);\n"; +} + + +string Logic(int op, string action, string chip, bool s, bool c) +{ + return Address(op, chip, s, c) ~ + ReadInto(_A, action, "address", c) ~ + SetNZ(_A); +} + + +string Add(int op, string chip, bool s, bool c) +{ + return Address(op, chip, s, c) ~ + ReadInto(Local("ubyte", "data"), "address", c) ~ + "if (" ~ _D ~ ")\n{\n" ~ + DecAdd(chip, s, c) ~ + "}\nelse\n{\n" ~ + HexAdd(chip, s, c) ~ + "}\n"; +} + +string HexAdd(string chip, bool s, bool c) +{ + return "uint sum = " ~ _A ~ " + data + " ~ _C ~ ";\n" ~ + _V ~ + " = (!((" ~ _A ~ " ^ data) & 0x80)) && ((data ^ sum) & 0x80);\n" ~ + _C ~ " = (sum > 0xFF);\n" ~ + SetNZ(_A ~ " = cast(ubyte)sum"); +} + +string DecAdd(string chip, bool s, bool c) +{ + bool cmos = (chip != "6502"); + + return "int a = " ~ _A ~ ";\n" ~ + "int al = (a & 0x0F) + (data & 0x0F) + " ~ _C ~ ";\n" ~ + "if (al >= 0x0A)\n" ~ + "al = ((al + 0x06) & 0x0F) + 0x10;\n" ~ + "a = (a & 0xF0) + (data & 0xF0) + al;\n" ~ + If!(cmos)("", + _N ~ " = cast(ubyte)a;\n" ~ + _Z ~ " = cast(ubyte)(" ~ _A ~ " + data + " ~ _C ~ ");\n") ~ + _V ~ + " = (!((" ~ _A ~ " ^ data) & 0x80)) && ((data ^ a) & 0x80);\n" ~ + "if (a >= 0xA0)\n" ~ + "a = a + 0x60;\n" ~ + _C ~ " = (a >= 0x100);\n" ~ + If!(cmos)( + SetNZ(_A ~ " = cast(ubyte)a") ~ Peek(_PC, s, c), + _A ~ " = cast(ubyte)a;\n"); +} + + +string Sub(int op, string chip, bool s, bool c) +{ + return Address(op, chip, s, c) ~ + ReadInto(Local("ubyte", "data"), "address", c) ~ + "if (" ~ _D ~ ")\n{\n" ~ + DecSub(chip, s, c) ~ + "}\nelse\n{\n" ~ + HexSub(chip, s, c) ~ + "}\n"; +} + +string HexSub(string chip, bool s, bool c) +{ + return "uint diff = " ~ _A ~ " - data - !" ~ _C ~ ";\n" ~ + _V ~ + " = ((" ~ _A ~ " ^ diff) & 0x80) && ((" ~ + _A ~ " ^ data) & 0x80);\n" ~ + _C ~ " = (diff < 0x100);\n" ~ + SetNZ(_A ~ " = cast(ubyte)diff"); +} + +string DecSub(string chip, bool s, bool c) +{ + return (chip == "6502" ? DecSubNMOS(s, c) : DecSubCMOS(s, c)); +} + +string DecSubNMOS(bool s, bool c) +{ + return "int a = " ~ _A ~ ";\n" ~ + "int al = (a & 0x0F) - (data & 0x0F) - !" ~ _C ~ ";\n" ~ + "if (al < 0)\n" ~ + "al = ((al - 0x06) & 0x0F) - 0x10;\n" ~ + "a = (a & 0xF0) - (data & 0xF0) + al;\n" ~ + "if (a < 0)\n" ~ + "a = a - 0x60;\n" ~ + "uint diff = " ~ _A ~ " - data - !" ~ _C ~ ";\n" ~ + _V ~ + " = ((" ~ _A ~ " ^ diff) & 0x80) && ((" ~ + _A ~ " ^ data) & 0x80);\n" ~ + _C ~ " = (diff < 0x100);\n" ~ + SetNZ("cast(ubyte)diff") ~ + _A ~ " = cast(ubyte)a;\n"; +} + +string DecSubCMOS(bool s, bool c) +{ + return "int a = " ~ _A ~ ";\n" ~ + "int al = (a & 0x0F) - (data & 0x0F) - !" ~ _C ~ ";\n" ~ + "a = a - data - !" ~ _C ~ ";\n" ~ + "if (a < 0) a = a - 0x60;\n" ~ + "if (al < 0) a = a - 0x06;\n" ~ + "uint diff = " ~ _A ~ " - data - !" ~ _C ~ ";\n" ~ + _V ~ + " = ((" ~ _A ~ " ^ diff) & 0x80) && ((" ~ + _A ~ " ^ data) & 0x80);\n" ~ + _C ~ " = (diff < 0x100);\n" ~ + Peek(_PC, s, c) ~ + SetNZ(_A ~ " = cast(ubyte)a"); +} + + +string Inc(string val) +{ + return val ~ "++;\n" ~ + SetNZ(val); +} + + +string Dec(string val) +{ + return val ~ "--;\n" ~ + SetNZ(val); +} + + +string ShiftLeft(string val) +{ + return _C ~ " = (" ~ val ~ " > 0x7F);\n" ~ + SetNZ(val ~ " = cast(ubyte)(" ~ val ~ " << 1)"); +} + + +string RotateLeft(string val) +{ + return "auto oldC = " ~ _C ~ ";\n" ~ + _C ~ " = (" ~ val ~ " > 0x7f);\n" ~ + SetNZ(val ~ " = cast(ubyte)(" ~ val ~ " << 1 | (oldC ? 1 : 0))"); +} + + +string ShiftRight(string val) +{ + return _C ~ " = ((" ~ val ~ " & 0x01) != 0);\n" ~ + SetNZ(val ~ " = " ~ val ~ " >> 1"); +} + + +string RotateRight(string val) +{ + return "auto oldC = " ~ _C ~ ";\n" ~ + _C ~ " = ((" ~ val ~ " & 0x01) != 0);\n" ~ + SetNZ(val ~ " = (" ~ val ~ " >> 1 | (oldC ? 0x80 : 0))"); +} + + +string TestReset() +{ + return _Z ~ " = data & " ~ _A ~ ";\n" ~ + "data &= (~" ~ _A ~ ");\n"; +} + + +string TestSet() +{ + return _Z ~ " = data & " ~ _A ~ ";\n" ~ + "data |= " ~ _A ~ ";\n"; +} + + +string RMW(int op, string action, string chip, bool s, bool c) { bool nmos = (chip == "6502"); - string PC = Attr("PC"); - if (op == 0x4c) - return Address(op, chip, s, c) ~ - 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 Address(op, chip, s, c) ~ + ReadInto(Local("ubyte", "data"), "address", c) ~ + If!(nmos)(Poke("address", "data", s, c), + Peek("address", s, c)) ~ + action ~ + Write("address", "data", 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 Address(int op, string chip, bool s, bool c) +{ + auto EXTRA_CYCLE = opExCyc(op, chip); + auto PC = Attr("PC"); + + final switch (opMode(op, chip)) + { + case IMP: + return AddrIMP(s, c); + case IMM: + return AddrIMM(s, c); + case ZP: + return AddrZP(s, c); + case ZPX: + return AddrZPXY(_X, chip, s, c); + case ZPY: + return AddrZPXY(_Y, chip, s, c); + case IZX: + return AddrIZX(chip, s, c); + case IZY: + return AddrIZY(op, chip, s, c); + case ABS: + return AddrABS(s, c); + case ABX: + return AddrABXY(op, _X, chip, s, c); + case ABY: + return AddrABXY(op, _Y, chip, s, c); + case IND: + return Local("ushort", "address") ~ " = 0;"; + case REL: + return Local("ushort", "address") ~ " = 0;"; + case ZPI: + return AddrZPI(s, c); + case ABI: + return Local("ushort", "address") ~ " = 0;"; + case NP1: + return ""; + case NP8: + return Local("ushort", "address") ~ " = 0;"; + case KIL: + return Local("ushort", "address") ~ " = 0;"; + } return ""; } +string AddrIMM(bool s, bool c) +{ + return Local("ushort") ~ "address = " ~ _PC ~ "++;\n"; +} + +string AddrIMP(bool s, bool c) +{ + return Peek(_PC, s, c); +} + +string AddrZP(bool s, bool c) +{ + return ReadOp(Local("ushort", "address"), 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(_PC, s, c)) ~ + Local("ushort") ~ + "address = cast(ubyte)(base + " ~ 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(_PC, s, c)) ~ + ReadWordZP("ushort", "address", "base + " ~ _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 + " ~ _Y ~ ");\n" ~ + CheckShortcut("address", _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); + + return ReadWordOp("ushort", "base", c) ~ + Local("ushort") ~ "address = cast(ushort)(base + " ~ reg ~ ");\n" ~ + CheckShortcut("address", _PC, exCyc, nmos, s, c); +} + +string AddrZPI(bool s, bool c) +{ + return ReadOp(Local("ushort", "base"), c) ~ + ReadWordZP("ushort", "address", "base", c); +} + +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 ReadInto(string var, string action, string addr, bool c) { return PreAccess(c) ~ @@ -598,7 +930,7 @@ string ReadInto(string var, string addr, bool c) string ReadOp(string var, bool c) { - return ReadInto(var, Attr("PC") ~ "++", c); + return ReadInto(var, _PC ~ "++", c); } string ReadRaw(string addr) @@ -609,10 +941,8 @@ string ReadRaw(string 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"; + return LoadLoByte(type, var, addr1, c) ~ + LoadHiByte(var, addr2, c); } string ReadWordBasic(string var, string addr1, string addr2, bool c) @@ -643,9 +973,7 @@ string ReadWordZP(string var, string addr, bool c) string ReadWordOp(string type, string var, bool c) { - string PC = Attr("PC"); - - return ReadWordBasic(type, var, PC ~ "++", PC ~ "++", c); + return ReadWordBasic(type, var, _PC ~ "++", _PC ~ "++", c); } string ReadWordOp(string var, bool c) @@ -653,309 +981,6 @@ 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); -} - - -string Load(int op, string reg, string chip, bool s, bool c) -{ - return Address(op, chip, s, c) ~ - ReadInto(Attr(reg), "address", c) ~ - SetNZ(Attr(reg)); -} - - -string Store(int op, string reg, string chip, bool s, bool c) -{ - return Address(op, chip, s, c) ~ - Write("address", Attr(reg), c); -} - - -string Compare(int op, string reg, string chip, bool s, bool c) -{ - return Address(op, chip, s, c) ~ - ReadInto(Local("ubyte", "data"), "address", c) ~ - UpdateFlag("C", Attr(reg) ~ " >= data") ~ - SetNZ("cast(ubyte)(" ~ Attr(reg) ~ " - data)"); -} - - -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"), action, "address", c) ~ - SetNZ(Attr("A")); -} - - -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) ~ - "}\nelse\n{\n" ~ - HexAdd(chip, s, c) ~ - "}\n"; -} - -string HexAdd(string chip, bool s, bool c) -{ - string A = Attr("A"), C = Attr("C"); - - return "uint sum = " ~ A ~ " + data + " ~ C ~ ";\n" ~ - Attr("V") ~ - " = (!((" ~ A ~ " ^ data) & 0x80)) && ((data ^ sum) & 0x80);\n" ~ - C ~ " = (sum > 0xFF);\n" ~ - SetNZ(A ~ " = cast(ubyte)sum"); -} - -string DecAdd(string chip, bool s, bool c) -{ - bool cmos = (chip != "6502"); - string A = Attr("A"), C = Attr("C"); - - return "int a = " ~ A ~ ";\n" ~ - "int al = (a & 0x0F) + (data & 0x0F) + " ~ C ~ ";\n" ~ - "if (al >= 0x0A)\n" ~ - "al = ((al + 0x06) & 0x0F) + 0x10;\n" ~ - "a = (a & 0xF0) + (data & 0xF0) + al;\n" ~ - If!(cmos)("", - Attr("N") ~ " = cast(ubyte)a;\n" ~ - Attr("Z") ~ " = cast(ubyte)(" ~ A ~ " + data + " ~ C ~ ");\n") ~ - Attr("V") ~ - " = (!((" ~ A ~ " ^ data) & 0x80)) && ((data ^ a) & 0x80);\n" ~ - "if (a >= 0xA0)\n" ~ - "a = a + 0x60;\n" ~ - C ~ " = (a >= 0x100);\n" ~ - If!(cmos)( - SetNZ(A ~ " = cast(ubyte)a") ~ Peek(Attr("PC"), s, c), - A ~ " = cast(ubyte)a;\n"); -} - - -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) ~ - "}\nelse\n{\n" ~ - HexSub(chip, s, c) ~ - "}\n"; -} - -string HexSub(string chip, bool s, bool c) -{ - string A = Attr("A"), C = Attr("C"); - - return "uint diff = " ~ A ~ " - data - !" ~ C ~ ";\n" ~ - Attr("V") ~ - " = ((" ~ A ~ " ^ diff) & 0x80) && ((" ~ A ~ " ^ data) & 0x80);\n" ~ - C ~ " = (diff < 0x100);\n" ~ - SetNZ(A ~ " = cast(ubyte)diff"); -} - -string DecSub(string chip, bool s, bool c) -{ - return (chip == "6502" ? DecSubNMOS(s, c) : DecSubCMOS(s, c)); -} - -string DecSubNMOS(bool s, bool c) -{ - string A = Attr("A"), C = Attr("C"); - - return "int a = " ~ A ~ ";\n" ~ - "int al = (a & 0x0F) - (data & 0x0F) - !" ~ C ~ ";\n" ~ - "if (al < 0)\n" ~ - "al = ((al - 0x06) & 0x0F) - 0x10;\n" ~ - "a = (a & 0xF0) - (data & 0xF0) + al;\n" ~ - "if (a < 0)\n" ~ - "a = a - 0x60;\n" ~ - "uint diff = " ~ A ~ " - data - !" ~ C ~ ";\n" ~ - Attr("V") ~ - " = ((" ~ A ~ " ^ diff) & 0x80) && ((" ~ A ~ " ^ data) & 0x80);\n" ~ - C ~ " = (diff < 0x100);\n" ~ - SetNZ("cast(ubyte)diff") ~ - A ~ " = cast(ubyte)a;\n"; -} - -string DecSubCMOS(bool s, bool c) -{ - string A = Attr("A"), C = Attr("C"); - - return "int a = " ~ A ~ ";\n" ~ - "int al = (a & 0x0F) - (data & 0x0F) - !" ~ C ~ ";\n" ~ - "a = a - data - !" ~ C ~ ";\n" ~ - "if (a < 0) a = a - 0x60;\n" ~ - "if (al < 0) a = a - 0x06;\n" ~ - "uint diff = " ~ A ~ " - data - !" ~ C ~ ";\n" ~ - Attr("V") ~ - " = ((" ~ A ~ " ^ diff) & 0x80) && ((" ~ A ~ " ^ data) & 0x80);\n" ~ - C ~ " = (diff < 0x100);\n" ~ - Peek(Attr("PC"), s, c) ~ - SetNZ(A ~ " = cast(ubyte)a"); -} - - -string Inc(string val) -{ - return val ~ "++;\n" ~ - SetNZ(val); -} - - -string Dec(string val) -{ - 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"); - - return Address(op, chip, s, c) ~ - ReadInto(Local("ubyte", "data"), "address", c) ~ - If!(nmos)(Poke("address", "data", s, c), - Peek("address", s, c)) ~ - action ~ - Write("address", "data", c); -} - - -string Address(int op, string chip, bool s, bool c) -{ - auto EXTRA_CYCLE = opExCyc(op, chip); - auto PC = Attr("PC"); - - final switch (opMode(op, chip)) - { - case IMP: - return AddrIMP(s, c); - case IMM: - return AddrIMM(s, c); - case ZP: - return AddrZP(s, c); - case ZPX: - return AddrZPXY("X", chip, s, c); - case ZPY: - return AddrZPXY("Y", chip, s, c); - case IZX: - return AddrIZX(chip, s, c); - case IZY: - return AddrIZY(op, chip, s, c); - case ABS: - return AddrABS(s, c); - case ABX: - return AddrABXY(op, "X", chip, s, c); - case ABY: - return AddrABXY(op, "Y", chip, s, c); - case IND: - return Local("ushort", "address") ~ " = 0;"; - case REL: - return Local("ushort", "address") ~ " = 0;"; - case ZPI: - return AddrZPI(s, c); - case ABI: - return Local("ushort", "address") ~ " = 0;"; - case NP1: - return ""; - case NP8: - return Local("ushort", "address") ~ " = 0;"; - case KIL: - return Local("ushort", "address") ~ " = 0;"; - } - return ""; -} - - string PreAccess(bool cumulative) { return If!(cumulative)("++cycles;\n", Attr("clock") ~ ".tick();\n"); @@ -982,77 +1007,85 @@ string Write(string addr, string val, bool cumulative) string IncPC() { - return "++" ~ Attr("PC") ~ ";\n"; + return "++" ~ _PC ~ ";\n"; } string IncSP() { - return "++" ~ Attr("S") ~ ";\n"; + return "++" ~ _S ~ ";\n"; } string DecSP() { - return "--" ~ Attr("S") ~ ";\n"; + return "--" ~ _S ~ ";\n"; } string PullStatus(bool s, bool c) { - return Peek("0x0100 + " ~ Attr("S"), s, c) ~ + return Peek(STACK, s, c) ~ IncSP() ~ PreAccess(c) ~ Attr("statusFromByte") ~ "(" ~ - ReadRaw("0x0100 + " ~ Attr("S")) ~ ");\n"; + ReadRaw(STACK) ~ ");\n"; } string PullInto(string var, bool s, bool c) { - return Peek("0x0100 + " ~ Attr("S"), s, c) ~ - IncSP() ~ - ReadInto(var, "0x0100 + " ~ Attr("S"), c); + return IncSP() ~ + ReadInto(var, STACK, c); } string Push(string val, bool s, bool c) { - return Write("0x0100 + " ~ Attr("S"), val, c) ~ + return Write(STACK, val, c) ~ DecSP(); } string PushPC(bool s, bool c) { - return Push(HiByte(Attr("PC")), s, c) ~ - Push(LoByte(Attr("PC")), s, c); + return Push(HiByte(_PC), s, c) ~ + Push(LoByte(_PC), s, c); } string PullPC(bool s, bool c) { - string PC = Attr("PC"); - - return PullInto(PC, s, c) ~ - PreAccess(c) ~ + return PullInto(_PC, s, c) ~ IncSP() ~ - PC ~ " |= (" ~ ReadRaw("0x0100 + " ~ Attr("S")) ~ " << 8);\n"; + LoadHiByte(_PC, STACK, c); +} + +string LoadLoByte(string type, string var, string addr, bool c) +{ + return PreAccess(c) ~ + Local(type, var) ~ " = " ~ ReadRaw(addr) ~ ";\n"; +} + +string LoadHiByte(string var, string addr, bool c) +{ + return PreAccess(c) ~ + var ~ " |= (" ~ ReadRaw(addr) ~ " << 8);\n"; } string SetFlag(string flag) { - return Attr(flag) ~ " = true;\n"; + return flag ~ " = true;\n"; } string ClearFlag(string flag) { - return Attr(flag) ~ " = false;\n"; + return flag ~ " = false;\n"; } string UpdateFlag(string flag, string val) { - return Attr(flag) ~ " = (" ~ val ~ ");\n"; + return flag ~ " = (" ~ val ~ ");\n"; } string SetNZ(string var) { - return Attr("N") ~ " = " ~ Attr("Z") ~ " = (" ~ var ~ ");\n"; + return _N ~ " = " ~ _Z ~ " = (" ~ var ~ ");\n"; } string Done(bool cumulative) diff --git a/test/test_new_cpu.d b/test/test_new_cpu.d index 4b82f44..5cf5c6e 100644 --- a/test/test_new_cpu.d +++ b/test/test_new_cpu.d @@ -53,5 +53,7 @@ void main() 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]); + 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]); }