[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 6502 illegal opcodes questions
- Subject: Re: 6502 illegal opcodes questions
- From: Scott Hemphill <hemphill@hemphills.net>
- Date: 25 Apr 2006 22:39:51 -0400
- Newsgroups: comp.sys.cbm, comp.sys.apple2, rec.games.video.classic
- References: <444be7a0$0$11080$9b4e6d93@newsread4.arcor-online.net> <444df05e$0$4499$9b4e6d93@newsread2.arcor-online.net> <m3wtddijl3.fsf@jade.local> <444e8df3$0$4500$9b4e6d93@newsread2.arcor-online.net>
- Reply-to: hemphill@alumni.caltech.edu
- Sender: hemphill@jade.local
- User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.4
- Xref: g2news2.google.com comp.sys.cbm:14651 comp.sys.apple2:6753 rec.games.video.classic:4466
Linards Ticmanis <ticmanis@gmx.de> writes:
> Scott Hemphill wrote:
> >> I'm still not quite happy with some ugly details that I haven't seen
> >> documented too well:
> >>
> >> 1.) Operation of ARR ($6B) when the decimal flag is SET.
> >>
> >> 2.) Exact operation of decimal mode ADC and SBC in both the 6502 and
> >> the 65C02.
> > I have C code which emulates ADC and SBC for the 65C02 for all
> > values of
> > the argments and flags.
>
> Thanks Scott! I've copied the algorithm from VICE for now, but that is
> of course NMOS 6502 only, since Commodore never switched to the 65C02
> chips for their own computers. Thus I am very interested in your code
> for better coverage of 65C02. Would you mind posting it here or
> mailing it to me? My From address is valid.
OK, here it is. A is the accumulator, b is the argument (an unsigned 8-bit
quantity). V, D, and C are booleans which represent the state of the
corresponding flags. NZ is a byte which holds the state of the N and Z
flags. The N flag is set if (NZ & 0x80) is true, and the Z flag is set
if (NZ == 0) is true. w is a 16-bit unsigned scratch location.
These instructions were tested by running a PRODOS program which combined
each of the 256 possible accumulator values with the 256 argument values.
The 64K combinations were output as a 128K file containing a one-byte result
and one byte of flags. The program was edited to produce 8 different
versions: (initial C set/clear)x(initial D set/clear)x(ADC/SBC). The
program versions were run on a Laser 128/EX and on an emulator, and the
results compared. (All of this was done about 20 years ago.)
#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 = (byte)w; \
NZ = A; \
} while (0)
#define SBC() \
do { \
if ((A^b) & 0x80) V = 1; else V = 0; \
if (D) { \
int tmp; \
tmp = 0xf + (A & 0xf) - (b & 0xf) + C; \
if (tmp < 0x10) { \
w = 0; \
tmp -= 6; \
} else { \
w = 0x10; \
tmp -= 0x10; \
} \
w += 0xf0 + (A & 0xf0) - (b & 0xf0); \
if (w < 0x100) { \
C = 0; \
if (V && w < 0x80) V = 0; \
w -= 0x60; \
} else { \
C = 1; \
if (V && w >= 0x180) V = 0; \
} \
w += tmp; \
} else { \
w = 0xff + A - b + C; \
if (w < 0x100) { \
C = 0; \
if (V && w < 0x80) V = 0; \
} else { \
C = 1; \
if (V && w >= 0x180) V = 0; \
} \
} \
A = (byte)w; \
NZ = A; \
} while (0)
--
Scott Hemphill hemphill@alumni.caltech.edu
"This isn't flying. This is falling, with style." -- Buzz Lightyear