Strict and cumulative modes are now set by version, instead of template parameters.
This commit is contained in:
parent
76cfb27a7b
commit
d12f793d9a
File diff suppressed because it is too large
Load Diff
|
@ -29,17 +29,6 @@ import std.array, std.format;
|
|||
import cpu.ctfe_d6502;
|
||||
|
||||
|
||||
enum Strict : bool
|
||||
{
|
||||
no, yes
|
||||
}
|
||||
|
||||
enum Cumulative : bool
|
||||
{
|
||||
no, yes
|
||||
}
|
||||
|
||||
|
||||
template is6502(T)
|
||||
{
|
||||
enum is6502 = __traits(getMember, T, "_chip") == "6502";
|
||||
|
@ -51,13 +40,11 @@ template is65C02(T)
|
|||
}
|
||||
|
||||
|
||||
final class Cpu(string chip, bool strict, bool cumulative)
|
||||
final class Cpu(string chip)
|
||||
{
|
||||
static assert(chip == "6502" || chip == "65C02" || chip == "65c02");
|
||||
enum _isCpu = true;
|
||||
enum _chip = (chip == "6502" ? "6502" : "65C02");
|
||||
enum _isStrict = strict;
|
||||
enum _isCumulative = cumulative;
|
||||
|
||||
struct _Mem
|
||||
{
|
||||
|
@ -71,7 +58,7 @@ final class Cpu(string chip, bool strict, bool cumulative)
|
|||
|
||||
struct _Clock
|
||||
{
|
||||
static if (cumulative)
|
||||
version(Cumulative)
|
||||
/*
|
||||
* Updates the number of cycles executed. Called just
|
||||
* prior to the final read/write action of each opcode.
|
||||
|
@ -97,7 +84,7 @@ final class Cpu(string chip, bool strict, bool cumulative)
|
|||
version(OpFunctions) {}
|
||||
else
|
||||
{
|
||||
static if (cumulative) { int cycles; }
|
||||
version(Cumulative) { int cycles; }
|
||||
ushort address, base;
|
||||
ubyte data;
|
||||
}
|
||||
|
@ -138,23 +125,26 @@ final class Cpu(string chip, bool strict, bool cumulative)
|
|||
ubyte opcode;
|
||||
static if (!opArray)
|
||||
{
|
||||
static if (cumulative) { int cycles; }
|
||||
version(Cumulative) { int cycles; }
|
||||
ushort address, base;
|
||||
ubyte data;
|
||||
}
|
||||
do {
|
||||
static if (cumulative && !opArray)
|
||||
cycles = 1;
|
||||
// XXX figure out final cycle stuff
|
||||
static if (!cumulative)
|
||||
version(Cumulative)
|
||||
{
|
||||
static if (!opArray) cycles = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
clock.tick();
|
||||
}
|
||||
// XXX check signals, NMI/IRQ delays, etc.
|
||||
opcode = memory.read(PC++);
|
||||
mixin(OpExecute(_chip, strict, cumulative));
|
||||
mixin(OpExecute(_chip));
|
||||
} while (keepRunning);
|
||||
}
|
||||
|
||||
version(OpDelegates) mixin (OpBodies(_chip, strict, cumulative));
|
||||
version(OpDelegates) mixin (OpBodies(_chip));
|
||||
}
|
||||
|
||||
|
||||
|
@ -163,8 +153,8 @@ enum ushort IRQ_VECTOR = 0xFFFE;
|
|||
|
||||
private:
|
||||
|
||||
version(OpFunctions) mixin(OpBodies("6502", vStrict, vCumulative));
|
||||
version(OpFunctions) mixin(OpBodies("65C02", vStrict, vCumulative));
|
||||
version(OpFunctions) mixin(OpBodies("6502"));
|
||||
version(OpFunctions) mixin(OpBodies("65C02"));
|
||||
|
||||
|
||||
//alias Cpu!("6502", false, false) T1;
|
||||
|
|
58
test/base.d
58
test/base.d
|
@ -8,6 +8,16 @@ import test.cpu, test.opcodes;
|
|||
import cpu.data_d6502;
|
||||
|
||||
|
||||
version(Strict)
|
||||
enum strict = true;
|
||||
else
|
||||
enum strict = false;
|
||||
version(Cumulative)
|
||||
enum cumulative = true;
|
||||
else
|
||||
enum cumulative = false;
|
||||
|
||||
|
||||
/*
|
||||
* Emulates zero page, stack, and 3 additional pages of "main memory"
|
||||
* starting at a user-defined address. Accesses outside the defined
|
||||
|
@ -2672,7 +2682,7 @@ if (isCpu!T)
|
|||
|
||||
cycles = 2;
|
||||
return [Bus(Action.READ, pc)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+1)]);
|
||||
}
|
||||
|
||||
|
@ -2689,7 +2699,7 @@ if (isCpu!T)
|
|||
|
||||
cycles = 3;
|
||||
return [Bus(Action.READ, pc)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+1)]) ~
|
||||
[Bus(Action.WRITE, sp)];
|
||||
}
|
||||
|
@ -2708,7 +2718,7 @@ if (isCpu!T)
|
|||
|
||||
cycles = 4;
|
||||
return [Bus(Action.READ, pc)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+1),
|
||||
Bus(Action.READ, sp)]) ~
|
||||
[Bus(Action.READ, sp1)];
|
||||
|
@ -2729,7 +2739,7 @@ if (isCpu!T)
|
|||
cycles = 2 + decimal;
|
||||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1)] ~
|
||||
If!decimal(If!(isStrict!T)(
|
||||
If!decimal(If!(strict)(
|
||||
[Bus(Action.READ, pc+2)]));
|
||||
}
|
||||
|
||||
|
@ -2751,7 +2761,7 @@ if (isCpu!T)
|
|||
cycles = 2 + branch + px;
|
||||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1)] ~
|
||||
If!branch(If!(isStrict!T)(
|
||||
If!branch(If!(strict)(
|
||||
[Bus(Action.READ, pc+2)] ~
|
||||
If!px(
|
||||
[Bus(Action.READ, wrongAddr)])));
|
||||
|
@ -2806,7 +2816,7 @@ if (isCpu!T)
|
|||
cycles = 3; // + accesses_end
|
||||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
If!(isNMOS!T)(
|
||||
[Bus(Action.READ, op1)]) ~
|
||||
If!(isCMOS!T)(
|
||||
|
@ -2862,7 +2872,7 @@ if (isCpu!T)
|
|||
cycles = 5; // + accesses_end
|
||||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
If!(isNMOS!T)(
|
||||
[Bus(Action.READ, op1)]) ~
|
||||
If!(isCMOS!T)(
|
||||
|
@ -2963,14 +2973,14 @@ if (isCpu!T)
|
|||
if (guess != right)
|
||||
{
|
||||
cycles += 1;
|
||||
return If!(isStrict!T)(
|
||||
return If!(strict)(
|
||||
If!(isNMOS!T)([Bus(Action.READ, guess)]) ~
|
||||
If!(isCMOS!T)([Bus(Action.READ, pc + opLen)])); // XXX
|
||||
}
|
||||
else if (noShortcut)
|
||||
{
|
||||
cycles += 1;
|
||||
return If!(isStrict!T)([Bus(Action.READ, guess)]);
|
||||
return If!(strict)([Bus(Action.READ, guess)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2999,13 +3009,13 @@ if (isCpu!T)
|
|||
cycles += (rmw ? 3 : (write ? 1 : (1 + decimal)));
|
||||
return If!read(
|
||||
[Bus(Action.READ, addr)] ~
|
||||
If!decimal(If!(isStrict!T)(
|
||||
If!decimal(If!(strict)(
|
||||
[Bus(Action.READ, pc + opLen)]))) ~
|
||||
If!write(
|
||||
[Bus(Action.WRITE, addr)]) ~
|
||||
If!rmw(
|
||||
[Bus(Action.READ, addr)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
If!(isNMOS!T)(
|
||||
[Bus(Action.WRITE, addr)]) ~
|
||||
If!(isCMOS!T)(
|
||||
|
@ -3029,12 +3039,12 @@ if (isCpu!T)
|
|||
|
||||
cycles = 6;
|
||||
return [Bus(Action.READ, pc)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+1),
|
||||
Bus(Action.READ, sp)]) ~
|
||||
[Bus(Action.READ, sp1),
|
||||
Bus(Action.READ, sp2)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, ret)]);
|
||||
}
|
||||
|
||||
|
@ -3054,7 +3064,7 @@ if (isCpu!T)
|
|||
|
||||
cycles = 6;
|
||||
return [Bus(Action.READ, pc)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+1),
|
||||
Bus(Action.READ, sp)]) ~
|
||||
[Bus(Action.READ, sp1),
|
||||
|
@ -3077,7 +3087,7 @@ if (isCpu!T)
|
|||
|
||||
cycles = 7;
|
||||
return [Bus(Action.READ, pc)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+1)]) ~
|
||||
[Bus(Action.WRITE, sp),
|
||||
Bus(Action.WRITE, sp1),
|
||||
|
@ -3101,7 +3111,7 @@ if (isCpu!T)
|
|||
cycles = 6;
|
||||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, sp)]) ~
|
||||
[Bus(Action.WRITE, sp),
|
||||
Bus(Action.WRITE, sp1),
|
||||
|
@ -3140,7 +3150,7 @@ if (isCpu!T)
|
|||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1),
|
||||
Bus(Action.READ, pc+2)] ~
|
||||
If!(isStrict!T)(If!(isCMOS!T)(
|
||||
If!(strict)(If!(isCMOS!T)(
|
||||
[Bus(Action.READ, pc+3)])) ~ // XXX
|
||||
[Bus(Action.READ, ial),
|
||||
Bus(Action.READ, iah)];
|
||||
|
@ -3170,7 +3180,7 @@ if (isCpu!T && isCMOS!T)
|
|||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1),
|
||||
Bus(Action.READ, pc+2)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+3)]) ~ // XXX
|
||||
[Bus(Action.READ, ial),
|
||||
Bus(Action.READ, iah)];
|
||||
|
@ -3196,7 +3206,7 @@ if (isCpu!T && isCMOS!T)
|
|||
cycles = 8;
|
||||
return [Bus(Action.READ, pc),
|
||||
Bus(Action.READ, pc+1)] ~
|
||||
If!(isStrict!T)(
|
||||
If!(strict)(
|
||||
[Bus(Action.READ, pc+2),
|
||||
Bus(Action.READ, weird),
|
||||
Bus(Action.READ, 0xFFFF),
|
||||
|
@ -3337,16 +3347,6 @@ void test_opcode_timing(T)(ubyte opcode, busreport report)
|
|||
}
|
||||
|
||||
|
||||
version(Strict)
|
||||
enum testStrict = true;
|
||||
else
|
||||
enum testStrict = false;
|
||||
version(Cumulative)
|
||||
enum testCumulative = true;
|
||||
else
|
||||
enum testCumulative = false;
|
||||
|
||||
|
||||
struct CheckOptions
|
||||
{
|
||||
enum Addr
|
||||
|
|
34
test/cpu.d
34
test/cpu.d
|
@ -11,6 +11,16 @@ import std.conv, std.exception, std.random, std.string, std.traits;
|
|||
public import cpu.d6502 : Cpu, is6502, is65C02;
|
||||
|
||||
|
||||
version(Strict)
|
||||
enum strict = true;
|
||||
else
|
||||
enum strict = false;
|
||||
version(Cumulative)
|
||||
enum cumulative = true;
|
||||
else
|
||||
enum cumulative = false;
|
||||
|
||||
|
||||
// True if T is the type of a cpu.
|
||||
template isCpu(T)
|
||||
{
|
||||
|
@ -29,27 +39,13 @@ template isCMOS(T)
|
|||
enum isCMOS = is65C02!T;
|
||||
}
|
||||
|
||||
// True if the cpu type T accesses memory on every cycle.
|
||||
template isStrict(T)
|
||||
{
|
||||
enum isStrict = isCpu!T && __traits(getMember, T, "_isStrict");
|
||||
}
|
||||
|
||||
// True if the cpu type T aggregates ticks.
|
||||
template isCumulative(T)
|
||||
{
|
||||
enum isCumulative = isCpu!T && __traits(getMember, T, "_isCumulative");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The type of a cpu, based on its architecture (6502 or 65C02) and
|
||||
* its timing characteristics (strict or not bus access, cumulative or
|
||||
* not cycle reporting).
|
||||
* The type of a cpu, based on its architecture (6502 or 65C02).
|
||||
*/
|
||||
template CPU(string arch, bool strict, bool cumulative)
|
||||
template CPU(string arch)
|
||||
{
|
||||
alias Cpu!(arch, strict, cumulative) CPU;
|
||||
alias Cpu!(arch) CPU;
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,7 +66,7 @@ if (isCpu!T)
|
|||
void connectMem(T, S)(T cpu, ref S mem)
|
||||
if (isCpu!T)
|
||||
{
|
||||
static if (isCumulative!T)
|
||||
static if (cumulative)
|
||||
void tick(int cycles) {}
|
||||
else
|
||||
void tick() {}
|
||||
|
@ -96,7 +92,7 @@ if (isCpu!T)
|
|||
auto cycles = new int;
|
||||
auto wrappedTick = cpu.clock.tick;
|
||||
|
||||
static if (isCumulative!T)
|
||||
static if (cumulative)
|
||||
{
|
||||
void tick(int cyc)
|
||||
{
|
||||
|
|
|
@ -11,12 +11,12 @@ void main(string[] args)
|
|||
auto opts = CheckOptions(args);
|
||||
auto report = report_timing_debug();
|
||||
|
||||
alias CPU!("6502", testStrict, testCumulative) T1;
|
||||
alias CPU!("6502") T1;
|
||||
writeln("Testing bus/timing, 6502");
|
||||
foreach (op; opts.codes6502)
|
||||
test_opcode_timing!T1(cast(ubyte)op, report);
|
||||
|
||||
alias CPU!("65C02", testStrict, testCumulative) T2;
|
||||
alias CPU!("65C02") T2;
|
||||
writeln("Testing bus/timing, 65C02");
|
||||
foreach (op; opts.codes65C02)
|
||||
test_opcode_timing!T2(cast(ubyte)op, report);
|
||||
|
|
|
@ -228,11 +228,10 @@ if (isCpu!T)
|
|||
|
||||
version(Benchmark)
|
||||
{
|
||||
static assert(!testStrict && !testCumulative);
|
||||
import std.datetime, std.stdio;
|
||||
void f0()
|
||||
{
|
||||
testDecimalMode!(CPU!("65C02", false, false))();
|
||||
testDecimalMode!(CPU!("65C02"))();
|
||||
}
|
||||
|
||||
void main()
|
||||
|
@ -248,9 +247,9 @@ else
|
|||
void main()
|
||||
{
|
||||
writeln("Testing decimal mode, 6502");
|
||||
testDecimalMode!(CPU!("6502", testStrict, testCumulative))();
|
||||
testDecimalMode!(CPU!("6502"))();
|
||||
|
||||
writeln("Testing decimal mode, 65C02");
|
||||
testDecimalMode!(CPU!("65C02", testStrict, testCumulative))();
|
||||
testDecimalMode!(CPU!("65C02"))();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@ void main(string[] args)
|
|||
auto opts = CheckOptions(args);
|
||||
auto report = report_debug();
|
||||
|
||||
alias CPU!("6502", testStrict, testCumulative) T1;
|
||||
alias CPU!("6502") T1;
|
||||
writeln("Testing functionality, 6502");
|
||||
foreach (opcode; opts.codes6502)
|
||||
test_one_opcode!T1(cast(ubyte)opcode, report);
|
||||
|
||||
alias CPU!("65C02", testStrict, testCumulative) T2;
|
||||
alias CPU!("65C02") T2;
|
||||
writeln("Testing functionality, 65C02");
|
||||
foreach (opcode; opts.codes65C02)
|
||||
test_one_opcode!T2(cast(ubyte)opcode, report);
|
||||
|
|
Loading…
Reference in New Issue