OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_SIMULATOR_ARM64_H_ | 5 #ifndef V8_ARM64_SIMULATOR_ARM64_H_ |
6 #define V8_ARM64_SIMULATOR_ARM64_H_ | 6 #define V8_ARM64_SIMULATOR_ARM64_H_ |
7 | 7 |
8 #include <stdarg.h> | 8 #include <stdarg.h> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 | 205 |
206 // A wrapper class that stores an argument for one of the above Call | 206 // A wrapper class that stores an argument for one of the above Call |
207 // functions. | 207 // functions. |
208 // | 208 // |
209 // Only arguments up to 64 bits in size are supported. | 209 // Only arguments up to 64 bits in size are supported. |
210 class CallArgument { | 210 class CallArgument { |
211 public: | 211 public: |
212 template<typename T> | 212 template<typename T> |
213 explicit CallArgument(T argument) { | 213 explicit CallArgument(T argument) { |
214 bits_ = 0; | 214 bits_ = 0; |
215 ASSERT(sizeof(argument) <= sizeof(bits_)); | 215 DCHECK(sizeof(argument) <= sizeof(bits_)); |
216 memcpy(&bits_, &argument, sizeof(argument)); | 216 memcpy(&bits_, &argument, sizeof(argument)); |
217 type_ = X_ARG; | 217 type_ = X_ARG; |
218 } | 218 } |
219 | 219 |
220 explicit CallArgument(double argument) { | 220 explicit CallArgument(double argument) { |
221 ASSERT(sizeof(argument) == sizeof(bits_)); | 221 DCHECK(sizeof(argument) == sizeof(bits_)); |
222 memcpy(&bits_, &argument, sizeof(argument)); | 222 memcpy(&bits_, &argument, sizeof(argument)); |
223 type_ = D_ARG; | 223 type_ = D_ARG; |
224 } | 224 } |
225 | 225 |
226 explicit CallArgument(float argument) { | 226 explicit CallArgument(float argument) { |
227 // TODO(all): CallArgument(float) is untested, remove this check once | 227 // TODO(all): CallArgument(float) is untested, remove this check once |
228 // tested. | 228 // tested. |
229 UNIMPLEMENTED(); | 229 UNIMPLEMENTED(); |
230 // Make the D register a NaN to try to trap errors if the callee expects a | 230 // Make the D register a NaN to try to trap errors if the callee expects a |
231 // double. If it expects a float, the callee should ignore the top word. | 231 // double. If it expects a float, the callee should ignore the top word. |
232 ASSERT(sizeof(kFP64SignallingNaN) == sizeof(bits_)); | 232 DCHECK(sizeof(kFP64SignallingNaN) == sizeof(bits_)); |
233 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN)); | 233 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN)); |
234 // Write the float payload to the S register. | 234 // Write the float payload to the S register. |
235 ASSERT(sizeof(argument) <= sizeof(bits_)); | 235 DCHECK(sizeof(argument) <= sizeof(bits_)); |
236 memcpy(&bits_, &argument, sizeof(argument)); | 236 memcpy(&bits_, &argument, sizeof(argument)); |
237 type_ = D_ARG; | 237 type_ = D_ARG; |
238 } | 238 } |
239 | 239 |
240 // This indicates the end of the arguments list, so that CallArgument | 240 // This indicates the end of the arguments list, so that CallArgument |
241 // objects can be passed into varargs functions. | 241 // objects can be passed into varargs functions. |
242 static CallArgument End() { return CallArgument(); } | 242 static CallArgument End() { return CallArgument(); } |
243 | 243 |
244 int64_t bits() const { return bits_; } | 244 int64_t bits() const { return bits_; } |
245 bool IsEnd() const { return type_ == NO_ARG; } | 245 bool IsEnd() const { return type_ == NO_ARG; } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 | 283 |
284 // Run the simulator. | 284 // Run the simulator. |
285 static const Instruction* kEndOfSimAddress; | 285 static const Instruction* kEndOfSimAddress; |
286 void DecodeInstruction(); | 286 void DecodeInstruction(); |
287 void Run(); | 287 void Run(); |
288 void RunFrom(Instruction* start); | 288 void RunFrom(Instruction* start); |
289 | 289 |
290 // Simulation helpers. | 290 // Simulation helpers. |
291 template <typename T> | 291 template <typename T> |
292 void set_pc(T new_pc) { | 292 void set_pc(T new_pc) { |
293 ASSERT(sizeof(T) == sizeof(pc_)); | 293 DCHECK(sizeof(T) == sizeof(pc_)); |
294 memcpy(&pc_, &new_pc, sizeof(T)); | 294 memcpy(&pc_, &new_pc, sizeof(T)); |
295 pc_modified_ = true; | 295 pc_modified_ = true; |
296 } | 296 } |
297 Instruction* pc() { return pc_; } | 297 Instruction* pc() { return pc_; } |
298 | 298 |
299 void increment_pc() { | 299 void increment_pc() { |
300 if (!pc_modified_) { | 300 if (!pc_modified_) { |
301 pc_ = pc_->following(); | 301 pc_ = pc_->following(); |
302 } | 302 } |
303 | 303 |
304 pc_modified_ = false; | 304 pc_modified_ = false; |
305 } | 305 } |
306 | 306 |
307 virtual void Decode(Instruction* instr) { | 307 virtual void Decode(Instruction* instr) { |
308 decoder_->Decode(instr); | 308 decoder_->Decode(instr); |
309 } | 309 } |
310 | 310 |
311 void ExecuteInstruction() { | 311 void ExecuteInstruction() { |
312 ASSERT(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); | 312 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); |
313 CheckBreakNext(); | 313 CheckBreakNext(); |
314 Decode(pc_); | 314 Decode(pc_); |
315 LogProcessorState(); | 315 LogProcessorState(); |
316 increment_pc(); | 316 increment_pc(); |
317 CheckBreakpoints(); | 317 CheckBreakpoints(); |
318 } | 318 } |
319 | 319 |
320 // Declare all Visitor functions. | 320 // Declare all Visitor functions. |
321 #define DECLARE(A) void Visit##A(Instruction* instr); | 321 #define DECLARE(A) void Visit##A(Instruction* instr); |
322 VISITOR_LIST(DECLARE) | 322 VISITOR_LIST(DECLARE) |
323 #undef DECLARE | 323 #undef DECLARE |
324 | 324 |
325 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { | 325 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { |
326 return ((code == 31) && (r31mode == Reg31IsZeroRegister)); | 326 return ((code == 31) && (r31mode == Reg31IsZeroRegister)); |
327 } | 327 } |
328 | 328 |
329 // Register accessors. | 329 // Register accessors. |
330 // Return 'size' bits of the value of an integer register, as the specified | 330 // Return 'size' bits of the value of an integer register, as the specified |
331 // type. The value is zero-extended to fill the result. | 331 // type. The value is zero-extended to fill the result. |
332 // | 332 // |
333 template<typename T> | 333 template<typename T> |
334 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 334 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { |
335 ASSERT(code < kNumberOfRegisters); | 335 DCHECK(code < kNumberOfRegisters); |
336 if (IsZeroRegister(code, r31mode)) { | 336 if (IsZeroRegister(code, r31mode)) { |
337 return 0; | 337 return 0; |
338 } | 338 } |
339 return registers_[code].Get<T>(); | 339 return registers_[code].Get<T>(); |
340 } | 340 } |
341 | 341 |
342 // Common specialized accessors for the reg() template. | 342 // Common specialized accessors for the reg() template. |
343 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 343 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { |
344 return reg<int32_t>(code, r31mode); | 344 return reg<int32_t>(code, r31mode); |
345 } | 345 } |
346 | 346 |
347 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 347 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { |
348 return reg<int64_t>(code, r31mode); | 348 return reg<int64_t>(code, r31mode); |
349 } | 349 } |
350 | 350 |
351 // Write 'size' bits of 'value' into an integer register. The value is | 351 // Write 'size' bits of 'value' into an integer register. The value is |
352 // zero-extended. This behaviour matches AArch64 register writes. | 352 // zero-extended. This behaviour matches AArch64 register writes. |
353 | 353 |
354 // Like set_reg(), but infer the access size from the template type. | 354 // Like set_reg(), but infer the access size from the template type. |
355 template<typename T> | 355 template<typename T> |
356 void set_reg(unsigned code, T value, | 356 void set_reg(unsigned code, T value, |
357 Reg31Mode r31mode = Reg31IsZeroRegister) { | 357 Reg31Mode r31mode = Reg31IsZeroRegister) { |
358 ASSERT(code < kNumberOfRegisters); | 358 DCHECK(code < kNumberOfRegisters); |
359 if (!IsZeroRegister(code, r31mode)) | 359 if (!IsZeroRegister(code, r31mode)) |
360 registers_[code].Set(value); | 360 registers_[code].Set(value); |
361 } | 361 } |
362 | 362 |
363 // Common specialized accessors for the set_reg() template. | 363 // Common specialized accessors for the set_reg() template. |
364 void set_wreg(unsigned code, int32_t value, | 364 void set_wreg(unsigned code, int32_t value, |
365 Reg31Mode r31mode = Reg31IsZeroRegister) { | 365 Reg31Mode r31mode = Reg31IsZeroRegister) { |
366 set_reg(code, value, r31mode); | 366 set_reg(code, value, r31mode); |
367 } | 367 } |
368 | 368 |
369 void set_xreg(unsigned code, int64_t value, | 369 void set_xreg(unsigned code, int64_t value, |
370 Reg31Mode r31mode = Reg31IsZeroRegister) { | 370 Reg31Mode r31mode = Reg31IsZeroRegister) { |
371 set_reg(code, value, r31mode); | 371 set_reg(code, value, r31mode); |
372 } | 372 } |
373 | 373 |
374 // Commonly-used special cases. | 374 // Commonly-used special cases. |
375 template<typename T> | 375 template<typename T> |
376 void set_lr(T value) { | 376 void set_lr(T value) { |
377 ASSERT(sizeof(T) == kPointerSize); | 377 DCHECK(sizeof(T) == kPointerSize); |
378 set_reg(kLinkRegCode, value); | 378 set_reg(kLinkRegCode, value); |
379 } | 379 } |
380 | 380 |
381 template<typename T> | 381 template<typename T> |
382 void set_sp(T value) { | 382 void set_sp(T value) { |
383 ASSERT(sizeof(T) == kPointerSize); | 383 DCHECK(sizeof(T) == kPointerSize); |
384 set_reg(31, value, Reg31IsStackPointer); | 384 set_reg(31, value, Reg31IsStackPointer); |
385 } | 385 } |
386 | 386 |
387 int64_t sp() { return xreg(31, Reg31IsStackPointer); } | 387 int64_t sp() { return xreg(31, Reg31IsStackPointer); } |
388 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } | 388 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } |
389 int64_t fp() { | 389 int64_t fp() { |
390 return xreg(kFramePointerRegCode, Reg31IsStackPointer); | 390 return xreg(kFramePointerRegCode, Reg31IsStackPointer); |
391 } | 391 } |
392 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } | 392 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } |
393 | 393 |
394 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); } | 394 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); } |
395 | 395 |
396 template<typename T> | 396 template<typename T> |
397 T fpreg(unsigned code) const { | 397 T fpreg(unsigned code) const { |
398 ASSERT(code < kNumberOfRegisters); | 398 DCHECK(code < kNumberOfRegisters); |
399 return fpregisters_[code].Get<T>(); | 399 return fpregisters_[code].Get<T>(); |
400 } | 400 } |
401 | 401 |
402 // Common specialized accessors for the fpreg() template. | 402 // Common specialized accessors for the fpreg() template. |
403 float sreg(unsigned code) const { | 403 float sreg(unsigned code) const { |
404 return fpreg<float>(code); | 404 return fpreg<float>(code); |
405 } | 405 } |
406 | 406 |
407 uint32_t sreg_bits(unsigned code) const { | 407 uint32_t sreg_bits(unsigned code) const { |
408 return fpreg<uint32_t>(code); | 408 return fpreg<uint32_t>(code); |
(...skipping 14 matching lines...) Expand all Loading... |
423 default: | 423 default: |
424 UNREACHABLE(); | 424 UNREACHABLE(); |
425 return 0.0; | 425 return 0.0; |
426 } | 426 } |
427 } | 427 } |
428 | 428 |
429 // Write 'value' into a floating-point register. The value is zero-extended. | 429 // Write 'value' into a floating-point register. The value is zero-extended. |
430 // This behaviour matches AArch64 register writes. | 430 // This behaviour matches AArch64 register writes. |
431 template<typename T> | 431 template<typename T> |
432 void set_fpreg(unsigned code, T value) { | 432 void set_fpreg(unsigned code, T value) { |
433 ASSERT((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); | 433 DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); |
434 ASSERT(code < kNumberOfFPRegisters); | 434 DCHECK(code < kNumberOfFPRegisters); |
435 fpregisters_[code].Set(value); | 435 fpregisters_[code].Set(value); |
436 } | 436 } |
437 | 437 |
438 // Common specialized accessors for the set_fpreg() template. | 438 // Common specialized accessors for the set_fpreg() template. |
439 void set_sreg(unsigned code, float value) { | 439 void set_sreg(unsigned code, float value) { |
440 set_fpreg(code, value); | 440 set_fpreg(code, value); |
441 } | 441 } |
442 | 442 |
443 void set_sreg_bits(unsigned code, uint32_t value) { | 443 void set_sreg_bits(unsigned code, uint32_t value) { |
444 set_fpreg(code, value); | 444 set_fpreg(code, value); |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 SimSystemRegister fpcr_; | 737 SimSystemRegister fpcr_; |
738 | 738 |
739 // Only a subset of FPCR features are supported by the simulator. This helper | 739 // Only a subset of FPCR features are supported by the simulator. This helper |
740 // checks that the FPCR settings are supported. | 740 // checks that the FPCR settings are supported. |
741 // | 741 // |
742 // This is checked when floating-point instructions are executed, not when | 742 // This is checked when floating-point instructions are executed, not when |
743 // FPCR is set. This allows generated code to modify FPCR for external | 743 // FPCR is set. This allows generated code to modify FPCR for external |
744 // functions, or to save and restore it when entering and leaving generated | 744 // functions, or to save and restore it when entering and leaving generated |
745 // code. | 745 // code. |
746 void AssertSupportedFPCR() { | 746 void AssertSupportedFPCR() { |
747 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support. | 747 DCHECK(fpcr().FZ() == 0); // No flush-to-zero support. |
748 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. | 748 DCHECK(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. |
749 | 749 |
750 // The simulator does not support half-precision operations so fpcr().AHP() | 750 // The simulator does not support half-precision operations so fpcr().AHP() |
751 // is irrelevant, and is not checked here. | 751 // is irrelevant, and is not checked here. |
752 } | 752 } |
753 | 753 |
754 template <typename T> | 754 template <typename T> |
755 static int CalcNFlag(T result) { | 755 static int CalcNFlag(T result) { |
756 return (result >> (sizeof(T) * 8 - 1)) & 1; | 756 return (result >> (sizeof(T) * 8 - 1)) & 1; |
757 } | 757 } |
758 | 758 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 static void UnregisterCTryCatch() { | 829 static void UnregisterCTryCatch() { |
830 Simulator::current(Isolate::Current())->PopAddress(); | 830 Simulator::current(Isolate::Current())->PopAddress(); |
831 } | 831 } |
832 }; | 832 }; |
833 | 833 |
834 #endif // !defined(USE_SIMULATOR) | 834 #endif // !defined(USE_SIMULATOR) |
835 | 835 |
836 } } // namespace v8::internal | 836 } } // namespace v8::internal |
837 | 837 |
838 #endif // V8_ARM64_SIMULATOR_ARM64_H_ | 838 #endif // V8_ARM64_SIMULATOR_ARM64_H_ |
OLD | NEW |