Hello, 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__ > ijmp > > /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 ldi r31,hi8(-(gs(my_startlabel)) 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 ijmp 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 > warning. 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. Bjoern. _______________________________________________ AVR-libc-dev mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/avr-libc-dev
