mirror of
https://github.com/edmccard/twoapple-reboot.git
synced 2024-06-17 14:29:27 +00:00
Make test framework work with new cpu
This commit is contained in:
parent
e5f3f190a8
commit
d3a95c455d
141
test/cpu.d
141
test/cpu.d
|
@ -8,38 +8,37 @@ module test.cpu;
|
|||
|
||||
import std.conv, std.exception, std.random, std.string, std.traits;
|
||||
|
||||
public import d6502.nmosundoc : NmosUndoc;
|
||||
public import d6502.cmos : Cmos;
|
||||
public import cpu6502 : Cpu, is6502, is65C02;
|
||||
|
||||
|
||||
// True if T is the type of a cpu.
|
||||
template isCpu(T)
|
||||
{
|
||||
enum isCpu = __traits(hasMember, T, "_isCpuBase");
|
||||
enum isCpu = __traits(hasMember, T, "_isCpu");
|
||||
}
|
||||
|
||||
// True if the cpu type T represents a 6502.
|
||||
template isNMOS(T)
|
||||
{
|
||||
enum isNMOS = __traits(hasMember, T, "_isNMOS");
|
||||
enum isNMOS = is6502!T;
|
||||
}
|
||||
|
||||
// True if the cpu type T represents a 65C02.
|
||||
template isCMOS(T)
|
||||
{
|
||||
enum isCMOS = __traits(hasMember, T, "_isCMOS");
|
||||
enum isCMOS = is65C02!T;
|
||||
}
|
||||
|
||||
// True if the cpu type T accesses memory on every cycle.
|
||||
template isStrict(T)
|
||||
{
|
||||
enum isStrict = __traits(hasMember, T, "_isStrict");
|
||||
enum isStrict = isCpu!T && __traits(getMember, T, "_isStrict");
|
||||
}
|
||||
|
||||
// True if the cpu type T aggregates ticks.
|
||||
template isCumulative(T)
|
||||
{
|
||||
enum isCumulative = __traits(hasMember, T, "_isCumulative");
|
||||
enum isCumulative = isCpu!T && __traits(getMember, T, "_isCumulative");
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,11 +49,7 @@ template isCumulative(T)
|
|||
*/
|
||||
template CPU(string arch, bool strict, bool cumulative)
|
||||
{
|
||||
static if (arch == "65c02" || arch == "65C02")
|
||||
alias Cmos!(strict, cumulative) CPU;
|
||||
else static if (arch == "6502")
|
||||
alias NmosUndoc!(strict, cumulative) CPU;
|
||||
else static assert(0);
|
||||
alias Cpu!(arch, strict, cumulative) CPU;
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,12 +57,12 @@ auto makeCpu(T)(CpuInfo info)
|
|||
if (isCpu!T)
|
||||
{
|
||||
auto cpu = new T();
|
||||
cpu.programCounter = info.PC;
|
||||
cpu.stackPointer = info.SP;
|
||||
cpu.flag.fromByte(info.S);
|
||||
cpu.accumulator = info.A;
|
||||
cpu.xIndex = info.X;
|
||||
cpu.yIndex = info.Y;
|
||||
cpu.PC = info.PC;
|
||||
cpu.S = info.SP;
|
||||
cpu.statusFromByte(info.S);
|
||||
cpu.A = info.A;
|
||||
cpu.X = info.X;
|
||||
cpu.Y = info.Y;
|
||||
return cpu;
|
||||
}
|
||||
|
||||
|
@ -251,25 +246,20 @@ struct CpuInfo
|
|||
static CpuInfo fromCpu(T)(T cpu)
|
||||
{
|
||||
CpuInfo info;
|
||||
info.PC = cpu.programCounter;
|
||||
info.SP = cpu.stackPointer;
|
||||
info.A = cpu.accumulator;
|
||||
info.X = cpu.xIndex;
|
||||
info.Y = cpu.yIndex;
|
||||
info.S = cpu.flag.toByte();
|
||||
info.PC = cpu.PC;
|
||||
info.SP = cpu.S;
|
||||
info.A = cpu.A;
|
||||
info.X = cpu.X;
|
||||
info.Y = cpu.Y;
|
||||
info.S = cpu.statusToByte();
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sets the program counter.
|
||||
void setPC(T)(T cpu, int addr)
|
||||
if (isCpu!T)
|
||||
{
|
||||
cpu.programCounter = cast(ushort)addr;
|
||||
}
|
||||
|
||||
void setPC(T : CpuInfo)(ref T cpu, int addr)
|
||||
void setPC(T)(ref T cpu, int addr)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
cpu.PC = cast(ushort)addr;
|
||||
}
|
||||
|
@ -279,14 +269,10 @@ void incPC(T : CpuInfo)(ref T cpu, int amt = 1)
|
|||
cpu.PC = pageCrossAdd(cpu.PC, amt);
|
||||
}
|
||||
|
||||
// Returns the program counter.
|
||||
ushort getPC(T)(T cpu)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return cpu.programCounter;
|
||||
}
|
||||
|
||||
ushort getPC(T : CpuInfo)(ref T cpu)
|
||||
// Returns the program counter.
|
||||
ushort getPC(T)(ref T cpu)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
return cpu.PC;
|
||||
}
|
||||
|
@ -302,7 +288,7 @@ void setSP(T)(T cpu, int val)
|
|||
if (isCpu!T)
|
||||
{
|
||||
assert(val < 0x0200);
|
||||
cpu.stackPointer = cast(ubyte)val;
|
||||
cpu.S = cast(ubyte)val;
|
||||
}
|
||||
|
||||
void setSP(T : CpuInfo)(ref T cpu, int val)
|
||||
|
@ -329,7 +315,7 @@ void decSP(T : CpuInfo)(ref T cpu, int amt = -1)
|
|||
ushort getSP(T)(T cpu)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return 0x100 | cpu.stackPointer;
|
||||
return 0x100 | cpu.S;
|
||||
}
|
||||
|
||||
ushort getSP(T : CpuInfo)(ref T cpu)
|
||||
|
@ -369,75 +355,48 @@ if (isCpu!T || is(T == CpuInfo))
|
|||
}
|
||||
|
||||
// Sets the A register.
|
||||
void setA(T)(T cpu, int val)
|
||||
if (isCpu!T)
|
||||
{
|
||||
cpu.accumulator = cast(ubyte)val;
|
||||
}
|
||||
|
||||
void setA(T : CpuInfo)(ref T cpu, int val)
|
||||
void setA(T)(ref T cpu, int val)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
cpu.A = cast(ubyte)val;
|
||||
}
|
||||
|
||||
// Returns the A register.
|
||||
ubyte getA(T)(T cpu, int val)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return cpu.accumulator;
|
||||
}
|
||||
|
||||
ubyte getA(T : CpuInfo)(ref T cpu)
|
||||
// Returns the A register.
|
||||
ubyte getA(T)(ref T cpu)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
return cpu.A;
|
||||
}
|
||||
|
||||
|
||||
// Sets the X register.
|
||||
void setX(T)(T cpu, int val)
|
||||
if (isCpu!T)
|
||||
{
|
||||
cpu.xIndex = cast(ubyte)val;
|
||||
}
|
||||
|
||||
void setX(T : CpuInfo)(ref T cpu, int val)
|
||||
void setX(T)(ref T cpu, int val)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
cpu.X = cast(ubyte)val;
|
||||
}
|
||||
|
||||
// Returns the X register.
|
||||
ubyte getX(T)(T cpu)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return cpu.xIndex;
|
||||
}
|
||||
|
||||
ubyte getX(T : CpuInfo)(ref T cpu)
|
||||
// Returns the X register.
|
||||
ubyte getX(T)(ref T cpu)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
return cpu.X;
|
||||
}
|
||||
|
||||
|
||||
// Sets the Y register.
|
||||
void setY(T)(T cpu, int val)
|
||||
if (isCpu!T)
|
||||
{
|
||||
cpu.yIndex = cast(ubyte)val;
|
||||
}
|
||||
|
||||
void setY(T : CpuInfo)(ref T cpu, int val)
|
||||
void setY(T)(ref T cpu, int val)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
cpu.Y = cast(ubyte)val;
|
||||
}
|
||||
|
||||
// Returns the Y register.
|
||||
ubyte getY(T)(T cpu)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return cpu.yIndex;
|
||||
}
|
||||
|
||||
ubyte getY(T : CpuInfo)(ref T cpu)
|
||||
// Returns the Y register.
|
||||
ubyte getY(T)(ref T cpu)
|
||||
if (isCpu!T || is(T == CpuInfo))
|
||||
{
|
||||
return cpu.Y;
|
||||
}
|
||||
|
@ -472,9 +431,9 @@ string flagToString(Flag f)
|
|||
void setFlag(T)(T cpu, Flag[] flags...)
|
||||
if (isCpu!T)
|
||||
{
|
||||
auto reg = cpu.flag.toByte();
|
||||
auto reg = cpu.statusToByte();
|
||||
foreach (flag; flags) reg |= flag;
|
||||
cpu.flag.fromByte(reg);
|
||||
cpu.statusFromByte(reg);
|
||||
}
|
||||
|
||||
void setFlag(T : CpuInfo)(ref T cpu, Flag[] flags...)
|
||||
|
@ -486,9 +445,9 @@ void setFlag(T : CpuInfo)(ref T cpu, Flag[] flags...)
|
|||
void clearFlag(T)(T cpu, Flag[] flags...)
|
||||
if (isCpu!T)
|
||||
{
|
||||
auto reg = cpu.flag.toByte();
|
||||
auto reg = cpu.statusToByte();
|
||||
foreach (flag; flags) reg &= ~flag;
|
||||
cpu.flag.fromByte(reg);
|
||||
cpu.statusFromByte(reg);
|
||||
}
|
||||
|
||||
void clearFlag(T : CpuInfo)(ref T cpu, Flag[] flags...)
|
||||
|
@ -500,7 +459,8 @@ void clearFlag(T : CpuInfo)(ref T cpu, Flag[] flags...)
|
|||
bool getFlag(T)(T cpu, Flag f)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return (cpu.flag.toByte() & f) != 0;
|
||||
return (cpu.statusToByte() & f) != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getFlag(T : CpuInfo)(ref T cpu, Flag f)
|
||||
|
@ -513,7 +473,7 @@ bool getFlag(T : CpuInfo)(ref T cpu, Flag f)
|
|||
void setStatus(T)(T cpu, int val)
|
||||
if (isCpu!T)
|
||||
{
|
||||
cpu.flag.fromByte(cast(ubyte)val);
|
||||
cpu.statusFromByte(cast(ubyte)val);
|
||||
}
|
||||
|
||||
void setStatus(T : CpuInfo)(ref T cpu, int val)
|
||||
|
@ -525,7 +485,8 @@ void setStatus(T : CpuInfo)(ref T cpu, int val)
|
|||
ubyte getStatus(T)(T cpu)
|
||||
if (isCpu!T)
|
||||
{
|
||||
return cpu.flag.toByte();
|
||||
return cpu.statusToByte();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ubyte getStatus(T : CpuInfo)(ref T cpu)
|
||||
|
@ -604,8 +565,6 @@ if (isCpu!T || is(T == CpuInfo))
|
|||
case /*BNE*/ 0xD0: setFlag(cpu, Flag.Z); break;
|
||||
case /*BEQ*/ 0xF0: clearFlag(cpu, Flag.Z); break;
|
||||
default:
|
||||
if (isCMOS!T)
|
||||
enforce(opcode != 0x80, "BRA can never not branch");
|
||||
enforce(0, format("not a branching opcpde %0.2X", opcode));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user