summaryrefslogtreecommitdiff
path: root/libraries/ghc-prim
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ghc-prim')
-rw-r--r--libraries/ghc-prim/cbits/pdep.c48
-rw-r--r--libraries/ghc-prim/cbits/pext.c44
-rw-r--r--libraries/ghc-prim/ghc-prim.cabal2
3 files changed, 94 insertions, 0 deletions
diff --git a/libraries/ghc-prim/cbits/pdep.c b/libraries/ghc-prim/cbits/pdep.c
new file mode 100644
index 0000000000..8435ffe186
--- /dev/null
+++ b/libraries/ghc-prim/cbits/pdep.c
@@ -0,0 +1,48 @@
+#include "Rts.h"
+#include "MachDeps.h"
+
+extern StgWord64 hs_pdep64(StgWord64 src, StgWord64 mask);
+
+StgWord64
+hs_pdep64(StgWord64 src, StgWord64 mask)
+{
+ uint64_t result = 0;
+
+ while (1) {
+ // Mask out all but the lowest bit
+ const uint64_t lowest = (-mask & mask);
+
+ if (lowest == 0) {
+ break;
+ }
+
+ const uint64_t lsb = (uint64_t)((int64_t)(src << 63) >> 63);
+
+ result |= lsb & lowest;
+ mask &= ~lowest;
+ src >>= 1;
+ }
+
+ return result;
+}
+
+extern StgWord hs_pdep32(StgWord src, StgWord mask);
+StgWord
+hs_pdep32(StgWord src, StgWord mask)
+{
+ return hs_pdep64(src, mask);
+}
+
+extern StgWord hs_pdep16(StgWord src, StgWord mask);
+StgWord
+hs_pdep16(StgWord src, StgWord mask)
+{
+ return hs_pdep64(src, mask);
+}
+
+extern StgWord hs_pdep8(StgWord src, StgWord mask);
+StgWord
+hs_pdep8(StgWord src, StgWord mask)
+{
+ return hs_pdep64(src, mask);
+}
diff --git a/libraries/ghc-prim/cbits/pext.c b/libraries/ghc-prim/cbits/pext.c
new file mode 100644
index 0000000000..fe960b1342
--- /dev/null
+++ b/libraries/ghc-prim/cbits/pext.c
@@ -0,0 +1,44 @@
+#include "Rts.h"
+#include "MachDeps.h"
+
+extern StgWord64 hs_pext64(StgWord64 src, StgWord64 mask);
+
+StgWord64
+hs_pext64(StgWord64 src, StgWord64 mask)
+{
+ uint64_t result = 0;
+ int offset = 0;
+
+ for (int bit = 0; bit != sizeof(uint64_t) * 8; ++bit) {
+ const uint64_t src_bit = (src >> bit) & 1;
+ const uint64_t mask_bit = (mask >> bit) & 1;
+
+ if (mask_bit) {
+ result |= (uint64_t)(src_bit) << offset;
+ ++offset;
+ }
+ }
+
+ return result;
+}
+
+extern StgWord hs_pext32(StgWord src, StgWord mask);
+StgWord
+hs_pext32(StgWord src, StgWord mask)
+{
+ return hs_pext64(src, mask);
+}
+
+extern StgWord hs_pext16(StgWord src, StgWord mask);
+StgWord
+hs_pext16(StgWord src, StgWord mask)
+{
+ return hs_pext64(src, mask);
+}
+
+extern StgWord hs_pext8(StgWord src, StgWord mask);
+StgWord
+hs_pext8(StgWord src, StgWord mask)
+{
+ return hs_pext64(src, mask);
+}
diff --git a/libraries/ghc-prim/ghc-prim.cabal b/libraries/ghc-prim/ghc-prim.cabal
index e99686a10b..9b8c1ac196 100644
--- a/libraries/ghc-prim/ghc-prim.cabal
+++ b/libraries/ghc-prim/ghc-prim.cabal
@@ -73,6 +73,8 @@ Library
cbits/ctz.c
cbits/debug.c
cbits/longlong.c
+ cbits/pdep.c
+ cbits/pext.c
cbits/popcnt.c
cbits/word2float.c