-1

I'm looking for a generic way to load a 32 bits constant in ARM mode. Unfortunately I can't use neither "ldr rX, =const" (due to external problems) nor movw/movt (my target is a armv6k)

This is my attempt:

mov rX, 0
orr rX, (const&0x000000FF)
orr rX, (const&0x0000FF00)
orr rX, (const&0x00FF0000)
orr rX, (const&0xFF000000)

Is my code correct? Can you suggest me a better way? Thank you.

Mm7
  • 21
  • 3
  • 1
    As per the *related* links on the side, [SO tag ARM + constants](http://stackoverflow.com/search?q=[arm]+constants) gives at least, [ARM 12bit constants](http://stackoverflow.com/questions/20071767/arm-why-only-12-bits-for-immediate-constants), where I cited at least 5 different duplicates of this question. And some google searching will give [ARM blog](http://community.arm.com/groups/processors/blog/2010/07/27/how-to-load-constants-in-assembly-for-arm-architecture) which must answer all your questions. – artless noise Dec 28 '14 at 18:02
  • @artlessnoise Keep in mind that in my case "ldr rX, =const" can't be used. The links that you provide me don't solve the problem in this case. – Mm7 Dec 28 '14 at 22:38
  • You can use `ldr rX,=const`; what ever your *external problem* is, is your problem. The way to do this with ARM assembler is this way. You can manually code this and you have accepted an answer that say use `ldr rX, =const`. There are many other ways to do this with shorter mathematical identities (depending on constants) than the `orr` method. – artless noise Dec 30 '14 at 22:20
  • @artlessnoise I'm patching the Android Runtime (ART) to generate ARM mode code. ART has to handle also 32bit constant loading, but in this context I don't know how to handle PC-relative expressions (putting constants at the end of a function is also a problem), so I have to use mov/orr. This is why in the question I asked for a **generic** (constant is not known at compile time) way to load a 32bits function != "ldr rX,=const". For this reason all the links you provide me are not useful. I marked dwelch's answer as correct because it provide me a way to solve the problem (and it is not ldr). – Mm7 Dec 31 '14 at 09:32

1 Answers1

3

arm and gnu assemblers both allow the syntax:

ldr rX,=0x12345678

Which results in a location within pc relative addressing range (if possible) being allocated with the data word 0x12345678 and the instruction encoded as a pc-relative load, basically:

ldr r0,my_data
...
my_data: .word 0x12345678

Your other alternative is one instruction less than what you outlined:

mov rX,0x0000078
orr rX,rX,0x00005600
orr rX,rX,0x00340000
orr rX,rX,0x12000000

Now at least with gcc, dont know about arm, if you use the ldr rX,=number feature and the number can be encoded with a single move, it will encode that single mov...

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • re-reading, if you cant use the ldr rX,=const (cant imagine why) then you need to do the four instruction thing. – old_timer Dec 27 '14 at 22:46
  • The main reason it would not work is failure to issue an `.ltorg` instruction. The 'my_data' which is placed by the `.ltorg` may be far off a cache-line (this is why movw/movt are better) and if you only have a few instructions (sub/add/rsb, etc may also get the constant) it may be better than an `ldr rx,=constant`. Generally that is mis-guided as the `.ltorg` data will probably be used by other code doing the same thing so putting it in cache is not a bad thing. – artless noise Dec 28 '14 at 18:10
  • Another important point is the instruction is `ldr r0, [pc, #offset_my_data]`, which makes the code relocatable and if the data fits in a simple move, that will be used (`ldr r0,=0xfe` will be `mov r0, #0xfe` and will not emit anything to the *literal pool*). – artless noise Dec 28 '14 at 18:20