Phase 1 of the flag logic switch

This commit is contained in:
Jeff Parsons 2015-03-16 16:29:04 -07:00 committed by jeffpar
commit fa35c2da72
2 changed files with 118 additions and 251 deletions

View file

@ -1767,7 +1767,6 @@ X86CPU.prototype.setArithResult = function(dst, src, value, type, fSubtract)
this.resultSrc = src;
this.resultLogic = value;
this.resultType = type;
if (DEBUG) this.verifyFlags(type);
};
/**
@ -1790,40 +1789,9 @@ X86CPU.prototype.setLogicResult = function(value, type, carry, overflow)
this.resultLogic = value;
if (carry) this.setCF(); else this.clearCF();
if (overflow) this.setOF(); else this.clearOF();
if (DEBUG) this.verifyFlags(X86.RESULT.LOGIC | X86.RESULT.CF | X86.RESULT.OF);
return value;
};
/**
* verifyFlags(flags)
*
* @this {X86CPU}
* @param {number} flags
*/
X86CPU.prototype.verifyFlags = function(flags)
{
if (DEBUG) {
if (flags & X86.RESULT.CF) {
this.assert(!this.getCF() == !(this.resultFlags & X86.PS.CF));
}
if (flags & X86.RESULT.PF) {
this.assert(!this.getPF() == !(this.resultFlags & X86.PS.PF));
}
if (flags & X86.RESULT.AF) {
this.assert(!this.getAF() == !(this.resultFlags & X86.PS.AF));
}
if (flags & X86.RESULT.ZF) {
this.assert(!this.getZF() == !(this.resultFlags & X86.PS.ZF));
}
if (flags & X86.RESULT.SF) {
this.assert(!this.getSF() == !(this.resultFlags & X86.PS.SF));
}
if (flags & X86.RESULT.OF) {
this.assert(!this.getOF() == !(this.resultFlags & X86.PS.OF));
}
}
};
/**
* getCarry()
*
@ -1871,7 +1839,7 @@ X86CPU.prototype.getCF = function()
}
this.resultType &= ~X86.RESULT.CF;
}
if (!OLDFLAGS) return this.resultFlags & X86.PS.CF;
return this.resultFlags & X86.PS.CF;
}
return flag;
};
@ -1913,7 +1881,7 @@ X86CPU.prototype.getPF = function()
}
this.resultType &= ~X86.RESULT.PF;
}
if (!OLDFLAGS) return this.resultFlags & X86.PS.PF;
return this.resultFlags & X86.PS.PF;
}
return flag;
};
@ -1955,7 +1923,7 @@ X86CPU.prototype.getAF = function()
}
this.resultType &= ~X86.RESULT.AF;
}
if (!OLDFLAGS) return this.resultFlags & X86.PS.AF;
return this.resultFlags & X86.PS.AF;
}
return flag;
};
@ -1977,7 +1945,7 @@ X86CPU.prototype.getZF = function()
}
this.resultType &= ~X86.RESULT.ZF;
}
if (!OLDFLAGS) return this.resultFlags & X86.PS.ZF;
return this.resultFlags & X86.PS.ZF;
}
return flag;
};
@ -1999,7 +1967,7 @@ X86CPU.prototype.getSF = function()
}
this.resultType &= ~X86.RESULT.SF;
}
if (!OLDFLAGS) return this.resultFlags & X86.PS.SF;
return this.resultFlags & X86.PS.SF;
}
return flag;
};
@ -2045,7 +2013,7 @@ X86CPU.prototype.getOF = function()
}
this.resultType &= ~X86.RESULT.OF;
}
if (!OLDFLAGS) return this.resultFlags & X86.PS.OF;
return this.resultFlags & X86.PS.OF;
}
return flag;
};
@ -2212,7 +2180,7 @@ X86CPU.prototype.setCF = function()
*/
X86CPU.prototype.setPF = function()
{
if (!this.getPF()) this.resultParitySign ^= 0x1;
if ((0x6996 >> ((this.resultParitySign ^ (this.resultParitySign >> 4)) & 0xf)) & 1) this.resultParitySign ^= 0x1;
if (I386) {
this.resultType &= ~X86.RESULT.PF;
this.resultFlags |= X86.PS.PF;
@ -2254,7 +2222,7 @@ X86CPU.prototype.setZF = function()
*/
X86CPU.prototype.setSF = function()
{
if (!this.getSF()) {
if (!(this.resultParitySign & (this.resultSize >> 1))) {
this.resultParitySign ^= (this.resultSize >> 1) | (this.resultSize >> 2);
this.resultAuxOverflow ^= X86.RESULT.AUXOVF_OF;
}

View file

@ -803,7 +803,7 @@ X86.fnINCr = function INCr(w)
if (OLDFLAGS) {
this.resultAuxOverflow = w;
this.resultParitySign = result;
this.resultZeroCarry = result | (((this.resultZeroCarry & this.resultSize)? 1 : 0) << 16);
this.resultZeroCarry = (result & 0xffff) | (((this.resultZeroCarry & this.resultSize)? 1 : 0) << 16);
this.resultSize = X86.RESULT.SIZE_WORD;
}
if (I386) {
@ -1247,6 +1247,9 @@ X86.fnMULb = function MULb(dst, src)
} else {
this.clearCF(); this.clearOF();
}
if (DEBUG) {
if (this.resultZeroCarry & (this.resultSize - 1)) this.clearZF(); else this.setZF();
}
/*
* Multiply/divide instructions specify only a single operand, which the decoders pass to us
* via the dst parameter, so we set src to the other implied operand (either AX or DX:AX).
@ -1276,6 +1279,9 @@ X86.fnMULw = function MULw(dst, src)
} else {
this.clearCF(); this.clearOF();
}
if (DEBUG) {
if (this.resultZeroCarry & (this.resultSize - 1)) this.clearZF(); else this.setZF();
}
/*
* Multiply/divide instructions specify only a single operand, which the decoders pass to us
* via the dst parameter, so we set src to the other implied operand (either AX or DX:AX).
@ -1465,29 +1471,19 @@ X86.fnRCLb = function RCLb(dst, src)
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var temp;
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 9;
if (!shift) {
temp = dst | (carry << 8);
carry <<= 7;
} else {
temp = (dst << shift) | (carry << (shift - 1)) | (dst >> (9 - shift));
result = temp & 0xff;
}
X86.fnRotateFlags.call(this, temp, X86.RESULT.SIZE_BYTE);
if (I386) {
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).
*/
temp = ((dst << shift) | (carry << (shift - 1)) | (dst >> (9 - shift))) & 0xff;
carry = dst << (shift - 1);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.BYTE);
/*
* 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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.BYTE);
}
if (DEBUG && DEBUGGER) this.traceLog('RCLB', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1504,29 +1500,19 @@ X86.fnRCLw = function RCLw(dst, src)
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var temp;
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 17;
if (!shift) {
temp = dst | (carry << 16);
carry <<= 15;
} else {
temp = (dst << shift) | (carry << (shift - 1)) | (dst >> (17 - shift));
result = temp & 0xffff;
}
X86.fnRotateFlags.call(this, temp, X86.RESULT.SIZE_WORD);
if (I386) {
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).
*/
temp = ((dst << shift) | (carry << (shift - 1)) | (dst >> (17 - shift))) & 0xffff;
carry = dst << (shift - 1);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.WORD);
/*
* 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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.WORD);
}
if (DEBUG && DEBUGGER) this.traceLog('RCLW', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1547,22 +1533,17 @@ X86.fnRCRb = function RCRb(dst, src)
if (src) {
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 9;
result = (dst >> shift) | (carry << (8 - shift)) | (dst << (9 - shift));
X86.fnRotateFlags.call(this, result, X86.RESULT.SIZE_BYTE);
result &= 0xff;
if (I386) {
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).
*/
var temp = ((dst >> shift) | (carry << (8 - shift)) | (dst << (9 - shift))) & 0xff;
carry = dst << (8 - shift);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.BYTE);
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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.BYTE);
}
if (DEBUG && DEBUGGER) this.traceLog('RCRB', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1583,22 +1564,17 @@ X86.fnRCRw = function RCRw(dst, src)
if (src) {
var carry = this.getCarry();
var shift = (src & this.nShiftCountMask) % 17;
result = (dst >> shift) | (carry << (16 - shift)) | (dst << (17 - shift));
X86.fnRotateFlags.call(this, result, X86.RESULT.SIZE_WORD);
result &= 0xffff;
if (I386) {
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).
*/
var temp = ((dst >> shift) | (carry << (16 - shift)) | (dst << (17 - shift))) & 0xffff;
carry = dst << (16 - shift);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.WORD);
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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.WORD);
}
if (DEBUG && DEBUGGER) this.traceLog('RCRW', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1655,32 +1631,23 @@ X86.fnROLb = function ROLb(dst, src)
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var temp;
var carry;
var shift = src & 0x7; // this smaller mask obviates the need to mask with this.nShiftCountMask
if (!shift) {
temp = dst << 8;
/*
* shift is 8, which means the new carry will come from the dst bit
* at position 0.
*/
carry = dst << 7;
} else {
result = (temp = (dst << shift) | (dst >> (8 - shift))) & 0xff;
}
X86.fnRotateFlags.call(this, temp, X86.RESULT.SIZE_BYTE);
if (I386) {
var carry;
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).
*/
temp = ((dst << shift) | (dst >> (8 - shift))) & 0xff;
carry = dst << (shift - 1);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.BYTE);
/*
* 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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.BYTE);
}
if (DEBUG && DEBUGGER) this.traceLog('ROLB', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1699,28 +1666,19 @@ X86.fnROLw = function ROLw(dst, src)
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var temp;
var carry;
var shift = src & 0xf; // this smaller mask obviates the need to mask with this.nShiftCountMask
if (!shift) {
temp = dst << 16;
carry = dst << 15;
} else {
result = (temp = (dst << shift) | (dst >> (16 - shift))) & 0xffff;
}
X86.fnRotateFlags.call(this, temp, X86.RESULT.SIZE_WORD);
if (I386) {
var carry;
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).
*/
temp = ((dst << shift) | (dst >> (16 - shift))) & 0xffff;
carry = dst << (shift - 1);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.WORD);
/*
* 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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.WORD);
}
if (DEBUG && DEBUGGER) this.traceLog('ROLW', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1739,29 +1697,23 @@ X86.fnRORb = function RORb(dst, src)
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var temp;
var carry;
var shift = src & 0x7; // this smaller mask obviates the need to mask with this.nShiftCountMask
result = temp = ((dst >> shift) | (dst << (8 - shift))) & 0xff;
if (temp & 0x80) temp |= X86.RESULT.SIZE_BYTE;
X86.fnRotateFlags.call(this, temp, X86.RESULT.SIZE_BYTE);
if (I386) {
var carry;
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).
*/
temp = ((dst >> shift) | (dst << (8 - shift))) & 0xff;
carry = dst << (8 - shift);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.BYTE);
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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.BYTE);
}
if (DEBUG && DEBUGGER) this.traceLog('RORB', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1780,29 +1732,23 @@ X86.fnRORw = function RORw(dst, src)
var result = dst;
var flagsIn = (DEBUG? this.getPS() : 0);
if (src) {
var temp;
var carry;
var shift = src & 0xf; // this smaller mask obviates the need to mask with this.nShiftCountMask
result = temp = ((dst >> shift) | (dst << (16 - shift))) & 0xffff;
if (temp & 0x8000) temp |= X86.RESULT.SIZE_WORD;
X86.fnRotateFlags.call(this, temp, X86.RESULT.SIZE_WORD);
if (I386) {
var carry;
if (!shift) {
/*
* shift is 16, which means the new carry will come from the dst bit
* at position 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).
*/
temp = ((dst >> shift) | (dst << (16 - shift))) & 0xffff;
carry = dst << (16 - shift);
}
X86.setRotateResult.call(this, temp, result, carry, X86.RESULT.WORD);
if (!shift) {
/*
* shift is 16, which means the new carry will come from the dst bit
* at position 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);
}
X86.setRotateResult.call(this, result, carry, X86.RESULT.WORD);
}
if (DEBUG && DEBUGGER) this.traceLog('RORW', dst, src, flagsIn, this.getPS(), result);
return result;
@ -1825,17 +1771,8 @@ X86.fnSARb = function SARb(dst, src)
if (src) {
if (src > 8) src = 9; // this comparison obviates the need to mask with this.nShiftCountMask
var temp = ((dst << 24) >> 24) >> (src - 1);
this.resultZeroCarry = this.resultParitySign = temp >> 1;
if (temp & 0x01)
this.resultZeroCarry |= X86.RESULT.SIZE_BYTE;
else
this.resultZeroCarry &= ~X86.RESULT.SIZE_BYTE;
this.resultAuxOverflow = dst ^ this.resultZeroCarry;
this.resultSize = X86.RESULT.SIZE_BYTE;
dst = this.resultZeroCarry & 0xff;
if (I386) {
this.setLogicResult(dst, X86.RESULT.BYTE, temp & 0x1);
}
dst = (temp >> 1) & 0xff;
this.setLogicResult(dst, X86.RESULT.BYTE, temp & 0x1);
}
return dst;
};
@ -1857,17 +1794,8 @@ X86.fnSARw = function SARw(dst, src)
if (src) {
if (src > 16) src = 17; // this comparison obviates the need to mask with this.nShiftCountMask
var temp = ((dst << 16) >> 16) >> (src - 1);
this.resultZeroCarry = this.resultParitySign = temp >> 1;
if (temp & 0x01)
this.resultZeroCarry |= X86.RESULT.SIZE_WORD;
else
this.resultZeroCarry &= ~X86.RESULT.SIZE_WORD;
this.resultAuxOverflow = dst ^ this.resultZeroCarry;
this.resultSize = X86.RESULT.SIZE_WORD;
dst = this.resultZeroCarry & 0xffff;
if (I386) {
this.setLogicResult(dst, X86.RESULT.WORD, temp & 0x1);
}
dst = (temp >> 1) & 0xffff;
this.setLogicResult(dst, X86.RESULT.WORD, temp & 0x1);
}
return dst;
};
@ -2002,16 +1930,12 @@ X86.fnSHLb = function SHLb(dst, src)
if (src) {
var carry = 0;
if (src > 8) { // this comparison obviates the need to mask with this.nShiftCountMask
result = this.resultZeroCarry = this.resultParitySign = 0;
result = 0;
} else {
carry = dst << (src - 1);
result = (this.resultZeroCarry = this.resultParitySign = (carry << 1)) & 0xff;
}
this.resultAuxOverflow = 0;
this.resultSize = X86.RESULT.SIZE_BYTE;
if (I386) {
X86.setRotateResult.call(this, result, result, carry, X86.RESULT.BYTE);
result = (carry << 1) & 0xff;
}
this.setLogicResult(result, X86.RESULT.BYTE, carry & X86.RESULT.BYTE, (result ^ carry) & X86.RESULT.BYTE);
}
if (DEBUG && DEBUGGER) this.traceLog('SHLB', dst, src, flagsIn, this.getPS(), result);
return result;
@ -2036,16 +1960,12 @@ X86.fnSHLw = function SHLw(dst, src)
if (src) {
var carry = 0;
if (src > 16) { // this comparison obviates the need to mask with this.nShiftCountMask
result = this.resultZeroCarry = this.resultParitySign = 0;
result = 0;
} else {
carry = dst << (src - 1);
result = (this.resultZeroCarry = this.resultParitySign = (carry << 1)) & 0xffff;
}
this.resultAuxOverflow = 0;
this.resultSize = X86.RESULT.SIZE_WORD;
if (I386) {
X86.setRotateResult.call(this, result, result, carry, X86.RESULT.WORD);
result = (carry << 1) & 0xffff;
}
this.setLogicResult(result, X86.RESULT.WORD, carry & X86.RESULT.WORD, (result ^ carry) & X86.RESULT.WORD);
}
if (DEBUG && DEBUGGER) this.traceLog('SHLW', dst, src, flagsIn, this.getPS(), result);
return result;
@ -2067,17 +1987,8 @@ X86.fnSHRb = function SHRb(dst, src)
{
if (src) { // the following comparison obviates the need to mask with this.nShiftCountMask
var temp = (src > 8? 0 : (dst >> (src - 1)));
this.resultZeroCarry = this.resultParitySign = temp >> 1;
if (temp & 0x01)
this.resultZeroCarry |= X86.RESULT.SIZE_BYTE;
else
this.resultZeroCarry &= ~X86.RESULT.SIZE_BYTE;
this.resultAuxOverflow = dst ^ this.resultZeroCarry;
this.resultSize = X86.RESULT.SIZE_BYTE;
dst = this.resultZeroCarry & 0xff;
if (I386) {
this.setLogicResult(dst, X86.RESULT.BYTE, temp & 0x1, dst & X86.RESULT.BYTE);
}
dst = (temp >> 1) & 0xff;
this.setLogicResult(dst, X86.RESULT.BYTE, temp & 0x1, dst & X86.RESULT.BYTE);
}
return dst;
};
@ -2098,17 +2009,8 @@ X86.fnSHRw = function SHRw(dst, src)
{
if (src) { // the following comparison obviates the need to mask with this.nShiftCountMask
var temp = (src > 16? 0 : (dst >> (src - 1)));
this.resultZeroCarry = this.resultParitySign = temp >> 1;
if (temp & 0x01)
this.resultZeroCarry |= X86.RESULT.SIZE_WORD;
else
this.resultZeroCarry &= ~X86.RESULT.SIZE_WORD;
this.resultAuxOverflow = dst ^ this.resultZeroCarry;
this.resultSize = X86.RESULT.SIZE_WORD;
dst = this.resultZeroCarry & 0xffff;
if (I386) {
this.setLogicResult(dst, X86.RESULT.WORD, temp & 0x1, dst & X86.RESULT.WORD);
}
dst = (temp >> 1) & 0xffff;
this.setLogicResult(dst, X86.RESULT.WORD, temp & 0x1, dst & X86.RESULT.WORD);
}
return dst;
};
@ -2647,17 +2549,14 @@ X86.fnRotateFlags = function(result, size)
* defined behavior (or more importantly, some dependency on a different behavior), this seems good enough.
*
* @this {X86CPU}
* @param {number} temp (I386 result)
* @param {number} result
* @param {number} carry
* @param {number} size
*/
X86.setRotateResult = function(temp, result, carry, size)
X86.setRotateResult = function(result, carry, size)
{
this.assert(temp === result && !(carry & size) == !this.getCF() && !((result ^ carry) & size) == !this.getOF());
if (carry & size) this.setCF(); else this.clearCF();
if ((result ^ carry) & size) this.setOF(); else this.clearOF();
this.verifyFlags(X86.RESULT.CF | X86.RESULT.OF);
};
/**