(latest) cc65 strange problem with division / shift right.

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
(latest) cc65 strange problem with division / shift right.
by on (#160500)
Maybe I'm missing something, maybe I'm doing this the wrong way, or maybe there's a bug?

This code:

Code:
unsigned char prx, pry;
signed int a;

...

void main (void) {
    [...]
    a = 160 << 6;
    pry = a >> 6;
    [...]
    p_t3 (4, 1, pry);
    p_t5 (8, 1, a);
}


(p_t3 and p_t5 just print numbers using neslib, 3 and 5 digits).

pry should b 160, right? If I use the old cc65 I've been using for quite a long time (2.13), the numbers "160" and "10240" are displayed on screen. But when I use the latest cc65 snapshot from here, I get wrong results: pry now equals 224. Numbers "224" and "10240" are printed on screen.

Screenshot: Above, the ROM compiled using the old 2.13, below, the ROM compiled using the latest win32 snapshot.
Attachment:
wtf.png
wtf.png [ 29.18 KiB | Viewed 1356 times ]


So it seems that "pry = a >> 6;" is not working for some reason.

The most interesting thing is that I get exactly the same results if I use *64 and /64 (I guess the optimizer is replacing them with shifts).

Am I doing something wrong?

Attached is a ZIP with two folders, cc65new and cc65old. There's a .NES file inside each, one compiled with the latest snapshot, the other with the old version. The code is slightly different 'cause different crt0.s / neslib revisions are used, but the important bit is the same.
Attachment:
tests.zip [144.87 KiB]
Downloaded 81 times


These are just tests. This thing has surfaced while porting an old project to the latest version of cc65/neslib. Am I doing something wrong? I'm using fixed point math and I'm bit-shifting quite a lot. Never had a problem (I use several compilers and very similar code for different platforms).

EDIT:

I did some more tests. It seems to be wrong, and it seems there's a logic in the results I get. Maybe should I report it to the cc65 team? The snapshot was released quite a long ago, I'm surprised nobody has noticed *if* this is a bug and not myself doing it wrong...

Code:
10240 -> 10100000000000   / 64 ( >> 6)
  160 ->       10100000   <- expected
  224 ->       11100000   <- got this
 
 5120 ->  1010000000000   / 64 ( >> 6)
   80 ->        1010000   <- expected
   16 ->        0010000   <- got this

 9920 -> 10011011000000   / 64 ( >> 6)
  155 ->       10011011   <- expected
   27 ->          11011   <- got this
Re: (latest) cc65 strange problem with division / shift righ
by on (#160506)
You definitely found a bug.

In the older release, the >>6 generates calls to asrax4¹ and asrax2. In the newer one, it instead generates a call to just asrax4 and then tries to inline the remaining >>2, but it does it wrong (it forgets about X and sign-extends A instead of copying the two remaining bits from X).

¹ (asrax4: Arithmetic Shift Right the 16-bit signed integer in A and X by 4 bits)

You should file a bug, I just tested it against the current tree.

As a temporary workaround, you can save the result of the bit shift to a 16-bit variable first, and then store that into an 8-bit variable.
Re: (latest) cc65 strange problem with division / shift righ
by on (#160508)
Thanks, I will file a bug then. I was afraid that it was *me* who was doing it wrong.

Cheers :)