# ARM "add" instruction with shift

I'm trying to understand how ARM `add` with shift is implemented e.g.

``````sym.imp.__libc_start_main :

.plt:0x000082bc 00c68fe2 add ip, pc, 0, 12; after execution ip=0x82c4
.plt:0x000082c0 08ca8ce2 add ip, ip, 8, 20; after execution ip=0x102c4
.plt:0x000082c4 48fdbce5 ldr pc, [ip, 0xd48]!
``````

``````.plt:0x000082c0 08ca8ce2 add ip, ip, 8, 20;
``````

it will add `#0x8000` to the ip register. My question is why `#0x8000` ?

I'd assume it will be:

``````ip = ip + (8<<20)
``````

so `0x800000` but it's more like

``````ip = ip + (8<<(20-8))
``````

Why is that? do I always have to substract 8 from the shift ?

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`

1. `e` - always execute this instruction
2. `28` - add immediate
3. `c` - Rd is the ip
4. `c` - Rn is the ip
5. `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);
return (value<<count) | (value>>( (-count) & mask ));
}

uint32_t rotr32 (uint32_t value, unsigned int count) {
const unsigned int mask = (CHAR_BIT*sizeof(value)-1);
return (value>>count) | (value<<( (-count) & mask ));
}

int main()
{
printf("Result: 0x%x\n",rotr32(8,20));
return 0;
}
``````

The code will output:

``````Result: 0x8000
``````
• I see so its rotate right and not left, thanks! BTW. typo in the anwser on line "that it's not 8<<20 but instead it is 8<<(32-12)" should be 8>>(32-12) Aug 21 '17 at 19:14

It is proposed in the official document of arm When s = 1 and RD = R15 (PC), this instruction is used to save the status register CPSR, not to do calculation 