1
votes

I am in a situation where I need to store a pointer to the next instruction in Thumb-2 assembly code. Thumb-2 instructions can be 16- and 32-bit, and are thus halfword-aligned. When I use PC as the source operand in an add, I actually read the word-aligned program counter plus 4 (that is, either 2 or 4 more than the current instruction). Therefore, I need to add either 0 or 2 to the current program counter to get the next instruction address.

Now, I could use .align to get this instruction on a word boundary, in which case I can simply add 0. However, I would like to not use nops if not necessary.

Is something like the following possible?

.if alignment_of_next_instruction % 4 == 2
        add r12,pc,#2
.else
        add r12,pc,#0       @ just an example, mov would be better
.endif
        str r12,[sp,#-4]!

The reason I cannot use nop is that in some cases I don't need to get the address of the next instruction, but the instruction after that, or even one further. In those cases, an add is necessary, but whether I need to add 10 or 12 (for example) depends on alignment.

If this isn't clear, here is what .align would look like with my proposed syntax:

.if alignment_of_next_instruction % 4 == 2
        nop
.endif

I cannot find anything in the ARM SDK reference guide, section Assembler expressions and operators (5.9), but perhaps I should be looking elsewhere.

1
Using a longer but equivalent instruction instead of padding with NOPs is a known technique on x86 (where it's often possible to use a different encoding for an exactly identical instruction), but seldom used because assemblers won't do it for you. Hopefully someone knows or wants to implement something like this in an open-source assembler, because it's a cood idea for a viable syntax for this sort of thing.Peter Cordes
@PeterCordes I don't think there is a longer (or shorter) equivalent instruction, these adds are already 32 bits and I don't see a way to make them 16 bits - and on ARM those are all the options you get. I will see in the morning what the as source code looks like or perhaps write an email on the binutils list.user1544337
Can you do something with an instruction somewhere before the add, so it's always aligned the way you want for a mov? (For safely against future breakage, put a .p2align 2 before it, so you'll get a NOP if someone changes the code between where you create the alignment and where it's needed. So for now, it will not need to pad, but in future you'll get padding instead of breakage. Or use this conditional thing to create a build-time error if the requirement is violated.)Peter Cordes
@PeterCordes well, in the real code in some cases we need to store the address of the next-next instruction, so then a mov won't work. Sorry, perhaps I should have written that in the question. In any case, adding .align will already add at most one nop. It's really that in cases where an add is actually necessary (cannot be replaced by mov), the immediate value added should be different depending on the alignment.user1544337
I guess there are multiple use-cases for an assemble-time query of the current alignment. One of them is what I suggested; using alternate instructions to control alignment at a later point. Your use-case might not be solved by that exactly (depending on what you want the alignment of every instruction to be), so it counts as different.Peter Cordes

1 Answers

2
votes

Rather than faffing about trying to work in terms of addresses and offsets, just specify things in terms of instructions, i.e. with a label:

   adr r12, 1f
   ...
1: <instruction of interest>

The assembler and linker know what to do.