I am new to ARM world. In the ARM Cortex-A series : Programmer's guide (page 71), there is an example for BIC instruction :
BIC R0, R0, #0x800
As per the text, this basically clears the bit 11 in R0. I understand that the BIC works like R0 = R0 & (~val)
here (please correct me). But what I don't understand here is that how #0x800
was taken as-is and gets translated to 1000 0000 0000
literally. Instead, it should have been split into 4-bit:8-bit part as per immediate encoding rules.
And as per my understanding of ARM encoding for constants:
0x800 = 0000 1000 0000 0000
Out of these bits, we consider only last 12 bits for encoding and out of these 12 bits - first 4 bits decide the right-rotation in steps of 2 and the last 8 bits is the number right-rotated (considering it as 32bit). So in this case, since last 8 bits are all zeros, I should have got FFFF 0000
after 2*8 right-rotations.
And for the complete BIC instruction above, it should have then treated as :
R0 = R0 & (0000 FFFF)
I know I am wrong somewhere. Can someone please correct me.
The short answer is that you don't included an encoded literal field in your assembly, you include the value that has meaning, that you actually want to use. The assembler's job includes determining the (best, if there is one) instruction encoding for the specified assembly.
The assembler takes care of encoding values provided in assembly into the literal field of the instruction. #0x800
is the literal. As an assembler programmer, you just need to ensure that the literal is encodable.
It would be annoying and incredibly error-prone to have to calculate encoded rotates. This type of conversion is much of the difference between assembly and machine code. To look at the actual generated literal field, look at the result after assembly.
This also leads to some of the non-1-to-1 relationship between assembly and machine code seen in some ISAs.
The value 0x800
is directly the 0b1000_0000_0000
.
Assembling
BIC R0, R0, #0x800
gives me
02 0B C0 E3
So the Operand2
field is 0xB02
. This means that the Immediate is 0x02
, and the Rotate is 0xB
. Taking 0x00000002
and rotating right by 2 * 0xB
, we get the expected 0x800
.