I can't seem to find a way to, with a single instruction, place an immediate value into a register in a position that is not the lowest bit.
For instance, suppose you want your register to be r1 = 0x00110000
. Then, a multi instruction way to do this is.
mov r1, #0x11
lsl r1, #16
I'm working with several devices and some of them allow immediate values up to 32 bits, but most don't, so I can only use the basic ARM instructions.
Let your assembler encode the shift / rotate for you, by giving it the 0x00110000
value.
Most assemblers (including all ARM assemblers?) support assemble-time constant expressions so you can write
mov r1, #0x11 << 16
This will assemble in ARM mode to 11 18 a0 e3
. But in Thumb mode it requires ARMv6 Thumb2. See http://www.keil.com/support/man/docs/armasm/armasm_dom1361289878994.htm for the available forms of MOV.
Probably a better choice is and LDR pseudo-instruction that lets the assembler pick between a PC-relative load (from a literal pool) or a mov-immediate with some encoding. http://www.keil.com/support/man/docs/armasm/armasm_dom1359731145835.htm (That's keil's doc for their assembler, but GAS and clang also support the same syntax.)
ldr r1, =0x11 << 16
I'm working with several devices
Consider rebuilding for each device so you can make code optimized for each one. Especially if you use ldr reg, =value
- it can use mov.w reg, #imm16
when available.
and some of them allow immediate values up to 32 bits
If you're talking about ARMv6T2 movt
/ movw
, that's two 32-bit instructions each providing a 16-bit half.
No ARM is capable of encoding any arbitrary 32-bit constant with a single instruction; that would leave no bits for an opcode in a 32-bit instruction.