mirror of
https://github.com/edmccard/twoapple-reboot.git
synced 2025-01-14 12:30:10 +00:00
Cpu speedup; removed OpFunctions option
This commit is contained in:
parent
d12f793d9a
commit
a572ea9146
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
26
test/cpu.d
26
test/cpu.d
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user