Dmitry K. wrote:
Hi.

I have compile CVS version avr-libc (2007-02-20)
with for different compilers.

Dmitry,

While you are "testing", have you checked the code quality for the I/O "bit test" logic in avr-gcc v4.1.2?

I reported the following "bad I/O code" awhile back with avr-gcc v3.4.6:

An example of why more people should be "watching" the "avr-gcc" code generator are these three simple C routines which test a bit in one of the AVR microcontroller I/O ports. Because of the AVR instruction set's clever "sbic" and "sbis" instructions, the machine code for tests like these should be short...and very fast.

However, only "test3()" produces the expected (i.e., correct) AVR instructions:

#include <avr/io.h>

#define J1708_IN_PORT  PORTD
#define J1708_IN_DDR   DDRD
#define J1708_IN_PIN   PIND
#define J1708_IN_BIT   3

 int test1(void)
 {
   unsigned char bit = (J1708_IN_PIN & (1 << J1708_IN_BIT)) ? 1 : 0;
   return bit;
 }

 int test2(void) {
  if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 0;
  return 1;
 }

 int test3(void) {
  if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 1;
  return 0;
 }

...compiled with avr-gcc 3.4.6:

 C:/WinAVR_20060421/bin/avr-gcc -mmcu=atmega16 -Os \
         -mcall-prologues -Wall -c \
         -gstabs -Wa,-ahlmsd=x.lst -o test.o test.c

...gives us horrible code for all except "test3()":

 **** int test1(void)
 **** {
 ****     unsigned char bit = (J1708_IN_PIN & (1 << J1708_IN_BIT)) ? 1 : 0;
       test1:
               in r24,48-0x20
               clr r25
               ldi r18,3
       1:      lsr r25
               ror r24
               dec r18
               brne 1b
               andi r24,lo8(1)
 ****     return bit;
 **** }
               clr r25
               ret

 ****
 **** int test2(void) {
 ****    if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 0;
       test2:
               in r24,48-0x20
               clr r25
               movw r18,r24
               andi r18,lo8(8)
               andi r19,hi8(8)
               sbrc r24,3
               rjmp .L3
               movw r24,r18
               ret
       .L3:
 ****    return 1;
               ldi r24,lo8(1)
               ldi r25,hi8(1)
 **** }
               ret

 **** int test3(void) {
 ****    if (!(J1708_IN_PIN & (1 << J1708_IN_BIT))) return 1;
       test3:
               sbic 48-0x20,3
               rjmp .L5
               ldi r24,lo8(1)
               ldi r25,hi8(1)
               ret
       .L5:
 ****    return 0;
               ldi r24,lo8(0)
               ldi r25,hi8(0)
 **** }
               ret

The bit-shift "loop" code generated for "test1()" is really "special". :-) (Yes, that's 5 clocks per bit shift!)

I was lucky that my application only referenced bit 3 in the I/O port. If the hardware had used bit 6, the routine would take twice as long to execute...over 33 clocks for an I/O bit test that should have taken just a couple of clocks!

Note that the only difference between "test2()" and "test3()" is the return value (i.e., 0 vs. 1). Experiments show that returning "0" is what triggers the "bad behavior". This bad example takes 6 AVR instructions to do the work of one "sbic" instruction.

Best regards,

Bruce

--
Bruce D. Lightner
Lightner Engineering
La Jolla, California
Voice: +1-858-551-4011
FAX: +1-858-551-0777
Email: [EMAIL PROTECTED]
URL: http://www.lightner.net/lightner/bruce/

_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Reply via email to