How to work around limits?

What can I do to work around the platform limits I'm running into?

The first clue that your program has grown large enough to hit a platform limit is usually a compiler or linker error. One you might see is "16-bit code reference to foo() is out of range". Another is "Signed .word overflow; switch may be too large".

These errors mean that your program has grown too large, so that the linker couldn't generate a short 16-bit relative jump to reach one of your functions. In other words, one of your function calls is more than 32 KB away from the called function. This limit and others is discussed elsewhere in the FAQ (PlatformLimits).

There are several things you can do about this:

 

  • Reorder your modules in the link command. The idea is to move the module containing the called function closer to the caller's module. This is eventually futile, as you will inevitably get to a point that no rearrangement will satisfy the linker. It's also fundamentally a trial-and-error process, which can get tedious.

 

  • Use "relay functions". You could have a dedicated module in the middle of the link order that contains functions that call other functions. This method quickly hits a wall because the HotSync protocol limits individual resources to 64 KB; each of your program's code segments is stored in a single resource in the PRC file. (See below for info on multi-segmenting.)

 

  • Move some of the code out into a shared library. Since shared library calls don't use 16-bit relative jumps, you avoid the problem altogether. The first problem is that when you move one function into the library, you usually end up moving all functions that it depends on into the library as well. (The alternative is to pass the library function pointers to let it call back into your program.) The second problem is that a shared library can't have its own global data, so you usually end up having to pass around pointers to these global variables so that the shared library can access them. And the third problem is that function calls within the library are also subject to the 32 KB jump limit, so if it gets too big, you're back in the same tarpit that this question addresses. (GCC how-to, CodeWarrior how-to)

 

  • Move some of the code out into a GLib shared library. These are different than the SysLib? style of shared library. The same problems above apply to this style of library, except that it is much easier to do and you can access global data in the library (but not share it with the calling application). (GCC how-to)

 

  • Use multiple code resources (also known as multi-segmenting). This is the easiest method, but it has costs. Basically, it's a way of telling the linker to use "long jumps" between certain groups of modules. This is useful if you have your code partitioned into largely independent units, so that control only moves between units rarely. This will minimize the number of long jumps that the compiler has to generate. Long jumps take more processor time and code space than the default 16-bit relative jumps. (CodeWarrior how-to, GCC how-to.)

 

  • Change code generation models. The CodeWarrior tools can generate code using the small, smart, and large models, set in the 68K Processor preference panel. Small is preferred, but it doesn't allow jumps in the same resource that exceed 32K, meaning code near the front of the segment can't reach code at the end of the segment. The large and smart models use a longer code sequence to do a jump, allowing a longer reach, but the jumps execute slower and take more room in your program. See http://www.palmoswerks.com/stories/storyReader$4 for more details.

 

  • Use Expanded Mode. If you get errors in a CodeWarrior application about your "near data exceeding 64K" and you are using C++ features like virtual functions or exception handling, using Expanded Mode allows the compiler to setup a second data section for this data referenced from the A4 register. Details are in the white paper at http://www.metrowerks.com/MW/download/request.asp?product=PALMEXMODE

There's a similar article in Palm's Developer Knowledge Base.

Today: Sep 10, 2010