Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: src/a64/simulator-a64.h

Issue 144963003: A64: add missing files. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/regexp-macro-assembler-a64.cc ('k') | src/a64/simulator-a64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_A64_SIMULATOR_A64_H_
29 #define V8_A64_SIMULATOR_A64_H_
30
31 #include <stdarg.h>
32 #include <vector>
33
34 #include "v8.h"
35
36 #include "globals.h"
37 #include "utils.h"
38 #include "allocation.h"
39 #include "assembler.h"
40 #include "a64/assembler-a64.h"
41 #include "a64/decoder-a64.h"
42 #include "a64/disasm-a64.h"
43 #include "a64/instrument-a64.h"
44
45 #define REGISTER_CODE_LIST(R) \
46 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
47 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
48 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
49 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
50
51 namespace v8 {
52 namespace internal {
53
54 #if !defined(USE_SIMULATOR)
55
56 // Running without a simulator on a native A64 platform.
57 // When running without a simulator we call the entry directly.
58 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
59 (entry(p0, p1, p2, p3, p4))
60
61 typedef int (*a64_regexp_matcher)(String* input,
62 int64_t start_offset,
63 const byte* input_start,
64 const byte* input_end,
65 int* output,
66 int64_t output_size,
67 Address stack_base,
68 int64_t direct_call,
69 void* return_address,
70 Isolate* isolate);
71
72 // Call the generated regexp code directly. The code at the entry address
73 // should act as a function matching the type a64_regexp_matcher.
74 // The ninth argument is a dummy that reserves the space used for
75 // the return address added by the ExitFrame in native calls.
76 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
77 (FUNCTION_CAST<a64_regexp_matcher>(entry)( \
78 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
79
80 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
81 reinterpret_cast<TryCatch*>(try_catch_address)
82
83 // Running without a simulator there is nothing to do.
84 class SimulatorStack : public v8::internal::AllStatic {
85 public:
86 static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
87 uintptr_t c_limit) {
88 USE(isolate);
89 return c_limit;
90 }
91
92 static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
93 return try_catch_address;
94 }
95
96 static inline void UnregisterCTryCatch() { }
97 };
98
99 #else // !defined(USE_SIMULATOR)
100
101 enum ReverseByteMode {
102 Reverse16 = 0,
103 Reverse32 = 1,
104 Reverse64 = 2
105 };
106
107
108 // The proper way to initialize a simulated system register (such as NZCV) is as
109 // follows:
110 // SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
111 class SimSystemRegister {
112 public:
113 // The default constructor represents a register which has no writable bits.
114 // It is not possible to set its value to anything other than 0.
115 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
116
117 inline uint32_t RawValue() const {
118 return value_;
119 }
120
121 inline void SetRawValue(uint32_t new_value) {
122 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
123 }
124
125 inline uint32_t Bits(int msb, int lsb) const {
126 return unsigned_bitextract_32(msb, lsb, value_);
127 }
128
129 inline int32_t SignedBits(int msb, int lsb) const {
130 return signed_bitextract_32(msb, lsb, value_);
131 }
132
133 void SetBits(int msb, int lsb, uint32_t bits);
134
135 // Default system register values.
136 static SimSystemRegister DefaultValueFor(SystemRegister id);
137
138 #define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
139 inline uint32_t Name() const { return Func(HighBit, LowBit); } \
140 inline void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
141 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
142 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
143
144 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
145
146 #undef DEFINE_ZERO_BITS
147 #undef DEFINE_GETTER
148
149 protected:
150 // Most system registers only implement a few of the bits in the word. Other
151 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
152 // describes the bits which are not modifiable.
153 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
154 : value_(value), write_ignore_mask_(write_ignore_mask) { }
155
156 uint32_t value_;
157 uint32_t write_ignore_mask_;
158 };
159
160
161 // Represent a register (r0-r31, v0-v31).
162 template<int kSizeInBytes>
163 class SimRegisterBase {
164 public:
165 template<typename T>
166 void Set(T new_value, unsigned size = sizeof(T)) {
167 ASSERT(size <= kSizeInBytes);
168 ASSERT(size <= sizeof(new_value));
169 // All AArch64 registers are zero-extending; Writing a W register clears the
170 // top bits of the corresponding X register.
171 memset(value_, 0, kSizeInBytes);
172 memcpy(value_, &new_value, size);
173 }
174
175 // Copy 'size' bytes of the register to the result, and zero-extend to fill
176 // the result.
177 template<typename T>
178 T Get(unsigned size = sizeof(T)) const {
179 ASSERT(size <= kSizeInBytes);
180 T result;
181 memset(&result, 0, sizeof(result));
182 memcpy(&result, value_, size);
183 return result;
184 }
185
186 protected:
187 uint8_t value_[kSizeInBytes];
188 };
189 typedef SimRegisterBase<kXRegSizeInBytes> SimRegister; // r0-r31
190 typedef SimRegisterBase<kDRegSizeInBytes> SimFPRegister; // v0-v31
191
192
193 class Simulator : public DecoderVisitor {
194 public:
195 explicit Simulator(Decoder* decoder,
196 Isolate* isolate = NULL,
197 FILE* stream = stdout);
198 ~Simulator();
199
200 // System functions.
201
202 static void Initialize(Isolate* isolate);
203
204 static Simulator* current(v8::internal::Isolate* isolate);
205
206 // Call an arbitrary function taking an arbitrary number of arguments. The
207 // varargs list must be a set of arguments with type CallArgument, and
208 // terminated by CallArgument::End().
209 void CallVoid(byte* entry, ...);
210 void CallVoid(byte* entry, va_list args);
211
212 // Like CallVoid, but expect a return value.
213 int64_t CallInt64(byte* entry, ...);
214 double CallDouble(byte* entry, ...);
215
216 // V8 calls into generated JS code with 5 parameters and into
217 // generated RegExp code with 10 parameters. These are convenience functions,
218 // which set up the simulator state and grab the result on return.
219 int64_t CallJS(byte* entry,
220 byte* function_entry,
221 JSFunction* func,
222 Object* revc,
223 int64_t argc,
224 Object*** argv);
225 int64_t CallRegExp(byte* entry,
226 String* input,
227 int64_t start_offset,
228 const byte* input_start,
229 const byte* input_end,
230 int* output,
231 int64_t output_size,
232 Address stack_base,
233 int64_t direct_call,
234 void* return_address,
235 Isolate* isolate);
236
237 // A wrapper class that stores an argument for one of the above Call
238 // functions.
239 //
240 // Only arguments up to 64 bits in size are supported.
241 class CallArgument {
242 public:
243 template<typename T>
244 explicit CallArgument(T argument) {
245 ASSERT(sizeof(argument) <= sizeof(bits_));
246 memcpy(&bits_, &argument, sizeof(argument));
247 type_ = X_ARG;
248 }
249
250 explicit CallArgument(double argument) {
251 ASSERT(sizeof(argument) == sizeof(bits_));
252 memcpy(&bits_, &argument, sizeof(argument));
253 type_ = D_ARG;
254 }
255
256 explicit CallArgument(float argument) {
257 TODO_UNIMPLEMENTED("CallArgument(float) is untested.");
258 // Make the D register a NaN to try to trap errors if the callee expects a
259 // double. If it expects a float, the callee should ignore the top word.
260 ASSERT(sizeof(kFP64SignallingNaN) == sizeof(bits_));
261 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
262 // Write the float payload to the S register.
263 ASSERT(sizeof(argument) <= sizeof(bits_));
264 memcpy(&bits_, &argument, sizeof(argument));
265 type_ = D_ARG;
266 }
267
268 // This indicates the end of the arguments list, so that CallArgument
269 // objects can be passed into varargs functions.
270 static CallArgument End() { return CallArgument(); }
271
272 int64_t bits() const { return bits_; }
273 bool IsEnd() const { return type_ == NO_ARG; }
274 bool IsX() const { return type_ == X_ARG; }
275 bool IsD() const { return type_ == D_ARG; }
276
277 private:
278 enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
279
280 // All arguments are aligned to at least 64 bits and we don't support
281 // passing bigger arguments, so the payload size can be fixed at 64 bits.
282 int64_t bits_;
283 CallArgumentType type_;
284
285 CallArgument() { type_ = NO_ARG; }
286 };
287
288
289 // Start the debugging command line.
290 void Debug();
291
292 bool GetValue(const char* desc, int64_t* value);
293
294 bool PrintValue(const char* desc);
295
296 // Push an address onto the JS stack.
297 uintptr_t PushAddress(uintptr_t address);
298
299 // Pop an address from the JS stack.
300 uintptr_t PopAddress();
301
302 // Accessor to the internal simulator stack area.
303 uintptr_t StackLimit() const;
304
305 void ResetState();
306
307 // Runtime call support.
308 static void* RedirectExternalReference(void* external_function,
309 ExternalReference::Type type);
310
311 // Run the simulator.
312 static const Instruction* kEndOfSimAddress;
313 void DecodeInstruction();
314 void Run();
315 void RunFrom(Instruction* start);
316
317 // Simulation helpers.
318 template <typename T>
319 inline void set_pc(T new_pc) {
320 ASSERT(sizeof(T) == sizeof(pc_));
321 memcpy(&pc_, &new_pc, sizeof(T));
322 pc_modified_ = true;
323 }
324 inline Instruction* pc() { return pc_; }
325
326 inline void increment_pc() {
327 if (!pc_modified_) {
328 pc_ = pc_->NextInstruction();
329 }
330
331 pc_modified_ = false;
332 }
333
334 inline void ExecuteInstruction() {
335 ASSERT(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
336 CheckBreakNext();
337 decoder_->Decode(pc_);
338 LogProcessorState();
339 increment_pc();
340 CheckBreakpoints();
341 }
342
343 // Declare all Visitor functions.
344 #define DECLARE(A) void Visit##A(Instruction* instr);
345 VISITOR_LIST(DECLARE)
346 #undef DECLARE
347
348 // Register accessors.
349
350 // Return 'size' bits of the value of an integer register, as the specified
351 // type. The value is zero-extended to fill the result.
352 //
353 // The only supported values of 'size' are kXRegSize and kWRegSize.
354 template<typename T>
355 inline T reg(unsigned size, unsigned code,
356 Reg31Mode r31mode = Reg31IsZeroRegister) const {
357 unsigned size_in_bytes = size / 8;
358 ASSERT(size_in_bytes <= sizeof(T));
359 ASSERT((size == kXRegSize) || (size == kWRegSize));
360 ASSERT(code < kNumberOfRegisters);
361
362 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
363 T result;
364 memset(&result, 0, sizeof(result));
365 return result;
366 }
367 return registers_[code].Get<T>(size_in_bytes);
368 }
369
370 // Like reg(), but infer the access size from the template type.
371 template<typename T>
372 inline T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
373 return reg<T>(sizeof(T) * 8, code, r31mode);
374 }
375
376 // Common specialized accessors for the reg() template.
377 inline int32_t wreg(unsigned code,
378 Reg31Mode r31mode = Reg31IsZeroRegister) const {
379 return reg<int32_t>(code, r31mode);
380 }
381
382 inline int64_t xreg(unsigned code,
383 Reg31Mode r31mode = Reg31IsZeroRegister) const {
384 return reg<int64_t>(code, r31mode);
385 }
386
387 inline int64_t reg(unsigned size, unsigned code,
388 Reg31Mode r31mode = Reg31IsZeroRegister) const {
389 return reg<int64_t>(size, code, r31mode);
390 }
391
392 // Write 'size' bits of 'value' into an integer register. The value is
393 // zero-extended. This behaviour matches AArch64 register writes.
394 //
395 // The only supported values of 'size' are kXRegSize and kWRegSize.
396 template<typename T>
397 inline void set_reg(unsigned size, unsigned code, T value,
398 Reg31Mode r31mode = Reg31IsZeroRegister) {
399 unsigned size_in_bytes = size / 8;
400 ASSERT(size_in_bytes <= sizeof(T));
401 ASSERT((size == kXRegSize) || (size == kWRegSize));
402 ASSERT(code < kNumberOfRegisters);
403
404 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
405 return;
406 }
407 return registers_[code].Set(value, size_in_bytes);
408 }
409
410 // Like set_reg(), but infer the access size from the template type.
411 template<typename T>
412 inline void set_reg(unsigned code, T value,
413 Reg31Mode r31mode = Reg31IsZeroRegister) {
414 set_reg(sizeof(value) * 8, code, value, r31mode);
415 }
416
417 // Common specialized accessors for the set_reg() template.
418 inline void set_wreg(unsigned code, int32_t value,
419 Reg31Mode r31mode = Reg31IsZeroRegister) {
420 set_reg(kWRegSize, code, value, r31mode);
421 }
422
423 inline void set_xreg(unsigned code, int64_t value,
424 Reg31Mode r31mode = Reg31IsZeroRegister) {
425 set_reg(kXRegSize, code, value, r31mode);
426 }
427
428 // Commonly-used special cases.
429 template<typename T>
430 inline void set_lr(T value) {
431 ASSERT(sizeof(T) == kPointerSize);
432 set_reg(kLinkRegCode, value);
433 }
434
435 template<typename T>
436 inline void set_sp(T value) {
437 ASSERT(sizeof(T) == kPointerSize);
438 set_reg(31, value, Reg31IsStackPointer);
439 }
440
441 inline int64_t sp() { return xreg(31, Reg31IsStackPointer); }
442 inline int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
443 inline Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
444
445 // Return 'size' bits of the value of a floating-point register, as the
446 // specified type. The value is zero-extended to fill the result.
447 //
448 // The only supported values of 'size' are kDRegSize and kSRegSize.
449 template<typename T>
450 inline T fpreg(unsigned size, unsigned code) const {
451 unsigned size_in_bytes = size / 8;
452 ASSERT(size_in_bytes <= sizeof(T));
453 ASSERT((size == kDRegSize) || (size == kSRegSize));
454 ASSERT(code < kNumberOfFPRegisters);
455 return fpregisters_[code].Get<T>(size_in_bytes);
456 }
457
458 // Like fpreg(), but infer the access size from the template type.
459 template<typename T>
460 inline T fpreg(unsigned code) const {
461 return fpreg<T>(sizeof(T) * 8, code);
462 }
463
464 // Common specialized accessors for the fpreg() template.
465 inline float sreg(unsigned code) const {
466 return fpreg<float>(code);
467 }
468
469 inline uint32_t sreg_bits(unsigned code) const {
470 return fpreg<uint32_t>(code);
471 }
472
473 inline double dreg(unsigned code) const {
474 return fpreg<double>(code);
475 }
476
477 inline uint64_t dreg_bits(unsigned code) const {
478 return fpreg<uint64_t>(code);
479 }
480
481 inline double fpreg(unsigned size, unsigned code) const {
482 switch (size) {
483 case kSRegSize: return sreg(code);
484 case kDRegSize: return dreg(code);
485 default:
486 UNREACHABLE();
487 return 0.0;
488 }
489 }
490
491 // Write 'value' into a floating-point register. The value is zero-extended.
492 // This behaviour matches AArch64 register writes.
493 template<typename T>
494 inline void set_fpreg(unsigned code, T value) {
495 ASSERT((sizeof(value) == kDRegSizeInBytes) ||
496 (sizeof(value) == kSRegSizeInBytes));
497 ASSERT(code < kNumberOfFPRegisters);
498 fpregisters_[code].Set(value, sizeof(value));
499 }
500
501 // Common specialized accessors for the set_fpreg() template.
502 inline void set_sreg(unsigned code, float value) {
503 set_fpreg(code, value);
504 }
505
506 inline void set_sreg_bits(unsigned code, uint32_t value) {
507 set_fpreg(code, value);
508 }
509
510 inline void set_dreg(unsigned code, double value) {
511 set_fpreg(code, value);
512 }
513
514 inline void set_dreg_bits(unsigned code, uint64_t value) {
515 set_fpreg(code, value);
516 }
517
518 bool N() { return nzcv_.N() != 0; }
519 bool Z() { return nzcv_.Z() != 0; }
520 bool C() { return nzcv_.C() != 0; }
521 bool V() { return nzcv_.V() != 0; }
522 SimSystemRegister& nzcv() { return nzcv_; }
523
524 // TODO(jbramley): Find a way to make the fpcr_ members return the proper
525 // types, so this accessor is not necessary.
526 FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
527 SimSystemRegister& fpcr() { return fpcr_; }
528
529 // Debug helpers
530
531 // Simulator breakpoints.
532 struct Breakpoint {
533 Instruction* location;
534 bool enabled;
535 };
536 std::vector<Breakpoint> breakpoints_;
537 void SetBreakpoint(Instruction* breakpoint);
538 void ListBreakpoints();
539 void CheckBreakpoints();
540
541 // Helpers for the 'next' command.
542 // When this is set, the Simulator will insert a breakpoint after the next BL
543 // instruction it meets.
544 bool break_on_next_;
545 // Check if the Simulator should insert a break after the current instruction
546 // for the 'next' command.
547 void CheckBreakNext();
548
549 // Disassemble instruction at the given address.
550 void PrintInstructionsAt(Instruction* pc, uint64_t count);
551
552 void PrintSystemRegisters(bool print_all = false);
553 void PrintRegisters(bool print_all_regs = false);
554 void PrintFPRegisters(bool print_all_regs = false);
555 void PrintProcessorState();
556 void PrintWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
557 inline void LogSystemRegisters() {
558 if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters();
559 }
560 inline void LogRegisters() {
561 if (log_parameters_ & LOG_REGS) PrintRegisters();
562 }
563 inline void LogFPRegisters() {
564 if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters();
565 }
566 inline void LogProcessorState() {
567 LogSystemRegisters();
568 LogRegisters();
569 LogFPRegisters();
570 }
571 void LogWrite(uint8_t* address, uint64_t value, unsigned num_bytes) {
572 if (log_parameters_ & LOG_WRITE) PrintWrite(address, value, num_bytes);
573 }
574
575 inline int log_parameters() { return log_parameters_; }
576 void set_log_parameters(int new_parameters) {
577 if (new_parameters & LOG_DISASM) {
578 decoder_->InsertVisitorBefore(print_disasm_, this);
579 } else {
580 decoder_->RemoveVisitor(print_disasm_);
581 }
582 log_parameters_ = new_parameters;
583 }
584
585 static inline const char* WRegNameForCode(unsigned code,
586 Reg31Mode mode = Reg31IsZeroRegister);
587 static inline const char* XRegNameForCode(unsigned code,
588 Reg31Mode mode = Reg31IsZeroRegister);
589 static inline const char* SRegNameForCode(unsigned code);
590 static inline const char* DRegNameForCode(unsigned code);
591 static inline const char* VRegNameForCode(unsigned code);
592 static inline int CodeFromName(const char* name);
593
594 protected:
595 // Simulation helpers ------------------------------------
596 bool ConditionPassed(Condition cond) {
597 switch (cond) {
598 case eq:
599 return Z();
600 case ne:
601 return !Z();
602 case hs:
603 return C();
604 case lo:
605 return !C();
606 case mi:
607 return N();
608 case pl:
609 return !N();
610 case vs:
611 return V();
612 case vc:
613 return !V();
614 case hi:
615 return C() && !Z();
616 case ls:
617 return !(C() && !Z());
618 case ge:
619 return N() == V();
620 case lt:
621 return N() != V();
622 case gt:
623 return !Z() && (N() == V());
624 case le:
625 return !(!Z() && (N() == V()));
626 case nv: // Fall through.
627 case al:
628 return true;
629 default:
630 UNREACHABLE();
631 return false;
632 }
633 }
634
635 bool ConditionFailed(Condition cond) {
636 return !ConditionPassed(cond);
637 }
638
639 void AddSubHelper(Instruction* instr, int64_t op2);
640 int64_t AddWithCarry(unsigned reg_size,
641 bool set_flags,
642 int64_t src1,
643 int64_t src2,
644 int64_t carry_in = 0);
645 void LogicalHelper(Instruction* instr, int64_t op2);
646 void ConditionalCompareHelper(Instruction* instr, int64_t op2);
647 void LoadStoreHelper(Instruction* instr,
648 int64_t offset,
649 AddrMode addrmode);
650 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
651 uint8_t* AddressModeHelper(unsigned addr_reg,
652 int64_t offset,
653 AddrMode addrmode);
654
655 uint64_t MemoryRead(uint8_t* address, unsigned num_bytes);
656 uint8_t MemoryRead8(uint8_t* address);
657 uint16_t MemoryRead16(uint8_t* address);
658 uint32_t MemoryRead32(uint8_t* address);
659 float MemoryReadFP32(uint8_t* address);
660 uint64_t MemoryRead64(uint8_t* address);
661 double MemoryReadFP64(uint8_t* address);
662
663 void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
664 void MemoryWrite32(uint8_t* address, uint32_t value);
665 void MemoryWriteFP32(uint8_t* address, float value);
666 void MemoryWrite64(uint8_t* address, uint64_t value);
667 void MemoryWriteFP64(uint8_t* address, double value);
668
669 int64_t ShiftOperand(unsigned reg_size,
670 int64_t value,
671 Shift shift_type,
672 unsigned amount);
673 int64_t Rotate(unsigned reg_width,
674 int64_t value,
675 Shift shift_type,
676 unsigned amount);
677 int64_t ExtendValue(unsigned reg_width,
678 int64_t value,
679 Extend extend_type,
680 unsigned left_shift = 0);
681
682 uint64_t ReverseBits(uint64_t value, unsigned num_bits);
683 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
684
685 void FPCompare(double val0, double val1);
686 double FPRoundInt(double value, FPRounding round_mode);
687 double FPToDouble(float value);
688 float FPToFloat(double value, FPRounding round_mode);
689 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
690 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
691 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
692 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
693 int32_t FPToInt32(double value, FPRounding rmode);
694 int64_t FPToInt64(double value, FPRounding rmode);
695 uint32_t FPToUInt32(double value, FPRounding rmode);
696 uint64_t FPToUInt64(double value, FPRounding rmode);
697
698 template <typename T>
699 T FPMax(T a, T b);
700
701 template <typename T>
702 T FPMin(T a, T b);
703
704 template <typename T>
705 T FPMaxNM(T a, T b);
706
707 template <typename T>
708 T FPMinNM(T a, T b);
709
710 void CheckStackAlignment();
711
712 inline void CheckPCSComplianceAndRun();
713
714 #ifdef DEBUG
715 // Corruption values should have their least significant byte cleared to
716 // allow the code of the register being corrupted to be inserted.
717 static const uint64_t kCallerSavedRegisterCorruptionValue =
718 0xca11edc0de000000UL;
719 // This value is a NaN in both 32-bit and 64-bit FP.
720 static const uint64_t kCallerSavedFPRegisterCorruptionValue =
721 0x7ff000007f801000UL;
722 // This value is a mix of 32/64-bits NaN and "verbose" immediate.
723 static const uint64_t kDefaultCPURegisterCorruptionValue =
724 0x7ffbad007f8bad00UL;
725
726 void CorruptRegisters(CPURegList* list,
727 uint64_t value = kDefaultCPURegisterCorruptionValue);
728 void CorruptAllCallerSavedCPURegisters();
729 #endif
730
731 // Processor state ---------------------------------------
732
733 // Output stream.
734 FILE* stream_;
735 PrintDisassembler* print_disasm_;
736
737 // Instrumentation.
738 Instrument* instrument_;
739
740 // General purpose registers. Register 31 is the stack pointer.
741 SimRegister registers_[kNumberOfRegisters];
742
743 // Floating point registers
744 SimFPRegister fpregisters_[kNumberOfFPRegisters];
745
746 // Processor state
747 // bits[31, 27]: Condition flags N, Z, C, and V.
748 // (Negative, Zero, Carry, Overflow)
749 SimSystemRegister nzcv_;
750
751 // Floating-Point Control Register
752 SimSystemRegister fpcr_;
753
754 // Only a subset of FPCR features are supported by the simulator. This helper
755 // checks that the FPCR settings are supported.
756 //
757 // This is checked when floating-point instructions are executed, not when
758 // FPCR is set. This allows generated code to modify FPCR for external
759 // functions, or to save and restore it when entering and leaving generated
760 // code.
761 void AssertSupportedFPCR() {
762 ASSERT(fpcr().DN() == 0); // No default-NaN support.
763 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support.
764 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
765
766 // The simulator does not support half-precision operations so fpcr().AHP()
767 // is irrelevant, and is not checked here.
768 }
769
770 static inline int CalcNFlag(uint64_t result, unsigned reg_size) {
771 return (result >> (reg_size - 1)) & 1;
772 }
773
774 static inline int CalcZFlag(uint64_t result) {
775 return result == 0;
776 }
777
778 static const uint32_t kConditionFlagsMask = 0xf0000000;
779
780 // Stack
781 byte* stack_;
782 static const intptr_t stack_protection_size_ = KB;
783 intptr_t stack_size_;
784 byte* stack_limit_;
785 // TODO(aleram): protect the stack.
786
787 Decoder* decoder_;
788 Decoder* disassembler_decoder_;
789
790 // Indicates if the pc has been modified by the instruction and should not be
791 // automatically incremented.
792 bool pc_modified_;
793 Instruction* pc_;
794
795 static const char* xreg_names[];
796 static const char* wreg_names[];
797 static const char* sreg_names[];
798 static const char* dreg_names[];
799 static const char* vreg_names[];
800
801 // Debugger input.
802 void set_last_debugger_input(char* input) {
803 DeleteArray(last_debugger_input_);
804 last_debugger_input_ = input;
805 }
806 char* last_debugger_input() { return last_debugger_input_; }
807 char* last_debugger_input_;
808
809 private:
810 int log_parameters_;
811 Isolate* isolate_;
812 };
813
814
815 // When running with the simulator transition into simulated execution at this
816 // point.
817 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
818 reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS( \
819 FUNCTION_ADDR(entry), \
820 p0, p1, p2, p3, p4))
821
822 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
823 Simulator::current(Isolate::Current())->CallRegExp( \
824 entry, \
825 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
826
827 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
828 try_catch_address == NULL ? \
829 NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
830
831
832 // The simulator has its own stack. Thus it has a different stack limit from
833 // the C-based native code.
834 // See also 'class SimulatorStack' in arm/simulator-arm.h.
835 class SimulatorStack : public v8::internal::AllStatic {
836 public:
837 static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
838 uintptr_t c_limit) {
839 return Simulator::current(isolate)->StackLimit();
840 }
841
842 static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
843 Simulator* sim = Simulator::current(Isolate::Current());
844 return sim->PushAddress(try_catch_address);
845 }
846
847 static inline void UnregisterCTryCatch() {
848 Simulator::current(Isolate::Current())->PopAddress();
849 }
850 };
851
852 #endif // !defined(USE_SIMULATOR)
853
854 } } // namespace v8::internal
855
856 #endif // V8_A64_SIMULATOR_A64_H_
OLDNEW
« no previous file with comments | « src/a64/regexp-macro-assembler-a64.cc ('k') | src/a64/simulator-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698