* lib.c - Library Functions
*/
#include <acess.h>
+#include "../helpers.h"
+
+// === IMPORTS ===
+extern void __memcpy_align4(void *_dest, const void *_src, size_t _length);
+extern void __memcpy_byte(void *_dest, const void *_src, size_t _length);
+extern Uint32 __divmod32_asm(Uint32 Num, Uint32 Den, Uint32 *Rem);
// === PROTOTYPES ===
Uint64 __divmod64(Uint64 Num, Uint64 Den, Uint64 *Rem);
// === CODE ===
void *memcpy(void *_dest, const void *_src, size_t _length)
{
- Uint32 *dst;
- const Uint32 *src;
Uint8 *dst8 = _dest;
const Uint8 *src8 = _src;
+ if( ((tVAddr)_dest & 3) == 0 && ((tVAddr)_src & 3) == 0 )
+ {
+ __memcpy_align4(_dest, _src, _length);
+ return _dest;
+ }
+
// Handle small copies / Non-aligned
if( _length < 4 || ((tVAddr)_dest & 3) != ((tVAddr)_src & 3) )
{
- for( ; _length--; dst8++,src8++ )
- *dst8 = *src8;
+ __memcpy_byte(_dest, _src, _length);
return _dest;
}
// Force alignment
- while( (tVAddr)dst8 & 3 ) *dst8 ++ = *src8++;
- dst = (void *)dst8; src = (void *)src8;
-
- // DWORD copies
- for( ; _length > 3; _length -= 4)
- *dst++ = *src++;
+ while( (tVAddr)dst8 & 3 ) *dst8 ++ = *src8++, _length --;
- // Trailing bytes
- dst8 = (void*)dst; src8 = (void*)src;
- for( ; _length; _length -- )
- *dst8 ++ = *src8 ++;
+ __memcpy_align4(dst8, src8, _length);
return _dest;
}
_value = (Uint8)_value;
- // Handle small copies / Non-aligned
+ // Handle small copies
if( _length < 4 )
{
for( ; _length--; dst8++ )
return _dest;
}
-// Divide
-// - Find what power of two times Den is > Num
-// - Iterate down in bit significance
-// > If the `N` value is greater than `D`, we can set this bit
-#define DEF_DIVMOD(s) Uint##s __divmod##s(Uint##s N, Uint##s D, Uint##s*Rem){\
- Uint##s ret=0,add=1;\
- while(N>=D&&add) {D<<=1;add<<=1;}\
- while(add>1){\
- add>>=1;D>>=1;\
- if(N>=D){ret+=add;N-=D;}\
- }\
- if(Rem)*Rem = N;\
- return ret;\
-}
-
DEF_DIVMOD(64)
DEF_DIVMOD(32)
-
Uint64 DivMod64U(Uint64 Num, Uint64 Den, Uint64 *Rem)
{
Uint64 ret;
if(Den == 0) return 0; // TODO: #div0
+ if(Num < Den) {
+ if(Rem) *Rem = Num;
+ return 0;
+ }
if(Num == 0) {
if(Rem) *Rem = 0;
return 0;
if(Rem) *Rem = Num & 0xFFF;
return Num >> 12;
}
+
+ if( !(Den >> 32) && !(Num >> 32) ) {
+ if(Rem) *Rem = 0; // Clear high bits
+ return __divmod32_asm(Num, Den, (Uint32*)Rem);
+ }
ret = __divmod64(Num, Den, Rem);
return ret;
return ret;
}
-#define _divide_s_32(Num, Den, rem) __asm__ __volatile__ ( \
- "mov %0, #0\n" \
- " adds %1, %1, %1\n" \
- " .rept 32\n" \
- " adcs %0, %2, %0, lsl #1\n" \
- " subcc %0, %0, %3\n" \
- " adcs %1, %1, %1\n" \
- " .endr\n" \
- : "=r" (rem), "=r" (Num) \
- : "r" (Den) \
- : "cc" \
- )
Uint32 __udivsi3(Uint32 Num, Uint32 Den)
{
- return __divmod32(Num, Den, NULL);
+ return __divmod32_asm(Num, Den, NULL);
}
Uint32 __umodsi3(Uint32 Num, Uint32 Den)
{
Uint32 rem;
- __divmod32(Num, Den, &rem);
+ __divmod32_asm(Num, Den, &rem);
return rem;
}
-Sint32 __divsi3(Sint32 Num, Sint32 Den)
+static inline Sint32 DivMod32S(Sint32 Num, Sint32 Den, Sint32 *Rem)
{
- if( (Num < 0) && (Den < 0) )
- return __udivsi3(-Num, -Den);
- else if( Num < 0 )
- return __udivsi3(-Num, Den);
- else if( Den < 0 )
- return __udivsi3(Den, -Den);
+ Sint32 ret = 1;
+ if( Num < 0 ) {
+ ret = -ret;
+ Num = -Num;
+ }
+ if( Den < 0 ) {
+ ret = -ret;
+ Den = -Den;
+ }
+ if(ret < 0)
+ ret = -__divmod32(Num, Den, (Uint32*)Rem);
else
- return __udivsi3(Den, Den);
+ ret = __divmod32(Num, Den, (Uint32*)Rem);
+ return ret;
+}
+
+Sint32 __divsi3(Sint32 Num, Sint32 Den)
+{
+ return DivMod32S(Num, Den, NULL);
}
Sint32 __modsi3(Sint32 Num, Sint32 Den)
{
- if( (Num < 0) && (Den < 0) )
- return __umodsi3(-Num, -Den);
- else if( Num < 0 )
- return __umodsi3(-Num, Den);
- else if( Den < 0 )
- return __umodsi3(Den, -Den);
- else
- return __umodsi3(Den, Den);
+ Sint32 rem;
+ DivMod32S(Num, Den, &rem);
+ return rem;
}