Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 10:30 25 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MMBasic functionality not as described in the doc

Author Message
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2075
Posted: 09:28am 14 Jun 2024
Copy link to clipboard 
Print this post

Morning forum.

small heads-up.

I have just spent a while chasing down a tricky bug and it turns out due to the << and >> operators not doing what it says on the tin.

From the MicroMite manual:

"
Shift operators:
x << y x >> y These operate in a special way. << means that the value returned
will be the value of x shifted by y bits to the left while >> means the
same only right shifted. ... any bits
shifted off are discarded and any bits introduced are set to zero.
"

however, lost bits are clearly not shifted in as zeroes. Consider the following:
> dim n as integer
> n=1
> ?n<<63
-9223372036854775808     <-- as expected
> ?n<<64
1                       <-- huh? expected the one bit to get shifted away and return 0
> ?n<<65
2
> ?n>>64
1                      <-- works the other way too
>


so << and >> appear to be really rotates

easy enough work around (working with very large +/- integers might require more care) but hopefully this will lodge in your wet-ware and you won't get caught like I did.

It actually looks like the compiler directive isn't acting as (I) expected:
void op_shiftleft(void) {
   iret = (long long int)((unsigned long long int)iarg1 << (long long int)iarg2);
}


coz the outcome isn't a shift in the classic form... maybe you C proggers are totally aware of this

tried on an old MicroMite version and MMX 5.070105

h
Edited 2024-06-14 19:43 by CaptainBoing
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9110
Posted: 09:52am 14 Jun 2024
Copy link to clipboard 
Print this post

PicoMite and CMM2 both appear to be correct so could be a bug in the Microchip compiler
Edited 2024-06-14 20:00 by matherp
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2075
Posted: 09:59am 14 Jun 2024
Copy link to clipboard 
Print this post

cheers Pete. I am always reluctant to point the finger at an IDE but it is looking like it. In which case I am suspecting Thwills variant(s) and MMBasic for DOS will be OK too.

I always seem to find this obscure stuff that has never bothered anyone else in a 100 years

h
Edited 2024-06-14 20:15 by CaptainBoing
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2135
Posted: 12:11pm 14 Jun 2024
Copy link to clipboard 
Print this post

Latest MM2 version also.
> Micromite MKII MMBasic Ver 5.05.05
Copyright 2011-2021 Geoff Graham

ILI9488 driver loaded
>
> dim n as integer
> n=1
> ?n<<63
-9223372036854775808
> ?n<<64
1
> ?n<<65
2
> ?n<<72
256
> ?n>>64
1
> ?n>>65
0
> ? n
1

Same on MM+ Ver 5.05.05

Making it visible
for n=64 to 80 step 8:cls 255<<n :pause 2000:next

Edited 2024-06-14 22:49 by phil99
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3194
Posted: 02:03pm 14 Jun 2024
Copy link to clipboard 
Print this post

Thanks guys.

I now have quite a collection of minor bugs so I can see that an update is now overdue.

Geoff
Geoff Graham - http://geoffg.net
 
zeitfest
Guru

Joined: 31/07/2019
Location: Australia
Posts: 482
Posted: 01:21am 15 Jun 2024
Copy link to clipboard 
Print this post

IIRC there was an obscure compiler/library  directive/options(s) that determined how the "new" bits  were set - I can't remember the details atm , something similar to erased memory bits being set by default
Edited 2024-06-15 11:29 by zeitfest
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2350
Posted: 04:29am 15 Jun 2024
Copy link to clipboard 
Print this post

it could also be that the compiler generates code (using pascal pseudocode) similar to:

result := X << (count mod 64)

this would make some sense, as the count parameter needs to be constrained in some way to protect against getting stuck in a pointless loop - assuming here that << at the most fundamental level decomposes down to a series of 1-bit shifts.

one fix would be to use the pseudocode:

if abs(count)>63 then result := 0
                else if count<0 then result := X >> -count
                                else result := X << count


this fixes things for both shifts of more than 63 bits and negative values of count.

but then is there anything fundamentally wrong with existing behavior? one could argue, on the principal of "garbage in, garbage out", that perhaps the user themself should be expected to check for what is effectively an overflow in the count parameter?


cheers,
rob   :-)
Edited 2024-06-15 14:30 by robert.rozee
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2075
Posted: 08:56pm 15 Jun 2024
Copy link to clipboard 
Print this post

  robert.rozee said  ... decomposes down to a series of 1-bit shifts.
if the compiler uses the hardware efficiently, I think all 'mite CPU flavours contain a Barrel shifter

  robert.rozee said  
but then is there anything fundamentally wrong with existing behavior? one could argue, on the principal of "garbage in, garbage out"

