6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 8:57 pm

All times are UTC




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Mon Apr 23, 2018 8:54 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
It's not unusual for a routine to return a byte-sized value in A and a bit-sized value in C.

Suppose you also wanted to return a second bit-sized value, in Z - how would you tackle that?

Extra points for using fewer resources to do it.

For spoiler control, so you don't have to peek at previous responses if you don't want to, I'm going to put a lot of blank lines in - there's nothing more to see.

























nothing to see here






















-eot-


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 23, 2018 9:15 pm 
Offline

Joined: Mon Nov 11, 2002 6:53 pm
Posts: 79
Location: Seattle
Doesn't 'bit' perform a logical and between the accumulator and an address? IIRC it leaves the carry intact?

[Edit: It doesn't change the accumulator. So you could do something else here? I.e. ASL/BIT $nnnn]


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 23, 2018 9:26 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
Ah, yes, BIT is well-made for that sort of thing. I was thinking of INC or DEC. But you do need a memory location to work with. Maybe that's fine... I was thinking of somehow using stack space. But it all gets rather tangled.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 23, 2018 10:35 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
BIT could constrain which value you're holding in .A, so I don't think that would be great. If you wanted to return zero in .A and the Z flag unset, that'd be quite difficult to do with just BIT.

I was thinking you'd set up a RAM byte with %000000ZC (with Z inverted), load up .A with your return value, then LSR that byte to set up C and Z.

Alternatively, if you wanted to use the stack instead of a scratch ZP location, push a flag byte to the stack, set up .A, then PLP and RTS. This way might be a few cycles faster, without a read-modify-write instruction involved, but the flags byte also might take a bit more setup than the LSR method.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 24, 2018 7:59 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
Ah, PLP, that's a good thought. I'd been thinking about indirecting into the stack, but then you need to use or preserve X, and it's all too much.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 30, 2018 9:53 pm 
Offline
User avatar

Joined: Wed Mar 01, 2017 8:54 pm
Posts: 660
Location: North-Germany
With a 65802 or 65816 the SEP or REP should work (allthough not tested).

If you use the V Flag instead of Z you may set/clear V before reaching the end of the subroutine where you wish to return with a valid A and C.

The easiest way to return with an additional flag IMHO is using the D flag.


my 2 cents


Top
 Profile  
Reply with quote  
PostPosted: Tue May 01, 2018 12:22 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
I vote for White Flame's LSR scheme. :)

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Sun May 06, 2018 12:04 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
PHA/PLA don't affect the status register at all flag, so maybe something like this:
Code:
;code to calculate byte value
PHA
;code to set C
;code to set Z
PLA

for example
Code:
LDA VALUE  ;Byte to Return
PLA
LDA CARRY  ;Set Carry if Not Zero
CLC
ADC #255
LDA ZERO   ;Set Z if Zero
PHA


Top
 Profile  
Reply with quote  
PostPosted: Sun May 06, 2018 12:26 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
PHA doesn't affect flags, but PLA does set N and Z to match the newly loaded accumulator value, as with any other load instruction. I also think your example might have PHA/PLA reversed, unless you're doing something even more clever.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Mon May 28, 2018 7:45 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
The D flag is easy to set and clear, but hard to test (requires PHP, PLA, BIT#) and interferes with arithmetic if the caller forgets to clear it. The V flag is easy to test but harder to set (though easy to clear) because there's no SEV (unless you're on a 65816). N and Z are easy to test, but are interfered with by almost every ALU operation.

In practice, 6502 software does use the V flag for this purpose since it's corrupted by relatively few instructions - only ADC. SBC, BIT (not #), RTI and PLP. You can set it reliably using LDA #&40, ADC #&40, which also sets N, and clears C and Z. Similar two-instruction sequences (substitute #&80 or #&C0 in the LDA) can leave N and Z in different states, though it's not possible to set both N and Z simultaneously this way. Only BIT is capable of altering Z independently of N, besides directly loading the status register. To preserve N and Z while loading A with the return value, you'll need PHP, PLP.

C, V, N and Z can be set simultaneously in arbitrary combinations using LDA#, PHA, ..., PLP. On CMOS chips you can also build these flags using the index registers. On the 65816 you can set and clear the flags explicitly using SEP/REP.


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 8 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: