Search code examples
arm64

How do we store large decimal/hex value in ARMs?


I run into a roadblock and not sure where to go from here. I know MOV can only store a maximum of 0-65535 in decimal. However, the value I'm trying to store is 30,402,460.

I was going to use MVN as some source mention that can store bigger number in this format: MVN X9, #(num), #(num). However 30402460 / 110 = only equals 276,386 which is still above the decimal value of 65535 so I can't use MVN.

My question is; how do we store 30402460 to X9?


Solution

  • MOV is not a real instruction. It's an alias that will be turned into either MOVZ, MOVN or ORR as appropriate. But each of those have their own constraints:

    • MOVZ can load an arbitrary 16 bits, left-shifted by 0, 16, 32 or 48 bits. So you can only use this for values with 48 bits of all zeroes.
    • MOVN does the same as MOVZ, but inverts the register value. So you can only use this for values with at least 48 bits of all ones.
    • ORR can construct a really complicated bitmask which, as best as I can tell, can be any sequence of consecutive runs of zeroes, ones, zeroes or ones, zeroes, ones, repeated by any power of two that is a divisor of the register width. So you can load values like 0xaaaaaaaaaaaaaaaa, 0xfffffff00fffffff and 0x18, but not values like 0x0 or 0x5.

    The value 30402460 matches none of these constraints. The usual practice for loading such values is to use MOVZ followed by MOVK, the latter of which allows replacing 16 bits of a register without changing the other bits. So in your case:

    movz x9, 0x1cf, lsl 16
    movk x9, 0xe79c