#1451 - draigan - Sun Jan 19, 2003 12:35 am
I'm trying to do a division in some of my code (I'm simply using the division operator). If I put the division in my 'normal' code, it compiles and links fine. But if I put the division inside code that's inside IWRam, then I get this error:
test.o(.iwram+0x80): undefined reference to '__divsi3'
So a couple of questions:
1) How to make it so that it recognizes the divide in iwram
2) How to do a bios divide and call it from iwram
Thanks.
#1592 - draigan - Mon Jan 20, 2003 4:37 pm
anyone?
#1595 - Splam - Mon Jan 20, 2003 5:10 pm
Not sure about this one, I've never used / in C whilst coding GBA stuff, it's just toooo slow.
Try this..
Code: |
void FastIntDivide (s32 Numer, s32 Denom, s32 *Result, s32 *Remainder)
{
asm volatile
(
" mov r0,%2 \n"
" mov r1,%3 \n"
" swi 6 \n" //NOTE!!!!! Put 6 here for Thumb C Compiler mode.
" ldr r2,%0 \n" // Put 0x60000 there for ARM C Compiler mode.
" str r0,[r2] \n"
" ldr r2,%1 \n"
" str r1,[r2] \n"
: "=m" (Result), "=m" (Remainder) // Outputs
: "r" (Numer), "r" (Denom) // Inputs
: "r0","r1","r2","r3" // Regs crushed & smushed
);
}
|
Found it on a site somewhere (google is a good thing btw hehe), not sure if it works because I've never used it, all my "fast" code is in asm anyway. Note though the swi call and the difference between arm and thumb mode calling.
#1599 - Vortex - Mon Jan 20, 2003 5:21 pm
According to http://www.devrs.com/gba/files/gbadevfaqs.php#IncLibgcc
Quote: |
I get an "undefined reference" to one of these: __divsi3,__modsi3,__udivsi3,__umodsi3. Why?
The library libgcc.a is either not getting properly linked with your project or it is an incorrect version.
|
#1605 - tepples - Mon Jan 20, 2003 6:21 pm
Here's the fastest divide code on the GBA. It's potentially faster than the inline assembly fragment above because it doesn't have to put values in memory to get around GCC's lack of support for declaring inline asm registers. Put it in a file with extension .s
Code: |
@ int dv(int num, int den)
@ Divide two signed integers.
.THUMB
.THUMB_FUNC
.ALIGN
.GLOBL dv
dv:
cmp r1, #0
beq 0f
swi 6
bx lr
0:
ldr r0, =0x7fffffff
bx lr
|
Then put the following in your C program's header file:
int dv(int num, int den);
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#1627 - Splam - Mon Jan 20, 2003 8:47 pm
Personally I'd take out the div by zero check, if you're stupid enough to send the wrong values to it then you deserve a crash ;)
#1632 - ampz - Mon Jan 20, 2003 9:08 pm
Many divisions can be substituted by a multiplication and a bitshift.
#1634 - tepples - Mon Jan 20, 2003 9:24 pm
Splam wrote: |
Personally I'd take out the div by zero check, if you're stupid enough to send the wrong values to it then you deserve a crash ;) |
I put in the 1/0=Inf rule from projective geometry because when I used this function in the projection for my game's floor, it divided by zero whenever the camera tilted high enough to put the horizon on screen. Of course, it'd be easy to take it out.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#1747 - krozen - Wed Jan 22, 2003 2:53 pm
Hello,
I was just wondering how you would use that fast division within your C code. I've tried following an example I seen, and I cant seem to do it. I also tried putting it in a .s fil, but cannot include it properly. Somebody help me!!!!
Thank you
#1749 - col - Wed Jan 22, 2003 3:53 pm
Does anyone actually know how fast the bios divide really is - its all very well finding the quickest method to call it, but if it's not a fast algorithm whats the point?
So roughly how many cycles for the worst case? (excluding calling overhead)
cheers
col.
#1761 - ampz - Wed Jan 22, 2003 5:34 pm
To start with, it's stored in zero waitstate ROM...
#1765 - col - Wed Jan 22, 2003 6:55 pm
ampz wrote: |
To start with, it's stored in zero waitstate ROM... |
So You would put your custom divide code into iwram along with any other cpu intensive math functions...
Surely someone knows what the bios algorithm is?
cheers,
col
#1767 - Rich - Wed Jan 22, 2003 7:57 pm
Not sure what the copyright situation would be with simply posting the Bios divide code verbatim, but it's very easy to use the BatGBA emulator and trace through it :)
From my tests, the Bios routine, although substantially quicker than the C library routines, isn't that fast. Even when I took the code and relocated it in IWRAM, it's still slower than the code here http://www.peter-teichmann.de/ahinte.html, which is linked to on GameBoy Advance Dev'rs.
The code on Peters site also has some room for speedup :)
Rich.
#1786 - slapout - Thu Jan 23, 2003 3:35 am
The problem with division (in general) is that it generates remainders. Taking them into account is very cpu intensive. One of the things you can do is use shifting to divide by powers of 2. Also remember that division is just subtracting a number several times. Subtracting several time my be quicker than dividing.
I'm not an expert, that's just what I've read. And I'm not sure how well it translates to the GBA as I'm just a newbie to GBA programming.
#2093 - Maddox - Wed Jan 29, 2003 6:11 am
In the general case division by repeated subtraction is not a good idea. Consider:
Do you know how many subtractions that equals? Lots!
Next, remainders themselves are usually a by-product of the division algorithm itself. They are not intrinsically expensive to "take them into account" You absolutely can write a signed 32-bit/32-bit divide routing in IWRAM ARM code for ~100 cycles. (Don't know if that stacks up very well...)
_________________
You probably suck. I hope you're is not a game programmer.