STZ zp Opcode effect on various Retro-computers/consoles

Let's talk about anything related to the 6502 microprocessor.
AtariKSI
Posts: 10
Joined: 15 Jan 2013
Location: Planet X
Contact:

STZ zp Opcode effect on various Retro-computers/consoles

Post by AtariKSI »

I wrote a 6502/65C02 cross assembler within MPDOS Pro (PC side) and wanted the fastest code to detect whether a 65C02 was present in any 6502 based system. On Atari 5200/800 systems, I have been able to test using this code:
$600: PLA
STZ 213
RTS

D=USR(1536) : REM call from BASIC and D returns < 256 if 65C02 is present otherwise STZ opcode and argument gets treated as some "NOP zp". Can anyone try this on a C64/C128/Apple IIe/Atari 2600 to see what "STZ zp" opcode does?
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by Dr Jefyll »

Welcome AtariKSI.
I must say I find your proposed technique rather opaque, especially since you haven't included comments. As a courtesy, and since you're asking for assistance, it would be helpful if you were more informative.

However, since your goal is for a program to identify which processor it's executing on, perhaps you should refer to this thread. The approach in leeeeee's post (Tue Jun 22, 2004) seems to be the tidiest -- minimal setup, and no need to execute opcodes which may be undefined/unpredictable on the NMOS cpu.

cheers
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
AtariKSI
Posts: 10
Joined: 15 Jan 2013
Location: Planet X
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by AtariKSI »

Dr Jefyll wrote:
Welcome AtariKSI.
I must say I find your proposed technique rather opaque, especially since you haven't included comments. As a courtesy, and since you're asking for assistance, it would be helpful if you were more informative.
Only code I wrote is "STZ 213" which is self-explanatory. And I did put a comment in at the end with "REM..." I guess you aren't familiar with Atari programming so I forgive you for mistakingly calling it "opaque."
Quote:
However, since your goal is for a program to identify which processor it's executing on, perhaps you should refer to this thread. The approach in leeeeee's post (Tue Jun 22, 2004) seems to be the tidiest -- minimal setup, and no need to execute opcodes which may be undefined/unpredictable on the NMOS cpu.

cheers
Jeff
Thanks for that link, but after examining it, it turns out that code is wrong. It won't work on any Atari 8-bit console/computer that I use. Perhaps, it won't work on other platforms as well. Let's see the comments:

SED ; set decimal mode
CLC ; clear carry for add
LDA #$99 ; actually 99 decimal in this case
ADC #$01 ; +1 gives 00 and sets Zb on 65C02
CLD ; exit decimal mode

Comments are there but they don't seem to state exactly what he's trying to achieve in distinguishing between 65c02 and older versions of 6502 processors. But that's irrelevant as the code will not function correctly anyway. Take for example, an Atari 800 machine where a NMI like VBI or DLI are very commonly used in games/applications. If a NMI occurs while in decimal mode, it will probably hang the computer. And you don't want to put extra CLDs/SEDs into DLIs as that will truly increase overhead since they can occur like 15,000 per second. And even OS which is in ROM assumes VBI/DLIs are executing without having to worry about decimal mode. And how is this solution tidier even if it did work? To make it a subroutine like the one I wrote, you would add a "PLA" and "RTS" minimally. So a simple STZ zp of 3 cycles which happen to be working fine on all the machines I tried so far is not as good as that erroneous code which doesn't even work properly.

So back to my original question, anyone try "STZ zp" on Atari 2600/C64/C128/Apple IIe to see if it works like a NOP on those 6502 processors?
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by Dr Jefyll »

'kay, let me see if I can sort through this and reach a happy consensus. And I apologize if I seemed to describe your code as not being tidy. When I said, "leeeeee's post (Tue Jun 22, 2004) seems to be the tidiest," this was a comparison with other techniques in the thread, such as attempting to detect the effects of the $6C bug (in the words of the poster, "a little inconvenient to set up.")

I would enjoy learning how your proposed method functions, and discussing any pros & cons. It's true I'm not an Atari expert, and the same is true for a significant portion of the readership here. Would you still like to engage our interest as a group? This is a friendly bunch, and that's how we usually do things here.

cheers
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
AtariKSI
Posts: 10
Joined: 15 Jan 2013
Location: Planet X
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by AtariKSI »

Dr Jefyll wrote:
I would enjoy learning how your proposed method functions, and discussing any pros & cons. It's true I'm not an Atari expert, and the same is true for a significant portion of the readership here. Would you still like to engage our interest as a group? This is a friendly bunch, and that's how we usually do things here.

cheers
Jeff
On Commodore machines as well, even the normal interrupts assume binary mode (not decimal mode) so that solution in the other thread wouldn't be that useful. I read in some old magazine how they disable interrupts before using decimal mode. On Atari the NMIs and even IRQs on Atari 400/800 assume decimal flag is clear (binary mode). On the 800XL/130XE, the OS actually does do a "CLD" before servicing the IRQs but no such thing on NMIs. And there really isn't a single use of decimal mode (SED instruction) in the OS except the floating point routines which have to be called explicitly and most games/applications just avoid that floating point area all together from $D800..$DFFF.

