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 #include "aarch32/instructions-aarch32.h" 34 #include "aarch32/macro-assembler-aarch32.h" 35 36 namespace vixl { 37 38 namespace aarch32 { 39 40 class TestMacroAssembler { 41 public: TestMacroAssembler(MacroAssembler * masm)42 explicit TestMacroAssembler(MacroAssembler* masm) 43 : test(&masm->pool_manager_) {} GetPoolCheckpoint()44 int32_t GetPoolCheckpoint() const { return test.GetPoolCheckpoint(); } GetPoolSize()45 int GetPoolSize() const { return test.GetPoolSize(); } PoolIsEmpty()46 bool PoolIsEmpty() const { return test.PoolIsEmpty(); } 47 48 private: 49 TestPoolManager test; 50 }; 51 52 // Only check the simulator tests when we can actually run them. 53 // TODO: Improve this. 54 #if defined(__arm__) 55 static const bool kCheckSimulatorTestResults = true; 56 #else 57 static const bool kCheckSimulatorTestResults = false; 58 #endif 59 60 // Helper constants used to check for condition code combinations. These are 61 // not part of instruction definitions as no instruction uses them directly. 62 const uint32_t NoFlag = 0x0; 63 const uint32_t NFlag = 0x80000000; 64 const uint32_t ZFlag = 0x40000000; 65 const uint32_t CFlag = 0x20000000; 66 const uint32_t VFlag = 0x10000000; 67 const uint32_t NZFlag = NFlag | ZFlag; 68 const uint32_t NCFlag = NFlag | CFlag; 69 const uint32_t NVFlag = NFlag | VFlag; 70 const uint32_t ZCFlag = ZFlag | CFlag; 71 const uint32_t ZVFlag = ZFlag | VFlag; 72 const uint32_t CVFlag = CFlag | VFlag; 73 const uint32_t NZCFlag = NFlag | ZFlag | CFlag; 74 const uint32_t NZVFlag = NFlag | ZFlag | VFlag; 75 const uint32_t NCVFlag = NFlag | CFlag | VFlag; 76 const uint32_t ZCVFlag = ZFlag | CFlag | VFlag; 77 const uint32_t NZCVFlag = NFlag | ZFlag | CFlag | VFlag; 78 const uint32_t QFlag = 0x08000000; 79 80 const uint32_t GE0Flag = 0x00010000; 81 const uint32_t GE1Flag = 0x00020000; 82 const uint32_t GE2Flag = 0x00040000; 83 const uint32_t GE3Flag = 0x00080000; 84 const uint32_t GE01Flag = GE0Flag | GE1Flag; 85 const uint32_t GE02Flag = GE0Flag | GE2Flag; 86 const uint32_t GE03Flag = GE0Flag | GE3Flag; 87 const uint32_t GE12Flag = GE1Flag | GE2Flag; 88 const uint32_t GE13Flag = GE1Flag | GE3Flag; 89 const uint32_t GE23Flag = GE2Flag | GE3Flag; 90 const uint32_t GE012Flag = GE0Flag | GE1Flag | GE2Flag; 91 const uint32_t GE013Flag = GE0Flag | GE1Flag | GE3Flag; 92 const uint32_t GE023Flag = GE0Flag | GE2Flag | GE3Flag; 93 const uint32_t GE123Flag = GE1Flag | GE2Flag | GE3Flag; 94 const uint32_t GE0123Flag = GE0Flag | GE1Flag | GE2Flag | GE3Flag; 95 const uint32_t GEFlags = GE0123Flag; 96 97 struct vec128_t { 98 uint64_t l; 99 uint64_t h; 100 }; 101 102 class RegisterDump { 103 public: RegisterDump()104 RegisterDump() : completed_(false) { 105 VIXL_ASSERT(sizeof(dump_.r_[0]) == kRegSizeInBytes); 106 } 107 108 // The Dump method generates code to store a snapshot of the register values. 109 // It needs to be able to use the stack temporarily. 110 // 111 // The dumping code is generated though the given MacroAssembler. No registers 112 // are corrupted in the process apart for the program counter, but the stack 113 // is used briefly. Note the program counter cannot be retrieved from the 114 // register dump anyway. 115 void Dump(MacroAssembler* masm); 116 117 // Register accessors. reg(unsigned code)118 int32_t reg(unsigned code) const { 119 VIXL_ASSERT(IsComplete()); 120 // The collected program counter should not be accessed. 121 VIXL_ASSERT(code != kPcCode); 122 return dump_.r_[code]; 123 } 124 125 // QRegister accessors GetQRegisterBits(unsigned code)126 vec128_t GetQRegisterBits(unsigned code) const { 127 VIXL_ASSERT(IsComplete()); 128 VIXL_ASSERT(code < kNumberOfQRegisters); 129 vec128_t content = {dump_.d_[code * 2], dump_.d_[(code * 2) + 1]}; 130 return content; 131 } 132 133 // DRegister accessors GetDRegisterBits(unsigned code)134 uint64_t GetDRegisterBits(unsigned code) const { 135 VIXL_ASSERT(IsComplete()); 136 VIXL_ASSERT(code < kMaxNumberOfDRegisters); 137 return dump_.d_[code]; 138 } 139 140 // SRegister accessors GetSRegisterBits(unsigned code)141 uint32_t GetSRegisterBits(unsigned code) const { 142 VIXL_ASSERT(IsComplete()); 143 VIXL_ASSERT(code < kNumberOfSRegisters); 144 if ((code % 2) == 0) { 145 return GetDRegisterBits(code / 2) & 0xffffffff; 146 } else { 147 return GetDRegisterBits(code / 2) >> 32; 148 } 149 VIXL_UNREACHABLE(); 150 return 0; 151 } 152 153 // Stack pointer accessors. spreg()154 int32_t spreg() const { return reg(kSPRegNum); } 155 156 // Flags accessors. flags_nzcv()157 uint32_t flags_nzcv() const { 158 VIXL_ASSERT(IsComplete()); 159 return dump_.flags_ & NZCVFlag; 160 } 161 IsComplete()162 bool IsComplete() const { return completed_; } 163 164 private: 165 // Indicate whether the dump operation has been completed. 166 bool completed_; 167 168 // Store all the dumped elements in a simple struct so the implementation can 169 // use offsetof to quickly find the correct field. 170 struct dump_t { 171 // Core registers, except for PC. 172 uint32_t r_[kNumberOfRegisters - 1]; 173 uint64_t d_[kMaxNumberOfDRegisters]; 174 175 // NZCV flags, stored in bits 28 to 31. 176 // bit[31] : Negative 177 // bit[30] : Zero 178 // bit[29] : Carry 179 // bit[28] : oVerflow 180 uint32_t flags_; 181 } dump_; 182 }; 183 184 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg); 185 bool Equal32(uint32_t expected, const RegisterDump* core, uint32_t result); 186 bool Equal32(uint32_t expected, 187 const RegisterDump* core, 188 const SRegister& sreg); 189 bool Equal64(uint64_t expected, 190 const RegisterDump* core, 191 const DRegister& dreg); 192 bool Equal128(uint64_t expected_h, 193 uint64_t expected_l, 194 const RegisterDump* core, 195 const QRegister& qreg); 196 bool EqualFP32(float expected, const RegisterDump* core, const SRegister& dreg); 197 bool EqualFP64(double expected, 198 const RegisterDump* core, 199 const DRegister& dreg); 200 bool EqualNzcv(uint32_t expected, uint32_t result); 201 202 } // namespace aarch32 203 } // namespace vixl 204 205 #endif // VIXL_AARCH32_TEST_UTILS_AARCH32_H_ 206