While compiling a file, I noticed the following:
The command WordVariable = FnLSL(0x01, (13 - ByteVariable))
always sets WordVariable_h to 0, even when bit 12 should be set.
I implemented a workaround by changing it to: WordVariable = FnLSL(0x8001, (13 - ByteVariable))
This ensures that bit 12 is set correctly.
I don't know if there is another way to tell GCB that the first parameter of 'FnLSL' is a Word constant. I couldn't find one. Fortunately, bit 15 is not currently being used.
Ultimately, it comes down to which subroutine the compiler generates: 'FN_FNLSL91' or 'FN_FNLSL92'.
I think it would be better to base the decision on the target variable rather than on the first parameter.
For example, like this: If the target variable is a WordVariable, 'FN_FNLS91' is created; if it is a ByteVariable, 'FN_FNLS92' is created.
Best regards
Ralf
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
FnLsL and FnLsR should be replaced with ROTATE which is faster.
ROTATE SIMPLE clears the carry bit automatically. Like if the STATUS.C bit wasn’t there. https://gcbasic.sourceforge.io/help/_rotate.html
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
WARNING! -Unless you have all the time in the world, use ROTATE instead! :-)
Slightly more seriously:
A faster alternative to FnLSL is Rotate Left with the Simple option.
A faster alternative to FnLSR is Rotate Right with the Simple option.
Or if you want to put it at the bottom;
See Also: Rotate (Rotate Left with the Simple option) -A faster alternative to FnLSL
See Also: Rotate (Rotate Right with the Simple option) - A faster alternative to FnLSR
Sorry for jumping into your discussion here, but I’m reading about "Rotate variable Left Simple":
"... so the MSB of the variable fills the LSB of the variable on Rotate Left or the LSB fills the MSB on Rotate Right. "
And I’m reading about "FnLSL(BitsIn, NumBits)":
FnLSL (Logical Shift Left) performs a bitwise left shift. It returns BitsIn shifted left by NumBits places, equivalent to the C operation:
BitsOut = BitsIn << NumBits
This is not equivalent.
In only a few cases will it be possible to swap the two commands.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry. My memory was wrong about the new simple option. That was sloppy of me.
I usually do it this way if I want zeroes filling in:
STATUS.C=0
Rotate Myvariable Left
STATUS.C=0
Rotate Myvariable Left
STATUS.C=0
Rotate Myvariable Left
I used it to shift bits while playing sound samples and it was way faster than FnLSL
So what we need for the help, is an example like the above on replacing FnLSL?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So I measured this on an 18F27Q84:
32us: Wordvariable = FnLSL ([word]0x01, 13)
13us: Setting the variable, then 13 steps of STATUS.C=0 and Rotate Wordvariable Left
In a case like this, just rotating 13 times, then nulling what should be nulled afterwards instead of repeatedly doing STATUS.C=0 would be even faster.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When I think of it no example is really needed, since it becomes so simple using SHIFT.
What we need is a SHIFT page in the help to link to from the FnLSL and FnLSR pages.
In the help pages for FnLSL and FnLSR:
-A faster alternative to FnLSL/FnLSR is using Shift.
(or)
See Also
Shift. -A faster alternative to FnLSL/FnLSR
Last edit: Roger Jönsson 2026-11-03
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
In the help pages for FnLSL and FnLSR:
-A faster alternative to FnLSL/FnLSR is using Shift.
(and/or)
See Also
Shift. -A faster alternative to FnLSL/FnLSR.
New help page for Shift (just the basics, as I understand it).
Syntax
Shift Variable Direction
Description
Shift moves all bits in a byte, word or long variable one position to the left or right.
The shifted-in bits are zero.
The shifted‑out bit is lost (not placed in the carry flag and not fed back).
The variable is updated directly.
Example
Dim Myvariable as Byte = b'10010010'
Shift Myvariable Left //My Variable = b'00100100'
See Also
Rotate. Rotation with carry‑feedback.
And in the help page for Rotate, something like:
See Also:
Shift. Rotation without carry‑feedback.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks all, this is now covered in the Help source.
The FnLSL result (Ralf’s original report). FnLSL(0x01, n) takes the Byte overload because 0x01 is a Byte constant. The overload is chosen from the first argument’s type, not from the variable it is assigned to, so the high byte comes back as 0. Roger’s cast is the intended fix: WordVariable = FnLSL([word]0x01, 13). A constant larger than 255 selects the Word overload by itself, which is why 0x8001 worked. Ralf’s idea of choosing the overload from the destination type would need a compiler change, and the library cannot do it. Removing the Byte overload would make every Byte caller slower and bigger, so I am not changing it. The FnLSL and FnLSR pages now explain this and show the cast.
Shift. There is a new Shift Help page:
It shifts one bit per use on PIC and AVR.
A 0 is shifted in, the bit shifted out is discarded, and the carry is not fed back.
Shift Value, Left and Shift Value Left both work. The comma is optional, as are brackets round the variable.
It is faster than FnLSL and FnLSR for one place or a few places. For a variable shift count, or a shift inside an expression, FnLSL and FnLSR are still needed. As Ralf said, Rotate is not a logical shift either.
Changes to the other pages.
FnLSL, FnLSR and Rotate now have a See Also entry for Shift.
FnLSL and FnLSR have a “Faster alternative” note.
The Bitwise Operations Overview lists Shift, with FnLSL and FnLSR moved to the bottom, as Roger proposed. Its See Also line covers Set, SetWith, Rotate, Shift, FnLSL and FnLSR.
These will appear in the next Help build.
👍
1
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
While compiling a file, I noticed the following:
The command
WordVariable = FnLSL(0x01, (13 - ByteVariable))always sets
WordVariable_hto 0, even when bit 12 should be set.I implemented a workaround by changing it to:
WordVariable = FnLSL(0x8001, (13 - ByteVariable))This ensures that bit 12 is set correctly.
I don't know if there is another way to tell GCB that the first parameter of 'FnLSL' is a Word constant. I couldn't find one. Fortunately, bit 15 is not currently being used.
Ultimately, it comes down to which subroutine the compiler generates: 'FN_FNLSL91' or 'FN_FNLSL92'.
I think it would be better to base the decision on the target variable rather than on the first parameter.
For example, like this: If the target variable is a WordVariable, 'FN_FNLS91' is created; if it is a ByteVariable, 'FN_FNLS92' is created.
Best regards
Ralf
Try casting. -Like this:
Wordvariable = FnLSL ([word]0x01, 13)
(I tested and it returns 8192)
Hello Roger,
Yes, that works for me too.
Thanks for your quick help.
Regards
Ralf
FnLsL and FnLsR should be replaced with ROTATE which is faster.
ROTATE SIMPLE clears the carry bit automatically. Like if the STATUS.C bit wasn’t there.
https://gcbasic.sourceforge.io/help/_rotate.html
Agree, Rotate is a lot faster. :-)
There would be a point in mentioning Rotate as a faster alternative, in the FnLSL FnLSR help pages?
This is a good idea. Have a look at exists help, edit/revise, and I can change.
WARNING! -Unless you have all the time in the world, use ROTATE instead! :-)
Slightly more seriously:
A faster alternative to FnLSL is Rotate Left with the Simple option.
A faster alternative to FnLSR is Rotate Right with the Simple option.
Or if you want to put it at the bottom;
See Also:
Rotate (Rotate Left with the Simple option) -A faster alternative to FnLSL
See Also:
Rotate (Rotate Right with the Simple option) - A faster alternative to FnLSR
...Or something like that...
https://gcbasic.sourceforge.io/help/_fnlsl.html
https://gcbasic.sourceforge.io/help/_fnlsr.html
Last edit: Roger Jönsson 2026-11-02
Sorry for jumping into your discussion here, but I’m reading about "Rotate variable Left Simple":
"... so the MSB of the variable fills the LSB of the variable on Rotate Left or the LSB fills the MSB on Rotate Right. "
And I’m reading about "FnLSL(BitsIn, NumBits)":
FnLSL (Logical Shift Left) performs a bitwise left shift. It returns BitsIn shifted left by NumBits places, equivalent to the C operation:
BitsOut = BitsIn << NumBits
This is not equivalent.
In only a few cases will it be possible to swap the two commands.
Sorry. My memory was wrong about the new simple option. That was sloppy of me.
I usually do it this way if I want zeroes filling in:
STATUS.C=0
Rotate Myvariable Left
STATUS.C=0
Rotate Myvariable Left
STATUS.C=0
Rotate Myvariable Left
I used it to shift bits while playing sound samples and it was way faster than FnLSL
So what we need for the help, is an example like the above on replacing FnLSL?
How about this:
Sub ShiftLeft(WordVariable, ByteVariable)
Do while ByteVariable > 0
LSLF WordVariable
RLF WordVariable_h
Loop
End Sub
So I measured this on an 18F27Q84:
32us: Wordvariable = FnLSL ([word]0x01, 13)
13us: Setting the variable, then 13 steps of STATUS.C=0 and Rotate Wordvariable Left
In a case like this, just rotating 13 times, then nulling what should be nulled afterwards instead of repeatedly doing STATUS.C=0 would be even faster.
LSLF, RLF? What is that?
For convenience I would do like this:
And if a variable determines the number of rounds,
then it’s better to do it like this:
In this case, '0' is also possible.
Using LSLF saves you one instruction within the loop. But you're right—that’s not BASIC, of course.
Rotate Simple was just a hallucination!!! Not only AI is capable of that! :-)
I mixed it up with new command SHIFT (which keeps STATUS.C cleared).
It is obviosly too fresh for the help pages...
https://sourceforge.net/p/gcbasic/discussion/629990/thread/aea29a695f/
Last edit: Roger Jönsson 2026-11-03
When I think of it no example is really needed, since it becomes so simple using SHIFT.
What we need is a SHIFT page in the help to link to from the FnLSL and FnLSR pages.
In the help pages for FnLSL and FnLSR:
-A faster alternative to FnLSL/FnLSR is using Shift.
(or)
See Also
Shift. -A faster alternative to FnLSL/FnLSR
Last edit: Roger Jönsson 2026-11-03
Compressed help page for Shift (doesn't yet exist) as I understand it.
Syntax
Shift Variable Direction
Description
Shift moves all bits in a byte, word or long variable one position to the left or right.
The shifted-in bits are zero.
The shifted‑out bit is lost (not placed in the carry flag and not fed back).
The variable is updated directly.
Example
Dim Myvariable as Byte = b'10010010'
Shift Myvariable Left //My Variable = b'00100100'
See Also
Rotate. Rotation with carry‑feedback.
Last edit: Roger Jönsson 2026-11-03
And in the help page for Rotate, something like:
See Also:
Shift. Rotation without carry‑feedback.
Last edit: Roger Jönsson 2026-11-03
Ok. Can you summarise the advice? Exact changes per Help Page.
Thanks
In the help pages for FnLSL and FnLSR:
-A faster alternative to FnLSL/FnLSR is using Shift.
(and/or)
See Also
Shift. -A faster alternative to FnLSL/FnLSR.
New help page for Shift (just the basics, as I understand it).
Syntax
Shift Variable Direction
Description
Shift moves all bits in a byte, word or long variable one position to the left or right.
The shifted-in bits are zero.
The shifted‑out bit is lost (not placed in the carry flag and not fed back).
The variable is updated directly.
Example
Dim Myvariable as Byte = b'10010010'
Shift Myvariable Left //My Variable = b'00100100'
See Also
Rotate. Rotation with carry‑feedback.
And in the help page for Rotate, something like:
See Also:
Shift. Rotation without carry‑feedback.
Also (When a Shift help page exists):
In -Bitwise Operations Overview- add:
Shift . Performs a Bitwise shift, left or right. Faster than FnLSL/FnLSR
For more help see: Set, SetWith, Rotate, Shift (FnLSL and FnLSR)
https://gcbasic.sourceforge.io/help/_bitwise_operations_overview.html
I would move FnLSL and FnLSR to last in the table.
Last edit: Roger Jönsson 2026-11-03
Thanks all, this is now covered in the Help source.
The FnLSL result (Ralf’s original report). FnLSL(0x01, n) takes the Byte overload because 0x01 is a Byte constant. The overload is chosen from the first argument’s type, not from the variable it is assigned to, so the high byte comes back as 0. Roger’s cast is the intended fix: WordVariable = FnLSL([word]0x01, 13). A constant larger than 255 selects the Word overload by itself, which is why 0x8001 worked. Ralf’s idea of choosing the overload from the destination type would need a compiler change, and the library cannot do it. Removing the Byte overload would make every Byte caller slower and bigger, so I am not changing it. The FnLSL and FnLSR pages now explain this and show the cast.
Shift. There is a new Shift Help page:
It shifts one bit per use on PIC and AVR.
A 0 is shifted in, the bit shifted out is discarded, and the carry is not fed back.
Shift Value, Left and Shift Value Left both work. The comma is optional, as are brackets round the variable.
It is faster than FnLSL and FnLSR for one place or a few places. For a variable shift count, or a shift inside an expression, FnLSL and FnLSR are still needed. As Ralf said, Rotate is not a logical shift either.
Changes to the other pages.
FnLSL, FnLSR and Rotate now have a See Also entry for Shift.
FnLSL and FnLSR have a “Faster alternative” note.
The Bitwise Operations Overview lists Shift, with FnLSL and FnLSR moved to the bottom, as Roger proposed. Its See Also line covers Set, SetWith, Rotate, Shift, FnLSL and FnLSR.
These will appear in the next Help build.
Me update like!