1
1
const std = @import ("std" );
2
2
const cpu_import = @import ("cpu.zig" );
3
3
const utils = @import ("utils.zig" );
4
+ const cli = @import ("cli.zig" );
5
+ const c = @import ("Z80.zig" );
6
+
4
7
const Allocator = std .mem .Allocator ;
8
+ const Z80 = cpu_import .Z80 ;
9
+ const Flag = cpu_import .Flag ;
10
+
11
+ const Options = struct {
12
+ benchmark : bool ,
13
+ };
5
14
6
15
pub fn main () ! void {
7
16
var gpa = std .heap .GeneralPurposeAllocator (.{ .safety = true }){};
8
17
defer _ = gpa .deinit ();
9
18
10
19
const alloc = gpa .allocator ();
11
20
21
+ const args = try std .process .argsAlloc (alloc );
22
+ defer std .process .argsFree (alloc , args );
23
+
24
+ var options = Options { .benchmark = true };
25
+ if (! try cli .parse (args , Options , & options )) {
26
+ return ;
27
+ }
28
+
12
29
const tests = try loadTests (alloc );
13
30
defer tests .deinit ();
14
31
15
32
const results = try loadTestResults (alloc );
16
33
defer results .deinit ();
17
34
18
- var cpu = cpu_import .Z80 .init (alloc );
35
+ if (options .benchmark ) {
36
+ var cpu = c.Z80 {};
37
+ for (tests .value , 0.. ) | t , n | {
38
+ var memory = [_ ]u8 {0 } ** 0x10000 ;
39
+ loadBench (& cpu , t , & memory );
40
+ std .debug .print ("Running test '{s}'...\n " , .{t .name });
41
+
42
+ const read = struct {
43
+ fn read (context : ? * anyopaque , address : c_ushort ) callconv (.C ) u8 {
44
+ const mem : * [0x10000 ]u8 = @ptrCast (@alignCast (context .? ));
45
+ return mem [address ];
46
+ }
47
+ }.read ;
48
+
49
+ const write = struct {
50
+ fn write (context : ? * anyopaque , address : c_ushort , value : u8 ) callconv (.C ) void {
51
+ const mem : * [0x10000 ]u8 = @ptrCast (@alignCast (context .? ));
52
+ mem [address ] = value ;
53
+ }
54
+ }.write ;
55
+
56
+ cpu .read = read ;
57
+ cpu .fetch = read ;
58
+ cpu .write = write ;
59
+ cpu .fetch_opcode = read ;
60
+ cpu .context = & memory ;
61
+ _ = c .z80_run (& cpu , 1 );
62
+
63
+ compareBenchResult (& cpu , results .value [n ], & memory );
64
+ }
65
+ // runBenchmark(alloc, tests.value, results.value);
66
+ return ;
67
+ }
68
+
69
+ var cpu = Z80 .init (alloc );
19
70
for (tests .value , 0.. ) | t , n | {
20
71
std .debug .print ("Running test '{s}'...\n " , .{t .name });
21
72
loadTest (& cpu , t );
@@ -27,11 +78,136 @@ pub fn main() !void {
27
78
}
28
79
}
29
80
30
- fn compareResult (cpu : * cpu_import.Z80 , result : TestResult ) void {
81
+ fn runBenchmark (alloc : Allocator , tests : []TestCase , results : []TestResult ) void {
82
+ _ = alloc ;
83
+ var cpu = c.Z80 {};
84
+ for (tests , 0.. ) | t , n | {
85
+ var memory = [_ ]u8 {0 } ** 0x10000 ;
86
+ std .debug .print ("Running test '{s}'...\n " , .{t .name });
87
+ loadBench (& cpu , t , & memory );
88
+ _ = c .z80_run (& cpu , t .state .tStates );
89
+
90
+ compareBenchResult (& cpu , results [n ], & memory );
91
+ }
92
+ }
93
+
94
+ fn compareBenchResult (cpu : * c.Z80 , result : TestResult , memory : * [0x10000 ]u8 ) void {
95
+ _ = memory ;
96
+ if (result .state .af != cpu .af .uint16_value ) {
97
+ std .debug .print ("AF mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .af , cpu .af .uint16_value });
98
+ var expected_flag = Flag .init (utils .lo (result .state .afDash ));
99
+ var actual_flag = Flag .init (utils .lo (cpu .af .uint16_value ));
100
+ std .debug .print (" expected: " , .{});
101
+ expected_flag .dump ();
102
+ std .debug .print (" actual: " , .{});
103
+ actual_flag .dump ();
104
+ }
105
+
106
+ if (result .state .bc != cpu .bc .uint16_value ) {
107
+ std .debug .print ("BC mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .bc , cpu .bc .uint16_value });
108
+ }
109
+
110
+ if (result .state .de != cpu .de .uint16_value ) {
111
+ std .debug .print ("DE mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .de , cpu .de .uint16_value });
112
+ }
113
+
114
+ if (result .state .hl != cpu .hl .uint16_value ) {
115
+ std .debug .print ("HL mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .hl , cpu .hl .uint16_value });
116
+ }
117
+
118
+ if (result .state .afDash != cpu .af_ .uint16_value ) {
119
+ std .debug .print ("AF' mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .afDash , cpu .af_ .uint16_value });
120
+ }
121
+
122
+ if (result .state .bcDash != cpu .bc_ .uint16_value ) {
123
+ std .debug .print ("BC' mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .bcDash , cpu .bc_ .uint16_value });
124
+ }
125
+
126
+ if (result .state .deDash != cpu .de_ .uint16_value ) {
127
+ std .debug .print ("DE' mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .deDash , cpu .de_ .uint16_value });
128
+ }
129
+
130
+ if (result .state .hlDash != cpu .hl_ .uint16_value ) {
131
+ std .debug .print ("HL' mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .hlDash , cpu .hl_ .uint16_value });
132
+ }
133
+
134
+ // if (result.state.ix != cpu.ix.uint16_value) {
135
+ // std.debug.print("IX mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n", .{ result.state.ix, cpu.ix.uint16_value });
136
+ // }
137
+ //
138
+ // if (result.state.iy != cpu.iy.uint16_value) {
139
+ // std.debug.print("IY mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n", .{ result.state.iy, cpu.iy.uint16_value });
140
+ // }
141
+
142
+ if (result .state .sp != cpu .sp .uint16_value ) {
143
+ std .debug .print ("SP mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .sp , cpu .sp .uint16_value });
144
+ }
145
+
146
+ if (result .state .pc != cpu .pc .uint16_value ) {
147
+ std .debug .print ("PC mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .pc , cpu .pc .uint16_value });
148
+ }
149
+
150
+ if (result .state .i != cpu .i ) {
151
+ std .debug .print ("I mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .i , cpu .i });
152
+ }
153
+
154
+ if (result .state .r != cpu .r ) {
155
+ std .debug .print ("R mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .r , cpu .r });
156
+ }
157
+
158
+ // if (result.state.iff1 != cpu.iff1) {
159
+ // std.debug.print("IFF1 mismatch: expected {}, got {}\n", .{ result.state.iff1, cpu.iff1 });
160
+ // }
161
+ //
162
+ // if (result.state.iff2 != cpu.iff2) {
163
+ // std.debug.print("IFF2 mismatch: expected {}, got {}\n", .{ result.state.iff2, cpu.iff2 });
164
+ // }
165
+ //
166
+ // if (result.state.im != cpu.im) {
167
+ // std.debug.print("IM mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n", .{ result.state.im, cpu.im });
168
+ // }
169
+ //
170
+ // if (result.state.halted != cpu.halt_line) {
171
+ // std.debug.print("Halted mismatch: expected {}, got {}\n", .{ result.state.halted, cpu.halt_line });
172
+ // }
173
+ //
174
+ // if (result.state.tStates != cpu.cycles - 1) {
175
+ // std.debug.print("TStates mismatch: expected {d}, got {d}\n", .{ result.state.tStates, cpu.cycles - 1 });
176
+ // }
177
+ //
178
+ }
179
+
180
+ fn loadBench (cpu : * c.Z80 , t : TestCase , memory : * [0x10000 ]u8 ) void {
181
+ cpu .af .uint16_value = t .state .af ;
182
+ cpu .bc .uint16_value = t .state .bc ;
183
+ cpu .de .uint16_value = t .state .de ;
184
+ cpu .hl .uint16_value = t .state .hl ;
185
+ cpu .af_ .uint16_value = t .state .afDash ;
186
+ cpu .bc_ .uint16_value = t .state .bcDash ;
187
+ cpu .de_ .uint16_value = t .state .deDash ;
188
+ cpu .hl_ .uint16_value = t .state .hlDash ;
189
+ // cpu.ix.uint16_value = t.state.ix;
190
+ // cpu.iy.uint16_value = t.state.iy;
191
+ cpu .sp .uint16_value = t .state .sp ;
192
+ cpu .pc .uint16_value = t .state .pc ;
193
+ // cpu.memptr = t.state.memptr;
194
+ cpu .i = t .state .i ;
195
+ cpu .r = t .state .r ;
196
+ cpu .iff1 = if (t .state .iff1 ) 1 else 0 ;
197
+ cpu .iff2 = if (t .state .iff2 ) 1 else 0 ;
198
+ cpu .im = t .state .im ;
199
+ cpu .halt_line = if (t .state .halted ) 1 else 0 ;
200
+
201
+ for (t .memory ) | m | {
202
+ @memcpy (memory [m .address .. m .address + m .data .len ], m .data );
203
+ }
204
+ }
205
+
206
+ fn compareResult (cpu : * Z80 , result : TestResult ) void {
31
207
if (result .state .af != cpu .af ) {
32
208
std .debug .print ("AF mismatch: expected 0x{X:0>4}, got 0x{X:0>4}\n " , .{ result .state .af , cpu .af });
33
- var expected_flag = cpu_import . Flag .init (utils .lo (result .state .afDash ));
34
- var actual_flag = cpu_import . Flag .init (utils .lo (cpu .getF ()));
209
+ var expected_flag = Flag .init (utils .lo (result .state .afDash ));
210
+ var actual_flag = Flag .init (utils .lo (cpu .getF ()));
35
211
std .debug .print (" expected: " , .{});
36
212
expected_flag .dump ();
37
213
std .debug .print (" actual: " , .{});
@@ -148,7 +324,7 @@ fn loadTests(alloc: Allocator) !std.json.Parsed([]TestCase) {
148
324
return tests ;
149
325
}
150
326
151
- fn loadTest (cpu : * cpu_import. Z80 , t : TestCase ) void {
327
+ fn loadTest (cpu : * Z80 , t : TestCase ) void {
152
328
cpu .reset ();
153
329
cpu .af = t .state .af ;
154
330
cpu .bc = t .state .bc ;
0 commit comments