It's a Circular Shift on a 32-bit system.
Circular Shift
In computer programming, a circular shift (or bitwise rotation) is a
shift operator that shifts all bits of its operand. Unlike an
arithmetic shift, a circular shift does not preserve a number's sign
bit or distinguish a number's exponent from its significand (sometimes
referred to as the mantissa). Unlike a logical shift, the vacant bit
positions are not filled in with zeros but are filled in with the bits
that are shifted out of the sequence.
Understanding the code
First Line:
This is simply translated into add ip, pc
because rotate operations on #0
is still 0.
So it's actually IP = PC + (0 << 12) = PC + 0
Second Line:
Let's take apart the opcodes and understand the problematic line:
The opcodes should be read like this because of endianness: e28cca08
e
- always execute this instruction
28
- add immediate
c
- Rd is the ip
c
- Rn is the ip
a 08
- 8 right rotated by 20
The things is, that it's not 8<<20
but instead it is 8<<(32-12)
because we are on a 32-bit system and it is a Circular Shift.
Here's a C code that showing the Circular Shift based on the example from Wikipedia:
#include <stdint.h> // for uint32_t, to get 32bit-wide rotates, regardless of the size of int.
#include <limits.h> // for CHAR_BIT
uint32_t rotl32 (uint32_t value, unsigned int count) {
const unsigned int mask = (CHAR_BIT*sizeof(value)-1);
count &= mask;
return (value<<count) | (value>>( (-count) & mask ));
}
uint32_t rotr32 (uint32_t value, unsigned int count) {
const unsigned int mask = (CHAR_BIT*sizeof(value)-1);
count &= mask;
return (value>>count) | (value<<( (-count) & mask ));
}
int main()
{
printf("Result: 0x%x\n",rotr32(8,20));
return 0;
}
The code will output:
Result: 0x8000