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