mirror of
https://github.com/matrix-construct/construct
synced 2024-11-16 15:00:51 +01:00
ircd::simd: Add rotate left/right template interfaces.
This commit is contained in:
parent
13c2df9992
commit
972fbcc97d
3 changed files with 210 additions and 0 deletions
100
include/ircd/simd/rol.h
Normal file
100
include/ircd/simd/rol.h
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// The Construct
|
||||||
|
//
|
||||||
|
// Copyright (C) The Construct Developers, Authors & Contributors
|
||||||
|
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#define HAVE_IRCD_SIMD_ROL_H
|
||||||
|
|
||||||
|
// xmmx rotate-left interface
|
||||||
|
namespace ircd::simd
|
||||||
|
{
|
||||||
|
template<int b,
|
||||||
|
class V,
|
||||||
|
class T>
|
||||||
|
T _rol(const T) noexcept;
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 16, T>::type
|
||||||
|
rol(const T a) noexcept;
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 32, T>::type
|
||||||
|
rol(const T a) noexcept;
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 64, T>::type
|
||||||
|
rol(const T a) noexcept;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class V,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline T
|
||||||
|
ircd::simd::_rol(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
static_assert
|
||||||
|
(
|
||||||
|
sizeof(T) == sizeof(V)
|
||||||
|
);
|
||||||
|
|
||||||
|
static_assert
|
||||||
|
(
|
||||||
|
b % 8 == 0, "[emulated] xmmx register only rotates left at bytewise resolution."
|
||||||
|
);
|
||||||
|
|
||||||
|
constexpr int B
|
||||||
|
{
|
||||||
|
b / 8
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t i(0);
|
||||||
|
V arg(a), ret;
|
||||||
|
for(; i < B; ++i)
|
||||||
|
ret[i] = arg[sizeof(V) - B + i];
|
||||||
|
|
||||||
|
for(; i < sizeof(V); ++i)
|
||||||
|
ret[i] = arg[i - B];
|
||||||
|
|
||||||
|
return T(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline typename std::enable_if<sizeof(T) == 16, T>::type
|
||||||
|
ircd::simd::rol(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return _rol<b, u8x16>(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline typename std::enable_if<sizeof(T) == 32, T>::type
|
||||||
|
ircd::simd::rol(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return _rol<b, u8x32>(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline typename std::enable_if<sizeof(T) == 64, T>::type
|
||||||
|
ircd::simd::rol(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return _rol<b, u8x64>(a);
|
||||||
|
}
|
105
include/ircd/simd/ror.h
Normal file
105
include/ircd/simd/ror.h
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// The Construct
|
||||||
|
//
|
||||||
|
// Copyright (C) The Construct Developers, Authors & Contributors
|
||||||
|
// Copyright (C) 2016-2020 Jason Volk <jason@zemos.net>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#define HAVE_IRCD_SIMD_ROR_H
|
||||||
|
|
||||||
|
// xmmx rotate-right interface
|
||||||
|
namespace ircd::simd
|
||||||
|
{
|
||||||
|
template<int b,
|
||||||
|
class V,
|
||||||
|
class T>
|
||||||
|
T _ror(const T) noexcept;
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 16, T>::type
|
||||||
|
ror(const T a) noexcept;
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 32, T>::type
|
||||||
|
ror(const T a) noexcept;
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
typename std::enable_if<sizeof(T) == 64, T>::type
|
||||||
|
ror(const T a) noexcept;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class V,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline T
|
||||||
|
ircd::simd::_ror(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
static_assert
|
||||||
|
(
|
||||||
|
sizeof(T) == sizeof(V)
|
||||||
|
);
|
||||||
|
|
||||||
|
static_assert
|
||||||
|
(
|
||||||
|
b % 8 == 0, "[emulated] xmmx register only rotates left at bytewise resolution."
|
||||||
|
);
|
||||||
|
|
||||||
|
constexpr int B
|
||||||
|
{
|
||||||
|
b / 8
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr auto S
|
||||||
|
{
|
||||||
|
sizeof(V) - B
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t i(0);
|
||||||
|
V arg(a), ret;
|
||||||
|
for(; i < S; ++i)
|
||||||
|
ret[i] = arg[i + B];
|
||||||
|
|
||||||
|
for(; i < sizeof(V); ++i)
|
||||||
|
ret[i] = arg[i - S];
|
||||||
|
|
||||||
|
return T(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline typename std::enable_if<sizeof(T) == 16, T>::type
|
||||||
|
ircd::simd::ror(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return _ror<b, u8x16>(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline typename std::enable_if<sizeof(T) == 32, T>::type
|
||||||
|
ircd::simd::ror(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return _ror<b, u8x32>(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int b,
|
||||||
|
class T>
|
||||||
|
[[using gnu: always_inline, gnu_inline, artificial]]
|
||||||
|
extern inline typename std::enable_if<sizeof(T) == 64, T>::type
|
||||||
|
ircd::simd::ror(const T a)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
return _ror<b, u8x64>(a);
|
||||||
|
}
|
|
@ -22,6 +22,8 @@
|
||||||
#include "gather.h"
|
#include "gather.h"
|
||||||
#include "shl.h"
|
#include "shl.h"
|
||||||
#include "shr.h"
|
#include "shr.h"
|
||||||
|
#include "rol.h"
|
||||||
|
#include "ror.h"
|
||||||
#include "popcnt.h"
|
#include "popcnt.h"
|
||||||
#include "lzcnt.h"
|
#include "lzcnt.h"
|
||||||
#include "tzcnt.h"
|
#include "tzcnt.h"
|
||||||
|
@ -36,6 +38,9 @@ namespace ircd
|
||||||
using simd::shl;
|
using simd::shl;
|
||||||
using simd::shr;
|
using simd::shr;
|
||||||
|
|
||||||
|
using simd::rol;
|
||||||
|
using simd::ror;
|
||||||
|
|
||||||
using simd::lzcnt;
|
using simd::lzcnt;
|
||||||
using simd::tzcnt;
|
using simd::tzcnt;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue