#132479 - BrainSlugs83 - Wed Jun 27, 2007 5:01 am
I defined a function to be in IWRAM that I want to run fast by declaring it like this: CODE_IN_IWRAM u16 GetSpriteW(u16 SIdx)
where CODE_IN_IWRAM is defined as:
#define CODE_IN_IWRAM __attribute__((section(".iwram"), long_call))
but I get this warning (and no output file!):
relocation truncated to fit: R_ARM_THM_CALL against symbol `GetSpriteW(unsigned short)' defined in .iwram section in ccfsD2Ij.o
how can this be fixed?
#132482 - Ant6n - Wed Jun 27, 2007 6:04 am
maybe your iwram is full? do you have tons of stuff there?
#132486 - BrainSlugs83 - Wed Jun 27, 2007 7:11 am
That was the first time I ever tried to put anything there, it was two functions that were both pretty small (<20 lines of C), and they were linker errors -- how would the linker know if I was putting things in IWRAM at runtime anyway? (but no, I put nothing else in IWRAM.)
#132488 - chishm - Wed Jun 27, 2007 7:27 am
Make sure you put IWRAM code in a separate source file to normal code.
_________________
http://chishm.drunkencoders.com
http://dldi.drunkencoders.com
#132489 - BrainSlugs83 - Wed Jun 27, 2007 7:40 am
what's the point of the section attribute if it needs to be in another file? If it's in another file can't you just pass different compiler args to make it arm code anyway?
I suppose it makes sense that you would need to compile it to ARM, and put it in IWRAM, as opposed to doing just one or the other... it's too bad there's not a simpler way to do it.
#132496 - Cearn - Wed Jun 27, 2007 9:01 am
BrainSlug83 wrote: |
-- how would the linker know if I was putting things in IWRAM at runtime anyway? (but no, I put nothing else in IWRAM.) |
All non-const global variables are put in IWRAM unless you takes steps against it. It may be fuller than you know.
BrainSlugs83 wrote: |
what's the point of the section attribute if it needs to be in another file? If it's in another file can't you just pass different compiler args to make it arm code anyway?
I suppose it makes sense that you would need to compile it to ARM, and put it in IWRAM, as opposed to doing just one or the other... it's too bad there's not a simpler way to do it. |
The attributes are still necessary for the declaration. The caller needs to know that it needs to use a long_call to reach it.
The long_call bit is the problem, by the way, not the .iwram attribute. There are two kinds of function calls, 'near' and 'far'. Near-calls can be done with a simple bl (branch with link) instruction. Far-calls are outside the offset range of bl, and have to be performed by getting the address of the function first and then using bx (branch with exchange). The trouble is that GCC assumes that all functions within a file are in the same section and will always use bl. This can be overcome by using the -mlong-calls compiler option, which makes all calls far-calls. IIRC, far-calls are implemented as a double-branch, so it will make function calling a little slower though.
Additionally, is the purpose of GetSpriteW is to get the sprite's width? If so, it's better to make it an inline function instead of an ARM/IWRAM function. The overhead of the call alone is probably greater than the body of the function; especially if it's used multiple times in one function.
Oh, and don't use u16 as local variable/parameter types. Use int/u32, unless you really want extra instructions for every data operation you do with them.
#132499 - BrainSlugs83 - Wed Jun 27, 2007 9:10 am
sounds nasty, I'm avoiding this one at all costs.
Quote: |
Additionally, is the purpose of GetSpriteW is to get the sprite's width? |
The purpose isn't important -- I just wanted to know how to put a function into IWRAM and chose that one -- and yes, that's what GetSpriteW does -- I'm replacing it with a const LUT eventually though.
You guys seem to be awefully sure that my IWRAM is full, does that message only show up when IWRAM is full, or could it mean something else? I'm pretty sure I'm using less than 2KB of global variables, and IWRAM is 32KB big, no?
#132506 - Chano Marrano - Wed Jun 27, 2007 10:31 am
Sometimes, when you call an IWRAM function from an EWRAM function, the "relocation truncated to fit" error appears. Move the EWRAM function to IWRAM and you should have no more problems.
#132511 - Cearn - Wed Jun 27, 2007 11:15 am
BrainSlugs83 wrote: |
sounds nasty, I'm avoiding this one at all costs. |
If you want to be able to call functions from IWRAM, you will need this one.
BrainSlugs83 wrote: |
Quote: | Additionally, is the purpose of GetSpriteW is to get the sprite's width? | The purpose isn't important -- I just wanted to know how to put a function into IWRAM and chose that one -- and yes, that's what GetSpriteW does -- I'm replacing it with a const LUT eventually though. |
Fair enough.
Code: |
//! Get object's sizes as a byte array
static inline const u8 *obj_get_size(OBJ_ATTR *obj)
{ return oam_sizes[obj->attr0>>14][obj->attr1>>14]; }
//! Get object's width
static inline int obj_get_width(OBJ_ATTR *obj)
{ return obj_get_size(obj)[0]; }
//! Gets object's height
static inline int obj_get_height(OBJ_ATTR *obj)
{ return obj_get_size(obj)[1]; }
const u8 oam_sizes[3][4][2]=
{
{ { 8, 8}, {16,16}, {32,32}, {64,64} },
{ {16, 8}, {32, 8}, {32,16}, {64,32} },
{ { 8,16}, { 8,32}, {16,32}, {32,64} },
};
|
:)
BrainSlugs83 wrote: |
You guys seem to be awfully sure that my IWRAM is full, does that message only show up when IWRAM is full, or could it mean something else? I'm pretty sure I'm using less than 2KB of global variables, and IWRAM is 32KB big, no? |
It's not full. But my point was that it's not empty either. The real issue is the long_call thing. The long_call attribute doesn't work for functions within the same file.
Code: |
// --- File foo.c --------------------------------
CODE_IN_IWRAM int ifunc()
{
return 42;
}
int rfuncA()
{
return ifunc();
}
// --- File bar.c --------------------------------
CODE_IN_IWRAM int ifunc();
int rfuncB()
{
return ifunc();
}
|
The call from rfuncA fails. The call from rfuncB works fine. The key is that calls between sections should not be in the same file.
#132581 - BrainSlugs83 - Wed Jun 27, 2007 10:50 pm
Thanks, it's starting to make sense now.