// chip-specific support functions // // may override function definitions made previously chipname='z80'; // DMB: Update this grChipSize=7000; ngnd = nodenames['vss']; npwr = nodenames['vcc']; nodenamereset = '_reset'; presetLogLists=[ ['cycle',], ['ab','db','_m1','_rd','_wr','_mreq','_iorq','pc'], ['af', 'bc', 'de', 'hl', 'ix', 'iy', 'sp'], ['State'], ['_int','_nmi',nodenamereset], ]; function setupTransistors(){ for(i in transdefs){ var tdef = transdefs[i]; var name = tdef[0]; var gate = tdef[1]; var c1 = tdef[2]; var c2 = tdef[3]; var bb = tdef[4]; if(tdef[6]) // just ignore all the 'weak' transistors for now continue; if(c1==ngnd) {c1=c2;c2=ngnd;} if(c1==npwr) {c1=c2;c2=npwr;} var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2, bb: bb}; nodes[gate].gates.push(trans); nodes[c1].c1c2s.push(trans); nodes[c2].c1c2s.push(trans); transistors[name] = trans; } } // simulate a single clock phase with no update to graphics or trace function halfStep(){ var clk = isNodeHigh(nodenames['clk']); eval(clockTriggers[cycle]); if (clk) {setLow('clk'); } else {setHigh('clk'); } // DMB: It's almost certainly wrong to execute the on both clock edges handleBusRead(); handleBusWrite; } function goUntilSyncOrWrite(){ halfStep(); cycle++; while( !isNodeHigh(nodenames['clk']) || ( isNodeHigh(nodenames['_m1']) && isNodeHigh(nodenames['_wr']) ) ) { halfStep(); cycle++; } chipStatus(); } function initChip(){ var start = now(); for(var nn in nodes) { nodes[nn].state = false; nodes[nn].float = true; } nodes[ngnd].state = false; nodes[ngnd].float = false; nodes[npwr].state = true; nodes[npwr].float = false; for(var tn in transistors) transistors[tn].on = false; setLow(nodenamereset); setLow('clk'); setHigh('_busrq'); setHigh('_int'); setHigh('_nmi'); setHigh('_wait'); recalcNodeList(allNodes()); // DMB: Not sure why the 6800 sim did something like this //for(var i=0;i<8;i++){ // setHigh('clk'); // setLow('clk'); //} for(var i=0;i<31;i++){halfStep();} // avoid updating graphics and trace buffer before user code setHigh(nodenamereset); refresh(); cycle = 0; trace = Array(); if(typeof expertMode != "undefined") updateLogList(); chipStatus(); if(ctrace)console.log('initChip done after', now()-start); } function handleBusRead(){ if(!isNodeHigh(nodenames['_rd'])){ var a = readAddressBus(); var d = eval(readTriggers[a]); if(d == undefined) d = mRead(readAddressBus()); if(!isNodeHigh(nodenames['_m1'])) eval(fetchTriggers[d]); writeDataBus(d); } } function handleBusWrite(){ if(!isNodeHigh(nodenames['_wr'])){ var a = readAddressBus(); var d = readDataBus(); eval(writeTriggers[a]); mWrite(a,d); if(a<0x200) setCellValue(a,d); } } function readA(){return 0xFF ^ readBits('reg_a', 8);} function readF(){return 0xFF ^ readBits('reg_f', 8);} function readB(){return 0xFF ^ readBits('reg_b', 8);} function readC(){return 0xFF ^ readBits('reg_c', 8);} function readD(){return 0xFF ^ readBits('reg_d', 8);} function readE(){return 0xFF ^ readBits('reg_e', 8);} function readH(){return 0xFF ^ readBits('reg_h', 8);} function readL(){return 0xFF ^ readBits('reg_l', 8);} function readIX(){return 0xFFFF ^ ((readBits('reg_ixh', 8)<<8) + readBits('reg_ixl', 8));} function readIY(){return 0xFFFF ^ ((readBits('reg_iyh', 8)<<8) + readBits('reg_iyl', 8));} function readSP(){return 0xFFFF ^ ((readBits('reg_sph', 8)<<8) + readBits('reg_spl', 8));} function readPC(){return 0xFFFF ^ ((readBits('reg_pch', 8)<<8) + readBits('reg_pcl', 8));} function readPCL(){return 0xFF ^ readBits('reg_pcl', 8);} function readPCH(){return 0xFF ^ readBits('reg_pch', 8);} // The 6800 state control is something like a branching shift register // ... but not quite like that TCStates=[ "m1", "m2", "m3", "m4", "m5", "t1", "t2", "t3", "t4", "t5", "t6", ]; function listActiveTCStates() { var s=[]; for(var i=0;i>1; if(busname=='af') return busToHexInv('reg_a') + busToHexInv('reg_f'); if(busname=='bc') return busToHexInv('reg_b') + busToHexInv('reg_c'); if(busname=='de') return busToHexInv('reg_d') + busToHexInv('reg_e'); if(busname=='hl') return busToHexInv('reg_h') + busToHexInv('reg_l'); if(busname=='pc') return busToHexInv('reg_pch') + busToHexInv('reg_pcl'); if(busname=='sp') return busToHexInv('reg_sph') + busToHexInv('reg_spl'); if(busname=='ix') return busToHexInv('reg_ixh') + busToHexInv('reg_ixl'); if(busname=='iy') return busToHexInv('reg_iyh') + busToHexInv('reg_iyl'); if(busname=='State') return listActiveTCStates(); // DMB: TODO // if(busname=='Execute') // return disassemblytoHTML(readBits('ir',8)); // if(busname=='Fetch') // return !isNodeHigh(nodenames['_m1'])?disassemblytoHTML(readDataBus()):""; // if(busname=='plaOutputs') // // PLA outputs are mostly ^op- but some have a prefix too // // - we'll allow the x and xx prefix but ignore the # // return listActiveSignals('^([x]?x-)?op-'); // if(busname=='DPControl') // return listActiveSignals('^dpc[0-9]+_'); if(busname[0]=="-"){ // invert the value of the bus for display var value=busToHex(busname.slice(1)) if(typeof value != "undefined") return value.replace(/./g,function(x){return (15-parseInt(x,16)).toString(16)}); else return undefined;; } else { return busToHex(busname); } } function chipStatus(){ var ab = readAddressBus(); var machine1 = ' halfcyc:' + cycle + ' clk:' + readBit('clk') + ' AB:' + hexWord(ab) + ' D:' + hexByte(readDataBus()) + ' M1:' + readBit('_m1') + ' RD:' + readBit('_rd') + ' WR:' + readBit('_wr') + ' MREQ:' + readBit('_mreq') + ' IORQ:' + readBit('_iorq'); var machine2 = ' PC:' + hexWord(readPC()) + ' A:' + hexByte(readA()) + ' F:' + hexByte(readF()) + ' B:' + hexByte(readB()) + ' C:' + hexByte(readC()) + ' D:' + hexByte(readD()) + ' E:' + hexByte(readE()) + ' H:' + hexByte(readH()) + ' L:' + hexByte(readL()) + ' IX:' + hexWord(readIX()) + ' IY:' + hexWord(readIY()) + ' SP:' + hexWord(readSP()); var machine3 = 'State: ' + busToString('State') + 'Hz: ' + estimatedHz().toFixed(1); if(typeof expertMode != "undefined") { machine3 += ' Exec: ' + busToString('Execute'); // no T-state info for 6800 yet if(!isNodeHigh(nodenames['_m1'])) machine3 += ' (Fetch: ' + busToString('Fetch') + ')'; if(goldenChecksum != undefined) machine3 += " Chk:" + traceChecksum + ((traceChecksum==goldenChecksum)?" OK":" no match"); } setStatus(machine1, machine2, machine3); if (logThese.length>1) { updateLogbox(logThese); } selectCell(ab); } // DMB: TODO var disassembly={ 0x00: "nop", };