summaryrefslogtreecommitdiffstats
path: root/src/libgcc/__udivmoddi4.c
diff options
context:
space:
mode:
authorMichael Brown2007-07-30 03:37:42 +0200
committerMichael Brown2007-07-30 03:43:43 +0200
commit4ce8d61a5cb8a0e3f68bff8400ba2b8246c9a58f (patch)
tree807be055e6f6edd1c8f85cf6c17635251f0c276a /src/libgcc/__udivmoddi4.c
parentGCC's optimiser seems to screw up if this is left static... (diff)
downloadipxe-4ce8d61a5cb8a0e3f68bff8400ba2b8246c9a58f.tar.gz
ipxe-4ce8d61a5cb8a0e3f68bff8400ba2b8246c9a58f.tar.xz
ipxe-4ce8d61a5cb8a0e3f68bff8400ba2b8246c9a58f.zip
Import various libgcc functions from syslinux.
Experimentation reveals that gcc ignores -mrtd for the implicit arithmetic functions (e.g. __udivdi3), but not for the implicit memcpy() and memset() functions. Mark the implicit arithmetic functions with __attribute__((cdecl)) to compensate for this. (Note: we cannot mark with with __cdecl, because we define __cdecl to incorporate regparm(0) as well.)
Diffstat (limited to 'src/libgcc/__udivmoddi4.c')
-rw-r--r--src/libgcc/__udivmoddi4.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/libgcc/__udivmoddi4.c b/src/libgcc/__udivmoddi4.c
new file mode 100644
index 00000000..59966edb
--- /dev/null
+++ b/src/libgcc/__udivmoddi4.c
@@ -0,0 +1,32 @@
+#include "libgcc.h"
+
+LIBGCC uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p)
+{
+ uint64_t quot = 0, qbit = 1;
+
+ if ( den == 0 ) {
+ return 1/((unsigned)den); /* Intentional divide by zero, without
+ triggering a compiler warning which
+ would abort the build */
+ }
+
+ /* Left-justify denominator and count shift */
+ while ( (int64_t)den >= 0 ) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while ( qbit ) {
+ if ( den <= num ) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if ( rem_p )
+ *rem_p = num;
+
+ return quot;
+}