68kcounter
Version:
68000 ASM source code cycle counter
87 lines (79 loc) • 2.4 kB
text/typescript
/**
* Parses and asserts correct timings for every instruction in `instructions.s`
*/
import fs from "fs";
import parse from "../../src/parse";
import evaluate from "../../src/parse/evaluate";
import { Timing } from "../../src/timings";
const instructions = fs
.readFileSync(__dirname + "/../examples/instructions.s")
.toString();
/**
* Extract expected timings from line comment
*/
function parseComment(
comment: string,
m?: number
): { total: Timing; index: number } {
let index = 0;
const [timings, caseText] = comment
.substr(1)
.split(";")
.map((n) => n.trim());
// The comment suffix determines which timing we looks at where there are multiple values
switch (caseText) {
case "Branch not taken":
case "Branch not taken, cc true":
case "cc true":
case "Trap":
case "Trap, d0 > <ea>":
index = 1;
break;
case "Branch not taken, counter expired":
case "Trap, d0 < 0":
index = 2;
break;
}
if (timings.includes("=")) {
const total = parseTime(timings.split("=").pop().trim(), m);
return { total, index };
} else {
return {
total: parseTime(timings, m),
index,
};
}
}
/**
* Convert string formatted timing 'x(y/z)'
*/
const parseTime = (str: string, m?: number): Timing =>
str
.match(/([\d+m]+)\(([\d+m]+)\/([\d+m]+)\)/)
.slice(1)
.map((n) => evaluate(n.replace(/(\d)m/, "$1*m"), { m })) as Timing;
describe("instruction timings", () => {
const lines = parse(instructions);
for (let i = 0; i < lines.length; i++) {
const { statement, timing } = lines[i];
if (
// Does this look like it should be an instruction?
// Don't rely on `isInstruction()` as this won't catch unsupported mnemonics
!statement.isDirective() &&
!statement.isLabel() &&
statement.text.trim() && // ignore empty lines
!statement.text.match(/^\s*;/) // ignore comment-only lines
) {
test(statement.text, () => {
expect(statement.isInstruction()).toBeTruthy();
const { values: timings, calculation } = timing;
const m = Array.isArray(calculation.n)
? calculation.n[0]
: calculation.n;
const { total, index } = parseComment(statement.comment.text, m);
const idx = Math.min(index, timings.length - 1);
expect(timings[idx]).toEqual(total);
});
}
}
});