Understand common ARM patterns and translate them to C
Understand common ARM patterns and translate them to C
This series should point out ARM code that you often find in firmwares and what they mean and how the sourcecode of such functions could have looked like in C.
Re: Understand common ARM patterns and translate them to C
SHIFT instead of AND
Understanding the operations
You often find code that is shifting an registers bits to left and right (or the opposite way) by the same ammount of bits, for example:
The operation LS means "Logical Shift", a bitwise shift operation. The char following denotes the direction "L=Left", "R=Right" and the last char S sets the flags by the outcome of this operation (which it won't if the S is not given). The flags are in fact not relevant here and it would work exactly the same way without them.
The first register after the operation is the target register, the second the source register, which is also common ARM syntax. It means that the value of the second register "R1" is used for the shift operation and the result of it (which is hold in the processor accumulator so far) it put into the first register "R1". The number of bits to shift is the third parameter, "#25" in the example. The "#" denotes a direct, fixed value. When shifting values, some bits will "fall out of the register" because the are shifted away and new bits enter, which are per default "0".
Make a simulation
Let's see what happens when executing this operation with some patterns in R1:
The value of R1 is shifted by 25 positions to the left and load back into R1 again. This is result would be 0b11111110 00000000 00000000 00000000, so only the the lowest 7 bits of the original value survived that operation.
Now shifting back to the right again:
And the bits are on their original position 0b00000000 00000000 00000000 01111111.
Conclusion
The operation will in fact mask out the upper 25 bits of the register value. This could have been done with an bitwise AND operation also, but in fact would require more operation bytes and might be a little bit slower than shifting. So this is a optimization the compiler of the source did.
In pure C we would translate such an pattern to:
So whenever you encounter such an operation, just do an bitwise AND with a number that has the remaining bits of the given count set.
Understanding the operations
You often find code that is shifting an registers bits to left and right (or the opposite way) by the same ammount of bits, for example:
Code: Select all
LSLS R1, R1, #25
LSRS R1, R1, #25
The first register after the operation is the target register, the second the source register, which is also common ARM syntax. It means that the value of the second register "R1" is used for the shift operation and the result of it (which is hold in the processor accumulator so far) it put into the first register "R1". The number of bits to shift is the third parameter, "#25" in the example. The "#" denotes a direct, fixed value. When shifting values, some bits will "fall out of the register" because the are shifted away and new bits enter, which are per default "0".
Make a simulation
Let's see what happens when executing this operation with some patterns in R1:
Code: Select all
MOVS R1, #0b11111111 11111111 11111111 11111111
LSLS R1, R1, #25
Now shifting back to the right again:
Code: Select all
MOVS R1, #0b11111110 00000000 00000000 00000000
LSRS R1, R1, #25
Conclusion
The operation will in fact mask out the upper 25 bits of the register value. This could have been done with an bitwise AND operation also, but in fact would require more operation bytes and might be a little bit slower than shifting. So this is a optimization the compiler of the source did.
In pure C we would translate such an pattern to:
Code: Select all
uint32_t R1 = R1 & 0xFE;
# or shorter
uint32_t R1 &= 0xFE;