1d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org/*
2d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *
4d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  Use of this source code is governed by a BSD-style license
5d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  that can be found in the LICENSE file in the root of the source
6d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  tree. An additional intellectual property rights grant can be found
7d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  in the file PATENTS.  All contributing project authors may
8d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org */
10d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
11f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#ifndef TEST_REGISTER_STATE_CHECK_H_
12f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#define TEST_REGISTER_STATE_CHECK_H_
13d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
1493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "third_party/googletest/src/include/gtest/gtest.h"
1593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "./vpx_config.h"
1693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#if defined(_WIN64)
18d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
19d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#define _WIN32_LEAN_AND_MEAN
20d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include <windows.h>
21d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#include <winnt.h>
22d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
23d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgnamespace testing {
24d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgnamespace internal {
25d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
26d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orginline bool operator==(const M128A& lhs, const M128A& rhs) {
27d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  return (lhs.Low == rhs.Low && lhs.High == rhs.High);
28d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}
29d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
30d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}  // namespace internal
31d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}  // namespace testing
32d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
33d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgnamespace libvpx_test {
34d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
35d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org// Compares the state of xmm[6-15] at construction with their state at
36d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org// destruction. These registers should be preserved by the callee on
37d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org// Windows x64.
38d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org// Usage:
39d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org// {
40d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org//   RegisterStateCheck reg_check;
41d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org//   FunctionToVerify();
42d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org// }
43d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgclass RegisterStateCheck {
44d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org public:
45d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
46d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
47d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
48d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org private:
49d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  static bool StoreRegisters(CONTEXT* const context) {
50d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    const HANDLE this_thread = GetCurrentThread();
51d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    EXPECT_TRUE(this_thread != NULL);
52d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    context->ContextFlags = CONTEXT_FLOATING_POINT;
53d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
54d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
55d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    return context_saved;
56d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
57d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
58d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  // Compares the register state. Returns true if the states match.
59d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  bool Check() const {
60d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    if (!initialized_) return false;
61d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    CONTEXT post_context;
62d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    if (!StoreRegisters(&post_context)) return false;
63d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
64d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    const M128A* xmm_pre = &pre_context_.Xmm6;
65d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    const M128A* xmm_post = &post_context.Xmm6;
66d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    for (int i = 6; i <= 15; ++i) {
67d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
68d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      ++xmm_pre;
69d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org      ++xmm_post;
70d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    }
71d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org    return !testing::Test::HasNonfatalFailure();
72d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  }
73d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
74d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  bool initialized_;
75d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  CONTEXT pre_context_;
76d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org};
77d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
78d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#define REGISTER_STATE_CHECK(statement) do { \
79d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  libvpx_test::RegisterStateCheck reg_check; \
80d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org  statement;                               \
81d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org} while (false)
82d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
83d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}  // namespace libvpx_test
84d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
857765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org#elif defined(CONFIG_SHARED) && defined(HAVE_NEON_ASM) && defined(CONFIG_VP9) \
867765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org      && !CONFIG_SHARED && HAVE_NEON_ASM && CONFIG_VP9
8793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
8893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "vpx/vpx_integer.h"
8993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
9093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgextern "C" {
9193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Save the d8-d15 registers into store.
9293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgvoid vp9_push_neon(int64_t *store);
9393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
9493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
9593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgnamespace libvpx_test {
9693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
9793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Compares the state of d8-d15 at construction with their state at
9893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// destruction. These registers should be preserved by the callee on
9993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// arm platform.
10093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Usage:
10193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// {
10293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org//   RegisterStateCheck reg_check;
10393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org//   FunctionToVerify();
10493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// }
10593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgclass RegisterStateCheck {
10693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org public:
10793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  RegisterStateCheck() { initialized_ = StoreRegisters(pre_store_); }
10893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
10993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
11093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org private:
11193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  static bool StoreRegisters(int64_t store[8]) {
11293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    vp9_push_neon(store);
11393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return true;
11493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
11593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
11693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  // Compares the register state. Returns true if the states match.
11793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  bool Check() const {
11893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (!initialized_) return false;
11993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    int64_t post_store[8];
12093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    vp9_push_neon(post_store);
12193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    for (int i = 0; i < 8; ++i) {
12293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      EXPECT_EQ(pre_store_[i], post_store[i]) << "d"
12393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org          << i + 8 << " has been modified";
12493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    }
12593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return !testing::Test::HasNonfatalFailure();
12693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
12793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
12893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  bool initialized_;
12993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  int64_t pre_store_[8];
13093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org};
13193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
13293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#define REGISTER_STATE_CHECK(statement) do { \
13393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  libvpx_test::RegisterStateCheck reg_check; \
13493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  statement;                               \
13593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org} while (false)
13693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
13793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}  // namespace libvpx_test
13893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
13993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#else
140d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
141d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgnamespace libvpx_test {
142d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
143d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.orgclass RegisterStateCheck {};
144d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#define REGISTER_STATE_CHECK(statement) statement
145d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
146d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org}  // namespace libvpx_test
147d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
148d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org#endif  // _WIN64
149d348b8d765c019ee7250075d663a83db00c65c08tomfinegan@chromium.org
150f9586bb54d74c97d07b09eb2512f8569c9c1c025fgalligan@chromium.org#endif  // TEST_REGISTER_STATE_CHECK_H_
151