Not really a better idea for 3 bits, but it would be for 4:
prog_uint8_t inv_table[8]={0,4,2,6,1,5,3,7};
unsigned char inv_test(void)
{
return pgm_read_byte(&inv_table[PORTB & 0x3]);
}
The output from gcc 4.2.0:
byte inv_test(void)
{
return pgm_read_byte(&inv_table[PORTB & 0x3]);
96: e8 b3 in r30, 0x18 ; 24
98: ff 27 eor r31, r31
9a: e3 70 andi r30, 0x03 ; 3
9c: f0 70 andi r31, 0x00 ; 0
9e: ec 5a subi r30, 0xAC ; 172
a0: ff 4f sbci r31, 0xFF ; 255
a2: e4 91 lpm r30, Z
}
a4: 8e 2f mov r24, r30
a6: 99 27 eor r25, r25
a8: 08 95 ret
If not for the redundant "andi r31, 0x00" (when r31 has just been zeroed
by the "eor r31,r31") it would give the same number of instructions as
your code.
The nice thing about this approach is that it works the same for 4 or
more bits (up to 8).