hadamard: Add 4x4 test.
[aom.git] / test / register_state_check.h
blob4bf5120cc7fb754e55c8bc2470eaf6b8f2aebbc7
1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
12 #ifndef AOM_TEST_REGISTER_STATE_CHECK_H_
13 #define AOM_TEST_REGISTER_STATE_CHECK_H_
15 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
17 #include "config/aom_config.h"
19 #include "aom/aom_integer.h"
21 // API_REGISTER_STATE_CHECK(function)
22 // Validates the environment pre & post function execution to ensure the
23 // environment is in a consistent state. This should be used with API
24 // function sand assembly functions which are not expected to fully restore
25 // the system state.
26 // See platform implementations of RegisterStateCheck and
27 // RegisterStateCheckMMX for details.
29 #if defined(_WIN64) && ARCH_X86_64
31 #undef NOMINMAX
32 #define NOMINMAX
33 #define WIN32_LEAN_AND_MEAN
34 #include <windows.h>
35 #include <winnt.h>
37 inline bool operator==(const M128A &lhs, const M128A &rhs) {
38 return (lhs.Low == rhs.Low && lhs.High == rhs.High);
41 namespace libaom_test {
43 // Compares the state of xmm[6-15] at construction with their state at
44 // destruction. These registers should be preserved by the callee on
45 // Windows x64.
46 class RegisterStateCheck {
47 public:
48 RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
49 ~RegisterStateCheck() { Check(); }
51 private:
52 static bool StoreRegisters(CONTEXT *const context) {
53 const HANDLE this_thread = GetCurrentThread();
54 EXPECT_TRUE(this_thread != NULL);
55 context->ContextFlags = CONTEXT_FLOATING_POINT;
56 const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
57 EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
58 return context_saved;
61 // Compares the register state. Returns true if the states match.
62 void Check() const {
63 ASSERT_TRUE(initialized_);
64 CONTEXT post_context;
65 ASSERT_TRUE(StoreRegisters(&post_context));
67 const M128A *xmm_pre = &pre_context_.Xmm6;
68 const M128A *xmm_post = &post_context.Xmm6;
69 for (int i = 6; i <= 15; ++i) {
70 EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
71 ++xmm_pre;
72 ++xmm_post;
76 bool initialized_;
77 CONTEXT pre_context_;
79 } // namespace libaom_test
81 #else
83 namespace libaom_test {
85 class RegisterStateCheck {};
86 } // namespace libaom_test
88 #endif // _WIN64 && ARCH_X86_64
90 #if (ARCH_X86 || ARCH_X86_64) && defined(__GNUC__)
91 namespace libaom_test {
93 // Checks the FPU tag word pre/post execution to ensure emms has been called.
94 class RegisterStateCheckMMX {
95 public:
96 RegisterStateCheckMMX() {
97 __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_));
99 ~RegisterStateCheckMMX() { Check(); }
101 private:
102 // Checks the FPU tag word pre/post execution, returning false if not cleared
103 // to 0xffff.
104 void Check() const {
105 EXPECT_EQ(0xffff, pre_fpu_env_[4])
106 << "FPU was in an inconsistent state prior to call";
108 uint16_t post_fpu_env[14];
109 __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env));
110 EXPECT_EQ(0xffff, post_fpu_env[4])
111 << "FPU was left in an inconsistent state after call";
114 uint16_t pre_fpu_env_[14];
116 } // namespace libaom_test
118 #else
119 namespace libaom_test {
121 class RegisterStateCheckMMX {};
122 } // namespace libaom_test
124 #endif // (ARCH_X86 || ARCH_X86_64) && defined(__GNUC__)
126 #define API_REGISTER_STATE_CHECK(statement) \
127 do { \
128 libaom_test::RegisterStateCheck reg_check; \
129 libaom_test::RegisterStateCheckMMX reg_check_mmx; \
130 statement; \
131 (void)reg_check_mmx; \
132 (void)reg_check; \
133 } while (false)
135 #endif // AOM_TEST_REGISTER_STATE_CHECK_H_