Support for 80386 register dumps
This commit is contained in:
parent
eb196c3048
commit
5303d2fe20
12 changed files with 384 additions and 124 deletions
|
|
@ -23,10 +23,14 @@ I'm still on the lookout for a "Version 1" motherboard from 1986, so that I can
|
|||
|
||||
filedump --file=109592-001.hex --merge=109591-001.hex --output=1988-01-28.json
|
||||
|
||||
For a human-readable dump, use this command:
|
||||
For a more human-readable dump, use this command:
|
||||
|
||||
filedump --file=109592-001.hex --merge=109591-001.hex --comments
|
||||
|
||||
And for those who prefer binary files, the FileDump API can be used to recreate raw binary data from JSON data:
|
||||
|
||||
> [http://www.pcjs.org/api/v1/dump?file=http://www.pcjs.org/devices/pc/bios/compaq/deskpro386/1988-01-28.json&format=rom](http://www.pcjs.org/api/v1/dump?file=http://www.pcjs.org/devices/pc/bios/compaq/deskpro386/1988-01-28.json&format=rom)
|
||||
|
||||
The *.hex* files were produced by running [eeprom_read](http://github.com/phooky/PROM/blob/master/tools/eeprom_read/eeprom_read.pde)
|
||||
on a [chipKIT Uno32](http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,892,893&Prod=CHIPKIT-UNO32) Arduino-compatible
|
||||
prototyping board, and capturing the serial port output on my MacBook Pro -- as outlined in
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ C1PROM.prototype.copyImage = function()
|
|||
this.setError("ROM image size (" + str.toHexWord(cbImage) + ") does not match component-specified size (" + str.toHexWord(this.cbROM) + ")");
|
||||
return;
|
||||
}
|
||||
if (DEBUG) this.log("copyImage(): copying ROM to " + str.toHexAddr(this.offROM) + " (0x" + str.toHexWord(cbImage) + " bytes)");
|
||||
if (DEBUG) this.log("copyImage(): copying ROM to 0x" + str.toHexWord(this.offROM) + " (0x" + str.toHexWord(cbImage) + " bytes)");
|
||||
for (var i=0; i < cbImage; i++) {
|
||||
this.abMem[this.offROM + i] = this.abImage[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,8 @@ FileDump.prototype.loadFile = function(sFile, iStart, nSkip, done)
|
|||
{
|
||||
var obj = this;
|
||||
|
||||
var options = {encoding: str.endsWith(sFile, ".hex")? "utf8" : null};
|
||||
var sExt = str.getExtension(sFile);
|
||||
var options = {encoding: sExt == DumpAPI.FORMAT.JSON || sExt == DumpAPI.FORMAT.HEX? "utf8" : null};
|
||||
|
||||
var sFilePath = net.isRemote(sFile)? sFile : path.join(this.sServerRoot, sFile);
|
||||
|
||||
|
|
@ -277,22 +278,46 @@ FileDump.prototype.loadFile = function(sFile, iStart, nSkip, done)
|
|||
*/
|
||||
FileDump.prototype.setData = function(buf, iStart, nSkip)
|
||||
{
|
||||
var b, i, s;
|
||||
var b, i, j, s;
|
||||
if (typeof buf == "string") {
|
||||
/*
|
||||
* We've received a string that must be converted to a Buffer before we continue.
|
||||
*
|
||||
* At the moment, the only string-based file format we support is a ".hex" file,
|
||||
* which contains a series of byte values encoded in hex, separated by whitespace.
|
||||
*/
|
||||
var ab = [];
|
||||
var as = buf.split(/\s+/);
|
||||
for (i = 0; i < as.length; i++) {
|
||||
s = as[i];
|
||||
if (!s.length) continue;
|
||||
if (isNaN(b = parseInt(s, 16))) break;
|
||||
ab.push(b);
|
||||
if (buf.indexOf('{') >= 0) {
|
||||
/*
|
||||
* Treat the incoming string data as JSON data.
|
||||
*/
|
||||
var json;
|
||||
try {
|
||||
json = JSON.parse(buf);
|
||||
} catch (e) {
|
||||
json = null;
|
||||
}
|
||||
if (json && json.data && json.data.length) {
|
||||
for (i = 0; i < json.data.length; i++) {
|
||||
var dw = json.data[i];
|
||||
for (j = 0; j < 4; j++) {
|
||||
ab.push(dw & 0xff);
|
||||
dw >>>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Treat the incoming string data as HEX (ie, a series of byte values encoded in hex, separated by whitespace)
|
||||
*/
|
||||
var as = buf.split(/\s+/);
|
||||
for (i = 0; i < as.length; i++) {
|
||||
s = as[i];
|
||||
if (!s.length) continue;
|
||||
if (isNaN(b = parseInt(s, 16))) break;
|
||||
ab.push(b);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we didn't recognize the data, then simply return, leaving this.buf undefined.
|
||||
*/
|
||||
if (!ab.length) return;
|
||||
|
||||
buf = new Buffer(ab);
|
||||
}
|
||||
if (!this.buf) {
|
||||
|
|
@ -310,6 +335,16 @@ FileDump.prototype.setData = function(buf, iStart, nSkip)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* getData()
|
||||
*
|
||||
* @this {FileDump}
|
||||
* @return {Buffer|null}
|
||||
*/
|
||||
FileDump.prototype.getData = function()
|
||||
{
|
||||
return this.buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* dumpLine(nIndent, sLine, sComment)
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ var asNonDirectories = [
|
|||
var asExtsPlainText = [
|
||||
"65v",
|
||||
"bas",
|
||||
"hex",
|
||||
"map",
|
||||
"txt"
|
||||
];
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ HTTPAPI.redirect = function(req, res, next)
|
|||
}
|
||||
|
||||
for (sPath in aInternalRedirectPatterns) {
|
||||
var re = new RegExp(sPath);
|
||||
re = new RegExp(sPath);
|
||||
if (re.exec(req.url)) {
|
||||
req.url = req.url.replace(re, aInternalRedirectPatterns[sPath]);
|
||||
break;
|
||||
|
|
@ -757,18 +757,7 @@ HTTPAPI.processDumpAPI = function(req, res)
|
|||
}
|
||||
var file = new FileDump(sFormat, fComments, fDecimal, sServerRoot);
|
||||
file.loadFile(sFile, 0, 0, function(err) {
|
||||
if (!err) {
|
||||
file.convertToJSON(function(err, str) {
|
||||
if (!err) {
|
||||
nResponse = 200;
|
||||
} else {
|
||||
str = err.message;
|
||||
}
|
||||
res.status(nResponse).send(str);
|
||||
});
|
||||
} else {
|
||||
res.status(nResponse).send(err.message);
|
||||
}
|
||||
HTTPAPI.dumpFile(err, file, res);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
|
@ -789,10 +778,10 @@ HTTPAPI.dumpDisk = function(err, disk, res)
|
|||
var nResponse = 400; // default to "Bad Request"
|
||||
var sMIMEType = null;
|
||||
var sAttachment = null;
|
||||
|
||||
if (err) {
|
||||
/*
|
||||
* TODO: Do a better job of mapping the underlying error (eg, err.errno) to
|
||||
* the appropriate HTTP response error.
|
||||
* TODO: Do a better job of mapping the underlying error (eg, err.errno) to an appropriate HTTP response error.
|
||||
*/
|
||||
nResponse = 404;
|
||||
sResponse = err.message;
|
||||
|
|
@ -827,6 +816,63 @@ HTTPAPI.dumpDisk = function(err, disk, res)
|
|||
res.status(nResponse).send(sResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* dumpFile(err, file, res)
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {FileDump} file
|
||||
* @param {Object} res
|
||||
*/
|
||||
HTTPAPI.dumpFile = function(err, file, res)
|
||||
{
|
||||
var sResponse = "";
|
||||
var nResponse = 400; // default to "Bad Request"
|
||||
var sMIMEType = null;
|
||||
var sAttachment = null;
|
||||
|
||||
if (err) {
|
||||
/*
|
||||
* TODO: Do a better job of mapping the underlying error (eg, err.errno) to an appropriate HTTP response error.
|
||||
*/
|
||||
nResponse = 404;
|
||||
sResponse = err.message;
|
||||
} else {
|
||||
if (file.sFormat == DumpAPI.FORMAT.ROM) {
|
||||
// sMIMEType = "application/octet-stream";
|
||||
sMIMEType = "application/x-download";
|
||||
sAttachment = path.basename(file.sFilePath);
|
||||
var i = sAttachment.lastIndexOf('.');
|
||||
if (i > 0) sAttachment = sAttachment.substring(0, i+1) + DumpAPI.FORMAT.ROM;
|
||||
sResponse = file.getData();
|
||||
} else {
|
||||
file.convertToJSON(function(err, str) {
|
||||
if (!err) {
|
||||
nResponse = 200;
|
||||
} else {
|
||||
str = err.message;
|
||||
}
|
||||
res.status(nResponse).send(str);
|
||||
});
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Return a successful response ONLY if the file conversion call returned any data
|
||||
*/
|
||||
if (sResponse) {
|
||||
nResponse = 200;
|
||||
} else {
|
||||
sResponse = "unable to convert file image: " + file.sFilePath;
|
||||
}
|
||||
}
|
||||
if (sMIMEType) {
|
||||
res.set("Content-Type", sMIMEType);
|
||||
}
|
||||
if (sAttachment) {
|
||||
res.set("Content-Disposition", 'attachment; filename="' + sAttachment + '"');
|
||||
}
|
||||
res.status(nResponse).send(sResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* processReportAPI(req, res)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3323,7 +3323,7 @@ ChipSet.prototype.getIRRVector = function(iPIC)
|
|||
|
||||
var nIRQ = pic.nIRQBase + nIRL;
|
||||
if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
|
||||
this.printMessage("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.getIP(), this.cpu.getCS()) + " stack=" + str.toHexAddr(this.cpu.getSP(), this.cpu.getSS()), true);
|
||||
this.printMessage("getIRRVector(): IRQ " + nIRQ + " interrupting @" + this.dbg.hexOffset(this.cpu.getIP(), this.cpu.getCS()) + " stack=" + this.dbg.hexOffset(this.cpu.getSP(), this.cpu.getSS()), true);
|
||||
}
|
||||
if (MAXDEBUG && DEBUGGER) {
|
||||
this.acInterrupts[nIRQ]++;
|
||||
|
|
|
|||
|
|
@ -83,8 +83,11 @@ function Debugger(parmsDbg)
|
|||
this.cInstructions = -1;
|
||||
|
||||
/*
|
||||
* Default number of hex chars in a physical address (ie, for real-mode); updated by initBus().
|
||||
* Default number of hex chars in a register and a physical address (ie, for real-mode);
|
||||
* updated by initBus().
|
||||
*/
|
||||
this.cchReg = 4;
|
||||
this.maskReg = 0xffff;
|
||||
this.cchAddr = 5;
|
||||
|
||||
/*
|
||||
|
|
@ -1186,9 +1189,15 @@ if (DEBUGGER) {
|
|||
this.aaOpDescs[0x0F] = Debugger.aOpDescUndefined;
|
||||
if (this.cpu.model >= X86.MODEL_80286) {
|
||||
this.aaOpDescs[0x0F] = Debugger.aOpDesc0F;
|
||||
if (this.cpu.model >= X86.MODEL_80386) {
|
||||
this.cchReg = 8;
|
||||
this.maskReg = 0xffffffff|0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.selectRegs();
|
||||
|
||||
this.messageDump(Messages.DESC, function onDumpDesc(s) { dbg.dumpDesc(s); });
|
||||
this.messageDump(Messages.TSS, function onDumpTSS(s) { dbg.dumpTSS(s); });
|
||||
this.messageDump(Messages.DOS, function onDumpDOS(s) { dbg.dumpDOS(s); });
|
||||
|
|
@ -1301,6 +1310,43 @@ if (DEBUGGER) {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* selectRegs()
|
||||
*
|
||||
* @this {Debugger}
|
||||
*/
|
||||
Debugger.prototype.selectRegs = function()
|
||||
{
|
||||
if (this.cchReg <= 4) {
|
||||
this.regs = {
|
||||
AX: "AX",
|
||||
BX: "BX",
|
||||
CX: "CX",
|
||||
DX: "DX",
|
||||
SP: "SP",
|
||||
BP: "BP",
|
||||
SI: "SI",
|
||||
DI: "DI",
|
||||
IP: "IP",
|
||||
MS: "MS"
|
||||
}
|
||||
} else {
|
||||
this.regs = {
|
||||
AX: "EAX",
|
||||
BX: "EBX",
|
||||
CX: "ECX",
|
||||
DX: "EDX",
|
||||
SP: "ESP",
|
||||
BP: "EBP",
|
||||
SI: "ESI",
|
||||
DI: "EDI",
|
||||
IP: "EIP",
|
||||
MS: "CR0"
|
||||
}
|
||||
}
|
||||
this.regs.PS = "PS";
|
||||
};
|
||||
|
||||
/**
|
||||
* setFocus()
|
||||
*
|
||||
|
|
@ -1339,7 +1385,7 @@ if (DEBUGGER) {
|
|||
var wPID = this.getShort(aAddr, 2);
|
||||
var wParas = this.getShort(aAddr, 5);
|
||||
if (bSig != 0x4D && bSig != 0x5A) break;
|
||||
this.println(str.toHexAddr(0, seg) + ": '" + String.fromCharCode(bSig) + "' PID=" + str.toHexWord(wPID) + " LEN=" + str.toHexWord(wParas) + ' "' + this.dumpSZ(aAddr, 8) + '"');
|
||||
this.println(this.hexOffset(0, seg) + ": '" + String.fromCharCode(bSig) + "' PID=" + str.toHexWord(wPID) + " LEN=" + str.toHexWord(wParas) + ' "' + this.dumpSZ(aAddr, 8) + '"');
|
||||
seg += 1 + wParas;
|
||||
}
|
||||
};
|
||||
|
|
@ -1593,7 +1639,7 @@ if (DEBUGGER) {
|
|||
Debugger.prototype.message = function(sMessage, fAddress)
|
||||
{
|
||||
if (fAddress) {
|
||||
sMessage += " @" + str.toHexAddr(this.cpu.getIP(), this.cpu.getCS());
|
||||
sMessage += " @" + this.hexOffset(this.cpu.getIP(), this.cpu.getCS());
|
||||
}
|
||||
|
||||
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
|
||||
|
|
@ -1659,7 +1705,7 @@ if (DEBUGGER) {
|
|||
* at the moment. If that changes, then this will have to change as well.
|
||||
*/
|
||||
addr -= 2;
|
||||
this.message("INT 0x" + str.toHexByte(nInt) + ": AH=" + str.toHexByte(AH) + " @" + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.getCS()) + sFunc);
|
||||
this.message("INT 0x" + str.toHexByte(nInt) + ": AH=" + str.toHexByte(AH) + " @" + this.hexOffset(addr - this.cpu.segCS.base, this.cpu.getCS()) + sFunc);
|
||||
}
|
||||
return fMessage;
|
||||
};
|
||||
|
|
@ -1699,7 +1745,7 @@ if (DEBUGGER) {
|
|||
segFrom = this.cpu.getCS();
|
||||
addrFrom -= this.cpu.segCS.base;
|
||||
}
|
||||
this.message(component.idComponent + "." + (bOut != null? "outPort" : "inPort") + "(0x" + str.toHexWord(port) + "," + (name? name : "unknown") + (bOut != null? ",0x" + str.toHexByte(bOut) : "") + ")" + (bIn != null? (": 0x" + str.toHexByte(bIn)) : "") + (addrFrom != null? (" @" + str.toHexAddr(addrFrom, segFrom)) : ""));
|
||||
this.message(component.idComponent + "." + (bOut != null? "outPort" : "inPort") + "(0x" + str.toHexWord(port) + "," + (name? name : "unknown") + (bOut != null? ",0x" + str.toHexByte(bOut) : "") + ")" + (bIn != null? (": 0x" + str.toHexByte(bIn)) : "") + (addrFrom != null? (" @" + this.hexOffset(addrFrom, segFrom)) : ""));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1737,7 +1783,7 @@ if (DEBUGGER) {
|
|||
if (this.traceEnabled !== undefined && this.traceEnabled[prop]) {
|
||||
var trace = Debugger.TRACE[prop];
|
||||
var len = (trace.size >> 2);
|
||||
var s = str.toHexAddr(this.cpu.opLIP - this.cpu.segCS.base, this.cpu.getCS()) + " " + Debugger.asIns[trace.ins] + "(" + str.toHex(dst, len) + "," + str.toHex(src, len) + "," + (flagsIn === null? "-" : str.toHexWord(flagsIn)) + ") " + str.toHex(result, len) + "," + (flagsOut === null? "-" : str.toHexWord(flagsOut));
|
||||
var s = this.hexOffset(this.cpu.opLIP - this.cpu.segCS.base, this.cpu.getCS()) + " " + Debugger.asIns[trace.ins] + "(" + str.toHex(dst, len) + "," + str.toHex(src, len) + "," + (flagsIn === null? "-" : str.toHexWord(flagsIn)) + ") " + str.toHex(result, len) + "," + (flagsOut === null? "-" : str.toHexWord(flagsOut));
|
||||
if (!this.aTraceBuffer.length) this.aTraceBuffer = new Array(Debugger.TRACE_LIMIT);
|
||||
this.aTraceBuffer[this.iTraceBuffer++] = s;
|
||||
if (this.iTraceBuffer >= this.aTraceBuffer.length) {
|
||||
|
|
@ -2416,7 +2462,23 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.prototype.hexAddr = function(aAddr)
|
||||
{
|
||||
return aAddr[1] == null? ("%" + str.toHex(aAddr[2])) : str.toHexAddr(aAddr[0], aAddr[1]);
|
||||
return aAddr[1] == null? ("%" + str.toHex(aAddr[2])) : this.hexOffset(aAddr[0], aAddr[1]);
|
||||
};
|
||||
|
||||
/**
|
||||
* hexOffset(off, sel)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {number} off
|
||||
* @param {number} [sel]
|
||||
* @return {string} the hex representation of off (or sel:off)
|
||||
*/
|
||||
Debugger.prototype.hexOffset = function(off, sel)
|
||||
{
|
||||
if (sel !== undefined) {
|
||||
return str.toHexWord(sel) + ":" + str.toHex(off, this.cchAddr < 8? 4 : 8);
|
||||
}
|
||||
return str.toHex(off);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2434,11 +2496,10 @@ if (DEBUGGER) {
|
|||
}
|
||||
if (aAddr[1] != null) {
|
||||
aAddr[0] += inc;
|
||||
/*
|
||||
* TODO: Shouldn't we be using the segment (aAddr[1]) limit instead of 0xffff?
|
||||
*/
|
||||
if (aAddr[0] != (aAddr[0] & 0xffff)) {
|
||||
aAddr[0] = aAddr[0] & 0xffff;
|
||||
var limit = this.getSegment(aAddr[1]).limit;
|
||||
if (aAddr[0] > limit) {
|
||||
this.assert(false);
|
||||
aAddr[0] = 0;
|
||||
aAddr[2] = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -2995,7 +3056,20 @@ if (DEBUGGER) {
|
|||
b = 0;
|
||||
break;
|
||||
}
|
||||
return " " + sFlag + (b? "1" : "0");
|
||||
return sFlag + (b? '1' : '0') + ' ';
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegStr(sName, reg)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} sName
|
||||
* @param {number} reg
|
||||
* @return {string}
|
||||
*/
|
||||
Debugger.prototype.getRegStr = function(sName, reg)
|
||||
{
|
||||
return sName + '=' + str.toHex(reg, this.cchReg) + ' ';
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -3027,38 +3101,90 @@ if (DEBUGGER) {
|
|||
};
|
||||
|
||||
/**
|
||||
* getRegStr(fProt)
|
||||
* getRegDump(fProt)
|
||||
*
|
||||
* Example of 8086 and 80286 real-mode register dump:
|
||||
*
|
||||
* AX=0000 BX=0000 CX=0000 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
|
||||
* SS=0000 DS=0000 ES=0000 PS=0002 V0 D0 I0 T0 S0 Z0 A0 P0 C0
|
||||
* F000:FFF0 EA5BE000F0 JMP F000:E05B
|
||||
*
|
||||
* Example of 80386 real-mode register dump:
|
||||
*
|
||||
* EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
|
||||
* ESP=00000000 EBP=00000000 ESI=00000000 EDI=00000000
|
||||
* SS=0000 DS=0000 ES=0000 PS=00000002 V0 D0 I0 T0 S0 Z0 A0 P0 C0
|
||||
* F000:0000FFF0 EA05F900F0 JMP F000:0000F905
|
||||
*
|
||||
* Example of 80286 protected-mode register dump:
|
||||
*
|
||||
* AX=0000 BX=0000 CX=0000 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
|
||||
* SS=0000[000000,FFFF] DS=0000[000000,FFFF] ES=0000[000000,FFFF] A20=ON
|
||||
* CS=F000[FF0000,FFFF] LD=0000[000000,FFFF] GD=[000000,FFFF] ID=[000000,03FF]
|
||||
* TR=0000 MS=FFF0 PS=0002 V0 D0 I0 T0 S0 Z0 A0 P0 C0
|
||||
* F000:FFF0 EA5BE000F0 JMP F000:E05B
|
||||
*
|
||||
* Example of 80386 protected-mode register dump:
|
||||
*
|
||||
* EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
|
||||
* ESP=00000000 EBP=00000000 ESI=00000000 EDI=00000000
|
||||
* SS=0000[00000000,FFFF] DS=0000[00000000,FFFF] ES=0000[00000000,FFFF]
|
||||
* CS=F000[FFFF0000,FFFF] FS=0000[00000000,FFFF] GS=0000[00000000,FFFF]
|
||||
* LD=0000[00000000,FFFF] GD=[00000000,FFFF] ID=[00000000,03FF] TR=0000 A20=ON
|
||||
* CR0=00000010 CR2=00000000 CR3=00000000 PS=00000002 V0 D0 I0 T0 S0 Z0 A0 P0 C0
|
||||
* F000:0000FFF0 EA05F900F0 JMP F000:0000F905
|
||||
*
|
||||
* We no longer include CS in real-mode (or EIP in any mode), because that information can be obtained from the
|
||||
* first line of disassembly, which an "r" or "rp" command will also display.
|
||||
*
|
||||
* Note that even when the processor is in real mode, you can always use the "rp" command to force a protected-mode
|
||||
* dump, in case you need to verify any selector base or limit values, since those do affect real-mode operation.
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {boolean} [fProt]
|
||||
* @return {string}
|
||||
*/
|
||||
Debugger.prototype.getRegStr = function(fProt)
|
||||
Debugger.prototype.getRegDump = function(fProt)
|
||||
{
|
||||
if (fProt === undefined) {
|
||||
fProt = !!(this.cpu.regCR0 & X86.CR0.MSW.PE);
|
||||
}
|
||||
var s = "AX=" + str.toHexWord(this.cpu.regEAX) +
|
||||
" BX=" + str.toHexWord(this.cpu.regEBX) +
|
||||
" CX=" + str.toHexWord(this.cpu.regECX) +
|
||||
" DX=" + str.toHexWord(this.cpu.regEDX) +
|
||||
" SP=" + str.toHexWord(this.cpu.getSP()) +
|
||||
" BP=" + str.toHexWord(this.cpu.regEBP) +
|
||||
" SI=" + str.toHexWord(this.cpu.regESI) +
|
||||
" DI=" + str.toHexWord(this.cpu.regEDI) + '\n';
|
||||
s += this.getSegStr(this.cpu.segDS, fProt) + ' ' + this.getSegStr(this.cpu.segES, fProt) + ' ' + this.getSegStr(this.cpu.segSS, fProt);
|
||||
s += (fProt? '\n' : ' ');
|
||||
s += this.getSegStr(this.cpu.segCS, fProt) + " IP=" + str.toHexWord(this.cpu.getIP()) +
|
||||
this.getFlagStr("V") + this.getFlagStr("D") + this.getFlagStr("I") + this.getFlagStr("T") +
|
||||
this.getFlagStr("S") + this.getFlagStr("Z") + this.getFlagStr("A") + this.getFlagStr("P") + this.getFlagStr("C") +
|
||||
" PS=" + str.toHexWord(this.cpu.getPS());
|
||||
var s = this.getRegStr(this.regs.AX, this.cpu.regEAX) +
|
||||
this.getRegStr(this.regs.BX, this.cpu.regEBX) +
|
||||
this.getRegStr(this.regs.CX, this.cpu.regECX) +
|
||||
this.getRegStr(this.regs.DX, this.cpu.regEDX) + (this.cchReg > 4? '\n' : '') +
|
||||
this.getRegStr(this.regs.SP, this.cpu.getSP()) +
|
||||
this.getRegStr(this.regs.BP, this.cpu.regEBP) +
|
||||
this.getRegStr(this.regs.SI, this.cpu.regESI) +
|
||||
this.getRegStr(this.regs.DI, this.cpu.regEDI) + '\n';
|
||||
s += this.getSegStr(this.cpu.segSS, fProt) + ' ' +
|
||||
this.getSegStr(this.cpu.segDS, fProt) + ' ' +
|
||||
this.getSegStr(this.cpu.segES, fProt) + ' ';
|
||||
if (fProt) {
|
||||
s += " MS=" + str.toHexWord(this.cpu.regCR0) + '\n' +
|
||||
this.getDTRStr("LD", this.cpu.segLDT.sel, this.cpu.segLDT.base, this.cpu.segLDT.base + this.cpu.segLDT.limit) + ' ' +
|
||||
this.getDTRStr("GD", null, this.cpu.addrGDT, this.cpu.addrGDTLimit) + ' ' +
|
||||
this.getDTRStr("ID", null, this.cpu.addrIDT, this.cpu.addrIDTLimit) + " TR=" + str.toHexWord(this.cpu.segTSS.sel) +
|
||||
" A20=" + (this.bus.getA20()? "ON" : "OFF");
|
||||
var sTR = "TR=" + str.toHexWord(this.cpu.segTSS.sel);
|
||||
var sA20 = "A20=" + (this.bus.getA20()? "ON " : "OFF ");
|
||||
if (this.cpu.model < X86.MODEL_80386) {
|
||||
sTR = '\n' + sTR;
|
||||
s += sA20; sA20 = '';
|
||||
}
|
||||
s += '\n' + this.getSegStr(this.cpu.segCS, fProt) + ' ';
|
||||
if (this.cpu.model >= X86.MODEL_80386) {
|
||||
sA20 += '\n';
|
||||
s += this.getSegStr(this.cpu.segFS, fProt) + ' ' +
|
||||
this.getSegStr(this.cpu.segGS, fProt) + '\n';
|
||||
}
|
||||
s += this.getDTRStr("LD", this.cpu.segLDT.sel, this.cpu.segLDT.base, this.cpu.segLDT.base + this.cpu.segLDT.limit) + ' ' +
|
||||
this.getDTRStr("GD", null, this.cpu.addrGDT, this.cpu.addrGDTLimit) + ' ' +
|
||||
this.getDTRStr("ID", null, this.cpu.addrIDT, this.cpu.addrIDTLimit) + ' ';
|
||||
s += sTR + ' ' + sA20;
|
||||
s += this.getRegStr(this.regs.MS, this.cpu.regCR0);
|
||||
if (this.cpu.model >= X86.MODEL_80386) {
|
||||
s += this.getRegStr("CR2", this.cpu.regCR2) + this.getRegStr("CR3", this.cpu.regCR3);
|
||||
}
|
||||
}
|
||||
s += this.getRegStr(this.regs.PS, this.cpu.getPS()) +
|
||||
this.getFlagStr("V") + this.getFlagStr("D") + this.getFlagStr("I") + this.getFlagStr("T") +
|
||||
this.getFlagStr("S") + this.getFlagStr("Z") + this.getFlagStr("A") + this.getFlagStr("P") + this.getFlagStr("C");
|
||||
return s;
|
||||
};
|
||||
|
||||
|
|
@ -3139,27 +3265,51 @@ if (DEBUGGER) {
|
|||
sValue = sValue.toUpperCase();
|
||||
switch (sValue) {
|
||||
case "AX":
|
||||
value = this.cpu.regEAX & 0xffff;
|
||||
break;
|
||||
case "EAX":
|
||||
value = this.cpu.regEAX;
|
||||
break;
|
||||
case "BX":
|
||||
value = this.cpu.regEBX & 0xffff;
|
||||
break;
|
||||
case "EBX":
|
||||
value = this.cpu.regEBX;
|
||||
break;
|
||||
case "CX":
|
||||
value = this.cpu.regECX & 0xffff;
|
||||
break;
|
||||
case "ECX":
|
||||
value = this.cpu.regECX;
|
||||
break;
|
||||
case "DX":
|
||||
value = this.cpu.regEDX & 0xffff;
|
||||
break;
|
||||
case "EDX":
|
||||
value = this.cpu.regEDX;
|
||||
break;
|
||||
case "SI":
|
||||
value = this.cpu.regESI & 0xffff;
|
||||
break;
|
||||
case "ESI":
|
||||
value = this.cpu.regESI;
|
||||
break;
|
||||
case "DI":
|
||||
value = this.cpu.regEDI & 0xffff;
|
||||
break;
|
||||
case "EDI":
|
||||
value = this.cpu.regEDI;
|
||||
break;
|
||||
case "BP":
|
||||
value = this.cpu.regEBP & 0xffff;
|
||||
break;
|
||||
case "EBP":
|
||||
value = this.cpu.regEBP;
|
||||
break;
|
||||
case "SP":
|
||||
value = this.cpu.getSP() & 0xffff;
|
||||
break;
|
||||
case "ESP":
|
||||
value = this.cpu.getSP();
|
||||
break;
|
||||
case "CS":
|
||||
|
|
@ -3179,6 +3329,9 @@ if (DEBUGGER) {
|
|||
* treat "PC" as an alias for the 16-bit flags register. So for purposes of parseValue(), "PC" has been removed.
|
||||
*/
|
||||
case "IP":
|
||||
value = this.cpu.getIP() & 0xffff;
|
||||
break;
|
||||
case "EIP":
|
||||
value = this.cpu.getIP();
|
||||
break;
|
||||
default:
|
||||
|
|
@ -3319,7 +3472,7 @@ if (DEBUGGER) {
|
|||
if (seg === undefined) seg = (addr >>> 4);
|
||||
var sSymbolOrig = aSymbols[sSymbol]['l'];
|
||||
if (sSymbolOrig) sSymbol = sSymbolOrig;
|
||||
this.println(str.toHexAddr(off, seg) + " " + sSymbol);
|
||||
this.println(this.hexOffset(off, seg) + " " + sSymbol);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -3967,13 +4120,13 @@ if (DEBUGGER) {
|
|||
sDelta = "";
|
||||
nDelta = aAddr[0] - aSymbol[1];
|
||||
if (nDelta) sDelta = " + " + str.toHexWord(nDelta);
|
||||
this.println(aSymbol[0] + " (" + str.toHexAddr(aSymbol[1], aAddr[1]) + ")" + sDelta);
|
||||
this.println(aSymbol[0] + " (" + this.hexOffset(aSymbol[1], aAddr[1]) + ")" + sDelta);
|
||||
}
|
||||
if (aSymbol.length > 4 && aSymbol[4]) {
|
||||
sDelta = "";
|
||||
nDelta = aSymbol[5] - aAddr[0];
|
||||
if (nDelta) sDelta = " - " + str.toHexWord(nDelta);
|
||||
this.println(aSymbol[4] + " (" + str.toHexAddr(aSymbol[5], aAddr[1]) + ")" + sDelta);
|
||||
this.println(aSymbol[4] + " (" + this.hexOffset(aSymbol[5], aAddr[1]) + ")" + sDelta);
|
||||
}
|
||||
} else {
|
||||
this.println("no symbols");
|
||||
|
|
@ -4285,55 +4438,82 @@ if (DEBUGGER) {
|
|||
}
|
||||
var w = parseInt(sValue, 16);
|
||||
if (!isNaN(w)) {
|
||||
sReg = sReg.toUpperCase();
|
||||
switch (sReg) {
|
||||
var sRegMatch = sReg.toUpperCase();
|
||||
if (sRegMatch.charAt(0) == 'E' && this.cchReg <= 4) {
|
||||
sRegMatch = null;
|
||||
}
|
||||
switch (sRegMatch) {
|
||||
case "AL":
|
||||
this.cpu.regEAX = (this.cpu.regEAX & 0xff00) | (w & 0xff);
|
||||
this.cpu.regEAX = (this.cpu.regEAX & ~0xff) | (w & 0xff);
|
||||
break;
|
||||
case "AH":
|
||||
this.cpu.regEAX = (this.cpu.regEAX & 0x00ff) | ((w << 8) & 0xff);
|
||||
this.cpu.regEAX = (this.cpu.regEAX & ~0xff00) | ((w << 8) & 0xff);
|
||||
break;
|
||||
case "AX":
|
||||
this.cpu.regEAX = (w & 0xffff);
|
||||
this.cpu.regEAX = (this.cpu.regEAX & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "EAX":
|
||||
this.cpu.regEAX = w;
|
||||
break;
|
||||
case "BL":
|
||||
this.cpu.regEBX = (this.cpu.regEBX & 0xff00) | (w & 0xff);
|
||||
this.cpu.regEBX = (this.cpu.regEBX & ~0xff) | (w & 0xff);
|
||||
break;
|
||||
case "BH":
|
||||
this.cpu.regEBX = (this.cpu.regEBX & 0x00ff) | ((w << 8) & 0xff);
|
||||
this.cpu.regEBX = (this.cpu.regEBX & ~0xff00) | ((w << 8) & 0xff);
|
||||
break;
|
||||
case "BX":
|
||||
this.cpu.regEBX = (w & 0xffff);
|
||||
this.cpu.regEBX = (this.cpu.regEBX & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "EBX":
|
||||
this.cpu.regEBX = w;
|
||||
break;
|
||||
case "CL":
|
||||
this.cpu.regECX = (this.cpu.regECX & 0xff00) | (w & 0xff);
|
||||
this.cpu.regECX = (this.cpu.regECX & ~0xff) | (w & 0xff);
|
||||
break;
|
||||
case "CH":
|
||||
this.cpu.regECX = (this.cpu.regECX & 0x00ff) | ((w << 8) & 0xff);
|
||||
this.cpu.regECX = (this.cpu.regECX & ~0xff00) | ((w << 8) & 0xff);
|
||||
break;
|
||||
case "CX":
|
||||
this.cpu.regECX = (w & 0xffff);
|
||||
this.cpu.regECX = (this.cpu.regECX & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "ECX":
|
||||
this.cpu.regECX = w;
|
||||
break;
|
||||
case "DL":
|
||||
this.cpu.regEDX = (this.cpu.regEDX & 0xff00) | (w & 0xff);
|
||||
this.cpu.regEDX = (this.cpu.regEDX & ~0xff) | (w & 0xff);
|
||||
break;
|
||||
case "DH":
|
||||
this.cpu.regEDX = (this.cpu.regEDX & 0x00ff) | ((w << 8) & 0xff);
|
||||
this.cpu.regEDX = (this.cpu.regEDX & ~0xff00) | ((w << 8) & 0xff);
|
||||
break;
|
||||
case "DX":
|
||||
this.cpu.regEDX = (w & 0xffff);
|
||||
this.cpu.regEDX = (this.cpu.regEDX & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "EDX":
|
||||
this.cpu.regEDX = w;
|
||||
break;
|
||||
case "SP":
|
||||
this.cpu.setSP((this.cpu.getSP() & ~0xffff) | (w & 0xffff));
|
||||
break;
|
||||
case "ESP":
|
||||
this.cpu.setSP(w);
|
||||
break;
|
||||
case "BP":
|
||||
this.cpu.regEBP = (w & 0xffff);
|
||||
this.cpu.regEBP = (this.cpu.regEBP & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "EBP":
|
||||
this.cpu.regEBP = w;
|
||||
break;
|
||||
case "SI":
|
||||
this.cpu.regESI = (w & 0xffff);
|
||||
this.cpu.regESI = (this.cpu.regESI & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "ESI":
|
||||
this.cpu.regESI = w;
|
||||
break;
|
||||
case "DI":
|
||||
this.cpu.regEDI = (w & 0xffff);
|
||||
this.cpu.regEDI = (this.cpu.regEDI & ~0xffff) | (w & 0xffff);
|
||||
break;
|
||||
case "EDI":
|
||||
this.cpu.regEDI = w;
|
||||
break;
|
||||
case "DS":
|
||||
this.cpu.setDS(w);
|
||||
|
|
@ -4390,7 +4570,7 @@ if (DEBUGGER) {
|
|||
var fUnknown = true;
|
||||
if (this.cpu.model >= X86.MODEL_80286) {
|
||||
fUnknown = false;
|
||||
switch(sReg){
|
||||
switch(sRegMatch){
|
||||
case "MS":
|
||||
X86Help.opHelpLMSW.call(this.cpu, w);
|
||||
break;
|
||||
|
|
@ -4422,7 +4602,7 @@ if (DEBUGGER) {
|
|||
}
|
||||
}
|
||||
|
||||
this.println((fCompact? '' : '\n') + this.getRegStr(fProt));
|
||||
this.println((fCompact? '' : '\n') + this.getRegDump(fProt));
|
||||
|
||||
if (fIns) {
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.getIP(), this.cpu.getCS());
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ Memory.TYPE = {
|
|||
Memory.readNone = function readNone(off)
|
||||
{
|
||||
if (DEBUGGER && this.dbg.messageEnabled(Messages.MEM) /* && !off */) {
|
||||
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr) + " from " + str.toHexAddr(this.cpu.getIP(), this.cpu.getCS()));
|
||||
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr) + " from " + this.dbg.hexOffset(this.cpu.getIP(), this.cpu.getCS()));
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ ROM.prototype.addROM = function(addr)
|
|||
{
|
||||
if (addr == null) return true;
|
||||
if (this.bus.addMemory(addr, this.sizeROM, Memory.TYPE.ROM)) {
|
||||
if (DEBUG) this.log("addROM(): copying ROM to " + str.toHexAddr(addr) + " (0x" + str.toHex(this.abROM.length) + " bytes)");
|
||||
if (DEBUG) this.log("addROM(): copying ROM to 0x" + str.toHex(addr) + " (0x" + str.toHex(this.abROM.length) + " bytes)");
|
||||
var bto = null;
|
||||
for (var off = 0; off < this.abROM.length; off++) {
|
||||
this.bus.setByteDirect(addr + off, this.abROM[off]);
|
||||
|
|
|
|||
|
|
@ -713,8 +713,10 @@ X86CPU.prototype.initProcessor = function()
|
|||
|
||||
if (this.model >= X86.MODEL_80186) {
|
||||
/*
|
||||
* TODO: I don't go out of my way to make 80186/80188 cycle times accurate, since no IBM PC models used
|
||||
* those processors; beyond the 8086, the next priority is the 80286, but we may revisit the 80186 someday.
|
||||
* I don't go out of my way to make 80186/80188 cycle times accurate, since I'm not aware of any
|
||||
* IBM PC models that used those processors; beyond the 8086, my next priorities are the 80286 and
|
||||
* 80386, but I might revisit the 80186 someday.
|
||||
*
|
||||
* Instruction handlers that contain "hard-coded" 80286 cycle times include: opINSb, opINSw, opOUTSb,
|
||||
* opOUTSw, opENTER, and opLEAVE.
|
||||
*/
|
||||
|
|
@ -805,8 +807,11 @@ X86CPU.prototype.reset = function()
|
|||
* or setIP(), whichever is appropriate; in unusual cases where only segCS is changing (eg, undocumented 8086
|
||||
* opcodes), use setCS().
|
||||
*
|
||||
* The other segment registers (DS, SS and ES) have similar setters (for segDS, segSS and segES), but those
|
||||
* functions do not mirror any segment:offset values in the same way that regLIP mirrors CS:IP.
|
||||
* Similarly, regLSP mirrors the linear address corresponding to SS:SP, and therefore you must rely on getSP()
|
||||
* to read the current SP, and setSP() and setSS() to update SP and SS.
|
||||
*
|
||||
* The other segment registers, such as segDS and segES, have similar getters and setters, but they do not mirror
|
||||
* any segment:offset values in the same way that regLIP mirrors CS:IP, or that regLSP mirrors SS:SP.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
|
|
@ -822,8 +827,8 @@ X86CPU.prototype.resetRegs = function()
|
|||
this.regEDI = 0;
|
||||
|
||||
/*
|
||||
* The following are internal "registers" that are used to capture intermediate values inside selected helper
|
||||
* functions and use them if they've been modified (or are known to always change); for example, the MUL and DIV
|
||||
* The following are internal "registers" used to capture intermediate values inside selected helper
|
||||
* functions and use them if they've been modified (or are known to change); for example, the MUL and DIV
|
||||
* instructions perform calculations that must be propagated to specific registers (eg, AX and/or DX), which
|
||||
* the ModRM decoder functions don't know about. We initialize them here mainly for documentation purposes.
|
||||
*/
|
||||
|
|
@ -831,15 +836,15 @@ X86CPU.prototype.resetRegs = function()
|
|||
|
||||
/*
|
||||
* Another internal "register" we occasionally need is an interim copy of bModRM, set inside selected opcode
|
||||
* handlers so that the helper function can have access to the instruction's bModRM without resorting to a closure
|
||||
* (which, in the Chrome V8 engine, for example, seems to cause constant recompilation).
|
||||
* handlers so that the helper function can have access to the instruction's bModRM without resorting to a
|
||||
* closure (which, in the Chrome V8 engine, for example, seems to cause constant recompilation).
|
||||
*/
|
||||
this.bModRM = 0;
|
||||
|
||||
/*
|
||||
* NOTE: Even though the MSW and IDTR are 80286-specific, we initialize them for ALL CPUs, so that
|
||||
* functions like X86Help.opHelpINT() can use the same code for both. The 8086/8088 have no direct way
|
||||
* of accessing or changing them, so this internal change should be perfectly safe for those processors.
|
||||
* NOTE: Even though the 8086 doesn't have CR0 (aka MSW) and IDTR, we initialize them for ALL CPUs, so
|
||||
* that functions like X86Help.opHelpINT() can use the same code for both. The 8086/8088 have no direct
|
||||
* way of accessing or changing them, so this internal change should be perfectly safe for those processors.
|
||||
*/
|
||||
this.regCR0 = X86.CR0.MSW.ON;
|
||||
this.addrIDT = 0; this.addrIDTLimit = 0x03FF;
|
||||
|
|
@ -847,15 +852,14 @@ X86CPU.prototype.resetRegs = function()
|
|||
|
||||
/*
|
||||
* This is set by opHelpFault() and reset (to -1) by resetRegs() and opIRET(); its initial purpose is to
|
||||
* "help" opHelpFault() determine when a nested fault should be converted into either a double-fault
|
||||
* (DF_FAULT) or a triple-fault (ie, a processor reset).
|
||||
* "help" opHelpFault() determine when a nested fault should be converted into either a double-fault (DF_FAULT)
|
||||
* or a triple-fault (ie, a processor reset).
|
||||
*/
|
||||
this.nFault = -1;
|
||||
|
||||
/*
|
||||
* Segment registers used to be defined as separate variables (eg, regCS and regCS0 stored the
|
||||
* segment number and base physical address, respectively), but all segment registers are now defined
|
||||
* as X86Seg objects.
|
||||
* Segment registers used to be defined as separate variables (eg, regCS and regCS0 stored the segment
|
||||
* number and base physical address, respectively), but all segment registers are now defined as X86Seg objects.
|
||||
*/
|
||||
this.segCS = new X86Seg(this, X86Seg.ID.CODE, "CS");
|
||||
this.segDS = new X86Seg(this, X86Seg.ID.DATA, "DS");
|
||||
|
|
@ -865,7 +869,12 @@ X86CPU.prototype.resetRegs = function()
|
|||
this.setSS(0);
|
||||
|
||||
if (I386 && this.model >= X86.MODEL_80386) {
|
||||
this.regCR0 = X86.CR0.ET;
|
||||
this.regCR0 = X86.CR0.ET; // formerly MSW
|
||||
this.regCR1 = 0; // reserved
|
||||
this.regCR2 = 0; // page fault linear address (PFLA)
|
||||
this.regCR3 = 0; // page directory base register (PDBR)
|
||||
this.aRegDR = new Array(8); // Debug Registers DR0-DR7
|
||||
this.aRegTR = new Array(8); // Test Registers TR0-TR7
|
||||
this.segFS = new X86Seg(this, X86Seg.ID.DATA, "FS");
|
||||
this.segGS = new X86Seg(this, X86Seg.ID.DATA, "GS");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -728,7 +728,7 @@ var X86Help = {
|
|||
}
|
||||
|
||||
if (this.messageEnabled(bitsMessage) || fHalt) {
|
||||
var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.getIP(), this.getCS()) + " (%" + str.toHex(this.regLIP, 6) + ")";
|
||||
var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + this.dbg.hexOffset(this.getIP(), this.getCS()) + " (%" + str.toHex(this.regLIP, 6) + ")";
|
||||
var fRunning = this.aFlags.fRunning;
|
||||
if (this.printMessage(sMessage, bitsMessage)) {
|
||||
if (fHalt) {
|
||||
|
|
@ -767,7 +767,7 @@ var X86Help = {
|
|||
*/
|
||||
opHelpUndefined: function() {
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
this.setError("Undefined opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regLIP)) + " at " + str.toHexAddr(this.getIP(), this.getCS()));
|
||||
this.setError("Undefined opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regLIP)) + " at 0x" + str.toHex(this.regLIP));
|
||||
this.stopCPU();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -166,21 +166,6 @@ str.toHexWord = function(w)
|
|||
return str.toHex(w, 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* toHexAddr(off, sel)
|
||||
*
|
||||
* @param {number} off
|
||||
* @param {number} [sel]
|
||||
* @return {string} the hex representation of sel:off
|
||||
*/
|
||||
str.toHexAddr = function(off, sel)
|
||||
{
|
||||
if (sel !== undefined) {
|
||||
return str.toHexWord(sel) + ":" + str.toHexWord(off);
|
||||
}
|
||||
return str.toHex(off);
|
||||
};
|
||||
|
||||
/**
|
||||
* getBaseName(sFileName, fStripExt)
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue