In my ATtiny84a AVR Assembly program I end up with a bit number between 0 and 7, in a register, lets say r16. Now I need to create a mask with that bit number set. To make it more complicated, the timing of the operation must be the same, regardless of what bit is set.
For example if r16 = 5 the resulting mask will be 0x20 (bit 5 set).
So far I have shifted a bit into position by LSL and using r16 (the bit number) as a loop counter, then to keep exact timing regardless bit number, do a dummy loop of NOP 8-r16 times.
The assembly instruction SBR sets bit(s) in a register from a mask so it can't be used. The assembly instruction SBI sets a bit in an I/O register from bit number, but it is a constant, not a register (I could have used an I/O register as a temp register).
The mask is then used to clear a bit in a memory location, so if there is another solution to do that from a bit number in a register, then it's fine too.
I have another solution to try out (shift based with carry) but I was hoping that someone have a more elegant solution than loops and shiftings.
Thank you all for your creative answers, but I went with the lookup table as a macro. I find this being the most flexible solution because I can easily have different lookup tables for various purposes at a fixed 7 cycles.
; @0 mask table
; @1 bit register
; @2 result register
.MACRO GetMask
ldi ZL,low(@0)
ldi ZH,high(@0)
add ZL,@1
adc ZH,ZERO
lpm @2,Z
.ENDM
bitmask_lookup:
.DB 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
inverse_lookup:
.DB ~0x01,~0x02,~0x04,~0x08,~0x10,~0x20,~0x40,~0x80
lrl2_lookup:
.DB 0x04,0x08,0x10,0x20,0x40,0x80,0x01,0x02
ldi r16,2
GetMask bitmask_lookup, r16, r1 ; gives r1 = 0b00000100
GetMask inverse_lookup, r16, r2 ; gives r2 = 0b11111011
GetMask lrl2_lookup, r16, r3 ; gives r3 = 0b00010000 (left rotate by 2)
Space is not so much of an issue, but speed is. However, I think this is a good compromise and I'm not forced to align data on quadwords. 7 vs 5 cycles is the price to pay.
I already have one "ZERO" register reserved through the whole program so it costs me nothing extra to do the 16bit addition.