Skip to contentSkip to conversation

lib.c: added unsigned 64bits division for 32 bits arch

PATCH Superseded Paul Semel 2 participants 5 messages Apr 7, 2018 x86

lore
Share & tools
lore

Paul Semel

author
#0 lore raw

PATCH 1/1 lib.c: added unsigned 64bits division for 32 bits arch

this is a simple implementation of unsigned 64bits divisions for 32 bits archs.

---
 common/lib.c      | 21 +++++++++++++++++++++
 include/xtf/lib.h |  4 ++++
 2 files changed, 25 insertions(+)
common/lib.c +21 -0
index acf4da1..36d5600 100644
@@ -68,6 +68,27 @@ int xtf_get_domid(void)
     return domid;
 }
 
+#if defined(__i386__)
+uint32_t __udiv64_32(uint64_t *n, uint32_t base)
+{
+    uint32_t rem;
+    uint32_t high = ((uint32_t *)n)[1];
+
+    ((uint32_t *)n)[1] = 0;
+    if (high >= base) {
+        ((uint32_t *)n)[1] = high / base;
+        high %= base;
+    }
+
+    __asm__("divl %2"
+            : "=a"(((uint32_t*)n)[0]), "=d"(rem)
+            : "rm"(base), "0"(((uint32_t*)n)[0]), "1"(high));
+
+    return rem;
+}
+
+#endif
+
 /*
  * Local variables:
  * mode: C
include/xtf/lib.h +4 -0
index abf8f25..4479286 100644
@@ -101,6 +101,10 @@ int xtf_probe_sysctl_interface_version(void);
  */
 int xtf_get_domid(void);
 
+#if defined(__i386__)
+uint32_t __udiv64_32(uint64_t *n, uint32_t base);
+#endif
+
 #endif /* XTF_LIB_H */
 
 /*
Signature · 7 lines
2.16.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#1 lore raw

common/lib.c

Quoted 13 lines · Paul Semel

this is a simple implementation of unsigned 64bits divisions for 32 bits archs.

---
 common/lib.c      | 21 +++++++++++++++++++++
 include/xtf/lib.h |  4 ++++
 2 files changed, 25 insertions(+)
common/lib.c +0 -0
index acf4da1..36d5600 100644

Thanks.  While x86 is the only supported arch, I am trying keep the code sensibly split between common and arch specific, so when Julien finally gets around to adding ARM support, it won't require major refactoring. (I'm sure there will be some, but I'm trying to keep it to a minimum.)

Please introduce a new arch/x86/lib.c for this function.  See arch/x86/decode.c as a decent example of the top and tail metadata.

common/lib.c int xtf_get_domid(void) · line 73

Quoted 7 lines
common/lib.c +3 -0
@@ -68,6 +68,27 @@ int xtf_get_domid(void)
     return domid;
 }
 
+#if defined(__i386__)
+uint32_t __udiv64_32(uint64_t *n, uint32_t base)
+{

A lot of this function would be clearer to read if you had

uint32_t *n_32 = (uint32_t *)n;

at which point, all other casts can be dropped.

common/lib.c int xtf_get_domid(void) · line 78

Quoted 5 lines
common/lib.c +5 -0
+    uint32_t rem;
+    uint32_t high = ((uint32_t *)n)[1];
+
+    ((uint32_t *)n)[1] = 0;
+    if (high >= base) {

XTF uses hypervisor style, so this should be

if ( high >= base )
{

common/lib.c int xtf_get_domid(void) · line 85

Quoted 7 lines
common/lib.c +7 -0
+        ((uint32_t *)n)[1] = high / base;
+        high %= base;
+    }
+
+    __asm__("divl %2"
+            : "=a"(((uint32_t*)n)[0]), "=d"(rem)
+            : "rm"(base), "0"(((uint32_t*)n)[0]), "1"(high));

You don't need the underscore variant of asm in C files at all, and because XTF is a freestanding project with no libraries, I don't bother with them in header files either.

For code clarity, please use named asm parameters, rather than positional ones, so something like:

asm ("div %[base]"
     : "=a" (n_32[0]), "=d" (rem)
     : [base] "rm" (base), "a" (n_32[0]), "d" (high));

Quoted 14 lines
common/lib.c +6 -0
+
+    return rem;
+}
+
+#endif
+
 /*
  * Local variables:
  * mode: C
include/xtf/lib.h +0 -0
index abf8f25..4479286 100644

include/xtf/lib.h int xtf_probe_sysctl_interface_version(void); · line 106

Quoted 6 lines
include/xtf/lib.h +3 -0
@@ -101,6 +101,10 @@ int xtf_probe_sysctl_interface_version(void);
  */
 int xtf_get_domid(void);
 
