Bugfixes to ADC/RRA and SBC/IBC opcodes in BCD mode. Thanks to the

guys on the Stella mailing list (especially Seagtgruff) for advice
and sample test ROMs wrt BCD mode.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1708 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-04-20 15:03:13 +00:00
parent 22311086fd
commit 41010aa5ee
5 changed files with 1211 additions and 1184 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: M6502.cxx,v 1.24 2009-01-01 18:13:38 stephena Exp $
// $Id: M6502.cxx,v 1.25 2009-04-20 15:03:13 stephena Exp $
//============================================================================
#include "M6502.hxx"
@ -37,16 +37,8 @@ M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
myWriteTraps = NULL;
#endif
// Compute the BCD lookup table
uInt16 t;
for(t = 0; t < 256; ++t)
{
ourBCDTable[0][t] = ((t >> 4) * 10) + (t & 0x0f);
ourBCDTable[1][t] = (((t % 100) / 10) << 4) | (t % 10);
}
// Compute the System Cycle table
for(t = 0; t < 256; ++t)
for(uInt32 t = 0; t < 256; ++t)
{
myInstructionSystemCycleTable[t] = ourInstructionProcessorCycleTable[t] *
mySystemCyclesPerProcessorCycle;
@ -190,9 +182,6 @@ ostream& operator<<(ostream& out, const M6502::AddressingMode& mode)
return out;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 M6502::ourBCDTable[2][256];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::AddressingMode M6502::ourAddressingModeTable[256] = {
Implied, IndirectX, Invalid, IndirectX, // 0x0?
@ -461,8 +450,9 @@ void M6502::delCondBreak(unsigned int brk)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6502::clearCondBreaks()
{
for(unsigned int i=0; i<myBreakConds.size(); i++)
for(uInt32 i = 0; i < myBreakConds.size(); i++)
delete myBreakConds[i];
myBreakConds.clear();
myBreakCondNames.clear();
}
@ -476,7 +466,7 @@ const StringList& M6502::getCondBreakNames() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int M6502::evalCondBreaks()
{
for(unsigned int i=0; i<myBreakConds.size(); i++)
for(uInt32 i = 0; i < myBreakConds.size(); i++)
if(myBreakConds[i]->evaluate())
return i;
@ -495,4 +485,5 @@ void M6502::setTraps(PackedBitArray *read, PackedBitArray *write)
myReadTraps = read;
myWriteTraps = write;
}
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: M6502.hxx,v 1.23 2009-01-01 18:13:38 stephena Exp $
// $Id: M6502.hxx,v 1.24 2009-04-20 15:03:13 stephena Exp $
//============================================================================
#ifndef M6502_HXX
@ -41,7 +41,7 @@ typedef Common::Array<Expression*> ExpressionList;
has a 64K addressing space.
@author Bradford W. Mott
@version $Id: M6502.hxx,v 1.23 2009-01-01 18:13:38 stephena Exp $
@version $Id: M6502.hxx,v 1.24 2009-04-20 15:03:13 stephena Exp $
*/
class M6502
{
@ -325,9 +325,6 @@ class M6502
/// This specifies how the opcode will access its argument
static AccessMode ourAccessModeTable[256];
/// Lookup table used for binary-code-decimal math
static uInt8 ourBCDTable[2][256];
/**
Table of instruction processor cycle times. In some cases additional
cycles will be added during the execution of an instruction.

View File

@ -13,14 +13,17 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: M6502.m4,v 1.7 2008-04-27 11:53:22 stephena Exp $
// $Id: M6502.m4,v 1.8 2009-04-20 15:03:13 stephena Exp $
//============================================================================
/**
Code and cases to emulate each of the 6502 instruction
Recompile with the following:
'm4 M6502[Hi|Low].m4 M6502.m4 > M6502[Hi|Low].ins'
@author Bradford W. Mott
@version $Id: M6502.m4,v 1.7 2008-04-27 11:53:22 stephena Exp $
@version $Id: M6502.m4,v 1.8 2009-04-20 15:03:13 stephena Exp $
*/
#ifndef NOTSAMEPAGE
@ -28,28 +31,33 @@
#endif
define(M6502_ADC, `{
uInt8 oldA = A;
Int16 nonBCDSum = (Int16)A + (Int16)operand + (C ? 1 : 0);
if(!D)
{
Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0);
V = ((sum > 127) || (sum < -128));
Int32 sum = A + operand + (C ? 1 : 0);
N = sum & 0x80;
V = ~(A ^ operand) & (A ^ sum) & 0x80;
notZ = sum & 0xff;
C = sum & 0xff00;
A = nonBCDSum;
C = (nonBCDSum > 0xff);
notZ = A;
N = A & 0x80;
A = (uInt8) sum;
}
else
{
Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0);
Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
Int32 hi = (A & 0xf0) + (operand & 0xf0);
notZ = (lo+hi) & 0xff;
if(lo > 0x09)
{
hi += 0x10;
lo += 0x06;
}
N = hi & 0x80;
V = ~(A ^ operand) & (A ^ hi) & 0x80;
if(hi > 0x90)
hi += 0x60;
C = hi & 0xff00;
notZ = nonBCDSum & 0xff; // Z flag calculation ignores D flag
C = (sum > 99);
A = ourBCDTable[1][sum & 0xff];
N = A & 0x80;
V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80);
A = (lo & 0x0f) + (hi & 0xf0);
}
}')
@ -273,35 +281,31 @@ define(M6502_ISB, `{
operand = operand + 1;
poke(operandAddress, operand);
uInt8 oldA = A;
// N, V, Z, C flags are the same in either mode (C calculated at the end)
Int32 sum = A - operand - (C ? 0 : 1);
N = sum & 0x80;
V = (A ^ operand) & (A ^ sum) & 0x80;
notZ = sum & 0xff;
if(!D)
{
operand = ~operand;
Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0);
V = ((difference > 127) || (difference < -128));
difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0);
A = difference;
C = (difference > 0xff);
notZ = A;
N = A & 0x80;
A = (uInt8) sum;
}
else
{
Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand]
- (C ? 0 : 1);
Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
Int32 hi = (A & 0xf0) - (operand & 0xf0);
if(lo & 0x10)
{
lo -= 6;
hi--;
}
if(hi & 0x0100)
hi -= 0x60;
if(difference < 0)
difference += 100;
A = ourBCDTable[1][difference];
notZ = A;
N = A & 0x80;
C = (oldA >= (operand + (C ? 0 : 1)));
V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80);
A = (lo & 0x0f) | (hi & 0xf0);
}
C = (sum & 0xff00) == 0;
}')
define(M6502_JMP, `{
@ -472,7 +476,6 @@ define(M6502_RORA, `{
}')
define(M6502_RRA, `{
uInt8 oldA = A;
bool oldC = C;
// Set carry flag according to the right-most bit
@ -483,24 +486,31 @@ define(M6502_RRA, `{
if(!D)
{
Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0);
V = ((sum > 127) || (sum < -128));
Int32 sum = A + operand + (C ? 1 : 0);
N = sum & 0x80;
V = ~(A ^ operand) & (A ^ sum) & 0x80;
notZ = sum & 0xff;
C = sum & 0xff00;
sum = (Int16)A + (Int16)operand + (C ? 1 : 0);
A = sum;
C = (sum > 0xff);
notZ = A;
N = A & 0x80;
A = (uInt8) sum;
}
else
{
Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0);
Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
Int32 hi = (A & 0xf0) + (operand & 0xf0);
notZ = (lo+hi) & 0xff;
if(lo > 0x09)
{
hi += 0x10;
lo += 0x06;
}
N = hi & 0x80;
V = ~(A ^ operand) & (A ^ hi) & 0x80;
if(hi > 0x90)
hi += 0x60;
C = hi & 0xff00;
C = (sum > 99);
A = ourBCDTable[1][sum & 0xff];
notZ = A;
N = A & 0x80;
V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80);
A = (lo & 0x0f) + (hi & 0xf0);
}
}')
@ -523,36 +533,31 @@ define(M6502_SAX, `{
}')
define(M6502_SBC, `{
uInt8 oldA = A;
// N, V, Z, C flags are the same in either mode (C calculated at the end)
Int32 sum = A - operand - (C ? 0 : 1);
N = sum & 0x80;
V = (A ^ operand) & (A ^ sum) & 0x80;
notZ = sum & 0xff;
if(!D)
{
operand = ~operand;
Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0);
V = ((difference > 127) || (difference < -128));
difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0);
A = difference;
C = (difference > 0xff);
notZ = A;
N = A & 0x80;
A = (uInt8) sum;
}
else
{
Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand]
- (C ? 0 : 1);
Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
Int32 hi = (A & 0xf0) - (operand & 0xf0);
if(lo & 0x10)
{
lo -= 6;
hi--;
}
if(hi & 0x0100)
hi -= 0x60;
if(difference < 0)
difference += 100;
// Z flag calculation ignores D flag
notZ = (((Int16)A) + ((Int16)~operand) + (C ? 1 : 0)) & 0xff;
A = ourBCDTable[1][difference];
N = A & 0x80;
C = (oldA >= (operand + (C ? 0 : 1)));
V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80);
A = (lo & 0x0f) | (hi & 0xf0);
}
C = (sum & 0xff00) == 0;
}')
define(M6502_SBX, `{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff