Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifndef TEST_REGISTER_STATE_CHECK_H_
     12 #define TEST_REGISTER_STATE_CHECK_H_
     13 
     14 #include "third_party/googletest/src/include/gtest/gtest.h"
     15 #include "./vpx_config.h"
     16 
     17 #if defined(_WIN64)
     18 
     19 #define _WIN32_LEAN_AND_MEAN
     20 #include <windows.h>
     21 #include <winnt.h>
     22 
     23 namespace testing {
     24 namespace internal {
     25 
     26 inline bool operator==(const M128A& lhs, const M128A& rhs) {
     27   return (lhs.Low == rhs.Low && lhs.High == rhs.High);
     28 }
     29 
     30 }  // namespace internal
     31 }  // namespace testing
     32 
     33 namespace libvpx_test {
     34 
     35 // Compares the state of xmm[6-15] at construction with their state at
     36 // destruction. These registers should be preserved by the callee on
     37 // Windows x64.
     38 // Usage:
     39 // {
     40 //   RegisterStateCheck reg_check;
     41 //   FunctionToVerify();
     42 // }
     43 class RegisterStateCheck {
     44  public:
     45   RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
     46   ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
     47 
     48  private:
     49   static bool StoreRegisters(CONTEXT* const context) {
     50     const HANDLE this_thread = GetCurrentThread();
     51     EXPECT_TRUE(this_thread != NULL);
     52     context->ContextFlags = CONTEXT_FLOATING_POINT;
     53     const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
     54     EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
     55     return context_saved;
     56   }
     57 
     58   // Compares the register state. Returns true if the states match.
     59   bool Check() const {
     60     if (!initialized_) return false;
     61     CONTEXT post_context;
     62     if (!StoreRegisters(&post_context)) return false;
     63 
     64     const M128A* xmm_pre = &pre_context_.Xmm6;
     65     const M128A* xmm_post = &post_context.Xmm6;
     66     for (int i = 6; i <= 15; ++i) {
     67       EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
     68       ++xmm_pre;
     69       ++xmm_post;
     70     }
     71     return !testing::Test::HasNonfatalFailure();
     72   }
     73 
     74   bool initialized_;
     75   CONTEXT pre_context_;
     76 };
     77 
     78 #define REGISTER_STATE_CHECK(statement) do { \
     79   libvpx_test::RegisterStateCheck reg_check; \
     80   statement;                               \
     81 } while (false)
     82 
     83 }  // namespace libvpx_test
     84 
     85 #elif defined(CONFIG_SHARED) && defined(HAVE_NEON) \
     86       && !CONFIG_SHARED && HAVE_NEON
     87 
     88 #include "vpx/vpx_integer.h"
     89 
     90 extern "C" {
     91 // Save the d8-d15 registers into store.
     92 void vp9_push_neon(int64_t *store);
     93 }
     94 
     95 namespace libvpx_test {
     96 
     97 // Compares the state of d8-d15 at construction with their state at
     98 // destruction. These registers should be preserved by the callee on
     99 // arm platform.
    100 // Usage:
    101 // {
    102 //   RegisterStateCheck reg_check;
    103 //   FunctionToVerify();
    104 // }
    105 class RegisterStateCheck {
    106  public:
    107   RegisterStateCheck() { initialized_ = StoreRegisters(pre_store_); }
    108   ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
    109 
    110  private:
    111   static bool StoreRegisters(int64_t store[8]) {
    112     vp9_push_neon(store);
    113     return true;
    114   }
    115 
    116   // Compares the register state. Returns true if the states match.
    117   bool Check() const {
    118     if (!initialized_) return false;
    119     int64_t post_store[8];
    120     vp9_push_neon(post_store);
    121     for (int i = 0; i < 8; ++i) {
    122       EXPECT_EQ(pre_store_[i], post_store[i]) << "d"
    123           << i + 8 << " has been modified";
    124     }
    125     return !testing::Test::HasNonfatalFailure();
    126   }
    127 
    128   bool initialized_;
    129   int64_t pre_store_[8];
    130 };
    131 
    132 #define REGISTER_STATE_CHECK(statement) do { \
    133   libvpx_test::RegisterStateCheck reg_check; \
    134   statement;                               \
    135 } while (false)
    136 
    137 }  // namespace libvpx_test
    138 
    139 #else
    140 
    141 namespace libvpx_test {
    142 
    143 class RegisterStateCheck {};
    144 #define REGISTER_STATE_CHECK(statement) statement
    145 
    146 }  // namespace libvpx_test
    147 
    148 #endif  // _WIN64
    149 
    150 #endif  // TEST_REGISTER_STATE_CHECK_H_
    151