8bitworkshop/gen/chunk-E6C2NBJH.js.map

8 lines
11 KiB
Plaintext

{
"version": 3,
"sources": ["../src/common/analysis.ts"],
"sourcesContent": ["\nimport { hex, byte2signed } from \"./util\";\nimport { Platform } from \"./baseplatform\";\n\nexport interface CodeAnalyzer {\n showLoopTimingForPC(pc:number);\n pc2minclocks : {[key:number]:number};\n pc2maxclocks : {[key:number]:number};\n MAX_CLOCKS : number;\n}\n\n/// VCS TIMING ANALYSIS\n\n// [taken, not taken]\nconst BRANCH_CONSTRAINTS = [\n [{N:0},{N:1}],\n [{N:1},{N:0}],\n [{V:0},{V:1}],\n [{V:1},{V:0}],\n [{C:0},{C:1}],\n [{C:1},{C:0}],\n [{Z:0},{Z:1}],\n [{Z:1},{Z:0}]\n];\n\nfunction constraintEquals(a,b) {\n if (a == null || b == null)\n return null;\n for (var n in a) {\n if (b[n] !== 'undefined')\n return a[n] == b[n];\n }\n for (var n in b) {\n if (a[n] !== 'undefined')\n return a[n] == b[n];\n }\n return null;\n}\n\nabstract class CodeAnalyzer6502 implements CodeAnalyzer {\n pc2minclocks = {};\n pc2maxclocks = {};\n START_CLOCKS : number;\n MAX_CLOCKS : number;\n WRAP_CLOCKS : boolean;\n jsrresult = {};\n platform : Platform;\n MAX_CYCLES : number = 2000;\n \n constructor(platform : Platform) {\n this.platform = platform;\n }\n\n getClockCountsAtPC(pc) {\n var opcode = this.platform.readAddress(pc);\n var meta = this.platform.getOpcodeMetadata(opcode, pc);\n return meta; // minCycles, maxCycles\n }\n\n traceInstructions(pc:number, minclocks:number, maxclocks:number, subaddr:number, constraints) {\n if (this.WRAP_CLOCKS) {\n if (this.pc2minclocks[pc] !== undefined)\n minclocks = Math.min(minclocks, this.pc2minclocks[pc]);\n if (this.pc2maxclocks[pc] !== undefined)\n maxclocks = Math.max(maxclocks, this.pc2maxclocks[pc]);\n }\n //console.log(\"trace\", hex(pc), minclocks, maxclocks);\n if (!constraints) constraints = {};\n var modified = true;\n var abort = false;\n for (var i=0; modified && !abort; i++) {\n if (i >= this.MAX_CYCLES) {\n console.log(\"too many cycles @\", hex(pc), \"routine\", hex(subaddr));\n break;\n }\n modified = false;\n if (this.WRAP_CLOCKS && minclocks >= this.MAX_CLOCKS) {\n // wrap clocks\n minclocks = minclocks % this.MAX_CLOCKS;\n maxclocks = maxclocks % this.MAX_CLOCKS;\n } else {\n // truncate clocks\n minclocks = Math.min(this.MAX_CLOCKS, minclocks);\n maxclocks = Math.min(this.MAX_CLOCKS, maxclocks);\n }\n var meta = this.getClockCountsAtPC(pc);\n var lob = this.platform.readAddress(pc+1);\n var hib = this.platform.readAddress(pc+2);\n var addr = lob + (hib << 8);\n var pc0 = pc;\n if (!(minclocks >= this.pc2minclocks[pc0])) {\n this.pc2minclocks[pc0] = minclocks;\n modified = true;\n }\n if (!(maxclocks <= this.pc2maxclocks[pc0])) {\n this.pc2maxclocks[pc0] = maxclocks;\n modified = true;\n }\n //console.log(hex(pc),minclocks,maxclocks,modified,meta,constraints);\n if (!meta.insnlength) {\n console.log(\"Illegal instruction!\", hex(pc), hex(meta.opcode), meta);\n break;\n }\n pc += meta.insnlength;\n var oldconstraints = constraints;\n constraints = null;\n // TODO: if jump to zero-page, maybe assume RTS?\n switch (meta.opcode) {\n case 0x19: case 0x1d:\n case 0x39: case 0x3d:\n case 0x59: case 0x5d:\n case 0x79: case 0x7d:\n case 0x99: case 0x9d:\n case 0xa9: case 0xad:\n case 0xb9: case 0xbd: case 0xbc: case 0xbe:\n case 0xd9: case 0xdd:\n case 0xf9: case 0xfd:\n if (lob == 0)\n meta.maxCycles -= 1; // no page boundary crossed\n break;\n // TODO: only VCS\n case 0x85:\n if (lob == 0x2) { // STA WSYNC\n minclocks = maxclocks = 0;\n meta.minCycles = meta.maxCycles = 0;\n }\n break;\n // TODO: only NES (sprite 0 poll)\n case 0x2c:\n if (lob == 0x02 && hib == 0x20) { // BIT $2002\n minclocks = 0;\n maxclocks = 4; // uncertainty b/c of assumed branch poll\n meta.minCycles = meta.maxCycles = 0;\n }\n break;\n // TODO: only Apple2 (vapor lock)\n /*\n case 0xad:\n if (lob == 0x61 && hib == 0xc0) { // LDA $C061\n minclocks = 0;\n maxclocks = 4; // uncertainty?\n meta.minCycles = meta.maxCycles = 0;\n }\n break;\n */\n case 0x20: // JSR\n // TODO: handle bare RTS case\n minclocks += meta.minCycles;\n maxclocks += meta.maxCycles;\n this.traceInstructions(addr, minclocks, maxclocks, addr, constraints);\n var result = this.jsrresult[addr];\n if (result) {\n minclocks = result.minclocks;\n maxclocks = result.maxclocks;\n } else {\n console.log(\"No JSR result!\", hex(pc), hex(addr));\n minclocks = maxclocks;\n //return;\n }\n break;\n case 0x4c: // JMP\n pc = addr; // TODO: make sure in ROM space\n break;\n case 0x40: // RTI\n abort = true;\n break;\n case 0x60: // RTS\n if (subaddr) { // TODO: 0 doesn't work\n // TODO: combine with previous result\n var result = this.jsrresult[subaddr];\n if (!result) {\n result = {minclocks:minclocks, maxclocks:maxclocks};\n } else {\n result = {\n minclocks:Math.min(minclocks,result.minclocks),\n maxclocks:Math.max(maxclocks,result.maxclocks)\n }\n }\n this.jsrresult[subaddr] = result;\n console.log(\"RTS\", hex(pc), hex(subaddr), this.jsrresult[subaddr]);\n }\n return;\n case 0x10: case 0x30: // branch\n case 0x50: case 0x70:\n case 0x90: case 0xB0:\n case 0xD0: case 0xF0:\n var newpc = pc + byte2signed(lob);\n var crosspage = (pc>>8) != (newpc>>8);\n if (!crosspage) meta.maxCycles--;\n // TODO: other instructions might modify flags too\n var cons = BRANCH_CONSTRAINTS[Math.floor((meta.opcode-0x10)/0x20)];\n var cons0 = constraintEquals(oldconstraints, cons[0]);\n var cons1 = constraintEquals(oldconstraints, cons[1]);\n // recursively trace the taken branch\n if (true || cons0 !== false) { // TODO?\n this.traceInstructions(newpc, minclocks+meta.maxCycles, maxclocks+meta.maxCycles, subaddr, cons[0]);\n }\n // abort if we will always take the branch\n if (cons1 === false) {\n console.log(\"branch always taken\", hex(pc), oldconstraints, cons[1]);\n abort = true;\n }\n constraints = cons[1]; // not taken\n meta.maxCycles = meta.minCycles; // branch not taken, no extra clock(s)\n break;\n case 0x6c:\n console.log(\"Instruction not supported!\", hex(pc), hex(meta.opcode), meta); // TODO\n return;\n }\n // add min/max instruction time to min/max clocks bound\n minclocks += meta.minCycles;\n maxclocks += meta.maxCycles;\n }\n }\n\n showLoopTimingForPC(pc:number) {\n this.pc2minclocks = {};\n this.pc2maxclocks = {};\n this.jsrresult = {};\n // recurse through all traces\n this.traceInstructions(pc | this.platform.getOriginPC(), this.START_CLOCKS, this.MAX_CLOCKS, 0, {});\n }\n}\n\n// 76 cycles * 2 (support two scanline kernels)\nexport class CodeAnalyzer_vcs extends CodeAnalyzer6502 {\n constructor(platform : Platform) {\n super(platform);\n this.MAX_CLOCKS = this.START_CLOCKS = 76*4; // 4 scanlines\n this.WRAP_CLOCKS = false;\n }\n}\n\n// https://wiki.nesdev.com/w/index.php/PPU_rendering#Line-by-line_timing\n// TODO: sprite 0 hit, CPU stalls\nexport class CodeAnalyzer_nes extends CodeAnalyzer6502 {\n constructor(platform : Platform) {\n super(platform);\n this.MAX_CLOCKS = 114; // 341 clocks for 3 scanlines\n this.START_CLOCKS = 0;\n this.WRAP_CLOCKS = true;\n }\n}\n\nexport class CodeAnalyzer_apple2 extends CodeAnalyzer6502 {\n constructor(platform : Platform) {\n super(platform);\n this.MAX_CLOCKS = 65;\n this.START_CLOCKS = 0;\n this.WRAP_CLOCKS = true;\n }\n}\n\n"],
"mappings": "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",
"names": []
}