BIT WISE AND/OR operation

Topics related to the use of Oberon language features

BIT WISE AND/OR operation

Postby Din » Tue Oct 23, 2018 11:29 pm

Hi,

I would like to know how to execute BIT wise AND and OR operation.

Here is something i tried but didn't work:
My goal is to perform => X (BITWISE AND) 0xFF

My initial data was "BYTE' type so I tried converting the BYTE to INTEGER and then used " VAL " to convert it to SET. I thought with SET i would be to able to perform something like this,

Code: Select all
PROCEDURE w5500Send* (offset, blockselect, buffer, len : BYTE);
VAR highaddress, i   : INTEGER;
      lowaddress   : BYTE;
      x,y          : SET;
      W: Texts.Writer;
      BEGIN
       highaddress := LSL( offset, 8 );                                     (* offset is the BYTE type argument which is left shifted and stored in " highaddress " as INTEGER type *)
       x := SYSTEM.VAL( SET, highaddress);                              (* Integer to SET *)[/color]
       FOR i := 0 TO 7 DO
         x{i} := x{i} * 1 ;                                                        (* This is where i thought i would do bit wise AND but it throws me an error " NOT A PROCEDURE TYPE"  *)
       END   
      highaddress := ORD(x)                                               (* SET to integer , at this point i want to extract only 8 bit LSB and i dont know how to do it.  *)
    END w5500Send;


I'm not sure if this is the right approach or is there any other way to perform BIT WISE AND/OR on BYTE type ? I would appreciate the help.
Din
 
Posts: 2
Joined: Mon Oct 15, 2018 10:12 pm

Re: BIT WISE AND/OR operation

Postby cfbsoftware » Wed Oct 24, 2018 10:54 am

That does not make sense to me. LSL(offset, 8) is going to set the LSB of highaddress to zero because you are shifting in eight zero bits.

I'm a little confused about what you are trying to do. To be able to help, I really need to know *what* problem you are trying to solve, not *how* you've attempted to solve it.

Having said that I'm guessing that you have a sixteen-bit address that you are trying to split into two bytes (or alternatively you are trying to construct a sixteen bit address from two bytes). If that is true, you do not have to use any bit manipulation, masking etc. It is much simpler than that in Oberon-07 because assigning an INTEGER to a BYTE automatically masks off the lowest 8-bits for you. There are several different ways to to do this. See the attached sample program for one possibility. It has been tested on Astrobe for RISC5 but just needs a couple of minor mods (IMPORT Main and a call to Test in the module initialisation section) to run it on the Cortex-M targets.

If at some other time in the future you do have a problem which really does lend itself to bit manipulation of integers have a look at the Logic operations discussion here in the Astrobe for Cortex-M3 Examples section of this forum. The example code is generally applicable to other implementations of Oberon-07.
Attachments
ByteManipulation.zip
(402 Bytes) Downloaded 73 times
cfbsoftware
Site Admin
 
Posts: 355
Joined: Fri Dec 31, 2010 12:30 pm

Re: BIT WISE AND/OR operation

Postby cfbsoftware » Sat Oct 27, 2018 11:00 am

There is a similar discussion currently on the ETH Oberon Mailing list. My latest reply is:

We have implemented two SYSTEM functions in the Astrobe for ARM Cortex-M compilers which use the ARM bitfield instructions BFI (Bitfield insert) and UBFX (Unsigned bitfield extract). These are very convenient to use when accessing arbitrary groups of bits that represent a positive integer buried in the middle of a 32-bit word. Here are some examples:

  • Example 1; Extracting a 4-bit bitfield from bit positions [7:4] of a word

    Code: Select all
    VAR word, bitfield: INTEGER;

      word := 0ABCDEF75H;
      SYSTEM.UBFX(bitfield, word, 7, 4);

    The resulting value of bitfield is 07H;

  • Example 2: Inserting an eight-bit bitfield into a word at bit positions [27:20]:

    Code: Select all
      word := 0AAADEF75H;
      bitfield := 0BCH;
      SYSTEM.BFI(word, 27, 20, bitfield); 

    The resulting value of word is 0ABCDEF75H.

  • Example 3: Just to show the bitfield length and bits do not have to be multiples of 8 or 4 etc. - extracting a ten-bit bitfield from a word at bit positions [22:13]

    Code: Select all
      word := 0ABCDEF75H;
      SYSTEM.UBFX(bitfield, word, 22, 13); 

    The resulting value of bitfield is 026FH;

For now you can do the same sort of thing in Oberon for RISC5 (albeit not quite as efficiently) with these two helper functions:

Code: Select all
PROCEDURE BFI*(VAR word: INTEGER; msb, lsb, bitfield: INTEGER);
BEGIN
  word := ORD(SYSTEM.VAL(SET, word) * (-{lsb..msb})) + LSL(bitfield, lsb)
END BFI;

Code: Select all
PROCEDURE UBFX*(VAR bitfield: INTEGER; word, msb, lsb: INTEGER);
BEGIN
  bitfield := ROR(ORD(SYSTEM.VAL(SET, word) * {lsb..msb}), lsb);
END UBFX;

We're considering implementing these in a future release of the Astrobe RISC5 compiler as built-in SYSTEM functions for efficiency reasons. If the bit positions are defined as constants as they are in the ARM instruction set, each function generates just five RISC5 instructions.

