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
26 // See platform implementations of RegisterStateCheck and
27 // RegisterStateCheckMMX for details.
29 #if defined(_WIN64) && ARCH_X86_64
33 #define WIN32_LEAN_AND_MEAN
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
46 class RegisterStateCheck
{
48 RegisterStateCheck() { initialized_
= StoreRegisters(&pre_context_
); }
49 ~RegisterStateCheck() { Check(); }
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();
61 // Compares the register state. Returns true if the states match.
63 ASSERT_TRUE(initialized_
);
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!";
79 } // namespace libaom_test
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
{
96 RegisterStateCheckMMX() {
97 __asm__
volatile("fstenv %0" : "=rm"(pre_fpu_env_
));
99 ~RegisterStateCheckMMX() { Check(); }
102 // Checks the FPU tag word pre/post execution, returning false if not cleared
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
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) \
128 libaom_test::RegisterStateCheck reg_check; \
129 libaom_test::RegisterStateCheckMMX reg_check_mmx; \
131 (void)reg_check_mmx; \
135 #endif // AOM_TEST_REGISTER_STATE_CHECK_H_