Contact me | Login | Search | Sitemap | Site Notice

Alternative Code for CPU Detection

After posting my suggestion on detecting the different CPU types in the 6502-Facebook group I got some feedback on how to improve the code. I want to show two alternative examples which I have successfully tried with different system configurations and they also yield reliable results:

*
* detect CPU type
*
DETECTCPU2
          	LDA	#00
  		INC	A		; 65C02/65816 arrives here
        	XBA               	; put $01 in B accu -> =NOP for 65C02
        	DEC	A            	; A=$00 if 65C02
        	XBA               	; get $01 back if 65816
        	INC  	A            	; make $01/$02
_contD    	STA 	b65C02
    		RTS    

This routine is the shortest as far as I know. Its principle is based on the fact that most of the commands are not interpreted by the 6502 besides the LDA and STA, hence the initial value of $00 is stored in the accumulator at the end identifying a 6502.

A drawback of this approach is the fact that the 6502 has quite a few "illegal" (undocumented) opcodes that may leave the processor in an undefined state and change register values in an unexpected manner. There is a wide variety of tricks known for demo coding - especially for the C64 - which exploit these "illegal" opcodes in order to achieve the wanted demo effects.

This routine works as far as I have tested it but there is no guarantee that there are 6502-processors out there that will not behave as expected. The same is true for my solution presented on the last page which uses a BRA-opcode as differentiator which might also fail in certain cases.

Therefore I want to present another solution using a different approach. The next listing shows code that uses a decimal mode flag behaviour test that is specific for the NMOS 6502 and prevents that the 6502 receives any undefined opcode.

First the carry flag is cleared and then a specific 65816 opcode is issued (SEP) which sets processor registers. In this case the carry flag is set. The 65C02 treats this opcode as a NOP so with a 65C02 the carry flag is still cleared, with a 65816 the carry flag is set and hence can be used to distinguish between a 65C02 and a 65816:

DETECTCPU3
		SED			; set decimal mode
		LDA	#$99
		CLC
		ADC	#$01		; accu = 0
		CLD			; clear decimal mode
		BMI	p6502		; n-flag is only set in a 6502
		CLC			; clear carry flag
		SEP	#%00000001	; 65816 opcode -> sets carry flag
		BCC	p65c02		; 65C02 -> carry still cleared
		INC	A
p65c02		INC 	A
p6502		STA	b65C02
		RTS				

This last code example returns $00 for a 6502, $01 for a 65C02 and $02 for a 65816 CPU.