The 8080 CPU now passes all the 8080 Exerciser tests
This commit is contained in:
parent
a64a6e7e05
commit
41f58a0035
7 changed files with 1231 additions and 1231 deletions
|
|
@ -441,24 +441,18 @@ CPUDef.opMVIH = function()
|
|||
*/
|
||||
CPUDef.opDAA = function()
|
||||
{
|
||||
var acc = this.regA;
|
||||
var fCarry = !!this.getCF();
|
||||
var fAuxCarry = !!this.getAF();
|
||||
if ((acc & 0xf) > 9 || fAuxCarry) {
|
||||
acc += 0x6;
|
||||
fAuxCarry = true;
|
||||
} else {
|
||||
fAuxCarry = false;
|
||||
var src = 0;
|
||||
var CF = this.getCF();
|
||||
var AF = this.getAF();
|
||||
if (AF || (this.regA & 0x0F) > 9) {
|
||||
src |= 0x06;
|
||||
}
|
||||
if (acc >= 0xa0 || fCarry) {
|
||||
acc += 0x60;
|
||||
fCarry = true;
|
||||
} else {
|
||||
fCarry = false;
|
||||
if (CF || this.regA >= 0x9A) {
|
||||
src |= 0x60;
|
||||
CF = CPUDef.PS.CF;
|
||||
}
|
||||
this.resultZeroCarry = this.resultParitySign = this.regA = (acc & 0xff);
|
||||
this.updateCF(fCarry);
|
||||
this.updateAF(fAuxCarry);
|
||||
this.regA = this.addByte(src);
|
||||
this.updateCF(!!CF);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2055,7 +2049,7 @@ CPUDef.opORAA = function()
|
|||
*/
|
||||
CPUDef.opCMPB = function()
|
||||
{
|
||||
this.cmpByte(this.regB);
|
||||
this.subByte(this.regB);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2066,7 +2060,7 @@ CPUDef.opCMPB = function()
|
|||
*/
|
||||
CPUDef.opCMPC = function()
|
||||
{
|
||||
this.cmpByte(this.regC);
|
||||
this.subByte(this.regC);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2077,7 +2071,7 @@ CPUDef.opCMPC = function()
|
|||
*/
|
||||
CPUDef.opCMPD = function()
|
||||
{
|
||||
this.cmpByte(this.regD);
|
||||
this.subByte(this.regD);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2088,7 +2082,7 @@ CPUDef.opCMPD = function()
|
|||
*/
|
||||
CPUDef.opCMPE = function()
|
||||
{
|
||||
this.cmpByte(this.regE);
|
||||
this.subByte(this.regE);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2099,7 +2093,7 @@ CPUDef.opCMPE = function()
|
|||
*/
|
||||
CPUDef.opCMPH = function()
|
||||
{
|
||||
this.cmpByte(this.regH);
|
||||
this.subByte(this.regH);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2110,7 +2104,7 @@ CPUDef.opCMPH = function()
|
|||
*/
|
||||
CPUDef.opCMPL = function()
|
||||
{
|
||||
this.cmpByte(this.regL);
|
||||
this.subByte(this.regL);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2121,7 +2115,7 @@ CPUDef.opCMPL = function()
|
|||
*/
|
||||
CPUDef.opCMPM = function()
|
||||
{
|
||||
this.cmpByte(this.getByte(this.getHL()));
|
||||
this.subByte(this.getByte(this.getHL()));
|
||||
this.nStepCycles -= 7;
|
||||
};
|
||||
|
||||
|
|
@ -2132,7 +2126,7 @@ CPUDef.opCMPM = function()
|
|||
*/
|
||||
CPUDef.opCMPA = function()
|
||||
{
|
||||
this.cmpByte(this.regA);
|
||||
this.subByte(this.regA);
|
||||
this.nStepCycles -= 4;
|
||||
};
|
||||
|
||||
|
|
@ -2859,7 +2853,7 @@ CPUDef.opCM = function()
|
|||
*/
|
||||
CPUDef.opCPI = function()
|
||||
{
|
||||
this.cmpByte(this.getPCByte());
|
||||
this.subByte(this.getPCByte());
|
||||
this.nStepCycles -= 7;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -749,34 +749,11 @@ CPUSim.prototype.andByte = function(src)
|
|||
return this.resultZeroCarry;
|
||||
};
|
||||
|
||||
/**
|
||||
* cmpByte(src)
|
||||
*
|
||||
* We perform this operation using 8-bit two's complement arithmetic, by negating src, adding,
|
||||
* and then inverting the resulting carry (resultZeroCarry ^ 0x100). This appears to mimic how
|
||||
* the 8080 manages the Auxiliary Carry flag (AF).
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @param {number} src
|
||||
*/
|
||||
CPUSim.prototype.cmpByte = function(src)
|
||||
{
|
||||
src = -src & 0xff;
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
/*
|
||||
* The final AND with 0xff isn't strictly necessary, since the result of the comparison is
|
||||
* not returned, but I like limiting the result variables to tidy 8-bit values (resultZeroCarry
|
||||
* being the 9-bit exception).
|
||||
*/
|
||||
this.resultParitySign = (this.resultZeroCarry = (this.regA + src) ^ 0x100) & 0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
* decByte(b)
|
||||
*
|
||||
* We perform this operation using 8-bit two's complement arithmetic, by negating src, adding,
|
||||
* and then inverting the resulting carry (resultZeroCarry ^ 0x100). This appears to mimic how
|
||||
* the 8080 manages the Auxiliary Carry flag (AF).
|
||||
* We perform this operation using 8-bit two's complement arithmetic, by negating and then adding
|
||||
* the implied src of 1. This appears to mimic how the 8080 manages the Auxiliary Carry flag (AF).
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @param {number} b
|
||||
|
|
@ -820,9 +797,32 @@ CPUSim.prototype.orByte = function(src)
|
|||
/**
|
||||
* subByte(src)
|
||||
*
|
||||
* We perform this operation using 8-bit two's complement arithmetic, by negating src, adding,
|
||||
* and then inverting the resulting carry (resultZeroCarry ^ 0x100). This appears to mimic how
|
||||
* the 8080 manages the Auxiliary Carry flag (AF).
|
||||
* We perform this operation using 8-bit two's complement arithmetic, by inverting src, adding
|
||||
* src + 1, and then inverting the resulting carry (resultZeroCarry ^ 0x100). This appears to mimic
|
||||
* how the 8080 manages the Auxiliary Carry flag (AF).
|
||||
*
|
||||
* This function is also used as a cmpByte() function; compare instructions simply ignore the
|
||||
* return value.
|
||||
*
|
||||
* Example: A=66, SUI $10
|
||||
*
|
||||
* If we created the two's complement of 0x10 by negating it, there would just be one addition:
|
||||
*
|
||||
* 0110 0110 (0x66)
|
||||
* + 1111 0000 (0xF0) (ie, -0x10)
|
||||
* ---------
|
||||
* 1 0101 0110 (0x56)
|
||||
*
|
||||
* But in order to mimic the 8080's AF flag, we must perform the two's complement of src in two steps,
|
||||
* inverting it before the add, and then incrementing after the add; eg:
|
||||
*
|
||||
* 0110 0110 (0x66)
|
||||
* + 1110 1111 (0xEF) (ie, ~0x10)
|
||||
* ---------
|
||||
* 1 0101 0101 (0x55)
|
||||
* + 0000 0001 (0x01)
|
||||
* ---------
|
||||
* 1 0101 0110 (0x56)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @param {number} src
|
||||
|
|
@ -830,17 +830,20 @@ CPUSim.prototype.orByte = function(src)
|
|||
*/
|
||||
CPUSim.prototype.subByte = function(src)
|
||||
{
|
||||
src = -src & 0xff;
|
||||
src ^= 0xff;
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
return this.resultParitySign = (this.resultZeroCarry = (this.regA + src) ^ 0x100) & 0xff;
|
||||
return this.resultParitySign = (this.resultZeroCarry = (this.regA + src + 1) ^ 0x100) & 0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
* subByteBorrow(src)
|
||||
*
|
||||
* We perform this operation using 8-bit two's complement arithmetic, by negating (src + carry),
|
||||
* adding, and then inverting the resulting carry (resultZeroCarry ^ 0x100). This appears to mimic
|
||||
* how the 8080 manages the Auxiliary Carry flag (AF).
|
||||
* We perform this operation using 8-bit two's complement arithmetic, using logic similar to subByte(),
|
||||
* but changing the final increment to a conditional increment, because if the Carry flag (CF) is set, then
|
||||
* we don't need to perform the increment at all.
|
||||
*
|
||||
* This mimics the behavior of subByte() when the Carry flag (CF) is clear, and hopefully also mimics how the
|
||||
* 8080 manages the Auxiliary Carry flag (AF) when the Carry flag (CF) is set.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @param {number} src
|
||||
|
|
@ -848,9 +851,9 @@ CPUSim.prototype.subByte = function(src)
|
|||
*/
|
||||
CPUSim.prototype.subByteBorrow = function(src)
|
||||
{
|
||||
src = -(src + ((this.resultZeroCarry & 0x100)? 1 : 0)) & 0xff;
|
||||
src ^= 0xff
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
return this.resultParitySign = (this.resultZeroCarry = (this.regA + src) ^ 0x100) & 0xff;
|
||||
return this.resultParitySign = (this.resultZeroCarry = (this.regA + src + ((this.resultZeroCarry & 0x100)? 0 : 1)) ^ 0x100) & 0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2544,7 +2544,7 @@ X86CPU.prototype.getPF = function()
|
|||
* getAF()
|
||||
*
|
||||
* To determine if there's been a carry out of the low 4 bits of an arithmetic operation,
|
||||
* we look at all the possible inputs for bit 4, and calculate AF = PS^(D^S):
|
||||
* we look at all the possible inputs for bit 4, and calculate AF = A^(D^S).
|
||||
*
|
||||
* D S A D^S AF
|
||||
* - - - --- --
|
||||
|
|
|
|||
Loading…
Reference in a new issue