I have spent a bit of time and have basically arrived at this function which is used in libgcc. So, basically, if someone does not want to link with libgcc for whatever reason. This code below is basically the optimized version of the subtraction loop which is basically what someone said in that post from a while back (they recommend to do). The code was actually not broken it is just that I never sat down and looked at the problem further because I was doing little divisions likely and was just wanting to give an example of how to implement the functions.
If you specify an architecture/machine to GCC and the ARM mode supports native division then the compiler should emit the sequence and not try to call the functions below. If you are in THUMB mode and you do a division then the compiler should emit the instructions if supported. The only other case you might worry about would be floating point instructions which (someone correct me if I am wrong) should be just as simple as actually doing them in C/C++ if your target machine/architecture supports them else it might try to call another function for software emulation. So linking to LIBGCC would really make sense because it should provide all those functions (the one below basically copied from LIBGCC).
I do not think LIBGCC will help the compiler in deciding to use FP operation for a INT operation if it was faster. I guess you just have to macro that up in your code. Not sure if you would even want too because I have not dug down into it.
But, if someone just wants to get their kernel, OS, system software, whatever up and running and does not want to link to LIBGCC for whatever reason then I think it is kind of cool to have this where it can be found and used.
Code: Select all
unsigned long udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
unsigned long bit = 1;
unsigned long res = 0;
while (den < num && bit && !(den & (1L<<31)))
{
den <<=1;
bit <<=1;
}
while (bit)
{
if (num >= den)
{
num -= den;
res |= bit;
}
bit >>=1;
den >>=1;
}
if (modwanted)
return num;
return res;
}
unsigned int __aeabi_uidiv(unsigned int num, unsigned int den) {
return udivmodsi4(num, den, 0);
}
int __aeabi_idiv(int num, int den) {
return udivmodsi4(num, den, 0);
}
Here is the old (said by some to be broken) code. I have to say technically it works, ROFL. It just is not the best way to do it.. Just can not believe someone just yanked it out with out putting in the better function above... *shugs*..
Code: Select all
CODE REMOVED (COMBUSTER EXPLAINED BELOW)
What do you guys think? Any mistakes? LOL