summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/bitops.nim12
1 files changed, 9 insertions, 3 deletions
diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim
index a518c25d2..d19c3d248 100644
--- a/lib/pure/bitops.nim
+++ b/lib/pure/bitops.nim
@@ -63,6 +63,12 @@ macro bitxor*[T: SomeInteger](x, y: T; z: varargs[T]): T =
 type BitsRange*[T] = range[0..sizeof(T)*8-1]
   ## A range with all bit positions for type `T`.
 
+template typeMasked[T: SomeInteger](x: T): T =
+  when defined(js):
+    x and ((0xffffffff_ffffffff'u shr (64 - sizeof(T) * 8)))
+  else:
+    x
+
 func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
   ## Returns an extracted (and shifted) slice of bits from `v`.
   runnableExamples:
@@ -73,7 +79,7 @@ func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1,
   let
     upmost = sizeof(T) * 8 - 1
     uv     = v.castToUnsigned
-  (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
+  ((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
 
 proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
   ## Mutates `v` into an extracted (and shifted) slice of bits from `v`.
@@ -85,7 +91,7 @@ proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1,
   let
     upmost = sizeof(T) * 8 - 1
     uv     = v.castToUnsigned
-  v = (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
+  v = ((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
 
 func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
   ## Creates a bitmask based on a slice of bits.
@@ -96,7 +102,7 @@ func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
   let
     upmost = sizeof(T) * 8 - 1
     bitmask = bitnot(0.T).castToUnsigned
-  (bitmask shl (upmost - slice.b + slice.a) shr (upmost - slice.b)).T
+  ((bitmask shl (upmost - slice.b + slice.a)).typeMasked shr (upmost - slice.b)).T
 
 proc masked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
   ## Returns `v`, with only the `1` bits from `mask` matching those of