1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-08 23:29:42 +00:00

merged all debug stuff into BaseDebugPlatform

This commit is contained in:
Steven Hugg 2019-08-26 18:14:50 -04:00
parent 80c02a98d5
commit 7f37644fc6
3 changed files with 87 additions and 259 deletions

View File

@ -18,7 +18,6 @@ export interface OpcodeMetadata {
export interface CpuState {
PC:number;
EPC?:number; // effective PC (for bankswitching)
T?:number; // TODO: remove in favor of 'stable'
o?:number;/*opcode*/
SP?:number
/*
@ -30,7 +29,6 @@ export interface EmuState {
b?:Uint8Array|number[], // RAM (TODO: not for vcs, support Uint8Array)
ram?:Uint8Array,
o?:{}, // verilog
T?:number, // verilog
};
export interface EmuControlsState {
}
@ -266,6 +264,17 @@ export abstract class BaseDebugPlatform extends BasePlatform {
preFrame() {
}
postFrame() {
if (this.debugCallback) {
if (this.debugBreakState) {
// reload debug state at end of frame after breakpoint
this.loadState(this.debugBreakState);
} else {
// save state every frame and rewind debug clocks
this.debugSavedState = this.saveState();
this.debugTargetClock -= this.debugClock;
this.debugClock = 0;
}
}
}
pollControls() {
}
@ -276,6 +285,76 @@ export abstract class BaseDebugPlatform extends BasePlatform {
this.advance(novideo);
this.postFrame();
}
// default debugging
abstract getSP() : number;
abstract getPC() : number;
abstract isStable() : boolean;
evalDebugCondition() {
if (this.debugCallback && !this.debugBreakState) {
this.debugCallback();
}
}
wasBreakpointHit() : boolean {
return this.debugBreakState != null;
}
breakpointHit(targetClock : number) {
console.log(this.debugTargetClock, targetClock, this.debugClock, this.isStable());
this.debugTargetClock = targetClock;
this.debugBreakState = this.saveState();
console.log("Breakpoint at clk", this.debugClock, "PC", this.debugBreakState.c.PC.toString(16));
this.pause();
if (this.onBreakpointHit) {
this.onBreakpointHit(this.debugBreakState);
}
}
runEval(evalfunc : DebugEvalCondition) {
this.setDebugCondition( () => {
if (++this.debugClock >= this.debugTargetClock && this.isStable()) {
var cpuState = this.getCPUState();
if (evalfunc(cpuState)) {
this.breakpointHit(this.debugClock);
return true;
} else {
return false;
}
}
});
}
runUntilReturn() {
var SP0 = this.getSP();
this.runEval( (c:CpuState) : boolean => {
return c.SP > SP0;
});
}
runToFrameClock(clock : number) : void {
this.restartDebugging();
this.debugTargetClock = clock;
this.runEval(() : boolean => { return true; });
}
step() {
this.runToFrameClock(this.debugClock+1);
}
stepBack() {
var prevState;
var prevClock;
var clock0 = this.debugTargetClock;
this.restartDebugging();
this.debugTargetClock = clock0 - 25; // TODO: depends on CPU
this.runEval( (c:CpuState) : boolean => {
if (this.debugClock < clock0) {
prevState = this.saveState();
prevClock = this.debugClock;
return false;
} else {
if (prevState) {
this.loadState(prevState);
this.debugClock = prevClock;
}
return true;
}
});
}
}
////// 6502
@ -299,93 +378,9 @@ export abstract class Base6502Platform extends BaseDebugPlatform {
debugPCDelta = -1;
fixPC(c) { c.PC = (c.PC + this.debugPCDelta) & 0xffff; return c; }
unfixPC(c) { c.PC = (c.PC - this.debugPCDelta) & 0xffff; return c;}
evalDebugCondition() {
if (this.debugCallback && !this.debugBreakState) {
this.debugCallback();
}
}
postFrame() {
if (this.debugCallback) {
if (this.debugBreakState) {
// reload debug state at end of frame after breakpoint
this.loadState(this.debugBreakState);
} else {
// save state every frame and rewind debug clocks
this.debugSavedState = this.saveState();
this.debugTargetClock -= this.debugClock;
this.debugClock = 0;
}
}
}
breakpointHit(targetClock : number) {
this.debugTargetClock = targetClock;
this.debugBreakState = this.saveState();
console.log("Breakpoint at clk", this.debugClock, "PC", this.debugBreakState.c.PC.toString(16));
this.pause();
if (this.onBreakpointHit) {
this.onBreakpointHit(this.debugBreakState);
}
}
runEval(evalfunc : DebugEvalCondition) {
this.setDebugCondition( () => {
if (this.debugClock++ > this.debugTargetClock) {
var cpuState = this.getCPUState();
if (evalfunc(cpuState)) {
this.breakpointHit(this.debugClock-1);
return true;
} else {
return false;
}
}
});
}
runToFrameClock?(clock : number) : void {
this.restartDebugging();
this.debugTargetClock = clock;
this.setDebugCondition( () => {
if (this.debugClock++ > this.debugTargetClock) {
this.breakpointHit(this.debugClock-1);
return true;
}
});
}
step() {
var previousPC = -1;
this.setDebugCondition( () => {
//console.log(this.debugClock, this.debugTargetClock, this.getCPUState().PC, this.getCPUState());
if (this.debugClock++ >= this.debugTargetClock) {
var thisState = this.getCPUState();
if (previousPC < 0) {
previousPC = thisState.PC;
} else {
// doesn't work w/ endless loops
if (thisState.PC != previousPC && thisState.T == 0) {
this.breakpointHit(this.debugClock-1);
return true;
}
}
}
return false;
});
}
stepBack() {
var prevState;
var prevClock;
this.setDebugCondition( () => {
if (this.debugClock++ >= this.debugTargetClock && prevState) {
this.loadState(prevState);
this.breakpointHit(prevClock-1);
return true;
} else if (this.debugClock > this.debugTargetClock-10 && this.debugClock <= this.debugTargetClock+this.debugPCDelta) { // TODO: why this works?
if (this.getCPUState().T == 0) {
prevState = this.saveState();
prevClock = this.debugClock;
}
}
return false;
});
}
getSP() { return this.getCPUState().SP };
getPC() { return this.getCPUState().PC };
isStable() { return !this.getCPUState()['T']; }
newCPU(membus : MemoryBus) {
var cpu = new jt.M6502();
@ -401,19 +396,6 @@ export abstract class Base6502Platform extends BaseDebugPlatform {
return (this.readAddress(0xfffc) | (this.readAddress(0xfffd) << 8)) & 0xffff;
}
runUntilReturn() {
var depth = 1;
this.runEval( (c:CpuState) => {
if (depth <= 0 && c.T == 0)
return true;
if (c.o == 0x20)
depth++;
else if (c.o == 0x60 || c.o == 0x40)
--depth;
return false;
});
}
disassemble(pc:number, read:(addr:number)=>number) : DisasmLine {
return disassemble6502(pc, read(pc), read(pc+1), read(pc+2));
}
@ -503,6 +485,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
getPC() { return this._cpu.getPC(); }
getSP() { return this._cpu.getSP(); }
isStable() { return true; }
// TODO: refactor other parts into here
runCPU(cpu, cycles:number) {
@ -524,89 +507,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
}
return n;
}
postFrame() {
if (this.debugCallback) {
if (this.debugBreakState) {
// if breakpoint, reload debug state after frame
this.loadState(this.debugBreakState);
} else {
// reset debug target clocks
this.debugSavedState = this.saveState();
if (this.debugTargetClock > 0)
this.debugTargetClock -= this.debugSavedState.c.T;
this.debugSavedState.c.T = 0;
this.loadState(this.debugSavedState);
}
}
}
breakpointHit(targetClock : number) {
this.debugTargetClock = targetClock;
this.debugBreakState = this.saveState();
console.log("Breakpoint at clk", this.debugBreakState.c.T, "PC", this.debugBreakState.c.PC.toString(16));
this.pause();
if (this.onBreakpointHit) {
this.onBreakpointHit(this.debugBreakState);
}
}
wasBreakpointHit() : boolean {
return this.debugBreakState != null;
}
// TODO: lower bound of clock value
step() {
this.setDebugCondition( () => {
var cpuState = this.getCPUState();
if (cpuState.T > this.debugTargetClock) {
this.breakpointHit(cpuState.T);
return true;
}
return false;
});
}
stepBack() {
var prevState;
var prevClock;
this.setDebugCondition( () => {
var cpuState = this.getCPUState();
var debugClock = cpuState.T;
if (debugClock >= this.debugTargetClock && prevState) {
this.loadState(prevState);
this.breakpointHit(prevClock);
return true;
} else if (debugClock > this.debugTargetClock-20 && debugClock < this.debugTargetClock) {
prevState = this.saveState();
prevClock = debugClock;
}
return false;
});
}
runEval(evalfunc : DebugEvalCondition) {
this.setDebugCondition( () => {
var cpuState = this.getCPUState();
if (cpuState.T > this.debugTargetClock) {
if (evalfunc(cpuState)) {
this.breakpointHit(cpuState.T);
return true;
}
}
return false;
});
}
runUntilReturn() {
var depth = 1;
this.runEval( (c) => {
if (depth <= 0)
return true;
var op = this.readAddress(c.PC);
if (op == 0xcd) // CALL
depth++;
else if (op == 0xc0 || op == 0xc8 || op == 0xc9 || op == 0xd0) // RET (TODO?)
--depth;
return false;
});
}
runToVsync() {
this.runEval((c) => { return c['intp']; });
}
getToolForFilename = getToolForFilename_z80;
getDefaultExtension() { return ".c"; };
// TODO: Z80 opcode metadata
@ -670,21 +571,6 @@ export abstract class Base6809Platform extends BaseZ80Platform {
getPC() { return this._cpu.PC; }
getSP() { return this._cpu.SP; }
runUntilReturn() {
var depth = 1;
this.runEval((c:CpuState) => {
if (depth <= 0)
return true;
var op = this.readAddress(c.PC);
// TODO: 6809 opcodes
if (op == 0x9d || op == 0xad || op == 0xbd) // CALL
depth++;
else if (op == 0x3b || op == 0x39) // RET
--depth;
return false;
});
}
cpuStateToLongString(c:CpuState) {
return cpuStateToLongString_6809(c);
}
@ -1091,6 +977,7 @@ export abstract class BaseMachinePlatform<T extends Machine> extends BaseDebugPl
saveState() { return this.machine.saveState(); }
getSP() { return this.machine.cpu.getSP(); }
getPC() { return this.machine.cpu.getPC(); }
isStable() { return this.machine.cpu.isStable(); }
getCPUState() { return this.machine.cpu.saveState(); }
loadControlsState(s) { this.machine.loadControlsState(s); }
saveControlsState() { return this.machine.saveControlsState(); }
@ -1162,63 +1049,6 @@ export abstract class BaseMachinePlatform<T extends Machine> extends BaseDebugPl
}
// TODO: reset target clock counter
breakpointHit(targetClock : number) {
console.log(this.debugTargetClock, targetClock, this.debugClock, this.machine.cpu.isStable());
this.debugTargetClock = targetClock;
this.debugBreakState = this.saveState();
console.log("Breakpoint at clk", this.debugClock, "PC", this.debugBreakState.c.PC.toString(16));
this.pause();
if (this.onBreakpointHit) {
this.onBreakpointHit(this.debugBreakState);
}
}
runEval(evalfunc : DebugEvalCondition) {
this.setDebugCondition( () => {
if (++this.debugClock >= this.debugTargetClock && this.machine.cpu.isStable()) {
var cpuState = this.getCPUState();
if (evalfunc(cpuState)) {
this.breakpointHit(this.debugClock);
return true;
} else {
return false;
}
}
});
}
runUntilReturn() {
var SP0 = this.machine.cpu.getSP();
this.runEval( (c:CpuState) : boolean => {
return c.SP > SP0;
});
}
runToFrameClock(clock : number) : void {
this.restartDebugging();
this.debugTargetClock = clock;
this.runEval(() : boolean => { return true; });
}
step() {
this.runToFrameClock(this.debugClock+1);
}
stepBack() {
var prevState;
var prevClock;
var clock0 = this.debugTargetClock;
this.restartDebugging();
this.debugTargetClock = clock0 - 25; // TODO: depends on CPU
this.runEval( (c:CpuState) : boolean => {
if (this.debugClock < clock0) {
prevState = this.saveState();
prevClock = this.debugClock;
return false;
} else {
if (prevState) {
this.loadState(prevState);
this.debugClock = prevClock;
}
return true;
}
});
}
getRasterScanline() {
return isRaster(this.machine) && this.machine.getRasterY();
}

View File

@ -55,7 +55,6 @@ interface MSXSlot {
export class MSX1 extends BaseZ80VDPBasedMachine {
numVisibleScanlines = 240;
overscan = true;
defaultROMSize = 0x8000;
ram = new Uint8Array(0x10000);

View File

@ -34,7 +34,6 @@ export class SG1000 extends BaseZ80VDPBasedMachine {
numVisibleScanlines = 240;
defaultROMSize = 0xc000;
overscan = true;
ram = new Uint8Array(0x400);
constructor() {