6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 9:22 pm

All times are UTC




Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Flag to Mask Conversions
PostPosted: Tue Aug 30, 2022 1:32 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
Greetings,

I spent a couple of enjoyable hours reading through some of this boards threads last night. This is my first post.

I have recently returned to 65xx assembly after a very long hiatus (my last time was in the early 80s).

For the heck of it (and to keep my mind sharp), my first foray back is to cobble together an Atari 2600 4k game binary.

As I experiment and learn the 2600, I find myself wishing I had a set of fast constant-time 6507 flag to mask conversion snippets.
Before I wrack my brain reinventing the wheel, I thought I'd check if anyone on this board knows of an existing set.

What I'm looking for is a set of "bithacks" for converting processor flag states (or boolean combination of processor flag states) to canonical 8-bit masks in A, in the least number of cycles but in constant-time.

By canonical mask I mean -1/0 (all bits on or all bits off), similar to Forth flags.

By constant-time I mean either branchless or using "ballasted" branches, so that all conditional paths through the code end up taking exactly the same number of cycles.

I'm perfectly fine with using undocumented 6507 opcodes, as they seem to be commonly used in 2600 homebrews.

Here are a couple of examples (I have no idea if these are optimal or not).

~C -> -1/0:

Code:
a900    lda #$00    (2)
e900    sbc #$00    (2)


C -> -1/0:

Code:
a900    lda #$00    (2)
e900    sbc #$00    (2)
49ff    eor #$ff    (2)


... and so on and so forth, including useful boolean combinations of N, V, C, Z.

Cheers,
Mark


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 2:53 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Welcome, Mark, and congratulations on ending your very long hiatus!

Here are two possible approaches. I'm pretty sure I understand what we're trying to achieve. But I'm less sure I've gotten all the details correct, as it's late and I'm getting sleepy! Maybe this will at least help you get started.

-- Jeff

Very fast but also very bulky:
Code:
php
pla
tax
lda LookupTable,X ;each element of the table is either 0 or $FF


A bit slower but a great deal smaller:
Code:
php
pla
eor #BitsToInvert
ora #BitsToIgnore ;now A= $FF or less than $FF
cmp #$FF          ;if A=$FF then carry=1 (ie, the CMP didn't borrow) else carry=0
lda #$00
sbc #0

_________________
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 Aug 30, 2022 3:47 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
Dr Jefyll wrote:
Welcome, Mark, and congratulations on ending your very long hiatus!

Here are two possible approaches. I'm pretty sure I understand what we're trying to achieve. But I'm less sure I've gotten all the details correct, as it's late and I'm getting sleepy! Maybe this will at least help you get started.

-- Jeff

Very fast but also very bulky:
Code:
php
pla
tax
lda LookupTable,X ;each element of the table is either 0 or $FF


A bit slower but a great deal smaller:
Code:
php
pla
eor #BitsToInvert
ora #BitsToIgnore ;now A= $FF or less than $FF
cmp #$FF          ;if A=$FF then carry=1 (ie, the CMP didn't borrow) else carry=0
lda #$00
sbc #0


Thanks very much for the kind welcome and the code. 8)

It's not exactly what I'm looking for, in the sense that I'm after the fastest routine per test rather than a generic approach.

For example if one is attempting to convert ~C to a mask, I'm guessing lda #0 sbc #0 at 4mc may be the fastest constant-time option, and perhaps lda #0 sbc #0 eor #$ff at 6mc is best for converting C to a mask, I don't really know. In summary, I'm after the best mask generator for each commonly useful SR flags test.

Cheers,
Mark


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 4:03 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Welcome.

I always welcome new tricks, but I can't imagine you'll be able to do this quite the way you had hoped. C is the only flag you can do this kind of thing with, so without conditional branches or tables, you're probably confined to PHP, PLA, and shifting the desired position into the C flag position and then doing your add or subtract. I'd be glad to be proven wrong. If someone comes up with a way, we should put it in the wiki.

