Assorted 80386 tweaks

This commit is contained in:
Jeff Parsons 2015-03-24 11:20:47 -07:00 committed by jeffpar
commit f5c0930f83
8 changed files with 255 additions and 232 deletions

View file

@ -1134,6 +1134,7 @@ CPU.prototype.yieldCPU = function()
this.aCounts.nCyclesNextYield = 0; // this will break us out of runCPU(), once we break out of stepCPU()
this.nBurstCycles -= this.nStepCycles;
this.nStepCycles = 0; // this will break us out of stepCPU()
if (DEBUG) this.nSnapCycles = this.nBurstCycles;
/*
* The Debugger calls yieldCPU() after every message() to ensure browser responsiveness, but it looks
* odd for those messages to show CPU state changes but for the CPU's own status display to not (ditto

View file

@ -4115,9 +4115,11 @@ if (DEBUGGER) {
/*
* We must create a new aAddr from the address we obtained from aHistory, because
* aAddr was a reference, not a copy, and we don't want getInstruction() modifying the original.
*
* TODO: By using a new address for each iteration, history dumps fail to disassemble 32-bit overrides properly.
*/
aAddr = this.newAddr(aAddr[0], aAddr[1], aAddr[2]);
this.println(this.getInstruction(aAddr, "history", -n));
this.println(this.getInstruction(aAddr, "history", n));
if (++iHistory == aHistory.length) iHistory = 0;
this.nextHistory = --n;
cLines--;
@ -4384,7 +4386,7 @@ if (DEBUGGER) {
if (sCategory !== undefined) {
var bitsMessage = 0;
if (sCategory == "all") {
bitsMessage = (0xffffffff|0) & ~(Messages.HALT | Messages.LOG);
bitsMessage = (0xffffffff|0) & ~(Messages.HALT | Messages.KEYS | Messages.LOG);
sCategory = null;
} else if (sCategory == "on") {
fCriteria = true;
@ -4980,8 +4982,8 @@ if (DEBUGGER) {
* aAddr[5] to true whenever the address size is 32-bit. Initially, both fields must be set to match
* the size of the current code segment.
*/
aAddr[4] = (this.cpu.dataSize == 4);
aAddr[5] = (this.cpu.addrSize == 4);
aAddr[4] = (this.cpu.segCS.dataSize == 4);
aAddr[5] = (this.cpu.segCS.addrSize == 4);
fInitSize = false;
}
if (this.isPrefixIns(bOpcode)) {

View file

@ -2287,9 +2287,6 @@ Video.prototype.captureTouch = function()
*/
Video.prototype.onFocusChange = function(fFocus)
{
if (this.fHasFocus != fFocus && DEBUG && this.messageEnabled()) {
this.printMessage("onFocusChange(" + (fFocus? "true" : "false") + ")", true);
}
/*
* As per http://stackoverflow.com/questions/6740253/disable-scrolling-when-changing-focus-form-elements-ipad-web-app,
* I decided to try this work-around to prevent the webpage from scrolling around whenever the canvas is given

View file

@ -2863,7 +2863,7 @@ X86CPU.prototype.getLongPrefetch = function(addr)
*/
X86CPU.prototype.getWordPrefetch = function(addr)
{
return (I386 && this.addrSize == 4? this.getLongPrefetch(addr) : this.getShortPrefetch(addr));
return (I386 && this.dataSize == 4? this.getLongPrefetch(addr) : this.getShortPrefetch(addr));
};
/**
@ -3017,7 +3017,7 @@ X86CPU.prototype.getIPWord = function()
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
}
this.regLIP += this.addrSize;
this.regLIP += this.dataSize;
if (this.regLIP > this.regLIPLimit) {
this.setIP(this.regLIP - this.segCS.base);
}

View file

@ -1337,16 +1337,13 @@ X86.fnRCLb = function RCLb(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 9;
shift %= 9;
if (!shift) {
carry <<= 7;
} else {
/*
* shift is 1-8, which means the new carry will come from the dst bit
* at position 7-0. To force it into position 7, left shift by (shift - 1).
*/
result = ((dst << shift) | (carry << (shift - 1)) | (dst >> (9 - shift))) & 0xff;
carry = dst << (shift - 1);
}
@ -1357,6 +1354,8 @@ X86.fnRCLb = function RCLb(dst, src)
};
/**
* fnRCLw(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src (1 or CL)
@ -1366,16 +1365,13 @@ X86.fnRCLw = function RCLw(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 17;
shift %= 17;
if (!shift) {
carry <<= 15;
} else {
/*
* shift is 1-16, which means the new carry will come from the dst bit
* at position 15-0. To force it into position 15, left shift by (shift - 1).
*/
result = ((dst << shift) | (carry << (shift - 1)) | (dst >> (17 - shift))) & 0xffff;
carry = dst << (shift - 1);
}
@ -1385,6 +1381,29 @@ X86.fnRCLw = function RCLw(dst, src)
return result;
};
/**
* fnRCLd(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src (1 or CL)
* @return {number}
*/
X86.fnRCLd = function RCLd(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = this.getCarry();
result = (dst << shift) | (carry << (shift - 1)) | (dst >>> (32 - shift));
carry = dst << (shift - 1);
X86.setRotateResult.call(this, result, carry, X86.RESULT.DWORD);
}
if (DEBUG && DEBUGGER) this.traceLog('RCLD', dst, src, flagsIn, this.getPS(), result);
return result;
};
/**
* fnRCRb(dst, src)
*
@ -1397,16 +1416,13 @@ X86.fnRCRb = function RCRb(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 9;
shift %= 9;
if (!shift) {
carry <<= 7;
} else {
/*
* shift is 1-8, which means the new carry will come from the dst bit
* at position 0-7. To force it into position 7, left shift by (8 - shift).
*/
result = ((dst >> shift) | (carry << (8 - shift)) | (dst << (9 - shift))) & 0xff;
carry = dst << (8 - shift);
}
@ -1428,16 +1444,13 @@ X86.fnRCRw = function RCRw(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 17;
shift %= 17;
if (!shift) {
carry <<= 15;
} else {
/*
* shift is 1-16, which means the new carry will come from the dst bit
* at position 0-15. To force it into position 15, left shift by (16 - shift).
*/
result = ((dst >> shift) | (carry << (16 - shift)) | (dst << (17 - shift))) & 0xffff;
carry = dst << (16 - shift);
}
@ -1447,6 +1460,29 @@ X86.fnRCRw = function RCRw(dst, src)
return result;
};
/**
* fnRCRd(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src (1 or CL)
* @return {number}
*/
X86.fnRCRd = function RCRd(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = this.getCarry();
result = (dst >>> shift) | (carry << (32 - shift)) | (dst << (33 - shift));
carry = dst << (32 - shift);
X86.setRotateResult.call(this, result, carry, X86.RESULT.DWORD);
}
if (DEBUG && DEBUGGER) this.traceLog('RCRD', dst, src, flagsIn, this.getPS(), result);
return result;
};
/**
* fnRETF(n)
*
@ -1497,23 +1533,13 @@ X86.fnROLb = function ROLb(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry;
/*
* The following mask obviates the need to use nShiftCountMask.
*/
var shift = src & 0x7;
shift &= 0x7;
if (!shift) {
/*
* shift is 8, which means the new carry will come from the dst bit
* at position 0.
*/
carry = dst << 7;
} else {
/*
* shift is 1-7, which means the new carry will come from the dst bit
* at position 7-1. To force it into position 7, left shift by (shift - 1).
*/
result = ((dst << shift) | (dst >> (8 - shift))) & 0xff;
carry = dst << (shift - 1);
}
@ -1535,19 +1561,13 @@ X86.fnROLw = function ROLw(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry;
/*
* The following mask obviates the need to use nShiftCountMask.
*/
var shift = src & 0xf;
shift &= 0xf;
if (!shift) {
carry = dst << 15;
} else {
/*
* shift is 1-15, which means the new carry will come from the dst bit
* at position 15-1. To force it into position 15, left shift by (shift - 1).
*/
result = ((dst << shift) | (dst >> (16 - shift))) & 0xffff;
carry = dst << (shift - 1);
}
@ -1569,22 +1589,13 @@ X86.fnRORb = function RORb(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry;
/*
* The following mask obviates the need to use nShiftCountMask.
*/
var shift = src & 0x7;
shift &= 0x7;
if (!shift) {
/*
* shift is 8, which means the new carry will come from the dst bit at position 7.
*/
carry = dst;
} else {
/*
* shift is 1-7, which means the new carry will come from the dst bit
* at position 0-6. To force it into position 7, left shift by (8 - shift).
*/
result = ((dst >> shift) | (dst << (8 - shift))) & 0xff;
carry = dst << (8 - shift);
}
@ -1606,22 +1617,13 @@ X86.fnRORw = function RORw(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry;
/*
* The following mask obviates the need to use nShiftCountMask.
*/
var shift = src & 0xf;
shift &= 0xf;
if (!shift) {
/*
* shift is 16, which means the new carry will come from dst bit 15.
*/
carry = dst;
} else {
/*
* shift is 1-15, which means the new carry will come from the dst bit
* at position 0-14. To force it into position 15, left shift by (16 - shift).
*/
result = ((dst >> shift) | (dst << (16 - shift))) & 0xffff;
carry = dst << (16 - shift);
}
@ -1645,12 +1647,10 @@ X86.fnRORw = function RORw(dst, src)
*/
X86.fnSARb = function SARb(dst, src)
{
if (src) {
/*
* The following comparison obviates the need to mask src with nShiftCountMask.
*/
if (src > 8) src = 9;
var temp = ((dst << 24) >> 24) >> (src - 1);
var shift = src & this.nShiftCountMask;
if (shift) {
if (shift > 8) shift = 9;
var temp = ((dst << 24) >> 24) >> (shift - 1);
dst = (temp >> 1) & 0xff;
this.setLogicResult(dst, X86.RESULT.BYTE, temp & 0x1);
}
@ -1671,12 +1671,10 @@ X86.fnSARb = function SARb(dst, src)
*/
X86.fnSARw = function SARw(dst, src)
{
if (src) {
/*
* The following comparison obviates the need to mask src with nShiftCountMask.
*/
if (src > 16) src = 17;
var temp = ((dst << 16) >> 16) >> (src - 1);
var shift = src & this.nShiftCountMask;
if (shift) {
if (shift > 16) shift = 17;
var temp = ((dst << 16) >> 16) >> (shift - 1);
dst = (temp >> 1) & 0xffff;
this.setLogicResult(dst, X86.RESULT.WORD, temp & 0x1);
}
@ -1796,15 +1794,13 @@ X86.fnSHLb = function SHLb(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = 0;
/*
* The following comparison obviates the need to mask src with nShiftCountMask.
*/
if (src > 8) {
if (shift > 8) {
result = 0;
} else {
carry = dst << (src - 1);
carry = dst << (shift - 1);
result = (carry << 1) & 0xff;
}
this.setLogicResult(result, X86.RESULT.BYTE, carry & X86.RESULT.BYTE, (result ^ carry) & X86.RESULT.BYTE);
@ -1829,15 +1825,13 @@ X86.fnSHLw = function SHLw(dst, src)
{
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var shift = src & this.nShiftCountMask;
if (shift) {
var carry = 0;
/*
* The following comparison obviates the need to mask src with nShiftCountMask.
*/
if (src > 16) {
if (shift > 16) {
result = 0;
} else {
carry = dst << (src - 1);
carry = dst << (shift - 1);
result = (carry << 1) & 0xffff;
}
this.setLogicResult(result, X86.RESULT.WORD, carry & X86.RESULT.WORD, (result ^ carry) & X86.RESULT.WORD);
@ -1860,11 +1854,9 @@ X86.fnSHLw = function SHLw(dst, src)
*/
X86.fnSHRb = function SHRb(dst, src)
{
if (src) {
/*
* The following comparison obviates the need to mask src with nShiftCountMask.
*/
var temp = (src > 8? 0 : (dst >> (src - 1)));
var shift = src & this.nShiftCountMask;
if (shift) {
var temp = (shift > 8? 0 : (dst >> (shift - 1)));
dst = (temp >> 1) & 0xff;
this.setLogicResult(dst, X86.RESULT.BYTE, temp & 0x1, dst & X86.RESULT.BYTE);
}
@ -1885,11 +1877,9 @@ X86.fnSHRb = function SHRb(dst, src)
*/
X86.fnSHRw = function SHRw(dst, src)
{
if (src) {
/*
* The following comparison obviates the need to mask src with nShiftCountMask.
*/
var temp = (src > 16? 0 : (dst >> (src - 1)));
var shift = src & this.nShiftCountMask;
if (shift) {
var temp = (shift > 16? 0 : (dst >> (shift - 1)));
dst = (temp >> 1) & 0xffff;
this.setLogicResult(dst, X86.RESULT.WORD, temp & 0x1, dst & X86.RESULT.WORD);
}
@ -2323,6 +2313,8 @@ X86.fnXORw = function XORw(dst, src)
};
/**
* fnXORd(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src
@ -2334,6 +2326,21 @@ X86.fnXORd = function XORd(dst, src)
return this.setLogicResult(dst ^ src, X86.RESULT.DWORD);
};
/**
* fnTBD(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src
* @return {number}
*/
X86.fnTBD = function TBD(dst, src)
{
this.printMessage("unimplemented 80386 opcode", true);
this.stopCPU();
return dst;
};
/**
* setRotateResult(result, carry, size)
*
@ -2355,43 +2362,57 @@ X86.setRotateResult = function(result, carry, size)
};
/**
* fnGRPCount1()
*
* @this {X86CPU}
* @return {number}
*/
X86.fnGRPCount1 = function() {
X86.fnGRPCount1 = function()
{
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 2 : this.CYCLES.nOpCyclesShift1M);
return 1;
};
/**
* fnGRPCountCL()
*
* @this {X86CPU}
* @return {number}
*/
X86.fnGRPCountCL = function() {
var count = this.regECX & this.nShiftCountMask;
X86.fnGRPCountCL = function()
{
var count = this.regECX & 0xff;
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.CYCLES.nOpCyclesShiftCR : this.CYCLES.nOpCyclesShiftCM) + (count << this.CYCLES.nOpCyclesShiftCS);
return count;
};
/**
* fnGRPCountImm()
*
* @this {X86CPU}
* @return {number}
*/
X86.fnGRPCountImm = function() {
X86.fnGRPCountImm = function()
{
var count = this.getIPByte();
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.CYCLES.nOpCyclesShiftCR : this.CYCLES.nOpCyclesShiftCM) + (count << this.CYCLES.nOpCyclesShiftCS);
return count;
};
/**
* fnGRPSrcNone()
*
* @this {X86CPU}
* @return {number|null}
*/
X86.fnGRPSrcNone = function() {
X86.fnGRPSrcNone = function()
{
return null;
};
/**
* fnGRPFault(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src
@ -2404,6 +2425,8 @@ X86.fnGRPFault = function(dst, src)
};
/**
* fnGRPInvalid(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src
@ -2416,6 +2439,8 @@ X86.fnGRPInvalid = function(dst, src)
};
/**
* fnGRPUndefined(dst, src)
*
* @this {X86CPU}
* @param {number} dst
* @param {number} src

View file

@ -1632,12 +1632,20 @@ X86.opINSw = function INSw()
}
if (nReps--) {
var addrFrom = this.regLIP - nDelta - 1;
var w = this.bus.checkPortInputNotify(this.regEDX, addrFrom);
if (BACKTRACK) this.backTrack.btiMemLo = this.backTrack.btiIO;
w |= (this.bus.checkPortInputNotify(this.regEDX, addrFrom) << 8);
if (BACKTRACK) this.backTrack.btiMemHi = this.backTrack.btiIO;
var w = 0, shift = 0;
for (var n = 0; n < this.dataSize; n++) {
w |= this.bus.checkPortInputNotify(this.regEDX, addrFrom) << shift;
shift += 8;
if (BACKTRACK) {
if (!n) {
this.backTrack.btiMemLo = this.backTrack.btiIO;
} else if (n == 1) {
this.backTrack.btiMemHi = this.backTrack.btiIO;
}
}
}
this.setSOWord(this.segES, this.regEDI & this.addrMask, w);
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize)) & this.addrMask);
this.nStepCycles -= nCycles;
this.regECX -= nDelta;
if (nReps) {
@ -1727,14 +1735,21 @@ X86.opOUTSw = function OUTSw()
}
if (nReps--) {
var w = this.getSOWord(this.segDS, this.regESI & this.addrMask);
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize)) & this.addrMask);
this.nStepCycles -= nCycles;
this.regECX -= nDelta;
var addrFrom = this.regLIP - nDelta - 1;
if (BACKTRACK) this.backTrack.btiIO = this.backTrack.btiMemLo;
this.bus.checkPortOutputNotify(this.regEDX, w & 0xff, addrFrom);
if (BACKTRACK) this.backTrack.btiIO = this.backTrack.btiMemHi;
this.bus.checkPortOutputNotify(this.regEDX, w >> 8, addrFrom);
var addrFrom = this.regLIP - nDelta - 1, shift = 0;
for (var n = 0; n < this.dataSize; n++) {
if (BACKTRACK) {
if (!n) {
this.backTrack.btiIO = this.backTrack.btiMemLo;
} else if (n == 1) {
this.backTrack.btiIO = this.backTrack.btiMemHi;
}
}
this.bus.checkPortOutputNotify(this.regEDX, (w >> shift) & 0xff, addrFrom);
shift += 8;
}
if (nReps) {
if (BUGS_8086) {
this.advanceIP(-2); // this instruction does not support segment overrides
@ -2542,15 +2557,15 @@ X86.opPOPF = function POPF()
X86.opSAHF = function SAHF()
{
/*
* NOTE: While it make LOOK more efficient to do this:
* NOTE: While it make seem more efficient to do this:
*
* this.setPS((this.getPS() & ~X86.PS.SAHF) | ((this.regEAX >> 8) & X86.PS.SAHF));
*
* the call to getPS() forces all the "indirect" flags to be resolved first, and then the call
* to setPS() forces them all to be recalculated, so on balance, the code below is probably more
* efficient, and may also avoid some unexpected side-effects of slamming the entire PS register.
* getPS() forces any "cached" flags to be resolved first, and setPS() must do extra work above
* and beyond setting the arithmetic and logical flags, so on balance, the code below may be more
* efficient, and may also avoid unexpected side-effects of updating the entire PS register.
*/
var ah = this.regEAX >> 8;
var ah = (this.regEAX >> 8) & 0xff;
if (ah & X86.PS.CF) this.setCF(); else this.clearCF();
if (ah & X86.PS.PF) this.setPF(); else this.clearPF();
if (ah & X86.PS.AF) this.setAF(); else this.clearAF();
@ -2567,7 +2582,7 @@ X86.opSAHF = function SAHF()
*/
X86.opLAHF = function LAHF()
{
this.regEAX = (this.regEAX & 0xff) | (this.getPS() & X86.PS.SAHF) << 8;
this.regEAX = (this.regEAX & ~0xff00) | (this.getPS() & X86.PS.SAHF) << 8;
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
};
@ -2681,7 +2696,7 @@ X86.opMOVSw = function MOVSw()
if (!(this.opPrefixes & X86.OPFLAG.REPEAT)) this.nStepCycles -= this.CYCLES.nOpCyclesMovSr0;
}
if (nReps--) {
var nInc = ((this.regPS & X86.PS.DF)? -2 : 2);
var nInc = ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize);
this.setSOWord(this.segES, this.regEDI & this.addrMask, this.getSOWord(this.segData, this.regESI));
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + nInc) & this.addrMask);
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + nInc) & this.addrMask);
@ -2761,7 +2776,7 @@ X86.opCMPSw = function CMPSw()
if (!(this.opPrefixes & X86.OPFLAG.REPEAT)) this.nStepCycles -= this.CYCLES.nOpCyclesCmpSr0;
}
if (nReps--) {
var nInc = ((this.regPS & X86.PS.DF)? -2 : 2);
var nInc = ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize);
var wDst = this.getEAWord(this.segData, this.regESI & this.addrMask);
var wSrc = this.modEAWord(this.segES, this.regEDI & this.addrMask);
X86.fnCMPw.call(this, wDst, wSrc);
@ -2830,9 +2845,6 @@ X86.opSTOSb = function STOSb()
if (!(this.opPrefixes & X86.OPFLAG.REPEAT)) this.nStepCycles -= this.CYCLES.nOpCyclesStoSr0;
}
if (nReps--) {
/*
* NOTE: We rely on setSOByte() to truncate regEAX to 8 bits; if setSOByte() changes, mask AX below.
*/
if (BACKTRACK) this.backTrack.btiMemLo = this.backTrack.btiAL;
this.setSOByte(this.segES, this.regEDI & this.addrMask, this.regEAX);
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
@ -2877,7 +2889,7 @@ X86.opSTOSw = function STOSw()
this.backTrack.btiMemLo = this.backTrack.btiAL; this.backTrack.btiMemHi = this.backTrack.btiAH;
}
this.setSOWord(this.segES, this.regEDI & this.addrMask, this.regEAX);
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize)) & this.addrMask);
this.nStepCycles -= nCycles;
this.regECX -= nDelta;
if (nReps) {
@ -2943,11 +2955,11 @@ X86.opLODSw = function LODSw()
if (!(this.opPrefixes & X86.OPFLAG.REPEAT)) this.nStepCycles -= this.CYCLES.nOpCyclesLodSr0;
}
if (nReps--) {
this.regEAX = this.getSOWord(this.segData, this.regESI & this.addrMask);
this.regEAX = (this.regEAX & ~this.dataMask) | this.getSOWord(this.segData, this.regESI & this.addrMask);
if (BACKTRACK) {
this.backTrack.btiAL = this.backTrack.btiMemLo; this.backTrack.btiAH = this.backTrack.btiMemHi;
}
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize)) & this.addrMask);
this.nStepCycles -= nCycles;
this.regECX -= nDelta;
if (nReps) {
@ -3020,8 +3032,8 @@ X86.opSCASw = function SCASw()
if (!(this.opPrefixes & X86.OPFLAG.REPEAT)) this.nStepCycles -= this.CYCLES.nOpCyclesScaSr0;
}
if (nReps--) {
X86.fnCMPw.call(this, this.regEAX, this.modEAWord(this.segES, this.regEDI & this.addrMask));
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
X86.fnCMPw.call(this, this.regEAX & this.dataMask, this.modEAWord(this.segES, this.regEDI & this.addrMask));
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -this.dataSize : this.dataSize)) & this.addrMask);
/*
* NOTE: As long as we're calling opGrpCMPb(), all our cycle times must be reduced by nOpCyclesArithRM
*/
@ -3269,6 +3281,16 @@ X86.opGrp2wi = function GRP2wi()
this.aOpModGrpWord[this.getIPByte()].call(this, X86.aOpGrp2w, X86.fnGRPCountImm);
};
/**
* op=0xC1 (GRP2 dword,imm16) (80186/80188 and up)
*
* @this {X86CPU}
*/
X86.opGrp2di = function GRP2di()
{
this.aOpModGrpWord[this.getIPByte()].call(this, X86.aOpGrp2d, X86.fnGRPCountImm);
};
/**
* op=0xC2 (RET n)
*
@ -3502,6 +3524,16 @@ X86.opGrp2w1 = function GRP2w1()
this.aOpModGrpWord[this.getIPByte()].call(this, X86.aOpGrp2w, X86.fnGRPCount1);
};
/**
* op=0xD1 (GRP2 dword,1)
*
* @this {X86CPU}
*/
X86.opGrp2d1 = function GRP2d1()
{
this.aOpModGrpWord[this.getIPByte()].call(this, X86.aOpGrp2d, X86.fnGRPCount1);
};
/**
* op=0xD2 (GRP2 byte,CL)
*
@ -3522,6 +3554,16 @@ X86.opGrp2wCL = function GRP2wCL()
this.aOpModGrpWord[this.getIPByte()].call(this, X86.aOpGrp2w, X86.fnGRPCountCL);
};
/**
* op=0xD3 (GRP2 dword,CL)
*
* @this {X86CPU}
*/
X86.opGrp2dCL = function GRP2dCL()
{
this.aOpModGrpWord[this.getIPByte()].call(this, X86.aOpGrp2d, X86.fnGRPCountCL);
};
/**
* op=0xD4 0x0A (AAM)
*
@ -4098,11 +4140,11 @@ X86.opUndefined = function()
};
/**
* opTBDd()
* opTBD()
*
* @this {X86CPU}
*/
X86.opTBDd = function()
X86.opTBD = function()
{
this.printMessage("unimplemented 80386 opcode", true);
this.stopCPU();
@ -4268,6 +4310,11 @@ X86.aOpGrp2w = [
X86.fnSHLw, X86.fnSHRw, X86.fnGRPUndefined, X86.fnSARw // 0xD1/0xD3(reg=0x4-0x7)
];
X86.aOpGrp2d = [
X86.fnTBD, X86.fnTBD, X86.fnRCLd, X86.fnRCRd, // 0xD1/0xD3(reg=0x0-0x3)
X86.fnTBD, X86.fnTBD, X86.fnGRPUndefined, X86.fnTBD // 0xD1/0xD3(reg=0x4-0x7)
];
X86.aOpGrp3b = [
X86.fnTEST8, X86.fnGRPUndefined, X86.fnNOTb, X86.fnNEGb, // 0xF6(reg=0x0-0x3)
X86.fnMULb, X86.fnIMULb, X86.fnDIVb, X86.fnIDIVb // 0xF6(reg=0x4-0x7)
@ -4290,32 +4337,35 @@ X86.aOpGrp4w = [
if (I386) {
/*
* Until we have *d() forms of all *w() opcode handlers, we need to put in placeholders (ie, opTBDd())
* Until we have *d() forms of all *w() opcode handlers, we need to put in placeholders (ie, opTBD())
*/
X86.aOpsD = {
0x01: X86.opTBDd, // opADDmd()
0x03: X86.opTBDd, // opADDrd()
0x05: X86.opTBDd, // opADDAXd()
0x09: X86.opTBDd, // opORmd()
0x0B: X86.opTBDd, // opORrd()
0x0D: X86.opTBDd, // opORAXd()
0x11: X86.opTBDd, // opADCmd()
0x13: X86.opTBDd, // opADCrd()
0x15: X86.opTBDd, // opADCAXd()
0x19: X86.opTBDd, // opSBBmd()
0x1B: X86.opTBDd, // opSBBrd()
0x1D: X86.opTBDd, // opSBBAXd()
0x01: X86.opTBD, // opADDmd()
0x03: X86.opTBD, // opADDrd()
0x05: X86.opTBD, // opADDAXd()
0x09: X86.opTBD, // opORmd()
0x0B: X86.opTBD, // opORrd()
0x0D: X86.opTBD, // opORAXd()
0x11: X86.opTBD, // opADCmd()
0x13: X86.opTBD, // opADCrd()
0x15: X86.opTBD, // opADCAXd()
0x19: X86.opTBD, // opSBBmd()
0x1B: X86.opTBD, // opSBBrd()
0x1D: X86.opTBD, // opSBBAXd()
0x21: X86.opANDmd,
0x23: X86.opANDrd,
0x25: X86.opANDAXd,
0x29: X86.opTBDd, // opSUBmd()
0x2B: X86.opTBDd, // opSUBrd()
0x2D: X86.opTBDd, // opSUBAXd()
0x31: X86.opTBDd, // opXORmd()
0x29: X86.opTBD, // opSUBmd()
0x2B: X86.opTBD, // opSUBrd()
0x2D: X86.opTBD, // opSUBAXd()
0x31: X86.opTBD, // opXORmd()
0x33: X86.opXORrd,
0x35: X86.opTBDd, // opXORAXd()
0x39: X86.opTBDd, // opCMPmd()
0x3B: X86.opTBDd, // opCMPrd()
0x3D: X86.opTBDd // opCMPAXd()
0x35: X86.opTBD, // opXORAXd()
0x39: X86.opTBD, // opCMPmd()
0x3B: X86.opTBD, // opCMPrd()
0x3D: X86.opTBD, // opCMPAXd()
0xC1: X86.opGrp2di,
0xD1: X86.opGrp2d1,
0xD3: X86.opGrp2dCL
};
}

View file

@ -216,7 +216,7 @@ X86Seg.loadIDTReal = function loadIDTReal(nIDT)
var addrIDT = cpu.addrIDT + (nIDT << 2);
var off = cpu.getShort(addrIDT);
cpu.regPS &= ~(X86.PS.TF | X86.PS.IF);
return this.load(cpu.getShort(addrIDT + 2)) + off;
return (this.load(cpu.getShort(addrIDT + 2)) + off)|0;
};
/**
@ -254,7 +254,7 @@ X86Seg.loadIDTProt = function loadIDTProt(nIDT)
*/
X86Seg.checkReadReal = function checkReadReal(off, cb, fSuppress)
{
return (this.base + off) | 0;
return (this.base + off)|0;
};
/**
@ -271,7 +271,7 @@ X86Seg.checkReadReal = function checkReadReal(off, cb, fSuppress)
*/
X86Seg.checkWriteReal = function checkWriteReal(off, cb, fSuppress)
{
return (this.base + off) | 0;
return (this.base + off)|0;
};
/**
@ -286,7 +286,7 @@ X86Seg.checkWriteReal = function checkWriteReal(off, cb, fSuppress)
X86Seg.checkReadProt = function checkReadProt(off, cb, fSuppress)
{
if (off + cb <= this.limit) {
return this.base + off;
return (this.base + off)|0;
}
return X86Seg.checkReadProtDisallowed.call(this, off, cb, fSuppress);
};
@ -303,7 +303,7 @@ X86Seg.checkReadProt = function checkReadProt(off, cb, fSuppress)
X86Seg.checkReadProtDown = function checkReadProtDown(off, cb, fSuppress)
{
if (off + cb > this.limit) {
return this.base + off;
return (this.base + off)|0;
}
return X86Seg.checkReadProtDisallowed.call(this, off, cb, fSuppress);
};
@ -337,7 +337,7 @@ X86Seg.checkReadProtDisallowed = function checkReadProtDisallowed(off, cb, fSupp
X86Seg.checkWriteProt = function checkWriteProt(off, cb, fSuppress)
{
if (off + cb <= this.limit) {
return this.base + off;
return (this.base + off)|0;
}
return X86Seg.checkWriteProtDisallowed.call(this, off, cb, fSuppress);
};
@ -354,7 +354,7 @@ X86Seg.checkWriteProt = function checkWriteProt(off, cb, fSuppress)
X86Seg.checkWriteProtDown = function checkWriteProtDown(off, cb, fSuppress)
{
if (off + cb > this.limit) {
return this.base + off;
return (this.base + off)|0;
}
return X86Seg.checkWriteProtDisallowed.call(this, off, cb, fSuppress);
};