Fixed 8080 bug exposed by the exerciser (but still a long way from 100% passing)
This commit is contained in:
parent
94c1ada877
commit
2a447fa6ae
8 changed files with 1974 additions and 13 deletions
|
|
@ -628,7 +628,7 @@ CPUDef.opSTC = function()
|
|||
CPUDef.opDADSP = function()
|
||||
{
|
||||
var w;
|
||||
this.setSP(w = this.getHL() + this.getSP());
|
||||
this.setHL(w = this.getHL() + this.getSP());
|
||||
this.resultZeroCarry = (this.resultZeroCarry & 0xff) | ((w >> 8) & 0x100);
|
||||
this.nStepCycles -= 10;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3707,6 +3707,7 @@ if (DEBUGGER) {
|
|||
sMsg = "halting";
|
||||
this.stopCPU();
|
||||
} else {
|
||||
if (this.isBusy(true)) return;
|
||||
sMsg = "already halted";
|
||||
}
|
||||
if (!fQuiet) this.println(sMsg);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,29 @@ function ROM(parmsROM)
|
|||
|
||||
Component.subclass(ROM);
|
||||
|
||||
ROM.CPM_VECTORS = [0x0000, 0x0005];
|
||||
ROM.CPM = {
|
||||
BIOS: {
|
||||
VECTOR: 0x0000
|
||||
},
|
||||
BDOS: {
|
||||
VECTOR: 0x0005,
|
||||
FUNC: { // function number (specified in regC)
|
||||
RESET: 0x00,
|
||||
CON_READ: 0x01, // output: A = L = ASCII character
|
||||
CON_WRITE: 0x02, // input: E = ASCII character
|
||||
AUX_READ: 0x03, // output: A = L = ASCII character
|
||||
AUX_WRITE: 0x04, // input: E = ASCII character
|
||||
PRN_WRITE: 0x05, // input: E = ASCII character
|
||||
MEM_SIZE: 0x06, // output: base address of CCP (Console Command Processor), but which register? (perhaps moot if this was CP/M 1.3 only...)
|
||||
CON_IO: 0x06, // input: E = ASCII character (or 0xFF to return ASCII character in A)
|
||||
GET_IOBYTE: 0x07,
|
||||
SET_IOBYTE: 0x08,
|
||||
STR_WRITE: 0x09 // input: DE = address of string
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ROM.CPM.VECTORS = [ROM.CPM.BIOS.VECTOR, ROM.CPM.BDOS.VECTOR];
|
||||
|
||||
/*
|
||||
* NOTE: There's currently no need for this component to have a reset() function, since
|
||||
|
|
@ -344,12 +366,14 @@ ROM.prototype.addROM = function(addr)
|
|||
* (namely, 0x0000, which is the CP/M reset vector, and 0x0005, which is the CP/M system call vector) and
|
||||
* then telling the CPU to call us whenever a HLT occurs, so we can check PC for one of these addresses.
|
||||
*/
|
||||
for (i = 0; i < ROM.CPM_VECTORS.length; i++) {
|
||||
this.bus.setByteDirect(ROM.CPM_VECTORS[i], CPUDef.OPCODE.HLT);
|
||||
for (i = 0; i < ROM.CPM.VECTORS.length; i++) {
|
||||
this.bus.setByteDirect(ROM.CPM.VECTORS[i], CPUDef.OPCODE.HLT);
|
||||
}
|
||||
|
||||
this.cpu.addHaltCheck(function(rom) {
|
||||
return function(addr) {rom.checkCPMVector(addr)};
|
||||
return function(addr) {
|
||||
return rom.checkCPMVector(addr)
|
||||
};
|
||||
}(this));
|
||||
|
||||
this.cpu.setReset(addr);
|
||||
|
|
@ -371,18 +395,88 @@ ROM.prototype.addROM = function(addr)
|
|||
*/
|
||||
ROM.prototype.checkCPMVector = function(addr)
|
||||
{
|
||||
var i = ROM.CPM_VECTORS.indexOf(addr);
|
||||
var i = ROM.CPM.VECTORS.indexOf(addr);
|
||||
if (i >= 0) {
|
||||
if (this.dbg) {
|
||||
this.println("CP/M vector " + str.toHexWord(addr));
|
||||
this.cpu.setPC(addr); // this is purely for the Debugger's benefit, to show the HLT
|
||||
this.dbg.stopCPU();
|
||||
var fCPM = false;
|
||||
var cpu = this.cpu;
|
||||
var dbg = this.dbg;
|
||||
if (addr == ROM.CPM.BDOS.VECTOR) {
|
||||
fCPM = true;
|
||||
switch(cpu.regC) {
|
||||
case ROM.CPM.BDOS.FUNC.CON_WRITE:
|
||||
this.writeCPMString(this.getCPMChar(cpu.regE));
|
||||
break;
|
||||
case ROM.CPM.BDOS.FUNC.STR_WRITE:
|
||||
this.writeCPMString(this.getCPMString(cpu.getDE(), '$'));
|
||||
break;
|
||||
default:
|
||||
fCPM = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fCPM) {
|
||||
CPUDef.opRET.call(cpu); // for recognized calls, automatically return
|
||||
}
|
||||
else if (dbg) {
|
||||
this.println("\nCP/M vector " + str.toHexWord(addr));
|
||||
cpu.setPC(addr); // this is purely for the Debugger's benefit, to show the HLT
|
||||
dbg.stopCPU();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* getCPMChar(ch)
|
||||
*
|
||||
* @this {ROM}
|
||||
* @param {number} ch
|
||||
* @return {string}
|
||||
*/
|
||||
ROM.prototype.getCPMChar = function(ch)
|
||||
{
|
||||
return String.fromCharCode(ch);
|
||||
};
|
||||
|
||||
/**
|
||||
* getCPMString(addr, chEnd)
|
||||
*
|
||||
* @this {ROM}
|
||||
* @param {number} addr (of a string)
|
||||
* @param {string|number} [chEnd] (terminating character, default is 0)
|
||||
* @return {string}
|
||||
*/
|
||||
ROM.prototype.getCPMString = function(addr, chEnd)
|
||||
{
|
||||
var s = "";
|
||||
var cchMax = 255;
|
||||
var bEnd = chEnd && chEnd.length && chEnd.charCodeAt(0) || chEnd || 0;
|
||||
while (cchMax--) {
|
||||
var b = this.cpu.getByte(addr++);
|
||||
if (b == bEnd) break;
|
||||
s += String.fromCharCode(b);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* writeCPMString(s)
|
||||
*
|
||||
* @this {ROM}
|
||||
* @param {string} s
|
||||
*/
|
||||
ROM.prototype.writeCPMString = function(s)
|
||||
{
|
||||
s = s.replace(/\r/g, '');
|
||||
if (this.controlPrint) {
|
||||
this.controlPrint.value += s;
|
||||
this.controlPrint.scrollTop = this.controlPrint.scrollHeight;
|
||||
}
|
||||
this.log(s);
|
||||
};
|
||||
|
||||
/**
|
||||
* cloneROM(addr)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6663,6 +6663,7 @@ if (DEBUGGER) {
|
|||
sMsg = "halting";
|
||||
this.stopCPU();
|
||||
} else {
|
||||
if (this.isBusy(true)) return;
|
||||
sMsg = "already halted";
|
||||
}
|
||||
if (!fQuiet) this.println(sMsg);
|
||||
|
|
|
|||
Loading…
Reference in a new issue