well, that thought sort of did occur to me - could it just be thought of as a rotate instead (it would split the platforms on the documentation Pico & CMM2 shift the examples correctly).

Having thought about this, I think your second example might be the fix. In each of the tests I did, the value I shifted - if you MOD 64 then shift, the answer is right... 1<<(64 mod 64) is 1<<0 which is one... like wise 65 is a <<1 which agan gives a two. So I think the compiler is doing that under the covers.

EDIT:
ok, tsting proves that is what is happening...

For n=0 To 80 Step 1:Print n,Bin$(15<<n,64):Next

50     0000000000111100000000000000000000000000000000000000000000000000
51     0000000001111000000000000000000000000000000000000000000000000000
52     0000000011110000000000000000000000000000000000000000000000000000
53     0000000111100000000000000000000000000000000000000000000000000000
54     0000001111000000000000000000000000000000000000000000000000000000
55     0000011110000000000000000000000000000000000000000000000000000000
56     0000111100000000000000000000000000000000000000000000000000000000
57     0001111000000000000000000000000000000000000000000000000000000000
58     0011110000000000000000000000000000000000000000000000000000000000
59     0111100000000000000000000000000000000000000000000000000000000000
60     1111000000000000000000000000000000000000000000000000000000000000
61     1110000000000000000000000000000000000000000000000000000000000000  <
62     1100000000000000000000000000000000000000000000000000000000000000  < should have low bits if it was rotate
63     1000000000000000000000000000000000000000000000000000000000000000  <
64     0000000000000000000000000000000000000000000000000000000000001111
65     0000000000000000000000000000000000000000000000000000000000011110
66     0000000000000000000000000000000000000000000000000000000000111100
67     0000000000000000000000000000000000000000000000000000000001111000
68     0000000000000000000000000000000000000000000000000000000011110000
69     0000000000000000000000000000000000000000000000000000000111100000
70     0000000000000000000000000000000000000000000000000000001111000000

h
Edited 2024-06-16 07:41 by CaptainBoing
 
Martin H.

Guru

Joined: 04/06/2022
Location: Germany
Posts: 1113
Posted: 04:45am 16 Jun 2024
Copy link to clipboard 
Print this post

The maximum number of bits is 64, so a further shift is not possible. We are talking about a bit shift, not a rotation. Therefore, no overflow bits appear on the right side.
If you try to shift by 64 or more, an overflow occurs. This means that only the values from 0 to 63 are considered, and any bit positions beyond that are ignored. Therefore, the number is effectively taken modulo 64 (n AND 63).


 N      0100001
AND     0011111
=       0000001

Edited 2024-06-16 14:46 by Martin H.
'no comment
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2075
Posted: 09:44am 16 Jun 2024
Copy link to clipboard 
Print this post

I actually regret starting this whole thread now. Interesting canter though it is, it was a waste of time once the low-level method is understood.

I think things are working it's just that I expected an "over-range" shift to zero-out the register... at machine level (i.e. assembler) if I shifted one bit at a time, over-range, it would do precisely that, but the use of specialised hardware in the chip to do the shift possibly mandates some checks.

What we have here is the compiler making sure the shift is always in range. simple.

Geoff; I don't think this should be on the bug list - unless you want to throw an "out of bounds" error. But to be frank, now the functionality is well understood, why bother tweaking anything? - except for compatibility with the newer Mites - as Peter noted above the H7 and Pico handle over-range shifts differently.

h
Edited 2024-06-16 19:47 by CaptainBoing
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3194
Posted: 01:23pm 16 Jun 2024
Copy link to clipboard 
Print this post

  CaptainBoing said  Geoff; I don't think this should be on the bug list - unless you want to throw an "out of bounds" error. But to be frank, now the functionality is well understood, why bother tweaking anything? - except for compatibility with the newer Mites - as Peter noted above the H7 and Pico handle over-range shifts differently.

I have not tested the rotate operators recently.  But, when the code was originally written (many years ago), the shift worked as described in the manual - so I need to find out what is going on here.  Regardless, the result and the manual should agree, so one or the other should change.

Geoff
Geoff Graham - http://geoffg.net
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2075
Posted: 07:47pm 16 Jun 2024
Copy link to clipboard 
Print this post

probably just some wording change in the MicroMite manual would do;

"
Shift operators:
x << y x >> y These operate in a special way. << means that the value returned
will be the value of x shifted by y bits to the left while >> means the
same only right shifted. ... any bits
shifted off are discarded and any bits introduced are set to zero.
Note: that y is subject to MOD 64
"

something like that covers it I think (although my wording is dreadful)

h
Edited 2024-06-17 05:47 by CaptainBoing
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024