aboutsummaryrefslogtreecommitdiff
path: root/benchmark/convert-instructions.ts
blob: 67a3f1f51a16b28c07d788a011d11b61917372fe (plain)
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
81
import * as fs from 'fs';
import * as prettier from 'prettier';

const input = fs.readFileSync('src/instruction.ts', { encoding: 'utf-8' });
let fnName = '';
let fnBody = '';
let openingBrace = false;
let currentInstruction = '';
let pattern = '';
let output = `
import { ICPU } from '../src/cpu';

function isTwoWordInstruction(opcode: number) {
  return (
    /* LDS */
    (opcode & 0xfe0f) === 0x9000 ||
    /* STS */
    (opcode & 0xfe0f) === 0x9200 ||
    /* CALL */
    (opcode & 0xfe0e) === 0x940e ||
    /* JMP */
    (opcode & 0xfe0e) === 0x940c
  );
}
`;
const patternToFn: Array<[string, string]> = [];
for (const line of input.split('\n')) {
  if (line.startsWith('  /* ')) {
    currentInstruction = line
      .trim()
      .split(',')[0]
      .split(' ')[1];
    fnBody = '';
    openingBrace = false;
    pattern = line.split(',')[1].split('*')[0];
    console.log(currentInstruction);
    fnName = 'inst' + currentInstruction.replace(/[\(\)]/g, '');
    patternToFn.push([pattern.trim(), fnName]);
  }
  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 && openingBrace) {
    fnBody += line;
  } else if (currentInstruction && !openingBrace) {
    openingBrace = line.includes('{');
  }
}

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, { singleQuote: true, parser: 'babel' });

fs.writeFileSync('benchmark/instruction-fn.ts', formattedOutput, {
  encoding: 'utf-8'
});