Cpu speedup; removed OpFunctions option

This commit is contained in:
edmccard 2012-04-13 21:35:40 -04:00
parent d12f793d9a
commit a572ea9146
5 changed files with 102 additions and 129 deletions

View File

@ -23,17 +23,10 @@ version(OpDelegates)
enum opArray = true; enum opArray = true;
} }
// OpFunctions: each opcode is a free function with a Cpu argument.
version(OpFunctions)
{
enum versionCheck = 2;
enum opArray = true;
}
// OpSwitch: each opcode is inlined in a 256-case switch. // OpSwitch: each opcode is inlined in a 256-case switch.
version(OpSwitch) version(OpSwitch)
{ {
enum versionCheck = 3; enum versionCheck = 2;
enum opArray = false; enum opArray = false;
} }
@ -45,7 +38,7 @@ version(OpSwitch)
*/ */
version(OpNestedSwitch) version(OpNestedSwitch)
{ {
enum versionCheck = 4; enum versionCheck = 3;
enum opArray = false; enum opArray = false;
} }
@ -59,71 +52,37 @@ string OpArrayDef()
{ {
version(OpDelegates) version(OpDelegates)
return q{void delegate()[256] opcodes;}; return q{void delegate()[256] opcodes;};
else version(OpFunctions)
return q{void function(typeof(this))[256] opcodes;};
else else
return ""; return "";
} }
string OpArrayInit() string OpArrayInit()
{ {
static if (!opArray) return ""; string ret;
else foreach (op; 0..256)
{ {
string ret; ret ~= Fmt("opcodes[0x#] = &opcode_#;\n",
foreach (op; 0..256) Hex2(op), Hex2(op));
{
version(OpDelegates)
ret ~= Fmt("opcodes[0x#] = &opcode_#;\n",
Hex2(op), Hex2(op));
version(OpFunctions)
ret ~= Fmt("opcodes[0x#] = &opcode_#!(typeof(this));\n",
Hex2(op), Hex2(op));
}
return ret;
} }
return ret;
} }
string OpBodies(string chip) string OpMethods(string chip)
{ {
static if (!opArray) return ""; string ret;
else foreach (op; 0..256)
{ {
string ret; ret ~= "final void opcode_" ~ Hex2(op) ~ "()\n{\n" ~
foreach (op; 0..256) If!(cumulative)("int cycles = 1;\n") ~
{ OpBody(op, chip) ~ "}\n";
version(OpDelegates)
ret ~= "final void opcode_" ~ Hex2(op) ~ "()\n{\n" ~
If!(cumulative)("int cycles = 1;\n") ~
OpBody(op, chip) ~ "}\n";
version(OpFunctions)
ret ~= "void opcode_" ~ Hex2(op) ~
"(T)(T cpu) if (is" ~ chip ~ "!T)\n{\n" ~
If!(cumulative)("int cycles = 1;\n") ~
OpBody(op, chip) ~ "}\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;
} }
string OpExecute(string chip) string OpExecute(string chip)
{ {
version(OpDelegates) version(OpDelegates)
return q{opcodes[opcode]();}; return q{opcodes[opcode]();};
version(OpFunctions)
return q{opcodes[opcode](this);};
version(OpSwitch) version(OpSwitch)
return Switch256(chip); return Switch256(chip);
version(OpNestedSwitch) version(OpNestedSwitch)
@ -900,42 +859,17 @@ string Strange_Undoc(string val)
string Local(string type) string Local(string type)
{ {
version(OpFunctions) return "";
return type ~ " ";
else
return "";
/+
version(OpSwitch)
return "";
else version(OpNestedSwitch)
return "";
else
return type ~ " ";
+/
} }
string Local(string type, string var) string Local(string type, string var)
{ {
version(OpFunctions) return var;
return type ~ " " ~ var;
else
return var;
/+
version(OpSwitch)
return var;
else version(OpNestedSwitch)
return var;
else
return type ~ " " ~ var;
+/
} }
string Attr(string var) string Attr(string var)
{ {
version(OpFunctions) return var;
return "cpu." ~ var;
else
return var;
} }

View File

@ -40,18 +40,25 @@ template is65C02(T)
} }
final class Cpu(string chip) final class Cpu(string chip, MEM, CLK)
if (__traits(compiles, {
MEM m; ubyte val; ushort addr;
val = m.read(addr);
m.write(addr, val);
CLK c; int cycles;
version(Cumulative) c.tick(cycles);
else c.tick();
}))
{ {
static assert(chip == "6502" || chip == "65C02" || chip == "65c02"); static assert(chip == "6502" || chip == "65C02" || chip == "65c02");
enum _isCpu = true; enum _isCpu = true;
enum _chip = (chip == "6502" ? "6502" : "65C02"); enum _chip = (chip == "6502" ? "6502" : "65C02");
version(RunTest)
{
struct _Mem struct _Mem
{ {
// Reads a value from system memory.
ubyte delegate(ushort addr) read; ubyte delegate(ushort addr) read;
// Writes a value to system memory.
void delegate(ushort addr, ubyte val) write; void delegate(ushort addr, ubyte val) write;
} }
_Mem memory; _Mem memory;
@ -59,19 +66,17 @@ final class Cpu(string chip)
struct _Clock struct _Clock
{ {
version(Cumulative) version(Cumulative)
/*
* Updates the number of cycles executed. Called just
* prior to the final read/write action of each opcode.
*/
void delegate(int cycles) tick; void delegate(int cycles) tick;
else else
/*
* Increments the number of cycles executed. Called prior
* to each read/write action.
*/
void delegate() tick; void delegate() tick;
} }
_Clock clock; _Clock clock;
}
else
{
MEM memory;
CLK clock;
}
ubyte A, X, Y, S; ubyte A, X, Y, S;
ushort PC; ushort PC;
@ -80,10 +85,9 @@ final class Cpu(string chip)
ubyte N, Z; ubyte N, Z;
bool V, D, I, C; bool V, D, I, C;
static if (opArray) { mixin(OpArrayDef()); } version(OpDelegates)
version(OpFunctions) {}
else
{ {
mixin(OpArrayDef());
version(Cumulative) { int cycles; } version(Cumulative) { int cycles; }
ushort address, base; ushort address, base;
ubyte data; ubyte data;
@ -92,9 +96,15 @@ final class Cpu(string chip)
// TODO: other methods for stopping cpu // TODO: other methods for stopping cpu
bool keepRunning; bool keepRunning;
this() this(MEM memory, CLK clock)
{ {
static if (opArray) mixin(OpArrayInit()); version(RunTest) {}
else
{
this.memory = memory;
this.clock = clock;
}
version(OpDelegates) mixin(OpArrayInit());
} }
final void statusFromByte(ubyte p) final void statusFromByte(ubyte p)
@ -144,19 +154,13 @@ final class Cpu(string chip)
} while (keepRunning); } while (keepRunning);
} }
version(OpDelegates) mixin (OpBodies(_chip)); version(OpDelegates) mixin (OpMethods(_chip));
} }
enum ushort IRQ_VECTOR = 0xFFFE; enum ushort IRQ_VECTOR = 0xFFFE;
private:
version(OpFunctions) mixin(OpBodies("6502"));
version(OpFunctions) mixin(OpBodies("65C02"));
//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;

View File

@ -10,15 +10,7 @@ import std.conv, std.exception, std.random, std.string, std.traits;
public import cpu.d6502 : Cpu, is6502, is65C02; public import cpu.d6502 : Cpu, is6502, is65C02;
import test.base : strict, cumulative;
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. // True if T is the type of a cpu.
@ -40,19 +32,29 @@ template isCMOS(T)
} }
// Not used in test mode, but needed to instantiate a cpu.
class DummyMem
{
ubyte read(ushort) { return 0; }
void write(ushort, ubyte) {}
static if (cumulative) { void tick(int) {} }
else { void tick() {} }
}
/* /*
* The type of a cpu, based on its architecture (6502 or 65C02). * The type of a cpu, based on its architecture (6502 or 65C02).
*/ */
template CPU(string arch) template CPU(string arch, M = DummyMem, C = DummyMem)
{ {
alias Cpu!(arch) CPU; alias Cpu!(arch, M, C) CPU;
} }
auto makeCpu(T)(CpuInfo info) auto makeCpu(T)(CpuInfo info)
if (isCpu!T) if (isCpu!T)
{ {
auto cpu = new T(); auto cpu = new T(null, null);
cpu.PC = info.PC; cpu.PC = info.PC;
cpu.S = info.SP; cpu.S = info.SP;
cpu.statusFromByte(info.S); cpu.statusFromByte(info.S);

View File

@ -6,10 +6,9 @@ enum OpDefs
{ {
None, None,
Delegates = 1, Delegates = 1,
Functions = 2, Switch = 2,
Switch = 4, NestedSwitch = 4,
NestedSwitch = 8, All = 7
All = 15
} }
enum Tests enum Tests
@ -39,7 +38,6 @@ version(DigitalMars)
{ {
defStrings = [ defStrings = [
OpDefs.Delegates:" -version=OpDelegates", OpDefs.Delegates:" -version=OpDelegates",
OpDefs.Functions:" -version=OpFunctions",
OpDefs.Switch:" -version=OpSwitch", OpDefs.Switch:" -version=OpSwitch",
OpDefs.NestedSwitch:" -version=OpNestedSwitch" OpDefs.NestedSwitch:" -version=OpNestedSwitch"
]; ];
@ -83,7 +81,7 @@ void main(string[] args)
writeln( writeln(
`Options: `Options:
--test=type Func, Bus, Dec, or All --test=type Func, Bus, Dec, or All
--def=style Delegates, Functions, Switch, or NestedSwitch --def=style Delegates, Switch, or NestedSwitch
--op=num test opcode 'num' (num is hex) --op=num test opcode 'num' (num is hex)
--op=name test all opcodes named 'name' --op=name test all opcodes named 'name'
--addr=mode test all opcodes with addressing mode 'mode' --addr=mode test all opcodes with addressing mode 'mode'
@ -136,7 +134,7 @@ void runTest(OpDefs def, Tests test, string[] args)
writeln("With strict=", s, " cumulative=", c); writeln("With strict=", s, " cumulative=", c);
string cmdline = defStrings[def] ~ stStrings[s] ~ cmStrings[c] ~ string cmdline = defStrings[def] ~ stStrings[s] ~ cmStrings[c] ~
fNames[test] ~ join(args, " "); fNames[test] ~ join(args, " ");
system("rdmd --force -I.. -I../src " ~ cmdline); system("rdmd --force -I.. -I../src -version=RunTest" ~ cmdline);
} }
} }
} }