What's the 00/FF thing for? I do use Forth; but in every case I can think of, anything non-0 is fine for a "true" flag. In 65c02 work, setting a flag byte can consist of just decrementing the byte and later testing it with BIT followed by BMI or BPL, as long as you don't decrement so many times the byte becomes positive again; and for clearing it, I just use STZ. I realize you don't have STZ on the 6507, and would have to do LDA #0, STA.

_________________
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 Aug 30, 2022 4:31 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
GARTHWILSON wrote:
Welcome.

I always welcome new tricks, but I can't imagine you'll be able to do this quite the way you had hoped. C is the only flag you can do this kind of thing with, so without conditional branches or tables, you're probably confined to PHP, PLA, and shifting the desired position into the C flag position and then doing your add or subtract. I'd be glad to be proven wrong. If someone comes up with a way, we should put it in the wiki.


Thank you. 8)

If it does turn out to be infeasible, then I'll at least try to reproduce some of the Bxx tests as mask producers to similar ends, e.g.

A = -(A>=0) [edited for correction (twice!)]
Code:
0a      asl         (2)
a900    lda #$00    (2)
e900    sbc #$00    (2)


GARTHWILSON wrote:

What's the 00/FF thing for? [...]


In Forth-83 test/query words returned -1/0, Forth-79 and Fig-Forth used 1/0.
Although I'm not a fan of the later ANS-Forth, I adopted some of the controversial changes of '83, particularly the -1/0 test results and the use of floored division.

As to why -1/0 is better, you can use a result directly as a mask.
Also, unlike C for example you don't need different operators for logical and bitwise operations, since they're the equivalent when using -1/0 as canonical flags.


Last edited by TheBrewThatIsTrue on Tue Aug 30, 2022 9:14 am, edited 3 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 4:43 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
Below is an example where I'm using the result of a comparison as a mask for the subsequent AND.

Code:
 Preload Player Graphics.

98      tya                     (2)x3   @ dk.000*.090-095
 N.B. clc rather than sec.
18      clc                     (2)x3   @ dk.000*.096-101
e587    sbc SRAM_P0_Y           (3)x3   @ dk.000*.102-110
c5a7    cmp CRAM_P0_HEIGHT      (3)x3   @ dk.000*.111-119
aa      tax                     (2)x3   @ dk.000*.120-125
a900    lda #$00                (2)x3   @ dk.000*.126-131
e900    sbc #$00                (2)x3   @ dk.000*.132-137
35a9    and CRAM_GRP0_ROWS,X    (4)x3   @ dk.000*.138-149


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 5:06 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
TheBrewThatIsTrue wrote:
GARTHWILSON wrote:

What's the 00/FF thing for? [...]

In Forth-83 test/query words returned -1/0, Forth-79 and Fig-Forth used 1/0.
Although I'm not a fan of the later ANS-Forth, I adopted some of the controversial changes of '83, particularly the -1/0 test results and the use of floored division.

As to why -1/0 is better, you can use a result directly as a mask.
Also, unlike C for example you don't need different operators for logical and bitwise operations, since they're the equivalent when using -1/0 as canonical flags.

Sorry—I didn't mean 1 versus -1 for a "true" flag, but that IF, WHILE, UNTIL, ABORT", ?DUP, ?EXIT, ?<anything> only look to see if it's 0 or not. Things that produce a flag, like 0=, >, etc. do produce a -1 as a true flag; but I've seldom found that it matters. In the rare case that it does matter, you can use 0<> to change any non-0 number into a -1.

_________________
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 Aug 30, 2022 5:40 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
GARTHWILSON wrote:
TheBrewThatIsTrue wrote:
GARTHWILSON wrote:

What's the 00/FF thing for? [...]

In Forth-83 test/query words returned -1/0, Forth-79 and Fig-Forth used 1/0.
Although I'm not a fan of the later ANS-Forth, I adopted some of the controversial changes of '83, particularly the -1/0 test results and the use of floored division.

As to why -1/0 is better, you can use a result directly as a mask.
Also, unlike C for example you don't need different operators for logical and bitwise operations, since they're the equivalent when using -1/0 as canonical flags.