I'm all for a good solution but that decimal mode won't cut it. I don't mind another simple solution; not really stuck on "STZ zp" but that's the only one I found to be working on the systems I have programmed.
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
clockpulse
Posts: 87
Joined: 20 Oct 2012
Location: San Diego

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by clockpulse »

check this thread, there is some code posted, take a look at the first part, maybe that can be used for what you want to do.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by GARTHWILSON »

AtariKSI, I'm not familiar with the systems you're talking about but I'm a bit surprised that the ISRs don't clear the D flag if they need it clear. I can see your point though about saving the instruction time since they're interrupting 15,000 times a second on a 1MHz machine. But it does bring up another possibility, which is to do a BRK when it's in decimal mode and see if the interrupt sequence clears the decimal flag. If it does, it's a CMOS processor. I don't know if you have access to the ISRs to do this.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by Dr Jefyll »

AtariKSI wrote:
I'm all for a good solution but that decimal mode won't cut it. I don't mind another simple solution; not really stuck on "STZ zp" but that's the only one I found to be working on the systems I have programmed.
OK, I'm all for good solutions, too, although I'm not able to offer an opinion regarding these NMI issues. As for the "STZ zp" method you suggest, there's one main thing puzzling me. I guess the idea is that if the cpu is one that features the STZ instruction then the byte at 213 will be set to zero; otherwise a NOP occurs. Later the BASIC statement reads 213 for the result. But for such a test to be reliable, shouldn't you first establish a default? -- code something to set 213 to be non-zero? Or is there something about the call mechanism or the Atari environment that makes this unnecessary?

cheers
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by BigEd »

Hi AtariKSI, and welcome!
STZ direct is opcode $64. At http://visual6502.org/wiki/index.php?ti ... 56_Opcodes we learn that this is indeed a NOP on the NMOS 6502 - it is unspecified behaviour, but turns out to be a nop. It's a 3-cycle NOP and you'll see that there are some 2-cycle NOPs.

Two things bother me a bit: you perform PLA and RTS - does this mean you expect to run this code in an interrupt routine? It would not be safe to do that, because the stacked return address for RTS and RTI are different by 1. And yet, since the processor won't change while you're running, I don't see why you would want to run in an interrupt routine. As with Jeff, I think there's something about your environment which isn't familiar to us.

If you only check for 6502 or 65C02 at initialisation time, you don't, presumably, care about saving a few bytes or cycles in the check. I see the point about being unable to SED if there's a chance of NMIs and if the NMI routine will fail if decimal mode is set. And yet: how badly will it fail? Does it really use ADC or SBC in an NMI routine? If you only perform the check once, are you in fact safe?

At http://www.oxyron.de/html/opcodes02.html you'll find other undocumented behaviour.

