我一直在为MOS 6502开发一个仿真器,但是似乎无法使ADC和SBC正常工作。我正在用在仿真内存中0x4000加载的AllSuiteA program测试我的仿真器,对于test09,我当前的ADC和SBC实现都没有得到正确的标志。我已经尝试了无数次更改其算法,但是每次,进位标志和溢出标志都足够重要,并且会导致测试分支/不分支。
Both of my functions are based off this.
memory [0x10000]是累加器。它存储在内存范围之外,因此我可以有一个单独的寻址开关语句。
这是我对这些功能的实现之一:
case "ADC":
var t = memory[0x10000] + memory[address] + getFlag(flag_carry);
(memory[0x10000] & 0x80) != (t & 0x80) ? setFlag(flag_overflow) : clearFlag(flag_overflow);
signCalc(memory[0x10000]);
zeroCalc(t);
t > 255 ? setFlag(flag_carry) : clearFlag(flag_carry);
memory[0x10000] = t & 0xFF;
break;
case "SBC":
var t = memory[0x10000] - memory[address] - (!getFlag(flag_carry));
(t > 127 || t < -128) ? setFlag(flag_overflow) : clearFlag(flag_overflow);
t >= 0 ? setFlag(flag_carry) : clearFlag(flag_carry);
signCalc(t);
zeroCalc(t);
memory[0x10000] = t & 0xFF;
break;
在这一点上,我全都没主意,所以but I did also run into the same problem with the data offered here.因此,在这里失败的不仅仅是一个实现计划。 最佳答案
欢迎勇敢的冒险家来到6502“添加”和“减去”命令的奥秘大厅!许多人已经走在了您前面的这些步骤上,尽管很少有人完成了等待您的尝试。粗壮的心!
好,戏剧结束了。简而言之,ADC和SBC是几乎最难模拟的6502指令,主要是因为它们是令人难以置信的复杂逻辑。它们处理进位,溢出和十进制模式,并且当然实际上依赖于可以被认为是“隐藏”伪寄存器工作存储的东西。
更糟糕的是,关于这些说明的文章很多,而那里的很多文献都是错误的。我在2008年解决了这个问题,花了许多时间研究并从谷 shell 中分离出小麦。结果是一些我在这里重现的C#代码:
case 105: // ADC Immediate
_memTemp = _mem[++_PC.Contents];
_TR.Contents = _AC.Contents + _memTemp + _SR[_BIT0_SR_CARRY];
if (_SR[_BIT3_SR_DECIMAL] == 1)
{
if (((_AC.Contents ^ _memTemp ^ _TR.Contents) & 0x10) == 0x10)
{
_TR.Contents += 0x06;
}
if ((_TR.Contents & 0xf0) > 0x90)
{
_TR.Contents += 0x60;
}
}
_SR[_BIT6_SR_OVERFLOW] = ((_AC.Contents ^ _TR.Contents) & (_memTemp ^ _TR.Contents) & 0x80) == 0x80 ? 1 : 0;
_SR[_BIT0_SR_CARRY] = (_TR.Contents & 0x100) == 0x100 ? 1 : 0;
_SR[_BIT1_SR_ZERO] = _TR.Contents == 0 ? 1 : 0;
_SR[_BIT7_SR_NEGATIVE] = _TR[_BIT7_SR_NEGATIVE];
_AC.Contents = _TR.Contents & 0xff;
break;