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

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

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/simulator-a64.h ('k') | src/a64/stub-cache-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 #include <stdlib.h>
29 #include <cmath>
30 #include <cstdarg>
31 #include "v8.h"
32
33 #if V8_TARGET_ARCH_A64
34
35 #include "disasm.h"
36 #include "assembler.h"
37 #include "a64/simulator-a64.h"
38 #include "macro-assembler.h"
39
40 namespace v8 {
41 namespace internal {
42
43 #if defined(USE_SIMULATOR)
44
45
46 // This macro provides a platform independent use of sscanf. The reason for
47 // SScanF not being implemented in a platform independent way through
48 // ::v8::internal::OS in the same way as SNPrintF is that the
49 // Windows C Run-Time Library does not provide vsscanf.
50 #define SScanF sscanf // NOLINT
51
52
53 // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
54 void PRINTF_CHECKING TraceSim(const char* format, ...) {
55 if (FLAG_trace_sim) {
56 va_list arguments;
57 va_start(arguments, format);
58 OS::VPrint(format, arguments);
59 va_end(arguments);
60 }
61 }
62
63
64 const Instruction* Simulator::kEndOfSimAddress = NULL;
65
66
67 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
68 int width = msb - lsb + 1;
69 ASSERT(is_uintn(bits, width) || is_intn(bits, width));
70
71 bits <<= lsb;
72 uint32_t mask = ((1 << width) - 1) << lsb;
73 ASSERT((mask & write_ignore_mask_) == 0);
74
75 value_ = (value_ & ~mask) | (bits & mask);
76 }
77
78
79 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
80 switch (id) {
81 case NZCV:
82 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
83 case FPCR:
84 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
85 default:
86 UNREACHABLE();
87 return SimSystemRegister();
88 }
89 }
90
91
92 void Simulator::Initialize(Isolate* isolate) {
93 if (isolate->simulator_initialized()) return;
94 isolate->set_simulator_initialized(true);
95 ExternalReference::set_redirector(isolate, &RedirectExternalReference);
96 }
97
98
99 // Get the active Simulator for the current thread.
100 Simulator* Simulator::current(Isolate* isolate) {
101 Isolate::PerIsolateThreadData* isolate_data =
102 isolate->FindOrAllocatePerThreadDataForThisThread();
103 ASSERT(isolate_data != NULL);
104
105 Simulator* sim = isolate_data->simulator();
106 if (sim == NULL) {
107 // TODO(146): delete the simulator object when a thread/isolate goes away.
108 sim = new Simulator(new Decoder(), isolate);
109 isolate_data->set_simulator(sim);
110 }
111 return sim;
112 }
113
114
115 void Simulator::CallVoid(byte* entry, va_list args) {
116 int index_x = 0;
117 int index_d = 0;
118
119 // At this point, we don't know how much stack space we need (for arguments
120 // that don't fit into registers). We can only do one pass through the
121 // va_list, so we store the extra arguments in a vector, then copy them to
122 // their proper locations later.
123 std::vector<int64_t> stack_args(0);
124
125 // Process register arguments.
126 CallArgument arg = va_arg(args, CallArgument);
127 while (!arg.IsEnd()) {
128 if (arg.IsX() && (index_x < 8)) {
129 set_xreg(index_x++, arg.bits());
130 } else if (arg.IsD() && (index_d < 8)) {
131 set_dreg_bits(index_d++, arg.bits());
132 } else {
133 ASSERT(arg.IsD() || arg.IsX());
134 stack_args.push_back(arg.bits());
135 }
136 arg = va_arg(args, CallArgument);
137 }
138
139 // Process stack arguments, and make sure the stack is suitably aligned.
140 uintptr_t original_stack = sp();
141 uintptr_t entry_stack = original_stack -
142 stack_args.size() * sizeof(stack_args[0]);
143 if (OS::ActivationFrameAlignment() != 0) {
144 entry_stack &= -OS::ActivationFrameAlignment();
145 }
146 char * stack = reinterpret_cast<char*>(entry_stack);
147 std::vector<int64_t>::const_iterator it;
148 for (it = stack_args.begin(); it != stack_args.end(); it++) {
149 memcpy(stack, &(*it), sizeof(*it));
150 stack += sizeof(*it);
151 }
152
153 ASSERT(reinterpret_cast<uintptr_t>(stack) <= original_stack);
154 set_sp(entry_stack);
155
156 // Call the generated code.
157 set_pc(entry);
158 set_lr(kEndOfSimAddress);
159 CheckPCSComplianceAndRun();
160
161 set_sp(original_stack);
162 }
163
164
165
166 void Simulator::CallVoid(byte* entry, ...) {
167 va_list args;
168 va_start(args, entry);
169 CallVoid(entry, args);
170 va_end(args);
171 }
172
173
174 int64_t Simulator::CallInt64(byte* entry, ...) {
175 va_list args;
176 va_start(args, entry);
177 CallVoid(entry, args);
178 va_end(args);
179
180 return xreg(0);
181 }
182
183
184 double Simulator::CallDouble(byte* entry, ...) {
185 va_list args;
186 va_start(args, entry);
187 CallVoid(entry, args);
188 va_end(args);
189
190 return dreg(0);
191 }
192
193
194 int64_t Simulator::CallJS(byte* entry,
195 byte* function_entry,
196 JSFunction* func,
197 Object* revc,
198 int64_t argc,
199 Object*** argv) {
200 return CallInt64(entry,
201 CallArgument(function_entry),
202 CallArgument(func),
203 CallArgument(revc),
204 CallArgument(argc),
205 CallArgument(argv),
206 CallArgument::End());
207 }
208
209 int64_t Simulator::CallRegExp(byte* entry,
210 String* input,
211 int64_t start_offset,
212 const byte* input_start,
213 const byte* input_end,
214 int* output,
215 int64_t output_size,
216 Address stack_base,
217 int64_t direct_call,
218 void* return_address,
219 Isolate* isolate) {
220 return CallInt64(entry,
221 CallArgument(input),
222 CallArgument(start_offset),
223 CallArgument(input_start),
224 CallArgument(input_end),
225 CallArgument(output),
226 CallArgument(output_size),
227 CallArgument(stack_base),
228 CallArgument(direct_call),
229 CallArgument(return_address),
230 CallArgument(isolate),
231 CallArgument::End());
232 }
233
234
235 void Simulator::CheckPCSComplianceAndRun() {
236 #ifdef DEBUG
237 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
238 CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count());
239
240 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
241 uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters];
242
243 CPURegList register_list = kCalleeSaved;
244 CPURegList fpregister_list = kCalleeSavedFP;
245
246 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
247 // x31 is not a caller saved register, so no need to specify if we want
248 // the stack or zero.
249 saved_registers[i] = xreg(register_list.PopLowestIndex().code());
250 }
251 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
252 saved_fpregisters[i] =
253 dreg_bits(fpregister_list.PopLowestIndex().code());
254 }
255 int64_t original_stack = sp();
256 #endif
257 // Start the simulation!
258 Run();
259 #ifdef DEBUG
260 CHECK_EQ(original_stack, sp());
261 // Check that callee-saved registers have been preserved.
262 register_list = kCalleeSaved;
263 fpregister_list = kCalleeSavedFP;
264 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
265 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
266 }
267 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
268 ASSERT(saved_fpregisters[i] ==
269 dreg_bits(fpregister_list.PopLowestIndex().code()));
270 }
271
272 // Corrupt caller saved register minus the return regiters.
273
274 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
275 // for now .
276 register_list = kCallerSaved;
277 register_list.Remove(x0);
278 register_list.Remove(x1);
279
280 // In theory d0 to d7 can be used for return values, but V8 only uses d0
281 // for now .
282 fpregister_list = kCallerSavedFP;
283 fpregister_list.Remove(d0);
284
285 CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue);
286 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
287 #endif
288 }
289
290
291 #ifdef DEBUG
292 // The least significant byte of the curruption value holds the corresponding
293 // register's code.
294 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
295 if (list->type() == CPURegister::kRegister) {
296 while (!list->IsEmpty()) {
297 unsigned code = list->PopLowestIndex().code();
298 set_xreg(code, value | code);
299 }
300 } else {
301 ASSERT(list->type() == CPURegister::kFPRegister);
302 while (!list->IsEmpty()) {
303 unsigned code = list->PopLowestIndex().code();
304 set_dreg_bits(code, value | code);
305 }
306 }
307 }
308
309
310 void Simulator::CorruptAllCallerSavedCPURegisters() {
311 // Corrupt alters its parameter so copy them first.
312 CPURegList register_list = kCallerSaved;
313 CPURegList fpregister_list = kCallerSavedFP;
314
315 CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue);
316 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
317 }
318 #endif
319
320
321 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
322 // TODO(all): Insert a marker in the extra space allocated on the stack.
323 uintptr_t Simulator::PushAddress(uintptr_t address) {
324 ASSERT(sizeof(uintptr_t) < 2 * kXRegSizeInBytes);
325 intptr_t new_sp = sp() - 2 * kXRegSizeInBytes;
326 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
327 *stack_slot = address;
328 set_sp(new_sp);
329 return new_sp;
330 }
331
332
333 uintptr_t Simulator::PopAddress() {
334 intptr_t current_sp = sp();
335 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
336 uintptr_t address = *stack_slot;
337 ASSERT(sizeof(uintptr_t) < 2 * kXRegSizeInBytes);
338 set_sp(current_sp + 2 * kXRegSizeInBytes);
339 return address;
340 }
341
342
343 // Returns the limit of the stack area to enable checking for stack overflows.
344 uintptr_t Simulator::StackLimit() const {
345 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
346 // pushing values.
347 // TODO(all): Increase the stack limit protection.
348
349 // The margin was decreased to 256 bytes, because we are intensively using
350 // the stack. The stack usage should decrease when our code improves. Then
351 // we can set it to 1024 again.
352 return reinterpret_cast<uintptr_t>(stack_limit_) + 256;
353 }
354
355
356 Simulator::Simulator(Decoder* decoder, Isolate* isolate, FILE* stream)
357 : decoder_(decoder), last_debugger_input_(NULL), log_parameters_(NO_PARAM),
358 isolate_(isolate) {
359 // Setup the decoder.
360 decoder_->AppendVisitor(this);
361
362 ResetState();
363
364 // Allocate and setup the simulator stack.
365 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
366 stack_ = new byte[stack_size_];
367 stack_limit_ = stack_ + stack_protection_size_;
368 byte* tos = stack_ + stack_size_ - stack_protection_size_;
369 // The stack pointer must be 16 bytes aligned.
370 set_sp(reinterpret_cast<int64_t>(tos) & ~0xfUL);
371
372 stream_ = stream;
373 print_disasm_ = new PrintDisassembler(stream_);
374
375 if (FLAG_trace_sim) {
376 decoder_->InsertVisitorBefore(print_disasm_, this);
377 log_parameters_ = LOG_ALL;
378 }
379
380 // The debugger needs to disassemble code without the simulator executing an
381 // instruction, so we create a dedicated decoder.
382 disassembler_decoder_ = new Decoder();
383 disassembler_decoder_->AppendVisitor(print_disasm_);
384
385 if (FLAG_log_instruction_stats) {
386 instrument_ = new Instrument(FLAG_log_instruction_file,
387 FLAG_log_instruction_period);
388 decoder_->AppendVisitor(instrument_);
389 }
390 }
391
392
393 void Simulator::ResetState() {
394 // Reset the system registers.
395 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
396 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
397
398 // Reset registers to 0.
399 pc_ = NULL;
400 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
401 set_xreg(i, 0xbadbeef);
402 }
403 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
404 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
405 set_dreg_bits(i, 0x7ff000007f800001UL);
406 }
407 // Returning to address 0 exits the Simulator.
408 set_lr(kEndOfSimAddress);
409
410 // Reset debug helpers.
411 breakpoints_.empty();
412 break_on_next_= false;
413 }
414
415
416 Simulator::~Simulator() {
417 delete[] stack_;
418 if (FLAG_log_instruction_stats) {
419 delete instrument_;
420 }
421 delete disassembler_decoder_;
422 delete print_disasm_;
423 DeleteArray(last_debugger_input_);
424 }
425
426
427 void Simulator::Run() {
428 pc_modified_ = false;
429 while (pc_ != kEndOfSimAddress) {
430 ExecuteInstruction();
431 }
432 }
433
434
435 void Simulator::RunFrom(Instruction* start) {
436 set_pc(start);
437 Run();
438 }
439
440
441 void Simulator::CheckStackAlignment() {
442 // TODO(aleram): The sp alignment check to perform depends on the processor
443 // state. Check the specifications for more details.
444 }
445
446
447 // When the generated code calls an external reference we need to catch that in
448 // the simulator. The external reference will be a function compiled for the
449 // host architecture. We need to call that function instead of trying to
450 // execute it with the simulator. We do that by redirecting the external
451 // reference to a svc (Supervisor Call) instruction that is handled by
452 // the simulator. We write the original destination of the jump just at a known
453 // offset from the svc instruction so the simulator knows what to call.
454 class Redirection {
455 public:
456 Redirection(void* external_function, ExternalReference::Type type)
457 : external_function_(external_function),
458 type_(type),
459 next_(NULL) {
460 redirect_call_.SetInstructionBits(
461 HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall));
462 Isolate* isolate = Isolate::Current();
463 next_ = isolate->simulator_redirection();
464 // TODO(all): Simulator flush I cache
465 isolate->set_simulator_redirection(this);
466 }
467
468 void* address_of_redirect_call() {
469 return reinterpret_cast<void*>(&redirect_call_);
470 }
471
472 void* external_function() { return external_function_; }
473 ExternalReference::Type type() { return type_; }
474
475 static Redirection* Get(void* external_function,
476 ExternalReference::Type type) {
477 Isolate* isolate = Isolate::Current();
478 Redirection* current = isolate->simulator_redirection();
479 for (; current != NULL; current = current->next_) {
480 if (current->external_function_ == external_function) {
481 ASSERT_EQ(current->type(), type);
482 return current;
483 }
484 }
485 return new Redirection(external_function, type);
486 }
487
488 static Redirection* FromHltInstruction(Instruction* redirect_call) {
489 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call);
490 char* addr_of_redirection =
491 addr_of_hlt - OFFSET_OF(Redirection, redirect_call_);
492 return reinterpret_cast<Redirection*>(addr_of_redirection);
493 }
494
495 static void* ReverseRedirection(int64_t reg) {
496 Redirection* redirection =
497 FromHltInstruction(reinterpret_cast<Instruction*>(reg));
498 return redirection->external_function();
499 }
500
501 private:
502 void* external_function_;
503 Instruction redirect_call_;
504 ExternalReference::Type type_;
505 Redirection* next_;
506 };
507
508
509 void* Simulator::RedirectExternalReference(void* external_function,
510 ExternalReference::Type type) {
511 Redirection* redirection = Redirection::Get(external_function, type);
512 return redirection->address_of_redirect_call();
513 }
514
515
516 const char* Simulator::xreg_names[] = {
517 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
518 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
519 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23",
520 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"};
521
522 const char* Simulator::wreg_names[] = {
523 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
524 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
525 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
526 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"};
527
528 const char* Simulator::sreg_names[] = {
529 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
530 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
531 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
532 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
533
534 const char* Simulator::dreg_names[] = {
535 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
536 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
537 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
538 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
539
540 const char* Simulator::vreg_names[] = {
541 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
542 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
543 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
544 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
545
546
547 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
548 ASSERT(code < kNumberOfRegisters);
549 // If the code represents the stack pointer, index the name after zr.
550 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
551 code = kZeroRegCode + 1;
552 }
553 return wreg_names[code];
554 }
555
556
557 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
558 ASSERT(code < kNumberOfRegisters);
559 // If the code represents the stack pointer, index the name after zr.
560 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
561 code = kZeroRegCode + 1;
562 }
563 return xreg_names[code];
564 }
565
566
567 const char* Simulator::SRegNameForCode(unsigned code) {
568 ASSERT(code < kNumberOfFPRegisters);
569 return sreg_names[code];
570 }
571
572
573 const char* Simulator::DRegNameForCode(unsigned code) {
574 ASSERT(code < kNumberOfFPRegisters);
575 return dreg_names[code];
576 }
577
578
579 const char* Simulator::VRegNameForCode(unsigned code) {
580 ASSERT(code < kNumberOfFPRegisters);
581 return vreg_names[code];
582 }
583
584
585 int Simulator::CodeFromName(const char* name) {
586 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
587 if ((strcmp(xreg_names[i], name) == 0) ||
588 (strcmp(wreg_names[i], name) == 0)) {
589 return i;
590 }
591 }
592 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
593 if ((strcmp(vreg_names[i], name) == 0) ||
594 (strcmp(dreg_names[i], name) == 0) ||
595 (strcmp(sreg_names[i], name) == 0)) {
596 return i;
597 }
598 }
599 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
600 return kSPRegInternalCode;
601 }
602 return -1;
603 }
604
605
606 // Helpers ---------------------------------------------------------------------
607 int64_t Simulator::AddWithCarry(unsigned reg_size,
608 bool set_flags,
609 int64_t src1,
610 int64_t src2,
611 int64_t carry_in) {
612 ASSERT((carry_in == 0) || (carry_in == 1));
613 ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
614
615 uint64_t u1, u2;
616 int64_t result;
617 int64_t signed_sum = src1 + src2 + carry_in;
618
619 uint32_t N, Z, C, V;
620
621 if (reg_size == kWRegSize) {
622 u1 = static_cast<uint64_t>(src1) & kWRegMask;
623 u2 = static_cast<uint64_t>(src2) & kWRegMask;
624
625 result = signed_sum & kWRegMask;
626 // Compute the C flag by comparing the sum to the max unsigned integer.
627 C = ((kWMaxUInt - u1) < (u2 + carry_in)) ||
628 ((kWMaxUInt - u1 - carry_in) < u2);
629 // Overflow iff the sign bit is the same for the two inputs and different
630 // for the result.
631 int64_t s_src1 = src1 << (kXRegSize - kWRegSize);
632 int64_t s_src2 = src2 << (kXRegSize - kWRegSize);
633 int64_t s_result = result << (kXRegSize - kWRegSize);
634 V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0);
635
636 } else {
637 u1 = static_cast<uint64_t>(src1);
638 u2 = static_cast<uint64_t>(src2);
639
640 result = signed_sum;
641 // Compute the C flag by comparing the sum to the max unsigned integer.
642 C = ((kXMaxUInt - u1) < (u2 + carry_in)) ||
643 ((kXMaxUInt - u1 - carry_in) < u2);
644 // Overflow iff the sign bit is the same for the two inputs and different
645 // for the result.
646 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
647 }
648
649 N = CalcNFlag(result, reg_size);
650 Z = CalcZFlag(result);
651
652 if (set_flags) {
653 nzcv().SetN(N);
654 nzcv().SetZ(Z);
655 nzcv().SetC(C);
656 nzcv().SetV(V);
657 }
658 return result;
659 }
660
661
662 int64_t Simulator::ShiftOperand(unsigned reg_size,
663 int64_t value,
664 Shift shift_type,
665 unsigned amount) {
666 if (amount == 0) {
667 return value;
668 }
669 int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
670 switch (shift_type) {
671 case LSL:
672 return (value << amount) & mask;
673 case LSR:
674 return static_cast<uint64_t>(value) >> amount;
675 case ASR: {
676 // Shift used to restore the sign.
677 unsigned s_shift = kXRegSize - reg_size;
678 // Value with its sign restored.
679 int64_t s_value = (value << s_shift) >> s_shift;
680 return (s_value >> amount) & mask;
681 }
682 case ROR: {
683 if (reg_size == kWRegSize) {
684 value &= kWRegMask;
685 }
686 return (static_cast<uint64_t>(value) >> amount) |
687 ((value & ((1L << amount) - 1L)) << (reg_size - amount));
688 }
689 default:
690 UNIMPLEMENTED();
691 return 0;
692 }
693 }
694
695
696 int64_t Simulator::ExtendValue(unsigned reg_size,
697 int64_t value,
698 Extend extend_type,
699 unsigned left_shift) {
700 switch (extend_type) {
701 case UXTB:
702 value &= kByteMask;
703 break;
704 case UXTH:
705 value &= kHalfWordMask;
706 break;
707 case UXTW:
708 value &= kWordMask;
709 break;
710 case SXTB:
711 value = (value << 56) >> 56;
712 break;
713 case SXTH:
714 value = (value << 48) >> 48;
715 break;
716 case SXTW:
717 value = (value << 32) >> 32;
718 break;
719 case UXTX:
720 case SXTX:
721 break;
722 default:
723 UNREACHABLE();
724 }
725 int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
726 return (value << left_shift) & mask;
727 }
728
729
730 void Simulator::FPCompare(double val0, double val1) {
731 AssertSupportedFPCR();
732
733 // TODO(jbramley): This assumes that the C++ implementation handles
734 // comparisons in the way that we expect (as per AssertSupportedFPCR()).
735 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
736 nzcv().SetRawValue(FPUnorderedFlag);
737 } else if (val0 < val1) {
738 nzcv().SetRawValue(FPLessThanFlag);
739 } else if (val0 > val1) {
740 nzcv().SetRawValue(FPGreaterThanFlag);
741 } else if (val0 == val1) {
742 nzcv().SetRawValue(FPEqualFlag);
743 } else {
744 UNREACHABLE();
745 }
746 }
747
748
749 void Simulator::SetBreakpoint(Instruction* location) {
750 for (unsigned i = 0; i < breakpoints_.size(); i++) {
751 if (breakpoints_.at(i).location == location) {
752 PrintF("Existing breakpoint at %p was %s\n",
753 reinterpret_cast<void*>(location),
754 breakpoints_.at(i).enabled ? "disabled" : "enabled");
755 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
756 return;
757 }
758 }
759 Breakpoint new_breakpoint = {location, true};
760 breakpoints_.push_back(new_breakpoint);
761 PrintF("Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
762 }
763
764
765 void Simulator::ListBreakpoints() {
766 PrintF("Breakpoints:\n");
767 for (unsigned i = 0; i < breakpoints_.size(); i++) {
768 PrintF("%p : %s\n",
769 reinterpret_cast<void*>(breakpoints_.at(i).location),
770 breakpoints_.at(i).enabled ? "enabled" : "disabled");
771 }
772 }
773
774
775 void Simulator::CheckBreakpoints() {
776 bool hit_a_breakpoint = false;
777 for (unsigned i = 0; i < breakpoints_.size(); i++) {
778 if ((breakpoints_.at(i).location == pc_) &&
779 breakpoints_.at(i).enabled) {
780 hit_a_breakpoint = true;
781 // Disable this breakpoint.
782 breakpoints_.at(i).enabled = false;
783 }
784 }
785 if (hit_a_breakpoint) {
786 PrintF("Hit and disabled a breakpoint at %p.\n",
787 reinterpret_cast<void*>(pc_));
788 Debug();
789 }
790 }
791
792
793 void Simulator::CheckBreakNext() {
794 // If the current instruction is a BL, insert a breakpoint just after it.
795 if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
796 SetBreakpoint(pc_->NextInstruction());
797 break_on_next_ = false;
798 }
799 }
800
801
802 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
803 Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
804 for (Instruction* pc = start; pc < end; pc = pc->NextInstruction()) {
805 disassembler_decoder_->Decode(pc);
806 }
807 }
808
809
810 void Simulator::PrintSystemRegisters(bool print_all) {
811 static bool first_run = true;
812
813 // Define some colour codes to use for the register dump.
814 // TODO(jbramley): Find a more elegant way of defining these.
815 char const * const clr_normal = (FLAG_log_colour) ? ("\033[m") : ("");
816 char const * const clr_flag_name = (FLAG_log_colour) ? ("\033[1;30m") : ("");
817 char const * const clr_flag_value = (FLAG_log_colour) ? ("\033[1;37m") : ("");
818
819 static SimSystemRegister last_nzcv;
820 if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) {
821 fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
822 clr_flag_name,
823 clr_flag_value,
824 N(), Z(), C(), V(),
825 clr_normal);
826 }
827 last_nzcv = nzcv();
828
829 static SimSystemRegister last_fpcr;
830 if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) {
831 static const char * rmode[] = {
832 "0b00 (Round to Nearest)",
833 "0b01 (Round towards Plus Infinity)",
834 "0b10 (Round towards Minus Infinity)",
835 "0b11 (Round towards Zero)"
836 };
837 ASSERT(fpcr().RMode() <= (sizeof(rmode) / sizeof(rmode[0])));
838 fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
839 clr_flag_name,
840 clr_flag_value,
841 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
842 clr_normal);
843 }
844 last_fpcr = fpcr();
845
846 first_run = false;
847 }
848
849
850 void Simulator::PrintRegisters(bool print_all_regs) {
851 static bool first_run = true;
852 static int64_t last_regs[kNumberOfRegisters];
853
854 // Define some colour codes to use for the register dump.
855 // TODO(jbramley): Find a more elegant way of defining these.
856 char const * const clr_normal = (FLAG_log_colour) ? ("\033[m") : ("");
857 char const * const clr_reg_name = (FLAG_log_colour) ? ("\033[1;34m") : ("");
858 char const * const clr_reg_value = (FLAG_log_colour) ? ("\033[1;36m") : ("");
859
860 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
861 if (print_all_regs || first_run ||
862 (last_regs[i] != xreg(i, Reg31IsStackPointer))) {
863 fprintf(stream_,
864 "# %s%4s:%s 0x%016" PRIx64 "%s\n",
865 clr_reg_name,
866 XRegNameForCode(i, Reg31IsStackPointer),
867 clr_reg_value,
868 xreg(i, Reg31IsStackPointer),
869 clr_normal);
870 }
871 // Cache the new register value so the next run can detect any changes.
872 last_regs[i] = xreg(i, Reg31IsStackPointer);
873 }
874 first_run = false;
875 }
876
877
878 void Simulator::PrintFPRegisters(bool print_all_regs) {
879 static bool first_run = true;
880 static uint64_t last_regs[kNumberOfFPRegisters];
881
882 // Define some colour codes to use for the register dump.
883 // TODO(jbramley): Find a more elegant way of defining these.
884 char const * const clr_normal = (FLAG_log_colour) ? ("\033[m") : ("");
885 char const * const clr_reg_name = (FLAG_log_colour) ? ("\033[1;33m") : ("");
886 char const * const clr_reg_value = (FLAG_log_colour) ? ("\033[1;35m") : ("");
887
888 // Print as many rows of registers as necessary, keeping each individual
889 // register in the same column each time (to make it easy to visually scan
890 // for changes).
891 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
892 if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) {
893 fprintf(stream_,
894 "# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
895 clr_reg_name,
896 VRegNameForCode(i),
897 clr_reg_value,
898 dreg_bits(i),
899 clr_normal,
900 clr_reg_name,
901 DRegNameForCode(i),
902 clr_reg_value,
903 dreg(i),
904 clr_reg_name,
905 SRegNameForCode(i),
906 clr_reg_value,
907 sreg(i),
908 clr_normal);
909 }
910 // Cache the new register value so the next run can detect any changes.
911 last_regs[i] = dreg_bits(i);
912 }
913 first_run = false;
914 }
915
916
917 void Simulator::PrintProcessorState() {
918 PrintSystemRegisters();
919 PrintRegisters();
920 PrintFPRegisters();
921 }
922
923
924 void Simulator::PrintWrite(uint8_t* address,
925 uint64_t value,
926 unsigned num_bytes) {
927 // Define some color codes to use for memory logging.
928 const char* const clr_normal = (FLAG_log_colour) ? ("\033[m")
929 : ("");
930 const char* const clr_memory_value = (FLAG_log_colour) ? ("\033[1;32m")
931 : ("");
932 const char* const clr_memory_address = (FLAG_log_colour) ? ("\033[32m")
933 : ("");
934
935 // The template is "# value -> address". The template is not directly used
936 // in the printf since compilers tend to struggle with the parametrized
937 // width (%0*).
938 const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIx64 "%s\n";
939 fprintf(stream_,
940 format,
941 clr_memory_value,
942 num_bytes * 2, // The width in hexa characters.
943 value,
944 clr_normal,
945 clr_memory_address,
946 address,
947 clr_normal);
948 }
949
950
951 // Visitors---------------------------------------------------------------------
952
953 void Simulator::VisitUnimplemented(Instruction* instr) {
954 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
955 reinterpret_cast<void*>(instr), instr->InstructionBits());
956 UNIMPLEMENTED();
957 }
958
959
960 void Simulator::VisitUnallocated(Instruction* instr) {
961 fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n",
962 reinterpret_cast<void*>(instr), instr->InstructionBits());
963 UNIMPLEMENTED();
964 }
965
966
967 void Simulator::VisitPCRelAddressing(Instruction* instr) {
968 switch (instr->Mask(PCRelAddressingMask)) {
969 case ADR:
970 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
971 break;
972 case ADRP: // Not implemented in the assembler.
973 UNIMPLEMENTED();
974 break;
975 default:
976 UNREACHABLE();
977 break;
978 }
979 }
980
981
982 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
983 switch (instr->Mask(UnconditionalBranchMask)) {
984 case BL:
985 set_lr(instr->NextInstruction());
986 // Fall through.
987 case B:
988 set_pc(instr->ImmPCOffsetTarget());
989 break;
990 default:
991 UNREACHABLE();
992 }
993 }
994
995
996 void Simulator::VisitConditionalBranch(Instruction* instr) {
997 ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
998 if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
999 set_pc(instr->ImmPCOffsetTarget());
1000 }
1001 }
1002
1003
1004 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1005 Instruction* target = reg<Instruction*>(instr->Rn());
1006 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1007 case BLR: {
1008 set_lr(instr->NextInstruction());
1009 // Fall through.
1010 }
1011 case BR:
1012 case RET: set_pc(target); break;
1013 default: UNIMPLEMENTED();
1014 }
1015 }
1016
1017
1018 void Simulator::VisitTestBranch(Instruction* instr) {
1019 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1020 instr->ImmTestBranchBit40();
1021 bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
1022 switch (instr->Mask(TestBranchMask)) {
1023 case TBZ: break;
1024 case TBNZ: take_branch = !take_branch; break;
1025 default: UNIMPLEMENTED();
1026 }
1027 if (take_branch) {
1028 set_pc(instr->ImmPCOffsetTarget());
1029 }
1030 }
1031
1032
1033 void Simulator::VisitCompareBranch(Instruction* instr) {
1034 unsigned rt = instr->Rt();
1035 bool take_branch = false;
1036 switch (instr->Mask(CompareBranchMask)) {
1037 case CBZ_w: take_branch = (wreg(rt) == 0); break;
1038 case CBZ_x: take_branch = (xreg(rt) == 0); break;
1039 case CBNZ_w: take_branch = (wreg(rt) != 0); break;
1040 case CBNZ_x: take_branch = (xreg(rt) != 0); break;
1041 default: UNIMPLEMENTED();
1042 }
1043 if (take_branch) {
1044 set_pc(instr->ImmPCOffsetTarget());
1045 }
1046 }
1047
1048
1049 void Simulator::AddSubHelper(Instruction* instr, int64_t op2) {
1050 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1051 bool set_flags = instr->FlagsUpdate();
1052 int64_t new_val = 0;
1053 Instr operation = instr->Mask(AddSubOpMask);
1054
1055 switch (operation) {
1056 case ADD:
1057 case ADDS: {
1058 new_val = AddWithCarry(reg_size,
1059 set_flags,
1060 reg(reg_size, instr->Rn(), instr->RnMode()),
1061 op2);
1062 break;
1063 }
1064 case SUB:
1065 case SUBS: {
1066 new_val = AddWithCarry(reg_size,
1067 set_flags,
1068 reg(reg_size, instr->Rn(), instr->RnMode()),
1069 ~op2,
1070 1);
1071 break;
1072 }
1073 default: UNREACHABLE();
1074 }
1075
1076 set_reg(reg_size, instr->Rd(), new_val, instr->RdMode());
1077 }
1078
1079
1080 void Simulator::VisitAddSubShifted(Instruction* instr) {
1081 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1082 int64_t op2 = ShiftOperand(reg_size,
1083 reg(reg_size, instr->Rm()),
1084 static_cast<Shift>(instr->ShiftDP()),
1085 instr->ImmDPShift());
1086 AddSubHelper(instr, op2);
1087 }
1088
1089
1090 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1091 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1092 AddSubHelper(instr, op2);
1093 }
1094
1095
1096 void Simulator::VisitAddSubExtended(Instruction* instr) {
1097 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1098 int64_t op2 = ExtendValue(reg_size,
1099 reg(reg_size, instr->Rm()),
1100 static_cast<Extend>(instr->ExtendMode()),
1101 instr->ImmExtendShift());
1102 AddSubHelper(instr, op2);
1103 }
1104
1105
1106 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1107 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1108 int64_t op2 = reg(reg_size, instr->Rm());
1109 int64_t new_val;
1110
1111 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
1112 op2 = ~op2;
1113 }
1114
1115 new_val = AddWithCarry(reg_size,
1116 instr->FlagsUpdate(),
1117 reg(reg_size, instr->Rn()),
1118 op2,
1119 C());
1120
1121 set_reg(reg_size, instr->Rd(), new_val);
1122 }
1123
1124
1125 void Simulator::VisitLogicalShifted(Instruction* instr) {
1126 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1127 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1128 unsigned shift_amount = instr->ImmDPShift();
1129 int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
1130 shift_amount);
1131 if (instr->Mask(NOT) == NOT) {
1132 op2 = ~op2;
1133 }
1134 LogicalHelper(instr, op2);
1135 }
1136
1137
1138 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1139 LogicalHelper(instr, instr->ImmLogical());
1140 }
1141
1142
1143 void Simulator::LogicalHelper(Instruction* instr, int64_t op2) {
1144 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1145 int64_t op1 = reg(reg_size, instr->Rn());
1146 int64_t result = 0;
1147 bool update_flags = false;
1148
1149 // Switch on the logical operation, stripping out the NOT bit, as it has a
1150 // different meaning for logical immediate instructions.
1151 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1152 case ANDS: update_flags = true; // Fall through.
1153 case AND: result = op1 & op2; break;
1154 case ORR: result = op1 | op2; break;
1155 case EOR: result = op1 ^ op2; break;
1156 default:
1157 UNIMPLEMENTED();
1158 }
1159
1160 if (update_flags) {
1161 nzcv().SetN(CalcNFlag(result, reg_size));
1162 nzcv().SetZ(CalcZFlag(result));
1163 nzcv().SetC(0);
1164 nzcv().SetV(0);
1165 }
1166
1167 set_reg(reg_size, instr->Rd(), result, instr->RdMode());
1168 }
1169
1170
1171 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1172 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1173 ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
1174 }
1175
1176
1177 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1178 ConditionalCompareHelper(instr, instr->ImmCondCmp());
1179 }
1180
1181
1182 void Simulator::ConditionalCompareHelper(Instruction* instr, int64_t op2) {
1183 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1184 int64_t op1 = reg(reg_size, instr->Rn());
1185
1186 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1187 // If the condition passes, set the status flags to the result of comparing
1188 // the operands.
1189 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1190 AddWithCarry(reg_size, true, op1, ~op2, 1);
1191 } else {
1192 ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1193 AddWithCarry(reg_size, true, op1, op2, 0);
1194 }
1195 } else {
1196 // If the condition fails, set the status flags to the nzcv immediate.
1197 nzcv().SetFlags(instr->Nzcv());
1198 }
1199 }
1200
1201
1202 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1203 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1204 LoadStoreHelper(instr, offset, Offset);
1205 }
1206
1207
1208 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1209 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1210 }
1211
1212
1213 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1214 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1215 }
1216
1217
1218 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1219 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1220 }
1221
1222
1223 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1224 Extend ext = static_cast<Extend>(instr->ExtendMode());
1225 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1226 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1227
1228 int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
1229 shift_amount);
1230 LoadStoreHelper(instr, offset, Offset);
1231 }
1232
1233
1234 void Simulator::LoadStoreHelper(Instruction* instr,
1235 int64_t offset,
1236 AddrMode addrmode) {
1237 unsigned srcdst = instr->Rt();
1238 unsigned addr_reg = instr->Rn();
1239 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode);
1240 int num_bytes = 1 << instr->SizeLS();
1241 uint8_t* stack = NULL;
1242
1243 // Handle the writeback for stores before the store. On a CPU the writeback
1244 // and the store are atomic, but when running on the simulator it is possible
1245 // to be interrupted in between. The simulator is not thread safe and V8 does
1246 // not require it to be to run JavaScript therefore the profiler may sample
1247 // the "simulated" CPU in the middle of load/store with writeback. The code
1248 // below ensures that push operations are safe even when interrupted: the
1249 // stack pointer will be decremented before adding an element to the stack.
1250 if (instr->IsStore()) {
1251 LoadStoreWriteBack(addr_reg, offset, addrmode);
1252
1253 // For store the address post writeback is used to check access below the
1254 // stack.
1255 stack = reinterpret_cast<uint8_t*>(sp());
1256 }
1257
1258 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
1259 switch (op) {
1260 case LDRB_w:
1261 case LDRH_w:
1262 case LDR_w:
1263 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break;
1264 case STRB_w:
1265 case STRH_w:
1266 case STR_w:
1267 case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break;
1268 case LDRSB_w: {
1269 set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead8(address), SXTB));
1270 break;
1271 }
1272 case LDRSB_x: {
1273 set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead8(address), SXTB));
1274 break;
1275 }
1276 case LDRSH_w: {
1277 set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead16(address), SXTH));
1278 break;
1279 }
1280 case LDRSH_x: {
1281 set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead16(address), SXTH));
1282 break;
1283 }
1284 case LDRSW_x: {
1285 set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
1286 break;
1287 }
1288 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break;
1289 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break;
1290 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break;
1291 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break;
1292 default: UNIMPLEMENTED();
1293 }
1294
1295 // Handle the writeback for loads after the load to ensure safe pop
1296 // operation even when interrupted in the middle of it. The stack pointer
1297 // is only updated after the load so pop(fp) will never break the invariant
1298 // sp <= fp expected while walking the stack in the sampler.
1299 if (instr->IsLoad()) {
1300 // For loads the address pre writeback is used to check access below the
1301 // stack.
1302 stack = reinterpret_cast<uint8_t*>(sp());
1303
1304 LoadStoreWriteBack(addr_reg, offset, addrmode);
1305 }
1306
1307 // Accesses below the stack pointer (but above the platform stack limit) are
1308 // not allowed in the ABI.
1309 CheckMemoryAccess(address, stack);
1310 }
1311
1312
1313 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1314 LoadStorePairHelper(instr, Offset);
1315 }
1316
1317
1318 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1319 LoadStorePairHelper(instr, PreIndex);
1320 }
1321
1322
1323 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1324 LoadStorePairHelper(instr, PostIndex);
1325 }
1326
1327
1328 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
1329 LoadStorePairHelper(instr, Offset);
1330 }
1331
1332
1333 void Simulator::LoadStorePairHelper(Instruction* instr,
1334 AddrMode addrmode) {
1335 unsigned rt = instr->Rt();
1336 unsigned rt2 = instr->Rt2();
1337 unsigned addr_reg = instr->Rn();
1338 int offset = instr->ImmLSPair() << instr->SizeLSPair();
1339 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode);
1340 uint8_t* stack = NULL;
1341
1342 // Handle the writeback for stores before the store. On a CPU the writeback
1343 // and the store are atomic, but when running on the simulator it is possible
1344 // to be interrupted in between. The simulator is not thread safe and V8 does
1345 // not require it to be to run JavaScript therefore the profiler may sample
1346 // the "simulated" CPU in the middle of load/store with writeback. The code
1347 // below ensures that push operations are safe even when interrupted: the
1348 // stack pointer will be decremented before adding an element to the stack.
1349 if (instr->IsStore()) {
1350 LoadStoreWriteBack(addr_reg, offset, addrmode);
1351
1352 // For store the address post writeback is used to check access below the
1353 // stack.
1354 stack = reinterpret_cast<uint8_t*>(sp());
1355 }
1356
1357 LoadStorePairOp op =
1358 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1359
1360 // 'rt' and 'rt2' can only be aliased for stores.
1361 ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1362
1363 switch (op) {
1364 case LDP_w: {
1365 set_wreg(rt, MemoryRead32(address));
1366 set_wreg(rt2, MemoryRead32(address + kWRegSizeInBytes));
1367 break;
1368 }
1369 case LDP_s: {
1370 set_sreg(rt, MemoryReadFP32(address));
1371 set_sreg(rt2, MemoryReadFP32(address + kSRegSizeInBytes));
1372 break;
1373 }
1374 case LDP_x: {
1375 set_xreg(rt, MemoryRead64(address));
1376 set_xreg(rt2, MemoryRead64(address + kXRegSizeInBytes));
1377 break;
1378 }
1379 case LDP_d: {
1380 set_dreg(rt, MemoryReadFP64(address));
1381 set_dreg(rt2, MemoryReadFP64(address + kDRegSizeInBytes));
1382 break;
1383 }
1384 case LDPSW_x: {
1385 set_xreg(rt, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
1386 set_xreg(rt2, ExtendValue(kXRegSize,
1387 MemoryRead32(address + kWRegSizeInBytes), SXTW));
1388 break;
1389 }
1390 case STP_w: {
1391 MemoryWrite32(address, wreg(rt));
1392 MemoryWrite32(address + kWRegSizeInBytes, wreg(rt2));
1393 break;
1394 }
1395 case STP_s: {
1396 MemoryWriteFP32(address, sreg(rt));
1397 MemoryWriteFP32(address + kSRegSizeInBytes, sreg(rt2));
1398 break;
1399 }
1400 case STP_x: {
1401 MemoryWrite64(address, xreg(rt));
1402 MemoryWrite64(address + kXRegSizeInBytes, xreg(rt2));
1403 break;
1404 }
1405 case STP_d: {
1406 MemoryWriteFP64(address, dreg(rt));
1407 MemoryWriteFP64(address + kDRegSizeInBytes, dreg(rt2));
1408 break;
1409 }
1410 default: UNREACHABLE();
1411 }
1412
1413 // Handle the writeback for loads after the load to ensure safe pop
1414 // operation even when interrupted in the middle of it. The stack pointer
1415 // is only updated after the load so pop(fp) will never break the invariant
1416 // sp <= fp expected while walking the stack in the sampler.
1417 if (instr->IsLoad()) {
1418 // For loads the address pre writeback is used to check access below the
1419 // stack.
1420 stack = reinterpret_cast<uint8_t*>(sp());
1421
1422 LoadStoreWriteBack(addr_reg, offset, addrmode);
1423 }
1424
1425 // Accesses below the stack pointer (but above the platform stack limit) are
1426 // not allowed in the ABI.
1427 CheckMemoryAccess(address, stack);
1428 }
1429
1430
1431 void Simulator::VisitLoadLiteral(Instruction* instr) {
1432 uint8_t* address = instr->LiteralAddress();
1433 unsigned rt = instr->Rt();
1434
1435 switch (instr->Mask(LoadLiteralMask)) {
1436 case LDR_w_lit: set_wreg(rt, MemoryRead32(address)); break;
1437 case LDR_x_lit: set_xreg(rt, MemoryRead64(address)); break;
1438 case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address)); break;
1439 case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address)); break;
1440 default: UNREACHABLE();
1441 }
1442 }
1443
1444
1445 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg,
1446 int64_t offset,
1447 AddrMode addrmode) {
1448 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1449 int64_t address = xreg(addr_reg, Reg31IsStackPointer);
1450 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
1451 // When the base register is SP the stack pointer is required to be
1452 // quadword aligned prior to the address calculation and write-backs.
1453 // Misalignment will cause a stack alignment fault.
1454 ALIGNMENT_EXCEPTION();
1455 }
1456
1457 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1458 address += offset;
1459 }
1460
1461 return reinterpret_cast<uint8_t*>(address);
1462 }
1463
1464
1465 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
1466 int64_t offset,
1467 AddrMode addrmode) {
1468 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1469 ASSERT(offset != 0);
1470 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1471 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
1472 }
1473 }
1474
1475
1476 void Simulator::CheckMemoryAccess(uint8_t* address, uint8_t* stack) {
1477 if ((address >= stack_limit_) && (address < stack)) {
1478 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
1479 fprintf(stream_, " sp is here: 0x%16p\n", stack);
1480 fprintf(stream_, " access was here: 0x%16p\n", address);
1481 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_);
1482 fprintf(stream_, "\n");
1483 ABORT();
1484 }
1485 }
1486
1487
1488 uint64_t Simulator::MemoryRead(uint8_t* address, unsigned num_bytes) {
1489 ASSERT(address != NULL);
1490 ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
1491 uint64_t read = 0;
1492 memcpy(&read, address, num_bytes);
1493 return read;
1494 }
1495
1496
1497 uint8_t Simulator::MemoryRead8(uint8_t* address) {
1498 return MemoryRead(address, sizeof(uint8_t));
1499 }
1500
1501
1502 uint16_t Simulator::MemoryRead16(uint8_t* address) {
1503 return MemoryRead(address, sizeof(uint16_t));
1504 }
1505
1506
1507 uint32_t Simulator::MemoryRead32(uint8_t* address) {
1508 return MemoryRead(address, sizeof(uint32_t));
1509 }
1510
1511
1512 float Simulator::MemoryReadFP32(uint8_t* address) {
1513 return rawbits_to_float(MemoryRead32(address));
1514 }
1515
1516
1517 uint64_t Simulator::MemoryRead64(uint8_t* address) {
1518 return MemoryRead(address, sizeof(uint64_t));
1519 }
1520
1521
1522 double Simulator::MemoryReadFP64(uint8_t* address) {
1523 return rawbits_to_double(MemoryRead64(address));
1524 }
1525
1526
1527 void Simulator::MemoryWrite(uint8_t* address,
1528 uint64_t value,
1529 unsigned num_bytes) {
1530 ASSERT(address != NULL);
1531 ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
1532
1533 LogWrite(address, value, num_bytes);
1534 memcpy(address, &value, num_bytes);
1535 }
1536
1537
1538 void Simulator::MemoryWrite32(uint8_t* address, uint32_t value) {
1539 MemoryWrite(address, value, sizeof(uint32_t));
1540 }
1541
1542
1543 void Simulator::MemoryWriteFP32(uint8_t* address, float value) {
1544 MemoryWrite32(address, float_to_rawbits(value));
1545 }
1546
1547
1548 void Simulator::MemoryWrite64(uint8_t* address, uint64_t value) {
1549 MemoryWrite(address, value, sizeof(uint64_t));
1550 }
1551
1552
1553 void Simulator::MemoryWriteFP64(uint8_t* address, double value) {
1554 MemoryWrite64(address, double_to_rawbits(value));
1555 }
1556
1557
1558 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
1559 MoveWideImmediateOp mov_op =
1560 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1561 int64_t new_xn_val = 0;
1562
1563 bool is_64_bits = instr->SixtyFourBits() == 1;
1564 // Shift is limited for W operations.
1565 ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
1566
1567 // Get the shifted immediate.
1568 int64_t shift = instr->ShiftMoveWide() * 16;
1569 int64_t shifted_imm16 = instr->ImmMoveWide() << shift;
1570
1571 // Compute the new value.
1572 switch (mov_op) {
1573 case MOVN_w:
1574 case MOVN_x: {
1575 new_xn_val = ~shifted_imm16;
1576 if (!is_64_bits) new_xn_val &= kWRegMask;
1577 break;
1578 }
1579 case MOVK_w:
1580 case MOVK_x: {
1581 unsigned reg_code = instr->Rd();
1582 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1583 : wreg(reg_code);
1584 new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
1585 break;
1586 }
1587 case MOVZ_w:
1588 case MOVZ_x: {
1589 new_xn_val = shifted_imm16;
1590 break;
1591 }
1592 default:
1593 UNREACHABLE();
1594 }
1595
1596 // Update the destination register.
1597 set_xreg(instr->Rd(), new_xn_val);
1598 }
1599
1600
1601 void Simulator::VisitConditionalSelect(Instruction* instr) {
1602 uint64_t new_val = xreg(instr->Rn());
1603
1604 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1605 new_val = xreg(instr->Rm());
1606 switch (instr->Mask(ConditionalSelectMask)) {
1607 case CSEL_w:
1608 case CSEL_x: break;
1609 case CSINC_w:
1610 case CSINC_x: new_val++; break;
1611 case CSINV_w:
1612 case CSINV_x: new_val = ~new_val; break;
1613 case CSNEG_w:
1614 case CSNEG_x: new_val = -new_val; break;
1615 default: UNIMPLEMENTED();
1616 }
1617 }
1618 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1619 set_reg(reg_size, instr->Rd(), new_val);
1620 }
1621
1622
1623 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
1624 unsigned dst = instr->Rd();
1625 unsigned src = instr->Rn();
1626
1627 switch (instr->Mask(DataProcessing1SourceMask)) {
1628 case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSize)); break;
1629 case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSize)); break;
1630 case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break;
1631 case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break;
1632 case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break;
1633 case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break;
1634 case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break;
1635 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSize)); break;
1636 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSize)); break;
1637 case CLS_w: {
1638 set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSize));
1639 break;
1640 }
1641 case CLS_x: {
1642 set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSize));
1643 break;
1644 }
1645 default: UNIMPLEMENTED();
1646 }
1647 }
1648
1649
1650 uint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) {
1651 ASSERT((num_bits == kWRegSize) || (num_bits == kXRegSize));
1652 uint64_t result = 0;
1653 for (unsigned i = 0; i < num_bits; i++) {
1654 result = (result << 1) | (value & 1);
1655 value >>= 1;
1656 }
1657 return result;
1658 }
1659
1660
1661 uint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) {
1662 // Split the 64-bit value into an 8-bit array, where b[0] is the least
1663 // significant byte, and b[7] is the most significant.
1664 uint8_t bytes[8];
1665 uint64_t mask = 0xff00000000000000UL;
1666 for (int i = 7; i >= 0; i--) {
1667 bytes[i] = (value & mask) >> (i * 8);
1668 mask >>= 8;
1669 }
1670
1671 // Permutation tables for REV instructions.
1672 // permute_table[Reverse16] is used by REV16_x, REV16_w
1673 // permute_table[Reverse32] is used by REV32_x, REV_w
1674 // permute_table[Reverse64] is used by REV_x
1675 ASSERT((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2));
1676 static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1},
1677 {4, 5, 6, 7, 0, 1, 2, 3},
1678 {0, 1, 2, 3, 4, 5, 6, 7} };
1679 uint64_t result = 0;
1680 for (int i = 0; i < 8; i++) {
1681 result <<= 8;
1682 result |= bytes[permute_table[mode][i]];
1683 }
1684 return result;
1685 }
1686
1687
1688 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
1689 // TODO(mcapewel) move these to a higher level file, as they are global
1690 // assumptions.
1691 ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
1692 ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7FFFFFFF);
1693
1694 Shift shift_op = NO_SHIFT;
1695 int64_t result = 0;
1696 switch (instr->Mask(DataProcessing2SourceMask)) {
1697 case SDIV_w: {
1698 int32_t rn = wreg(instr->Rn());
1699 int32_t rm = wreg(instr->Rm());
1700 if ((rn == kWMinInt) && (rm == -1)) {
1701 result = kWMinInt;
1702 } else if (rm == 0) {
1703 // Division by zero can be trapped, but not on A-class processors.
1704 result = 0;
1705 } else {
1706 result = rn / rm;
1707 }
1708 break;
1709 }
1710 case SDIV_x: {
1711 int64_t rn = xreg(instr->Rn());
1712 int64_t rm = xreg(instr->Rm());
1713 if ((rn == kXMinInt) && (rm == -1)) {
1714 result = kXMinInt;
1715 } else if (rm == 0) {
1716 // Division by zero can be trapped, but not on A-class processors.
1717 result = 0;
1718 } else {
1719 result = rn / rm;
1720 }
1721 break;
1722 }
1723 case UDIV_w: {
1724 uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
1725 uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
1726 if (rm == 0) {
1727 // Division by zero can be trapped, but not on A-class processors.
1728 result = 0;
1729 } else {
1730 result = rn / rm;
1731 }
1732 break;
1733 }
1734 case UDIV_x: {
1735 uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
1736 uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
1737 if (rm == 0) {
1738 // Division by zero can be trapped, but not on A-class processors.
1739 result = 0;
1740 } else {
1741 result = rn / rm;
1742 }
1743 break;
1744 }
1745 case LSLV_w:
1746 case LSLV_x: shift_op = LSL; break;
1747 case LSRV_w:
1748 case LSRV_x: shift_op = LSR; break;
1749 case ASRV_w:
1750 case ASRV_x: shift_op = ASR; break;
1751 case RORV_w:
1752 case RORV_x: shift_op = ROR; break;
1753 default: UNIMPLEMENTED();
1754 }
1755
1756 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1757 if (shift_op != NO_SHIFT) {
1758 // Shift distance encoded in the least-significant five/six bits of the
1759 // register.
1760 int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
1761 unsigned shift = wreg(instr->Rm()) & mask;
1762 result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
1763 shift);
1764 }
1765 set_reg(reg_size, instr->Rd(), result);
1766 }
1767
1768
1769 // The algorithm used is described in section 8.2 of
1770 // Hacker's Delight, by Henry S. Warren, Jr.
1771 // It assumes that a right shift on a signed integer is an arithmetic shift.
1772 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
1773 uint64_t u0, v0, w0;
1774 int64_t u1, v1, w1, w2, t;
1775
1776 u0 = u & 0xffffffffL;
1777 u1 = u >> 32;
1778 v0 = v & 0xffffffffL;
1779 v1 = v >> 32;
1780
1781 w0 = u0 * v0;
1782 t = u1 * v0 + (w0 >> 32);
1783 w1 = t & 0xffffffffL;
1784 w2 = t >> 32;
1785 w1 = u0 * v1 + w1;
1786
1787 return u1 * v1 + w2 + (w1 >> 32);
1788 }
1789
1790
1791 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
1792 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1793
1794 int64_t result = 0;
1795 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
1796 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
1797 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
1798 int64_t rn_s32 = reg<int32_t>(instr->Rn());
1799 int64_t rm_s32 = reg<int32_t>(instr->Rm());
1800 switch (instr->Mask(DataProcessing3SourceMask)) {
1801 case MADD_w:
1802 case MADD_x:
1803 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
1804 break;
1805 case MSUB_w:
1806 case MSUB_x:
1807 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
1808 break;
1809 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
1810 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
1811 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
1812 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
1813 case SMULH_x:
1814 ASSERT(instr->Ra() == kZeroRegCode);
1815 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
1816 break;
1817 default: UNIMPLEMENTED();
1818 }
1819 set_reg(reg_size, instr->Rd(), result);
1820 }
1821
1822
1823 void Simulator::VisitBitfield(Instruction* instr) {
1824 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1825 int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
1826 int64_t R = instr->ImmR();
1827 int64_t S = instr->ImmS();
1828 int64_t diff = S - R;
1829 int64_t mask;
1830 if (diff >= 0) {
1831 mask = diff < reg_size - 1 ? (1L << (diff + 1)) - 1
1832 : reg_mask;
1833 } else {
1834 mask = ((1L << (S + 1)) - 1);
1835 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
1836 diff += reg_size;
1837 }
1838
1839 // inzero indicates if the extracted bitfield is inserted into the
1840 // destination register value or in zero.
1841 // If extend is true, extend the sign of the extracted bitfield.
1842 bool inzero = false;
1843 bool extend = false;
1844 switch (instr->Mask(BitfieldMask)) {
1845 case BFM_x:
1846 case BFM_w:
1847 break;
1848 case SBFM_x:
1849 case SBFM_w:
1850 inzero = true;
1851 extend = true;
1852 break;
1853 case UBFM_x:
1854 case UBFM_w:
1855 inzero = true;
1856 break;
1857 default:
1858 UNIMPLEMENTED();
1859 }
1860
1861 int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
1862 int64_t src = reg(reg_size, instr->Rn());
1863 // Rotate source bitfield into place.
1864 int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
1865 // Determine the sign extension.
1866 int64_t topbits = ((1L << (reg_size - diff - 1)) - 1) << (diff + 1);
1867 int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
1868
1869 // Merge sign extension, dest/zero and bitfield.
1870 result = signbits | (result & mask) | (dst & ~mask);
1871
1872 set_reg(reg_size, instr->Rd(), result);
1873 }
1874
1875
1876 void Simulator::VisitExtract(Instruction* instr) {
1877 unsigned lsb = instr->ImmS();
1878 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
1879 : kWRegSize;
1880 set_reg(reg_size,
1881 instr->Rd(),
1882 (static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb) |
1883 (reg(reg_size, instr->Rn()) << (reg_size - lsb)));
1884 }
1885
1886
1887 void Simulator::VisitFPImmediate(Instruction* instr) {
1888 AssertSupportedFPCR();
1889
1890 unsigned dest = instr->Rd();
1891 switch (instr->Mask(FPImmediateMask)) {
1892 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
1893 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
1894 default: UNREACHABLE();
1895 }
1896 }
1897
1898
1899 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
1900 AssertSupportedFPCR();
1901
1902 unsigned dst = instr->Rd();
1903 unsigned src = instr->Rn();
1904
1905 FPRounding round = RMode();
1906
1907 switch (instr->Mask(FPIntegerConvertMask)) {
1908 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
1909 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
1910 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
1911 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
1912 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
1913 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
1914 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
1915 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
1916 case FCVTMS_ws:
1917 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
1918 break;
1919 case FCVTMS_xs:
1920 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
1921 break;
1922 case FCVTMS_wd:
1923 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
1924 break;
1925 case FCVTMS_xd:
1926 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
1927 break;
1928 case FCVTMU_ws:
1929 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
1930 break;
1931 case FCVTMU_xs:
1932 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
1933 break;
1934 case FCVTMU_wd:
1935 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
1936 break;
1937 case FCVTMU_xd:
1938 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
1939 break;
1940 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
1941 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
1942 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
1943 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
1944 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
1945 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
1946 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
1947 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
1948 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
1949 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
1950 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
1951 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
1952 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
1953 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
1954 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
1955 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
1956 case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
1957 case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
1958 case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
1959 case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
1960
1961 // A 32-bit input can be handled in the same way as a 64-bit input, since
1962 // the sign- or zero-extension will not affect the conversion.
1963 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
1964 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
1965 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
1966 case UCVTF_dw: {
1967 set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
1968 break;
1969 }
1970 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
1971 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
1972 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
1973 case UCVTF_sw: {
1974 set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
1975 break;
1976 }
1977
1978 default: UNREACHABLE();
1979 }
1980 }
1981
1982
1983 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
1984 AssertSupportedFPCR();
1985
1986 unsigned dst = instr->Rd();
1987 unsigned src = instr->Rn();
1988 int fbits = 64 - instr->FPScale();
1989
1990 FPRounding round = RMode();
1991
1992 switch (instr->Mask(FPFixedPointConvertMask)) {
1993 // A 32-bit input can be handled in the same way as a 64-bit input, since
1994 // the sign- or zero-extension will not affect the conversion.
1995 case SCVTF_dx_fixed:
1996 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
1997 break;
1998 case SCVTF_dw_fixed:
1999 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2000 break;
2001 case UCVTF_dx_fixed:
2002 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2003 break;
2004 case UCVTF_dw_fixed: {
2005 set_dreg(dst,
2006 UFixedToDouble(reg<uint32_t>(src), fbits, round));
2007 break;
2008 }
2009 case SCVTF_sx_fixed:
2010 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2011 break;
2012 case SCVTF_sw_fixed:
2013 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2014 break;
2015 case UCVTF_sx_fixed:
2016 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2017 break;
2018 case UCVTF_sw_fixed: {
2019 set_sreg(dst,
2020 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2021 break;
2022 }
2023 default: UNREACHABLE();
2024 }
2025 }
2026
2027
2028 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
2029 value = FPRoundInt(value, rmode);
2030 if (value >= kWMaxInt) {
2031 return kWMaxInt;
2032 } else if (value < kWMinInt) {
2033 return kWMinInt;
2034 }
2035 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
2036 }
2037
2038
2039 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
2040 value = FPRoundInt(value, rmode);
2041 if (value >= kXMaxInt) {
2042 return kXMaxInt;
2043 } else if (value < kXMinInt) {
2044 return kXMinInt;
2045 }
2046 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
2047 }
2048
2049
2050 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
2051 value = FPRoundInt(value, rmode);
2052 if (value >= kWMaxUInt) {
2053 return kWMaxUInt;
2054 } else if (value < 0.0) {
2055 return 0;
2056 }
2057 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
2058 }
2059
2060
2061 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
2062 value = FPRoundInt(value, rmode);
2063 if (value >= kXMaxUInt) {
2064 return kXMaxUInt;
2065 } else if (value < 0.0) {
2066 return 0;
2067 }
2068 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
2069 }
2070
2071
2072 void Simulator::VisitFPCompare(Instruction* instr) {
2073 AssertSupportedFPCR();
2074
2075 unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
2076 double fn_val = fpreg(reg_size, instr->Rn());
2077
2078 switch (instr->Mask(FPCompareMask)) {
2079 case FCMP_s:
2080 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
2081 case FCMP_s_zero:
2082 case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
2083 default: UNIMPLEMENTED();
2084 }
2085 }
2086
2087
2088 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2089 AssertSupportedFPCR();
2090
2091 switch (instr->Mask(FPConditionalCompareMask)) {
2092 case FCCMP_s:
2093 case FCCMP_d: {
2094 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2095 // If the condition passes, set the status flags to the result of
2096 // comparing the operands.
2097 unsigned reg_size = instr->FPType() == FP32 ? kSRegSize : kDRegSize;
2098 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
2099 } else {
2100 // If the condition fails, set the status flags to the nzcv immediate.
2101 nzcv().SetFlags(instr->Nzcv());
2102 }
2103 break;
2104 }
2105 default: UNIMPLEMENTED();
2106 }
2107 }
2108
2109
2110 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2111 AssertSupportedFPCR();
2112
2113 Instr selected;
2114 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2115 selected = instr->Rn();
2116 } else {
2117 selected = instr->Rm();
2118 }
2119
2120 switch (instr->Mask(FPConditionalSelectMask)) {
2121 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2122 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2123 default: UNIMPLEMENTED();
2124 }
2125 }
2126
2127
2128 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2129 AssertSupportedFPCR();
2130
2131 unsigned fd = instr->Rd();
2132 unsigned fn = instr->Rn();
2133
2134 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2135 case FMOV_s: set_sreg(fd, sreg(fn)); break;
2136 case FMOV_d: set_dreg(fd, dreg(fn)); break;
2137 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break;
2138 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break;
2139 case FNEG_s: set_sreg(fd, -sreg(fn)); break;
2140 case FNEG_d: set_dreg(fd, -dreg(fn)); break;
2141 case FSQRT_s: set_sreg(fd, std::sqrt(sreg(fn))); break;
2142 case FSQRT_d: set_dreg(fd, std::sqrt(dreg(fn))); break;
2143 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break;
2144 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break;
2145 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
2146 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
2147 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
2148 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
2149 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
2150 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
2151 default: UNIMPLEMENTED();
2152 }
2153 }
2154
2155
2156 // Assemble the specified IEEE-754 components into the target type and apply
2157 // appropriate rounding.
2158 // sign: 0 = positive, 1 = negative
2159 // exponent: Unbiased IEEE-754 exponent.
2160 // mantissa: The mantissa of the input. The top bit (which is not encoded for
2161 // normal IEEE-754 values) must not be omitted. This bit has the
2162 // value 'pow(2, exponent)'.
2163 //
2164 // The input value is assumed to be a normalized value. That is, the input may
2165 // not be infinity or NaN. If the source value is subnormal, it must be
2166 // normalized before calling this function such that the highest set bit in the
2167 // mantissa has the value 'pow(2, exponent)'.
2168 //
2169 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
2170 // calling a templated FPRound.
2171 template <class T, int ebits, int mbits>
2172 static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
2173 FPRounding round_mode) {
2174 ASSERT((sign == 0) || (sign == 1));
2175
2176 // Only the FPTieEven rounding mode is implemented.
2177 ASSERT(round_mode == FPTieEven);
2178 USE(round_mode);
2179
2180 // Rounding can promote subnormals to normals, and normals to infinities. For
2181 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
2182 // encodable as a float, but rounding based on the low-order mantissa bits
2183 // could make it overflow. With ties-to-even rounding, this value would become
2184 // an infinity.
2185
2186 // ---- Rounding Method ----
2187 //
2188 // The exponent is irrelevant in the rounding operation, so we treat the
2189 // lowest-order bit that will fit into the result ('onebit') as having
2190 // the value '1'. Similarly, the highest-order bit that won't fit into
2191 // the result ('halfbit') has the value '0.5'. The 'point' sits between
2192 // 'onebit' and 'halfbit':
2193 //
2194 // These bits fit into the result.
2195 // |---------------------|
2196 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2197 // ||
2198 // / |
2199 // / halfbit
2200 // onebit
2201 //
2202 // For subnormal outputs, the range of representable bits is smaller and
2203 // the position of onebit and halfbit depends on the exponent of the
2204 // input, but the method is otherwise similar.
2205 //
2206 // onebit(frac)
2207 // |
2208 // | halfbit(frac) halfbit(adjusted)
2209 // | / /
2210 // | | |
2211 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
2212 // 0b00.0... -> 0b00.0... -> 0b00
2213 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
2214 // 0b00.1... -> 0b00.1... -> 0b01
2215 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
2216 // 0b01.0... -> 0b01.0... -> 0b01
2217 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
2218 // 0b01.1... -> 0b01.1... -> 0b10
2219 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
2220 // 0b10.0... -> 0b10.0... -> 0b10
2221 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
2222 // 0b10.1... -> 0b10.1... -> 0b11
2223 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
2224 // ... / | / |
2225 // / | / |
2226 // / |
2227 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
2228 //
2229 // mantissa = (mantissa >> shift) + halfbit(adjusted);
2230
2231 static const int mantissa_offset = 0;
2232 static const int exponent_offset = mantissa_offset + mbits;
2233 static const int sign_offset = exponent_offset + ebits;
2234 STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1));
2235
2236 // Bail out early for zero inputs.
2237 if (mantissa == 0) {
2238 return sign << sign_offset;
2239 }
2240
2241 // If all bits in the exponent are set, the value is infinite or NaN.
2242 // This is true for all binary IEEE-754 formats.
2243 static const int infinite_exponent = (1 << ebits) - 1;
2244 static const int max_normal_exponent = infinite_exponent - 1;
2245
2246 // Apply the exponent bias to encode it for the result. Doing this early makes
2247 // it easy to detect values that will be infinite or subnormal.
2248 exponent += max_normal_exponent >> 1;
2249
2250 if (exponent > max_normal_exponent) {
2251 // Overflow: The input is too large for the result type to represent. The
2252 // FPTieEven rounding mode handles overflows using infinities.
2253 exponent = infinite_exponent;
2254 mantissa = 0;
2255 return (sign << sign_offset) |
2256 (exponent << exponent_offset) |
2257 (mantissa << mantissa_offset);
2258 }
2259
2260 // Calculate the shift required to move the top mantissa bit to the proper
2261 // place in the destination type.
2262 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
2263 int shift = highest_significant_bit - mbits;
2264
2265 if (exponent <= 0) {
2266 // The output will be subnormal (before rounding).
2267
2268 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
2269 // is necessary because the exponent of a subnormal value (encoded as 0) is
2270 // the same as the exponent of the smallest normal value (encoded as 1).
2271 shift += -exponent + 1;
2272
2273 // Handle inputs that would produce a zero output.
2274 //
2275 // Shifts higher than highest_significant_bit+1 will always produce a zero
2276 // result. A shift of exactly highest_significant_bit+1 might produce a
2277 // non-zero result after rounding.
2278 if (shift > (highest_significant_bit + 1)) {
2279 // The result will always be +/-0.0.
2280 return sign << sign_offset;
2281 }
2282
2283 // Properly encode the exponent for a subnormal output.
2284 exponent = 0;
2285 } else {
2286 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
2287 // normal values.
2288 mantissa &= ~(1UL << highest_significant_bit);
2289 }
2290
2291 if (shift > 0) {
2292 // We have to shift the mantissa to the right. Some precision is lost, so we
2293 // need to apply rounding.
2294 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
2295 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
2296 uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
2297 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
2298
2299 T result = (sign << sign_offset) |
2300 (exponent << exponent_offset) |
2301 ((mantissa >> shift) << mantissa_offset);
2302
2303 // A very large mantissa can overflow during rounding. If this happens, the
2304 // exponent should be incremented and the mantissa set to 1.0 (encoded as
2305 // 0). Applying halfbit_adjusted after assembling the float has the nice
2306 // side-effect that this case is handled for free.
2307 //
2308 // This also handles cases where a very large finite value overflows to
2309 // infinity, or where a very large subnormal value overflows to become
2310 // normal.
2311 return result + halfbit_adjusted;
2312 } else {
2313 // We have to shift the mantissa to the left (or not at all). The input
2314 // mantissa is exactly representable in the output mantissa, so apply no
2315 // rounding correction.
2316 return (sign << sign_offset) |
2317 (exponent << exponent_offset) |
2318 ((mantissa << -shift) << mantissa_offset);
2319 }
2320 }
2321
2322
2323 // See FPRound for a description of this function.
2324 static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
2325 uint64_t mantissa, FPRounding round_mode) {
2326 int64_t bits =
2327 FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
2328 exponent,
2329 mantissa,
2330 round_mode);
2331 return rawbits_to_double(bits);
2332 }
2333
2334
2335 // See FPRound for a description of this function.
2336 static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
2337 uint64_t mantissa, FPRounding round_mode) {
2338 int32_t bits =
2339 FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
2340 exponent,
2341 mantissa,
2342 round_mode);
2343 return rawbits_to_float(bits);
2344 }
2345
2346
2347 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
2348 if (src >= 0) {
2349 return UFixedToDouble(src, fbits, round);
2350 } else {
2351 // This works for all negative values, including INT64_MIN.
2352 return -UFixedToDouble(-src, fbits, round);
2353 }
2354 }
2355
2356
2357 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
2358 // An input of 0 is a special case because the result is effectively
2359 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2360 if (src == 0) {
2361 return 0.0;
2362 }
2363
2364 // Calculate the exponent. The highest significant bit will have the value
2365 // 2^exponent.
2366 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2367 const int64_t exponent = highest_significant_bit - fbits;
2368
2369 return FPRoundToDouble(0, exponent, src, round);
2370 }
2371
2372
2373 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
2374 if (src >= 0) {
2375 return UFixedToFloat(src, fbits, round);
2376 } else {
2377 // This works for all negative values, including INT64_MIN.
2378 return -UFixedToFloat(-src, fbits, round);
2379 }
2380 }
2381
2382
2383 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
2384 // An input of 0 is a special case because the result is effectively
2385 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2386 if (src == 0) {
2387 return 0.0f;
2388 }
2389
2390 // Calculate the exponent. The highest significant bit will have the value
2391 // 2^exponent.
2392 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2393 const int32_t exponent = highest_significant_bit - fbits;
2394
2395 return FPRoundToFloat(0, exponent, src, round);
2396 }
2397
2398
2399 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
2400 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
2401 (value == kFP64NegativeInfinity) || std::isnan(value)) {
2402 return value;
2403 }
2404
2405 double int_result = floor(value);
2406 double error = value - int_result;
2407 switch (round_mode) {
2408 case FPTieAway: {
2409 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2410 // result is positive, round up.
2411 if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
2412 int_result++;
2413 }
2414 break;
2415 }
2416 case FPTieEven: {
2417 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2418 // result is odd, round up.
2419 if ((error > 0.5) ||
2420 ((error == 0.5) && (fmod(int_result, 2) != 0))) {
2421 int_result++;
2422 }
2423 break;
2424 }
2425 case FPZero: {
2426 // If value > 0 then we take floor(value)
2427 // otherwise, ceil(value)
2428 if (value < 0) {
2429 int_result = ceil(value);
2430 }
2431 break;
2432 }
2433 case FPNegativeInfinity: {
2434 // We always use floor(value).
2435 break;
2436 }
2437 default: UNIMPLEMENTED();
2438 }
2439 return int_result;
2440 }
2441
2442
2443 double Simulator::FPToDouble(float value) {
2444 switch (std::fpclassify(value)) {
2445 case FP_NAN: {
2446 // Convert NaNs as the processor would, assuming that FPCR.DN (default
2447 // NaN) is not set:
2448 // - The sign is propagated.
2449 // - The payload (mantissa) is transferred entirely, except that the top
2450 // bit is forced to '1', making the result a quiet NaN. The unused
2451 // (low-order) payload bits are set to 0.
2452 uint32_t raw = float_to_rawbits(value);
2453
2454 uint64_t sign = raw >> 31;
2455 uint64_t exponent = (1 << 11) - 1;
2456 uint64_t payload = unsigned_bitextract_64(21, 0, raw);
2457 payload <<= (52 - 23); // The unused low-order bits should be 0.
2458 payload |= (1L << 51); // Force a quiet NaN.
2459
2460 return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
2461 }
2462
2463 case FP_ZERO:
2464 case FP_NORMAL:
2465 case FP_SUBNORMAL:
2466 case FP_INFINITE: {
2467 // All other inputs are preserved in a standard cast, because every value
2468 // representable using an IEEE-754 float is also representable using an
2469 // IEEE-754 double.
2470 return static_cast<double>(value);
2471 }
2472 }
2473
2474 UNREACHABLE();
2475 return static_cast<double>(value);
2476 }
2477
2478
2479 float Simulator::FPToFloat(double value, FPRounding round_mode) {
2480 // Only the FPTieEven rounding mode is implemented.
2481 ASSERT(round_mode == FPTieEven);
2482 USE(round_mode);
2483
2484 switch (std::fpclassify(value)) {
2485 case FP_NAN: {
2486 // Convert NaNs as the processor would, assuming that FPCR.DN (default
2487 // NaN) is not set:
2488 // - The sign is propagated.
2489 // - The payload (mantissa) is transferred as much as possible, except
2490 // that the top bit is forced to '1', making the result a quiet NaN.
2491 uint64_t raw = double_to_rawbits(value);
2492
2493 uint32_t sign = raw >> 63;
2494 uint32_t exponent = (1 << 8) - 1;
2495 uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw);
2496 payload |= (1 << 22); // Force a quiet NaN.
2497
2498 return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
2499 }
2500
2501 case FP_ZERO:
2502 case FP_INFINITE: {
2503 // In a C++ cast, any value representable in the target type will be
2504 // unchanged. This is always the case for +/-0.0 and infinities.
2505 return static_cast<float>(value);
2506 }
2507
2508 case FP_NORMAL:
2509 case FP_SUBNORMAL: {
2510 // Convert double-to-float as the processor would, assuming that FPCR.FZ
2511 // (flush-to-zero) is not set.
2512 uint64_t raw = double_to_rawbits(value);
2513 // Extract the IEEE-754 double components.
2514 uint32_t sign = raw >> 63;
2515 // Extract the exponent and remove the IEEE-754 encoding bias.
2516 int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023;
2517 // Extract the mantissa and add the implicit '1' bit.
2518 uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
2519 if (std::fpclassify(value) == FP_NORMAL) {
2520 mantissa |= (1UL << 52);
2521 }
2522 return FPRoundToFloat(sign, exponent, mantissa, round_mode);
2523 }
2524 }
2525
2526 UNREACHABLE();
2527 return value;
2528 }
2529
2530
2531 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2532 AssertSupportedFPCR();
2533
2534 unsigned fd = instr->Rd();
2535 unsigned fn = instr->Rn();
2536 unsigned fm = instr->Rm();
2537
2538 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2539 case FADD_s: set_sreg(fd, sreg(fn) + sreg(fm)); break;
2540 case FADD_d: set_dreg(fd, dreg(fn) + dreg(fm)); break;
2541 case FSUB_s: set_sreg(fd, sreg(fn) - sreg(fm)); break;
2542 case FSUB_d: set_dreg(fd, dreg(fn) - dreg(fm)); break;
2543 case FMUL_s: set_sreg(fd, sreg(fn) * sreg(fm)); break;
2544 case FMUL_d: set_dreg(fd, dreg(fn) * dreg(fm)); break;
2545 case FDIV_s: set_sreg(fd, sreg(fn) / sreg(fm)); break;
2546 case FDIV_d: set_dreg(fd, dreg(fn) / dreg(fm)); break;
2547 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
2548 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
2549 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
2550 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
2551 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); break;
2552 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); break;
2553 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); break;
2554 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); break;
2555 default: UNIMPLEMENTED();
2556 }
2557 }
2558
2559
2560 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2561 AssertSupportedFPCR();
2562
2563 unsigned fd = instr->Rd();
2564 unsigned fn = instr->Rn();
2565 unsigned fm = instr->Rm();
2566 unsigned fa = instr->Ra();
2567
2568 // The C99 (and C++11) fma function performs a fused multiply-accumulate.
2569 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2570 // fd = fa +/- (fn * fm)
2571 case FMADD_s: set_sreg(fd, fmaf(sreg(fn), sreg(fm), sreg(fa))); break;
2572 case FMSUB_s: set_sreg(fd, fmaf(-sreg(fn), sreg(fm), sreg(fa))); break;
2573 case FMADD_d: set_dreg(fd, fma(dreg(fn), dreg(fm), dreg(fa))); break;
2574 case FMSUB_d: set_dreg(fd, fma(-dreg(fn), dreg(fm), dreg(fa))); break;
2575 // Variants of the above where the result is negated.
2576 case FNMADD_s: set_sreg(fd, -fmaf(sreg(fn), sreg(fm), sreg(fa))); break;
2577 case FNMSUB_s: set_sreg(fd, -fmaf(-sreg(fn), sreg(fm), sreg(fa))); break;
2578 case FNMADD_d: set_dreg(fd, -fma(dreg(fn), dreg(fm), dreg(fa))); break;
2579 case FNMSUB_d: set_dreg(fd, -fma(-dreg(fn), dreg(fm), dreg(fa))); break;
2580 default: UNIMPLEMENTED();
2581 }
2582 }
2583
2584
2585 template <typename T>
2586 T Simulator::FPMax(T a, T b) {
2587 if (IsSignallingNaN(a)) {
2588 return a;
2589 } else if (IsSignallingNaN(b)) {
2590 return b;
2591 } else if (std::isnan(a)) {
2592 ASSERT(IsQuietNaN(a));
2593 return a;
2594 } else if (std::isnan(b)) {
2595 ASSERT(IsQuietNaN(b));
2596 return b;
2597 }
2598
2599 if ((a == 0.0) && (b == 0.0) &&
2600 (copysign(1.0, a) != copysign(1.0, b))) {
2601 // a and b are zero, and the sign differs: return +0.0.
2602 return 0.0;
2603 } else {
2604 return (a > b) ? a : b;
2605 }
2606 }
2607
2608
2609 template <typename T>
2610 T Simulator::FPMaxNM(T a, T b) {
2611 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2612 a = kFP64NegativeInfinity;
2613 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2614 b = kFP64NegativeInfinity;
2615 }
2616 return FPMax(a, b);
2617 }
2618
2619 template <typename T>
2620 T Simulator::FPMin(T a, T b) {
2621 if (IsSignallingNaN(a)) {
2622 return a;
2623 } else if (IsSignallingNaN(b)) {
2624 return b;
2625 } else if (std::isnan(a)) {
2626 ASSERT(IsQuietNaN(a));
2627 return a;
2628 } else if (std::isnan(b)) {
2629 ASSERT(IsQuietNaN(b));
2630 return b;
2631 }
2632
2633 if ((a == 0.0) && (b == 0.0) &&
2634 (copysign(1.0, a) != copysign(1.0, b))) {
2635 // a and b are zero, and the sign differs: return -0.0.
2636 return -0.0;
2637 } else {
2638 return (a < b) ? a : b;
2639 }
2640 }
2641
2642
2643 template <typename T>
2644 T Simulator::FPMinNM(T a, T b) {
2645 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2646 a = kFP64PositiveInfinity;
2647 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2648 b = kFP64PositiveInfinity;
2649 }
2650 return FPMin(a, b);
2651 }
2652
2653
2654 void Simulator::VisitSystem(Instruction* instr) {
2655 // Some system instructions hijack their Op and Cp fields to represent a
2656 // range of immediates instead of indicating a different instruction. This
2657 // makes the decoding tricky.
2658 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2659 switch (instr->Mask(SystemSysRegMask)) {
2660 case MRS: {
2661 switch (instr->ImmSystemRegister()) {
2662 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
2663 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
2664 default: UNIMPLEMENTED();
2665 }
2666 break;
2667 }
2668 case MSR: {
2669 switch (instr->ImmSystemRegister()) {
2670 case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break;
2671 case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break;
2672 default: UNIMPLEMENTED();
2673 }
2674 break;
2675 }
2676 }
2677 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2678 ASSERT(instr->Mask(SystemHintMask) == HINT);
2679 switch (instr->ImmHint()) {
2680 case NOP: break;
2681 default: UNIMPLEMENTED();
2682 }
2683 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2684 __sync_synchronize();
2685 } else {
2686 UNIMPLEMENTED();
2687 }
2688 }
2689
2690
2691 bool Simulator::GetValue(const char* desc, int64_t* value) {
2692 int regnum = CodeFromName(desc);
2693 if (regnum >= 0) {
2694 unsigned code = regnum;
2695 if (code == kZeroRegCode) {
2696 // Catch the zero register and return 0.
2697 *value = 0;
2698 return true;
2699 } else if (code == kSPRegInternalCode) {
2700 // Translate the stack pointer code to 31, for Reg31IsStackPointer.
2701 code = 31;
2702 }
2703 if (desc[0] == 'w') {
2704 *value = wreg(code, Reg31IsStackPointer);
2705 } else {
2706 *value = xreg(code, Reg31IsStackPointer);
2707 }
2708 return true;
2709 } else if (strncmp(desc, "0x", 2) == 0) {
2710 return SScanF(desc + 2, "%" SCNx64,
2711 reinterpret_cast<uint64_t*>(value)) == 1;
2712 } else {
2713 return SScanF(desc, "%" SCNu64,
2714 reinterpret_cast<uint64_t*>(value)) == 1;
2715 }
2716 }
2717
2718
2719 bool Simulator::PrintValue(const char* desc) {
2720 // Define some colour codes to use for the register dump.
2721 // TODO(jbramley): Find a more elegant way of defining these.
2722 char const * const clr_normal = FLAG_log_colour ? "\033[m" : "";
2723 char const * const clr_reg_name = FLAG_log_colour ? "\033[1;34m" : "";
2724 char const * const clr_reg_value = FLAG_log_colour ? "\033[1;36m" : "";
2725 char const * const clr_fpreg_name = FLAG_log_colour ? "\033[1;33m" : "";
2726 char const * const clr_fpreg_value = FLAG_log_colour ? "\033[1;35m" : "";
2727
2728 if (strcmp(desc, "csp") == 0) {
2729 ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
2730 PrintF("%s csp:%s 0x%016" PRIx64 "%s\n",
2731 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
2732 return true;
2733 } else if (strcmp(desc, "wcsp") == 0) {
2734 ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
2735 PrintF("%s wcsp:%s 0x%08" PRIx32 "%s\n",
2736 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
2737 return true;
2738 }
2739
2740 int i = CodeFromName(desc);
2741 if (i == -1) {
2742 return false;
2743 }
2744 ASSERT(i >= 0);
2745
2746 if (desc[0] == 'v') {
2747 PrintF("%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
2748 clr_fpreg_name, VRegNameForCode(i),
2749 clr_fpreg_value, double_to_rawbits(dreg(i)),
2750 clr_normal,
2751 clr_fpreg_name, DRegNameForCode(i),
2752 clr_fpreg_value, dreg(i),
2753 clr_fpreg_name, SRegNameForCode(i),
2754 clr_fpreg_value, sreg(i),
2755 clr_normal);
2756 return true;
2757 } else if (desc[0] == 'd') {
2758 PrintF("%s %s:%s %g%s\n",
2759 clr_fpreg_name, DRegNameForCode(i),
2760 clr_fpreg_value, dreg(i),
2761 clr_normal);
2762 return true;
2763 } else if (desc[0] == 's') {
2764 PrintF("%s %s:%s %g%s\n",
2765 clr_fpreg_name, SRegNameForCode(i),
2766 clr_fpreg_value, sreg(i),
2767 clr_normal);
2768 return true;
2769 } else if (desc[0] == 'w') {
2770 PrintF("%s %s:%s 0x%08" PRIx32 "%s\n",
2771 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
2772 return true;
2773 } else {
2774 // X register names have a wide variety of starting characters, but anything
2775 // else will be an X register.
2776 PrintF("%s %s:%s 0x%016" PRIx64 "%s\n",
2777 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
2778 return true;
2779 }
2780 }
2781
2782
2783 void Simulator::Debug() {
2784 #define COMMAND_SIZE 63
2785 #define ARG_SIZE 255
2786
2787 #define STR(a) #a
2788 #define XSTR(a) STR(a)
2789
2790 char cmd[COMMAND_SIZE + 1];
2791 char arg1[ARG_SIZE + 1];
2792 char arg2[ARG_SIZE + 1];
2793 char* argv[3] = { cmd, arg1, arg2 };
2794
2795 // Make sure to have a proper terminating character if reaching the limit.
2796 cmd[COMMAND_SIZE] = 0;
2797 arg1[ARG_SIZE] = 0;
2798 arg2[ARG_SIZE] = 0;
2799
2800 bool done = false;
2801 bool cleared_log_disasm_bit = false;
2802
2803 while (!done) {
2804 // Disassemble the next instruction to execute before doing anything else.
2805 PrintInstructionsAt(pc_, 1);
2806 // Read the command line.
2807 char* line = ReadLine("sim> ");
2808 if (line == NULL) {
2809 break;
2810 } else {
2811 // Repeat last command by default.
2812 char* last_input = last_debugger_input();
2813 if (strcmp(line, "\n") == 0 && (last_input != NULL)) {
2814 DeleteArray(line);
2815 line = last_input;
2816 } else {
2817 // Update the latest command ran
2818 set_last_debugger_input(line);
2819 }
2820
2821 // Use sscanf to parse the individual parts of the command line. At the
2822 // moment no command expects more than two parameters.
2823 int argc = SScanF(line,
2824 "%" XSTR(COMMAND_SIZE) "s "
2825 "%" XSTR(ARG_SIZE) "s "
2826 "%" XSTR(ARG_SIZE) "s",
2827 cmd, arg1, arg2);
2828
2829 // stepi / si ------------------------------------------------------------
2830 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
2831 // We are about to execute instructions, after which by default we
2832 // should increment the pc_. If it was set when reaching this debug
2833 // instruction, it has not been cleared because this instruction has not
2834 // completed yet. So clear it manually.
2835 pc_modified_ = false;
2836
2837 if (argc == 1) {
2838 ExecuteInstruction();
2839 } else {
2840 int64_t number_of_instructions_to_execute = 1;
2841 GetValue(arg1, &number_of_instructions_to_execute);
2842
2843 set_log_parameters(log_parameters() | LOG_DISASM);
2844 while (number_of_instructions_to_execute-- > 0) {
2845 ExecuteInstruction();
2846 }
2847 set_log_parameters(log_parameters() & ~LOG_DISASM);
2848 PrintF("\n");
2849 }
2850
2851 // If it was necessary, the pc has already been updated or incremented
2852 // when executing the instruction. So we do not want it to be updated
2853 // again. It will be cleared when exiting.
2854 pc_modified_ = true;
2855
2856 // next / n --------------------------------------------------------------
2857 } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
2858 // Tell the simulator to break after the next executed BL.
2859 break_on_next_ = true;
2860 // Continue.
2861 done = true;
2862
2863 // continue / cont / c ---------------------------------------------------
2864 } else if ((strcmp(cmd, "continue") == 0) ||
2865 (strcmp(cmd, "cont") == 0) ||
2866 (strcmp(cmd, "c") == 0)) {
2867 // Leave the debugger shell.
2868 done = true;
2869
2870 // disassemble / disasm / di ---------------------------------------------
2871 } else if (strcmp(cmd, "disassemble") == 0 ||
2872 strcmp(cmd, "disasm") == 0 ||
2873 strcmp(cmd, "di") == 0) {
2874 int64_t n_of_instrs_to_disasm = 10; // default value.
2875 int64_t address = reinterpret_cast<int64_t>(pc_); // default value.
2876 if (argc >= 2) { // disasm <n of instrs>
2877 GetValue(arg1, &n_of_instrs_to_disasm);
2878 }
2879 if (argc >= 3) { // disasm <n of instrs> <address>
2880 GetValue(arg2, &address);
2881 }
2882
2883 // Disassemble.
2884 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
2885 n_of_instrs_to_disasm);
2886 PrintF("\n");
2887
2888 // print / p -------------------------------------------------------------
2889 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
2890 if (argc == 2) {
2891 if (strcmp(arg1, "all") == 0) {
2892 // TODO(all): better support for printing in the debugger.
2893 PrintRegisters(true);
2894 PrintFPRegisters(true);
2895 } else {
2896 if (!PrintValue(arg1)) {
2897 PrintF("%s unrecognized\n", arg1);
2898 }
2899 }
2900 } else {
2901 PrintF(
2902 "print <register>\n"
2903 " Print the content of a register. (alias 'p')\n"
2904 " 'print all' will print all registers.\n"
2905 " Use 'printobject' to get more details about the value.\n");
2906 }
2907
2908 // printobject / po ------------------------------------------------------
2909 } else if ((strcmp(cmd, "printobject") == 0) ||
2910 (strcmp(cmd, "po") == 0)) {
2911 if (argc == 2) {
2912 int64_t value;
2913 if (GetValue(arg1, &value)) {
2914 Object* obj = reinterpret_cast<Object*>(value);
2915 PrintF("%s: \n", arg1);
2916 #ifdef DEBUG
2917 obj->PrintLn();
2918 #else
2919 obj->ShortPrint();
2920 PrintF("\n");
2921 #endif
2922 } else {
2923 PrintF("%s unrecognized\n", arg1);
2924 }
2925 } else {
2926 PrintF("printobject <value>\n"
2927 "printobject <register>\n"
2928 " Print details about the value. (alias 'po')\n");
2929 }
2930
2931 // stack / mem ----------------------------------------------------------
2932 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
2933 int64_t* cur = NULL;
2934 int64_t* end = NULL;
2935 int next_arg = 1;
2936
2937 if (strcmp(cmd, "stack") == 0) {
2938 cur = reinterpret_cast<int64_t*>(jssp());
2939
2940 } else { // "mem"
2941 int64_t value;
2942 if (!GetValue(arg1, &value)) {
2943 PrintF("%s unrecognized\n", arg1);
2944 continue;
2945 }
2946 cur = reinterpret_cast<int64_t*>(value);
2947 next_arg++;
2948 }
2949
2950 int64_t words;
2951 if (argc == next_arg) {
2952 words = 10;
2953 } else if (argc == next_arg + 1) {
2954 if (!GetValue(argv[next_arg], &words)) {
2955 PrintF("%s unrecognized\n", argv[next_arg]);
2956 PrintF("Printing 10 double words by default");
2957 words = 10;
2958 }
2959 }
2960 end = cur + words;
2961
2962 while (cur < end) {
2963 PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64,
2964 reinterpret_cast<uint64_t>(cur), *cur, *cur);
2965 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
2966 int64_t value = *cur;
2967 Heap* current_heap = v8::internal::Isolate::Current()->heap();
2968 if (((value & 1) == 0) || current_heap->Contains(obj)) {
2969 PrintF(" (");
2970 if ((value & kSmiTagMask) == 0) {
2971 STATIC_ASSERT(kSmiValueSize == 32);
2972 int32_t untagged = (value >> kSmiShift) & 0xffffffff;
2973 PrintF("smi %" PRId32, untagged);
2974 } else {
2975 obj->ShortPrint();
2976 }
2977 PrintF(")");
2978 }
2979 PrintF("\n");
2980 cur++;
2981 }
2982
2983 // trace / t -------------------------------------------------------------
2984 } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
2985 if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
2986 (LOG_DISASM | LOG_REGS)) {
2987 PrintF("Enabling disassembly and registers tracing\n");
2988 set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
2989 } else {
2990 PrintF("Disabling disassembly and registers tracing\n");
2991 set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
2992 }
2993
2994 // break / b -------------------------------------------------------------
2995 } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
2996 if (argc == 2) {
2997 int64_t value;
2998 if (GetValue(arg1, &value)) {
2999 SetBreakpoint(reinterpret_cast<Instruction*>(value));
3000 } else {
3001 PrintF("%s unrecognized\n", arg1);
3002 }
3003 } else {
3004 ListBreakpoints();
3005 PrintF("Use `break <address>` to set or disable a breakpoint\n");
3006 }
3007
3008 // gdb -------------------------------------------------------------------
3009 } else if (strcmp(cmd, "gdb") == 0) {
3010 PrintF("Relinquishing control to gdb.\n");
3011 OS::DebugBreak();
3012 PrintF("Regaining control from gdb.\n");
3013
3014 // sysregs ---------------------------------------------------------------
3015 } else if (strcmp(cmd, "sysregs") == 0) {
3016 PrintSystemRegisters();
3017
3018 // help / h --------------------------------------------------------------
3019 } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3020 PrintF(
3021 "stepi / si\n"
3022 " stepi <n>\n"
3023 " Step <n> instructions.\n"
3024 "next / n\n"
3025 " Continue execution until a BL instruction is reached.\n"
3026 " At this point a breakpoint is set just after this BL.\n"
3027 " Then execution is resumed. It will probably later hit the\n"
3028 " breakpoint just set.\n"
3029 "continue / cont / c\n"
3030 " Continue execution from here.\n"
3031 "disassemble / disasm / di\n"
3032 " disassemble <n> <address>\n"
3033 " Disassemble <n> instructions from current <address>.\n"
3034 " By default <n> is 20 and <address> is the current pc.\n"
3035 "print / p\n"
3036 " print <register>\n"
3037 " Print the content of a register.\n"
3038 " 'print all' will print all registers.\n"
3039 " Use 'printobject' to get more details about the value.\n"
3040 "printobject / po\n"
3041 " printobject <value>\n"
3042 " printobject <register>\n"
3043 " Print details about the value.\n"
3044 "stack\n"
3045 " stack [<words>]\n"
3046 " Dump stack content, default dump 10 words\n"
3047 "mem\n"
3048 " mem <address> [<words>]\n"
3049 " Dump memory content, default dump 10 words\n"
3050 "trace / t\n"
3051 " Toggle disassembly and register tracing\n"
3052 "break / b\n"
3053 " break : list all breakpoints\n"
3054 " break <address> : set / enable / disable a breakpoint.\n"
3055 "gdb\n"
3056 " Enter gdb.\n"
3057 "sysregs\n"
3058 " Print all system registers (including NZCV).\n");
3059 } else {
3060 PrintF("Unknown command: %s\n", cmd);
3061 PrintF("Use 'help' for more information.\n");
3062 }
3063 }
3064 if (cleared_log_disasm_bit == true) {
3065 set_log_parameters(log_parameters_ | LOG_DISASM);
3066 }
3067 }
3068 }
3069
3070
3071 // Calls into the V8 runtime are based on this very simple interface.
3072 // Note: To be able to return two values from some calls the code in runtime.cc
3073 // uses the ObjectPair structure.
3074 // The simulator assumes all runtime calls return two 64-bits values. If they
3075 // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
3076 struct ObjectPair {
3077 int64_t res0;
3078 int64_t res1;
3079 };
3080
3081
3082 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
3083 int64_t arg1,
3084 int64_t arg2,
3085 int64_t arg3,
3086 int64_t arg4,
3087 int64_t arg5,
3088 int64_t arg6,
3089 int64_t arg7);
3090
3091 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
3092 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
3093 typedef double (*SimulatorRuntimeFPCall)(double arg1);
3094 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
3095
3096 // This signature supports direct call in to API function native callback
3097 // (refer to InvocationCallback in v8.h).
3098 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
3099 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
3100
3101 // This signature supports direct call to accessor getter callback.
3102 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
3103 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
3104 void* arg2);
3105
3106 void Simulator::VisitException(Instruction* instr) {
3107 // Define some colour codes to use for log messages.
3108 // TODO(jbramley): Find a more elegant way of defining these.
3109 char const* const clr_normal = (FLAG_log_colour) ? ("\033[m")
3110 : ("");
3111 char const* const clr_debug_number = (FLAG_log_colour) ? ("\033[1;33m")
3112 : ("");
3113 char const* const clr_debug_message = (FLAG_log_colour) ? ("\033[0;33m")
3114 : ("");
3115 char const* const clr_printf = (FLAG_log_colour) ? ("\033[0;32m")
3116 : ("");
3117
3118 switch (instr->Mask(ExceptionMask)) {
3119 case HLT: {
3120 if (instr->ImmException() == kImmExceptionIsDebug) {
3121 // Read the arguments encoded inline in the instruction stream.
3122 uint32_t code;
3123 uint32_t parameters;
3124 char const * message;
3125
3126 ASSERT(sizeof(*pc_) == 1);
3127 memcpy(&code, pc_ + kDebugCodeOffset, sizeof(code));
3128 memcpy(&parameters, pc_ + kDebugParamsOffset, sizeof(parameters));
3129 message = reinterpret_cast<char const *>(pc_ + kDebugMessageOffset);
3130
3131 // Always print something when we hit a debug point that breaks.
3132 // We are going to break, so printing something is not an issue in
3133 // terms of speed.
3134 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3135 if (message != NULL) {
3136 PrintF("%sDebugger hit %d: %s%s%s\n",
3137 clr_debug_number,
3138 code,
3139 clr_debug_message,
3140 message,
3141 clr_normal);
3142 } else {
3143 PrintF("%sDebugger hit %d.%s\n",
3144 clr_debug_number,
3145 code,
3146 clr_normal);
3147 }
3148 }
3149
3150 // Other options.
3151 switch (parameters & kDebuggerTracingDirectivesMask) {
3152 case TRACE_ENABLE:
3153 set_log_parameters(log_parameters() | parameters);
3154 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3155 if (parameters & LOG_REGS) { PrintRegisters(); }
3156 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); }
3157 break;
3158 case TRACE_DISABLE:
3159 set_log_parameters(log_parameters() & ~parameters);
3160 break;
3161 case TRACE_OVERRIDE:
3162 set_log_parameters(parameters);
3163 break;
3164 default:
3165 // We don't support a one-shot LOG_DISASM.
3166 ASSERT((parameters & LOG_DISASM) == 0);
3167 // Don't print information that is already being traced.
3168 parameters &= ~log_parameters();
3169 // Print the requested information.
3170 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true);
3171 if (parameters & LOG_REGS) PrintRegisters(true);
3172 if (parameters & LOG_FP_REGS) PrintFPRegisters(true);
3173 }
3174
3175 // The stop parameters are inlined in the code. Skip them:
3176 // - Skip to the end of the message string.
3177 pc_ += kDebugMessageOffset + strlen(message) + 1;
3178 // - Advance to the next aligned location.
3179 pc_ = AlignUp(pc_, kInstructionSize);
3180 // - Verify that the unreachable marker is present.
3181 ASSERT(pc_->Mask(ExceptionMask) == HLT);
3182 ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable);
3183 // - Skip past the unreachable marker.
3184 set_pc(pc_->NextInstruction());
3185
3186 // Check if the debugger should break.
3187 if (parameters & BREAK) Debug();
3188
3189 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3190 // TODO(all): Extract the call redirection code into a separate
3191 // function.
3192
3193 Redirection* redirection = Redirection::FromHltInstruction(instr);
3194
3195 // The called C code might itself call simulated code, so any
3196 // caller-saved registers (including lr) could still be clobbered by a
3197 // redirected call.
3198 Instruction* return_address = lr();
3199
3200 // TODO(jbramley): Make external_function() a template so that we don't
3201 // have to explicitly cast the result for each redirection type.
3202 int64_t external =
3203 reinterpret_cast<int64_t>(redirection->external_function());
3204
3205 TraceSim("Call to host function at %p\n",
3206 reinterpret_cast<void*>(redirection->external_function()));
3207
3208 // SP must be 16 bytes aligned at the call interface.
3209 bool stack_alignment_exception = ((sp() & 0xf) != 0);
3210 if (stack_alignment_exception) {
3211 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
3212 ALIGNMENT_EXCEPTION();
3213 }
3214
3215 switch (redirection->type()) {
3216 default:
3217 TraceSim("Type: Unknown.\n");
3218 UNREACHABLE();
3219 break;
3220
3221 case ExternalReference::BUILTIN_CALL: {
3222 // MaybeObject* f(v8::internal::Arguments).
3223 TraceSim("Type: BUILTIN_CALL\n");
3224 SimulatorRuntimeCall target =
3225 reinterpret_cast<SimulatorRuntimeCall>(external);
3226
3227 // We don't know how many arguments are being passed, but we can
3228 // pass 8 without touching the stack. They will be ignored by the
3229 // host function if they aren't used.
3230 TraceSim("Arguments: "
3231 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
3232 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
3233 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
3234 "0x%016" PRIx64 ", 0x%016" PRIx64,
3235 xreg(0), xreg(1), xreg(2), xreg(3),
3236 xreg(4), xreg(5), xreg(6), xreg(7));
3237 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
3238 xreg(4), xreg(5), xreg(6), xreg(7));
3239 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64"}\n",
3240 result.res0, result.res1);
3241 #ifdef DEBUG
3242 CorruptAllCallerSavedCPURegisters();
3243 #endif
3244 set_xreg(0, result.res0);
3245 set_xreg(1, result.res1);
3246 break;
3247 }
3248
3249 case ExternalReference::DIRECT_API_CALL: {
3250 // void f(v8::FunctionCallbackInfo&)
3251 TraceSim("Type: DIRECT_API_CALL\n");
3252 SimulatorRuntimeDirectApiCall target =
3253 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
3254 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
3255 target(xreg(0));
3256 TraceSim("No return value.");
3257 #ifdef DEBUG
3258 CorruptAllCallerSavedCPURegisters();
3259 #endif
3260 break;
3261 }
3262
3263 case ExternalReference::BUILTIN_COMPARE_CALL: {
3264 // int f(double, double)
3265 TraceSim("Type: BUILTIN_COMPARE_CALL\n");
3266 SimulatorRuntimeCompareCall target =
3267 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
3268 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
3269 int64_t result = target(dreg(0), dreg(1));
3270 TraceSim("Returned: %" PRId64 "\n", result);
3271 #ifdef DEBUG
3272 CorruptAllCallerSavedCPURegisters();
3273 #endif
3274 set_xreg(0, result);
3275 break;
3276 }
3277
3278 case ExternalReference::BUILTIN_FP_CALL: {
3279 // double f(double)
3280 TraceSim("Type: BUILTIN_FP_CALL\n");
3281 SimulatorRuntimeFPCall target =
3282 reinterpret_cast<SimulatorRuntimeFPCall>(external);
3283 TraceSim("Argument: %f\n", dreg(0));
3284 double result = target(dreg(0));
3285 TraceSim("Returned: %f\n", result);
3286 #ifdef DEBUG
3287 CorruptAllCallerSavedCPURegisters();
3288 #endif
3289 set_dreg(0, result);
3290 break;
3291 }
3292
3293 case ExternalReference::BUILTIN_FP_FP_CALL: {
3294 // double f(double, double)
3295 TraceSim("Type: BUILTIN_FP_FP_CALL\n");
3296 SimulatorRuntimeFPFPCall target =
3297 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
3298 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
3299 double result = target(dreg(0), dreg(1));
3300 TraceSim("Returned: %f\n", result);
3301 #ifdef DEBUG
3302 CorruptAllCallerSavedCPURegisters();
3303 #endif
3304 set_dreg(0, result);
3305 break;
3306 }
3307
3308 case ExternalReference::BUILTIN_FP_INT_CALL: {
3309 // double f(double, int)
3310 TraceSim("Type: BUILTIN_FP_INT_CALL\n");
3311 SimulatorRuntimeFPIntCall target =
3312 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
3313 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
3314 double result = target(dreg(0), wreg(0));
3315 TraceSim("Returned: %f\n", result);
3316 #ifdef DEBUG
3317 CorruptAllCallerSavedCPURegisters();
3318 #endif
3319 set_dreg(0, result);
3320 break;
3321 }
3322
3323 case ExternalReference::DIRECT_GETTER_CALL: {
3324 // void f(Local<String> property, PropertyCallbackInfo& info)
3325 TraceSim("Type: DIRECT_GETTER_CALL\n");
3326 SimulatorRuntimeDirectGetterCall target =
3327 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
3328 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
3329 xreg(0), xreg(1));
3330 target(xreg(0), xreg(1));
3331 TraceSim("No return value.");
3332 #ifdef DEBUG
3333 CorruptAllCallerSavedCPURegisters();
3334 #endif
3335 break;
3336 }
3337
3338 case ExternalReference::PROFILING_API_CALL: {
3339 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
3340 TraceSim("Type: PROFILING_API_CALL\n");
3341 SimulatorRuntimeProfilingApiCall target =
3342 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
3343 void* arg1 = Redirection::ReverseRedirection(xreg(1));
3344 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
3345 target(xreg(0), arg1);
3346 TraceSim("No return value.");
3347 #ifdef DEBUG
3348 CorruptAllCallerSavedCPURegisters();
3349 #endif
3350 break;
3351 }
3352
3353 case ExternalReference::PROFILING_GETTER_CALL: {
3354 // void f(Local<String> property, PropertyCallbackInfo& info,
3355 // AccessorGetterCallback callback)
3356 TraceSim("Type: PROFILING_GETTER_CALL\n");
3357 SimulatorRuntimeProfilingGetterCall target =
3358 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
3359 external);
3360 void* arg2 = Redirection::ReverseRedirection(xreg(2));
3361 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
3362 xreg(0), xreg(1), arg2);
3363 target(xreg(0), xreg(1), arg2);
3364 TraceSim("No return value.");
3365 #ifdef DEBUG
3366 CorruptAllCallerSavedCPURegisters();
3367 #endif
3368 break;
3369 }
3370 }
3371
3372 set_lr(return_address);
3373 set_pc(return_address);
3374 } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3375 // Read the argument encoded inline in the instruction stream.
3376 uint32_t type;
3377 ASSERT(sizeof(*pc_) == 1);
3378 memcpy(&type, pc_ + kPrintfTypeOffset, sizeof(type));
3379
3380 const char* format = reg<const char*>(0);
3381
3382 // Pass all of the relevant PCS registers onto printf. It doesn't
3383 // matter if we pass too many as the extra ones won't be read.
3384 int result;
3385 fputs(clr_printf, stream_);
3386 if (type == CPURegister::kRegister) {
3387 result = fprintf(stream_, format,
3388 xreg(1), xreg(2), xreg(3), xreg(4),
3389 xreg(5), xreg(6), xreg(7));
3390 } else if (type == CPURegister::kFPRegister) {
3391 result = fprintf(stream_, format,
3392 dreg(0), dreg(1), dreg(2), dreg(3),
3393 dreg(4), dreg(5), dreg(6), dreg(7));
3394 } else {
3395 ASSERT(type == CPURegister::kNoRegister);
3396 result = fprintf(stream_, "%s", format);
3397 }
3398 fputs(clr_normal, stream_);
3399 set_xreg(0, result);
3400
3401 // TODO(jbramley): Consider clobbering all caller-saved registers here.
3402
3403 // The printf parameters are inlined in the code, so skip them.
3404 set_pc(pc_->InstructionAtOffset(kPrintfLength));
3405
3406 // Set LR as if we'd just called a native printf function.
3407 set_lr(pc());
3408
3409 } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3410 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3411 reinterpret_cast<void*>(pc_));
3412 abort();
3413
3414 } else {
3415 OS::DebugBreak();
3416 }
3417 break;
3418 }
3419
3420 default:
3421 UNIMPLEMENTED();
3422 }
3423 }
3424
3425 #endif // USE_SIMULATOR
3426
3427 } } // namespace v8::internal
3428
3429 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/simulator-a64.h ('k') | src/a64/stub-cache-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698