(I agree, of course, with Jeff's query about the prior value at 213.)

Cheers
Ed
rwiker
Posts: 294
Joined: 03 Mar 2011

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by rwiker »

BigEd wrote:
Hi AtariKSI, and welcome!
STZ direct is opcode $64. At http://visual6502.org/wiki/index.php?ti ... 56_Opcodes we learn that this is indeed a NOP on the NMOS 6502 - it is unspecified behaviour, but turns out to be a nop. It's a 3-cycle NOP and you'll see that there are some 2-cycle NOPs.

Two things bother me a bit: you perform PLA and RTS - does this mean you expect to run this code in an interrupt routine? It would not be safe to do that, because the stacked return address for RTS and RTI are different by 1. And yet, since the processor won't change while you're running, I don't see why you would want to run in an interrupt routine. As with Jeff, I think there's something about your environment which isn't familiar to us.

If you only check for 6502 or 65C02 at initialisation time, you don't, presumably, care about saving a few bytes or cycles in the check. I see the point about being unable to SED if there's a chance of NMIs and if the NMI routine will fail if decimal mode is set. And yet: how badly will it fail? Does it really use ADC or SBC in an NMI routine? If you only perform the check once, are you in fact safe?

At http://www.oxyron.de/html/opcodes02.html you'll find other undocumented behaviour.

(I agree, of course, with Jeff's query about the prior value at 213.)

Cheers
Ed
The PLA and RTS are because this function is supposed to be called form BASIC, via something like A = USER(1536, B, C, D), where B, C, D are 16-bit integers passed on the stack. $D4 and $D5 are used to to set up the return value; see http://www.atariarchives.org/cfn/12/02/0091.php.

The original code still looks badly broken, though.
rwiker
Posts: 294
Joined: 03 Mar 2011

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by rwiker »

rwiker wrote:

The PLA and RTS are because this function is supposed to be called form BASIC, via something like A = USER(1536, B, C, D), where B, C, D are 16-bit integers passed on the stack. $D4 and $D5 are used to to set up the return value; see http://www.atariarchives.org/cfn/12/02/0091.php.

The original code still looks badly broken, though.
Ok, let me expand on that. The PLA is for pulling the argument count (which should be 0, 1, 2 or 3) off the stack, so that the next item on the stack is the return address. Here, the assumption is that there will be no further arguments on the stack, so most like the machine will crash if you accidentally add parameters to the USR() call. Then again, it will also crash if you supply an incorrect address, so this may not be much of an issue.

On the other hand, as has already been mentioned, the code does not set the contents of $D4 and $D5, so the test will not work correctly unless something else guarantees that $D5 has a non-zero value.
AtariKSI
Posts: 10
Joined: 15 Jan 2013
Location: Planet X
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by AtariKSI »

rwiker wrote:
rwiker wrote:

The PLA and RTS are because this function is supposed to be called form BASIC, via something like A = USER(1536, B, C, D), where B, C, D are 16-bit integers passed on the stack. $D4 and $D5 are used to to set up the return value; see http://www.atariarchives.org/cfn/12/02/0091.php.

The original code still looks badly broken, though.
Ok, let me expand on that. The PLA is for pulling the argument count (which should be 0, 1, 2 or 3) off the stack, so that the next item on the stack is the return address. Here, the assumption is that there will be no further arguments on the stack, so most like the machine will crash if you accidentally add parameters to the USR() call. Then again, it will also crash if you supply an incorrect address, so this may not be much of an issue.

On the other hand, as has already been mentioned, the code does not set the contents of $D4 and $D5, so the test will not work correctly unless something else guarantees that $D5 has a non-zero value.
Sorry, that's wrong. Code is complete routine callable from basic not badly broken. If only argument of USR function is the address to call, then one PLA is needed to keep stack in order. And $D4 and $D5 are initialized to the address of the machine language subroutine so they are initialized. They are well defined upon entry to subroutine. And I only elected to modify $D5 (213) since my compare is "<256" so the MSB was enough to perform this check. More info on $D4,$D5 is here: http://www.atariarchives.org/mapping/appendix11.php

So by calling d = USR(1536), 213 = 6 and 212 = 0 and doing STZ 213 will set 213 to zero so updon return from routine D=0 if 65C02 exists else the STZ 213 is just a NOP 213 and D=1536 when routine returns. I guess one might ask why Atari BASIC bothers to return the same address you passed to it. One reason I see is that my routine was simplistic and used absolute locations for the call. But I could easily have done the following to detect a 65C02 in BASIC:

IF USR(ADR("hd<inv. U><ctrl .>"))<256 THEN PRINT "You have a 65C02"

Here the Address of the routine is floating in string space and I directly put the ASCII (ATASCII) version of the opcodes of the routine into the string since it's relocatable.
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
AtariKSI
Posts: 10
Joined: 15 Jan 2013
Location: Planet X
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by AtariKSI »

clockpulse wrote:
check this thread, there is some code posted, take a look at the first part, maybe that can be used for what you want to do.
I'll look at that and see if that'll work also on the machines I have. It looks he is also using undocumented opcodes and a bunch of them.
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
AtariKSI
Posts: 10
Joined: 15 Jan 2013
Location: Planet X
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by AtariKSI »

GARTHWILSON wrote:
AtariKSI, I'm not familiar with the systems you're talking about but I'm a bit surprised that the ISRs don't clear the D flag if they need it clear. I can see your point though about saving the instruction time since they're interrupting 15,000 times a second on a 1MHz machine. But it does bring up another possibility, which is to do a BRK when it's in decimal mode and see if the interrupt sequence clears the decimal flag. If it does, it's a CMOS processor. I don't know if you have access to the ISRs to do this.
If you peek the IRQ main vector and follow it on Atari 400/800 or Commodore OS ROMs, you'll see that the pointer at [65534] points to somewhere else in ROM which just does a "JMP [534]" (on Atari). There's no CLD being performed. And VBIs/DLIs also don't perform CLDs. They could but they assume no one is doing SEDs in the background or the code is written independent of decimal/binary mode; they restrict code to instructions that doesn't involve the D flag. D flag issue may be the reason why they ended up clearing the D flag on 65c02 processors automatically on interrupts, NMIs, and power up resets. And another reason why the NES variant doesn't even have the decimal mode.

Atari is a 1.79Mhz machine and you can program which scanline to have a NMI occur (display list interrupt) so the picture below shows all 128 colors although graphics mode only allow for maximum of 5 colors. A typical DLI would be like:

1536: PHA
1537: LDA #2 ;color value
1539: STA 53272 ;store color register
1542: LDA 1538 ;modify the code itself
1545: ADC #2
1548: STA 1538
1545: PLA
1546: RTI

So adding a CLD into the above that occur every scanline (15Khz) would use up 2*200 = 400 extra cycles/frame reducing background time.
Attachments
Screen shot of Atari 5200 image.
Screen shot of Atari 5200 image.
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: STZ zp Opcode effect on various Retro-computers/consoles

Post by BigEd »

OK, thanks, that makes sense as to why decimal mode would be a problem for an NMI routine. But as I say, if you run your machine test once, and CLD follows SED pretty closely, you'll only get a momentary colour glitch, right?
Ed
Post Reply