1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifndef TEST_REGISTER_STATE_CHECK_H_
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TEST_REGISTER_STATE_CHECK_H_
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/googletest/src/include/gtest/gtest.h"
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h"
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(_WIN64)
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define _WIN32_LEAN_AND_MEAN
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <windows.h>
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <winnt.h>
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan
23233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace testing {
24233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace internal {
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan
26233d2500723e5594f3e7c70896ffeeef32b9c950ywaninline bool operator==(const M128A& lhs, const M128A& rhs) {
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return (lhs.Low == rhs.Low && lhs.High == rhs.High);
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace internal
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace testing
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan
33233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace libvpx_test {
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Compares the state of xmm[6-15] at construction with their state at
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan// destruction. These registers should be preserved by the callee on
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Windows x64.
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Usage:
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan// {
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan//   RegisterStateCheck reg_check;
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan//   FunctionToVerify();
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan// }
43233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass RegisterStateCheck {
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan public:
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan  RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan private:
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan  static bool StoreRegisters(CONTEXT* const context) {
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const HANDLE this_thread = GetCurrentThread();
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(this_thread != NULL);
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan    context->ContextFlags = CONTEXT_FLOATING_POINT;
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan    EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return context_saved;
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Compares the register state. Returns true if the states match.
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan  bool Check() const {
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!initialized_) return false;
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CONTEXT post_context;
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!StoreRegisters(&post_context)) return false;
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const M128A* xmm_pre = &pre_context_.Xmm6;
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const M128A* xmm_post = &post_context.Xmm6;
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int i = 6; i <= 15; ++i) {
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++xmm_pre;
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++xmm_post;
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return !testing::Test::HasNonfatalFailure();
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan  bool initialized_;
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan  CONTEXT pre_context_;
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define REGISTER_STATE_CHECK(statement) do { \
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan  libvpx_test::RegisterStateCheck reg_check; \
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan  statement;                               \
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan} while (false)
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace libvpx_test
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif defined(CONFIG_SHARED) && defined(HAVE_NEON) \
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan      && !CONFIG_SHARED && HAVE_NEON
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_integer.h"
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan
90233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern "C" {
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Save the d8-d15 registers into store.
92233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_push_neon(int64_t *store);
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan
95233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace libvpx_test {
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Compares the state of d8-d15 at construction with their state at
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan// destruction. These registers should be preserved by the callee on
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan// arm platform.
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Usage:
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan// {
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan//   RegisterStateCheck reg_check;
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan//   FunctionToVerify();
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan// }
105233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass RegisterStateCheck {
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan public:
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  RegisterStateCheck() { initialized_ = StoreRegisters(pre_store_); }
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan private:
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  static bool StoreRegisters(int64_t store[8]) {
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_push_neon(store);
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Compares the register state. Returns true if the states match.
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  bool Check() const {
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!initialized_) return false;
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64_t post_store[8];
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_push_neon(post_store);
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int i = 0; i < 8; ++i) {
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EXPECT_EQ(pre_store_[i], post_store[i]) << "d"
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan          << i + 8 << " has been modified";
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return !testing::Test::HasNonfatalFailure();
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  bool initialized_;
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t pre_store_[8];
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define REGISTER_STATE_CHECK(statement) do { \
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  libvpx_test::RegisterStateCheck reg_check; \
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  statement;                               \
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan} while (false)
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace libvpx_test
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
141233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace libvpx_test {
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
143233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass RegisterStateCheck {};
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define REGISTER_STATE_CHECK(statement) statement
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace libvpx_test
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif  // _WIN64
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif  // TEST_REGISTER_STATE_CHECK_H_
151