blob: 586f204be503eb8a782693335b4a3d5465a08b8a [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#ifndef V8_ARM64_SIMULATOR_ARM64_H_
6#define V8_ARM64_SIMULATOR_ARM64_H_
7
8#include <stdarg.h>
9#include <vector>
10
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/allocation.h"
12#include "src/arm64/assembler-arm64.h"
13#include "src/arm64/decoder-arm64.h"
14#include "src/arm64/disasm-arm64.h"
15#include "src/arm64/instrument-arm64.h"
16#include "src/assembler.h"
Ben Murdochc5610432016-08-08 18:44:38 +010017#include "src/base/compiler-specific.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/globals.h"
19#include "src/utils.h"
20
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021namespace v8 {
22namespace internal {
23
24#if !defined(USE_SIMULATOR)
25
26// Running without a simulator on a native ARM64 platform.
27// When running without a simulator we call the entry directly.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029 (entry(p0, p1, p2, p3, p4))
30
31typedef int (*arm64_regexp_matcher)(String* input,
32 int64_t start_offset,
33 const byte* input_start,
34 const byte* input_end,
35 int* output,
36 int64_t output_size,
37 Address stack_base,
38 int64_t direct_call,
39 void* return_address,
40 Isolate* isolate);
41
42// Call the generated regexp code directly. The code at the entry address
43// should act as a function matching the type arm64_regexp_matcher.
44// The ninth argument is a dummy that reserves the space used for
45// the return address added by the ExitFrame in native calls.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
47 p7, p8) \
48 (FUNCTION_CAST<arm64_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, \
49 NULL, p8))
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050
51// Running without a simulator there is nothing to do.
52class SimulatorStack : public v8::internal::AllStatic {
53 public:
54 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 uintptr_t c_limit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 USE(isolate);
57 return c_limit;
58 }
59
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 static uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate,
61 uintptr_t try_catch_address) {
62 USE(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 return try_catch_address;
64 }
65
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 static void UnregisterCTryCatch(v8::internal::Isolate* isolate) {
67 USE(isolate);
68 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069};
70
71#else // !defined(USE_SIMULATOR)
72
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073
74// The proper way to initialize a simulated system register (such as NZCV) is as
75// follows:
76// SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
77class SimSystemRegister {
78 public:
79 // The default constructor represents a register which has no writable bits.
80 // It is not possible to set its value to anything other than 0.
81 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
82
83 uint32_t RawValue() const {
84 return value_;
85 }
86
87 void SetRawValue(uint32_t new_value) {
88 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
89 }
90
91 uint32_t Bits(int msb, int lsb) const {
92 return unsigned_bitextract_32(msb, lsb, value_);
93 }
94
95 int32_t SignedBits(int msb, int lsb) const {
96 return signed_bitextract_32(msb, lsb, value_);
97 }
98
99 void SetBits(int msb, int lsb, uint32_t bits);
100
101 // Default system register values.
102 static SimSystemRegister DefaultValueFor(SystemRegister id);
103
104#define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type) \
105 Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); } \
106 void Set##Name(Type bits) { \
107 SetBits(HighBit, LowBit, static_cast<Type>(bits)); \
108 }
109#define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
110 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
111 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
112#undef DEFINE_ZERO_BITS
113#undef DEFINE_GETTER
114
115 protected:
116 // Most system registers only implement a few of the bits in the word. Other
117 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
118 // describes the bits which are not modifiable.
119 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
120 : value_(value), write_ignore_mask_(write_ignore_mask) { }
121
122 uint32_t value_;
123 uint32_t write_ignore_mask_;
124};
125
126
127// Represent a register (r0-r31, v0-v31).
128class SimRegisterBase {
129 public:
130 template<typename T>
131 void Set(T new_value) {
132 value_ = 0;
133 memcpy(&value_, &new_value, sizeof(T));
134 }
135
136 template<typename T>
137 T Get() const {
138 T result;
139 memcpy(&result, &value_, sizeof(T));
140 return result;
141 }
142
143 protected:
144 int64_t value_;
145};
146
147
148typedef SimRegisterBase SimRegister; // r0-r31
149typedef SimRegisterBase SimFPRegister; // v0-v31
150
151
152class Simulator : public DecoderVisitor {
153 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 static void FlushICache(v8::internal::HashMap* i_cache, void* start,
155 size_t size) {
156 USE(i_cache);
157 USE(start);
158 USE(size);
159 }
160
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
162 Isolate* isolate = NULL,
163 FILE* stream = stderr);
164 Simulator();
165 ~Simulator();
166
167 // System functions.
168
169 static void Initialize(Isolate* isolate);
170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 static void TearDown(HashMap* i_cache, Redirection* first);
172
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 static Simulator* current(v8::internal::Isolate* isolate);
174
175 class CallArgument;
176
177 // Call an arbitrary function taking an arbitrary number of arguments. The
178 // varargs list must be a set of arguments with type CallArgument, and
179 // terminated by CallArgument::End().
180 void CallVoid(byte* entry, CallArgument* args);
181
182 // Like CallVoid, but expect a return value.
183 int64_t CallInt64(byte* entry, CallArgument* args);
184 double CallDouble(byte* entry, CallArgument* args);
185
186 // V8 calls into generated JS code with 5 parameters and into
187 // generated RegExp code with 10 parameters. These are convenience functions,
188 // which set up the simulator state and grab the result on return.
189 int64_t CallJS(byte* entry,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000190 Object* new_target,
191 Object* target,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 Object* revc,
193 int64_t argc,
194 Object*** argv);
195 int64_t CallRegExp(byte* entry,
196 String* input,
197 int64_t start_offset,
198 const byte* input_start,
199 const byte* input_end,
200 int* output,
201 int64_t output_size,
202 Address stack_base,
203 int64_t direct_call,
204 void* return_address,
205 Isolate* isolate);
206
207 // A wrapper class that stores an argument for one of the above Call
208 // functions.
209 //
210 // Only arguments up to 64 bits in size are supported.
211 class CallArgument {
212 public:
213 template<typename T>
214 explicit CallArgument(T argument) {
215 bits_ = 0;
216 DCHECK(sizeof(argument) <= sizeof(bits_));
217 memcpy(&bits_, &argument, sizeof(argument));
218 type_ = X_ARG;
219 }
220
221 explicit CallArgument(double argument) {
222 DCHECK(sizeof(argument) == sizeof(bits_));
223 memcpy(&bits_, &argument, sizeof(argument));
224 type_ = D_ARG;
225 }
226
227 explicit CallArgument(float argument) {
228 // TODO(all): CallArgument(float) is untested, remove this check once
229 // tested.
230 UNIMPLEMENTED();
231 // Make the D register a NaN to try to trap errors if the callee expects a
232 // double. If it expects a float, the callee should ignore the top word.
233 DCHECK(sizeof(kFP64SignallingNaN) == sizeof(bits_));
234 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
235 // Write the float payload to the S register.
236 DCHECK(sizeof(argument) <= sizeof(bits_));
237 memcpy(&bits_, &argument, sizeof(argument));
238 type_ = D_ARG;
239 }
240
241 // This indicates the end of the arguments list, so that CallArgument
242 // objects can be passed into varargs functions.
243 static CallArgument End() { return CallArgument(); }
244
245 int64_t bits() const { return bits_; }
246 bool IsEnd() const { return type_ == NO_ARG; }
247 bool IsX() const { return type_ == X_ARG; }
248 bool IsD() const { return type_ == D_ARG; }
249
250 private:
251 enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
252
253 // All arguments are aligned to at least 64 bits and we don't support
254 // passing bigger arguments, so the payload size can be fixed at 64 bits.
255 int64_t bits_;
256 CallArgumentType type_;
257
258 CallArgument() { type_ = NO_ARG; }
259 };
260
261
262 // Start the debugging command line.
263 void Debug();
264
265 bool GetValue(const char* desc, int64_t* value);
266
267 bool PrintValue(const char* desc);
268
269 // Push an address onto the JS stack.
270 uintptr_t PushAddress(uintptr_t address);
271
272 // Pop an address from the JS stack.
273 uintptr_t PopAddress();
274
275 // Accessor to the internal simulator stack area.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 uintptr_t StackLimit(uintptr_t c_limit) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277
278 void ResetState();
279
280 // Runtime call support.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 static void* RedirectExternalReference(Isolate* isolate,
282 void* external_function,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 ExternalReference::Type type);
284 void DoRuntimeCall(Instruction* instr);
285
286 // Run the simulator.
287 static const Instruction* kEndOfSimAddress;
288 void DecodeInstruction();
289 void Run();
290 void RunFrom(Instruction* start);
291
292 // Simulation helpers.
293 template <typename T>
294 void set_pc(T new_pc) {
295 DCHECK(sizeof(T) == sizeof(pc_));
296 memcpy(&pc_, &new_pc, sizeof(T));
297 pc_modified_ = true;
298 }
299 Instruction* pc() { return pc_; }
300
301 void increment_pc() {
302 if (!pc_modified_) {
303 pc_ = pc_->following();
304 }
305
306 pc_modified_ = false;
307 }
308
309 virtual void Decode(Instruction* instr) {
310 decoder_->Decode(instr);
311 }
312
313 void ExecuteInstruction() {
314 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
315 CheckBreakNext();
316 Decode(pc_);
317 increment_pc();
318 CheckBreakpoints();
319 }
320
321 // Declare all Visitor functions.
322 #define DECLARE(A) void Visit##A(Instruction* instr);
323 VISITOR_LIST(DECLARE)
324 #undef DECLARE
325
326 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const {
327 return ((code == 31) && (r31mode == Reg31IsZeroRegister));
328 }
329
330 // Register accessors.
331 // Return 'size' bits of the value of an integer register, as the specified
332 // type. The value is zero-extended to fill the result.
333 //
334 template<typename T>
335 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
336 DCHECK(code < kNumberOfRegisters);
337 if (IsZeroRegister(code, r31mode)) {
338 return 0;
339 }
340 return registers_[code].Get<T>();
341 }
342
343 // Common specialized accessors for the reg() template.
344 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
345 return reg<int32_t>(code, r31mode);
346 }
347
348 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
349 return reg<int64_t>(code, r31mode);
350 }
351
352 // Write 'value' into an integer register. The value is zero-extended. This
353 // behaviour matches AArch64 register writes.
354 template<typename T>
355 void set_reg(unsigned code, T value,
356 Reg31Mode r31mode = Reg31IsZeroRegister) {
357 set_reg_no_log(code, value, r31mode);
358 LogRegister(code, r31mode);
359 }
360
361 // Common specialized accessors for the set_reg() template.
362 void set_wreg(unsigned code, int32_t value,
363 Reg31Mode r31mode = Reg31IsZeroRegister) {
364 set_reg(code, value, r31mode);
365 }
366
367 void set_xreg(unsigned code, int64_t value,
368 Reg31Mode r31mode = Reg31IsZeroRegister) {
369 set_reg(code, value, r31mode);
370 }
371
372 // As above, but don't automatically log the register update.
373 template <typename T>
374 void set_reg_no_log(unsigned code, T value,
375 Reg31Mode r31mode = Reg31IsZeroRegister) {
376 DCHECK(code < kNumberOfRegisters);
377 if (!IsZeroRegister(code, r31mode)) {
378 registers_[code].Set(value);
379 }
380 }
381
382 void set_wreg_no_log(unsigned code, int32_t value,
383 Reg31Mode r31mode = Reg31IsZeroRegister) {
384 set_reg_no_log(code, value, r31mode);
385 }
386
387 void set_xreg_no_log(unsigned code, int64_t value,
388 Reg31Mode r31mode = Reg31IsZeroRegister) {
389 set_reg_no_log(code, value, r31mode);
390 }
391
392 // Commonly-used special cases.
393 template<typename T>
394 void set_lr(T value) {
395 DCHECK(sizeof(T) == kPointerSize);
396 set_reg(kLinkRegCode, value);
397 }
398
399 template<typename T>
400 void set_sp(T value) {
401 DCHECK(sizeof(T) == kPointerSize);
402 set_reg(31, value, Reg31IsStackPointer);
403 }
404
405 int64_t sp() { return xreg(31, Reg31IsStackPointer); }
406 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
407 int64_t fp() {
408 return xreg(kFramePointerRegCode, Reg31IsStackPointer);
409 }
410 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 Address get_sp() const { return reg<Address>(31, Reg31IsStackPointer); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413
414 template<typename T>
415 T fpreg(unsigned code) const {
416 DCHECK(code < kNumberOfRegisters);
417 return fpregisters_[code].Get<T>();
418 }
419
420 // Common specialized accessors for the fpreg() template.
421 float sreg(unsigned code) const {
422 return fpreg<float>(code);
423 }
424
425 uint32_t sreg_bits(unsigned code) const {
426 return fpreg<uint32_t>(code);
427 }
428
429 double dreg(unsigned code) const {
430 return fpreg<double>(code);
431 }
432
433 uint64_t dreg_bits(unsigned code) const {
434 return fpreg<uint64_t>(code);
435 }
436
437 double fpreg(unsigned size, unsigned code) const {
438 switch (size) {
439 case kSRegSizeInBits: return sreg(code);
440 case kDRegSizeInBits: return dreg(code);
441 default:
442 UNREACHABLE();
443 return 0.0;
444 }
445 }
446
447 // Write 'value' into a floating-point register. The value is zero-extended.
448 // This behaviour matches AArch64 register writes.
449 template<typename T>
450 void set_fpreg(unsigned code, T value) {
451 set_fpreg_no_log(code, value);
452
453 if (sizeof(value) <= kSRegSize) {
454 LogFPRegister(code, kPrintSRegValue);
455 } else {
456 LogFPRegister(code, kPrintDRegValue);
457 }
458 }
459
460 // Common specialized accessors for the set_fpreg() template.
461 void set_sreg(unsigned code, float value) {
462 set_fpreg(code, value);
463 }
464
465 void set_sreg_bits(unsigned code, uint32_t value) {
466 set_fpreg(code, value);
467 }
468
469 void set_dreg(unsigned code, double value) {
470 set_fpreg(code, value);
471 }
472
473 void set_dreg_bits(unsigned code, uint64_t value) {
474 set_fpreg(code, value);
475 }
476
477 // As above, but don't automatically log the register update.
478 template <typename T>
479 void set_fpreg_no_log(unsigned code, T value) {
480 DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
481 DCHECK(code < kNumberOfFPRegisters);
482 fpregisters_[code].Set(value);
483 }
484
485 void set_sreg_no_log(unsigned code, float value) {
486 set_fpreg_no_log(code, value);
487 }
488
489 void set_dreg_no_log(unsigned code, double value) {
490 set_fpreg_no_log(code, value);
491 }
492
493 SimSystemRegister& nzcv() { return nzcv_; }
494 SimSystemRegister& fpcr() { return fpcr_; }
495
496 // Debug helpers
497
498 // Simulator breakpoints.
499 struct Breakpoint {
500 Instruction* location;
501 bool enabled;
502 };
503 std::vector<Breakpoint> breakpoints_;
504 void SetBreakpoint(Instruction* breakpoint);
505 void ListBreakpoints();
506 void CheckBreakpoints();
507
508 // Helpers for the 'next' command.
509 // When this is set, the Simulator will insert a breakpoint after the next BL
510 // instruction it meets.
511 bool break_on_next_;
512 // Check if the Simulator should insert a break after the current instruction
513 // for the 'next' command.
514 void CheckBreakNext();
515
516 // Disassemble instruction at the given address.
517 void PrintInstructionsAt(Instruction* pc, uint64_t count);
518
519 // Print all registers of the specified types.
520 void PrintRegisters();
521 void PrintFPRegisters();
522 void PrintSystemRegisters();
523
524 // Like Print* (above), but respect log_parameters().
525 void LogSystemRegisters() {
526 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters();
527 }
528 void LogRegisters() {
529 if (log_parameters() & LOG_REGS) PrintRegisters();
530 }
531 void LogFPRegisters() {
532 if (log_parameters() & LOG_FP_REGS) PrintFPRegisters();
533 }
534
535 // Specify relevant register sizes, for PrintFPRegister.
536 //
537 // These values are bit masks; they can be combined in case multiple views of
538 // a machine register are interesting.
539 enum PrintFPRegisterSizes {
540 kPrintDRegValue = 1 << kDRegSize,
541 kPrintSRegValue = 1 << kSRegSize,
542 kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue
543 };
544
545 // Print individual register values (after update).
546 void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
547 void PrintFPRegister(unsigned code,
548 PrintFPRegisterSizes sizes = kPrintAllFPRegValues);
549 void PrintSystemRegister(SystemRegister id);
550
551 // Like Print* (above), but respect log_parameters().
552 void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
553 if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode);
554 }
555 void LogFPRegister(unsigned code,
556 PrintFPRegisterSizes sizes = kPrintAllFPRegValues) {
557 if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes);
558 }
559 void LogSystemRegister(SystemRegister id) {
560 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id);
561 }
562
563 // Print memory accesses.
564 void PrintRead(uintptr_t address, size_t size, unsigned reg_code);
565 void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code);
566 void PrintWrite(uintptr_t address, size_t size, unsigned reg_code);
567 void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code);
568
569 // Like Print* (above), but respect log_parameters().
570 void LogRead(uintptr_t address, size_t size, unsigned reg_code) {
571 if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code);
572 }
573 void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) {
574 if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code);
575 }
576 void LogWrite(uintptr_t address, size_t size, unsigned reg_code) {
577 if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code);
578 }
579 void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) {
580 if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code);
581 }
582
583 int log_parameters() { return log_parameters_; }
584 void set_log_parameters(int new_parameters) {
585 log_parameters_ = new_parameters;
586 if (!decoder_) {
587 if (new_parameters & LOG_DISASM) {
588 PrintF("Run --debug-sim to dynamically turn on disassembler\n");
589 }
590 return;
591 }
592 if (new_parameters & LOG_DISASM) {
593 decoder_->InsertVisitorBefore(print_disasm_, this);
594 } else {
595 decoder_->RemoveVisitor(print_disasm_);
596 }
597 }
598
599 static inline const char* WRegNameForCode(unsigned code,
600 Reg31Mode mode = Reg31IsZeroRegister);
601 static inline const char* XRegNameForCode(unsigned code,
602 Reg31Mode mode = Reg31IsZeroRegister);
603 static inline const char* SRegNameForCode(unsigned code);
604 static inline const char* DRegNameForCode(unsigned code);
605 static inline const char* VRegNameForCode(unsigned code);
606 static inline int CodeFromName(const char* name);
607
608 protected:
609 // Simulation helpers ------------------------------------
610 bool ConditionPassed(Condition cond) {
611 SimSystemRegister& flags = nzcv();
612 switch (cond) {
613 case eq:
614 return flags.Z();
615 case ne:
616 return !flags.Z();
617 case hs:
618 return flags.C();
619 case lo:
620 return !flags.C();
621 case mi:
622 return flags.N();
623 case pl:
624 return !flags.N();
625 case vs:
626 return flags.V();
627 case vc:
628 return !flags.V();
629 case hi:
630 return flags.C() && !flags.Z();
631 case ls:
632 return !(flags.C() && !flags.Z());
633 case ge:
634 return flags.N() == flags.V();
635 case lt:
636 return flags.N() != flags.V();
637 case gt:
638 return !flags.Z() && (flags.N() == flags.V());
639 case le:
640 return !(!flags.Z() && (flags.N() == flags.V()));
641 case nv: // Fall through.
642 case al:
643 return true;
644 default:
645 UNREACHABLE();
646 return false;
647 }
648 }
649
650 bool ConditionFailed(Condition cond) {
651 return !ConditionPassed(cond);
652 }
653
654 template<typename T>
655 void AddSubHelper(Instruction* instr, T op2);
656 template<typename T>
657 T AddWithCarry(bool set_flags,
658 T src1,
659 T src2,
660 T carry_in = 0);
661 template<typename T>
662 void AddSubWithCarry(Instruction* instr);
663 template<typename T>
664 void LogicalHelper(Instruction* instr, T op2);
665 template<typename T>
666 void ConditionalCompareHelper(Instruction* instr, T op2);
667 void LoadStoreHelper(Instruction* instr,
668 int64_t offset,
669 AddrMode addrmode);
670 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
671 uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset,
672 AddrMode addrmode);
673 void LoadStoreWriteBack(unsigned addr_reg,
674 int64_t offset,
675 AddrMode addrmode);
676 void CheckMemoryAccess(uintptr_t address, uintptr_t stack);
677
678 // Memory read helpers.
679 template <typename T, typename A>
680 T MemoryRead(A address) {
681 T value;
682 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
683 (sizeof(value) == 4) || (sizeof(value) == 8));
684 memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
685 return value;
686 }
687
688 // Memory write helpers.
689 template <typename T, typename A>
690 void MemoryWrite(A address, T value) {
691 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
692 (sizeof(value) == 4) || (sizeof(value) == 8));
693 memcpy(reinterpret_cast<void*>(address), &value, sizeof(value));
694 }
695
696 template <typename T>
697 T ShiftOperand(T value,
698 Shift shift_type,
699 unsigned amount);
700 template <typename T>
701 T ExtendValue(T value,
702 Extend extend_type,
703 unsigned left_shift = 0);
704 template <typename T>
705 void Extract(Instruction* instr);
706 template <typename T>
707 void DataProcessing2Source(Instruction* instr);
708 template <typename T>
709 void BitfieldHelper(Instruction* instr);
710
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711 template <typename T>
712 T FPDefaultNaN() const;
713
714 void FPCompare(double val0, double val1);
715 double FPRoundInt(double value, FPRounding round_mode);
716 double FPToDouble(float value);
717 float FPToFloat(double value, FPRounding round_mode);
718 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
719 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
720 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
721 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
722 int32_t FPToInt32(double value, FPRounding rmode);
723 int64_t FPToInt64(double value, FPRounding rmode);
724 uint32_t FPToUInt32(double value, FPRounding rmode);
725 uint64_t FPToUInt64(double value, FPRounding rmode);
726
727 template <typename T>
728 T FPAdd(T op1, T op2);
729
730 template <typename T>
731 T FPDiv(T op1, T op2);
732
733 template <typename T>
734 T FPMax(T a, T b);
735
736 template <typename T>
737 T FPMaxNM(T a, T b);
738
739 template <typename T>
740 T FPMin(T a, T b);
741
742 template <typename T>
743 T FPMinNM(T a, T b);
744
745 template <typename T>
746 T FPMul(T op1, T op2);
747
748 template <typename T>
749 T FPMulAdd(T a, T op1, T op2);
750
751 template <typename T>
752 T FPSqrt(T op);
753
754 template <typename T>
755 T FPSub(T op1, T op2);
756
757 // Standard NaN processing.
758 template <typename T>
759 T FPProcessNaN(T op);
760
761 bool FPProcessNaNs(Instruction* instr);
762
763 template <typename T>
764 T FPProcessNaNs(T op1, T op2);
765
766 template <typename T>
767 T FPProcessNaNs3(T op1, T op2, T op3);
768
769 void CheckStackAlignment();
770
771 inline void CheckPCSComplianceAndRun();
772
773#ifdef DEBUG
774 // Corruption values should have their least significant byte cleared to
775 // allow the code of the register being corrupted to be inserted.
776 static const uint64_t kCallerSavedRegisterCorruptionValue =
777 0xca11edc0de000000UL;
778 // This value is a NaN in both 32-bit and 64-bit FP.
779 static const uint64_t kCallerSavedFPRegisterCorruptionValue =
780 0x7ff000007f801000UL;
781 // This value is a mix of 32/64-bits NaN and "verbose" immediate.
782 static const uint64_t kDefaultCPURegisterCorruptionValue =
783 0x7ffbad007f8bad00UL;
784
785 void CorruptRegisters(CPURegList* list,
786 uint64_t value = kDefaultCPURegisterCorruptionValue);
787 void CorruptAllCallerSavedCPURegisters();
788#endif
789
790 // Pseudo Printf instruction
791 void DoPrintf(Instruction* instr);
792
793 // Processor state ---------------------------------------
794
795 // Output stream.
796 FILE* stream_;
797 PrintDisassembler* print_disasm_;
Ben Murdochc5610432016-08-08 18:44:38 +0100798 void PRINTF_FORMAT(2, 3) TraceSim(const char* format, ...);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799
800 // Instrumentation.
801 Instrument* instrument_;
802
803 // General purpose registers. Register 31 is the stack pointer.
804 SimRegister registers_[kNumberOfRegisters];
805
806 // Floating point registers
807 SimFPRegister fpregisters_[kNumberOfFPRegisters];
808
809 // Processor state
810 // bits[31, 27]: Condition flags N, Z, C, and V.
811 // (Negative, Zero, Carry, Overflow)
812 SimSystemRegister nzcv_;
813
814 // Floating-Point Control Register
815 SimSystemRegister fpcr_;
816
817 // Only a subset of FPCR features are supported by the simulator. This helper
818 // checks that the FPCR settings are supported.
819 //
820 // This is checked when floating-point instructions are executed, not when
821 // FPCR is set. This allows generated code to modify FPCR for external
822 // functions, or to save and restore it when entering and leaving generated
823 // code.
824 void AssertSupportedFPCR() {
825 DCHECK(fpcr().FZ() == 0); // No flush-to-zero support.
826 DCHECK(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
827
828 // The simulator does not support half-precision operations so fpcr().AHP()
829 // is irrelevant, and is not checked here.
830 }
831
832 template <typename T>
833 static int CalcNFlag(T result) {
834 return (result >> (sizeof(T) * 8 - 1)) & 1;
835 }
836
837 static int CalcZFlag(uint64_t result) {
838 return result == 0;
839 }
840
841 static const uint32_t kConditionFlagsMask = 0xf0000000;
842
843 // Stack
844 uintptr_t stack_;
845 static const size_t stack_protection_size_ = KB;
846 size_t stack_size_;
847 uintptr_t stack_limit_;
848
849 Decoder<DispatchingDecoderVisitor>* decoder_;
850 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_;
851
852 // Indicates if the pc has been modified by the instruction and should not be
853 // automatically incremented.
854 bool pc_modified_;
855 Instruction* pc_;
856
857 static const char* xreg_names[];
858 static const char* wreg_names[];
859 static const char* sreg_names[];
860 static const char* dreg_names[];
861 static const char* vreg_names[];
862
863 // Debugger input.
864 void set_last_debugger_input(char* input) {
865 DeleteArray(last_debugger_input_);
866 last_debugger_input_ = input;
867 }
868 char* last_debugger_input() { return last_debugger_input_; }
869 char* last_debugger_input_;
870
871 private:
872 void Init(FILE* stream);
873
874 int log_parameters_;
875 Isolate* isolate_;
876};
877
878
879// When running with the simulator transition into simulated execution at this
880// point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
882 reinterpret_cast<Object*>(Simulator::current(isolate)->CallJS( \
883 FUNCTION_ADDR(entry), p0, p1, p2, p3, p4))
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
886 p7, p8) \
887 static_cast<int>(Simulator::current(isolate)->CallRegExp( \
888 entry, p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889
890
891// The simulator has its own stack. Thus it has a different stack limit from
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892// the C-based native code. The JS-based limit normally points near the end of
893// the simulator stack. When the C-based limit is exhausted we reflect that by
894// lowering the JS-based limit as well, to make stack checks trigger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895class SimulatorStack : public v8::internal::AllStatic {
896 public:
897 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
898 uintptr_t c_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 return Simulator::current(isolate)->StackLimit(c_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900 }
901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 static uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate,
903 uintptr_t try_catch_address) {
904 Simulator* sim = Simulator::current(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 return sim->PushAddress(try_catch_address);
906 }
907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908 static void UnregisterCTryCatch(v8::internal::Isolate* isolate) {
909 Simulator::current(isolate)->PopAddress();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 }
911};
912
913#endif // !defined(USE_SIMULATOR)
914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915} // namespace internal
916} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917
918#endif // V8_ARM64_SIMULATOR_ARM64_H_