View File

@ -214,10 +214,20 @@ if (isCpu!T)
mem.write(0x8055, 0x84); mem.write(0x8055, 0x84);
} }
auto cpu = new T(); version(Benchmark)
connectMem(cpu, mem); {
auto runner = new BreakRunner(mem);
auto cpu = new T(runner, runner);
setPC(cpu, 0x8000); setPC(cpu, 0x8000);
try { cpu.run(true); } catch (StopException e) {}
}
else
{
auto cpu = new T(null, null);
setPC(cpu, 0x8000);
connectMem(cpu, mem);
runUntilBRK(cpu); runUntilBRK(cpu);
}
if (mem[0x8003]) if (mem[0x8003])
{ {
// TODO: check data block to find out what failed exactly // TODO: check data block to find out what failed exactly
@ -229,9 +239,34 @@ if (isCpu!T)
version(Benchmark) version(Benchmark)
{ {
import std.datetime, std.stdio; import std.datetime, std.stdio;
final class BreakRunner
{
TestMemory* mem;
this(ref TestMemory mem)
{
this.mem = &mem;
}
final ubyte read(ushort addr)
{
if (addr == 0xFFFE) throw new StopException("BRK");
return mem.read(addr);
}
final void write(ushort addr, ubyte val)
{
mem.write(addr, val);
}
static if (cumulative) { final void tick(int) {} }
else { final void tick() {} }
}
void f0() void f0()
{ {
testDecimalMode!(CPU!("65C02"))(); testDecimalMode!(CPU!("65C02", BreakRunner, BreakRunner))();
} }
void main() void main()