Sorry—I didn't mean 1 versus -1 for a "true" flag, but that IF, WHILE, UNTIL, ABORT", ?DUP, ?EXIT, ?<anything> only look to see if it's 0 or not. Things that produce a flag, like 0=, >, etc. do produce a -1 as a true flag; but I've seldom found that it matters. In the rare case that it does matter, you can use 0<> to change any non-0 number into a -1.


Yes, in the grand scheme it's a very minor difference, sometimes a small convenience, other times a small inconvenience. Which you favor is more a question of personal coding style and taste than anything else.
And of course, with Forth you can always have it your way. :)


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 5:53 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
The reason I'm keen on mask generators is that, in the display kernel of a 2600 game, I'd like to avoid branches wherever I can easily do so, since all control flow paths will need to be balanced to consume the exact same number of cycles, and ballasting branches is a pain. :)


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 6:10 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Which HP calc is your avatar of?

_________________
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 Aug 30, 2022 6:20 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
GARTHWILSON wrote:
Which HP calc is your avatar of?


It's an HP-16C Computer Scientist, bought it at Macy's in San Francisco in the early 80s.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 6:58 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Nice! I use the HP-41cx regularly. It doesn't have as many computer-science functions as the 16c, but my Advantage module has the base conversions and boolean functions, 32-bit, which is adequate for me. There is another module that just came out in the last couple of years that does the 16c stuff with 64-bit numbers, using buffers it sets up for the extra bits. I don't have that module, but I have a lot of others loaded. Engineers are still introducing fantastic modules for it, even today. The 41CL and I believe the DM41x are a lot faster than the original HP product and come with over 300 modules pre-installed in flash. Unfortunately the DM41x does not have HP-IL, and HP-IL was the whole reason I got into the 41 in 1986. Actually my 41 controlled the Bytek Writer EPROM programmer with an RS-232 interface for my early 65c02 work, after a manual home-made programmer proved to be non-workable due to its slowness and vulnerability to human error. One of the interface converters I have for the 41 (and 71) is HP-IL to RS-232.

_________________
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 Aug 30, 2022 8:04 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
GARTHWILSON wrote:
Nice! I use the HP-41cx regularly. It doesn't have as many computer-science functions as the 16c, but my Advantage module has the base conversions and boolean functions, 32-bit, which is adequate for me. There is another module that just came out in the last couple of years that does the 16c stuff with 64-bit numbers, using buffers it sets up for the extra bits. I don't have that module, but I have a lot of others loaded. Engineers are still introducing fantastic modules for it, even today. The 41CL and I believe the DM41x are a lot faster than the original HP product and come with over 300 modules pre-installed in flash. Unfortunately the DM41x does not have HP-IL, and HP-IL was the whole reason I got into the 41 in 1986. Actually my 41 controlled the Bytek Writer EPROM programmer with an RS-232 interface for my early 65c02 work, after a manual home-made programmer proved to be non-workable due to its slowness and vulnerability to human error. One of the interface converters I have for the 41 (and 71) is HP-IL to RS-232.


Very very cool 8)
I was just reading last night or this morning about your use of HP-IL on your workbench computers page.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 8:40 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Welcome, Mark! An interesting quest, to be sure. And rather jumping in at the deep end of deterministic runtime, to pick the 2600. But I look forward to seeing some ingenious ideas.

You might find the resources linked here useful, if any are new to you:
https://alienbill.com/2600/

And there's an in-browser IDE for the 2600 which might help when you want to test things:
https://8bitworkshop.com/v3.9.0/?file=e ... atform=vcs


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 30, 2022 9:08 am 
Offline
User avatar

Joined: Fri Aug 26, 2022 9:17 am
Posts: 12
Location: Manila, Philippines
BigEd wrote:
Welcome, Mark! An interesting quest, to be sure. And rather jumping in at the deep end of deterministic runtime, to pick the 2600. But I look forward to seeing some ingenious ideas.

You might find the resources linked here useful, if any are new to you:
https://alienbill.com/2600/

And there's an in-browser IDE for the 2600 which might help when you want to test things:
https://8bitworkshop.com/v3.9.0/?file=e ... atform=vcs


Thanks for the welcome and the resources BigEd. :D


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

All times are UTC


Who is online

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