Ultimately, a bitfield capability built in to the language (similarly to Verilog) could be useful. Maybe so we could write statements like:

Code: Select all
 bitfield := word[22:13];

 word[22:13] := bitfield;
cfbsoftware
Site Admin
 
Posts: 355
Joined: Fri Dec 31, 2010 12:30 pm

Re: BIT WISE AND/OR operation

Postby cfbsoftware » Sun Oct 28, 2018 12:13 am

Because all of the parameters are integers I have discovered just by writing the test program that it is easy to make mistakes when using these procedures. If they are not used in the correct order the resulting problems can be tricky to diagnose. If performance is not a crucial issue then it is wise to add some parameter-checking assertions so that these sorts of errors are detected ASAP. The following assertions are aimed to check that MSB and LSB are in the correct order; LSB and MSB are in the range 0..31 and that the bitfield parameter to BFI is not larger than space allocated to it. The checks are not foolproof but they should help in most cases.

Code: Select all
PROCEDURE BFI*(VAR word: INTEGER; msb, lsb, bitfield: INTEGER);
BEGIN
  ASSERT(msb >= lsb);
  ASSERT(msb DIV 32 = 0);
  ASSERT(lsb DIV 32 = 0);
  (* Ensure bitfield fits into the target area *)
  ASSERT((BITS(bitfield) * (-{0..msb-lsb})) = {});
  word := ORD(BITS(word) * (-{lsb..msb})) + LSL(bitfield, lsb)
END BFI;


Code: Select all
PROCEDURE UBFX*(VAR bitfield: INTEGER; word, msb, lsb: INTEGER);
BEGIN
  ASSERT(msb >= lsb);
  ASSERT(msb DIV 32 = 0);
  ASSERT(lsb DIV 32 = 0);
  bitfield := ROR(ORD(BITS(word) * {lsb..msb}), lsb);
END UBFX;


The built-in BITS function is an addition to Oberon-07 that has been implemented in the Astrobe for Cortex-M compilers. If you are using the RISC5 Oberon-07 compiler you can use the following helper function:
Code: Select all
PROCEDURE BITS(i: INTEGER): SET;
BEGIN
  RETURN SYSTEM.VAL(SET, i)
END BITS;
cfbsoftware
Site Admin
 
Posts: 355
Joined: Fri Dec 31, 2010 12:30 pm

Re: BIT WISE AND/OR operation

Postby joerg » Sun Oct 28, 2018 11:28 am

Din

The statement „X (bitwise and) 0xFF“ is in Oberon „X MOD 256“ (or „X MOD 100H“ if you prefer hex).
The compiler will tranlate this to a bitwise AND instead of a remainder of a division as the divisor is a power of two.

Her a possible way to code your procedure:
Code: Select all
PROCEDURE w5500Send(offset: INTEGER; blockselect: BYTE;
                    buffer: ARRAY OF BYTE; len: INTEGER);
   VAR i: INTEGER;
   BEGIN
     (* select chip *)        S.PUT(spiCtrl, W5500);
     (* address phase *)      SPI(offset DIV 256); SPI(offset MOD 256);
     (* control phase *)      SPI(blockselect*8 + 4);  (* assuming VDM *)
     (* data phase *)         FOR i := 0 TO len-1 DO SPI(buf[i]) END;
     (* deselect the chip *)  S.PUT(spiCtrl, 0);
   END w5500Send;


To be on the safe side, you could start with three ASSERTs to check the validity of your input parameters
ASSERT(offset < 10000H); ASSERT(blockselect < 32); ASSERT (len < LEN(buffer));

Joerg
joerg
 
Posts: 1
Joined: Sun Oct 28, 2018 11:09 am

Re: BIT WISE AND/OR operation

Postby cfbsoftware » Fri Nov 02, 2018 11:53 pm

cfbsoftware wrote:Because all of the parameters are integers I have discovered just by writing the test program that it is easy to make mistakes when using these procedures. If they are not used in the correct order ...

On second thoughts it is better to make UBFX a function rather than a procedure. The corresponding function is named UBF (Unsigned Bit Field - a noun):

Code: Select all
PROCEDURE UBF*(word, msb, lsb: INTEGER): INTEGER;
BEGIN
  ASSERT(msb >= lsb);
  ASSERT(msb DIV 32 = 0);
  ASSERT(lsb DIV 32 = 0);
  RETURN ROR(ORD(BITS(word) * {lsb..msb}), lsb)
END UBF;

The corresponding examples become:

  • Example 1; Extracting a 4-bit bitfield from bit positions [7:4] of a word

    Code: Select all
    VAR word, bitfield: INTEGER;

      word := 0ABCDEF75H;
      bitfield := UBF(word, 7, 4);

    The resulting value of bitfield is 07H;

  • Example 3: Just to show the bitfield length and bits do not have to be multiples of 8 or 4 etc. - extracting a ten-bit bitfield from a word at bit positions [22:13]

    Code: Select all
      word := 0ABCDEF75H;
      bitfield := UBF(word, 22, 13); 

    The resulting value of bitfield is 026FH;
cfbsoftware
Site Admin
 
Posts: 355
Joined: Fri Dec 31, 2010 12:30 pm


Return to Oberon Language

cron