1 // Copyright 2017, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef VIXL_AARCH32_TEST_UTILS_AARCH32_H_ 28 #define VIXL_AARCH32_TEST_UTILS_AARCH32_H_ 29 30 #include "../test-pool-manager.h" 31 #include "../test-runner.h" 32 #include "aarch32/constants-aarch32.h" 33 #pragma clang optimize off 34 #include "aarch32/instructions-aarch32.h" 35 #pragma clang optimize on 36 #include "aarch32/macro-assembler-aarch32.h" 37 38 namespace vixl { 39 40 namespace aarch32 { 41 42 class TestMacroAssembler { 43 public: TestMacroAssembler(MacroAssembler * masm)44 explicit TestMacroAssembler(MacroAssembler* masm) 45 : test(&masm->pool_manager_) {} GetPoolCheckpoint()46 int32_t GetPoolCheckpoint() const { return test.GetPoolCheckpoint(); } GetPoolSize()47 int GetPoolSize() const { return test.GetPoolSize(); } PoolIsEmpty()48 bool PoolIsEmpty() const { return test.PoolIsEmpty(); } 49 50 private: 51 TestPoolManager test; 52 }; 53 54 // Only check the simulator tests when we can actually run them. 55 // TODO: Improve this. 56 #if defined(__arm__) 57 static const bool kCheckSimulatorTestResults = true; 58 #else 59 static const bool kCheckSimulatorTestResults = false; 60 #endif 61 62 // Helper constants used to check for condition code combinations. These are 63 // not part of instruction definitions as no instruction uses them directly. 64 const uint32_t NoFlag = 0x0; 65 const uint32_t NFlag = 0x80000000; 66 const uint32_t ZFlag = 0x40000000; 67 const uint32_t CFlag = 0x20000000; 68 const uint32_t VFlag = 0x10000000; 69 const uint32_t NZFlag = NFlag | ZFlag; 70 const uint32_t NCFlag = NFlag | CFlag; 71 const uint32_t NVFlag = NFlag | VFlag; 72 const uint32_t ZCFlag = ZFlag | CFlag; 73 const uint32_t ZVFlag = ZFlag | VFlag; 74 const uint32_t CVFlag = CFlag | VFlag; 75 const uint32_t NZCFlag = NFlag | ZFlag | CFlag; 76 const uint32_t NZVFlag = NFlag | ZFlag | VFlag; 77 const uint32_t NCVFlag = NFlag | CFlag | VFlag; 78 const uint32_t ZCVFlag = ZFlag | CFlag | VFlag; 79 const uint32_t NZCVFlag = NFlag | ZFlag | CFlag | VFlag; 80 const uint32_t QFlag = 0x08000000; 81 82 const uint32_t GE0Flag = 0x00010000; 83 const uint32_t GE1Flag = 0x00020000; 84 const uint32_t GE2Flag = 0x00040000; 85 const uint32_t GE3Flag = 0x00080000; 86 const uint32_t GE01Flag = GE0Flag | GE1Flag; 87 const uint32_t GE02Flag = GE0Flag | GE2Flag; 88 const uint32_t GE03Flag = GE0Flag | GE3Flag; 89 const uint32_t GE12Flag = GE1Flag | GE2Flag; 90 const uint32_t GE13Flag = GE1Flag | GE3Flag; 91 const uint32_t GE23Flag = GE2Flag | GE3Flag; 92 const uint32_t GE012Flag = GE0Flag | GE1Flag | GE2Flag; 93 const uint32_t GE013Flag = GE0Flag | GE1Flag | GE3Flag; 94 const uint32_t GE023Flag = GE0Flag | GE2Flag | GE3Flag; 95 const uint32_t GE123Flag = GE1Flag | GE2Flag | GE3Flag; 96 const uint32_t GE0123Flag = GE0Flag | GE1Flag | GE2Flag | GE3Flag; 97 const uint32_t GEFlags = GE0123Flag; 98 99 struct vec128_t { 100 uint64_t l; 101 uint64_t h; 102 }; 103 104 class RegisterDump { 105 public: RegisterDump()106 RegisterDump() : completed_(false) { 107 VIXL_ASSERT(sizeof(dump_.r_[0]) == kRegSizeInBytes); 108 } 109 110 // The Dump method generates code to store a snapshot of the register values. 111 // It needs to be able to use the stack temporarily. 112 // 113 // The dumping code is generated though the given MacroAssembler. No registers 114 // are corrupted in the process apart for the program counter, but the stack 115 // is used briefly. Note the program counter cannot be retrieved from the 116 // register dump anyway. 117 void Dump(MacroAssembler* masm); 118 119 // Register accessors. reg(unsigned code)120 int32_t reg(unsigned code) const { 121 VIXL_ASSERT(IsComplete()); 122 // The collected program counter should not be accessed. 123 VIXL_ASSERT(code != kPcCode); 124 return dump_.r_[code]; 125 } 126 127 // QRegister accessors GetQRegisterBits(unsigned code)128 vec128_t GetQRegisterBits(unsigned code) const { 129 VIXL_ASSERT(IsComplete()); 130 VIXL_ASSERT(code < kNumberOfQRegisters); 131 vec128_t content = {dump_.d_[code * 2], dump_.d_[(code * 2) + 1]}; 132 return content; 133 } 134 135 // DRegister accessors GetDRegisterBits(unsigned code)136 uint64_t GetDRegisterBits(unsigned code) const { 137 VIXL_ASSERT(IsComplete()); 138 VIXL_ASSERT(code < kMaxNumberOfDRegisters); 139 return dump_.d_[code]; 140 } 141 142 // SRegister accessors GetSRegisterBits(unsigned code)143 uint32_t GetSRegisterBits(unsigned code) const { 144 VIXL_ASSERT(IsComplete()); 145 VIXL_ASSERT(code < kNumberOfSRegisters); 146 if ((code % 2) == 0) { 147 return GetDRegisterBits(code / 2) & 0xffffffff; 148 } else { 149 return GetDRegisterBits(code / 2) >> 32; 150 } 151 VIXL_UNREACHABLE(); 152 return 0; 153 } 154 155 // Stack pointer accessors. spreg()156 int32_t spreg() const { return reg(kSPRegNum); } 157 158 // Flags accessors. flags_nzcv()159 uint32_t flags_nzcv() const { 160 VIXL_ASSERT(IsComplete()); 161 return dump_.flags_ & NZCVFlag; 162 } 163 IsComplete()164 bool IsComplete() const { return completed_; } 165 166 private: 167 // Indicate whether the dump operation has been completed. 168 bool completed_; 169 170 // Store all the dumped elements in a simple struct so the implementation can 171 // use offsetof to quickly find the correct field. 172 struct dump_t { 173 // Core registers, except for PC. 174 uint32_t r_[kNumberOfRegisters - 1]; 175 uint64_t d_[kMaxNumberOfDRegisters]; 176 177 // NZCV flags, stored in bits 28 to 31. 178 // bit[31] : Negative 179 // bit[30] : Zero 180 // bit[29] : Carry 181 // bit[28] : oVerflow 182 uint32_t flags_; 183 } dump_; 184 }; 185 186 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg); 187 bool Equal32(uint32_t expected, const RegisterDump* core, uint32_t result); 188 bool Equal32(uint32_t expected, 189 const RegisterDump* core, 190 const SRegister& sreg); 191 bool Equal64(uint64_t expected, 192 const RegisterDump* core, 193 const DRegister& dreg); 194 bool Equal128(uint64_t expected_h, 195 uint64_t expected_l, 196 const RegisterDump* core, 197 const QRegister& qreg); 198 bool EqualFP32(float expected, const RegisterDump* core, const SRegister& dreg); 199 bool EqualFP64(double expected, 200 const RegisterDump* core, 201 const DRegister& dreg); 202 bool EqualNzcv(uint32_t expected, uint32_t result); 203 204 } // namespace aarch32 205 } // namespace vixl 206 207 #endif // VIXL_AARCH32_TEST_UTILS_AARCH32_H_ 208