Raandaall_Flaagg wrote:
(Not sure if 0 is classed as positive)
Well, if you're talking there about whether the 6502 classes zero as positive, you just need to ask yourself what `BPL` does when the last test tested a 0 value.
Raandaall_Flaagg wrote:
This makes perfect sense. I have been handling them as two values, but should be handling as three values.
Right. But you
were handling them as three values at some point, so it's really more a question of
where you handle the values. This misconception burned me as well in my 6800 simulator's first implementation of ADC and SBC. It originally looked like this:
Code:
def sub(m, minuend, subtrahend, affectC=True): # `m` is the "machine" object
# ...calculate, set flags, return result...
def suba(m): m.a = sub(m, m.a, readbyte(m)) # immediate; readbyte(m) reads byte at PC++
def subaz(m): m.a = sub(m, m.a, m.mem[readbyte(m)]) # zero page addressing
def sbca(m): m.a = sub(m, m.a, readbyte(m)+m.C) # adding because C is the "borrow" flag on 6800
def sbcaz(m): m.a = sub(m, m.a, m.mem[readbyte(m)]+m.C)
# etc. for other addressing modes
(Side note: when comparing 6800 code with 6502 code, remember that the 6502 uses the C flag differently: when subtracting C is a "not borrow" flag on the 6502.)
You can probably now see the
conceptual problem there in the structure of the simulator: the routine that does the arithmetic for subtract instructions doesn't do
all of the arithemtic calculations; in the case of the SBC instruction some of the calculations are done
outside that routine, before it is called. Thus the "ALU" doesn't actually see the original inputs, and what it sees as the subtrahend is sometimes not actually the real subtrahend. Oops!
The solution, of course, is to stop doing arithmetic on parameters outside of sub() and instead pass in
all of the parameters:
Code:
def sub(m, minuend, subtrahend, borrow=0, affectC=True):
...
# just one line added to the body:
difference = incbyte(difference, -borrow)
...
def sbca(m): m.a = sub(m, m.a, readbyte(m), borrow=m.C)
# etc.
In my case that alone, with no changes to the flag calculations in sub(), fixed the problem. (I was setting flags based on the equations handily provided by Motorola in their reference guide; the flags were wrong because I was calculating them based on the subtrahend plus the borrow, rather than the actual subtrahend.)
You may find it worthwhile having a look to see if your code design and/or something in your conception of your emulator's CPU model helped lead toward this bug, too, since such conceptual errors can lead to other bugs as well (either now or in the future when someone tweaks something).