[comp.sys.apple2] 65C02 ADC in Decimal Mode

lee@chsun1.uchicago.edu (Dwight A Lee) (02/19/91)

I'm writing a function in C which needs to behave exactly like a 65C02
ADC (add with carry).  Unfortunately, I am unable to find out just how
the N (negative) and V (overflow) processor flags are set when the
processor is in decimal mode.

Either direct information or pointers to information sources would be
appreciated.

I seem to recall reading in Litchy & Eyes (_Programming the 65816_)
that N and V were not used in decimal-mode ADC on the 6502, but that
this was corrected in the 65C02 and later 65 processors.

On a related note, how would negative decimal numbers be represented?
Is there a standard way?  If 99, for example, was used as a -1,
wouldn't this limit one-byte representations to a single digit (for
posible multiple-byte calculations) or to a lopsided range (if the
high bit is used as in binary mode)?

Thanks for any information.  Email or post.  Net summary will be
provided if more than two "me too" requests are received.
-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dwight A Lee / lee@chsun1.uchicago.edu / T904107@niucs.BITNET / tCS/BB / Font
I speak only for myself.  /  "I am not the only dust my mother raised" - TMBG

hemphill@over.world (Scott Hemphill) (02/19/91)

>>>>> On 19 Feb 91 00:34:54 GMT, lee@chsun1.uchicago.edu (Dwight A Lee) said:

> I'm writing a function in C which needs to behave exactly like a 65C02
> ADC (add with carry).  Unfortunately, I am unable to find out just how
> the N (negative) and V (overflow) processor flags are set when the
> processor is in decimal mode.

Here is some C code that is straight out of a simulator I have written for
the 65c02.  I have verified that it gives the correct answers for all possible
operands.  (Even when adding invalid bcd in decimal mode!)

Variables:
   A   the accumulator (an unsigned char)
   b   the other operand (an unsigned char)
   C   the carry flag (0 or 1)
   D   the decimal mode flag (0 or 1)
   V   the overflow flag (0 or 1)
   w   (an unsigned int temporary)
   NZ  the N and Z flags are derived from this unsigned int

A word of explation about "NZ": one optimization my simulator makes is to
avoid computing the N and Z bits unnecessarily.  I do this by storing an
intermediate value in NZ.  If I need to compute "N" or "Z" later, I can
do so.  "N" is equivalent to (NZ >= 0x80) and "Z" is equivalent to
((Z & 0xff) == 0).  Anyway, here's the code:

#define ADC()                                        \
      do {                                           \
        if ((A^b) & 0x80) V = 0; else V = 1;         \
        if (D) {                                     \
          w = (A & 0xf) + (b & 0xf) + C;             \
          if (w >= 10) w = 0x10 | ((w+6)&0xf);       \
          w += (A & 0xf0) + (b & 0xf0);              \
          if (w >= 160) {                            \
            C = 1;                                   \
            if (V && w >= 0x180) V = 0;              \
            w += 0x60;                               \
          } else {                                   \
            C = 0;                                   \
            if (V && w < 0x80) V = 0;                \
          }                                          \
        } else {                                     \
          w = A + b + C;                             \
          if (w >= 0x100) {                          \
            C = 1;                                   \
            if (V && w >= 0x180) V = 0;              \
          } else {                                   \
            C = 0;                                   \
            if (V && w < 0x80) V = 0;                \
          }                                          \
        }                                            \
        A = w;                                       \
        NZ = A;                                      \
      } while (0)

--
Scott Hemphill	hemphill@csvax.cs.caltech.edu	...!ames!elroy!cit-vax!hemphill