Bitfields

General discussions about working with the Astrobe IDE and programming ARM Cortex-M0, M3, M4 and M7 microcontrollers.
Post Reply
steve64
Posts: 44
Joined: Mon Jul 09, 2018 8:56 am
Location: Italy

Bitfields

Post by steve64 » Fri Jul 20, 2018 4:09 pm

It seems that the BFI and BFX procedures only work with constants for msb and lsb.
Is this confirmed? If so, what's the reason?

cfbsoftware
Site Admin
Posts: 525
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: Bitfields

Post by cfbsoftware » Fri Jul 20, 2018 11:23 pm

BFI is designed to efficiently generate a single ARMv7-M architecture instruction:

Code: Select all

BFI <Rd>, <Rn>, #<lsb>, #<width>

where:

<Rd>    Specifies the destination register.
<Rn>    Specifies the source register.
<lsb>   Specifies the least significant destination bit, in the range 0 to 31.
<width> Specifies the number of bits
<lsb> and <width> are constant values encoded in the instruction so these need to be known at compile-time. The same applies to BFX.

if you want to do bit manipulation using variables you can use Oberon's SET variables, operators and functions (INCL and EXCL). If you are new to Oberon the following article by Niklaus Wirth should be useful to you:

SET: A neglected data type, and its compilation for the ARM

cfbsoftware
Site Admin
Posts: 525
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: Bitfields

Post by cfbsoftware » Sat Nov 03, 2018 12:01 am

Alternative approaches are discussed in BIT WISE AND/OR operation on the Oberon Language forum.

cfbsoftware
Site Admin
Posts: 525
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: Bitfields

Post by cfbsoftware » Sun Feb 10, 2019 6:02 am

When working on v7.0 of Astrobe I took the opportunity to refactor some code by using Astrobe's built-in bitfield insert (BFI) and extract (BFX) operators. The most satisfying example of this was transforming the Cortex-M7 caching code (which I previously could not get my head around) from:

Code: Select all

  setMsk := BITS(LSL(01FFH, 5));
  wayMsk := BITS(LSL(3H, 30));
  SYSTEM.GET(CCSIDR, ccsidr);
  sets := LSR(ORD(ccsidr * BITS(LSL(07FFFH, 13))), 13);
  REPEAT
    ways := LSR(ORD(ccsidr * BITS(LSL(03FFH, 3))), 3);
    REPEAT
      SYSTEM.PUT(DCISW, (BITS(LSL(sets, 5)) * setMsk) +
                        (BITS(LSL(ways,30)) * wayMsk));
      DEC(ways);
    UNTIL ways < 0;
    DEC(sets);
  UNTIL sets < 0;
To the equivalent:

Code: Select all

 SYSTEM.GET(CCSIDR, ccsidr);
 sets := BFX(ccsidr, 27, 13);  (* extract bits 27..13 to sets *)
 REPEAT
    ways := BFX(ccsidr, 12, 3);
    dcisw := 0;
    BFI(dcisw, 13, 5, sets);  (* Insert sets into bits 13..5 *)
    REPEAT
      BFI(dcisw, 31, 30, ways);
      SYSTEM.PUT(DCISW, dcisw);                  
      DEC(ways);
    UNTIL ways < 0;
    DEC(sets);
UNTIL sets < 0;
As well as making it easier to correlate this to the definition of caching in the STM32 Reference manual, it also had the benefit of reducing the code generated for the module by more than 30%.

Post Reply