bruce_lee wrote:
the results i get :
accumulator = 225; //overflow was set and carry
processor_stat = 241;
result from simulator:
accumulator = 160; //negative flag was set
processor_stat = 241
It looks like you've swapped the values of the accumulator and processor_stat in this part of your post. If so, it would appear that the value of M you used was 225 (you didn't mention what value you plugged in there). In that case, the "simulator" results are correct, i.e. entering with:
A register = 16, M variable = 225, d flag = 0, c flag = 0
the result should be:
A register = 241, n flag = 1, v flag = 0, z flag = 0, c flag = 0
The logic of what you are doing appears to be correct, but you have to pay careful attention to the width of t, the width of the subtraction operation, whether A and M are being sign extended, and whether the comparisons are signed or unsigned.
One thing that would give the behavior that you see is if t were declared as an unsigned variable. All unsigned values are greater than 0 so the t>=0 comparison would always be true. The t>127 OR t<-128 comparsions, for a 16-bit variable (e.g.) would be equivalent to the comparison unsigned comparsion (t > 127 AND t <= 65535) OR (t >= 0 AND t < 65536-128), which is always true.
Remember, the C flag is based on unsigned subtraction, and the V flag is based on signed subtraction. Here's one (untested) way of doing it (for the d flag = 0 case):
Code:
// Inputs:
//
// A: 8-bit integer
// C: 0 or 1
// M: 8-bit integer
//
// Outputs:
//
// A: 8-bit integer
// C: 0 or 1
// N: 0 or 1
// V: 0 or 1
// Z: 0 or 1
//
// Local variables:
//
// a16: signed 16-bit integer
// m16: signed 16-bit integer
// t: signed 16-bit integer
// when d flag is zero
// signed subtraction
a16 = A
m16 = M
a16 = (a16 & 0x7F) // ensure that 0 <= a16 <= 127
m16 = (m16 & 0x7F) // ensure that 0 <= m16 <= 127
a16 = a16 - (((A & 0x80) == 0) ? 0 : 128) // ensure that -128 <= a16 <= 127
m16 = m16 - (((M & 0x80) == 0) ? 0 : 128) // ensure that -128 <= m16 <= 127
t = a16 - m16 - C
V = (t >= -128 AND t <= 127) ? 0 : 1
// unsigned subtraction
a16 = A
m16 = M
a16 = (a16 & 0x00FF) // ensure that 0 <= a16 <= 255
m16 = (m16 & 0x00FF) // ensure that 0 <= a16 <= 255
t = a16 - m16 - C
A = (t & 0x00FF)
C = (t < 0) ? 0 : 1
N = ((t & 0x0080) == 0) ? 0 : 1
Z = ((t & 0x00FF) == 0) ? 0 : 1
Another option for the d flag = 0 case is to reuse your ADC code. Just call the ADC code with M XOR 0xFF (for 8-bit values, this is equal to 255-M). In other words:
SBC #NUMBER
gives exactly the same results (A register, and N, V, Z, and C flags) as:
ADC #255-NUMBER
assuming that, upon entry, the D flag was 0, and the same value of the A register and C flag were used in each case.