gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > DevkitARM and long switch() statements

#24419 - rmy - Tue Aug 03, 2004 12:35 pm

I get an error message when I try to compile my project with devkitARM. "Error: invalid offset, value too big (0x00000412)" is produced in different files (by the assembler it seems). It seems to happen when using locally a declared array in a rather long function. And then "Error: branch out of range" when compiling long switch() statements.

My code (which is C++) compiles fine with devkitAdvance.

Anyone has a clue? Is there a trick to make switches long-branch?

#24424 - tepples - Tue Aug 03, 2004 4:33 pm

"0x00000412" looks like it's just barely over a binary order of magnitude threshold. Perhaps if you could compile that function with size optimizations (-Os rather than -O2 or -O3). Perhaps you just lucked out with DevKit Advance's compilation and got an 0x000003f4 or something.

To make switch statements long-branch, put them in separate functions, either outside the function with a big switch or (if you need to access lots of local variables and won't be moving to ARM ADS anytime soon) as GCC's nested functions.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#24439 - rmy - Tue Aug 03, 2004 8:02 pm

Thanks.

I am beginning to have a creeping feeling that Devkit Advance does not report this kind of error during compile. I have had to track down the cause of odd behaviour before, and found that removing locally declared char arrays have been solution. Maybe with DevikitARM I don't have to play guessing games any more.

Anyone knows what is happening, in technical terms? Am I overflowing the call stack for thumb code? Are local variables kept on the call stack, or does it have its own?

Also: I am curious about the optimising flags. To which link stages do they apply? If I compile my code with devkit advance and -O2, the code stops working. Using it when linking is no problem though.

#24443 - poslundc - Tue Aug 03, 2004 8:20 pm

rmy wrote:
Anyone knows what is happening, in technical terms? Am I overflowing the call stack for thumb code? Are local variables kept on the call stack, or does it have its own?


Local variables are on the stack, and while I don't think it's an overflow problem (overflow wouldn't generate an error; your program would just crash :P ), it may be a bug in GCC's implementation if your array is too large to be referenced in relation to the stack pointer or something.

As for the switch bug, it is probably attempting to jump to the correct position in the code using PC-relative arithmetic, and finding that the destination label is out of range to do so with an immediate value. Tepples' suggestion should cure the problem just fine.

Dan.

#24444 - Miked0801 - Tue Aug 03, 2004 8:22 pm

Switch can be either compiled as a table look up, load to r15 combo or a series of cmp, b(condition) statements. The compiler should be smart enough to handle choosing the correct method in terms of making it not crash.

A way around this (if your data is cardinal) is to create a table of function ptrs and directyl array access into them then jump to the functions. This cna make much, much cleaner looking code.

#24446 - sajiimori - Tue Aug 03, 2004 8:28 pm

Yay, data orientation! =)

#24473 - rmy - Wed Aug 04, 2004 9:32 am

Miked0801 wrote:
A way around this (if your data is cardinal) is to create a table of function ptrs and directyl array access into them then jump to the functions. This cna make much, much cleaner looking code.


I am doing this elsewhere, but for some purposes (like button press parsing) I don't find it handy. Moving the switch into their own functions and generally keeping methods small works, although inner methods seem to be unsupported for C++.

It is a bit frustrating to have to code around a compiler limitation (dare I say bug?) in this way. :-( It turns out the problem is not only for switches, but class constructors and breaking out of other conditional structures as well.

#24478 - rmy - Wed Aug 04, 2004 12:57 pm

By the way, I found this in the gcc bugzilla. Anyone know a devkit based on gcc 3.5?

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16626

#24551 - wintermute - Thu Aug 05, 2004 4:01 pm

rmy wrote:
By the way, I found this in the gcc bugzilla. Anyone know a devkit based on gcc 3.5?

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16626


that isn't your problem, unfortunately. the test case given there works fine on devkitARM.

Just as a matter of interest, try compiliing your code *without* the -mlong-calls switch. It's not actually necessary unless you're calling rom code from iwram and will result in a slight code bloat.

#24582 - rmy - Fri Aug 06, 2004 2:08 pm

Thanks for the input.

Seems like the -mlong-calls are the cause.

When removing it I don't get the errors any more, and after reorganizing a bit, it turns out I only need it when compiling the interrupt handler. It looks like the -mlong-calls makes the compiler expect that it can short-branch out of any conditional and any function (on early return). There is also problems with variables.

Also I found that I can now compile with -O2 after having added a volatile flag on the vsync register. Suddenly all my performance worries has been smashed to dust.