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

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

[avr-gcc-list] cbr and negative numbers


From: Ruud Vlaming
Subject: [avr-gcc-list] cbr and negative numbers
Date: Wed, 10 Sep 2008 15:57:15 +0200
User-agent: KMail/1.9.1

Suppose you compile the (nonsense) code below under
'standard' settings (see below for my settings, but is does 
not really matter for now) Then there is no problem. 
However, if you activate the 8 bit integer option -mint8 
you get an error:
  code_Test.s:75: Error: number must be less than 256

  void TestCBR(void) __attribute__ ((naked, used));
  void TestCBR(void)
  { asm volatile ( 
     "cbr r31, 0xC0         \n\t" /* This value passes          */
     "cbr r31,%[_A_]        \n\t" /* This value passes          */
     "sbr r31,%[_B_]        \n\t" /* This value passes          */
     "cbr r31,%[_B_]        \n\t" /* This may generate an error */
     "ret                   \n\t" 
     "" ::
     [_A_] "i" (0x70),
     [_B_] "i" (0xC0)); }

Now, this has nothing to do with lib c (for which mint8 is
discurraged), but with the part that translates the assembler
into opcodes. This is why:

without -mint8 you get
  TestCBR:
  .LFB11:
  .LM7:
  /* prologue: frame size=0 */
  /* prologue: naked */
  /* prologue end (size=0) */
  /* #APP */
          cbr r31, 0xC0
          cbr r31,112
          sbr r31,192
          cbr r31,192
          ret

with -mint8 you get
  TestCBR:
  .LFB11:
  .LM7:
  /* prologue: frame size=0 */
  /* prologue: naked */
  /* prologue end (size=0) */
  /* #APP */
          cbr r31, 0xC0
          cbr r31,112
          sbr r31,-64
          cbr r31,-64
          ret

The negative numbers are ofcourse a direct consequence of the
-mint8 option where -64 equals 192. For most instructions
this is not a problem since -64 can be represented as follows
  8 bit: 0xC0
 16 bit: 0xFFC0
 32 bit: 0xFFFFFFC0
Whatever you take, the last 2 bytes will always be C0.

But the AVR CBR instruction must perform a calculation first
before the opcode can be produced. (CBR is transformed into
an ANDI) Thats why sbr r31,-64 works whereas cbr r31,-64 does
not.

I don't know if this might be called a bug, but it is annoying.
Of course, it is not so difficult to circumvent this problem, but
if you have parametarized assembler (like i have) you cannot be
sure if the problem might occur at some later moment. Or you must
eliminate the CBR instructions all together. It looks like the
CBR is the only instruction suffering this problem.

I think the best solution would be to prohibit the compiler from
emitting negative numbers as arguments, independant if the setting
is -mint8 or not. Positive numbers (or even better: hexadecimal)
would be a lot clearer.

Ruud.


(*) my settings where:
avr-gcc -save-temps -mmcu=attiny861 -Wall -Wno-main -Winline 
  -Wundef -gdwarf-2 -Os -funsigned-char -fomit-frame-pointer 
  -fpack-struct -fshort-enums

Btw, i know that -mint8 is an option that not everybody loves,
and some may even go that far as to say it should be prohibited.
In any case, using this option (and a little carefull programming)
can reduce your code by 8%!! I think such an option is an absolute
necessity for anyone working low level. It would of course be better
to have an option which would honnor the bitlengths of the predefined
integers, and still be suppressing 16bit promotion of operators.
Until that day we have to stick with -mint8.




reply via email to

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