Menu ▾ ▴

Criticism of the 'FnLSL' command

Ralf Pagel
2026-11-01
2026-11-03
  • Ralf Pagel

    Ralf Pagel - 2026-11-01

    Hello,

    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

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-01

    Try casting. -Like this:
    Wordvariable = FnLSL ([word]0x01, 13)
    (I tested and it returns 8192)

     
  • Ralf Pagel

    Ralf Pagel - 2026-11-02

    Hello Roger,

    Yes, that works for me too.
    Thanks for your quick help.

    Regards
    Ralf

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-02

    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

     
  • Anobium

    Anobium - 2026-11-02

    Agree, Rotate is a lot faster. :-)

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-02

    There would be a point in mentioning Rotate as a faster alternative, in the FnLSL FnLSR help pages?

     
    • Anobium

      Anobium - 2026-11-02

      This is a good idea. Have a look at exists help, edit/revise, and I can change.

       
  • Roger Jönsson

    Roger Jönsson - 2026-11-02

    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
  • Ralf Pagel

    Ralf Pagel - 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.

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-02

    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?

     
  • Ralf Pagel

    Ralf Pagel - 2026-11-02

    How about this:

    Sub ShiftLeft(WordVariable, ByteVariable)
    Do while ByteVariable > 0
    LSLF WordVariable
    RLF WordVariable_h
    Loop
    End Sub

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-02

    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.

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-02

    LSLF, RLF? What is that?

    For convenience I would do like this:

    wordvariable=1
    
    Repeat 13
    STATUS.C=0
    Rotate wordvariable Left
    End Repeat
    
     
  • Ralf Pagel

    Ralf Pagel - 2026-11-02

    And if a variable determines the number of rounds,
    then it’s better to do it like this:

    wordvariable = 1
    
    Do while ByteVariable > 0
      STATUS.C = 0
      Rotate wordvariable Left
    Loop
    

    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.

     
    👍
    1
  • Roger Jönsson

    Roger Jönsson - 2026-11-03

    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
  • Roger Jönsson

    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
  • Roger Jönsson

    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
  • Roger Jönsson

    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
  • Anobium

    Anobium - 2026-11-03

    Ok. Can you summarise the advice? Exact changes per Help Page.

    Thanks

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-03

    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.

     
  • Roger Jönsson

    Roger Jönsson - 2026-11-03

    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
  • Anobium

    Anobium - 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.

     
    👍
    1
  • Roger Jönsson

    Roger Jönsson - 2026-11-03

    Me update like!

     
    👍
    1

Log in to post a comment.