Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1374 from mathias-lang-sociomantic/bitswap-ulong
Browse files Browse the repository at this point in the history
Add core.bitopt.bitswap(ulong)
  • Loading branch information
MartinNowak committed Sep 6, 2015
2 parents 46fdff3 + 10821c6 commit 3e3426f
Showing 1 changed file with 72 additions and 0 deletions.
72 changes: 72 additions & 0 deletions src/core/bitop.d
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,75 @@ unittest
foreach(i; 0 .. 32)
assert(bitswap(1 << i) == 1 << 32 - i - 1);
}

/**
* Reverses the order of bits in a 64-bit integer.
*/
ulong bitswap ( ulong x ) pure @trusted
{
version (D_InlineAsm_X86_64)
{
asm pure nothrow @nogc { naked; }

version (Win64)
asm pure nothrow @nogc { mov RAX, RCX; }
else
asm pure nothrow @nogc { mov RAX, RDI; }

asm pure nothrow @nogc
{
// Author: Tiago Gasiba.
mov RDX, RAX;
shr RAX, 1;
mov RCX, 0x5555_5555_5555_5555L;
and RDX, RCX;
and RAX, RCX;
shl RDX, 1;
or RAX, RDX;

mov RDX, RAX;
shr RAX, 2;
mov RCX, 0x3333_3333_3333_3333L;
and RDX, RCX;
and RAX, RCX;
shl RDX, 2;
or RAX, RDX;

mov RDX, RAX;
shr RAX, 4;
mov RCX, 0x0f0f_0f0f_0f0f_0f0fL;
and RDX, RCX;
and RAX, RCX;
shl RDX, 4;
or RAX, RDX;
bswap RAX;
ret;
}
}
else
{
// swap odd and even bits
x = ((x >> 1) & 0x5555_5555_5555_5555L) | ((x & 0x5555_5555_5555_5555L) << 1);
// swap consecutive pairs
x = ((x >> 2) & 0x3333_3333_3333_3333L) | ((x & 0x3333_3333_3333_3333L) << 2);
// swap nibbles
x = ((x >> 4) & 0x0f0f_0f0f_0f0f_0f0fL) | ((x & 0x0f0f_0f0f_0f0f_0f0fL) << 4);
// swap bytes
x = ((x >> 8) & 0x00FF_00FF_00FF_00FFL) | ((x & 0x00FF_00FF_00FF_00FFL) << 8);
// swap shorts
x = ((x >> 16) & 0x0000_FFFF_0000_FFFFL) | ((x & 0x0000_FFFF_0000_FFFFL) << 16);
// swap ints
x = ( x >> 32 ) | ( x << 32);
return x;
}
}

unittest
{
assert (bitswap( 0b1000000000000000000000010000000000000000100000000000000000000001)
== 0b1000000000000000000000010000000000000000100000000000000000000001);
assert (bitswap( 0b1110000000000000000000010000000000000000100000000000000000000001)
== 0b1000000000000000000000010000000000000000100000000000000000000111);
foreach (i; 0 .. 64)
assert(bitswap(1UL << i) == 1UL << 64 - i - 1);
}

0 comments on commit 3e3426f

Please sign in to comment.