assemblyarmcortex-m

What is the most efficient way to write two (for example) bits of a register using cortex-m0 instruction set?


Simple example. We want to write '01' bits in the most right bits of register. Should we reset '0' bit and set '1' bit separately? Is there a way to do it in a single instruction?

For instance, if the register has a value 0x11000002: the most right bits are '10', and at the end it should be 0x11000001: the most right bits are '01', the rest of bits remain unchanged.


Solution

  • I don't think you can do it better than three instructions:

            @ set least 3 bits of R0 to 01
            movs r1, #3
            bics r0, r1    @ clear least two bits of R0
            adds r0, #1    @ set LSB of R0
    

    If you do this in a loop, you can hoist the constant load out of the loop for two instructions per iteration.

    If you don't have a spare register, you can also do

            lsrs r0, #2    @ shift out least two bits of R0
            lsls r0, #2    @ shift remaining bits back into position
            adds r0, #1    @ set LSB of R0
    

    This takes the same 3 cycles as the approach above, but it doesn't need a separate register. Slower if you can hoist the constant load out of the loop.

    On a Cortex-M3 or better, you can indeed do it in only two instructions:

             movs r1, #1
             bfi r0, r1, #0, #2  @ insert least two bits of R1 into R0
    

    There are other options, too, such as

             bic r0, #3   
             adds r0, #1
    

    if you don't want to use an extra register, but the one above is best if you can hoist the constant load out of a loop.