Clear upper 16-bits in 1 ARM instruction
-
08-07-2019 - |
Question
In ARM assembly immediates are encoded by an 8-bit rotated value which means we can only encode
(0-256)^2n.
Now my problem is that I want to clear the upper 16-bits of r0 and replace it with the half-word stored r1. But because of the limited range of the immediates I have to do: -
bic r0, r0, #0xff000000
bic r0, r0, #0x00ff0000
add r0, r0, r1, LSL #16
Is it possible to do replace the 2 bic instructions with a single instruction? 0xffff0000 is unencodable. Perhaps I should be using another logical operation to clear the upper 16-bits?
Thanks
EDIT: Sorry I forgot to say that the top 16-bits of r1 is empty, and I'm using an ARM7TDMI
Solution
How about:
orr r0,r1,r0,lsl #16
mov r0,r0,ror #16
(This assumes that the top halfword of r1 is empty, like your reference code did.) Depending on the circumstances, you might be able to omit the final mov here by merging it with some later code.
OTHER TIPS
If you have a new enough ARM core the asked question is simple:
movt r0, #0
orr r0, r0, r1,lsl#16
See http://www.keil.com/support/man/docs/armasm/armasm_cjagdjbf.htm
However if you do have ARMv6+ you can actually do the whole quoted example in one go:
pkhbt r0, r0, r1,lsl#16
See http://www.keil.com/support/man/docs/armasm/armasm_cihjedjg.htm
"replace it with the half-word stored r1" - does this mean you can assume the top 16 bits of r1 are zero? If so,
add r0, r1, r0 lsl #16
mov r0, r0 ror #16
Think of the mov as a placeholder, since you can hopefully move the ror to whatever would take r0 as input next and actually do useful work in the same cycle.
On ARMv6 (e.g. MPCore), you can say
uxth r1, r1
orr r0, r1, r0, asl #16
If you can clear the whole thing, you could xor
it with itself.
If you need to retain the bottom half, might you be able to left-shift the register 8 bits and back? That may be same number of instructions, though.
For the C code
(a<<16)|((short)b)
gcc generates
mov r1, r1, asl #16
mov r1, r1, asr #16
orr r0, r1, r0, asl #16
which doesn't use any immediates - it's still two instructions, though.
You can use BFC instruction. Bit Field Clear. This instruction clears n bits from m bit