<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Thu, 11 May 1995 13:44:55 +0100
From   : lamcw <lamcw@...>
Subject: ADC, SBC and BCD

Hello all,


I had some problems with emulating the SBC opcode recently. SBC performs

  A-M-!C   where !C is the complement of C or 1-C

i.e.

  A-M-(1-C)  or A-(M+1-C).

This is just textbook stuff. So I went ahead and coded


    byte = M + 1 - C;

    result = rega - byte;

    if (rega>=byte) set C; else reset C;


Looks okay, the correct values were being churned out. Only when I came
across a game for another 6502 machine I'm emulating, did I notice that
either adds/subtractions were screwing up. Many hours of frustration later,
I realised I could not use the above strategy to evaluate the C flag.
Instead I needed

    wu = rega - M - 1 - C;   /* wu is unsigned int */

    if (wu&256) reset C; else set C;


The first method fails when M=255 and C=0. Then byte=0 (if byte is an 
unsigned char) and if rega=255 (say) the following 'if' statement will
set C when in fact it should reset C. The second method allows for this
and produces the correct C flag.

The bug in the first method is a little tricky to detect since it is
correct 255 out 256 times.


As for BCD arithmetic, I believe only the C flag functions as expected
both for ADC and SBC (in 64doc, it is claimed the C flag is incorrectly
set... but this is clearly unthinkable since multi-byte BCD subtractions
would not be possible). The N,V and Z flags are set according to the
BINARY result. i.e. 

  LDA#&99
  SED
  CLC
  ADC#1

will leave a result of zero in A but Z will NOT be set. The BINARY result
is &9A and hence Z is reset. Same for N and V flags.


Hope this is of some help,

Regards,


Chris Lam,
Aston University,
U.K.









<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>