From a572ea91467f1639f7a50f5e5589051f04aa389b Mon Sep 17 00:00:00 2001 From: edmccard Date: Fri, 13 Apr 2012 21:35:40 -0400 Subject: [PATCH] Cpu speedup; removed OpFunctions option --- src/cpu/ctfe_d6502.d | 100 ++++++++----------------------------------- src/cpu/d6502.d | 52 +++++++++++----------- test/cpu.d | 26 +++++------ test/runtests.d | 12 +++--- test/test_decimal.d | 41 ++++++++++++++++-- 5 files changed, 102 insertions(+), 129 deletions(-) diff --git a/src/cpu/ctfe_d6502.d b/src/cpu/ctfe_d6502.d index 4aa4918..1bd0890 100644 --- a/src/cpu/ctfe_d6502.d +++ b/src/cpu/ctfe_d6502.d @@ -23,17 +23,10 @@ version(OpDelegates) 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. version(OpSwitch) { - enum versionCheck = 3; + enum versionCheck = 2; enum opArray = false; } @@ -45,7 +38,7 @@ version(OpSwitch) */ version(OpNestedSwitch) { - enum versionCheck = 4; + enum versionCheck = 3; enum opArray = false; } @@ -59,71 +52,37 @@ string OpArrayDef() { version(OpDelegates) return q{void delegate()[256] opcodes;}; - else version(OpFunctions) - return q{void function(typeof(this))[256] opcodes;}; else return ""; } string OpArrayInit() { - static if (!opArray) return ""; - else + string ret; + foreach (op; 0..256) { - string ret; - foreach (op; 0..256) - { - 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; + ret ~= Fmt("opcodes[0x#] = &opcode_#;\n", + Hex2(op), Hex2(op)); } + return ret; } -string OpBodies(string chip) +string OpMethods(string chip) { - static if (!opArray) return ""; - else + string ret; + foreach (op; 0..256) { - string ret; - foreach (op; 0..256) - { - 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; + ret ~= "final void opcode_" ~ Hex2(op) ~ "()\n{\n" ~ + If!(cumulative)("int cycles = 1;\n") ~ + OpBody(op, chip) ~ "}\n"; } + return ret; } string OpExecute(string chip) { version(OpDelegates) return q{opcodes[opcode]();}; - version(OpFunctions) - return q{opcodes[opcode](this);}; version(OpSwitch) return Switch256(chip); version(OpNestedSwitch) @@ -900,42 +859,17 @@ string Strange_Undoc(string val) string Local(string type) { - version(OpFunctions) - return type ~ " "; - else - return ""; -/+ - version(OpSwitch) - return ""; - else version(OpNestedSwitch) - return ""; - else - return type ~ " "; -+/ + return ""; } string Local(string type, string var) { - version(OpFunctions) - return type ~ " " ~ var; - else - return var; -/+ - version(OpSwitch) - return var; - else version(OpNestedSwitch) - return var; - else - return type ~ " " ~ var; -+/ + return var; } string Attr(string var) { - version(OpFunctions) - return "cpu." ~ var; - else - return var; + return var; } diff --git a/src/cpu/d6502.d b/src/cpu/d6502.d index 5f399b7..cace916 100644 --- a/src/cpu/d6502.d +++ b/src/cpu/d6502.d @@ -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"); enum _isCpu = true; enum _chip = (chip == "6502" ? "6502" : "65C02"); +version(RunTest) +{ struct _Mem { - // Reads a value from system memory. ubyte delegate(ushort addr) read; - - // Writes a value to system memory. void delegate(ushort addr, ubyte val) write; } _Mem memory; @@ -59,19 +66,17 @@ final class Cpu(string chip) struct _Clock { 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; else - /* - * Increments the number of cycles executed. Called prior - * to each read/write action. - */ void delegate() tick; } _Clock clock; +} +else +{ + MEM memory; + CLK clock; +} ubyte A, X, Y, S; ushort PC; @@ -80,10 +85,9 @@ final class Cpu(string chip) ubyte N, Z; bool V, D, I, C; - static if (opArray) { mixin(OpArrayDef()); } - version(OpFunctions) {} - else + version(OpDelegates) { + mixin(OpArrayDef()); version(Cumulative) { int cycles; } ushort address, base; ubyte data; @@ -92,9 +96,15 @@ final class Cpu(string chip) // TODO: other methods for stopping cpu 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) @@ -144,19 +154,13 @@ final class Cpu(string chip) } while (keepRunning); } - version(OpDelegates) mixin (OpBodies(_chip)); + version(OpDelegates) mixin (OpMethods(_chip)); } 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, true) T2; //alias Cpu!("6502", true, false) T3; diff --git a/test/cpu.d b/test/cpu.d index fde563f..f8bc3cd 100644 --- a/test/cpu.d +++ b/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; - -version(Strict) - enum strict = true; -else - enum strict = false; -version(Cumulative) - enum cumulative = true; -else - enum cumulative = false; +import test.base : strict, cumulative; // 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). */ -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) if (isCpu!T) { - auto cpu = new T(); + auto cpu = new T(null, null); cpu.PC = info.PC; cpu.S = info.SP; cpu.statusFromByte(info.S); diff --git a/test/runtests.d b/test/runtests.d index 7dbb6aa..f2769da 100644 --- a/test/runtests.d +++ b/test/runtests.d @@ -6,10 +6,9 @@ enum OpDefs { None, Delegates = 1, - Functions = 2, - Switch = 4, - NestedSwitch = 8, - All = 15 + Switch = 2, + NestedSwitch = 4, + All = 7 } enum Tests @@ -39,7 +38,6 @@ version(DigitalMars) { defStrings = [ OpDefs.Delegates:" -version=OpDelegates", - OpDefs.Functions:" -version=OpFunctions", OpDefs.Switch:" -version=OpSwitch", OpDefs.NestedSwitch:" -version=OpNestedSwitch" ]; @@ -83,7 +81,7 @@ void main(string[] args) writeln( `Options: --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=name test all opcodes named 'name' --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); string cmdline = defStrings[def] ~ stStrings[s] ~ cmStrings[c] ~ fNames[test] ~ join(args, " "); - system("rdmd --force -I.. -I../src " ~ cmdline); + system("rdmd --force -I.. -I../src -version=RunTest" ~ cmdline); } } } diff --git a/test/test_decimal.d b/test/test_decimal.d index abd879a..8c690b7 100644 --- a/test/test_decimal.d +++ b/test/test_decimal.d @@ -214,10 +214,20 @@ if (isCpu!T) mem.write(0x8055, 0x84); } - auto cpu = new T(); - connectMem(cpu, mem); +version(Benchmark) +{ + auto runner = new BreakRunner(mem); + auto cpu = new T(runner, runner); 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); +} if (mem[0x8003]) { // TODO: check data block to find out what failed exactly @@ -229,9 +239,34 @@ if (isCpu!T) version(Benchmark) { 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() { - testDecimalMode!(CPU!("65C02"))(); + testDecimalMode!(CPU!("65C02", BreakRunner, BreakRunner))(); } void main()