2

I'm using a dsPIC33F and GCC. I want to rotate the bits in a word once left or right, like this:

       MSB             LSB
input: 0101 1101 0101 1101
right: 1010 1110 1010 1110
left : 1011 1010 1011 1010

(In case it's not clear, the LSB moves into the MSB's position for the right rotate and vice versa.)

My processor already has a rotate right (rrnc, rrc) and rotate left instruction (rlnc, rlc), so I'm hoping the compiler will optimise this in. If not, I might have to use inline assembly.

Jason S
  • 184,598
  • 164
  • 608
  • 970
Thomas O
  • 6,026
  • 12
  • 42
  • 60

3 Answers3

6

You may write them as obvious combination of conventional shifts:

x rol N == x << N | x >> width-N
x ror N == x >> N | x << width-N

where width is number of bits in number you rotate.

Intelligent compiler may (i think it would be) detect this combination and compile to rotation instruction.

Note it works for unsigned and if width is equal to number of bits in machine word you are dealing on (16 for unsigned int on dsPIC).

Vovanium
  • 3,798
  • 17
  • 23
  • 1
    Be aware that a shift that is greater than the word size results in undefined behaviour in C. So you should supply ASM or C that obeys the language. – jww Nov 30 '14 at 22:17
  • @jww: Actually this is fine as long as `x` is unsigned, which it ought to be if you are doing rotations. See http://stackoverflow.com/q/3784996/ for quotes from the relevant standards. – Nemo Jul 15 '15 at 21:39
  • 1
    @Nemo - if `N` or `width-N` is the size of a register, then its undefined behavior. I've spent two days clearing them from Clang's and G++'s Undefined Behavior sanitizer (UBsan). Grab a copy of Fedora 21 or Debian 8, and compile with `CFLAGS += -fsanitize=undefined` and `CXXFLAGS += -fsanitize=undefined`. – jww Jul 15 '15 at 21:56
  • 1
    @jww: Yeah, you're right. The relevant section of the standard is not cited in the answer I linked. C++11 section 5.8 paragraph (1) says: "The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand." So this answer fails for N <= 0 or N >= width. (Although it might happen to "work" on platforms where the shift count in the assembly instruction is interpreted modulo the word size... Like x86. Still technically undefined of course.) – Nemo Jul 15 '15 at 22:28
1

There is no circular shift in C. (Reference)

Inline assembly might be the way to go, if performance is critical. Otherwise you could use the code in the article linked above.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
0

There is a GCC for dsPIC? Look in its manual if it has got an intrinsic for circular shifts. The other option is inline asm.

AndreKR
  • 32,613
  • 18
  • 106
  • 168
  • It has no intrinsic for the rrc instruction. And yes, there is a GCC for dsPIC, but not quite in that it is a custom build by Microchip and I don't think that dsPIC support is native to GCC. – Thomas O Nov 17 '10 at 18:11