6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat May 18, 2024 3:06 am

All times are UTC




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Tue Dec 14, 2021 6:44 pm 
Offline

Joined: Sun Jan 10, 2021 11:25 pm
Posts: 64
Hey, I've been thinking about a corner case that exists in llvm-mos's code generator, and I was wondering if there's a stock 6502-wizard answer to the conundrum.

I've got a virtualized "Compare against zero" instruction that sets N and Z from a value. It's usually pretty easy to do this; if some earlier instruction set N and Z, and they haven't been clobbered yet, then there isn't even anything to do. The instruction is free to clobber C, so the A,X,Y case can be handled by a TXA or something, or if all three are busy, a CMP #0, CPX #0, or CPY #0. The zero page case can usually be handled by a similar LDAXY.

There's one section of this routine that really burns me though: what to do if we need to set N Z from a zero page location, but A, X, and Y are all busy. The obvious thing to do would be to PHA PLA around the sequence, but PLA would clobber the NZ result we just computed! The N and Z values always feed right into a branch, so I could try to move the PLA into the branch destination, but the branch destination might be branched to from somewhere else, and that would see a rogue PLA.

I ended up just emitting INC zp; DEC zp, which I hate: it's 4 bytes and 10 cycles to compare a zero page location to zero. But I'm at a loss to come up with anything better. The only other ace up my sleeve is to require at least one of A, X, or Y to be free at each comparison against zero, but I expect that to unnecessarily slow down the common cases in service of this rare (but terrible) case.

Is there a better way to get NZ out of the zero page in as constrained a situation as this? 4 bytes and 10 cycles aren't *that* bad; I could get cute with stack manipulation, but I'm pretty sure that would end up bigger.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 14, 2021 7:20 pm 
Offline

Joined: Thu Jan 21, 2016 7:33 pm
Posts: 270
Location: Placerville, CA
Isn't BIT exactly this? If the ZP location is zero, the AND it performs will set Z, and if bit 7 is set, it'll set N.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 14, 2021 8:10 pm 
Offline

Joined: Sun Jan 10, 2021 11:25 pm
Posts: 64
UGH, you're right.

I knew that BIT would set V without considering the result of the AND, but I didn't remember that it set N too.

Thanks.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 14, 2021 8:11 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8438
Location: Southern California
commodorejohn wrote:
Isn't BIT exactly this? If the ZP location is zero, the AND it performs will set Z, and if bit 7 is set, it'll set N.

The AND performed by BIT may give wrong results, depending on what's in A; for example, if the ZP location contains %11001001 and A happens to contain %00010010, the AND of the two will be 0, and Z will be set. BIT does however also transfer the memory location's bit 6 to V, without regard for what's in A (and of course also transfers bit 7 to N, again without regard for what's in A). Is there a way you could use that instead? (I don't know what you have in mind, but I suspect that's out.) (Mysterymath, I see you posted while I was writing.)

It's an interesting challenge, if there's a way to meet it. I often find there's another way to accomplish the same purpose with a totally different approach, if someone can get me out of my tunnel vision. I may also find that the different approach makes it unnecessary to solve the particular problem I thought needed solving.

_________________
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: Tue Dec 14, 2021 8:31 pm 
Offline

Joined: Sun Jan 10, 2021 11:25 pm
Posts: 64
Ah, I see that I made a classic error. If the ZP is zero, then Z will be set. But if Z is set, it doesn't necessarily mean the ZP is zero.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 14, 2021 9:46 pm 
Offline

Joined: Sun Jan 10, 2021 11:25 pm
Posts: 64
Garth, I'm actually getting a surprising bit of tracking on the "iunno, try to worm your way out of it" approach.

The compiler can't really know how difficult it's going to be to expand one of these pseudos until it finished laying things out, so it seems to be a bit over-eager in putting things in A, X, and Y, since those are "the fastest place to put things." Just for a laugh, I tried reversing the allocation preference order; having it first try putting things in the zero page registers, then to X, Y, and lastly A.

I expected a bloodbath, but instead this seems to have produced an overall performance gain. In the case I was looking at, this freed up the Y register, which means the whole expansion just became a LDY zp.

I've got the register allocator hooked up to know on an instruction-by-instruction basis how fast putting a value in each location is, and this overrides the defaultt order. So I think this will probably be the right approach: place it in the fastest place you can, but amongst all the equally fast places, put in the one least likely to screw you over when you're expanding pseudoinstructions later. (That is, ZP first, then X, then Y, then A). I suspect that assembly-language programmers kinda do this implicitly. If a human found that they needed a reg and none were free, they might go back and jiggle the code until one was free. Since the compiler can't really do that, it'll just have to be a bit paranoid about using them, since it may need one later.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 14, 2021 9:54 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8438
Location: Southern California
mysterymath wrote:
I suspect that assembly-language programmers kinda do this implicitly. If a human found that they needed a reg and none were free, they might go back and jiggle the code until one was free.

BigEd observed, "With 6502, I suspect more than one beginner has wondered why they can't do arithmetic or logic operations on X or Y, or struggled to remember which addressing modes use which of the two. And then the intermediate 6502 programmer will be loading and saving X and Y, while the expert always seems to have the right values already in place."

_________________
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: Tue Dec 14, 2021 11:35 pm 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
Just an FYI, From your first post, PHP/PLP would be a better use of the stack than PHA/PLA as it preserves all the processor bits of the last comparison (Negative, Overflow, Carry and Zero)


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 15, 2021 3:50 am 
Offline

Joined: Sun Jan 10, 2021 11:25 pm
Posts: 64
Ah yes, I went down that road too, if I recall.

Code:
STA save_zp
LDA zp_to_test
PHP
LDA save_zp
PLP
BNE dst


It'd be nice to use PHA/PLA instead of a save zp, but that would interleave two PHA/PLA pairs in a conflicting way:

Code:
PHA
PHP
PLA
PLP
BNE dst


The working (first) fragment takes 8 bytes and 16 cycles, vs INC zp; DEC zp, which takes 4 bytes and 10 cycles.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 15, 2021 8:28 am 
Offline

Joined: Thu Jan 21, 2016 7:33 pm
Posts: 270
Location: Placerville, CA
GARTHWILSON wrote:
The AND performed by BIT may give wrong results, depending on what's in A;

mysterymath wrote:
Ah, I see that I made a classic error. If the ZP is zero, then Z will be set. But if Z is set, it doesn't necessarily mean the ZP is zero.

Aha, right you are. Interesting...!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 6 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: