2727 distribution.
2828*/
2929
30+ import std.algorithm : canFind, filter, map;
3031import std.array : appender;
31- import std.file : exists;
32+ import std.conv : to;
33+ import std.file : exists, read;
3234import std.format ;
3335import std.getopt ;
36+ import std.parallelism : parallel;
3437import std.path : buildPath;
38+ import std.range : array, iota, split;
3539import std.stdio ;
40+ import std.string : strip;
41+ import std.traits : EnumMembers;
3642
3743import stdx.data.json;
44+ import xebin.emu;
3845
3946/* Emits `TaggedAlgebraic.opEquals` into this object file.
4047
@@ -171,6 +178,78 @@ unittest
171178 assert (tests[0 ].cycles == [Access(59082 , 177 , false ), Access(40 , 160 , true )]);
172179}
173180
181+ struct Result
182+ {
183+ ubyte opcode;
184+ size_t total, failed;
185+ }
186+
187+ Result runOpcode (CpuVariant v)(string path, ubyte opcode)
188+ {
189+ Result r = { opcode: opcode };
190+
191+ // WAI and STP do not finish and so they have empty files
192+ const text = cast (string ) read(path);
193+ if (! text.strip().length)
194+ return r;
195+
196+ foreach (ref t; parseTests(text))
197+ {}
198+
199+ return r;
200+ }
201+
202+ struct Target
203+ {
204+ string dir;
205+ CpuVariant cpu;
206+ }
207+
208+ immutable Target[] targets = [
209+ Target(" 6502" , CpuVariant.mos_6502),
210+ Target(" synertek65c02" , CpuVariant.wdc_65c02),
211+ Target(" rockwell65c02" , CpuVariant.rockwell_r65c02),
212+ Target(" wdc65c02" , CpuVariant.wdc_w65c02s),
213+ ];
214+
215+ size_t runTarget (CpuVariant v)(string dir, const (ubyte )[] opcodes)
216+ {
217+ auto results = new Result[opcodes.length];
218+ foreach (i, opcode; opcodes.parallel)
219+ {
220+ const path = buildPath(dir, format(" %02x.json" , opcode));
221+ results[i] = exists(path)
222+ ? runOpcode! v(path, opcode)
223+ : Result(opcode);
224+ }
225+
226+ size_t failed;
227+ return failed;
228+ }
229+
230+ ubyte [] parseOpcodes (string spec)
231+ {
232+ if (! spec.length)
233+ return iota (256 ).map! (i => cast (ubyte ) i).array;
234+ bool [256 ] set;
235+ foreach (part; spec.split(" ," ))
236+ {
237+ const range = part.split(" -" ).map! (a => a.to! uint (16 )).array;
238+ const lo = range[0 ];
239+ const hi = range.length > 1 ? range[1 ] : lo;
240+ foreach (i; lo .. hi + 1 )
241+ set[i] = true ;
242+ }
243+ return iota (256 ).filter! (i => set[i]).map! (i => cast (ubyte ) i).array;
244+ }
245+
246+ unittest
247+ {
248+ assert (parseOpcodes(" a9" ) == [0xa9 ]);
249+ assert (parseOpcodes(" b1-b5,00" ) == [0x00 , 0xb1 , 0xb2 , 0xb3 , 0xb4 , 0xb5 ]);
250+ assert (parseOpcodes(" " ).length == 256 );
251+ }
252+
174253string findSuite (string dir)
175254{
176255 if (dir.length)
@@ -184,8 +263,13 @@ string findSuite(string dir)
184263int main (string [] args)
185264{
186265 string dir;
266+ string cpuSpec;
267+ string opcodeSpec;
268+
187269 auto help = getopt(args,
188- " d|dir" , " root of SingleStepTests/65x02" , &dir);
270+ " d|dir" , " root of SingleStepTests/65x02" , &dir,
271+ " c|cpu" , " CPUs to test, comma separated (default: all found)." , &cpuSpec,
272+ " o|opcodes" , " Opcodes in hex, e.g. a9,1e,b1-b5 (default: all)." , &opcodeSpec);
189273
190274 if (help.helpWanted)
191275 {
@@ -202,5 +286,41 @@ int main(string[] args)
202286 return 2 ;
203287 }
204288
289+ const opcodes = parseOpcodes(opcodeSpec);
290+ const cpus = cpuSpec.length ? cpuSpec.split(" ," ) : null ;
291+
292+ size_t failed;
293+ size_t ran;
294+ foreach (target; targets)
295+ {
296+ if (cpus ! is null && ! cpus.canFind(target.dir) &&
297+ ! cpus.canFind(target.cpu.to! string ))
298+ continue ;
299+ const dataDir = buildPath(root, target.dir, " v1" );
300+ if (! exists(dataDir))
301+ continue ;
302+ ++ ran;
303+ writefln(" %s (%s)" , target.cpu, target.dir);
304+ stdout.flush();
305+ dispatch: switch (target.cpu)
306+ {
307+ static foreach (v; EnumMembers! CpuVariant)
308+ {
309+ case v:
310+ failed += runTarget! v(dataDir, opcodes);
311+ break dispatch;
312+ }
313+ default :
314+ assert (0 );
315+ }
316+ }
317+
318+ if (! ran)
319+ {
320+ stderr.writefln(" nothing to run -- no family member under %s matched --cpu" , root);
321+ return 2 ;
322+ }
323+ writefln(" %d opcode%s with failures" , failed, failed == 1 ? " " : " s" );
324+
205325 return 0 ;
206326}
0 commit comments