It is currently Sun Jan 21, 2018 5:35 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: CC65 bit shifting bug?
PostPosted: Wed Dec 06, 2017 2:01 pm 
Offline
User avatar

Joined: Sun Sep 26, 2010 10:29 pm
Posts: 40
Hi,
I am wondering if I am facing a known CC65 bug: I am using a simple macro to calculate, in which 32x30 tile the given x/y coordinates a placed.
The calculation is as follows: (((y/8)*32)+(x/8)). To calculate this more efficiently, I am transforming this formula, using bit operators like follows:

    step 0: (((y/8)*32)+(x/8)) --> working
    step 1: (((y/8)*32)|(x>>3)) --> working
    step 2: (((y>>3)*32)|(x>>3)) --> working
    step 3: (((y>>3)<<5)|(x>>3)) --> working
    step 4: ((y<<2)|(x>>3)) --> not working!

I rebuild each version using Java and here all versions produce the same result. Here is the Java code:
Code:
   
                int x = 110;
      int y = 50;
      
      int result1 = (((y/8)*32)+(x/8));
      int result2 = (((y>>3)<<5)|(x>>3));
      int result3 = ((y<<2)|(x>>3));
      
      System.out.println(result1); //output: 205
      System.out.println(result2); //output: 205
      System.out.println(result3); //output: 205


I guess there is something special with CC65 bit shifting? The problem obviously lies in the part when combining two shifts into one.

Regards
Sebastian


Top
 Profile  
 
PostPosted: Wed Dec 06, 2017 2:08 pm 
Offline

Joined: Sun Jan 31, 2016 9:55 pm
Posts: 39
Quote:
step 3: (((y>>3)<<5)|(x>>3)) --> working
step 4: ((y<<2)|(x>>3)) --> not working!


This isn't a valid transformation. ((y>>3)<<5) is not equivalent to (y<<2). If it were, then (y>>3)<<3 would be the same as y, but when you do y>>3, you chop off the lower 3 bits, and doing y<<3 afterward doesn't bring them back.


Top
 Profile  
 
PostPosted: Wed Dec 06, 2017 2:21 pm 
Offline
User avatar

Joined: Sun Sep 26, 2010 10:29 pm
Posts: 40
Thanks for explaining. I guess this operation is working in my Java code, since I use int and not unsigned char, like in my C code.


Top
 Profile  
 
PostPosted: Wed Dec 06, 2017 3:07 pm 
Offline

Joined: Sun Jan 31, 2016 9:55 pm
Posts: 39
You are right that int and unsigned char will have different behaviors. In Java, >> is an arithmetic right shift, while for an unsigned number you will get a logical right shift (in Java represented by >>>).

You are working to optimize this part of the expression:
((y>>3)<<5).

This might be compiled something like:
Code:
lda yValue
lsr
lsr
lsr
asl
asl
asl
asl
asl


Note that doing shifts by amounts more than 1 takes multiple instructions on the 6502, so replacing it with a different operation can be beneficial.

If you have a byte y made up of bits a-h:
abcdefgh

y>>3 is:
000abcde

and that shifted left 5 is:
cde00000

So the value is equivalent to:
(y<<2)&0b11100000

This can be compiled to
Code:
lda yValue
asl
asl
and #%11100000


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: ccovell, Yahoo [Bot] and 12 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:  
Powered by phpBB® Forum Software © phpBB Group