1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #if V8_TARGET_ARCH_ARM64
13 #include "assembler.h"
14 #include "arm64/decoder-arm64-inl.h"
15 #include "arm64/simulator-arm64.h"
16 #include "macro-assembler.h"
21 #if defined(USE_SIMULATOR)
24 // This macro provides a platform independent use of sscanf. The reason for
25 // SScanF not being implemented in a platform independent way through
26 // ::v8::internal::OS in the same way as SNPrintF is that the
27 // Windows C Run-Time Library does not provide vsscanf.
28 #define SScanF sscanf // NOLINT
31 // Helpers for colors.
32 // Depending on your terminal configuration, the colour names may not match the
34 #define COLOUR(colour_code) "\033[" colour_code "m"
35 #define BOLD(colour_code) "1;" colour_code
44 typedef char const * const TEXT_COLOUR;
45 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : "";
46 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR(BOLD(GREY)) : "";
47 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(BOLD(WHITE)) : "";
48 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR(BOLD(BLUE)) : "";
49 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(BOLD(INDIGO)) : "";
50 TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : "";
51 TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(BOLD(PURPLE)) : "";
52 TEXT_COLOUR clr_memory_value = FLAG_log_colour ? COLOUR(BOLD(GREEN)) : "";
53 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR(GREEN) : "";
54 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : "";
55 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(ORANGE) : "";
56 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
59 // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
60 void Simulator::TraceSim(const char* format, ...) {
63 va_start(arguments, format);
64 OS::VFPrint(stream_, format, arguments);
70 const Instruction* Simulator::kEndOfSimAddress = NULL;
73 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
74 int width = msb - lsb + 1;
75 ASSERT(is_uintn(bits, width) || is_intn(bits, width));
78 uint32_t mask = ((1 << width) - 1) << lsb;
79 ASSERT((mask & write_ignore_mask_) == 0);
81 value_ = (value_ & ~mask) | (bits & mask);
85 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
88 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
90 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
93 return SimSystemRegister();
98 void Simulator::Initialize(Isolate* isolate) {
99 if (isolate->simulator_initialized()) return;
100 isolate->set_simulator_initialized(true);
101 ExternalReference::set_redirector(isolate, &RedirectExternalReference);
105 // Get the active Simulator for the current thread.
106 Simulator* Simulator::current(Isolate* isolate) {
107 Isolate::PerIsolateThreadData* isolate_data =
108 isolate->FindOrAllocatePerThreadDataForThisThread();
109 ASSERT(isolate_data != NULL);
111 Simulator* sim = isolate_data->simulator();
113 if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) {
114 sim = new Simulator(new Decoder<DispatchingDecoderVisitor>(), isolate);
116 sim = new Decoder<Simulator>();
117 sim->isolate_ = isolate;
119 isolate_data->set_simulator(sim);
125 void Simulator::CallVoid(byte* entry, CallArgument* args) {
129 std::vector<int64_t> stack_args(0);
130 for (int i = 0; !args[i].IsEnd(); i++) {
131 CallArgument arg = args[i];
132 if (arg.IsX() && (index_x < 8)) {
133 set_xreg(index_x++, arg.bits());
134 } else if (arg.IsD() && (index_d < 8)) {
135 set_dreg_bits(index_d++, arg.bits());
137 ASSERT(arg.IsD() || arg.IsX());
138 stack_args.push_back(arg.bits());
142 // Process stack arguments, and make sure the stack is suitably aligned.
143 uintptr_t original_stack = sp();
144 uintptr_t entry_stack = original_stack -
145 stack_args.size() * sizeof(stack_args[0]);
146 if (OS::ActivationFrameAlignment() != 0) {
147 entry_stack &= -OS::ActivationFrameAlignment();
149 char * stack = reinterpret_cast<char*>(entry_stack);
150 std::vector<int64_t>::const_iterator it;
151 for (it = stack_args.begin(); it != stack_args.end(); it++) {
152 memcpy(stack, &(*it), sizeof(*it));
153 stack += sizeof(*it);
156 ASSERT(reinterpret_cast<uintptr_t>(stack) <= original_stack);
159 // Call the generated code.
161 set_lr(kEndOfSimAddress);
162 CheckPCSComplianceAndRun();
164 set_sp(original_stack);
168 int64_t Simulator::CallInt64(byte* entry, CallArgument* args) {
169 CallVoid(entry, args);
174 double Simulator::CallDouble(byte* entry, CallArgument* args) {
175 CallVoid(entry, args);
180 int64_t Simulator::CallJS(byte* entry,
181 byte* function_entry,
186 CallArgument args[] = {
187 CallArgument(function_entry),
194 return CallInt64(entry, args);
197 int64_t Simulator::CallRegExp(byte* entry,
199 int64_t start_offset,
200 const byte* input_start,
201 const byte* input_end,
206 void* return_address,
208 CallArgument args[] = {
210 CallArgument(start_offset),
211 CallArgument(input_start),
212 CallArgument(input_end),
213 CallArgument(output),
214 CallArgument(output_size),
215 CallArgument(stack_base),
216 CallArgument(direct_call),
217 CallArgument(return_address),
218 CallArgument(isolate),
221 return CallInt64(entry, args);
225 void Simulator::CheckPCSComplianceAndRun() {
227 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
228 CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count());
230 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
231 uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters];
233 CPURegList register_list = kCalleeSaved;
234 CPURegList fpregister_list = kCalleeSavedFP;
236 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
237 // x31 is not a caller saved register, so no need to specify if we want
238 // the stack or zero.
239 saved_registers[i] = xreg(register_list.PopLowestIndex().code());
241 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
242 saved_fpregisters[i] =
243 dreg_bits(fpregister_list.PopLowestIndex().code());
245 int64_t original_stack = sp();
247 // Start the simulation!
250 CHECK_EQ(original_stack, sp());
251 // Check that callee-saved registers have been preserved.
252 register_list = kCalleeSaved;
253 fpregister_list = kCalleeSavedFP;
254 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
255 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
257 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
258 ASSERT(saved_fpregisters[i] ==
259 dreg_bits(fpregister_list.PopLowestIndex().code()));
262 // Corrupt caller saved register minus the return regiters.
264 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
266 register_list = kCallerSaved;
267 register_list.Remove(x0);
268 register_list.Remove(x1);
270 // In theory d0 to d7 can be used for return values, but V8 only uses d0
272 fpregister_list = kCallerSavedFP;
273 fpregister_list.Remove(d0);
275 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
276 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
282 // The least significant byte of the curruption value holds the corresponding
284 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
285 if (list->type() == CPURegister::kRegister) {
286 while (!list->IsEmpty()) {
287 unsigned code = list->PopLowestIndex().code();
288 set_xreg(code, value | code);
291 ASSERT(list->type() == CPURegister::kFPRegister);
292 while (!list->IsEmpty()) {
293 unsigned code = list->PopLowestIndex().code();
294 set_dreg_bits(code, value | code);
300 void Simulator::CorruptAllCallerSavedCPURegisters() {
301 // Corrupt alters its parameter so copy them first.
302 CPURegList register_list = kCallerSaved;
303 CPURegList fpregister_list = kCallerSavedFP;
305 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
306 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
311 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
312 uintptr_t Simulator::PushAddress(uintptr_t address) {
313 ASSERT(sizeof(uintptr_t) < 2 * kXRegSize);
314 intptr_t new_sp = sp() - 2 * kXRegSize;
315 uintptr_t* alignment_slot =
316 reinterpret_cast<uintptr_t*>(new_sp + kXRegSize);
317 memcpy(alignment_slot, &kSlotsZapValue, kPointerSize);
318 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
319 memcpy(stack_slot, &address, kPointerSize);
325 uintptr_t Simulator::PopAddress() {
326 intptr_t current_sp = sp();
327 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
328 uintptr_t address = *stack_slot;
329 ASSERT(sizeof(uintptr_t) < 2 * kXRegSize);
330 set_sp(current_sp + 2 * kXRegSize);
335 // Returns the limit of the stack area to enable checking for stack overflows.
336 uintptr_t Simulator::StackLimit() const {
337 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
339 return reinterpret_cast<uintptr_t>(stack_limit_) + 1024;
343 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
344 Isolate* isolate, FILE* stream)
346 last_debugger_input_(NULL),
347 log_parameters_(NO_PARAM),
349 // Setup the decoder.
350 decoder_->AppendVisitor(this);
354 if (FLAG_trace_sim) {
355 decoder_->InsertVisitorBefore(print_disasm_, this);
356 log_parameters_ = LOG_ALL;
359 if (FLAG_log_instruction_stats) {
360 instrument_ = new Instrument(FLAG_log_instruction_file,
361 FLAG_log_instruction_period);
362 decoder_->AppendVisitor(instrument_);
367 Simulator::Simulator()
369 last_debugger_input_(NULL),
370 log_parameters_(NO_PARAM),
373 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats);
377 void Simulator::Init(FILE* stream) {
380 // Allocate and setup the simulator stack.
381 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
382 stack_ = new byte[stack_size_];
383 stack_limit_ = stack_ + stack_protection_size_;
384 byte* tos = stack_ + stack_size_ - stack_protection_size_;
385 // The stack pointer must be 16 bytes aligned.
386 set_sp(reinterpret_cast<int64_t>(tos) & ~0xfUL);
389 print_disasm_ = new PrintDisassembler(stream_);
391 // The debugger needs to disassemble code without the simulator executing an
392 // instruction, so we create a dedicated decoder.
393 disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>();
394 disassembler_decoder_->AppendVisitor(print_disasm_);
398 void Simulator::ResetState() {
399 // Reset the system registers.
400 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
401 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
403 // Reset registers to 0.
405 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
406 set_xreg(i, 0xbadbeef);
408 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
409 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
410 set_dreg_bits(i, 0x7ff000007f800001UL);
412 // Returning to address 0 exits the Simulator.
413 set_lr(kEndOfSimAddress);
415 // Reset debug helpers.
416 breakpoints_.empty();
417 break_on_next_= false;
421 Simulator::~Simulator() {
423 if (FLAG_log_instruction_stats) {
426 delete disassembler_decoder_;
427 delete print_disasm_;
428 DeleteArray(last_debugger_input_);
433 void Simulator::Run() {
434 pc_modified_ = false;
435 while (pc_ != kEndOfSimAddress) {
436 ExecuteInstruction();
441 void Simulator::RunFrom(Instruction* start) {
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.
456 Redirection(void* external_function, ExternalReference::Type type)
457 : external_function_(external_function),
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);
468 void* address_of_redirect_call() {
469 return reinterpret_cast<void*>(&redirect_call_);
472 template <typename T>
473 T external_function() { return reinterpret_cast<T>(external_function_); }
475 ExternalReference::Type type() { return type_; }
477 static Redirection* Get(void* external_function,
478 ExternalReference::Type type) {
479 Isolate* isolate = Isolate::Current();
480 Redirection* current = isolate->simulator_redirection();
481 for (; current != NULL; current = current->next_) {
482 if (current->external_function_ == external_function) {
483 ASSERT_EQ(current->type(), type);
487 return new Redirection(external_function, type);
490 static Redirection* FromHltInstruction(Instruction* redirect_call) {
491 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call);
492 char* addr_of_redirection =
493 addr_of_hlt - OFFSET_OF(Redirection, redirect_call_);
494 return reinterpret_cast<Redirection*>(addr_of_redirection);
497 static void* ReverseRedirection(int64_t reg) {
498 Redirection* redirection =
499 FromHltInstruction(reinterpret_cast<Instruction*>(reg));
500 return redirection->external_function<void*>();
504 void* external_function_;
505 Instruction redirect_call_;
506 ExternalReference::Type type_;
511 // Calls into the V8 runtime are based on this very simple interface.
512 // Note: To be able to return two values from some calls the code in runtime.cc
513 // uses the ObjectPair structure.
514 // The simulator assumes all runtime calls return two 64-bits values. If they
515 // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
522 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
531 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
532 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
533 typedef double (*SimulatorRuntimeFPCall)(double arg1);
534 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
536 // This signature supports direct call in to API function native callback
537 // (refer to InvocationCallback in v8.h).
538 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
539 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
541 // This signature supports direct call to accessor getter callback.
542 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
543 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
546 void Simulator::DoRuntimeCall(Instruction* instr) {
547 Redirection* redirection = Redirection::FromHltInstruction(instr);
549 // The called C code might itself call simulated code, so any
550 // caller-saved registers (including lr) could still be clobbered by a
552 Instruction* return_address = lr();
554 int64_t external = redirection->external_function<int64_t>();
556 TraceSim("Call to host function at %p\n",
557 redirection->external_function<void*>());
559 // SP must be 16-byte-aligned at the call interface.
560 bool stack_alignment_exception = ((sp() & 0xf) != 0);
561 if (stack_alignment_exception) {
562 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
563 FATAL("ALIGNMENT EXCEPTION");
566 switch (redirection->type()) {
568 TraceSim("Type: Unknown.\n");
572 case ExternalReference::BUILTIN_CALL: {
573 // Object* f(v8::internal::Arguments).
574 TraceSim("Type: BUILTIN_CALL\n");
575 SimulatorRuntimeCall target =
576 reinterpret_cast<SimulatorRuntimeCall>(external);
578 // We don't know how many arguments are being passed, but we can
579 // pass 8 without touching the stack. They will be ignored by the
580 // host function if they aren't used.
581 TraceSim("Arguments: "
582 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
583 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
584 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
585 "0x%016" PRIx64 ", 0x%016" PRIx64,
586 xreg(0), xreg(1), xreg(2), xreg(3),
587 xreg(4), xreg(5), xreg(6), xreg(7));
588 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
589 xreg(4), xreg(5), xreg(6), xreg(7));
590 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n",
591 result.res0, result.res1);
593 CorruptAllCallerSavedCPURegisters();
595 set_xreg(0, result.res0);
596 set_xreg(1, result.res1);
600 case ExternalReference::DIRECT_API_CALL: {
601 // void f(v8::FunctionCallbackInfo&)
602 TraceSim("Type: DIRECT_API_CALL\n");
603 SimulatorRuntimeDirectApiCall target =
604 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
605 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
607 TraceSim("No return value.");
609 CorruptAllCallerSavedCPURegisters();
614 case ExternalReference::BUILTIN_COMPARE_CALL: {
615 // int f(double, double)
616 TraceSim("Type: BUILTIN_COMPARE_CALL\n");
617 SimulatorRuntimeCompareCall target =
618 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
619 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
620 int64_t result = target(dreg(0), dreg(1));
621 TraceSim("Returned: %" PRId64 "\n", result);
623 CorruptAllCallerSavedCPURegisters();
629 case ExternalReference::BUILTIN_FP_CALL: {
631 TraceSim("Type: BUILTIN_FP_CALL\n");
632 SimulatorRuntimeFPCall target =
633 reinterpret_cast<SimulatorRuntimeFPCall>(external);
634 TraceSim("Argument: %f\n", dreg(0));
635 double result = target(dreg(0));
636 TraceSim("Returned: %f\n", result);
638 CorruptAllCallerSavedCPURegisters();
644 case ExternalReference::BUILTIN_FP_FP_CALL: {
645 // double f(double, double)
646 TraceSim("Type: BUILTIN_FP_FP_CALL\n");
647 SimulatorRuntimeFPFPCall target =
648 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
649 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
650 double result = target(dreg(0), dreg(1));
651 TraceSim("Returned: %f\n", result);
653 CorruptAllCallerSavedCPURegisters();
659 case ExternalReference::BUILTIN_FP_INT_CALL: {
660 // double f(double, int)
661 TraceSim("Type: BUILTIN_FP_INT_CALL\n");
662 SimulatorRuntimeFPIntCall target =
663 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
664 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
665 double result = target(dreg(0), wreg(0));
666 TraceSim("Returned: %f\n", result);
668 CorruptAllCallerSavedCPURegisters();
674 case ExternalReference::DIRECT_GETTER_CALL: {
675 // void f(Local<String> property, PropertyCallbackInfo& info)
676 TraceSim("Type: DIRECT_GETTER_CALL\n");
677 SimulatorRuntimeDirectGetterCall target =
678 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
679 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
681 target(xreg(0), xreg(1));
682 TraceSim("No return value.");
684 CorruptAllCallerSavedCPURegisters();
689 case ExternalReference::PROFILING_API_CALL: {
690 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
691 TraceSim("Type: PROFILING_API_CALL\n");
692 SimulatorRuntimeProfilingApiCall target =
693 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
694 void* arg1 = Redirection::ReverseRedirection(xreg(1));
695 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
696 target(xreg(0), arg1);
697 TraceSim("No return value.");
699 CorruptAllCallerSavedCPURegisters();
704 case ExternalReference::PROFILING_GETTER_CALL: {
705 // void f(Local<String> property, PropertyCallbackInfo& info,
706 // AccessorGetterCallback callback)
707 TraceSim("Type: PROFILING_GETTER_CALL\n");
708 SimulatorRuntimeProfilingGetterCall target =
709 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
711 void* arg2 = Redirection::ReverseRedirection(xreg(2));
712 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
713 xreg(0), xreg(1), arg2);
714 target(xreg(0), xreg(1), arg2);
715 TraceSim("No return value.");
717 CorruptAllCallerSavedCPURegisters();
723 set_lr(return_address);
724 set_pc(return_address);
728 void* Simulator::RedirectExternalReference(void* external_function,
729 ExternalReference::Type type) {
730 Redirection* redirection = Redirection::Get(external_function, type);
731 return redirection->address_of_redirect_call();
735 const char* Simulator::xreg_names[] = {
736 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
737 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
738 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23",
739 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"};
741 const char* Simulator::wreg_names[] = {
742 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
743 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
744 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
745 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"};
747 const char* Simulator::sreg_names[] = {
748 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
749 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
750 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
751 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
753 const char* Simulator::dreg_names[] = {
754 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
755 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
756 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
757 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
759 const char* Simulator::vreg_names[] = {
760 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
761 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
762 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
763 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
766 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
767 ASSERT(code < kNumberOfRegisters);
768 // If the code represents the stack pointer, index the name after zr.
769 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
770 code = kZeroRegCode + 1;
772 return wreg_names[code];
776 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
777 ASSERT(code < kNumberOfRegisters);
778 // If the code represents the stack pointer, index the name after zr.
779 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
780 code = kZeroRegCode + 1;
782 return xreg_names[code];
786 const char* Simulator::SRegNameForCode(unsigned code) {
787 ASSERT(code < kNumberOfFPRegisters);
788 return sreg_names[code];
792 const char* Simulator::DRegNameForCode(unsigned code) {
793 ASSERT(code < kNumberOfFPRegisters);
794 return dreg_names[code];
798 const char* Simulator::VRegNameForCode(unsigned code) {
799 ASSERT(code < kNumberOfFPRegisters);
800 return vreg_names[code];
804 int Simulator::CodeFromName(const char* name) {
805 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
806 if ((strcmp(xreg_names[i], name) == 0) ||
807 (strcmp(wreg_names[i], name) == 0)) {
811 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
812 if ((strcmp(vreg_names[i], name) == 0) ||
813 (strcmp(dreg_names[i], name) == 0) ||
814 (strcmp(sreg_names[i], name) == 0)) {
818 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
819 return kSPRegInternalCode;
825 // Helpers ---------------------------------------------------------------------
826 int64_t Simulator::AddWithCarry(unsigned reg_size,
831 ASSERT((carry_in == 0) || (carry_in == 1));
832 ASSERT((reg_size == kXRegSizeInBits) || (reg_size == kWRegSizeInBits));
836 int64_t signed_sum = src1 + src2 + carry_in;
840 if (reg_size == kWRegSizeInBits) {
841 u1 = static_cast<uint64_t>(src1) & kWRegMask;
842 u2 = static_cast<uint64_t>(src2) & kWRegMask;
844 result = signed_sum & kWRegMask;
845 // Compute the C flag by comparing the sum to the max unsigned integer.
846 C = ((kWMaxUInt - u1) < (u2 + carry_in)) ||
847 ((kWMaxUInt - u1 - carry_in) < u2);
848 // Overflow iff the sign bit is the same for the two inputs and different
850 int64_t s_src1 = src1 << (kXRegSizeInBits - kWRegSizeInBits);
851 int64_t s_src2 = src2 << (kXRegSizeInBits - kWRegSizeInBits);
852 int64_t s_result = result << (kXRegSizeInBits - kWRegSizeInBits);
853 V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0);
856 u1 = static_cast<uint64_t>(src1);
857 u2 = static_cast<uint64_t>(src2);
860 // Compute the C flag by comparing the sum to the max unsigned integer.
861 C = ((kXMaxUInt - u1) < (u2 + carry_in)) ||
862 ((kXMaxUInt - u1 - carry_in) < u2);
863 // Overflow iff the sign bit is the same for the two inputs and different
865 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
868 N = CalcNFlag(result, reg_size);
869 Z = CalcZFlag(result);
881 int64_t Simulator::ShiftOperand(unsigned reg_size,
888 int64_t mask = reg_size == kXRegSizeInBits ? kXRegMask : kWRegMask;
889 switch (shift_type) {
891 return (value << amount) & mask;
893 return static_cast<uint64_t>(value) >> amount;
895 // Shift used to restore the sign.
896 unsigned s_shift = kXRegSizeInBits - reg_size;
897 // Value with its sign restored.
898 int64_t s_value = (value << s_shift) >> s_shift;
899 return (s_value >> amount) & mask;
902 if (reg_size == kWRegSizeInBits) {
905 return (static_cast<uint64_t>(value) >> amount) |
906 ((value & ((1L << amount) - 1L)) << (reg_size - amount));
915 int64_t Simulator::ExtendValue(unsigned reg_size,
918 unsigned left_shift) {
919 switch (extend_type) {
924 value &= kHalfWordMask;
930 value = (value << 56) >> 56;
933 value = (value << 48) >> 48;
936 value = (value << 32) >> 32;
944 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask;
945 return (value << left_shift) & mask;
949 template<> double Simulator::FPDefaultNaN<double>() const {
950 return kFP64DefaultNaN;
954 template<> float Simulator::FPDefaultNaN<float>() const {
955 return kFP32DefaultNaN;
959 void Simulator::FPCompare(double val0, double val1) {
960 AssertSupportedFPCR();
962 // TODO(jbramley): This assumes that the C++ implementation handles
963 // comparisons in the way that we expect (as per AssertSupportedFPCR()).
964 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
965 nzcv().SetRawValue(FPUnorderedFlag);
966 } else if (val0 < val1) {
967 nzcv().SetRawValue(FPLessThanFlag);
968 } else if (val0 > val1) {
969 nzcv().SetRawValue(FPGreaterThanFlag);
970 } else if (val0 == val1) {
971 nzcv().SetRawValue(FPEqualFlag);
978 void Simulator::SetBreakpoint(Instruction* location) {
979 for (unsigned i = 0; i < breakpoints_.size(); i++) {
980 if (breakpoints_.at(i).location == location) {
982 "Existing breakpoint at %p was %s\n",
983 reinterpret_cast<void*>(location),
984 breakpoints_.at(i).enabled ? "disabled" : "enabled");
985 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
989 Breakpoint new_breakpoint = {location, true};
990 breakpoints_.push_back(new_breakpoint);
992 "Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
996 void Simulator::ListBreakpoints() {
997 PrintF(stream_, "Breakpoints:\n");
998 for (unsigned i = 0; i < breakpoints_.size(); i++) {
999 PrintF(stream_, "%p : %s\n",
1000 reinterpret_cast<void*>(breakpoints_.at(i).location),
1001 breakpoints_.at(i).enabled ? "enabled" : "disabled");
1006 void Simulator::CheckBreakpoints() {
1007 bool hit_a_breakpoint = false;
1008 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1009 if ((breakpoints_.at(i).location == pc_) &&
1010 breakpoints_.at(i).enabled) {
1011 hit_a_breakpoint = true;
1012 // Disable this breakpoint.
1013 breakpoints_.at(i).enabled = false;
1016 if (hit_a_breakpoint) {
1017 PrintF(stream_, "Hit and disabled a breakpoint at %p.\n",
1018 reinterpret_cast<void*>(pc_));
1024 void Simulator::CheckBreakNext() {
1025 // If the current instruction is a BL, insert a breakpoint just after it.
1026 if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
1027 SetBreakpoint(pc_->following());
1028 break_on_next_ = false;
1033 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1034 Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
1035 for (Instruction* pc = start; pc < end; pc = pc->following()) {
1036 disassembler_decoder_->Decode(pc);
1041 void Simulator::PrintSystemRegisters(bool print_all) {
1042 static bool first_run = true;
1044 static SimSystemRegister last_nzcv;
1045 if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) {
1046 fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
1049 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
1054 static SimSystemRegister last_fpcr;
1055 if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) {
1056 static const char * rmode[] = {
1057 "0b00 (Round to Nearest)",
1058 "0b01 (Round towards Plus Infinity)",
1059 "0b10 (Round towards Minus Infinity)",
1060 "0b11 (Round towards Zero)"
1062 ASSERT(fpcr().RMode() <= (sizeof(rmode) / sizeof(rmode[0])));
1063 fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1066 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1075 void Simulator::PrintRegisters(bool print_all_regs) {
1076 static bool first_run = true;
1077 static int64_t last_regs[kNumberOfRegisters];
1079 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1080 if (print_all_regs || first_run ||
1081 (last_regs[i] != xreg(i, Reg31IsStackPointer))) {
1083 "# %s%4s:%s 0x%016" PRIx64 "%s\n",
1085 XRegNameForCode(i, Reg31IsStackPointer),
1087 xreg(i, Reg31IsStackPointer),
1090 // Cache the new register value so the next run can detect any changes.
1091 last_regs[i] = xreg(i, Reg31IsStackPointer);
1097 void Simulator::PrintFPRegisters(bool print_all_regs) {
1098 static bool first_run = true;
1099 static uint64_t last_regs[kNumberOfFPRegisters];
1101 // Print as many rows of registers as necessary, keeping each individual
1102 // register in the same column each time (to make it easy to visually scan
1104 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
1105 if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) {
1107 "# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
1123 // Cache the new register value so the next run can detect any changes.
1124 last_regs[i] = dreg_bits(i);
1130 void Simulator::PrintProcessorState() {
1131 PrintSystemRegisters();
1137 void Simulator::PrintWrite(uint8_t* address,
1139 unsigned num_bytes) {
1140 // The template is "# value -> address". The template is not directly used
1141 // in the printf since compilers tend to struggle with the parametrized
1143 const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIx64 "%s\n";
1147 num_bytes * 2, // The width in hexa characters.
1156 // Visitors---------------------------------------------------------------------
1158 void Simulator::VisitUnimplemented(Instruction* instr) {
1159 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1160 reinterpret_cast<void*>(instr), instr->InstructionBits());
1165 void Simulator::VisitUnallocated(Instruction* instr) {
1166 fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1167 reinterpret_cast<void*>(instr), instr->InstructionBits());
1172 void Simulator::VisitPCRelAddressing(Instruction* instr) {
1173 switch (instr->Mask(PCRelAddressingMask)) {
1175 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
1177 case ADRP: // Not implemented in the assembler.
1187 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
1188 switch (instr->Mask(UnconditionalBranchMask)) {
1190 set_lr(instr->following());
1193 set_pc(instr->ImmPCOffsetTarget());
1201 void Simulator::VisitConditionalBranch(Instruction* instr) {
1202 ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1203 if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
1204 set_pc(instr->ImmPCOffsetTarget());
1209 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1210 Instruction* target = reg<Instruction*>(instr->Rn());
1211 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1213 set_lr(instr->following());
1214 if (instr->Rn() == 31) {
1215 // BLR XZR is used as a guard for the constant pool. We should never hit
1216 // this, but if we do trap to allow debugging.
1222 case RET: set_pc(target); break;
1223 default: UNIMPLEMENTED();
1228 void Simulator::VisitTestBranch(Instruction* instr) {
1229 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1230 instr->ImmTestBranchBit40();
1231 bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
1232 switch (instr->Mask(TestBranchMask)) {
1234 case TBNZ: take_branch = !take_branch; break;
1235 default: UNIMPLEMENTED();
1238 set_pc(instr->ImmPCOffsetTarget());
1243 void Simulator::VisitCompareBranch(Instruction* instr) {
1244 unsigned rt = instr->Rt();
1245 bool take_branch = false;
1246 switch (instr->Mask(CompareBranchMask)) {
1247 case CBZ_w: take_branch = (wreg(rt) == 0); break;
1248 case CBZ_x: take_branch = (xreg(rt) == 0); break;
1249 case CBNZ_w: take_branch = (wreg(rt) != 0); break;
1250 case CBNZ_x: take_branch = (xreg(rt) != 0); break;
1251 default: UNIMPLEMENTED();
1254 set_pc(instr->ImmPCOffsetTarget());
1259 void Simulator::AddSubHelper(Instruction* instr, int64_t op2) {
1260 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1262 bool set_flags = instr->FlagsUpdate();
1263 int64_t new_val = 0;
1264 Instr operation = instr->Mask(AddSubOpMask);
1266 switch (operation) {
1269 new_val = AddWithCarry(reg_size,
1271 reg(reg_size, instr->Rn(), instr->RnMode()),
1277 new_val = AddWithCarry(reg_size,
1279 reg(reg_size, instr->Rn(), instr->RnMode()),
1284 default: UNREACHABLE();
1287 set_reg(reg_size, instr->Rd(), new_val, instr->RdMode());
1291 void Simulator::VisitAddSubShifted(Instruction* instr) {
1292 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1294 int64_t op2 = ShiftOperand(reg_size,
1295 reg(reg_size, instr->Rm()),
1296 static_cast<Shift>(instr->ShiftDP()),
1297 instr->ImmDPShift());
1298 AddSubHelper(instr, op2);
1302 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1303 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1304 AddSubHelper(instr, op2);
1308 void Simulator::VisitAddSubExtended(Instruction* instr) {
1309 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1311 int64_t op2 = ExtendValue(reg_size,
1312 reg(reg_size, instr->Rm()),
1313 static_cast<Extend>(instr->ExtendMode()),
1314 instr->ImmExtendShift());
1315 AddSubHelper(instr, op2);
1319 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1320 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1322 int64_t op2 = reg(reg_size, instr->Rm());
1325 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
1329 new_val = AddWithCarry(reg_size,
1330 instr->FlagsUpdate(),
1331 reg(reg_size, instr->Rn()),
1335 set_reg(reg_size, instr->Rd(), new_val);
1339 void Simulator::VisitLogicalShifted(Instruction* instr) {
1340 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1342 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1343 unsigned shift_amount = instr->ImmDPShift();
1344 int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
1346 if (instr->Mask(NOT) == NOT) {
1349 LogicalHelper(instr, op2);
1353 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1354 LogicalHelper(instr, instr->ImmLogical());
1358 void Simulator::LogicalHelper(Instruction* instr, int64_t op2) {
1359 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1361 int64_t op1 = reg(reg_size, instr->Rn());
1363 bool update_flags = false;
1365 // Switch on the logical operation, stripping out the NOT bit, as it has a
1366 // different meaning for logical immediate instructions.
1367 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1368 case ANDS: update_flags = true; // Fall through.
1369 case AND: result = op1 & op2; break;
1370 case ORR: result = op1 | op2; break;
1371 case EOR: result = op1 ^ op2; break;
1377 nzcv().SetN(CalcNFlag(result, reg_size));
1378 nzcv().SetZ(CalcZFlag(result));
1383 set_reg(reg_size, instr->Rd(), result, instr->RdMode());
1387 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1388 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1390 ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
1394 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1395 ConditionalCompareHelper(instr, instr->ImmCondCmp());
1399 void Simulator::ConditionalCompareHelper(Instruction* instr, int64_t op2) {
1400 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1402 int64_t op1 = reg(reg_size, instr->Rn());
1404 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1405 // If the condition passes, set the status flags to the result of comparing
1407 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1408 AddWithCarry(reg_size, true, op1, ~op2, 1);
1410 ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1411 AddWithCarry(reg_size, true, op1, op2, 0);
1414 // If the condition fails, set the status flags to the nzcv immediate.
1415 nzcv().SetFlags(instr->Nzcv());
1420 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1421 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1422 LoadStoreHelper(instr, offset, Offset);
1426 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1427 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1431 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1432 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1436 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1437 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1441 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1442 Extend ext = static_cast<Extend>(instr->ExtendMode());
1443 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1444 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1446 int64_t offset = ExtendValue(kXRegSizeInBits, xreg(instr->Rm()), ext,
1448 LoadStoreHelper(instr, offset, Offset);
1452 void Simulator::LoadStoreHelper(Instruction* instr,
1454 AddrMode addrmode) {
1455 unsigned srcdst = instr->Rt();
1456 unsigned addr_reg = instr->Rn();
1457 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode);
1458 int num_bytes = 1 << instr->SizeLS();
1459 uint8_t* stack = NULL;
1461 // Handle the writeback for stores before the store. On a CPU the writeback
1462 // and the store are atomic, but when running on the simulator it is possible
1463 // to be interrupted in between. The simulator is not thread safe and V8 does
1464 // not require it to be to run JavaScript therefore the profiler may sample
1465 // the "simulated" CPU in the middle of load/store with writeback. The code
1466 // below ensures that push operations are safe even when interrupted: the
1467 // stack pointer will be decremented before adding an element to the stack.
1468 if (instr->IsStore()) {
1469 LoadStoreWriteBack(addr_reg, offset, addrmode);
1471 // For store the address post writeback is used to check access below the
1473 stack = reinterpret_cast<uint8_t*>(sp());
1476 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
1481 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break;
1485 case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break;
1488 ExtendValue(kWRegSizeInBits, MemoryRead8(address), SXTB));
1493 ExtendValue(kXRegSizeInBits, MemoryRead8(address), SXTB));
1498 ExtendValue(kWRegSizeInBits, MemoryRead16(address), SXTH));
1503 ExtendValue(kXRegSizeInBits, MemoryRead16(address), SXTH));
1508 ExtendValue(kXRegSizeInBits, MemoryRead32(address), SXTW));
1511 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break;
1512 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break;
1513 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break;
1514 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break;
1515 default: UNIMPLEMENTED();
1518 // Handle the writeback for loads after the load to ensure safe pop
1519 // operation even when interrupted in the middle of it. The stack pointer
1520 // is only updated after the load so pop(fp) will never break the invariant
1521 // sp <= fp expected while walking the stack in the sampler.
1522 if (instr->IsLoad()) {
1523 // For loads the address pre writeback is used to check access below the
1525 stack = reinterpret_cast<uint8_t*>(sp());
1527 LoadStoreWriteBack(addr_reg, offset, addrmode);
1530 // Accesses below the stack pointer (but above the platform stack limit) are
1531 // not allowed in the ABI.
1532 CheckMemoryAccess(address, stack);
1536 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1537 LoadStorePairHelper(instr, Offset);
1541 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1542 LoadStorePairHelper(instr, PreIndex);
1546 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1547 LoadStorePairHelper(instr, PostIndex);
1551 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
1552 LoadStorePairHelper(instr, Offset);
1556 void Simulator::LoadStorePairHelper(Instruction* instr,
1557 AddrMode addrmode) {
1558 unsigned rt = instr->Rt();
1559 unsigned rt2 = instr->Rt2();
1560 unsigned addr_reg = instr->Rn();
1561 int offset = instr->ImmLSPair() << instr->SizeLSPair();
1562 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode);
1563 uint8_t* stack = NULL;
1565 // Handle the writeback for stores before the store. On a CPU the writeback
1566 // and the store are atomic, but when running on the simulator it is possible
1567 // to be interrupted in between. The simulator is not thread safe and V8 does
1568 // not require it to be to run JavaScript therefore the profiler may sample
1569 // the "simulated" CPU in the middle of load/store with writeback. The code
1570 // below ensures that push operations are safe even when interrupted: the
1571 // stack pointer will be decremented before adding an element to the stack.
1572 if (instr->IsStore()) {
1573 LoadStoreWriteBack(addr_reg, offset, addrmode);
1575 // For store the address post writeback is used to check access below the
1577 stack = reinterpret_cast<uint8_t*>(sp());
1580 LoadStorePairOp op =
1581 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1583 // 'rt' and 'rt2' can only be aliased for stores.
1584 ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1588 set_wreg(rt, MemoryRead32(address));
1589 set_wreg(rt2, MemoryRead32(address + kWRegSize));
1593 set_sreg(rt, MemoryReadFP32(address));
1594 set_sreg(rt2, MemoryReadFP32(address + kSRegSize));
1598 set_xreg(rt, MemoryRead64(address));
1599 set_xreg(rt2, MemoryRead64(address + kXRegSize));
1603 set_dreg(rt, MemoryReadFP64(address));
1604 set_dreg(rt2, MemoryReadFP64(address + kDRegSize));
1608 set_xreg(rt, ExtendValue(kXRegSizeInBits, MemoryRead32(address), SXTW));
1609 set_xreg(rt2, ExtendValue(kXRegSizeInBits,
1610 MemoryRead32(address + kWRegSize), SXTW));
1614 MemoryWrite32(address, wreg(rt));
1615 MemoryWrite32(address + kWRegSize, wreg(rt2));
1619 MemoryWriteFP32(address, sreg(rt));
1620 MemoryWriteFP32(address + kSRegSize, sreg(rt2));
1624 MemoryWrite64(address, xreg(rt));
1625 MemoryWrite64(address + kXRegSize, xreg(rt2));
1629 MemoryWriteFP64(address, dreg(rt));
1630 MemoryWriteFP64(address + kDRegSize, dreg(rt2));
1633 default: UNREACHABLE();
1636 // Handle the writeback for loads after the load to ensure safe pop
1637 // operation even when interrupted in the middle of it. The stack pointer
1638 // is only updated after the load so pop(fp) will never break the invariant
1639 // sp <= fp expected while walking the stack in the sampler.
1640 if (instr->IsLoad()) {
1641 // For loads the address pre writeback is used to check access below the
1643 stack = reinterpret_cast<uint8_t*>(sp());
1645 LoadStoreWriteBack(addr_reg, offset, addrmode);
1648 // Accesses below the stack pointer (but above the platform stack limit) are
1649 // not allowed in the ABI.
1650 CheckMemoryAccess(address, stack);
1654 void Simulator::VisitLoadLiteral(Instruction* instr) {
1655 uint8_t* address = instr->LiteralAddress();
1656 unsigned rt = instr->Rt();
1658 switch (instr->Mask(LoadLiteralMask)) {
1659 case LDR_w_lit: set_wreg(rt, MemoryRead32(address)); break;
1660 case LDR_x_lit: set_xreg(rt, MemoryRead64(address)); break;
1661 case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address)); break;
1662 case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address)); break;
1663 default: UNREACHABLE();
1668 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg,
1670 AddrMode addrmode) {
1671 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1672 int64_t address = xreg(addr_reg, Reg31IsStackPointer);
1673 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
1674 // When the base register is SP the stack pointer is required to be
1675 // quadword aligned prior to the address calculation and write-backs.
1676 // Misalignment will cause a stack alignment fault.
1677 FATAL("ALIGNMENT EXCEPTION");
1680 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1684 return reinterpret_cast<uint8_t*>(address);
1688 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
1690 AddrMode addrmode) {
1691 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1692 ASSERT(offset != 0);
1693 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1694 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
1699 void Simulator::CheckMemoryAccess(uint8_t* address, uint8_t* stack) {
1700 if ((address >= stack_limit_) && (address < stack)) {
1701 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
1702 fprintf(stream_, " sp is here: 0x%16p\n", stack);
1703 fprintf(stream_, " access was here: 0x%16p\n", address);
1704 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_);
1705 fprintf(stream_, "\n");
1706 FATAL("ACCESS BELOW STACK POINTER");
1711 uint64_t Simulator::MemoryRead(uint8_t* address, unsigned num_bytes) {
1712 ASSERT(address != NULL);
1713 ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
1715 memcpy(&read, address, num_bytes);
1720 uint8_t Simulator::MemoryRead8(uint8_t* address) {
1721 return MemoryRead(address, sizeof(uint8_t));
1725 uint16_t Simulator::MemoryRead16(uint8_t* address) {
1726 return MemoryRead(address, sizeof(uint16_t));
1730 uint32_t Simulator::MemoryRead32(uint8_t* address) {
1731 return MemoryRead(address, sizeof(uint32_t));
1735 float Simulator::MemoryReadFP32(uint8_t* address) {
1736 return rawbits_to_float(MemoryRead32(address));
1740 uint64_t Simulator::MemoryRead64(uint8_t* address) {
1741 return MemoryRead(address, sizeof(uint64_t));
1745 double Simulator::MemoryReadFP64(uint8_t* address) {
1746 return rawbits_to_double(MemoryRead64(address));
1750 void Simulator::MemoryWrite(uint8_t* address,
1752 unsigned num_bytes) {
1753 ASSERT(address != NULL);
1754 ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
1756 LogWrite(address, value, num_bytes);
1757 memcpy(address, &value, num_bytes);
1761 void Simulator::MemoryWrite32(uint8_t* address, uint32_t value) {
1762 MemoryWrite(address, value, sizeof(uint32_t));
1766 void Simulator::MemoryWriteFP32(uint8_t* address, float value) {
1767 MemoryWrite32(address, float_to_rawbits(value));
1771 void Simulator::MemoryWrite64(uint8_t* address, uint64_t value) {
1772 MemoryWrite(address, value, sizeof(uint64_t));
1776 void Simulator::MemoryWriteFP64(uint8_t* address, double value) {
1777 MemoryWrite64(address, double_to_rawbits(value));
1781 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
1782 MoveWideImmediateOp mov_op =
1783 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1784 int64_t new_xn_val = 0;
1786 bool is_64_bits = instr->SixtyFourBits() == 1;
1787 // Shift is limited for W operations.
1788 ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
1790 // Get the shifted immediate.
1791 int64_t shift = instr->ShiftMoveWide() * 16;
1792 int64_t shifted_imm16 = instr->ImmMoveWide() << shift;
1794 // Compute the new value.
1798 new_xn_val = ~shifted_imm16;
1799 if (!is_64_bits) new_xn_val &= kWRegMask;
1804 unsigned reg_code = instr->Rd();
1805 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1807 new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
1812 new_xn_val = shifted_imm16;
1819 // Update the destination register.
1820 set_xreg(instr->Rd(), new_xn_val);
1824 void Simulator::VisitConditionalSelect(Instruction* instr) {
1825 uint64_t new_val = xreg(instr->Rn());
1827 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1828 new_val = xreg(instr->Rm());
1829 switch (instr->Mask(ConditionalSelectMask)) {
1833 case CSINC_x: new_val++; break;
1835 case CSINV_x: new_val = ~new_val; break;
1837 case CSNEG_x: new_val = -new_val; break;
1838 default: UNIMPLEMENTED();
1841 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1843 set_reg(reg_size, instr->Rd(), new_val);
1847 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
1848 unsigned dst = instr->Rd();
1849 unsigned src = instr->Rn();
1851 switch (instr->Mask(DataProcessing1SourceMask)) {
1852 case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSizeInBits)); break;
1853 case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSizeInBits)); break;
1854 case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break;
1855 case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break;
1856 case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break;
1857 case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break;
1858 case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break;
1859 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits));
1861 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits));
1864 set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits));
1868 set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits));
1871 default: UNIMPLEMENTED();
1876 uint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) {
1877 ASSERT((num_bits == kWRegSizeInBits) || (num_bits == kXRegSizeInBits));
1878 uint64_t result = 0;
1879 for (unsigned i = 0; i < num_bits; i++) {
1880 result = (result << 1) | (value & 1);
1887 uint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) {
1888 // Split the 64-bit value into an 8-bit array, where b[0] is the least
1889 // significant byte, and b[7] is the most significant.
1891 uint64_t mask = 0xff00000000000000UL;
1892 for (int i = 7; i >= 0; i--) {
1893 bytes[i] = (value & mask) >> (i * 8);
1897 // Permutation tables for REV instructions.
1898 // permute_table[Reverse16] is used by REV16_x, REV16_w
1899 // permute_table[Reverse32] is used by REV32_x, REV_w
1900 // permute_table[Reverse64] is used by REV_x
1901 ASSERT((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2));
1902 static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1},
1903 {4, 5, 6, 7, 0, 1, 2, 3},
1904 {0, 1, 2, 3, 4, 5, 6, 7} };
1905 uint64_t result = 0;
1906 for (int i = 0; i < 8; i++) {
1908 result |= bytes[permute_table[mode][i]];
1914 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
1915 Shift shift_op = NO_SHIFT;
1917 switch (instr->Mask(DataProcessing2SourceMask)) {
1919 int32_t rn = wreg(instr->Rn());
1920 int32_t rm = wreg(instr->Rm());
1921 if ((rn == kWMinInt) && (rm == -1)) {
1923 } else if (rm == 0) {
1924 // Division by zero can be trapped, but not on A-class processors.
1932 int64_t rn = xreg(instr->Rn());
1933 int64_t rm = xreg(instr->Rm());
1934 if ((rn == kXMinInt) && (rm == -1)) {
1936 } else if (rm == 0) {
1937 // Division by zero can be trapped, but not on A-class processors.
1945 uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
1946 uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
1948 // Division by zero can be trapped, but not on A-class processors.
1956 uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
1957 uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
1959 // Division by zero can be trapped, but not on A-class processors.
1967 case LSLV_x: shift_op = LSL; break;
1969 case LSRV_x: shift_op = LSR; break;
1971 case ASRV_x: shift_op = ASR; break;
1973 case RORV_x: shift_op = ROR; break;
1974 default: UNIMPLEMENTED();
1977 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
1979 if (shift_op != NO_SHIFT) {
1980 // Shift distance encoded in the least-significant five/six bits of the
1982 int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
1983 unsigned shift = wreg(instr->Rm()) & mask;
1984 result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
1987 set_reg(reg_size, instr->Rd(), result);
1991 // The algorithm used is described in section 8.2 of
1992 // Hacker's Delight, by Henry S. Warren, Jr.
1993 // It assumes that a right shift on a signed integer is an arithmetic shift.
1994 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
1995 uint64_t u0, v0, w0;
1996 int64_t u1, v1, w1, w2, t;
1998 u0 = u & 0xffffffffL;
2000 v0 = v & 0xffffffffL;
2004 t = u1 * v0 + (w0 >> 32);
2005 w1 = t & 0xffffffffL;
2009 return u1 * v1 + w2 + (w1 >> 32);
2013 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
2014 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
2018 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2019 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
2020 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
2021 int64_t rn_s32 = reg<int32_t>(instr->Rn());
2022 int64_t rm_s32 = reg<int32_t>(instr->Rm());
2023 switch (instr->Mask(DataProcessing3SourceMask)) {
2026 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
2030 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
2032 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
2033 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
2034 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
2035 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
2037 ASSERT(instr->Ra() == kZeroRegCode);
2038 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
2040 default: UNIMPLEMENTED();
2042 set_reg(reg_size, instr->Rd(), result);
2046 void Simulator::VisitBitfield(Instruction* instr) {
2047 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits
2049 int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
2050 int64_t R = instr->ImmR();
2051 int64_t S = instr->ImmS();
2052 int64_t diff = S - R;
2055 mask = diff < reg_size - 1 ? (1L << (diff + 1)) - 1
2058 mask = ((1L << (S + 1)) - 1);
2059 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
2063 // inzero indicates if the extracted bitfield is inserted into the
2064 // destination register value or in zero.
2065 // If extend is true, extend the sign of the extracted bitfield.
2066 bool inzero = false;
2067 bool extend = false;
2068 switch (instr->Mask(BitfieldMask)) {
2085 int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
2086 int64_t src = reg(reg_size, instr->Rn());
2087 // Rotate source bitfield into place.
2088 int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
2089 // Determine the sign extension.
2090 int64_t topbits_preshift = (1L << (reg_size - diff - 1)) - 1;
2091 int64_t signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0)
2094 // Merge sign extension, dest/zero and bitfield.
2095 result = signbits | (result & mask) | (dst & ~mask);
2097 set_reg(reg_size, instr->Rd(), result);
2101 void Simulator::VisitExtract(Instruction* instr) {
2102 unsigned lsb = instr->ImmS();
2103 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
2107 (static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb) |
2108 (reg(reg_size, instr->Rn()) << (reg_size - lsb)));
2112 void Simulator::VisitFPImmediate(Instruction* instr) {
2113 AssertSupportedFPCR();
2115 unsigned dest = instr->Rd();
2116 switch (instr->Mask(FPImmediateMask)) {
2117 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
2118 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
2119 default: UNREACHABLE();
2124 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
2125 AssertSupportedFPCR();
2127 unsigned dst = instr->Rd();
2128 unsigned src = instr->Rn();
2130 FPRounding round = fpcr().RMode();
2132 switch (instr->Mask(FPIntegerConvertMask)) {
2133 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
2134 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
2135 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
2136 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
2137 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
2138 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
2139 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
2140 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
2142 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
2145 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
2148 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
2151 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
2154 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
2157 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
2160 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
2163 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
2165 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
2166 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
2167 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
2168 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
2169 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
2170 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
2171 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
2172 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
2173 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
2174 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
2175 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
2176 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
2177 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
2178 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
2179 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
2180 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
2181 case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
2182 case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
2183 case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
2184 case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
2186 // A 32-bit input can be handled in the same way as a 64-bit input, since
2187 // the sign- or zero-extension will not affect the conversion.
2188 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
2189 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
2190 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
2192 set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2195 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
2196 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
2197 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
2199 set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2203 default: UNREACHABLE();
2208 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2209 AssertSupportedFPCR();
2211 unsigned dst = instr->Rd();
2212 unsigned src = instr->Rn();
2213 int fbits = 64 - instr->FPScale();
2215 FPRounding round = fpcr().RMode();
2217 switch (instr->Mask(FPFixedPointConvertMask)) {
2218 // A 32-bit input can be handled in the same way as a 64-bit input, since
2219 // the sign- or zero-extension will not affect the conversion.
2220 case SCVTF_dx_fixed:
2221 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2223 case SCVTF_dw_fixed:
2224 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2226 case UCVTF_dx_fixed:
2227 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2229 case UCVTF_dw_fixed: {
2231 UFixedToDouble(reg<uint32_t>(src), fbits, round));
2234 case SCVTF_sx_fixed:
2235 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2237 case SCVTF_sw_fixed:
2238 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2240 case UCVTF_sx_fixed:
2241 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2243 case UCVTF_sw_fixed: {
2245 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2248 default: UNREACHABLE();
2253 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
2254 value = FPRoundInt(value, rmode);
2255 if (value >= kWMaxInt) {
2257 } else if (value < kWMinInt) {
2260 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
2264 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
2265 value = FPRoundInt(value, rmode);
2266 if (value >= kXMaxInt) {
2268 } else if (value < kXMinInt) {
2271 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
2275 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
2276 value = FPRoundInt(value, rmode);
2277 if (value >= kWMaxUInt) {
2279 } else if (value < 0.0) {
2282 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
2286 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
2287 value = FPRoundInt(value, rmode);
2288 if (value >= kXMaxUInt) {
2290 } else if (value < 0.0) {
2293 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
2297 void Simulator::VisitFPCompare(Instruction* instr) {
2298 AssertSupportedFPCR();
2300 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2302 double fn_val = fpreg(reg_size, instr->Rn());
2304 switch (instr->Mask(FPCompareMask)) {
2306 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
2308 case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
2309 default: UNIMPLEMENTED();
2314 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2315 AssertSupportedFPCR();
2317 switch (instr->Mask(FPConditionalCompareMask)) {
2320 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2321 // If the condition passes, set the status flags to the result of
2322 // comparing the operands.
2323 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2325 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
2327 // If the condition fails, set the status flags to the nzcv immediate.
2328 nzcv().SetFlags(instr->Nzcv());
2332 default: UNIMPLEMENTED();
2337 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2338 AssertSupportedFPCR();
2341 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2342 selected = instr->Rn();
2344 selected = instr->Rm();
2347 switch (instr->Mask(FPConditionalSelectMask)) {
2348 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2349 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2350 default: UNIMPLEMENTED();
2355 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2356 AssertSupportedFPCR();
2358 unsigned fd = instr->Rd();
2359 unsigned fn = instr->Rn();
2361 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2362 case FMOV_s: set_sreg(fd, sreg(fn)); break;
2363 case FMOV_d: set_dreg(fd, dreg(fn)); break;
2364 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break;
2365 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break;
2366 case FNEG_s: set_sreg(fd, -sreg(fn)); break;
2367 case FNEG_d: set_dreg(fd, -dreg(fn)); break;
2368 case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break;
2369 case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break;
2370 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break;
2371 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break;
2373 set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break;
2375 set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break;
2376 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
2377 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
2378 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
2379 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
2380 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
2381 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
2382 default: UNIMPLEMENTED();
2387 // Assemble the specified IEEE-754 components into the target type and apply
2388 // appropriate rounding.
2389 // sign: 0 = positive, 1 = negative
2390 // exponent: Unbiased IEEE-754 exponent.
2391 // mantissa: The mantissa of the input. The top bit (which is not encoded for
2392 // normal IEEE-754 values) must not be omitted. This bit has the
2393 // value 'pow(2, exponent)'.
2395 // The input value is assumed to be a normalized value. That is, the input may
2396 // not be infinity or NaN. If the source value is subnormal, it must be
2397 // normalized before calling this function such that the highest set bit in the
2398 // mantissa has the value 'pow(2, exponent)'.
2400 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
2401 // calling a templated FPRound.
2402 template <class T, int ebits, int mbits>
2403 static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
2404 FPRounding round_mode) {
2405 ASSERT((sign == 0) || (sign == 1));
2407 // Only the FPTieEven rounding mode is implemented.
2408 ASSERT(round_mode == FPTieEven);
2411 // Rounding can promote subnormals to normals, and normals to infinities. For
2412 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
2413 // encodable as a float, but rounding based on the low-order mantissa bits
2414 // could make it overflow. With ties-to-even rounding, this value would become
2417 // ---- Rounding Method ----
2419 // The exponent is irrelevant in the rounding operation, so we treat the
2420 // lowest-order bit that will fit into the result ('onebit') as having
2421 // the value '1'. Similarly, the highest-order bit that won't fit into
2422 // the result ('halfbit') has the value '0.5'. The 'point' sits between
2423 // 'onebit' and 'halfbit':
2425 // These bits fit into the result.
2426 // |---------------------|
2427 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2433 // For subnormal outputs, the range of representable bits is smaller and
2434 // the position of onebit and halfbit depends on the exponent of the
2435 // input, but the method is otherwise similar.
2439 // | halfbit(frac) halfbit(adjusted)
2442 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
2443 // 0b00.0... -> 0b00.0... -> 0b00
2444 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
2445 // 0b00.1... -> 0b00.1... -> 0b01
2446 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
2447 // 0b01.0... -> 0b01.0... -> 0b01
2448 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
2449 // 0b01.1... -> 0b01.1... -> 0b10
2450 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
2451 // 0b10.0... -> 0b10.0... -> 0b10
2452 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
2453 // 0b10.1... -> 0b10.1... -> 0b11
2454 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
2458 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
2460 // mantissa = (mantissa >> shift) + halfbit(adjusted);
2462 static const int mantissa_offset = 0;
2463 static const int exponent_offset = mantissa_offset + mbits;
2464 static const int sign_offset = exponent_offset + ebits;
2465 STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1));
2467 // Bail out early for zero inputs.
2468 if (mantissa == 0) {
2469 return sign << sign_offset;
2472 // If all bits in the exponent are set, the value is infinite or NaN.
2473 // This is true for all binary IEEE-754 formats.
2474 static const int infinite_exponent = (1 << ebits) - 1;
2475 static const int max_normal_exponent = infinite_exponent - 1;
2477 // Apply the exponent bias to encode it for the result. Doing this early makes
2478 // it easy to detect values that will be infinite or subnormal.
2479 exponent += max_normal_exponent >> 1;
2481 if (exponent > max_normal_exponent) {
2482 // Overflow: The input is too large for the result type to represent. The
2483 // FPTieEven rounding mode handles overflows using infinities.
2484 exponent = infinite_exponent;
2486 return (sign << sign_offset) |
2487 (exponent << exponent_offset) |
2488 (mantissa << mantissa_offset);
2491 // Calculate the shift required to move the top mantissa bit to the proper
2492 // place in the destination type.
2493 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
2494 int shift = highest_significant_bit - mbits;
2496 if (exponent <= 0) {
2497 // The output will be subnormal (before rounding).
2499 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
2500 // is necessary because the exponent of a subnormal value (encoded as 0) is
2501 // the same as the exponent of the smallest normal value (encoded as 1).
2502 shift += -exponent + 1;
2504 // Handle inputs that would produce a zero output.
2506 // Shifts higher than highest_significant_bit+1 will always produce a zero
2507 // result. A shift of exactly highest_significant_bit+1 might produce a
2508 // non-zero result after rounding.
2509 if (shift > (highest_significant_bit + 1)) {
2510 // The result will always be +/-0.0.
2511 return sign << sign_offset;
2514 // Properly encode the exponent for a subnormal output.
2517 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
2519 mantissa &= ~(1UL << highest_significant_bit);
2523 // We have to shift the mantissa to the right. Some precision is lost, so we
2524 // need to apply rounding.
2525 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
2526 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
2527 uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
2528 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
2530 T result = (sign << sign_offset) |
2531 (exponent << exponent_offset) |
2532 ((mantissa >> shift) << mantissa_offset);
2534 // A very large mantissa can overflow during rounding. If this happens, the
2535 // exponent should be incremented and the mantissa set to 1.0 (encoded as
2536 // 0). Applying halfbit_adjusted after assembling the float has the nice
2537 // side-effect that this case is handled for free.
2539 // This also handles cases where a very large finite value overflows to
2540 // infinity, or where a very large subnormal value overflows to become
2542 return result + halfbit_adjusted;
2544 // We have to shift the mantissa to the left (or not at all). The input
2545 // mantissa is exactly representable in the output mantissa, so apply no
2546 // rounding correction.
2547 return (sign << sign_offset) |
2548 (exponent << exponent_offset) |
2549 ((mantissa << -shift) << mantissa_offset);
2554 // See FPRound for a description of this function.
2555 static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
2556 uint64_t mantissa, FPRounding round_mode) {
2558 FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
2562 return rawbits_to_double(bits);
2566 // See FPRound for a description of this function.
2567 static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
2568 uint64_t mantissa, FPRounding round_mode) {
2570 FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
2574 return rawbits_to_float(bits);
2578 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
2580 return UFixedToDouble(src, fbits, round);
2582 // This works for all negative values, including INT64_MIN.
2583 return -UFixedToDouble(-src, fbits, round);
2588 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
2589 // An input of 0 is a special case because the result is effectively
2590 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2595 // Calculate the exponent. The highest significant bit will have the value
2597 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2598 const int64_t exponent = highest_significant_bit - fbits;
2600 return FPRoundToDouble(0, exponent, src, round);
2604 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
2606 return UFixedToFloat(src, fbits, round);
2608 // This works for all negative values, including INT64_MIN.
2609 return -UFixedToFloat(-src, fbits, round);
2614 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
2615 // An input of 0 is a special case because the result is effectively
2616 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2621 // Calculate the exponent. The highest significant bit will have the value
2623 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2624 const int32_t exponent = highest_significant_bit - fbits;
2626 return FPRoundToFloat(0, exponent, src, round);
2630 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
2631 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
2632 (value == kFP64NegativeInfinity)) {
2634 } else if (std::isnan(value)) {
2635 return FPProcessNaN(value);
2638 double int_result = floor(value);
2639 double error = value - int_result;
2640 switch (round_mode) {
2642 // Take care of correctly handling the range ]-0.5, -0.0], which must
2644 if ((-0.5 < value) && (value < 0.0)) {
2647 } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
2648 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2649 // result is positive, round up.
2655 // Take care of correctly handling the range [-0.5, -0.0], which must
2657 if ((-0.5 <= value) && (value < 0.0)) {
2660 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2661 // result is odd, round up.
2662 } else if ((error > 0.5) ||
2663 ((error == 0.5) && (fmod(int_result, 2) != 0))) {
2669 // If value > 0 then we take floor(value)
2670 // otherwise, ceil(value)
2672 int_result = ceil(value);
2676 case FPNegativeInfinity: {
2677 // We always use floor(value).
2680 default: UNIMPLEMENTED();
2686 double Simulator::FPToDouble(float value) {
2687 switch (std::fpclassify(value)) {
2689 if (fpcr().DN()) return kFP64DefaultNaN;
2691 // Convert NaNs as the processor would:
2692 // - The sign is propagated.
2693 // - The payload (mantissa) is transferred entirely, except that the top
2694 // bit is forced to '1', making the result a quiet NaN. The unused
2695 // (low-order) payload bits are set to 0.
2696 uint32_t raw = float_to_rawbits(value);
2698 uint64_t sign = raw >> 31;
2699 uint64_t exponent = (1 << 11) - 1;
2700 uint64_t payload = unsigned_bitextract_64(21, 0, raw);
2701 payload <<= (52 - 23); // The unused low-order bits should be 0.
2702 payload |= (1L << 51); // Force a quiet NaN.
2704 return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
2711 // All other inputs are preserved in a standard cast, because every value
2712 // representable using an IEEE-754 float is also representable using an
2714 return static_cast<double>(value);
2719 return static_cast<double>(value);
2723 float Simulator::FPToFloat(double value, FPRounding round_mode) {
2724 // Only the FPTieEven rounding mode is implemented.
2725 ASSERT(round_mode == FPTieEven);
2728 switch (std::fpclassify(value)) {
2730 if (fpcr().DN()) return kFP32DefaultNaN;
2732 // Convert NaNs as the processor would:
2733 // - The sign is propagated.
2734 // - The payload (mantissa) is transferred as much as possible, except
2735 // that the top bit is forced to '1', making the result a quiet NaN.
2736 uint64_t raw = double_to_rawbits(value);
2738 uint32_t sign = raw >> 63;
2739 uint32_t exponent = (1 << 8) - 1;
2740 uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw);
2741 payload |= (1 << 22); // Force a quiet NaN.
2743 return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
2748 // In a C++ cast, any value representable in the target type will be
2749 // unchanged. This is always the case for +/-0.0 and infinities.
2750 return static_cast<float>(value);
2754 case FP_SUBNORMAL: {
2755 // Convert double-to-float as the processor would, assuming that FPCR.FZ
2756 // (flush-to-zero) is not set.
2757 uint64_t raw = double_to_rawbits(value);
2758 // Extract the IEEE-754 double components.
2759 uint32_t sign = raw >> 63;
2760 // Extract the exponent and remove the IEEE-754 encoding bias.
2761 int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023;
2762 // Extract the mantissa and add the implicit '1' bit.
2763 uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
2764 if (std::fpclassify(value) == FP_NORMAL) {
2765 mantissa |= (1UL << 52);
2767 return FPRoundToFloat(sign, exponent, mantissa, round_mode);
2776 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2777 AssertSupportedFPCR();
2779 unsigned fd = instr->Rd();
2780 unsigned fn = instr->Rn();
2781 unsigned fm = instr->Rm();
2783 // Fmaxnm and Fminnm have special NaN handling.
2784 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2785 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return;
2786 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return;
2787 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return;
2788 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return;
2790 break; // Fall through.
2793 if (FPProcessNaNs(instr)) return;
2795 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2796 case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break;
2797 case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break;
2798 case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break;
2799 case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break;
2800 case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break;
2801 case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break;
2802 case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break;
2803 case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break;
2804 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
2805 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
2806 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
2807 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
2812 // These were handled before the standard FPProcessNaNs() stage.
2814 default: UNIMPLEMENTED();
2819 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2820 AssertSupportedFPCR();
2822 unsigned fd = instr->Rd();
2823 unsigned fn = instr->Rn();
2824 unsigned fm = instr->Rm();
2825 unsigned fa = instr->Ra();
2827 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2828 // fd = fa +/- (fn * fm)
2829 case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
2830 case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
2831 case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
2832 case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
2833 // Negated variants of the above.
2835 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2838 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2841 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2844 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2846 default: UNIMPLEMENTED();
2851 template <typename T>
2852 T Simulator::FPAdd(T op1, T op2) {
2853 // NaNs should be handled elsewhere.
2854 ASSERT(!std::isnan(op1) && !std::isnan(op2));
2856 if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
2857 // inf + -inf returns the default NaN.
2858 return FPDefaultNaN<T>();
2860 // Other cases should be handled by standard arithmetic.
2866 template <typename T>
2867 T Simulator::FPDiv(T op1, T op2) {
2868 // NaNs should be handled elsewhere.
2869 ASSERT(!std::isnan(op1) && !std::isnan(op2));
2871 if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
2872 // inf / inf and 0.0 / 0.0 return the default NaN.
2873 return FPDefaultNaN<T>();
2875 // Other cases should be handled by standard arithmetic.
2881 template <typename T>
2882 T Simulator::FPMax(T a, T b) {
2883 // NaNs should be handled elsewhere.
2884 ASSERT(!std::isnan(a) && !std::isnan(b));
2886 if ((a == 0.0) && (b == 0.0) &&
2887 (copysign(1.0, a) != copysign(1.0, b))) {
2888 // a and b are zero, and the sign differs: return +0.0.
2891 return (a > b) ? a : b;
2896 template <typename T>
2897 T Simulator::FPMaxNM(T a, T b) {
2898 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2899 a = kFP64NegativeInfinity;
2900 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2901 b = kFP64NegativeInfinity;
2904 T result = FPProcessNaNs(a, b);
2905 return std::isnan(result) ? result : FPMax(a, b);
2908 template <typename T>
2909 T Simulator::FPMin(T a, T b) {
2910 // NaNs should be handled elsewhere.
2911 ASSERT(!isnan(a) && !isnan(b));
2913 if ((a == 0.0) && (b == 0.0) &&
2914 (copysign(1.0, a) != copysign(1.0, b))) {
2915 // a and b are zero, and the sign differs: return -0.0.
2918 return (a < b) ? a : b;
2923 template <typename T>
2924 T Simulator::FPMinNM(T a, T b) {
2925 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2926 a = kFP64PositiveInfinity;
2927 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2928 b = kFP64PositiveInfinity;
2931 T result = FPProcessNaNs(a, b);
2932 return std::isnan(result) ? result : FPMin(a, b);
2936 template <typename T>
2937 T Simulator::FPMul(T op1, T op2) {
2938 // NaNs should be handled elsewhere.
2939 ASSERT(!std::isnan(op1) && !std::isnan(op2));
2941 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
2942 // inf * 0.0 returns the default NaN.
2943 return FPDefaultNaN<T>();
2945 // Other cases should be handled by standard arithmetic.
2951 template<typename T>
2952 T Simulator::FPMulAdd(T a, T op1, T op2) {
2953 T result = FPProcessNaNs3(a, op1, op2);
2955 T sign_a = copysign(1.0, a);
2956 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
2957 bool isinf_prod = std::isinf(op1) || std::isinf(op2);
2958 bool operation_generates_nan =
2959 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0
2960 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
2961 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
2963 if (std::isnan(result)) {
2964 // Generated NaNs override quiet NaNs propagated from a.
2965 if (operation_generates_nan && IsQuietNaN(a)) {
2966 return FPDefaultNaN<T>();
2972 // If the operation would produce a NaN, return the default NaN.
2973 if (operation_generates_nan) {
2974 return FPDefaultNaN<T>();
2977 // Work around broken fma implementations for exact zero results: The sign of
2978 // exact 0.0 results is positive unless both a and op1 * op2 are negative.
2979 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
2980 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
2983 result = FusedMultiplyAdd(op1, op2, a);
2984 ASSERT(!std::isnan(result));
2986 // Work around broken fma implementations for rounded zero results: If a is
2987 // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
2988 if ((a == 0.0) && (result == 0.0)) {
2989 return copysign(0.0, sign_prod);
2996 template <typename T>
2997 T Simulator::FPSqrt(T op) {
2998 if (std::isnan(op)) {
2999 return FPProcessNaN(op);
3000 } else if (op < 0.0) {
3001 return FPDefaultNaN<T>();
3003 return std::sqrt(op);
3008 template <typename T>
3009 T Simulator::FPSub(T op1, T op2) {
3010 // NaNs should be handled elsewhere.
3011 ASSERT(!std::isnan(op1) && !std::isnan(op2));
3013 if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
3014 // inf - inf returns the default NaN.
3015 return FPDefaultNaN<T>();
3017 // Other cases should be handled by standard arithmetic.
3023 template <typename T>
3024 T Simulator::FPProcessNaN(T op) {
3025 ASSERT(std::isnan(op));
3026 return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
3030 template <typename T>
3031 T Simulator::FPProcessNaNs(T op1, T op2) {
3032 if (IsSignallingNaN(op1)) {
3033 return FPProcessNaN(op1);
3034 } else if (IsSignallingNaN(op2)) {
3035 return FPProcessNaN(op2);
3036 } else if (std::isnan(op1)) {
3037 ASSERT(IsQuietNaN(op1));
3038 return FPProcessNaN(op1);
3039 } else if (std::isnan(op2)) {
3040 ASSERT(IsQuietNaN(op2));
3041 return FPProcessNaN(op2);
3048 template <typename T>
3049 T Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
3050 if (IsSignallingNaN(op1)) {
3051 return FPProcessNaN(op1);
3052 } else if (IsSignallingNaN(op2)) {
3053 return FPProcessNaN(op2);
3054 } else if (IsSignallingNaN(op3)) {
3055 return FPProcessNaN(op3);
3056 } else if (std::isnan(op1)) {
3057 ASSERT(IsQuietNaN(op1));
3058 return FPProcessNaN(op1);
3059 } else if (std::isnan(op2)) {
3060 ASSERT(IsQuietNaN(op2));
3061 return FPProcessNaN(op2);
3062 } else if (std::isnan(op3)) {
3063 ASSERT(IsQuietNaN(op3));
3064 return FPProcessNaN(op3);
3071 bool Simulator::FPProcessNaNs(Instruction* instr) {
3072 unsigned fd = instr->Rd();
3073 unsigned fn = instr->Rn();
3074 unsigned fm = instr->Rm();
3077 if (instr->Mask(FP64) == FP64) {
3078 double result = FPProcessNaNs(dreg(fn), dreg(fm));
3079 if (std::isnan(result)) {
3080 set_dreg(fd, result);
3084 float result = FPProcessNaNs(sreg(fn), sreg(fm));
3085 if (std::isnan(result)) {
3086 set_sreg(fd, result);
3095 void Simulator::VisitSystem(Instruction* instr) {
3096 // Some system instructions hijack their Op and Cp fields to represent a
3097 // range of immediates instead of indicating a different instruction. This
3098 // makes the decoding tricky.
3099 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3100 switch (instr->Mask(SystemSysRegMask)) {
3102 switch (instr->ImmSystemRegister()) {
3103 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
3104 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
3105 default: UNIMPLEMENTED();
3110 switch (instr->ImmSystemRegister()) {
3111 case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break;
3112 case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break;
3113 default: UNIMPLEMENTED();
3118 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3119 ASSERT(instr->Mask(SystemHintMask) == HINT);
3120 switch (instr->ImmHint()) {
3122 default: UNIMPLEMENTED();
3124 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3125 __sync_synchronize();
3132 bool Simulator::GetValue(const char* desc, int64_t* value) {
3133 int regnum = CodeFromName(desc);
3135 unsigned code = regnum;
3136 if (code == kZeroRegCode) {
3137 // Catch the zero register and return 0.
3140 } else if (code == kSPRegInternalCode) {
3141 // Translate the stack pointer code to 31, for Reg31IsStackPointer.
3144 if (desc[0] == 'w') {
3145 *value = wreg(code, Reg31IsStackPointer);
3147 *value = xreg(code, Reg31IsStackPointer);
3150 } else if (strncmp(desc, "0x", 2) == 0) {
3151 return SScanF(desc + 2, "%" SCNx64,
3152 reinterpret_cast<uint64_t*>(value)) == 1;
3154 return SScanF(desc, "%" SCNu64,
3155 reinterpret_cast<uint64_t*>(value)) == 1;
3160 bool Simulator::PrintValue(const char* desc) {
3161 if (strcmp(desc, "csp") == 0) {
3162 ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3163 PrintF(stream_, "%s csp:%s 0x%016" PRIx64 "%s\n",
3164 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3166 } else if (strcmp(desc, "wcsp") == 0) {
3167 ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3168 PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n",
3169 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3173 int i = CodeFromName(desc);
3174 STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters);
3175 if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false;
3177 if (desc[0] == 'v') {
3178 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3179 clr_fpreg_name, VRegNameForCode(i),
3180 clr_fpreg_value, double_to_rawbits(dreg(i)),
3182 clr_fpreg_name, DRegNameForCode(i),
3183 clr_fpreg_value, dreg(i),
3184 clr_fpreg_name, SRegNameForCode(i),
3185 clr_fpreg_value, sreg(i),
3188 } else if (desc[0] == 'd') {
3189 PrintF(stream_, "%s %s:%s %g%s\n",
3190 clr_fpreg_name, DRegNameForCode(i),
3191 clr_fpreg_value, dreg(i),
3194 } else if (desc[0] == 's') {
3195 PrintF(stream_, "%s %s:%s %g%s\n",
3196 clr_fpreg_name, SRegNameForCode(i),
3197 clr_fpreg_value, sreg(i),
3200 } else if (desc[0] == 'w') {
3201 PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n",
3202 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3205 // X register names have a wide variety of starting characters, but anything
3206 // else will be an X register.
3207 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n",
3208 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
3214 void Simulator::Debug() {
3215 #define COMMAND_SIZE 63
3216 #define ARG_SIZE 255
3219 #define XSTR(a) STR(a)
3221 char cmd[COMMAND_SIZE + 1];
3222 char arg1[ARG_SIZE + 1];
3223 char arg2[ARG_SIZE + 1];
3224 char* argv[3] = { cmd, arg1, arg2 };
3226 // Make sure to have a proper terminating character if reaching the limit.
3227 cmd[COMMAND_SIZE] = 0;
3232 bool cleared_log_disasm_bit = false;
3235 // Disassemble the next instruction to execute before doing anything else.
3236 PrintInstructionsAt(pc_, 1);
3237 // Read the command line.
3238 char* line = ReadLine("sim> ");
3242 // Repeat last command by default.
3243 char* last_input = last_debugger_input();
3244 if (strcmp(line, "\n") == 0 && (last_input != NULL)) {
3248 // Update the latest command ran
3249 set_last_debugger_input(line);
3252 // Use sscanf to parse the individual parts of the command line. At the
3253 // moment no command expects more than two parameters.
3254 int argc = SScanF(line,
3255 "%" XSTR(COMMAND_SIZE) "s "
3256 "%" XSTR(ARG_SIZE) "s "
3257 "%" XSTR(ARG_SIZE) "s",
3260 // stepi / si ------------------------------------------------------------
3261 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
3262 // We are about to execute instructions, after which by default we
3263 // should increment the pc_. If it was set when reaching this debug
3264 // instruction, it has not been cleared because this instruction has not
3265 // completed yet. So clear it manually.
3266 pc_modified_ = false;
3269 ExecuteInstruction();
3271 int64_t number_of_instructions_to_execute = 1;
3272 GetValue(arg1, &number_of_instructions_to_execute);
3274 set_log_parameters(log_parameters() | LOG_DISASM);
3275 while (number_of_instructions_to_execute-- > 0) {
3276 ExecuteInstruction();
3278 set_log_parameters(log_parameters() & ~LOG_DISASM);
3282 // If it was necessary, the pc has already been updated or incremented
3283 // when executing the instruction. So we do not want it to be updated
3284 // again. It will be cleared when exiting.
3285 pc_modified_ = true;
3287 // next / n --------------------------------------------------------------
3288 } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
3289 // Tell the simulator to break after the next executed BL.
3290 break_on_next_ = true;
3294 // continue / cont / c ---------------------------------------------------
3295 } else if ((strcmp(cmd, "continue") == 0) ||
3296 (strcmp(cmd, "cont") == 0) ||
3297 (strcmp(cmd, "c") == 0)) {
3298 // Leave the debugger shell.
3301 // disassemble / disasm / di ---------------------------------------------
3302 } else if (strcmp(cmd, "disassemble") == 0 ||
3303 strcmp(cmd, "disasm") == 0 ||
3304 strcmp(cmd, "di") == 0) {
3305 int64_t n_of_instrs_to_disasm = 10; // default value.
3306 int64_t address = reinterpret_cast<int64_t>(pc_); // default value.
3307 if (argc >= 2) { // disasm <n of instrs>
3308 GetValue(arg1, &n_of_instrs_to_disasm);
3310 if (argc >= 3) { // disasm <n of instrs> <address>
3311 GetValue(arg2, &address);
3315 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3316 n_of_instrs_to_disasm);
3319 // print / p -------------------------------------------------------------
3320 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3322 if (strcmp(arg1, "all") == 0) {
3323 PrintRegisters(true);
3324 PrintFPRegisters(true);
3326 if (!PrintValue(arg1)) {
3327 PrintF("%s unrecognized\n", arg1);
3332 "print <register>\n"
3333 " Print the content of a register. (alias 'p')\n"
3334 " 'print all' will print all registers.\n"
3335 " Use 'printobject' to get more details about the value.\n");
3338 // printobject / po ------------------------------------------------------
3339 } else if ((strcmp(cmd, "printobject") == 0) ||
3340 (strcmp(cmd, "po") == 0)) {
3343 if (GetValue(arg1, &value)) {
3344 Object* obj = reinterpret_cast<Object*>(value);
3345 PrintF("%s: \n", arg1);
3353 PrintF("%s unrecognized\n", arg1);
3356 PrintF("printobject <value>\n"
3357 "printobject <register>\n"
3358 " Print details about the value. (alias 'po')\n");
3361 // stack / mem ----------------------------------------------------------
3362 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
3363 int64_t* cur = NULL;
3364 int64_t* end = NULL;
3367 if (strcmp(cmd, "stack") == 0) {
3368 cur = reinterpret_cast<int64_t*>(jssp());
3372 if (!GetValue(arg1, &value)) {
3373 PrintF("%s unrecognized\n", arg1);
3376 cur = reinterpret_cast<int64_t*>(value);
3381 if (argc == next_arg) {
3383 } else if (argc == next_arg + 1) {
3384 if (!GetValue(argv[next_arg], &words)) {
3385 PrintF("%s unrecognized\n", argv[next_arg]);
3386 PrintF("Printing 10 double words by default");
3395 PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64,
3396 reinterpret_cast<uint64_t>(cur), *cur, *cur);
3397 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
3398 int64_t value = *cur;
3399 Heap* current_heap = v8::internal::Isolate::Current()->heap();
3400 if (((value & 1) == 0) || current_heap->Contains(obj)) {
3402 if ((value & kSmiTagMask) == 0) {
3403 STATIC_ASSERT(kSmiValueSize == 32);
3404 int32_t untagged = (value >> kSmiShift) & 0xffffffff;
3405 PrintF("smi %" PRId32, untagged);
3415 // trace / t -------------------------------------------------------------
3416 } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
3417 if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
3418 (LOG_DISASM | LOG_REGS)) {
3419 PrintF("Enabling disassembly and registers tracing\n");
3420 set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
3422 PrintF("Disabling disassembly and registers tracing\n");
3423 set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
3426 // break / b -------------------------------------------------------------
3427 } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
3430 if (GetValue(arg1, &value)) {
3431 SetBreakpoint(reinterpret_cast<Instruction*>(value));
3433 PrintF("%s unrecognized\n", arg1);
3437 PrintF("Use `break <address>` to set or disable a breakpoint\n");
3440 // gdb -------------------------------------------------------------------
3441 } else if (strcmp(cmd, "gdb") == 0) {
3442 PrintF("Relinquishing control to gdb.\n");
3444 PrintF("Regaining control from gdb.\n");
3446 // sysregs ---------------------------------------------------------------
3447 } else if (strcmp(cmd, "sysregs") == 0) {
3448 PrintSystemRegisters();
3450 // help / h --------------------------------------------------------------
3451 } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3455 " Step <n> instructions.\n"
3457 " Continue execution until a BL instruction is reached.\n"
3458 " At this point a breakpoint is set just after this BL.\n"
3459 " Then execution is resumed. It will probably later hit the\n"
3460 " breakpoint just set.\n"
3461 "continue / cont / c\n"
3462 " Continue execution from here.\n"
3463 "disassemble / disasm / di\n"
3464 " disassemble <n> <address>\n"
3465 " Disassemble <n> instructions from current <address>.\n"
3466 " By default <n> is 20 and <address> is the current pc.\n"
3468 " print <register>\n"
3469 " Print the content of a register.\n"
3470 " 'print all' will print all registers.\n"
3471 " Use 'printobject' to get more details about the value.\n"
3472 "printobject / po\n"
3473 " printobject <value>\n"
3474 " printobject <register>\n"
3475 " Print details about the value.\n"
3477 " stack [<words>]\n"
3478 " Dump stack content, default dump 10 words\n"
3480 " mem <address> [<words>]\n"
3481 " Dump memory content, default dump 10 words\n"
3483 " Toggle disassembly and register tracing\n"
3485 " break : list all breakpoints\n"
3486 " break <address> : set / enable / disable a breakpoint.\n"
3490 " Print all system registers (including NZCV).\n");
3492 PrintF("Unknown command: %s\n", cmd);
3493 PrintF("Use 'help' for more information.\n");
3496 if (cleared_log_disasm_bit == true) {
3497 set_log_parameters(log_parameters_ | LOG_DISASM);
3503 void Simulator::VisitException(Instruction* instr) {
3504 switch (instr->Mask(ExceptionMask)) {
3506 if (instr->ImmException() == kImmExceptionIsDebug) {
3507 // Read the arguments encoded inline in the instruction stream.
3509 uint32_t parameters;
3512 pc_->InstructionAtOffset(kDebugCodeOffset),
3515 pc_->InstructionAtOffset(kDebugParamsOffset),
3516 sizeof(parameters));
3517 char const *message =
3518 reinterpret_cast<char const*>(
3519 pc_->InstructionAtOffset(kDebugMessageOffset));
3521 // Always print something when we hit a debug point that breaks.
3522 // We are going to break, so printing something is not an issue in
3524 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3525 if (message != NULL) {
3527 "%sDebugger hit %d: %s%s%s\n",
3535 "%sDebugger hit %d.%s\n",
3543 switch (parameters & kDebuggerTracingDirectivesMask) {
3545 set_log_parameters(log_parameters() | parameters);
3546 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3547 if (parameters & LOG_REGS) { PrintRegisters(); }
3548 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); }
3551 set_log_parameters(log_parameters() & ~parameters);
3553 case TRACE_OVERRIDE:
3554 set_log_parameters(parameters);
3557 // We don't support a one-shot LOG_DISASM.
3558 ASSERT((parameters & LOG_DISASM) == 0);
3559 // Don't print information that is already being traced.
3560 parameters &= ~log_parameters();
3561 // Print the requested information.
3562 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true);
3563 if (parameters & LOG_REGS) PrintRegisters(true);
3564 if (parameters & LOG_FP_REGS) PrintFPRegisters(true);
3567 // The stop parameters are inlined in the code. Skip them:
3568 // - Skip to the end of the message string.
3569 size_t size = kDebugMessageOffset + strlen(message) + 1;
3570 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize));
3571 // - Verify that the unreachable marker is present.
3572 ASSERT(pc_->Mask(ExceptionMask) == HLT);
3573 ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable);
3574 // - Skip past the unreachable marker.
3575 set_pc(pc_->following());
3577 // Check if the debugger should break.
3578 if (parameters & BREAK) Debug();
3580 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3581 DoRuntimeCall(instr);
3582 } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3583 // Read the argument encoded inline in the instruction stream.
3586 pc_->InstructionAtOffset(kPrintfTypeOffset),
3589 const char* format = reg<const char*>(0);
3591 // Pass all of the relevant PCS registers onto printf. It doesn't
3592 // matter if we pass too many as the extra ones won't be read.
3594 fputs(clr_printf, stream_);
3595 if (type == CPURegister::kRegister) {
3596 result = fprintf(stream_, format,
3597 xreg(1), xreg(2), xreg(3), xreg(4),
3598 xreg(5), xreg(6), xreg(7));
3599 } else if (type == CPURegister::kFPRegister) {
3600 result = fprintf(stream_, format,
3601 dreg(0), dreg(1), dreg(2), dreg(3),
3602 dreg(4), dreg(5), dreg(6), dreg(7));
3604 ASSERT(type == CPURegister::kNoRegister);
3605 result = fprintf(stream_, "%s", format);
3607 fputs(clr_normal, stream_);
3610 CorruptAllCallerSavedCPURegisters();
3613 set_xreg(0, result);
3615 // The printf parameters are inlined in the code, so skip them.
3616 set_pc(pc_->InstructionAtOffset(kPrintfLength));
3618 // Set LR as if we'd just called a native printf function.
3621 } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3622 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3623 reinterpret_cast<void*>(pc_));
3637 #endif // USE_SIMULATOR
3639 } } // namespace v8::internal
3641 #endif // V8_TARGET_ARCH_ARM64