6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Sep 20, 2024 2:37 pm

All times are UTC




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Jan 15, 2013 9:32 am 
Offline

Joined: Tue Jan 15, 2013 9:23 am
Posts: 10
Location: Planet X
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 15, 2013 3:39 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
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


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 15, 2013 10:59 pm 
Offline

Joined: Tue Jan 15, 2013 9:23 am
Posts: 10
Location: Planet X
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 15, 2013 11:56 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
'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


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 1:12 am 
Offline

Joined: Tue Jan 15, 2013 9:23 am
Posts: 10
Location: Planet X
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 1:36 am 
Offline

Joined: Sat Oct 20, 2012 8:41 pm
Posts: 87
Location: San Diego
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 1:41 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 3:17 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
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


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 7:43 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 1:07 pm 
Offline

Joined: Thu Mar 03, 2011 5:56 pm
Posts: 284
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 2:08 pm 
Offline

Joined: Thu Mar 03, 2011 5:56 pm
Posts: 284
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 4:26 pm 
Offline

Joined: Tue Jan 15, 2013 9:23 am
Posts: 10
Location: Planet X
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 4:29 pm 
Offline

Joined: Tue Jan 15, 2013 9:23 am
Posts: 10
Location: Planet X
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 4:42 pm 
Offline

Joined: Tue Jan 15, 2013 9:23 am
Posts: 10
Location: Planet X
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:
File comment: Screen shot of Atari 5200 image.
ATRLOGO.JPG
ATRLOGO.JPG [ 20.44 KiB | Viewed 1409 times ]

_________________
http://www.krishnasoft.com -- "...simply wonderful." Make the world a better place-- instead of complicating things, make them simply wonderful.
Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 16, 2013 6:27 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: