1*fb1b10abSAndroid Build Coastguard Worker /* 2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 3*fb1b10abSAndroid Build Coastguard Worker * 4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*fb1b10abSAndroid Build Coastguard Worker */ 10*fb1b10abSAndroid Build Coastguard Worker 11*fb1b10abSAndroid Build Coastguard Worker #ifndef VPX_TEST_REGISTER_STATE_CHECK_H_ 12*fb1b10abSAndroid Build Coastguard Worker #define VPX_TEST_REGISTER_STATE_CHECK_H_ 13*fb1b10abSAndroid Build Coastguard Worker 14*fb1b10abSAndroid Build Coastguard Worker #include "gtest/gtest.h" 15*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h" 16*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_integer.h" 17*fb1b10abSAndroid Build Coastguard Worker 18*fb1b10abSAndroid Build Coastguard Worker // ASM_REGISTER_STATE_CHECK(asm_function) 19*fb1b10abSAndroid Build Coastguard Worker // Minimally validates the environment pre & post function execution. This 20*fb1b10abSAndroid Build Coastguard Worker // variant should be used with assembly functions which are not expected to 21*fb1b10abSAndroid Build Coastguard Worker // fully restore the system state. See platform implementations of 22*fb1b10abSAndroid Build Coastguard Worker // RegisterStateCheck for details. 23*fb1b10abSAndroid Build Coastguard Worker // 24*fb1b10abSAndroid Build Coastguard Worker // API_REGISTER_STATE_CHECK(api_function) 25*fb1b10abSAndroid Build Coastguard Worker // Performs all the checks done by ASM_REGISTER_STATE_CHECK() and any 26*fb1b10abSAndroid Build Coastguard Worker // additional checks to ensure the environment is in a consistent state pre & 27*fb1b10abSAndroid Build Coastguard Worker // post function execution. This variant should be used with API functions. 28*fb1b10abSAndroid Build Coastguard Worker // See platform implementations of RegisterStateCheckXXX for details. 29*fb1b10abSAndroid Build Coastguard Worker // 30*fb1b10abSAndroid Build Coastguard Worker 31*fb1b10abSAndroid Build Coastguard Worker #if defined(_WIN64) && VPX_ARCH_X86_64 32*fb1b10abSAndroid Build Coastguard Worker 33*fb1b10abSAndroid Build Coastguard Worker #undef NOMINMAX 34*fb1b10abSAndroid Build Coastguard Worker #define NOMINMAX 35*fb1b10abSAndroid Build Coastguard Worker #ifndef WIN32_LEAN_AND_MEAN 36*fb1b10abSAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN 37*fb1b10abSAndroid Build Coastguard Worker #endif 38*fb1b10abSAndroid Build Coastguard Worker #include <intrin.h> 39*fb1b10abSAndroid Build Coastguard Worker #include <windows.h> 40*fb1b10abSAndroid Build Coastguard Worker #include <winnt.h> 41*fb1b10abSAndroid Build Coastguard Worker 42*fb1b10abSAndroid Build Coastguard Worker inline bool operator==(const M128A &lhs, const M128A &rhs) { 43*fb1b10abSAndroid Build Coastguard Worker return (lhs.Low == rhs.Low && lhs.High == rhs.High); 44*fb1b10abSAndroid Build Coastguard Worker } 45*fb1b10abSAndroid Build Coastguard Worker 46*fb1b10abSAndroid Build Coastguard Worker namespace libvpx_test { 47*fb1b10abSAndroid Build Coastguard Worker 48*fb1b10abSAndroid Build Coastguard Worker // Compares the state of xmm[6-15] at construction with their state at 49*fb1b10abSAndroid Build Coastguard Worker // destruction. These registers should be preserved by the callee on 50*fb1b10abSAndroid Build Coastguard Worker // Windows x64. 51*fb1b10abSAndroid Build Coastguard Worker class RegisterStateCheck { 52*fb1b10abSAndroid Build Coastguard Worker public: RegisterStateCheck()53*fb1b10abSAndroid Build Coastguard Worker RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); } ~RegisterStateCheck()54*fb1b10abSAndroid Build Coastguard Worker ~RegisterStateCheck() { Check(); } 55*fb1b10abSAndroid Build Coastguard Worker 56*fb1b10abSAndroid Build Coastguard Worker private: StoreRegisters(CONTEXT * const context)57*fb1b10abSAndroid Build Coastguard Worker static bool StoreRegisters(CONTEXT *const context) { 58*fb1b10abSAndroid Build Coastguard Worker const HANDLE this_thread = GetCurrentThread(); 59*fb1b10abSAndroid Build Coastguard Worker EXPECT_NE(this_thread, nullptr); 60*fb1b10abSAndroid Build Coastguard Worker context->ContextFlags = CONTEXT_FLOATING_POINT; 61*fb1b10abSAndroid Build Coastguard Worker const bool context_saved = GetThreadContext(this_thread, context) == TRUE; 62*fb1b10abSAndroid Build Coastguard Worker EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError(); 63*fb1b10abSAndroid Build Coastguard Worker return context_saved; 64*fb1b10abSAndroid Build Coastguard Worker } 65*fb1b10abSAndroid Build Coastguard Worker 66*fb1b10abSAndroid Build Coastguard Worker // Compares the register state. Returns true if the states match. Check()67*fb1b10abSAndroid Build Coastguard Worker void Check() const { 68*fb1b10abSAndroid Build Coastguard Worker ASSERT_TRUE(initialized_); 69*fb1b10abSAndroid Build Coastguard Worker CONTEXT post_context; 70*fb1b10abSAndroid Build Coastguard Worker ASSERT_TRUE(StoreRegisters(&post_context)); 71*fb1b10abSAndroid Build Coastguard Worker 72*fb1b10abSAndroid Build Coastguard Worker const M128A *xmm_pre = &pre_context_.Xmm6; 73*fb1b10abSAndroid Build Coastguard Worker const M128A *xmm_post = &post_context.Xmm6; 74*fb1b10abSAndroid Build Coastguard Worker for (int i = 6; i <= 15; ++i) { 75*fb1b10abSAndroid Build Coastguard Worker EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!"; 76*fb1b10abSAndroid Build Coastguard Worker ++xmm_pre; 77*fb1b10abSAndroid Build Coastguard Worker ++xmm_post; 78*fb1b10abSAndroid Build Coastguard Worker } 79*fb1b10abSAndroid Build Coastguard Worker } 80*fb1b10abSAndroid Build Coastguard Worker 81*fb1b10abSAndroid Build Coastguard Worker bool initialized_; 82*fb1b10abSAndroid Build Coastguard Worker CONTEXT pre_context_; 83*fb1b10abSAndroid Build Coastguard Worker }; 84*fb1b10abSAndroid Build Coastguard Worker 85*fb1b10abSAndroid Build Coastguard Worker #define ASM_REGISTER_STATE_CHECK(statement) \ 86*fb1b10abSAndroid Build Coastguard Worker do { \ 87*fb1b10abSAndroid Build Coastguard Worker { \ 88*fb1b10abSAndroid Build Coastguard Worker libvpx_test::RegisterStateCheck reg_check; \ 89*fb1b10abSAndroid Build Coastguard Worker statement; \ 90*fb1b10abSAndroid Build Coastguard Worker } \ 91*fb1b10abSAndroid Build Coastguard Worker _ReadWriteBarrier(); \ 92*fb1b10abSAndroid Build Coastguard Worker } while (false) 93*fb1b10abSAndroid Build Coastguard Worker 94*fb1b10abSAndroid Build Coastguard Worker } // namespace libvpx_test 95*fb1b10abSAndroid Build Coastguard Worker 96*fb1b10abSAndroid Build Coastguard Worker #elif defined(CONFIG_SHARED) && defined(HAVE_NEON_ASM) && \ 97*fb1b10abSAndroid Build Coastguard Worker defined(CONFIG_VP9) && !CONFIG_SHARED && HAVE_NEON_ASM && CONFIG_VP9 98*fb1b10abSAndroid Build Coastguard Worker 99*fb1b10abSAndroid Build Coastguard Worker extern "C" { 100*fb1b10abSAndroid Build Coastguard Worker // Save the d8-d15 registers into store. 101*fb1b10abSAndroid Build Coastguard Worker void vpx_push_neon(int64_t *store); 102*fb1b10abSAndroid Build Coastguard Worker } 103*fb1b10abSAndroid Build Coastguard Worker 104*fb1b10abSAndroid Build Coastguard Worker namespace libvpx_test { 105*fb1b10abSAndroid Build Coastguard Worker 106*fb1b10abSAndroid Build Coastguard Worker // Compares the state of d8-d15 at construction with their state at 107*fb1b10abSAndroid Build Coastguard Worker // destruction. These registers should be preserved by the callee on 108*fb1b10abSAndroid Build Coastguard Worker // arm platform. 109*fb1b10abSAndroid Build Coastguard Worker class RegisterStateCheck { 110*fb1b10abSAndroid Build Coastguard Worker public: RegisterStateCheck()111*fb1b10abSAndroid Build Coastguard Worker RegisterStateCheck() { vpx_push_neon(pre_store_); } ~RegisterStateCheck()112*fb1b10abSAndroid Build Coastguard Worker ~RegisterStateCheck() { Check(); } 113*fb1b10abSAndroid Build Coastguard Worker 114*fb1b10abSAndroid Build Coastguard Worker private: 115*fb1b10abSAndroid Build Coastguard Worker // Compares the register state. Returns true if the states match. Check()116*fb1b10abSAndroid Build Coastguard Worker void Check() const { 117*fb1b10abSAndroid Build Coastguard Worker int64_t post_store[8]; 118*fb1b10abSAndroid Build Coastguard Worker vpx_push_neon(post_store); 119*fb1b10abSAndroid Build Coastguard Worker for (int i = 0; i < 8; ++i) { 120*fb1b10abSAndroid Build Coastguard Worker EXPECT_EQ(pre_store_[i], post_store[i]) 121*fb1b10abSAndroid Build Coastguard Worker << "d" << i + 8 << " has been modified"; 122*fb1b10abSAndroid Build Coastguard Worker } 123*fb1b10abSAndroid Build Coastguard Worker } 124*fb1b10abSAndroid Build Coastguard Worker 125*fb1b10abSAndroid Build Coastguard Worker int64_t pre_store_[8]; 126*fb1b10abSAndroid Build Coastguard Worker }; 127*fb1b10abSAndroid Build Coastguard Worker 128*fb1b10abSAndroid Build Coastguard Worker #if defined(__GNUC__) 129*fb1b10abSAndroid Build Coastguard Worker #define ASM_REGISTER_STATE_CHECK(statement) \ 130*fb1b10abSAndroid Build Coastguard Worker do { \ 131*fb1b10abSAndroid Build Coastguard Worker { \ 132*fb1b10abSAndroid Build Coastguard Worker libvpx_test::RegisterStateCheck reg_check; \ 133*fb1b10abSAndroid Build Coastguard Worker statement; \ 134*fb1b10abSAndroid Build Coastguard Worker } \ 135*fb1b10abSAndroid Build Coastguard Worker __asm__ volatile("" ::: "memory"); \ 136*fb1b10abSAndroid Build Coastguard Worker } while (false) 137*fb1b10abSAndroid Build Coastguard Worker #else 138*fb1b10abSAndroid Build Coastguard Worker #define ASM_REGISTER_STATE_CHECK(statement) \ 139*fb1b10abSAndroid Build Coastguard Worker do { \ 140*fb1b10abSAndroid Build Coastguard Worker libvpx_test::RegisterStateCheck reg_check; \ 141*fb1b10abSAndroid Build Coastguard Worker statement; \ 142*fb1b10abSAndroid Build Coastguard Worker } while (false) 143*fb1b10abSAndroid Build Coastguard Worker #endif 144*fb1b10abSAndroid Build Coastguard Worker 145*fb1b10abSAndroid Build Coastguard Worker } // namespace libvpx_test 146*fb1b10abSAndroid Build Coastguard Worker 147*fb1b10abSAndroid Build Coastguard Worker #else 148*fb1b10abSAndroid Build Coastguard Worker 149*fb1b10abSAndroid Build Coastguard Worker namespace libvpx_test { 150*fb1b10abSAndroid Build Coastguard Worker 151*fb1b10abSAndroid Build Coastguard Worker class RegisterStateCheck {}; 152*fb1b10abSAndroid Build Coastguard Worker #define ASM_REGISTER_STATE_CHECK(statement) statement 153*fb1b10abSAndroid Build Coastguard Worker 154*fb1b10abSAndroid Build Coastguard Worker } // namespace libvpx_test 155*fb1b10abSAndroid Build Coastguard Worker 156*fb1b10abSAndroid Build Coastguard Worker #endif // _WIN64 && VPX_ARCH_X86_64 157*fb1b10abSAndroid Build Coastguard Worker 158*fb1b10abSAndroid Build Coastguard Worker #if VPX_ARCH_X86 || VPX_ARCH_X86_64 159*fb1b10abSAndroid Build Coastguard Worker #if defined(__GNUC__) 160*fb1b10abSAndroid Build Coastguard Worker 161*fb1b10abSAndroid Build Coastguard Worker namespace libvpx_test { 162*fb1b10abSAndroid Build Coastguard Worker 163*fb1b10abSAndroid Build Coastguard Worker // Checks the FPU tag word pre/post execution to ensure emms has been called. 164*fb1b10abSAndroid Build Coastguard Worker class RegisterStateCheckMMX { 165*fb1b10abSAndroid Build Coastguard Worker public: RegisterStateCheckMMX()166*fb1b10abSAndroid Build Coastguard Worker RegisterStateCheckMMX() { 167*fb1b10abSAndroid Build Coastguard Worker __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_)); 168*fb1b10abSAndroid Build Coastguard Worker } ~RegisterStateCheckMMX()169*fb1b10abSAndroid Build Coastguard Worker ~RegisterStateCheckMMX() { Check(); } 170*fb1b10abSAndroid Build Coastguard Worker 171*fb1b10abSAndroid Build Coastguard Worker private: 172*fb1b10abSAndroid Build Coastguard Worker // Checks the FPU tag word pre/post execution, returning false if not cleared 173*fb1b10abSAndroid Build Coastguard Worker // to 0xffff. Check()174*fb1b10abSAndroid Build Coastguard Worker void Check() const { 175*fb1b10abSAndroid Build Coastguard Worker EXPECT_EQ(0xffff, pre_fpu_env_[4]) 176*fb1b10abSAndroid Build Coastguard Worker << "FPU was in an inconsistent state prior to call"; 177*fb1b10abSAndroid Build Coastguard Worker 178*fb1b10abSAndroid Build Coastguard Worker uint16_t post_fpu_env[14]; 179*fb1b10abSAndroid Build Coastguard Worker __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env)); 180*fb1b10abSAndroid Build Coastguard Worker EXPECT_EQ(0xffff, post_fpu_env[4]) 181*fb1b10abSAndroid Build Coastguard Worker << "FPU was left in an inconsistent state after call"; 182*fb1b10abSAndroid Build Coastguard Worker } 183*fb1b10abSAndroid Build Coastguard Worker 184*fb1b10abSAndroid Build Coastguard Worker uint16_t pre_fpu_env_[14]; 185*fb1b10abSAndroid Build Coastguard Worker }; 186*fb1b10abSAndroid Build Coastguard Worker 187*fb1b10abSAndroid Build Coastguard Worker #define API_REGISTER_STATE_CHECK(statement) \ 188*fb1b10abSAndroid Build Coastguard Worker do { \ 189*fb1b10abSAndroid Build Coastguard Worker { \ 190*fb1b10abSAndroid Build Coastguard Worker libvpx_test::RegisterStateCheckMMX reg_check_mmx; \ 191*fb1b10abSAndroid Build Coastguard Worker ASM_REGISTER_STATE_CHECK(statement); \ 192*fb1b10abSAndroid Build Coastguard Worker } \ 193*fb1b10abSAndroid Build Coastguard Worker __asm__ volatile("" ::: "memory"); \ 194*fb1b10abSAndroid Build Coastguard Worker } while (false) 195*fb1b10abSAndroid Build Coastguard Worker 196*fb1b10abSAndroid Build Coastguard Worker } // namespace libvpx_test 197*fb1b10abSAndroid Build Coastguard Worker 198*fb1b10abSAndroid Build Coastguard Worker #endif // __GNUC__ 199*fb1b10abSAndroid Build Coastguard Worker #endif // VPX_ARCH_X86 || VPX_ARCH_X86_64 200*fb1b10abSAndroid Build Coastguard Worker 201*fb1b10abSAndroid Build Coastguard Worker #ifndef API_REGISTER_STATE_CHECK 202*fb1b10abSAndroid Build Coastguard Worker #define API_REGISTER_STATE_CHECK ASM_REGISTER_STATE_CHECK 203*fb1b10abSAndroid Build Coastguard Worker #endif 204*fb1b10abSAndroid Build Coastguard Worker 205*fb1b10abSAndroid Build Coastguard Worker #endif // VPX_TEST_REGISTER_STATE_CHECK_H_ 206