[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-libc-dev] Re: AVR GCC 4.1.1 and switch statements
[avr-libc-dev] Re: AVR GCC 4.1.1 and switch statements
Fri, 3 Nov 2006 23:22:30 +0100
I'm just back from vacation, so I've read this thread only right now. I've had
a brief look at the issue. I come to the conclusion that we are having two
issues to fix the warning bug.
1.) gcc generates code that refers to the jump table address as if it were a
code label address. I.e. in fact the label of the jump table does not contain
code but data. I.e. the data with the address of jump targets. Gcc presently
uses the gs() macro when accessing the switch table address while it should
make use of pm() instead.
2.) With the the presently generated assembly code of gcc, i.e. with gs() the
warning is justified, but only for the avr6 targets.
The basic issue is that gcc realizes some type of address arithmetic, address
arithmetic that is dangerous if two conditions are met. 1.) the address needs
to be a code label and 2.) the target needs to be a >128k device.
This is what the warning is about ...
Joerg Wunsch wrote on Freitag, 3. November 2006 19:01 :
> As Eric Weddington wrote:
> > I'm working on the RZ200 kit display board firmware and I was
> > getting some strange assembler warning messages (through it's
> > temporary file from GCC). It seems that AVR GCC doesn't like switch
> > statements that have a lot cases. I don't know the exact number
> > that is the cutoff point. And I think I saw someone else make this
> > comment too, either on AVR Freaks or on avr-gcc-list (or it could of
> > even been on the gcc list).
> I think on avr-gcc-list. I've been hoping Björn would eventually look
> at it... It's not a GCC 4.x issue, it's rather an issue with the
> linker stub stuff.
> It happens whenever a jump table is created. Björn added another
> operator for to the assembler, called "gs". This one is emitted as
> part of the jump table computation:
> subi r30,lo8(-(gs(.L258)))
> sbci r31,hi8(-(gs(.L258)))
The label .L256 most probably is an address refering to the beginning of a
jump table that resides in the .progmem.gcc_sw_table sections. Thus, this
label isn't in fact pointing to code but to progmem data.
> lsl r30
> rol r31
> lpm __tmp_reg__,Z+
> lpm r31,Z
> mov r30,__tmp_reg__
> /var/tmp//ccAYIFV3.s: Assembler messages:
> /var/tmp//ccAYIFV3.s:21: Warning: expression dangerous with linker stubs
> /var/tmp//ccAYIFV3.s:22: Warning: expression dangerous with linker stubs
> I think what the warning is going to tell is is that if the jump table
> would ever cross a "page" boundary (like a 128 KiB block boundary),
> funny things will happen.
No the reason for me for adding this warning was the following:
Imagine that somebody is generating or writing assembly code where depending
on some condition he whishes to jump not to some label, say my_startlabel or
to an address 10 instructions behind, i.e. (my_startlabel + 20) instead.
Assume that we are having a >128k target.
Straight forward method would be, that he takes the address of the first
label, loads it in a register, conditionally adds 10 and makes a relative
jump, i.e. ijmp.
What happens depends on where the destination function ends up. If
"my_startlabel" is below the 128k boundary, everything is fine.
If it is placed by the linker behind the 128k boundary, there is no way to
reach the destination address by use of a 16 bit pointer! The linker
recognizes this and adds a "jmp my_startlabel" instruction below the 128k
boundary and replaces the value of (my_startlabel) in instructions like
ldi r30,lo8(-(gs(my_startlabel)) and
by the address of the jump instruction. I.e. instead of loading the address of
the unreachable function itself, it loads the address of the jump
instruction. If one then does simply a
instruction everything works fine. The indirect jump first jumps with its 16
bits scope to the jump instruction below 128k and the jump instruction with
it's 23 bit scope will jump to the final target. The problem shows up when
jumping to the address "my_startlabel" + 20. In case that "my_startlabel" is
behind the 128k boundary, one would be doing calculations which yield as a
result some address shortly behind the jump stub! I.e. somewhere in the
nirvana. This is what the warning is about.
I.e. the message is: The assembler should disallow arithmetics with addresses
for code and this is what the warning is about.
> But I've got no idea about what the luser could do to avoid that
The first thing would be to make gas disable this warning for avrX with X < 6.
The next thing would be to make gcc generate code where this warning is no
longer generated, i.e. by using the pm() directive instead of the gs()
directive for the table jump stuff. This would be a bit more work and
possibly this is not easily feasible since we would need to clearly
distinguish pointers to code and pointers to data.
> OK, now that you bring this up, maybe it's best to just add Björn to
> the Cc list... Björn, please keep the uriah.heep.sax.de address in
> the reply so I might read it at home.
As I understand that this is not a blocking bug, I'd like to suggest to first
implement the small change in binutils myself. We maybe should discuss more
in detail on what to do with gcc. The easiest solution would be to disable
the casesi pattern for the >128k devices completely.
|[Prev in Thread]
||[Next in Thread]|
- [avr-libc-dev] Re: AVR GCC 4.1.1 and switch statements,
Björn Haase <=