| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #include "test/cctest/cctest.h" | 32 #include "test/cctest/cctest.h" |
| 33 | 33 |
| 34 #include "src/arm64/macro-assembler-arm64.h" | 34 #include "src/arm64/macro-assembler-arm64.h" |
| 35 #include "src/arm64/utils-arm64.h" | 35 #include "src/arm64/utils-arm64.h" |
| 36 #include "src/macro-assembler.h" | 36 #include "src/macro-assembler.h" |
| 37 | 37 |
| 38 | 38 |
| 39 namespace v8 { | 39 namespace v8 { |
| 40 namespace internal { | 40 namespace internal { |
| 41 | 41 |
| 42 // Structure representing Q registers in a RegisterDump. |
| 43 struct vec128_t { |
| 44 uint64_t l; |
| 45 uint64_t h; |
| 46 }; |
| 42 | 47 |
| 43 // RegisterDump: Object allowing integer, floating point and flags registers | 48 // RegisterDump: Object allowing integer, floating point and flags registers |
| 44 // to be saved to itself for future reference. | 49 // to be saved to itself for future reference. |
| 45 class RegisterDump { | 50 class RegisterDump { |
| 46 public: | 51 public: |
| 47 RegisterDump() : completed_(false) {} | 52 RegisterDump() : completed_(false) {} |
| 48 | 53 |
| 49 // The Dump method generates code to store a snapshot of the register values. | 54 // The Dump method generates code to store a snapshot of the register values. |
| 50 // It needs to be able to use the stack temporarily, and requires that the | 55 // It needs to be able to use the stack temporarily, and requires that the |
| 51 // current stack pointer is csp, and is properly aligned. | 56 // current stack pointer is csp, and is properly aligned. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 65 } | 70 } |
| 66 | 71 |
| 67 inline int64_t xreg(unsigned code) const { | 72 inline int64_t xreg(unsigned code) const { |
| 68 if (code == kSPRegInternalCode) { | 73 if (code == kSPRegInternalCode) { |
| 69 return spreg(); | 74 return spreg(); |
| 70 } | 75 } |
| 71 CHECK(RegAliasesMatch(code)); | 76 CHECK(RegAliasesMatch(code)); |
| 72 return dump_.x_[code]; | 77 return dump_.x_[code]; |
| 73 } | 78 } |
| 74 | 79 |
| 75 // FPRegister accessors. | 80 // VRegister accessors. |
| 76 inline uint32_t sreg_bits(unsigned code) const { | 81 inline uint32_t sreg_bits(unsigned code) const { |
| 77 CHECK(FPRegAliasesMatch(code)); | 82 CHECK(FPRegAliasesMatch(code)); |
| 78 return dump_.s_[code]; | 83 return dump_.s_[code]; |
| 79 } | 84 } |
| 80 | 85 |
| 81 inline float sreg(unsigned code) const { | 86 inline float sreg(unsigned code) const { |
| 82 return rawbits_to_float(sreg_bits(code)); | 87 return bit_cast<float>(sreg_bits(code)); |
| 83 } | 88 } |
| 84 | 89 |
| 85 inline uint64_t dreg_bits(unsigned code) const { | 90 inline uint64_t dreg_bits(unsigned code) const { |
| 86 CHECK(FPRegAliasesMatch(code)); | 91 CHECK(FPRegAliasesMatch(code)); |
| 87 return dump_.d_[code]; | 92 return dump_.d_[code]; |
| 88 } | 93 } |
| 89 | 94 |
| 90 inline double dreg(unsigned code) const { | 95 inline double dreg(unsigned code) const { |
| 91 return rawbits_to_double(dreg_bits(code)); | 96 return bit_cast<double>(dreg_bits(code)); |
| 92 } | 97 } |
| 93 | 98 |
| 99 inline vec128_t qreg(unsigned code) const { return dump_.q_[code]; } |
| 100 |
| 94 // Stack pointer accessors. | 101 // Stack pointer accessors. |
| 95 inline int64_t spreg() const { | 102 inline int64_t spreg() const { |
| 96 CHECK(SPRegAliasesMatch()); | 103 CHECK(SPRegAliasesMatch()); |
| 97 return dump_.sp_; | 104 return dump_.sp_; |
| 98 } | 105 } |
| 99 | 106 |
| 100 inline int32_t wspreg() const { | 107 inline int32_t wspreg() const { |
| 101 CHECK(SPRegAliasesMatch()); | 108 CHECK(SPRegAliasesMatch()); |
| 102 return static_cast<int32_t>(dump_.wsp_); | 109 return static_cast<int32_t>(dump_.wsp_); |
| 103 } | 110 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 128 | 135 |
| 129 // As RegAliasesMatch, but for the stack pointer. | 136 // As RegAliasesMatch, but for the stack pointer. |
| 130 bool SPRegAliasesMatch() const { | 137 bool SPRegAliasesMatch() const { |
| 131 CHECK(IsComplete()); | 138 CHECK(IsComplete()); |
| 132 return ((dump_.sp_ & kWRegMask) == dump_.wsp_); | 139 return ((dump_.sp_ & kWRegMask) == dump_.wsp_); |
| 133 } | 140 } |
| 134 | 141 |
| 135 // As RegAliasesMatch, but for floating-point registers. | 142 // As RegAliasesMatch, but for floating-point registers. |
| 136 bool FPRegAliasesMatch(unsigned code) const { | 143 bool FPRegAliasesMatch(unsigned code) const { |
| 137 CHECK(IsComplete()); | 144 CHECK(IsComplete()); |
| 138 CHECK(code < kNumberOfFPRegisters); | 145 CHECK(code < kNumberOfVRegisters); |
| 139 return (dump_.d_[code] & kSRegMask) == dump_.s_[code]; | 146 return (dump_.d_[code] & kSRegMask) == dump_.s_[code]; |
| 140 } | 147 } |
| 141 | 148 |
| 142 // Store all the dumped elements in a simple struct so the implementation can | 149 // Store all the dumped elements in a simple struct so the implementation can |
| 143 // use offsetof to quickly find the correct field. | 150 // use offsetof to quickly find the correct field. |
| 144 struct dump_t { | 151 struct dump_t { |
| 145 // Core registers. | 152 // Core registers. |
| 146 uint64_t x_[kNumberOfRegisters]; | 153 uint64_t x_[kNumberOfRegisters]; |
| 147 uint32_t w_[kNumberOfRegisters]; | 154 uint32_t w_[kNumberOfRegisters]; |
| 148 | 155 |
| 149 // Floating-point registers, as raw bits. | 156 // Floating-point registers, as raw bits. |
| 150 uint64_t d_[kNumberOfFPRegisters]; | 157 uint64_t d_[kNumberOfVRegisters]; |
| 151 uint32_t s_[kNumberOfFPRegisters]; | 158 uint32_t s_[kNumberOfVRegisters]; |
| 159 |
| 160 // Vector registers. |
| 161 vec128_t q_[kNumberOfVRegisters]; |
| 152 | 162 |
| 153 // The stack pointer. | 163 // The stack pointer. |
| 154 uint64_t sp_; | 164 uint64_t sp_; |
| 155 uint64_t wsp_; | 165 uint64_t wsp_; |
| 156 | 166 |
| 157 // NZCV flags, stored in bits 28 to 31. | 167 // NZCV flags, stored in bits 28 to 31. |
| 158 // bit[31] : Negative | 168 // bit[31] : Negative |
| 159 // bit[30] : Zero | 169 // bit[30] : Zero |
| 160 // bit[29] : Carry | 170 // bit[29] : Carry |
| 161 // bit[28] : oVerflow | 171 // bit[28] : oVerflow |
| 162 uint64_t flags_; | 172 uint64_t flags_; |
| 163 } dump_; | 173 } dump_; |
| 164 | 174 |
| 165 static dump_t for_sizeof(); | 175 static dump_t for_sizeof(); |
| 166 STATIC_ASSERT(sizeof(for_sizeof().d_[0]) == kDRegSize); | 176 static_assert(kXRegSize == kDRegSize, "X and D registers must be same size."); |
| 167 STATIC_ASSERT(sizeof(for_sizeof().s_[0]) == kSRegSize); | 177 static_assert(kWRegSize == kSRegSize, "W and S registers must be same size."); |
| 168 STATIC_ASSERT(sizeof(for_sizeof().d_[0]) == kXRegSize); | 178 static_assert(sizeof(for_sizeof().q_[0]) == kQRegSize, |
| 169 STATIC_ASSERT(sizeof(for_sizeof().s_[0]) == kWRegSize); | 179 "Array elements must be size of Q register."); |
| 170 STATIC_ASSERT(sizeof(for_sizeof().x_[0]) == kXRegSize); | 180 static_assert(sizeof(for_sizeof().d_[0]) == kDRegSize, |
| 171 STATIC_ASSERT(sizeof(for_sizeof().w_[0]) == kWRegSize); | 181 "Array elements must be size of D register."); |
| 182 static_assert(sizeof(for_sizeof().s_[0]) == kSRegSize, |
| 183 "Array elements must be size of S register."); |
| 184 static_assert(sizeof(for_sizeof().x_[0]) == kXRegSize, |
| 185 "Array elements must be size of X register."); |
| 186 static_assert(sizeof(for_sizeof().w_[0]) == kWRegSize, |
| 187 "Array elements must be size of W register."); |
| 172 }; | 188 }; |
| 173 | 189 |
| 174 // Some of these methods don't use the RegisterDump argument, but they have to | 190 // Some of these methods don't use the RegisterDump argument, but they have to |
| 175 // accept them so that they can overload those that take register arguments. | 191 // accept them so that they can overload those that take register arguments. |
| 176 bool Equal32(uint32_t expected, const RegisterDump*, uint32_t result); | 192 bool Equal32(uint32_t expected, const RegisterDump*, uint32_t result); |
| 177 bool Equal64(uint64_t expected, const RegisterDump*, uint64_t result); | 193 bool Equal64(uint64_t expected, const RegisterDump*, uint64_t result); |
| 178 | 194 |
| 179 bool EqualFP32(float expected, const RegisterDump*, float result); | 195 bool EqualFP32(float expected, const RegisterDump*, float result); |
| 180 bool EqualFP64(double expected, const RegisterDump*, double result); | 196 bool EqualFP64(double expected, const RegisterDump*, double result); |
| 181 | 197 |
| 182 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg); | 198 bool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg); |
| 183 bool Equal64(uint64_t expected, const RegisterDump* core, const Register& reg); | 199 bool Equal64(uint64_t expected, const RegisterDump* core, const Register& reg); |
| 184 | 200 |
| 185 bool EqualFP32(float expected, const RegisterDump* core, | 201 bool EqualFP32(float expected, const RegisterDump* core, |
| 186 const FPRegister& fpreg); | 202 const VRegister& fpreg); |
| 187 bool EqualFP64(double expected, const RegisterDump* core, | 203 bool EqualFP64(double expected, const RegisterDump* core, |
| 188 const FPRegister& fpreg); | 204 const VRegister& fpreg); |
| 189 | 205 |
| 190 bool Equal64(const Register& reg0, const RegisterDump* core, | 206 bool Equal64(const Register& reg0, const RegisterDump* core, |
| 191 const Register& reg1); | 207 const Register& reg1); |
| 208 bool Equal128(uint64_t expected_h, uint64_t expected_l, |
| 209 const RegisterDump* core, const VRegister& reg); |
| 192 | 210 |
| 193 bool EqualNzcv(uint32_t expected, uint32_t result); | 211 bool EqualNzcv(uint32_t expected, uint32_t result); |
| 194 | 212 |
| 195 bool EqualRegisters(const RegisterDump* a, const RegisterDump* b); | 213 bool EqualRegisters(const RegisterDump* a, const RegisterDump* b); |
| 196 | 214 |
| 197 // Populate the w, x and r arrays with registers from the 'allowed' mask. The | 215 // Populate the w, x and r arrays with registers from the 'allowed' mask. The |
| 198 // r array will be populated with <reg_size>-sized registers, | 216 // r array will be populated with <reg_size>-sized registers, |
| 199 // | 217 // |
| 200 // This allows for tests which use large, parameterized blocks of registers | 218 // This allows for tests which use large, parameterized blocks of registers |
| 201 // (such as the push and pop tests), but where certain registers must be | 219 // (such as the push and pop tests), but where certain registers must be |
| 202 // avoided as they are used for other purposes. | 220 // avoided as they are used for other purposes. |
| 203 // | 221 // |
| 204 // Any of w, x, or r can be NULL if they are not required. | 222 // Any of w, x, or r can be NULL if they are not required. |
| 205 // | 223 // |
| 206 // The return value is a RegList indicating which registers were allocated. | 224 // The return value is a RegList indicating which registers were allocated. |
| 207 RegList PopulateRegisterArray(Register* w, Register* x, Register* r, | 225 RegList PopulateRegisterArray(Register* w, Register* x, Register* r, |
| 208 int reg_size, int reg_count, RegList allowed); | 226 int reg_size, int reg_count, RegList allowed); |
| 209 | 227 |
| 210 // As PopulateRegisterArray, but for floating-point registers. | 228 // As PopulateRegisterArray, but for floating-point registers. |
| 211 RegList PopulateFPRegisterArray(FPRegister* s, FPRegister* d, FPRegister* v, | 229 RegList PopulateVRegisterArray(VRegister* s, VRegister* d, VRegister* v, |
| 212 int reg_size, int reg_count, RegList allowed); | 230 int reg_size, int reg_count, RegList allowed); |
| 213 | 231 |
| 214 // Ovewrite the contents of the specified registers. This enables tests to | 232 // Ovewrite the contents of the specified registers. This enables tests to |
| 215 // check that register contents are written in cases where it's likely that the | 233 // check that register contents are written in cases where it's likely that the |
| 216 // correct outcome could already be stored in the register. | 234 // correct outcome could already be stored in the register. |
| 217 // | 235 // |
| 218 // This always overwrites X-sized registers. If tests are operating on W | 236 // This always overwrites X-sized registers. If tests are operating on W |
| 219 // registers, a subsequent write into an aliased W register should clear the | 237 // registers, a subsequent write into an aliased W register should clear the |
| 220 // top word anyway, so clobbering the full X registers should make tests more | 238 // top word anyway, so clobbering the full X registers should make tests more |
| 221 // rigorous. | 239 // rigorous. |
| 222 void Clobber(MacroAssembler* masm, RegList reg_list, | 240 void Clobber(MacroAssembler* masm, RegList reg_list, |
| 223 uint64_t const value = 0xfedcba9876543210UL); | 241 uint64_t const value = 0xfedcba9876543210UL); |
| 224 | 242 |
| 225 // As Clobber, but for FP registers. | 243 // As Clobber, but for FP registers. |
| 226 void ClobberFP(MacroAssembler* masm, RegList reg_list, | 244 void ClobberFP(MacroAssembler* masm, RegList reg_list, |
| 227 double const value = kFP64SignallingNaN); | 245 double const value = kFP64SignallingNaN); |
| 228 | 246 |
| 229 // As Clobber, but for a CPURegList with either FP or integer registers. When | 247 // As Clobber, but for a CPURegList with either FP or integer registers. When |
| 230 // using this method, the clobber value is always the default for the basic | 248 // using this method, the clobber value is always the default for the basic |
| 231 // Clobber or ClobberFP functions. | 249 // Clobber or ClobberFP functions. |
| 232 void Clobber(MacroAssembler* masm, CPURegList reg_list); | 250 void Clobber(MacroAssembler* masm, CPURegList reg_list); |
| 233 | 251 |
| 234 } // namespace internal | 252 } // namespace internal |
| 235 } // namespace v8 | 253 } // namespace v8 |
| 236 | 254 |
| 237 #endif // V8_ARM64_TEST_UTILS_ARM64_H_ | 255 #endif // V8_ARM64_TEST_UTILS_ARM64_H_ |
| OLD | NEW |