BIT WISE AND/OR operation

Topics related to the use of Oberon language features
Post Reply
Din
Posts: 2
Joined: Mon Oct 15, 2018 10:12 pm

BIT WISE AND/OR operation

Post by 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.

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

Re: BIT WISE AND/OR operation

Post by 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 2671 times

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

Re: BIT WISE AND/OR operation

Post by cfbsoftware » Sat Oct 27, 2018 11:00 am

We have implemented two built-in functions, BFI and BFX, 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;
      bitfield := BFX(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;
      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;
      bitfield := BFX(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 BFX*(word, msb, lsb: INTEGER): INTEGER; 
BEGIN
  bitfield := ROR(ORD(SYSTEM.VAL(SET, word) * {lsb..msb}), lsb); 
END BFX;
We're considering implementing these in a future release of the Astrobe RISC5 compiler as built-in 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.

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

Re: BIT WISE AND/OR operation

Post by 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

Post Reply