diff options
Diffstat (limited to 'test/register_state_check.h')
-rw-r--r-- | test/register_state_check.h | 84 |
1 files changed, 65 insertions, 19 deletions
diff --git a/test/register_state_check.h b/test/register_state_check.h index 1ee149b0c..8d4beea5f 100644 --- a/test/register_state_check.h +++ b/test/register_state_check.h @@ -13,6 +13,20 @@ #include "third_party/googletest/src/include/gtest/gtest.h" #include "./vpx_config.h" +#include "vpx/vpx_integer.h" + +// ASM_REGISTER_STATE_CHECK(asm_function) +// Minimally validates the environment pre & post function execution. This +// variant should be used with assembly functions which are not expected to +// fully restore the system state. See platform implementations of +// RegisterStateCheck for details. +// +// API_REGISTER_STATE_CHECK(api_function) +// Performs all the checks done by ASM_REGISTER_STATE_CHECK() and any +// additional checks to ensure the environment is in a consistent state pre & +// post function execution. This variant should be used with API functions. +// See platform implementations of RegisterStateCheckXXX for details. +// #if defined(_WIN64) @@ -35,11 +49,6 @@ namespace libvpx_test { // Compares the state of xmm[6-15] at construction with their state at // destruction. These registers should be preserved by the callee on // Windows x64. -// Usage: -// { -// RegisterStateCheck reg_check; -// FunctionToVerify(); -// } class RegisterStateCheck { public: RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); } @@ -75,9 +84,9 @@ class RegisterStateCheck { CONTEXT pre_context_; }; -#define REGISTER_STATE_CHECK(statement) do { \ - libvpx_test::RegisterStateCheck reg_check; \ - statement; \ +#define ASM_REGISTER_STATE_CHECK(statement) do { \ + libvpx_test::RegisterStateCheck reg_check; \ + statement; \ } while (false) } // namespace libvpx_test @@ -85,8 +94,6 @@ class RegisterStateCheck { #elif defined(CONFIG_SHARED) && defined(HAVE_NEON_ASM) && defined(CONFIG_VP9) \ && !CONFIG_SHARED && HAVE_NEON_ASM && CONFIG_VP9 -#include "vpx/vpx_integer.h" - extern "C" { // Save the d8-d15 registers into store. void vp9_push_neon(int64_t *store); @@ -97,11 +104,6 @@ namespace libvpx_test { // Compares the state of d8-d15 at construction with their state at // destruction. These registers should be preserved by the callee on // arm platform. -// Usage: -// { -// RegisterStateCheck reg_check; -// FunctionToVerify(); -// } class RegisterStateCheck { public: RegisterStateCheck() { initialized_ = StoreRegisters(pre_store_); } @@ -129,9 +131,9 @@ class RegisterStateCheck { int64_t pre_store_[8]; }; -#define REGISTER_STATE_CHECK(statement) do { \ - libvpx_test::RegisterStateCheck reg_check; \ - statement; \ +#define ASM_REGISTER_STATE_CHECK(statement) do { \ + libvpx_test::RegisterStateCheck reg_check; \ + statement; \ } while (false) } // namespace libvpx_test @@ -141,10 +143,54 @@ class RegisterStateCheck { namespace libvpx_test { class RegisterStateCheck {}; -#define REGISTER_STATE_CHECK(statement) statement +#define ASM_REGISTER_STATE_CHECK(statement) statement } // namespace libvpx_test #endif // _WIN64 +#if ARCH_X86 || ARCH_X86_64 +#if defined(__GNUC__) + +namespace libvpx_test { + +// Checks the FPU tag word pre/post execution to ensure emms has been called. +class RegisterStateCheckMMX { + public: + RegisterStateCheckMMX() { + __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_)); + } + ~RegisterStateCheckMMX() { EXPECT_TRUE(Check()); } + + private: + // Checks the FPU tag word pre/post execution, returning false if not cleared + // to 0xffff. + bool Check() const { + EXPECT_EQ(0xffff, pre_fpu_env_[4]) + << "FPU was in an inconsistent state prior to call"; + + uint16_t post_fpu_env[14]; + __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env)); + EXPECT_EQ(0xffff, post_fpu_env[4]) + << "FPU was left in an inconsistent state after call"; + return !testing::Test::HasNonfatalFailure(); + } + + uint16_t pre_fpu_env_[14]; +}; + +#define API_REGISTER_STATE_CHECK(statement) do { \ + libvpx_test::RegisterStateCheckMMX reg_check; \ + ASM_REGISTER_STATE_CHECK(statement); \ +} while (false) + +} // namespace libvpx_test + +#endif // __GNUC__ +#endif // ARCH_X86 || ARCH_X86_64 + +#ifndef API_REGISTER_STATE_CHECK +#define API_REGISTER_STATE_CHECK ASM_REGISTER_STATE_CHECK +#endif + #endif // TEST_REGISTER_STATE_CHECK_H_ |