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 KingdomPosts: 2075 |
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 KingdomPosts: 9110 |
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 KingdomPosts: 2075 |
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: AustraliaPosts: 2135 |
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: AustraliaPosts: 3194 |
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: AustraliaPosts: 482 |
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 ZealandPosts: 2350 |
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 KingdomPosts: 2075 |
if the compiler uses the hardware efficiently, I think all 'mite CPU flavours contain a Barrel shifter 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: GermanyPosts: 1113 |
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 KingdomPosts: 2075 |
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: AustraliaPosts: 3194 |
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 KingdomPosts: 2075 |
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 |