[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Routine to detect CPU type (was Re: apple 2 chip's help)



David Empson <dempson@actrix.gen.nz> wrote:

> If you are writing a program which depends on the R65C02 instructions,
> you should definitely include code to test the CPU type (6502, 65C02,
> R65C02 or 65802/65816) before executing any instructions specific to the
> R65C02.  There was a routine in Eyes & Lichty which detected most of
> these, and I worked out an extended version which identified all four
> major types (I'd have to do a bit of hunting to find it, or reconstruct
> it).

I've managed to locate the original article I posted in October 1994
with this detection routine (this required a fair amount of searching on
my IIgs).  Here is the text of my earlier article, with a little editing
for tidiness.


I've had a request for a revised version of the routine to detect the
processor, so that it can identify a Rockwell R65C02.

Here is the routine I've come up with.  This routine has an additional
benefit: it will correctly detect a 65802/65816 if the chip is in 8-bit
native mode (the previous routine would incorrectly identify it as a
65C02).  Neither routine will work properly if the 65802/65816 is in
native mode with the M or X bits clear (i.e. 16-bit registers).

0320- A0 00     LDY #$00
0322- F8        SED
0323- A9 99     LDA #$99
0325- 18        CLC
0326- 69 01     ADC #$01
0328- D8        CLD
0329- D0 15     BMI $0340  ; 6502: N flag not affected by decimal add
032B- A0 03     LDY #$03
032D- A2 00     LDX #$00
032F- BB        TYX        ; 65802 instruction, NOP on all 65C02s
0330- D0 0E     BNE $0340  ; Branch only on 65802/816
0332- A6 EA     LDX $EA
0334- 88        DEY
0335- 84 EA     STY $EA
0337- 17 EA     RMB1 $EA   ; Rockwell R65C02 instruction
0339- C4 EA     CPY $EA    ; Location $EA unaffected on other 65C02
033B- 86 EA     STX $EA
033D- D0 01     BNE $0340  ; Branch only on Rockwell R65C02 (test CPY)
033F- 88        DEY
0340- 84 00     STY $00
0342- 60        RTS

I've included comments to show the general logic.  The routine first
tests for a 6502 using the same trick as before: relying on the negative
flag not being affected by an add in decimal mode.  This only happens on
a 6502.

The next part of the code checks for a 65802 or 65816 by seeing if the
TYX instruction is implemented (transfer Y to X).  On a 65C02 (both
types), this is an undefined opcode, which will behave as a NOP.  On the
65C02, the Z flag will still be set from the LDX #$00 instruction.  On
the 65802/65816, the Z flag will be clear because the TYX instruction
set the X register to 3 (the contents of Y).  The branch only occurs on
the 65802/65816.

The third part of the code tests for a Rockwell R65C02 by seeing if the
special zero page bit manipulation instructions are present.  The R65C02
has 32 extra opcodes.  The instructions are:

RMBn zp          Reset Memory Bit n in zero page location (8 opcodes)
SMBn zp          Set Memory Bit n in zero page location (8 opcodes)
BBRn zp,dest     Branch if bit n reset in zero page location (8 opcodes)
BBSn zp,dest     Branch if bit n set in zero page location (8 opcodes)

The opcodes are:

$07, $17, $27, $37, $47, $57, $67, $77 (RMBn zp)
$87, $97, $A7, $B7, $C7, $D7, $E7, $F7 (SMBn zp)
$0F, $1F, $2F, $3F, $4F, $5F, $6F, $7F (BBRn zp,dest)
$8F, $9F, $AF, $BF, $CF, $DF, $EF, $FF (BBSn zp,dest)

The code saves the contents of zero page location $EA, sets it to 2,
then tries to use the RMB1 instruction to clear bit 1 of the location.

On a Rockwell R65C02, this will work, and location $EA will now contain
zero, so the following CPY sees that the location has changed.

On any other 65C02, the $17 opcode is undefined, so acts as a NOP.  The
operand ($EA) is then executed as an instrution.  $EA is the opcode for
NOP, so nothing happens.  Location $EA still contains $02, so the CPY
sees that the location is the same.

The following STX is used to restore the original contents of location
$EA.  It doesn't affect the flags.  The following BNE tests the result
of the CPY.  If the branch occurs, we have a Rockwell R65C02.  If not,
we have a standard 65C02.

So, after calling this routine, location 0 (and the acummulator) contain
one of the following values:

0  6502
1  Standard 65C02
2  Rockwell R65C02
3  65802 or 65816


Incidentally, I found that a IIe clone I have here contains a Rockwell
R65C02, so I've tested this routine on all four types of processor
(except the 65802, but I have tested it on the 65816).

Here is a BASIC subroutine to implement the above routine.

6000 REM IDENTIFY THE PROCESSOR
6010 I = 800
6020 READ J: IF J < 0 THEN GOTO 6040
6030 POKE I,J: I = I + 1: GOTO 6020
6040 CALL 800
6050 CPU = PEEK(0): REM 0 = 6502, 1 = 65C02, 2 = R65C02, 3 = 65802/816
6060 RETURN
6070 DATA 160,0,248,169,153,24,105,1,216,48,21,160,3,162,0,187,208,14
6080 DATA 166,234,136,132,234,23,234,196,234,134,234,208,1,136,132,0
6090 DATA 96,-1

Share and enjoy!