1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
import * as fs from 'fs';
import * as prettier from 'prettier';
import prettierOptions from '../prettier.config';
const input = fs.readFileSync('src/cpu/instruction.ts', { encoding: 'utf-8' });
let fnName = '';
let fnBody = '';
let currentInstruction = '';
let pattern = '';
let output = `
import { ICPU } from '../src/cpu/cpu';
function isTwoWordInstruction(opcode: number) {
return (
/* LDS */
(opcode & 0xfe0f) === 0x9000 ||
/* STS */
(opcode & 0xfe0f) === 0x9200 ||
/* CALL */
(opcode & 0xfe0e) === 0x940e ||
/* JMP */
(opcode & 0xfe0e) === 0x940c
);
}
/* eslint-disable @typescript-eslint/no-unused-vars */
`;
const patternToFn: Array<[string, string]> = [];
for (const line of input.split('\n')) {
if (line.startsWith(' /* ') && line.includes(', ')) {
currentInstruction = line.trim().split(',')[0].split(' ')[1];
fnBody = '';
pattern = line.split(',')[1].split('*')[0];
console.log(currentInstruction);
fnName = 'inst' + currentInstruction.replace(/[()]/g, '');
patternToFn.push([pattern.trim(), fnName]);
} else if (line.startsWith(' }')) {
output += `
export function ${fnName}(cpu: ICPU, opcode: number) {
/*${pattern}*/
${fnBody}
cpu.cycles++;
if (++cpu.pc >= cpu.progMem.length) {
cpu.pc = 0;
}
}
`;
currentInstruction = '';
} else if (currentInstruction) {
fnBody += line;
}
}
let executeInstructionCases = ``;
output += `\nexport const instructions = [`;
let i = 1;
for (const [fnPattern, fn] of patternToFn) {
output += `{pattern: '${fnPattern}', fn: ${fn}, idx: ${i}},`;
executeInstructionCases += `case ${i}: ${fn}(cpu, opcode); break;\n`;
i++;
}
output += ']';
output += `\n
export function executeInstruction(idx: number, cpu: ICPU, opcode: number) {
switch (idx) {
${executeInstructionCases}
default: instNOP(cpu, opcode);
}
}`;
const formattedOutput = prettier.format(output, {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...(prettierOptions as any),
parser: 'babel',
});
fs.writeFileSync('benchmark/instruction-fn.ts', formattedOutput, {
encoding: 'utf-8',
});
|