From 27ea13401dfa443243d588c5636c85e1037b986d Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Sun, 1 Dec 2019 23:18:22 +0200 Subject: feat: improve benchmark code compare 3 alternatives: 1. Current avrInstruction() implementation 2. Map opcodes using a Javascript map 3. Map opcodes using a Uint16Array and big switch statement --- benchmark/convert-instructions.ts | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'benchmark/convert-instructions.ts') diff --git a/benchmark/convert-instructions.ts b/benchmark/convert-instructions.ts index 7e8e3fd..67a3f1f 100644 --- a/benchmark/convert-instructions.ts +++ b/benchmark/convert-instructions.ts @@ -2,15 +2,15 @@ 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'; -import { u16 } from '../src/types'; -function isTwoWordInstruction(opcode: u16) { +function isTwoWordInstruction(opcode: number) { return ( /* LDS */ (opcode & 0xfe0f) === 0x9000 || @@ -23,6 +23,7 @@ function isTwoWordInstruction(opcode: u16) { ); } `; +const patternToFn: Array<[string, string]> = []; for (const line of input.split('\n')) { if (line.startsWith(' /* ')) { currentInstruction = line @@ -33,11 +34,12 @@ for (const line of input.split('\n')) { openingBrace = false; pattern = line.split(',')[1].split('*')[0]; console.log(currentInstruction); - currentInstruction = currentInstruction.replace(/[\(\)]/g, ''); + fnName = 'inst' + currentInstruction.replace(/[\(\)]/g, ''); + patternToFn.push([pattern.trim(), fnName]); } if (line.startsWith(' }')) { output += ` - export function inst${currentInstruction}(cpu: ICPU, opcode: number) { + export function ${fnName}(cpu: ICPU, opcode: number) { /*${pattern}*/ ${fnBody} cpu.cycles++; @@ -54,6 +56,24 @@ for (const line of input.split('\n')) { } } +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, { -- cgit v1.2.3