avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Re: Why is gcc promoting on an unsigned char?


From: J.C. Wren
Subject: Re: [avr-gcc-list] Re: Why is gcc promoting on an unsigned char?
Date: Tue, 23 Dec 2003 02:07:34 -0500
User-agent: KMail/1.5.4

        Well, we get marginally better results with this, but still 3 extra 
instructions.  Putting in typecasts everywhere else in the statement as a 
test had no additional impact.

        --jc

      data |= (unsigned char) (bit_is_set (DATAPIN, DATA) ? i : 0);
  80: 33 27          eor   r19, r19
  82: c9 9b          sbis  0x19, 1  ; 25
  84: 05 c0          rjmp  .+10        ; 0x90
  86: 84 2f          mov   r24, r20
  88: 99 27          eor   r25, r25
  8a: 82 2b          or r24, r18
  8c: 93 2b          or r25, r19
  8e: 02 c0          rjmp  .+4         ; 0x94
  90: 93 2f          mov   r25, r19
  92: 82 2f          mov   r24, r18
  94: 28 2f          mov   r18, r24


On Tuesday 23 December 2003 01:37 am, Rune Christensen wrote:
> Hello
>
> I think that I have found an answer to you.
>
> Earlier Eric Weddington wrote:
>
> This is not a bug. The C Standard states that bitwise operators can promote
> a char to an int. GCC adheres to the Standard pretty closely, even though
> some things in the Standard are not amenable to embedded systems. Remember
> that GCC is used on a variety of computer platforms as well. This issue is
> also noted in the avr-libc FAQ (#20), which is in the avr-libc user manual.
> Did you look there?
>
> The workaround is to typecast the operation. For example if you are
> clearing bits, you could do something like:
>
> (uint8_t)PORTB &= (uint8_t)~mask;
>
> Note that in the specific example of clearing bits, be sure to place the
> typecast *before* the bitwise NOT operator, as that operator could promote
> to int.
>
> If you feel that liberally sprinkling typecasts would look ugly, you can
> always create macros, such as:
>
> #define bit_clear_byte(var, mask)   ((uint8_t)(var) &= (uint8_t)~(mask))
>
> bit_clear_byte(PORTB, 0x01);
>
> You can also define macros for 16-bit sizes:
>
> #define bit_clear_word(var, mask)   ((uint16_t)(var) &= (uint16_t)~(mask))
>
> And of course macros for setting bits, toggling bits, etc.
>
> -----Original Message-----
> From: address@hidden
> [mailto:address@hidden Behalf Of J.C. Wren
> Sent: Tuesday, December 23, 2003 7:09 AM
> To: address@hidden
> Subject: [avr-gcc-list] Re: Why is gcc promoting on an unsigned char?
>
>
> OK, part of that was my fault, I had "i << 1" instead of "1 << i".  But
> nonetheless, we still see some extra code at 0x94, 0x9c, 0xa0, and 0xa4.
> The
> compiler should be able to foresee the type of 'data', and not promote the
> intermediate results, right?
>
>       --jc
>
>       loop_until_bit_is_clear (CLKPIN, CLK);     // Receive first databit
>   80: c8 99          sbic  0x19, 0  ; 25
>   82: fe cf          rjmp  .-4         ; 0x80
>       data |= (bit_is_set (DATAPIN, DATA) ? (1 << i) : 0);
>   84: 33 27          eor   r19, r19
>   86: c9 9b          sbis  0x19, 1  ; 25
>   88: 0b c0          rjmp  .+22        ; 0xa0
>   8a: 97 2f          mov   r25, r23
>   8c: 86 2f          mov   r24, r22
>   8e: 04 2e          mov   r0, r20
>   90: 02 c0          rjmp  .+4         ; 0x96
>   92: 88 0f          add   r24, r24
>   94: 99 1f          adc   r25, r25
>   96: 0a 94          dec   r0
>   98: e2 f7          brpl  .-8         ; 0x92
>   9a: 82 2b          or r24, r18
>   9c: 93 2b          or r25, r19
>   9e: 02 c0          rjmp  .+4         ; 0xa4
>   a0: 93 2f          mov   r25, r19
>   a2: 82 2f          mov   r24, r18
>   a4: 28 2f          mov   r18, r24
>       loop_until_bit_is_set (CLKPIN, CLK);
>   a6: c8 9b          sbis  0x19, 0  ; 25
>   a8: fe cf          rjmp  .-4         ; 0xa6
>   aa: 4f 5f          subi  r20, 0xFF   ; 255
>   ac: 48 30          cpi   r20, 0x08   ; 8
>   ae: 40 f3          brcs  .-48        ; 0x80
>    }
>
> On Tuesday 23 December 2003 00:58 am, J.C. Wren wrote:
> >     In this sample of code below, both i and data are defined as unsigned
> > char. For some reason, GCC is effectively promoting i and data to an int
> > for the operations.  The register tracking then fails to realize that it
> > already has r18 loaded at 0x98, and moves r24 back to r18, inspite of
> > having just moved r18 to r24.
> >
> >     By casting the (i << 1) to unsigned char, I can eliminate one
>
> instruction,
>
> > but no amount of casting can further reduce out the promotion to int side
> > effects.
> >
> >     --jc
> >
> >
> >       data |= (bit_is_set (DATAPIN, DATA) ? (i << 1) : 0);
> >   80: 33 27          eor   r19, r19
> >   82: c9 9b          sbis  0x19, 1  ; 25
> >   84: 07 c0          rjmp  .+14        ; 0x94
> >   86: 84 2f          mov   r24, r20
> >   88: 99 27          eor   r25, r25
> >   8a: 88 0f          add   r24, r24
> >   8c: 99 1f          adc   r25, r25
> >   8e: 82 2b          or r24, r18
> >   90: 93 2b          or r25, r19
> >   92: 02 c0          rjmp  .+4         ; 0x98
> >   94: 93 2f          mov   r25, r19
> >   96: 82 2f          mov   r24, r18
> >   98: 28 2f          mov   r18, r24
> >
> > By casting the (i << 1) to unsigned char, I can eliminate one instruction
> >
> >       data |= (bit_is_set (DATAPIN, DATA) ? (unsigned char) (i << 1) :
> > 0); 80: 33 27          eor   r19, r19
> >   82: c9 9b          sbis  0x19, 1  ; 25
> >   84: 06 c0          rjmp  .+12        ; 0x92
> >   86: 84 2f          mov   r24, r20
> >   88: 88 0f          add   r24, r24
> >   8a: 99 27          eor   r25, r25
> >   8c: 82 2b          or r24, r18
> >   8e: 93 2b          or r25, r19
> >   90: 02 c0          rjmp  .+4         ; 0x96
> >   92: 93 2f          mov   r25, r19
> >   94: 82 2f          mov   r24, r18
> >   96: 28 2f          mov   r18, r24
>
> _______________________________________________
> avr-gcc-list mailing list
> address@hidden
> http://www.avr1.org/mailman/listinfo/avr-gcc-list



reply via email to

[Prev in Thread] Current Thread [Next in Thread]