0
votes

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.

1
Loading from a literal pool is a single instruction but is not smaller in size. Unclear what your objective is.Jester
Wait what? Your title says store to memory (AFAIK all ARM store instructions use any spare bits for addressing mode offsets, not immediate store data). But then you're just talking about loading an immediate value into a register. mov r1, #0x11 << 16 assembles fine; use that. I think Thumb2 mode allows a rotated 8-bit immediate, and your assembler knows how to encode any encodeable immediate.Peter Cordes
Ah thank you @PeterCordes ! I didn't even think about using that notation! And yes, there's a mistake in the title, I'll correct it nowDominus
Or you can just use ldr r1, =0x00110000 and let the assembler sort it out.Jester

1 Answers

1
votes

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.