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

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

Issue 181453002: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 6 years, 10 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 uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
87 uintptr_t c_limit) {
88 USE(isolate);
89 return c_limit;
90 }
91
92 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
93 return try_catch_address;
94 }
95
96 static 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 uint32_t RawValue() const {
118 return value_;
119 }
120
121 void SetRawValue(uint32_t new_value) {
122 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
123 }
124
125 uint32_t Bits(int msb, int lsb) const {
126 return unsigned_bitextract_32(msb, lsb, value_);
127 }
128
129 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 uint32_t Name() const { return Func(HighBit, LowBit); } \
140 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 = stderr);
198 ~Simulator();
199
200 // System functions.
201
202 static void Initialize(Isolate* isolate);
203
204 static Simulator* current(v8::internal::Isolate* isolate);
205
206 class CallArgument;
207
208 // Call an arbitrary function taking an arbitrary number of arguments. The
209 // varargs list must be a set of arguments with type CallArgument, and
210 // terminated by CallArgument::End().
211 void CallVoid(byte* entry, CallArgument* args);
212
213 // Like CallVoid, but expect a return value.
214 int64_t CallInt64(byte* entry, CallArgument* args);
215 double CallDouble(byte* entry, CallArgument* args);
216
217 // V8 calls into generated JS code with 5 parameters and into
218 // generated RegExp code with 10 parameters. These are convenience functions,
219 // which set up the simulator state and grab the result on return.
220 int64_t CallJS(byte* entry,
221 byte* function_entry,
222 JSFunction* func,
223 Object* revc,
224 int64_t argc,
225 Object*** argv);
226 int64_t CallRegExp(byte* entry,
227 String* input,
228 int64_t start_offset,
229 const byte* input_start,
230 const byte* input_end,
231 int* output,
232 int64_t output_size,
233 Address stack_base,
234 int64_t direct_call,
235 void* return_address,
236 Isolate* isolate);
237
238 // A wrapper class that stores an argument for one of the above Call
239 // functions.
240 //
241 // Only arguments up to 64 bits in size are supported.
242 class CallArgument {
243 public:
244 template<typename T>
245 explicit CallArgument(T argument) {
246 ASSERT(sizeof(argument) <= sizeof(bits_));
247 memcpy(&bits_, &argument, sizeof(argument));
248 type_ = X_ARG;
249 }
250
251 explicit CallArgument(double argument) {
252 ASSERT(sizeof(argument) == sizeof(bits_));
253 memcpy(&bits_, &argument, sizeof(argument));
254 type_ = D_ARG;
255 }
256
257 explicit CallArgument(float argument) {
258 // TODO(all): CallArgument(float) is untested, remove this check once
259 // tested.
260 UNIMPLEMENTED();
261 // Make the D register a NaN to try to trap errors if the callee expects a
262 // double. If it expects a float, the callee should ignore the top word.
263 ASSERT(sizeof(kFP64SignallingNaN) == sizeof(bits_));
264 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
265 // Write the float payload to the S register.
266 ASSERT(sizeof(argument) <= sizeof(bits_));
267 memcpy(&bits_, &argument, sizeof(argument));
268 type_ = D_ARG;
269 }
270
271 // This indicates the end of the arguments list, so that CallArgument
272 // objects can be passed into varargs functions.
273 static CallArgument End() { return CallArgument(); }
274
275 int64_t bits() const { return bits_; }
276 bool IsEnd() const { return type_ == NO_ARG; }
277 bool IsX() const { return type_ == X_ARG; }
278 bool IsD() const { return type_ == D_ARG; }
279
280 private:
281 enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
282
283 // All arguments are aligned to at least 64 bits and we don't support
284 // passing bigger arguments, so the payload size can be fixed at 64 bits.
285 int64_t bits_;
286 CallArgumentType type_;
287
288 CallArgument() { type_ = NO_ARG; }
289 };
290
291
292 // Start the debugging command line.
293 void Debug();
294
295 bool GetValue(const char* desc, int64_t* value);
296
297 bool PrintValue(const char* desc);
298
299 // Push an address onto the JS stack.
300 uintptr_t PushAddress(uintptr_t address);
301
302 // Pop an address from the JS stack.
303 uintptr_t PopAddress();
304
305 // Accessor to the internal simulator stack area.
306 uintptr_t StackLimit() const;
307
308 void ResetState();
309
310 // Runtime call support.
311 static void* RedirectExternalReference(void* external_function,
312 ExternalReference::Type type);
313
314 // Run the simulator.
315 static const Instruction* kEndOfSimAddress;
316 void DecodeInstruction();
317 void Run();
318 void RunFrom(Instruction* start);
319
320 // Simulation helpers.
321 template <typename T>
322 void set_pc(T new_pc) {
323 ASSERT(sizeof(T) == sizeof(pc_));
324 memcpy(&pc_, &new_pc, sizeof(T));
325 pc_modified_ = true;
326 }
327 Instruction* pc() { return pc_; }
328
329 void increment_pc() {
330 if (!pc_modified_) {
331 pc_ = pc_->NextInstruction();
332 }
333
334 pc_modified_ = false;
335 }
336
337 void ExecuteInstruction() {
338 ASSERT(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
339 CheckBreakNext();
340 decoder_->Decode(pc_);
341 LogProcessorState();
342 increment_pc();
343 CheckBreakpoints();
344 }
345
346 // Declare all Visitor functions.
347 #define DECLARE(A) void Visit##A(Instruction* instr);
348 VISITOR_LIST(DECLARE)
349 #undef DECLARE
350
351 // Register accessors.
352
353 // Return 'size' bits of the value of an integer register, as the specified
354 // type. The value is zero-extended to fill the result.
355 //
356 // The only supported values of 'size' are kXRegSize and kWRegSize.
357 template<typename T>
358 T reg(unsigned size, unsigned code,
359 Reg31Mode r31mode = Reg31IsZeroRegister) const {
360 unsigned size_in_bytes = size / 8;
361 ASSERT(size_in_bytes <= sizeof(T));
362 ASSERT((size == kXRegSize) || (size == kWRegSize));
363 ASSERT(code < kNumberOfRegisters);
364
365 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
366 T result;
367 memset(&result, 0, sizeof(result));
368 return result;
369 }
370 return registers_[code].Get<T>(size_in_bytes);
371 }
372
373 // Like reg(), but infer the access size from the template type.
374 template<typename T>
375 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
376 return reg<T>(sizeof(T) * 8, code, r31mode);
377 }
378
379 // Common specialized accessors for the reg() template.
380 int32_t wreg(unsigned code,
381 Reg31Mode r31mode = Reg31IsZeroRegister) const {
382 return reg<int32_t>(code, r31mode);
383 }
384
385 int64_t xreg(unsigned code,
386 Reg31Mode r31mode = Reg31IsZeroRegister) const {
387 return reg<int64_t>(code, r31mode);
388 }
389
390 int64_t reg(unsigned size, unsigned code,
391 Reg31Mode r31mode = Reg31IsZeroRegister) const {
392 return reg<int64_t>(size, code, r31mode);
393 }
394
395 // Write 'size' bits of 'value' into an integer register. The value is
396 // zero-extended. This behaviour matches AArch64 register writes.
397 //
398 // The only supported values of 'size' are kXRegSize and kWRegSize.
399 template<typename T>
400 void set_reg(unsigned size, unsigned code, T value,
401 Reg31Mode r31mode = Reg31IsZeroRegister) {
402 unsigned size_in_bytes = size / 8;
403 ASSERT(size_in_bytes <= sizeof(T));
404 ASSERT((size == kXRegSize) || (size == kWRegSize));
405 ASSERT(code < kNumberOfRegisters);
406
407 if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
408 return;
409 }
410 return registers_[code].Set(value, size_in_bytes);
411 }
412
413 // Like set_reg(), but infer the access size from the template type.
414 template<typename T>
415 void set_reg(unsigned code, T value,
416 Reg31Mode r31mode = Reg31IsZeroRegister) {
417 set_reg(sizeof(value) * 8, code, value, r31mode);
418 }
419
420 // Common specialized accessors for the set_reg() template.
421 void set_wreg(unsigned code, int32_t value,
422 Reg31Mode r31mode = Reg31IsZeroRegister) {
423 set_reg(kWRegSize, code, value, r31mode);
424 }
425
426 void set_xreg(unsigned code, int64_t value,
427 Reg31Mode r31mode = Reg31IsZeroRegister) {
428 set_reg(kXRegSize, code, value, r31mode);
429 }
430
431 // Commonly-used special cases.
432 template<typename T>
433 void set_lr(T value) {
434 ASSERT(sizeof(T) == kPointerSize);
435 set_reg(kLinkRegCode, value);
436 }
437
438 template<typename T>
439 void set_sp(T value) {
440 ASSERT(sizeof(T) == kPointerSize);
441 set_reg(31, value, Reg31IsStackPointer);
442 }
443
444 int64_t sp() { return xreg(31, Reg31IsStackPointer); }
445 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
446 int64_t fp() {
447 return xreg(kFramePointerRegCode, Reg31IsStackPointer);
448 }
449 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
450
451 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); }
452
453 // Return 'size' bits of the value of a floating-point register, as the
454 // specified type. The value is zero-extended to fill the result.
455 //
456 // The only supported values of 'size' are kDRegSize and kSRegSize.
457 template<typename T>
458 T fpreg(unsigned size, unsigned code) const {
459 unsigned size_in_bytes = size / 8;
460 ASSERT(size_in_bytes <= sizeof(T));
461 ASSERT((size == kDRegSize) || (size == kSRegSize));
462 ASSERT(code < kNumberOfFPRegisters);
463 return fpregisters_[code].Get<T>(size_in_bytes);
464 }
465
466 // Like fpreg(), but infer the access size from the template type.
467 template<typename T>
468 T fpreg(unsigned code) const {
469 return fpreg<T>(sizeof(T) * 8, code);
470 }
471
472 // Common specialized accessors for the fpreg() template.
473 float sreg(unsigned code) const {
474 return fpreg<float>(code);
475 }
476
477 uint32_t sreg_bits(unsigned code) const {
478 return fpreg<uint32_t>(code);
479 }
480
481 double dreg(unsigned code) const {
482 return fpreg<double>(code);
483 }
484
485 uint64_t dreg_bits(unsigned code) const {
486 return fpreg<uint64_t>(code);
487 }
488
489 double fpreg(unsigned size, unsigned code) const {
490 switch (size) {
491 case kSRegSize: return sreg(code);
492 case kDRegSize: return dreg(code);
493 default:
494 UNREACHABLE();
495 return 0.0;
496 }
497 }
498
499 // Write 'value' into a floating-point register. The value is zero-extended.
500 // This behaviour matches AArch64 register writes.
501 template<typename T>
502 void set_fpreg(unsigned code, T value) {
503 ASSERT((sizeof(value) == kDRegSizeInBytes) ||
504 (sizeof(value) == kSRegSizeInBytes));
505 ASSERT(code < kNumberOfFPRegisters);
506 fpregisters_[code].Set(value, sizeof(value));
507 }
508
509 // Common specialized accessors for the set_fpreg() template.
510 void set_sreg(unsigned code, float value) {
511 set_fpreg(code, value);
512 }
513
514 void set_sreg_bits(unsigned code, uint32_t value) {
515 set_fpreg(code, value);
516 }
517
518 void set_dreg(unsigned code, double value) {
519 set_fpreg(code, value);
520 }
521
522 void set_dreg_bits(unsigned code, uint64_t value) {
523 set_fpreg(code, value);
524 }
525
526 bool N() { return nzcv_.N() != 0; }
527 bool Z() { return nzcv_.Z() != 0; }
528 bool C() { return nzcv_.C() != 0; }
529 bool V() { return nzcv_.V() != 0; }
530 SimSystemRegister& nzcv() { return nzcv_; }
531
532 // TODO(jbramley): Find a way to make the fpcr_ members return the proper
533 // types, so this accessor is not necessary.
534 FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
535 SimSystemRegister& fpcr() { return fpcr_; }
536
537 // Debug helpers
538
539 // Simulator breakpoints.
540 struct Breakpoint {
541 Instruction* location;
542 bool enabled;
543 };
544 std::vector<Breakpoint> breakpoints_;
545 void SetBreakpoint(Instruction* breakpoint);
546 void ListBreakpoints();
547 void CheckBreakpoints();
548
549 // Helpers for the 'next' command.
550 // When this is set, the Simulator will insert a breakpoint after the next BL
551 // instruction it meets.
552 bool break_on_next_;
553 // Check if the Simulator should insert a break after the current instruction
554 // for the 'next' command.
555 void CheckBreakNext();
556
557 // Disassemble instruction at the given address.
558 void PrintInstructionsAt(Instruction* pc, uint64_t count);
559
560 void PrintSystemRegisters(bool print_all = false);
561 void PrintRegisters(bool print_all_regs = false);
562 void PrintFPRegisters(bool print_all_regs = false);
563 void PrintProcessorState();
564 void PrintWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
565 void LogSystemRegisters() {
566 if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters();
567 }
568 void LogRegisters() {
569 if (log_parameters_ & LOG_REGS) PrintRegisters();
570 }
571 void LogFPRegisters() {
572 if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters();
573 }
574 void LogProcessorState() {
575 LogSystemRegisters();
576 LogRegisters();
577 LogFPRegisters();
578 }
579 void LogWrite(uint8_t* address, uint64_t value, unsigned num_bytes) {
580 if (log_parameters_ & LOG_WRITE) PrintWrite(address, value, num_bytes);
581 }
582
583 int log_parameters() { return log_parameters_; }
584 void set_log_parameters(int new_parameters) {
585 if (new_parameters & LOG_DISASM) {
586 decoder_->InsertVisitorBefore(print_disasm_, this);
587 } else {
588 decoder_->RemoveVisitor(print_disasm_);
589 }
590 log_parameters_ = new_parameters;
591 }
592
593 static inline const char* WRegNameForCode(unsigned code,
594 Reg31Mode mode = Reg31IsZeroRegister);
595 static inline const char* XRegNameForCode(unsigned code,
596 Reg31Mode mode = Reg31IsZeroRegister);
597 static inline const char* SRegNameForCode(unsigned code);
598 static inline const char* DRegNameForCode(unsigned code);
599 static inline const char* VRegNameForCode(unsigned code);
600 static inline int CodeFromName(const char* name);
601
602 protected:
603 // Simulation helpers ------------------------------------
604 bool ConditionPassed(Condition cond) {
605 switch (cond) {
606 case eq:
607 return Z();
608 case ne:
609 return !Z();
610 case hs:
611 return C();
612 case lo:
613 return !C();
614 case mi:
615 return N();
616 case pl:
617 return !N();
618 case vs:
619 return V();
620 case vc:
621 return !V();
622 case hi:
623 return C() && !Z();
624 case ls:
625 return !(C() && !Z());
626 case ge:
627 return N() == V();
628 case lt:
629 return N() != V();
630 case gt:
631 return !Z() && (N() == V());
632 case le:
633 return !(!Z() && (N() == V()));
634 case nv: // Fall through.
635 case al:
636 return true;
637 default:
638 UNREACHABLE();
639 return false;
640 }
641 }
642
643 bool ConditionFailed(Condition cond) {
644 return !ConditionPassed(cond);
645 }
646
647 void AddSubHelper(Instruction* instr, int64_t op2);
648 int64_t AddWithCarry(unsigned reg_size,
649 bool set_flags,
650 int64_t src1,
651 int64_t src2,
652 int64_t carry_in = 0);
653 void LogicalHelper(Instruction* instr, int64_t op2);
654 void ConditionalCompareHelper(Instruction* instr, int64_t op2);
655 void LoadStoreHelper(Instruction* instr,
656 int64_t offset,
657 AddrMode addrmode);
658 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
659 uint8_t* LoadStoreAddress(unsigned addr_reg,
660 int64_t offset,
661 AddrMode addrmode);
662 void LoadStoreWriteBack(unsigned addr_reg,
663 int64_t offset,
664 AddrMode addrmode);
665 void CheckMemoryAccess(uint8_t* address, uint8_t* stack);
666
667 uint64_t MemoryRead(uint8_t* address, unsigned num_bytes);
668 uint8_t MemoryRead8(uint8_t* address);
669 uint16_t MemoryRead16(uint8_t* address);
670 uint32_t MemoryRead32(uint8_t* address);
671 float MemoryReadFP32(uint8_t* address);
672 uint64_t MemoryRead64(uint8_t* address);
673 double MemoryReadFP64(uint8_t* address);
674
675 void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
676 void MemoryWrite32(uint8_t* address, uint32_t value);
677 void MemoryWriteFP32(uint8_t* address, float value);
678 void MemoryWrite64(uint8_t* address, uint64_t value);
679 void MemoryWriteFP64(uint8_t* address, double value);
680
681 int64_t ShiftOperand(unsigned reg_size,
682 int64_t value,
683 Shift shift_type,
684 unsigned amount);
685 int64_t Rotate(unsigned reg_width,
686 int64_t value,
687 Shift shift_type,
688 unsigned amount);
689 int64_t ExtendValue(unsigned reg_width,
690 int64_t value,
691 Extend extend_type,
692 unsigned left_shift = 0);
693
694 uint64_t ReverseBits(uint64_t value, unsigned num_bits);
695 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
696
697 void FPCompare(double val0, double val1);
698 double FPRoundInt(double value, FPRounding round_mode);
699 double FPToDouble(float value);
700 float FPToFloat(double value, FPRounding round_mode);
701 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
702 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
703 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
704 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
705 int32_t FPToInt32(double value, FPRounding rmode);
706 int64_t FPToInt64(double value, FPRounding rmode);
707 uint32_t FPToUInt32(double value, FPRounding rmode);
708 uint64_t FPToUInt64(double value, FPRounding rmode);
709
710 template <typename T>
711 T FPMax(T a, T b);
712
713 template <typename T>
714 T FPMin(T a, T b);
715
716 template <typename T>
717 T FPMaxNM(T a, T b);
718
719 template <typename T>
720 T FPMinNM(T a, T b);
721
722 void CheckStackAlignment();
723
724 inline void CheckPCSComplianceAndRun();
725
726 #ifdef DEBUG
727 // Corruption values should have their least significant byte cleared to
728 // allow the code of the register being corrupted to be inserted.
729 static const uint64_t kCallerSavedRegisterCorruptionValue =
730 0xca11edc0de000000UL;
731 // This value is a NaN in both 32-bit and 64-bit FP.
732 static const uint64_t kCallerSavedFPRegisterCorruptionValue =
733 0x7ff000007f801000UL;
734 // This value is a mix of 32/64-bits NaN and "verbose" immediate.
735 static const uint64_t kDefaultCPURegisterCorruptionValue =
736 0x7ffbad007f8bad00UL;
737
738 void CorruptRegisters(CPURegList* list,
739 uint64_t value = kDefaultCPURegisterCorruptionValue);
740 void CorruptAllCallerSavedCPURegisters();
741 #endif
742
743 // Processor state ---------------------------------------
744
745 // Output stream.
746 FILE* stream_;
747 PrintDisassembler* print_disasm_;
748
749 // Instrumentation.
750 Instrument* instrument_;
751
752 // General purpose registers. Register 31 is the stack pointer.
753 SimRegister registers_[kNumberOfRegisters];
754
755 // Floating point registers
756 SimFPRegister fpregisters_[kNumberOfFPRegisters];
757
758 // Processor state
759 // bits[31, 27]: Condition flags N, Z, C, and V.
760 // (Negative, Zero, Carry, Overflow)
761 SimSystemRegister nzcv_;
762
763 // Floating-Point Control Register
764 SimSystemRegister fpcr_;
765
766 // Only a subset of FPCR features are supported by the simulator. This helper
767 // checks that the FPCR settings are supported.
768 //
769 // This is checked when floating-point instructions are executed, not when
770 // FPCR is set. This allows generated code to modify FPCR for external
771 // functions, or to save and restore it when entering and leaving generated
772 // code.
773 void AssertSupportedFPCR() {
774 ASSERT(fpcr().DN() == 0); // No default-NaN support.
775 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support.
776 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
777
778 // The simulator does not support half-precision operations so fpcr().AHP()
779 // is irrelevant, and is not checked here.
780 }
781
782 static int CalcNFlag(uint64_t result, unsigned reg_size) {
783 return (result >> (reg_size - 1)) & 1;
784 }
785
786 static int CalcZFlag(uint64_t result) {
787 return result == 0;
788 }
789
790 static const uint32_t kConditionFlagsMask = 0xf0000000;
791
792 // Stack
793 byte* stack_;
794 static const intptr_t stack_protection_size_ = KB;
795 intptr_t stack_size_;
796 byte* stack_limit_;
797 // TODO(aleram): protect the stack.
798
799 Decoder* decoder_;
800 Decoder* disassembler_decoder_;
801
802 // Indicates if the pc has been modified by the instruction and should not be
803 // automatically incremented.
804 bool pc_modified_;
805 Instruction* pc_;
806
807 static const char* xreg_names[];
808 static const char* wreg_names[];
809 static const char* sreg_names[];
810 static const char* dreg_names[];
811 static const char* vreg_names[];
812
813 // Debugger input.
814 void set_last_debugger_input(char* input) {
815 DeleteArray(last_debugger_input_);
816 last_debugger_input_ = input;
817 }
818 char* last_debugger_input() { return last_debugger_input_; }
819 char* last_debugger_input_;
820
821 private:
822 int log_parameters_;
823 Isolate* isolate_;
824 };
825
826
827 // When running with the simulator transition into simulated execution at this
828 // point.
829 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
830 reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS( \
831 FUNCTION_ADDR(entry), \
832 p0, p1, p2, p3, p4))
833
834 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
835 Simulator::current(Isolate::Current())->CallRegExp( \
836 entry, \
837 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
838
839 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
840 try_catch_address == NULL ? \
841 NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
842
843
844 // The simulator has its own stack. Thus it has a different stack limit from
845 // the C-based native code.
846 // See also 'class SimulatorStack' in arm/simulator-arm.h.
847 class SimulatorStack : public v8::internal::AllStatic {
848 public:
849 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
850 uintptr_t c_limit) {
851 return Simulator::current(isolate)->StackLimit();
852 }
853
854 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
855 Simulator* sim = Simulator::current(Isolate::Current());
856 return sim->PushAddress(try_catch_address);
857 }
858
859 static void UnregisterCTryCatch() {
860 Simulator::current(Isolate::Current())->PopAddress();
861 }
862 };
863
864 #endif // !defined(USE_SIMULATOR)
865
866 } } // namespace v8::internal
867
868 #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