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 TEST_REGISTER_STATE_CHECK_H_
13 #define 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 // ASM_REGISTER_STATE_CHECK(asm_function)
22 // Minimally validates the environment pre & post function execution. This
23 // variant should be used with assembly functions which are not expected to
24 // fully restore the system state. See platform implementations of
25 // RegisterStateCheck for details.
27 // API_REGISTER_STATE_CHECK(api_function)
28 // Performs all the checks done by ASM_REGISTER_STATE_CHECK() and any
29 // additional checks to ensure the environment is in a consistent state pre &
30 // post function execution. This variant should be used with API functions.
31 // See platform implementations of RegisterStateCheckXXX for details.
34 #if defined(_WIN64) && ARCH_X86_64
38 #define WIN32_LEAN_AND_MEAN
42 inline bool operator==(const M128A
&lhs
, const M128A
&rhs
) {
43 return (lhs
.Low
== rhs
.Low
&& lhs
.High
== rhs
.High
);
46 namespace libaom_test
{
48 // Compares the state of xmm[6-15] at construction with their state at
49 // destruction. These registers should be preserved by the callee on
51 class RegisterStateCheck
{
53 RegisterStateCheck() { initialized_
= StoreRegisters(&pre_context_
); }
54 ~RegisterStateCheck() { Check(); }
57 static bool StoreRegisters(CONTEXT
*const context
) {
58 const HANDLE this_thread
= GetCurrentThread();
59 EXPECT_TRUE(this_thread
!= NULL
);
60 context
->ContextFlags
= CONTEXT_FLOATING_POINT
;
61 const bool context_saved
= GetThreadContext(this_thread
, context
) == TRUE
;
62 EXPECT_TRUE(context_saved
) << "GetLastError: " << GetLastError();
66 // Compares the register state. Returns true if the states match.
68 ASSERT_TRUE(initialized_
);
70 ASSERT_TRUE(StoreRegisters(&post_context
));
72 const M128A
*xmm_pre
= &pre_context_
.Xmm6
;
73 const M128A
*xmm_post
= &post_context
.Xmm6
;
74 for (int i
= 6; i
<= 15; ++i
) {
75 EXPECT_EQ(*xmm_pre
, *xmm_post
) << "xmm" << i
<< " has been modified!";
85 #define ASM_REGISTER_STATE_CHECK(statement) \
87 libaom_test::RegisterStateCheck reg_check; \
91 } // namespace libaom_test
95 namespace libaom_test
{
97 class RegisterStateCheck
{};
98 #define ASM_REGISTER_STATE_CHECK(statement) statement
100 } // namespace libaom_test
102 #endif // _WIN64 && ARCH_X86_64
104 #if ARCH_X86 || ARCH_X86_64
105 #if defined(__GNUC__)
107 namespace libaom_test
{
109 // Checks the FPU tag word pre/post execution to ensure emms has been called.
110 class RegisterStateCheckMMX
{
112 RegisterStateCheckMMX() {
113 __asm__
volatile("fstenv %0" : "=rm"(pre_fpu_env_
));
115 ~RegisterStateCheckMMX() { Check(); }
118 // Checks the FPU tag word pre/post execution, returning false if not cleared
121 EXPECT_EQ(0xffff, pre_fpu_env_
[4])
122 << "FPU was in an inconsistent state prior to call";
124 uint16_t post_fpu_env
[14];
125 __asm__
volatile("fstenv %0" : "=rm"(post_fpu_env
));
126 EXPECT_EQ(0xffff, post_fpu_env
[4])
127 << "FPU was left in an inconsistent state after call";
130 uint16_t pre_fpu_env_
[14];
133 #define API_REGISTER_STATE_CHECK(statement) \
135 libaom_test::RegisterStateCheckMMX reg_check; \
136 ASM_REGISTER_STATE_CHECK(statement); \
139 } // namespace libaom_test
142 #endif // ARCH_X86 || ARCH_X86_64
144 #ifndef API_REGISTER_STATE_CHECK
145 #define API_REGISTER_STATE_CHECK ASM_REGISTER_STATE_CHECK
148 #endif // TEST_REGISTER_STATE_CHECK_H_