Home > front end >  How can I elegantly take advantage of ARM instructions like REV and RBIT when writing C code?
How can I elegantly take advantage of ARM instructions like REV and RBIT when writing C code?

Time:01-10

I am writing C code which may be compiled for the Arm Cortex-M3 microcontroller.

This microcontroller supports several useful instructions for efficiently manipulating bits in registers, including REV*, RBIT, SXT*.

Useful Cortex-M3 instructions

When writing C code, how can I take advantage of these instructions if I need those specific functions? For example, how can I complete this code?

#define REVERSE_BIT_ORDER(x)    {  /* what to write here? */ }

I would like to do this without using inline assembler so that this code is both portable, and readable.

Added:

In part, I am asking how to express such a function in C elegantly. For example, it's easy to express bit shifting in C, because it's built into the language. Likewise, setting or clearing bits. But bit reversal is unknown in C, and so is very hard to express. For example, this is how I would reverse bits:

unsigned int ReverseBits(unsigned int x)
{
    unsigned int ret = 0;
    for (int i=0; i<32; i  )
    {
        ret <<= 1;
        if (x & (1<<i))
            ret |= 1;
    }
    return ret;
}

Would the compiler recognise this as bit reversal, and issue the correct instruction?

CodePudding user response:

Reversing bits in a 32 bit integer is such an exotic instruction so that might be why you can't reproduce it. I was able to generate code that utilizes REV (reverse byte order) however, which is a far more common use-case:

#include <stdint.h>

uint32_t endianize (uint32_t input)
{
  return ((input >> 24) & 0x000000FF) |
         ((input >>  8) & 0x0000FF00) |
         ((input <<  8) & 0x00FF0000) |
         ((input << 24) & 0xFF000000) ;
}

With gcc -O3 -mcpu=cortex-m3 -ffreestanding (for ARM32, vers 11.2.1 "none"):

endianize:
        rev     r0, r0
        bx      lr

https://godbolt.org/z/odGqzjTGz

It works for clang armv7-a 15.0.0 too, long as you use -mcpu=cortex-m3.

So this would support the idea of avoiding manual optimizations and let the compiler worry about such. Although asm("rev r0,r0") is arguably far more readable than the bitwise C goo.

CodePudding user response:

It would be best if you used CMSIS intrinsic.

__REV, __REV16 etc. Those CMSIS header files contain much much more.

You can get them from here:

https://github.com/ARM-software/CMSIS_5

and you are looking for cmsis_gcc.h file (or similar if you use another compiler).

  • Related