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

Commit

Permalink
Add core.bitopt.bitswap(ulong)
Browse files Browse the repository at this point in the history
The original (D1) core.bitop module had both the 32 and 64 bits versions, but only the 32 bits version was added to druntime.
This commit contains the original tango code of bitswap(ulong), only slightly modified using feedback from the 32 bits version.
  • Loading branch information
mathias-lang-sociomantic committed Sep 3, 2015
1 parent 4e799b7 commit 10821c6
Showing 1 changed file with 72 additions and 0 deletions.
72 changes: 72 additions & 0 deletions src/core/bitop.d
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 10821c6

Please sign in to comment.