+#if defined(__i386__)
+uint32_t __udiv64_32(uint64_t *n, uint32_t base);
+#endif

Please move to arch/x86/include/arch/lib.h (to match the change in C file), add a doxygen comment, and drop the guards.

Dropping the guards is a trick to make it far easier to write common code which is compiler visible and doesn't bitrot as easily, and does fairly well at spotting unsigned long vs uint32/64 mismatches.  Your references to this function need to be inside an "if ( IS_DEFINED(CONFIG_32BIT) )" to allow the 64bit builds to link, but the end result is easier to read.

~Andrew

_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel

author
#2 lore raw

PATCH v2 1/1 lib.c: added unsigned 64bits division for 32 bits arch

this is a simple implementation of unsigned 64bits divisions for 32 bits archs.

---
 arch/x86/include/arch/lib.h |  2 ++
 arch/x86/lib.c              | 37 +++++++++++++++++++++++++++++++++++++
 build/files.mk              |  1 +
 3 files changed, 40 insertions(+)
 create mode 100644 arch/x86/lib.c
arch/x86/include/arch/lib.h +2 -0
index 0045902..e077b12 100644
@@ -374,6 +374,8 @@ static inline void write_xcr0(uint64_t xcr0)
     xsetbv(0, xcr0);
 }
 
+uint32_t __udiv64_32(uint64_t *n, uint32_t base);
+
 #endif /* XTF_X86_LIB_H */
 
 /*
arch/x86/lib.c new file +37 -0
new file mode 100644
index 0000000..46a5353
@@ -0,0 +1,37 @@
+/**
+ * @file arch/x86/decode.c
+ *
+ * Helper routines for decoding x86 architectural state.
+ */
+#include <xtf/lib.h>
+#include <xtf/libc.h>
+
+uint32_t __udiv64_32(uint64_t *n, uint32_t base)
+{
+    uint32_t rem;
+    uint32_t *n_32 = (uint32_t *)n;
+    uint32_t high = n_32[1];
+
+    n_32[1] = 0;
+    if ( high >= base )
+    {
+        n_32[1] = high / base;
+        high %= base;
+    }
+
+    asm("divl %[base]"
+            : "=a" (n_32[0]), "=d" (rem)
+            : [base] "rm" (base), "0" (n_32[0]), "1" (high));
+
+    return rem;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
build/files.mk +1 -0
index 46b42d6..284ce6e 100644
@@ -18,6 +18,7 @@ obj-perarch += $(ROOT)/common/setup.o
 obj-perarch += $(ROOT)/common/xenbus.o
 
 obj-perenv += $(ROOT)/arch/x86/decode.o
+obj-perenv += $(ROOT)/arch/x86/lib.o
 obj-perenv += $(ROOT)/arch/x86/desc.o
 obj-perenv += $(ROOT)/arch/x86/extable.o
 obj-perenv += $(ROOT)/arch/x86/grant_table.o
Signature · 7 lines
2.16.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
author
#4 lore raw
Quoted 4 lines · Andrew Cooper
Quoted 3 lines · Paul Semel

this is a simple implementation of unsigned 64bits divisions for 32 bits archs.

Quoted 9 lines
Quoted 1 line

I'm terribly sorry not to have spotted this before, but the code actually looks rather familiar.

Grep for divmod64 in the source.

~Andrew

No problem, I am really sorry too not to have spotted this before !

Signature · 6 lines
Paul

_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel