Files
AnyPS5/core/libs/tests/GuestDinkumwareDivision.cpp
T

193 lines
14 KiB
C++

#include "prx/libc/include/Api.hpp"
#include <bit>
#include <cfenv>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <initializer_list>
#include <xmmintrin.h>
namespace {
struct Case {
unsigned function;
unsigned rounding;
unsigned denormals;
std::uint64_t first;
std::uint64_t second;
std::uint64_t result;
unsigned flags;
};
constexpr Case Cases[] = {
{0, 0, 0, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 0, 0, 0x0000000000000000ull, 0x0000000000000000ull, 0xfff8000000000000ull, 1u},
{0, 0, 1, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 0, 1, 0x3ff0000000000000ull, 0x0000000000000000ull, 0x7ff0000000000000ull, 4u},
{0, 0, 2, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 0, 2, 0xbff0000000000000ull, 0x0000000000000000ull, 0xfff0000000000000ull, 4u},
{0, 0, 3, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 0, 3, 0x0000000000000000ull, 0xbff0000000000000ull, 0x8000000000000000ull, 0u},
{0, 1, 0, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 1, 0, 0x7ff0000000000001ull, 0x3ff0000000000000ull, 0x7ff8000000000001ull, 1u},
{0, 1, 1, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 1, 1, 0x7ff8000000001234ull, 0xfff8000000005678ull, 0x7ff8000000001234ull, 0u},
{0, 1, 2, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 1, 2, 0xfff8000000005678ull, 0x7ff8000000001234ull, 0xfff8000000005678ull, 0u},
{0, 1, 3, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 1, 3, 0x0000000000000001ull, 0xbff0000000000000ull, 0x8000000000000000ull, 0u},
{0, 2, 0, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555556ull, 32u},
{0, 2, 0, 0x7fefffffffffffffull, 0x3fd0000000000000ull, 0x7ff0000000000000ull, 40u},
{0, 2, 1, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555556ull, 32u},
{0, 2, 1, 0x3fd0000000000000ull, 0x7fefffffffffffffull, 0x0001000000000001ull, 48u},
{0, 2, 2, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555556ull, 32u},
{0, 2, 2, 0x0000000000000000ull, 0x0000000000000000ull, 0xfff8000000000000ull, 1u},
{0, 2, 3, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555556ull, 32u},
{0, 2, 3, 0x3ff0000000000000ull, 0x0000000000000000ull, 0x7ff0000000000000ull, 4u},
{0, 3, 0, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 3, 0, 0xbff0000000000000ull, 0x0000000000000000ull, 0xfff0000000000000ull, 4u},
{0, 3, 1, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 3, 1, 0x0000000000000000ull, 0xbff0000000000000ull, 0x8000000000000000ull, 0u},
{0, 3, 2, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 3, 2, 0x7ff0000000000001ull, 0x3ff0000000000000ull, 0x7ff8000000000001ull, 1u},
{0, 3, 3, 0x3ff0000000000000ull, 0x4008000000000000ull, 0x3fd5555555555555ull, 32u},
{0, 3, 3, 0x7ff8000000001234ull, 0xfff8000000005678ull, 0x7ff8000000001234ull, 0u},
{1, 0, 0, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 0, 0, 0x0000000000000000ull, 0x0000000000000000ull, 0x00000000ffc00000ull, 1u},
{1, 0, 1, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 0, 1, 0x000000003f800000ull, 0x0000000000000000ull, 0x000000007f800000ull, 4u},
{1, 0, 2, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 0, 2, 0x00000000bf800000ull, 0x0000000000000000ull, 0x00000000ff800000ull, 4u},
{1, 0, 3, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 0, 3, 0x0000000000000000ull, 0x00000000bf800000ull, 0x0000000080000000ull, 0u},
{1, 1, 0, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 1, 0, 0x000000007f800001ull, 0x000000003f800000ull, 0x000000007fc00001ull, 1u},
{1, 1, 1, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 1, 1, 0x000000007fc01234ull, 0x00000000ffc05678ull, 0x000000007fc01234ull, 0u},
{1, 1, 2, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 1, 2, 0x00000000ffc05678ull, 0x000000007fc01234ull, 0x00000000ffc05678ull, 0u},
{1, 1, 3, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 1, 3, 0x0000000000000001ull, 0x00000000bf800000ull, 0x0000000080000000ull, 0u},
{1, 2, 0, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 2, 0, 0x000000007f7fffffull, 0x000000003e800000ull, 0x000000007f800000ull, 40u},
{1, 2, 1, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 2, 1, 0x000000003e800000ull, 0x000000007f7fffffull, 0x0000000000080001ull, 48u},
{1, 2, 2, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 2, 2, 0x0000000000000000ull, 0x0000000000000000ull, 0x00000000ffc00000ull, 1u},
{1, 2, 3, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaabull, 32u},
{1, 2, 3, 0x000000003f800000ull, 0x0000000000000000ull, 0x000000007f800000ull, 4u},
{1, 3, 0, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 3, 0, 0x00000000bf800000ull, 0x0000000000000000ull, 0x00000000ff800000ull, 4u},
{1, 3, 1, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 3, 1, 0x0000000000000000ull, 0x00000000bf800000ull, 0x0000000080000000ull, 0u},
{1, 3, 2, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 3, 2, 0x000000007f800001ull, 0x000000003f800000ull, 0x000000007fc00001ull, 1u},
{1, 3, 3, 0x000000003f800000ull, 0x0000000040400000ull, 0x000000003eaaaaaaull, 32u},
{1, 3, 3, 0x000000007fc01234ull, 0x00000000ffc05678ull, 0x000000007fc01234ull, 0u},
{2, 0, 0, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 0, 0, 0x0000000000000000ull, 0x0000000000000000ull, 0x7ff0000000000000ull, 4u},
{2, 0, 1, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 0, 1, 0x8000000000000000ull, 0x0000000000000000ull, 0xfff0000000000000ull, 4u},
{2, 0, 2, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 0, 2, 0x0000000000000001ull, 0x0000000000000000ull, 0x7ff0000000000000ull, 42u},
{2, 0, 3, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 0, 3, 0x000fffffffffffffull, 0x0000000000000000ull, 0x7ff0000000000000ull, 4u},
{2, 1, 0, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 1, 0, 0x0010000000000000ull, 0x0000000000000000ull, 0x7fd0000000000000ull, 0u},
{2, 1, 1, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 1, 1, 0x7fefffffffffffffull, 0x0000000000000000ull, 0x0004000000000000ull, 48u},
{2, 1, 2, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 1, 2, 0x7ff0000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0u},
{2, 1, 3, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 1, 3, 0x7ff0000000000001ull, 0x0000000000000000ull, 0x7ff8000000000001ull, 1u},
{2, 2, 0, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555556ull, 32u},
{2, 2, 0, 0x7ff8000000001234ull, 0x0000000000000000ull, 0x7ff8000000001234ull, 0u},
{2, 2, 1, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555556ull, 32u},
{2, 2, 1, 0xfff8000000005678ull, 0x0000000000000000ull, 0xfff8000000005678ull, 0u},
{2, 2, 2, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555556ull, 32u},
{2, 2, 2, 0x0000000000000000ull, 0x0000000000000000ull, 0x7ff0000000000000ull, 4u},
{2, 2, 3, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555556ull, 32u},
{2, 2, 3, 0x8000000000000000ull, 0x0000000000000000ull, 0xfff0000000000000ull, 4u},
{2, 3, 0, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 3, 0, 0x0000000000000001ull, 0x0000000000000000ull, 0x7fefffffffffffffull, 42u},
{2, 3, 1, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 3, 1, 0x000fffffffffffffull, 0x0000000000000000ull, 0x7ff0000000000000ull, 4u},
{2, 3, 2, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 3, 2, 0x0010000000000000ull, 0x0000000000000000ull, 0x7fd0000000000000ull, 0u},
{2, 3, 3, 0x4008000000000000ull, 0x0000000000000000ull, 0x3fd5555555555555ull, 32u},
{2, 3, 3, 0x7fefffffffffffffull, 0x0000000000000000ull, 0x0000000000000000ull, 48u},
{3, 0, 0, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 0, 0, 0x0000000000000000ull, 0x0000000000000000ull, 0x000000007f800000ull, 4u},
{3, 0, 1, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 0, 1, 0x0000000080000000ull, 0x0000000000000000ull, 0x00000000ff800000ull, 4u},
{3, 0, 2, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 0, 2, 0x0000000000000001ull, 0x0000000000000000ull, 0x000000007f800000ull, 42u},
{3, 0, 3, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 0, 3, 0x00000000007fffffull, 0x0000000000000000ull, 0x000000007f800000ull, 4u},
{3, 1, 0, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 1, 0, 0x0000000000800000ull, 0x0000000000000000ull, 0x000000007e800000ull, 0u},
{3, 1, 1, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 1, 1, 0x000000007f7fffffull, 0x0000000000000000ull, 0x0000000000200000ull, 48u},
{3, 1, 2, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 1, 2, 0x000000007f800000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0u},
{3, 1, 3, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 1, 3, 0x000000007f800001ull, 0x0000000000000000ull, 0x000000007fc00001ull, 1u},
{3, 2, 0, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 2, 0, 0x000000007fc01234ull, 0x0000000000000000ull, 0x000000007fc01234ull, 0u},
{3, 2, 1, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 2, 1, 0x00000000ffc05678ull, 0x0000000000000000ull, 0x00000000ffc05678ull, 0u},
{3, 2, 2, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 2, 2, 0x0000000000000000ull, 0x0000000000000000ull, 0x000000007f800000ull, 4u},
{3, 2, 3, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaabull, 32u},
{3, 2, 3, 0x0000000080000000ull, 0x0000000000000000ull, 0x00000000ff800000ull, 4u},
{3, 3, 0, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 3, 0, 0x0000000000000001ull, 0x0000000000000000ull, 0x000000007f7fffffull, 42u},
{3, 3, 1, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 3, 1, 0x00000000007fffffull, 0x0000000000000000ull, 0x000000007f800000ull, 4u},
{3, 3, 2, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 3, 2, 0x0000000000800000ull, 0x0000000000000000ull, 0x000000007e800000ull, 0u},
{3, 3, 3, 0x0000000040400000ull, 0x0000000000000000ull, 0x000000003eaaaaaaull, 32u},
{3, 3, 3, 0x000000007f7fffffull, 0x0000000000000000ull, 0x0000000000000000ull, 48u},
};
int StandardFlags(unsigned flags) {
return ((flags & 1u) ? FE_INVALID : 0) | ((flags & 4u) ? FE_DIVBYZERO : 0) |
((flags & 8u) ? FE_OVERFLOW : 0) | ((flags & 16u) ? FE_UNDERFLOW : 0) |
((flags & 32u) ? FE_INEXACT : 0);
}
}
int main() {
std::fenv_t saved;
if (std::fegetenv(&saved) != 0) return 1;
const auto savedCsr = _mm_getcsr();
const int savedError = *__error_nid_postfix();
unsigned index = 0;
for (const auto& test : Cases) {
for (unsigned sticky : {0u, 5u, 32u}) {
if (std::fesetenv(FE_DFL_ENV) != 0) return 1;
const unsigned control = 0x1f80u | (test.rounding << 13u) | ((test.denormals & 1u) ? 0x40u : 0u) | ((test.denormals & 2u) ? 0x8000u : 0u);
*__error_nid_postfix() = 97;
_mm_setcsr(control | sticky);
std::uint64_t result = 0;
if (test.function == 0) result = std::bit_cast<std::uint64_t>(_Divide_nid_postfix(std::bit_cast<double>(test.first), std::bit_cast<double>(test.second)));
else if (test.function == 1) result = std::bit_cast<std::uint32_t>(_FDivide_nid_postfix(std::bit_cast<float>(static_cast<std::uint32_t>(test.first)), std::bit_cast<float>(static_cast<std::uint32_t>(test.second))));
else if (test.function == 2) result = std::bit_cast<std::uint64_t>(_Recip_nid_postfix(std::bit_cast<double>(test.first)));
else result = std::bit_cast<std::uint32_t>(_FRecip_nid_postfix(std::bit_cast<float>(static_cast<std::uint32_t>(test.first))));
const unsigned csr = _mm_getcsr();
const int flags = std::fetestexcept(FE_ALL_EXCEPT);
const int error = *__error_nid_postfix();
if (result != test.result || csr != (control | test.flags | sticky) || flags != StandardFlags(test.flags | sticky) || error != 97) {
std::fprintf(stderr, "Dinkumware division case %u sticky %u: bits %016llx/%016llx csr %x/%x flags %x/%x errno %d\n", index, sticky,
static_cast<unsigned long long>(result), static_cast<unsigned long long>(test.result), csr, control | test.flags | sticky, flags, StandardFlags(test.flags | sticky), error);
return 1;
}
}
++index;
}
if (std::fesetenv(&saved) != 0) return 1;
_mm_setcsr(savedCsr);
*__error_nid_postfix() = savedError;
}