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

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

Issue 148293020: Merge experimental/a64 to bleeding_edge. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove ARM from OWNERS 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 // 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 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 Instruction* pc() { return pc_; }
325
326 void increment_pc() {
327 if (!pc_modified_) {
328 pc_ = pc_->NextInstruction();
329 }
330
331 pc_modified_ = false;
332 }
333
334 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 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 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 int32_t wreg(unsigned code,
378 Reg31Mode r31mode = Reg31IsZeroRegister) const {
379 return reg<int32_t>(code, r31mode);
380 }
381
382 int64_t xreg(unsigned code,
383 Reg31Mode r31mode = Reg31IsZeroRegister) const {
384 return reg<int64_t>(code, r31mode);
385 }
386
387 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 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 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 void set_wreg(unsigned code, int32_t value,
419 Reg31Mode r31mode = Reg31IsZeroRegister) {
420 set_reg(kWRegSize, code, value, r31mode);
421 }
422
423 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 void set_lr(T value) {
431 ASSERT(sizeof(T) == kPointerSize);
432 set_reg(kLinkRegCode, value);
433 }
434
435 template<typename T>
436 void set_sp(T value) {
437 ASSERT(sizeof(T) == kPointerSize);
438 set_reg(31, value, Reg31IsStackPointer);
439 }
440
441 int64_t sp() { return xreg(31, Reg31IsStackPointer); }
442 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
443 int64_t fp() {
444 return xreg(kFramePointerRegCode, Reg31IsStackPointer);
445 }
446 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
447
448 Address get_sp() { return reinterpret_cast<Address>(sp()); }
449
450 // Return 'size' bits of the value of a floating-point register, as the
451 // specified type. The value is zero-extended to fill the result.
452 //
453 // The only supported values of 'size' are kDRegSize and kSRegSize.
454 template<typename T>
455 T fpreg(unsigned size, unsigned code) const {
456 unsigned size_in_bytes = size / 8;
457 ASSERT(size_in_bytes <= sizeof(T));
458 ASSERT((size == kDRegSize) || (size == kSRegSize));
459 ASSERT(code < kNumberOfFPRegisters);
460 return fpregisters_[code].Get<T>(size_in_bytes);
461 }
462
463 // Like fpreg(), but infer the access size from the template type.
464 template<typename T>
465 T fpreg(unsigned code) const {
466 return fpreg<T>(sizeof(T) * 8, code);
467 }
468
469 // Common specialized accessors for the fpreg() template.
470 float sreg(unsigned code) const {
471 return fpreg<float>(code);
472 }
473
474 uint32_t sreg_bits(unsigned code) const {
475 return fpreg<uint32_t>(code);
476 }
477
478 double dreg(unsigned code) const {
479 return fpreg<double>(code);
480 }
481
482 uint64_t dreg_bits(unsigned code) const {
483 return fpreg<uint64_t>(code);
484 }
485
486 double fpreg(unsigned size, unsigned code) const {
487 switch (size) {
488 case kSRegSize: return sreg(code);
489 case kDRegSize: return dreg(code);
490 default:
491 UNREACHABLE();
492 return 0.0;
493 }
494 }
495
496 // Write 'value' into a floating-point register. The value is zero-extended.
497 // This behaviour matches AArch64 register writes.
498 template<typename T>
499 void set_fpreg(unsigned code, T value) {
500 ASSERT((sizeof(value) == kDRegSizeInBytes) ||
501 (sizeof(value) == kSRegSizeInBytes));
502 ASSERT(code < kNumberOfFPRegisters);
503 fpregisters_[code].Set(value, sizeof(value));
504 }
505
506 // Common specialized accessors for the set_fpreg() template.
507 void set_sreg(unsigned code, float value) {
508 set_fpreg(code, value);
509 }
510
511 void set_sreg_bits(unsigned code, uint32_t value) {
512 set_fpreg(code, value);
513 }
514
515 void set_dreg(unsigned code, double value) {
516 set_fpreg(code, value);
517 }
518
519 void set_dreg_bits(unsigned code, uint64_t value) {
520 set_fpreg(code, value);
521 }
522
523 bool N() { return nzcv_.N() != 0; }
524 bool Z() { return nzcv_.Z() != 0; }
525 bool C() { return nzcv_.C() != 0; }
526 bool V() { return nzcv_.V() != 0; }
527 SimSystemRegister& nzcv() { return nzcv_; }
528
529 // TODO(jbramley): Find a way to make the fpcr_ members return the proper
530 // types, so this accessor is not necessary.
531 FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
532 SimSystemRegister& fpcr() { return fpcr_; }
533
534 // Debug helpers
535
536 // Simulator breakpoints.
537 struct Breakpoint {
538 Instruction* location;
539 bool enabled;
540 };
541 std::vector<Breakpoint> breakpoints_;
542 void SetBreakpoint(Instruction* breakpoint);
543 void ListBreakpoints();
544 void CheckBreakpoints();
545
546 // Helpers for the 'next' command.
547 // When this is set, the Simulator will insert a breakpoint after the next BL
548 // instruction it meets.
549 bool break_on_next_;
550 // Check if the Simulator should insert a break after the current instruction
551 // for the 'next' command.
552 void CheckBreakNext();
553
554 // Disassemble instruction at the given address.
555 void PrintInstructionsAt(Instruction* pc, uint64_t count);
556
557 void PrintSystemRegisters(bool print_all = false);
558 void PrintRegisters(bool print_all_regs = false);
559 void PrintFPRegisters(bool print_all_regs = false);
560 void PrintProcessorState();
561 void PrintWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
562 void LogSystemRegisters() {
563 if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters();
564 }
565 void LogRegisters() {
566 if (log_parameters_ & LOG_REGS) PrintRegisters();
567 }
568 void LogFPRegisters() {
569 if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters();
570 }
571 void LogProcessorState() {
572 LogSystemRegisters();
573 LogRegisters();
574 LogFPRegisters();
575 }
576 void LogWrite(uint8_t* address, uint64_t value, unsigned num_bytes) {
577 if (log_parameters_ & LOG_WRITE) PrintWrite(address, value, num_bytes);
578 }
579
580 int log_parameters() { return log_parameters_; }
581 void set_log_parameters(int new_parameters) {
582 if (new_parameters & LOG_DISASM) {
583 decoder_->InsertVisitorBefore(print_disasm_, this);
584 } else {
585 decoder_->RemoveVisitor(print_disasm_);
586 }
587 log_parameters_ = new_parameters;
588 }
589
590 static inline const char* WRegNameForCode(unsigned code,
591 Reg31Mode mode = Reg31IsZeroRegister);
592 static inline const char* XRegNameForCode(unsigned code,
593 Reg31Mode mode = Reg31IsZeroRegister);
594 static inline const char* SRegNameForCode(unsigned code);
595 static inline const char* DRegNameForCode(unsigned code);
596 static inline const char* VRegNameForCode(unsigned code);
597 static inline int CodeFromName(const char* name);
598
599 protected:
600 // Simulation helpers ------------------------------------
601 bool ConditionPassed(Condition cond) {
602 switch (cond) {
603 case eq:
604 return Z();
605 case ne:
606 return !Z();
607 case hs:
608 return C();
609 case lo:
610 return !C();
611 case mi:
612 return N();
613 case pl:
614 return !N();
615 case vs:
616 return V();
617 case vc:
618 return !V();
619 case hi:
620 return C() && !Z();
621 case ls:
622 return !(C() && !Z());
623 case ge:
624 return N() == V();
625 case lt:
626 return N() != V();
627 case gt:
628 return !Z() && (N() == V());
629 case le:
630 return !(!Z() && (N() == V()));
631 case nv: // Fall through.
632 case al:
633 return true;
634 default:
635 UNREACHABLE();
636 return false;
637 }
638 }
639
640 bool ConditionFailed(Condition cond) {
641 return !ConditionPassed(cond);
642 }
643
644 void AddSubHelper(Instruction* instr, int64_t op2);
645 int64_t AddWithCarry(unsigned reg_size,
646 bool set_flags,
647 int64_t src1,
648 int64_t src2,
649 int64_t carry_in = 0);
650 void LogicalHelper(Instruction* instr, int64_t op2);
651 void ConditionalCompareHelper(Instruction* instr, int64_t op2);
652 void LoadStoreHelper(Instruction* instr,
653 int64_t offset,
654 AddrMode addrmode);
655 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
656 uint8_t* LoadStoreAddress(unsigned addr_reg,
657 int64_t offset,
658 AddrMode addrmode);
659 void LoadStoreWriteBack(unsigned addr_reg,
660 int64_t offset,
661 AddrMode addrmode);
662 void CheckMemoryAccess(uint8_t* address, uint8_t* stack);
663
664 uint64_t MemoryRead(uint8_t* address, unsigned num_bytes);
665 uint8_t MemoryRead8(uint8_t* address);
666 uint16_t MemoryRead16(uint8_t* address);
667 uint32_t MemoryRead32(uint8_t* address);
668 float MemoryReadFP32(uint8_t* address);
669 uint64_t MemoryRead64(uint8_t* address);
670 double MemoryReadFP64(uint8_t* address);
671
672 void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes);
673 void MemoryWrite32(uint8_t* address, uint32_t value);
674 void MemoryWriteFP32(uint8_t* address, float value);
675 void MemoryWrite64(uint8_t* address, uint64_t value);
676 void MemoryWriteFP64(uint8_t* address, double value);
677
678 int64_t ShiftOperand(unsigned reg_size,
679 int64_t value,
680 Shift shift_type,
681 unsigned amount);
682 int64_t Rotate(unsigned reg_width,
683 int64_t value,
684 Shift shift_type,
685 unsigned amount);
686 int64_t ExtendValue(unsigned reg_width,
687 int64_t value,
688 Extend extend_type,
689 unsigned left_shift = 0);
690
691 uint64_t ReverseBits(uint64_t value, unsigned num_bits);
692 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
693
694 void FPCompare(double val0, double val1);
695 double FPRoundInt(double value, FPRounding round_mode);
696 double FPToDouble(float value);
697 float FPToFloat(double value, FPRounding round_mode);
698 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
699 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
700 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
701 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
702 int32_t FPToInt32(double value, FPRounding rmode);
703 int64_t FPToInt64(double value, FPRounding rmode);
704 uint32_t FPToUInt32(double value, FPRounding rmode);
705 uint64_t FPToUInt64(double value, FPRounding rmode);
706
707 template <typename T>
708 T FPMax(T a, T b);
709
710 template <typename T>
711 T FPMin(T a, T b);
712
713 template <typename T>
714 T FPMaxNM(T a, T b);
715
716 template <typename T>
717 T FPMinNM(T a, T b);
718
719 void CheckStackAlignment();
720
721 inline void CheckPCSComplianceAndRun();
722
723 #ifdef DEBUG
724 // Corruption values should have their least significant byte cleared to
725 // allow the code of the register being corrupted to be inserted.
726 static const uint64_t kCallerSavedRegisterCorruptionValue =
727 0xca11edc0de000000UL;
728 // This value is a NaN in both 32-bit and 64-bit FP.
729 static const uint64_t kCallerSavedFPRegisterCorruptionValue =
730 0x7ff000007f801000UL;
731 // This value is a mix of 32/64-bits NaN and "verbose" immediate.
732 static const uint64_t kDefaultCPURegisterCorruptionValue =
733 0x7ffbad007f8bad00UL;
734
735 void CorruptRegisters(CPURegList* list,
736 uint64_t value = kDefaultCPURegisterCorruptionValue);
737 void CorruptAllCallerSavedCPURegisters();
738 #endif
739
740 // Processor state ---------------------------------------
741
742 // Output stream.
743 FILE* stream_;
744 PrintDisassembler* print_disasm_;
745
746 // Instrumentation.
747 Instrument* instrument_;
748
749 // General purpose registers. Register 31 is the stack pointer.
750 SimRegister registers_[kNumberOfRegisters];
751
752 // Floating point registers
753 SimFPRegister fpregisters_[kNumberOfFPRegisters];
754
755 // Processor state
756 // bits[31, 27]: Condition flags N, Z, C, and V.
757 // (Negative, Zero, Carry, Overflow)
758 SimSystemRegister nzcv_;
759
760 // Floating-Point Control Register
761 SimSystemRegister fpcr_;
762
763 // Only a subset of FPCR features are supported by the simulator. This helper
764 // checks that the FPCR settings are supported.
765 //
766 // This is checked when floating-point instructions are executed, not when
767 // FPCR is set. This allows generated code to modify FPCR for external
768 // functions, or to save and restore it when entering and leaving generated
769 // code.
770 void AssertSupportedFPCR() {
771 ASSERT(fpcr().DN() == 0); // No default-NaN support.
772 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support.
773 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only.
774
775 // The simulator does not support half-precision operations so fpcr().AHP()
776 // is irrelevant, and is not checked here.
777 }
778
779 static int CalcNFlag(uint64_t result, unsigned reg_size) {
780 return (result >> (reg_size - 1)) & 1;
781 }
782
783 static int CalcZFlag(uint64_t result) {
784 return result == 0;
785 }
786
787 static const uint32_t kConditionFlagsMask = 0xf0000000;
788
789 // Stack
790 byte* stack_;
791 static const intptr_t stack_protection_size_ = KB;
792 intptr_t stack_size_;
793 byte* stack_limit_;
794 // TODO(aleram): protect the stack.
795
796 Decoder* decoder_;
797 Decoder* disassembler_decoder_;
798
799 // Indicates if the pc has been modified by the instruction and should not be
800 // automatically incremented.
801 bool pc_modified_;
802 Instruction* pc_;
803
804 static const char* xreg_names[];
805 static const char* wreg_names[];
806 static const char* sreg_names[];
807 static const char* dreg_names[];
808 static const char* vreg_names[];
809
810 // Debugger input.
811 void set_last_debugger_input(char* input) {
812 DeleteArray(last_debugger_input_);
813 last_debugger_input_ = input;
814 }
815 char* last_debugger_input() { return last_debugger_input_; }
816 char* last_debugger_input_;
817
818 private:
819 int log_parameters_;
820 Isolate* isolate_;
821 };
822
823
824 // When running with the simulator transition into simulated execution at this
825 // point.
826 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
827 reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS( \
828 FUNCTION_ADDR(entry), \
829 p0, p1, p2, p3, p4))
830
831 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
832 Simulator::current(Isolate::Current())->CallRegExp( \
833 entry, \
834 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
835
836 #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
837 try_catch_address == NULL ? \
838 NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
839
840
841 // The simulator has its own stack. Thus it has a different stack limit from
842 // the C-based native code.
843 // See also 'class SimulatorStack' in arm/simulator-arm.h.
844 class SimulatorStack : public v8::internal::AllStatic {
845 public:
846 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
847 uintptr_t c_limit) {
848 return Simulator::current(isolate)->StackLimit();
849 }
850
851 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
852 Simulator* sim = Simulator::current(Isolate::Current());
853 return sim->PushAddress(try_catch_address);
854 }
855
856 static void UnregisterCTryCatch() {
857 Simulator::current(Isolate::Current())->PopAddress();
858 }
859 };
860
861 #endif // !defined(USE_SIMULATOR)
862
863 } } // namespace v8::internal
864
865 #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