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
12 #include "src/arm64/decoder-arm64-inl.h"
13 #include "src/arm64/simulator-arm64.h"
14 #include "src/assembler.h"
15 #include "src/disasm.h"
16 #include "src/macro-assembler.h"
17 #include "src/ostreams.h"
22 #if defined(USE_SIMULATOR)
25 // This macro provides a platform independent use of sscanf. The reason for
26 // SScanF not being implemented in a platform independent way through
27 // ::v8::internal::OS in the same way as SNPrintF is that the
28 // Windows C Run-Time Library does not provide vsscanf.
29 #define SScanF sscanf // NOLINT
32 // Helpers for colors.
33 #define COLOUR(colour_code) "\033[0;" colour_code "m"
34 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
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(WHITE) : "";
47 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : "";
48 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : "";
49 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : "";
50 TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : "";
51 TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : "";
52 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : "";
53 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : "";
54 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : "";
55 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
58 // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
59 void Simulator::TraceSim(const char* format, ...) {
62 va_start(arguments, format);
63 base::OS::VFPrint(stream_, format, arguments);
69 const Instruction* Simulator::kEndOfSimAddress = NULL;
72 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
73 int width = msb - lsb + 1;
74 DCHECK(is_uintn(bits, width) || is_intn(bits, width));
77 uint32_t mask = ((1 << width) - 1) << lsb;
78 DCHECK((mask & write_ignore_mask_) == 0);
80 value_ = (value_ & ~mask) | (bits & mask);
84 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
87 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
89 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
92 return SimSystemRegister();
97 void Simulator::Initialize(Isolate* isolate) {
98 if (isolate->simulator_initialized()) return;
99 isolate->set_simulator_initialized(true);
100 ExternalReference::set_redirector(isolate, &RedirectExternalReference);
104 // Get the active Simulator for the current thread.
105 Simulator* Simulator::current(Isolate* isolate) {
106 Isolate::PerIsolateThreadData* isolate_data =
107 isolate->FindOrAllocatePerThreadDataForThisThread();
108 DCHECK(isolate_data != NULL);
110 Simulator* sim = isolate_data->simulator();
112 if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) {
113 sim = new Simulator(new Decoder<DispatchingDecoderVisitor>(), isolate);
115 sim = new Decoder<Simulator>();
116 sim->isolate_ = isolate;
118 isolate_data->set_simulator(sim);
124 void Simulator::CallVoid(byte* entry, CallArgument* args) {
128 std::vector<int64_t> stack_args(0);
129 for (int i = 0; !args[i].IsEnd(); i++) {
130 CallArgument arg = args[i];
131 if (arg.IsX() && (index_x < 8)) {
132 set_xreg(index_x++, arg.bits());
133 } else if (arg.IsD() && (index_d < 8)) {
134 set_dreg_bits(index_d++, arg.bits());
136 DCHECK(arg.IsD() || arg.IsX());
137 stack_args.push_back(arg.bits());
141 // Process stack arguments, and make sure the stack is suitably aligned.
142 uintptr_t original_stack = sp();
143 uintptr_t entry_stack = original_stack -
144 stack_args.size() * sizeof(stack_args[0]);
145 if (base::OS::ActivationFrameAlignment() != 0) {
146 entry_stack &= -base::OS::ActivationFrameAlignment();
148 char * stack = reinterpret_cast<char*>(entry_stack);
149 std::vector<int64_t>::const_iterator it;
150 for (it = stack_args.begin(); it != stack_args.end(); it++) {
151 memcpy(stack, &(*it), sizeof(*it));
152 stack += sizeof(*it);
155 DCHECK(reinterpret_cast<uintptr_t>(stack) <= original_stack);
158 // Call the generated code.
160 set_lr(kEndOfSimAddress);
161 CheckPCSComplianceAndRun();
163 set_sp(original_stack);
167 int64_t Simulator::CallInt64(byte* entry, CallArgument* args) {
168 CallVoid(entry, args);
173 double Simulator::CallDouble(byte* entry, CallArgument* args) {
174 CallVoid(entry, args);
179 int64_t Simulator::CallJS(byte* entry,
180 byte* function_entry,
185 CallArgument args[] = {
186 CallArgument(function_entry),
193 return CallInt64(entry, args);
196 int64_t Simulator::CallRegExp(byte* entry,
198 int64_t start_offset,
199 const byte* input_start,
200 const byte* input_end,
205 void* return_address,
207 CallArgument args[] = {
209 CallArgument(start_offset),
210 CallArgument(input_start),
211 CallArgument(input_end),
212 CallArgument(output),
213 CallArgument(output_size),
214 CallArgument(stack_base),
215 CallArgument(direct_call),
216 CallArgument(return_address),
217 CallArgument(isolate),
220 return CallInt64(entry, args);
224 void Simulator::CheckPCSComplianceAndRun() {
226 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
227 CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count());
229 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
230 uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters];
232 CPURegList register_list = kCalleeSaved;
233 CPURegList fpregister_list = kCalleeSavedFP;
235 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
236 // x31 is not a caller saved register, so no need to specify if we want
237 // the stack or zero.
238 saved_registers[i] = xreg(register_list.PopLowestIndex().code());
240 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
241 saved_fpregisters[i] =
242 dreg_bits(fpregister_list.PopLowestIndex().code());
244 int64_t original_stack = sp();
246 // Start the simulation!
249 CHECK_EQ(original_stack, sp());
250 // Check that callee-saved registers have been preserved.
251 register_list = kCalleeSaved;
252 fpregister_list = kCalleeSavedFP;
253 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
254 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
256 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
257 DCHECK(saved_fpregisters[i] ==
258 dreg_bits(fpregister_list.PopLowestIndex().code()));
261 // Corrupt caller saved register minus the return regiters.
263 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
265 register_list = kCallerSaved;
266 register_list.Remove(x0);
267 register_list.Remove(x1);
269 // In theory d0 to d7 can be used for return values, but V8 only uses d0
271 fpregister_list = kCallerSavedFP;
272 fpregister_list.Remove(d0);
274 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
275 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
281 // The least significant byte of the curruption value holds the corresponding
283 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
284 if (list->type() == CPURegister::kRegister) {
285 while (!list->IsEmpty()) {
286 unsigned code = list->PopLowestIndex().code();
287 set_xreg(code, value | code);
290 DCHECK(list->type() == CPURegister::kFPRegister);
291 while (!list->IsEmpty()) {
292 unsigned code = list->PopLowestIndex().code();
293 set_dreg_bits(code, value | code);
299 void Simulator::CorruptAllCallerSavedCPURegisters() {
300 // Corrupt alters its parameter so copy them first.
301 CPURegList register_list = kCallerSaved;
302 CPURegList fpregister_list = kCallerSavedFP;
304 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
305 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
310 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
311 uintptr_t Simulator::PushAddress(uintptr_t address) {
312 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
313 intptr_t new_sp = sp() - 2 * kXRegSize;
314 uintptr_t* alignment_slot =
315 reinterpret_cast<uintptr_t*>(new_sp + kXRegSize);
316 memcpy(alignment_slot, &kSlotsZapValue, kPointerSize);
317 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
318 memcpy(stack_slot, &address, kPointerSize);
324 uintptr_t Simulator::PopAddress() {
325 intptr_t current_sp = sp();
326 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
327 uintptr_t address = *stack_slot;
328 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
329 set_sp(current_sp + 2 * kXRegSize);
334 // Returns the limit of the stack area to enable checking for stack overflows.
335 uintptr_t Simulator::StackLimit() const {
336 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
338 return stack_limit_ + 1024;
342 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
343 Isolate* isolate, FILE* stream)
345 last_debugger_input_(NULL),
346 log_parameters_(NO_PARAM),
348 // Setup the decoder.
349 decoder_->AppendVisitor(this);
353 if (FLAG_trace_sim) {
354 decoder_->InsertVisitorBefore(print_disasm_, this);
355 log_parameters_ = LOG_ALL;
358 if (FLAG_log_instruction_stats) {
359 instrument_ = new Instrument(FLAG_log_instruction_file,
360 FLAG_log_instruction_period);
361 decoder_->AppendVisitor(instrument_);
366 Simulator::Simulator()
368 last_debugger_input_(NULL),
369 log_parameters_(NO_PARAM),
372 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats);
376 void Simulator::Init(FILE* stream) {
379 // Allocate and setup the simulator stack.
380 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
381 stack_ = reinterpret_cast<uintptr_t>(new byte[stack_size_]);
382 stack_limit_ = stack_ + stack_protection_size_;
383 uintptr_t tos = stack_ + stack_size_ - stack_protection_size_;
384 // The stack pointer must be 16-byte aligned.
385 set_sp(tos & ~0xfUL);
388 print_disasm_ = new PrintDisassembler(stream_);
390 // The debugger needs to disassemble code without the simulator executing an
391 // instruction, so we create a dedicated decoder.
392 disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>();
393 disassembler_decoder_->AppendVisitor(print_disasm_);
397 void Simulator::ResetState() {
398 // Reset the system registers.
399 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
400 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
402 // Reset registers to 0.
404 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
405 set_xreg(i, 0xbadbeef);
407 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
408 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
409 set_dreg_bits(i, 0x7ff000007f800001UL);
411 // Returning to address 0 exits the Simulator.
412 set_lr(kEndOfSimAddress);
414 // Reset debug helpers.
415 breakpoints_.empty();
416 break_on_next_= false;
420 Simulator::~Simulator() {
421 delete[] reinterpret_cast<byte*>(stack_);
422 if (FLAG_log_instruction_stats) {
425 delete disassembler_decoder_;
426 delete print_disasm_;
427 DeleteArray(last_debugger_input_);
432 void Simulator::Run() {
433 pc_modified_ = false;
434 while (pc_ != kEndOfSimAddress) {
435 ExecuteInstruction();
440 void Simulator::RunFrom(Instruction* start) {
446 // When the generated code calls an external reference we need to catch that in
447 // the simulator. The external reference will be a function compiled for the
448 // host architecture. We need to call that function instead of trying to
449 // execute it with the simulator. We do that by redirecting the external
450 // reference to a svc (Supervisor Call) instruction that is handled by
451 // the simulator. We write the original destination of the jump just at a known
452 // offset from the svc instruction so the simulator knows what to call.
455 Redirection(void* external_function, ExternalReference::Type type)
456 : external_function_(external_function),
459 redirect_call_.SetInstructionBits(
460 HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall));
461 Isolate* isolate = Isolate::Current();
462 next_ = isolate->simulator_redirection();
463 // TODO(all): Simulator flush I cache
464 isolate->set_simulator_redirection(this);
467 void* address_of_redirect_call() {
468 return reinterpret_cast<void*>(&redirect_call_);
471 template <typename T>
472 T external_function() { return reinterpret_cast<T>(external_function_); }
474 ExternalReference::Type type() { return type_; }
476 static Redirection* Get(void* external_function,
477 ExternalReference::Type type) {
478 Isolate* isolate = Isolate::Current();
479 Redirection* current = isolate->simulator_redirection();
480 for (; current != NULL; current = current->next_) {
481 if (current->external_function_ == external_function) {
482 DCHECK_EQ(current->type(), type);
486 return new Redirection(external_function, type);
489 static Redirection* FromHltInstruction(Instruction* redirect_call) {
490 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call);
491 char* addr_of_redirection =
492 addr_of_hlt - OFFSET_OF(Redirection, redirect_call_);
493 return reinterpret_cast<Redirection*>(addr_of_redirection);
496 static void* ReverseRedirection(int64_t reg) {
497 Redirection* redirection =
498 FromHltInstruction(reinterpret_cast<Instruction*>(reg));
499 return redirection->external_function<void*>();
503 void* external_function_;
504 Instruction redirect_call_;
505 ExternalReference::Type type_;
510 // Calls into the V8 runtime are based on this very simple interface.
511 // Note: To be able to return two values from some calls the code in runtime.cc
512 // uses the ObjectPair structure.
513 // The simulator assumes all runtime calls return two 64-bits values. If they
514 // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
521 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
530 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
531 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
532 typedef double (*SimulatorRuntimeFPCall)(double arg1);
533 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
535 // This signature supports direct call in to API function native callback
536 // (refer to InvocationCallback in v8.h).
537 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
538 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
540 // This signature supports direct call to accessor getter callback.
541 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
542 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
545 void Simulator::DoRuntimeCall(Instruction* instr) {
546 Redirection* redirection = Redirection::FromHltInstruction(instr);
548 // The called C code might itself call simulated code, so any
549 // caller-saved registers (including lr) could still be clobbered by a
551 Instruction* return_address = lr();
553 int64_t external = redirection->external_function<int64_t>();
555 TraceSim("Call to host function at %p\n",
556 redirection->external_function<void*>());
558 // SP must be 16-byte-aligned at the call interface.
559 bool stack_alignment_exception = ((sp() & 0xf) != 0);
560 if (stack_alignment_exception) {
561 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
562 FATAL("ALIGNMENT EXCEPTION");
565 switch (redirection->type()) {
567 TraceSim("Type: Unknown.\n");
571 case ExternalReference::BUILTIN_CALL: {
572 // Object* f(v8::internal::Arguments).
573 TraceSim("Type: BUILTIN_CALL\n");
574 SimulatorRuntimeCall target =
575 reinterpret_cast<SimulatorRuntimeCall>(external);
577 // We don't know how many arguments are being passed, but we can
578 // pass 8 without touching the stack. They will be ignored by the
579 // host function if they aren't used.
580 TraceSim("Arguments: "
581 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
582 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
583 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
584 "0x%016" PRIx64 ", 0x%016" PRIx64,
585 xreg(0), xreg(1), xreg(2), xreg(3),
586 xreg(4), xreg(5), xreg(6), xreg(7));
587 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
588 xreg(4), xreg(5), xreg(6), xreg(7));
589 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n",
590 result.res0, result.res1);
592 CorruptAllCallerSavedCPURegisters();
594 set_xreg(0, result.res0);
595 set_xreg(1, result.res1);
599 case ExternalReference::DIRECT_API_CALL: {
600 // void f(v8::FunctionCallbackInfo&)
601 TraceSim("Type: DIRECT_API_CALL\n");
602 SimulatorRuntimeDirectApiCall target =
603 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
604 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
606 TraceSim("No return value.");
608 CorruptAllCallerSavedCPURegisters();
613 case ExternalReference::BUILTIN_COMPARE_CALL: {
614 // int f(double, double)
615 TraceSim("Type: BUILTIN_COMPARE_CALL\n");
616 SimulatorRuntimeCompareCall target =
617 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
618 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
619 int64_t result = target(dreg(0), dreg(1));
620 TraceSim("Returned: %" PRId64 "\n", result);
622 CorruptAllCallerSavedCPURegisters();
628 case ExternalReference::BUILTIN_FP_CALL: {
630 TraceSim("Type: BUILTIN_FP_CALL\n");
631 SimulatorRuntimeFPCall target =
632 reinterpret_cast<SimulatorRuntimeFPCall>(external);
633 TraceSim("Argument: %f\n", dreg(0));
634 double result = target(dreg(0));
635 TraceSim("Returned: %f\n", result);
637 CorruptAllCallerSavedCPURegisters();
643 case ExternalReference::BUILTIN_FP_FP_CALL: {
644 // double f(double, double)
645 TraceSim("Type: BUILTIN_FP_FP_CALL\n");
646 SimulatorRuntimeFPFPCall target =
647 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
648 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
649 double result = target(dreg(0), dreg(1));
650 TraceSim("Returned: %f\n", result);
652 CorruptAllCallerSavedCPURegisters();
658 case ExternalReference::BUILTIN_FP_INT_CALL: {
659 // double f(double, int)
660 TraceSim("Type: BUILTIN_FP_INT_CALL\n");
661 SimulatorRuntimeFPIntCall target =
662 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
663 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
664 double result = target(dreg(0), wreg(0));
665 TraceSim("Returned: %f\n", result);
667 CorruptAllCallerSavedCPURegisters();
673 case ExternalReference::DIRECT_GETTER_CALL: {
674 // void f(Local<String> property, PropertyCallbackInfo& info)
675 TraceSim("Type: DIRECT_GETTER_CALL\n");
676 SimulatorRuntimeDirectGetterCall target =
677 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
678 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
680 target(xreg(0), xreg(1));
681 TraceSim("No return value.");
683 CorruptAllCallerSavedCPURegisters();
688 case ExternalReference::PROFILING_API_CALL: {
689 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
690 TraceSim("Type: PROFILING_API_CALL\n");
691 SimulatorRuntimeProfilingApiCall target =
692 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
693 void* arg1 = Redirection::ReverseRedirection(xreg(1));
694 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
695 target(xreg(0), arg1);
696 TraceSim("No return value.");
698 CorruptAllCallerSavedCPURegisters();
703 case ExternalReference::PROFILING_GETTER_CALL: {
704 // void f(Local<String> property, PropertyCallbackInfo& info,
705 // AccessorNameGetterCallback callback)
706 TraceSim("Type: PROFILING_GETTER_CALL\n");
707 SimulatorRuntimeProfilingGetterCall target =
708 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
710 void* arg2 = Redirection::ReverseRedirection(xreg(2));
711 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
712 xreg(0), xreg(1), arg2);
713 target(xreg(0), xreg(1), arg2);
714 TraceSim("No return value.");
716 CorruptAllCallerSavedCPURegisters();
722 set_lr(return_address);
723 set_pc(return_address);
727 void* Simulator::RedirectExternalReference(void* external_function,
728 ExternalReference::Type type) {
729 Redirection* redirection = Redirection::Get(external_function, type);
730 return redirection->address_of_redirect_call();
734 const char* Simulator::xreg_names[] = {
735 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
736 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
737 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23",
738 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"};
740 const char* Simulator::wreg_names[] = {
741 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
742 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
743 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
744 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"};
746 const char* Simulator::sreg_names[] = {
747 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
748 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
749 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
750 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
752 const char* Simulator::dreg_names[] = {
753 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
754 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
755 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
756 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
758 const char* Simulator::vreg_names[] = {
759 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
760 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
761 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
762 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
765 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
766 STATIC_ASSERT(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1));
767 DCHECK(code < kNumberOfRegisters);
768 // The modulo operator has no effect here, but it silences a broken GCC
769 // warning about out-of-bounds array accesses.
770 code %= kNumberOfRegisters;
772 // If the code represents the stack pointer, index the name after zr.
773 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
774 code = kZeroRegCode + 1;
776 return wreg_names[code];
780 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
781 STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1));
782 DCHECK(code < kNumberOfRegisters);
783 code %= kNumberOfRegisters;
785 // If the code represents the stack pointer, index the name after zr.
786 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
787 code = kZeroRegCode + 1;
789 return xreg_names[code];
793 const char* Simulator::SRegNameForCode(unsigned code) {
794 STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters);
795 DCHECK(code < kNumberOfFPRegisters);
796 return sreg_names[code % kNumberOfFPRegisters];
800 const char* Simulator::DRegNameForCode(unsigned code) {
801 STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters);
802 DCHECK(code < kNumberOfFPRegisters);
803 return dreg_names[code % kNumberOfFPRegisters];
807 const char* Simulator::VRegNameForCode(unsigned code) {
808 STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters);
809 DCHECK(code < kNumberOfFPRegisters);
810 return vreg_names[code % kNumberOfFPRegisters];
814 int Simulator::CodeFromName(const char* name) {
815 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
816 if ((strcmp(xreg_names[i], name) == 0) ||
817 (strcmp(wreg_names[i], name) == 0)) {
821 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
822 if ((strcmp(vreg_names[i], name) == 0) ||
823 (strcmp(dreg_names[i], name) == 0) ||
824 (strcmp(sreg_names[i], name) == 0)) {
828 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
829 return kSPRegInternalCode;
835 // Helpers ---------------------------------------------------------------------
836 template <typename T>
837 T Simulator::AddWithCarry(bool set_flags,
841 typedef typename make_unsigned<T>::type unsignedT;
842 DCHECK((carry_in == 0) || (carry_in == 1));
844 T signed_sum = src1 + src2 + carry_in;
845 T result = signed_sum;
849 // Compute the C flag
850 unsignedT u1 = static_cast<unsignedT>(src1);
851 unsignedT u2 = static_cast<unsignedT>(src2);
852 unsignedT urest = std::numeric_limits<unsignedT>::max() - u1;
853 C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1))));
855 // Overflow iff the sign bit is the same for the two inputs and different
857 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
859 N = CalcNFlag(result);
860 Z = CalcZFlag(result);
867 LogSystemRegister(NZCV);
874 void Simulator::AddSubWithCarry(Instruction* instr) {
875 T op2 = reg<T>(instr->Rm());
878 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
882 new_val = AddWithCarry<T>(instr->FlagsUpdate(),
887 set_reg<T>(instr->Rd(), new_val);
890 template <typename T>
891 T Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) {
892 typedef typename make_unsigned<T>::type unsignedT;
898 switch (shift_type) {
900 return value << amount;
902 return static_cast<unsignedT>(value) >> amount;
904 return value >> amount;
906 return (static_cast<unsignedT>(value) >> amount) |
907 ((value & ((1L << amount) - 1L)) <<
908 (sizeof(unsignedT) * 8 - amount));
916 template <typename T>
917 T Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) {
918 const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8;
919 const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8;
920 const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8;
922 switch (extend_type) {
927 value &= kHalfWordMask;
933 value = (value << kSignExtendBShift) >> kSignExtendBShift;
936 value = (value << kSignExtendHShift) >> kSignExtendHShift;
939 value = (value << kSignExtendWShift) >> kSignExtendWShift;
947 return value << left_shift;
951 template <typename T>
952 void Simulator::Extract(Instruction* instr) {
953 unsigned lsb = instr->ImmS();
954 T op2 = reg<T>(instr->Rm());
958 T op1 = reg<T>(instr->Rn());
959 result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb));
961 set_reg<T>(instr->Rd(), result);
965 template<> double Simulator::FPDefaultNaN<double>() const {
966 return kFP64DefaultNaN;
970 template<> float Simulator::FPDefaultNaN<float>() const {
971 return kFP32DefaultNaN;
975 void Simulator::FPCompare(double val0, double val1) {
976 AssertSupportedFPCR();
978 // TODO(jbramley): This assumes that the C++ implementation handles
979 // comparisons in the way that we expect (as per AssertSupportedFPCR()).
980 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
981 nzcv().SetRawValue(FPUnorderedFlag);
982 } else if (val0 < val1) {
983 nzcv().SetRawValue(FPLessThanFlag);
984 } else if (val0 > val1) {
985 nzcv().SetRawValue(FPGreaterThanFlag);
986 } else if (val0 == val1) {
987 nzcv().SetRawValue(FPEqualFlag);
991 LogSystemRegister(NZCV);
995 void Simulator::SetBreakpoint(Instruction* location) {
996 for (unsigned i = 0; i < breakpoints_.size(); i++) {
997 if (breakpoints_.at(i).location == location) {
999 "Existing breakpoint at %p was %s\n",
1000 reinterpret_cast<void*>(location),
1001 breakpoints_.at(i).enabled ? "disabled" : "enabled");
1002 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
1006 Breakpoint new_breakpoint = {location, true};
1007 breakpoints_.push_back(new_breakpoint);
1009 "Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
1013 void Simulator::ListBreakpoints() {
1014 PrintF(stream_, "Breakpoints:\n");
1015 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1016 PrintF(stream_, "%p : %s\n",
1017 reinterpret_cast<void*>(breakpoints_.at(i).location),
1018 breakpoints_.at(i).enabled ? "enabled" : "disabled");
1023 void Simulator::CheckBreakpoints() {
1024 bool hit_a_breakpoint = false;
1025 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1026 if ((breakpoints_.at(i).location == pc_) &&
1027 breakpoints_.at(i).enabled) {
1028 hit_a_breakpoint = true;
1029 // Disable this breakpoint.
1030 breakpoints_.at(i).enabled = false;
1033 if (hit_a_breakpoint) {
1034 PrintF(stream_, "Hit and disabled a breakpoint at %p.\n",
1035 reinterpret_cast<void*>(pc_));
1041 void Simulator::CheckBreakNext() {
1042 // If the current instruction is a BL, insert a breakpoint just after it.
1043 if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
1044 SetBreakpoint(pc_->following());
1045 break_on_next_ = false;
1050 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1051 Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
1052 for (Instruction* pc = start; pc < end; pc = pc->following()) {
1053 disassembler_decoder_->Decode(pc);
1058 void Simulator::PrintSystemRegisters() {
1059 PrintSystemRegister(NZCV);
1060 PrintSystemRegister(FPCR);
1064 void Simulator::PrintRegisters() {
1065 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1071 void Simulator::PrintFPRegisters() {
1072 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
1078 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
1079 // Don't print writes into xzr.
1080 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1084 // The template is "# x<code>:value".
1085 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n",
1086 clr_reg_name, XRegNameForCode(code, r31mode),
1087 clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal);
1091 void Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) {
1092 // The template is "# v<code>:bits (d<code>:value, ...)".
1095 DCHECK((sizes & kPrintAllFPRegValues) == sizes);
1097 // Print the raw bits.
1098 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (",
1099 clr_fpreg_name, VRegNameForCode(code),
1100 clr_fpreg_value, fpreg<uint64_t>(code), clr_normal);
1102 // Print all requested value interpretations.
1103 bool need_separator = false;
1104 if (sizes & kPrintDRegValue) {
1105 fprintf(stream_, "%s%s%s: %s%g%s",
1106 need_separator ? ", " : "",
1107 clr_fpreg_name, DRegNameForCode(code),
1108 clr_fpreg_value, fpreg<double>(code), clr_normal);
1109 need_separator = true;
1112 if (sizes & kPrintSRegValue) {
1113 fprintf(stream_, "%s%s%s: %s%g%s",
1114 need_separator ? ", " : "",
1115 clr_fpreg_name, SRegNameForCode(code),
1116 clr_fpreg_value, fpreg<float>(code), clr_normal);
1117 need_separator = true;
1120 // End the value list.
1121 fprintf(stream_, ")\n");
1125 void Simulator::PrintSystemRegister(SystemRegister id) {
1128 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1129 clr_flag_name, clr_flag_value,
1130 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
1134 static const char * rmode[] = {
1135 "0b00 (Round to Nearest)",
1136 "0b01 (Round towards Plus Infinity)",
1137 "0b10 (Round towards Minus Infinity)",
1138 "0b11 (Round towards Zero)"
1140 DCHECK(fpcr().RMode() < arraysize(rmode));
1142 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1143 clr_flag_name, clr_flag_value,
1144 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1154 void Simulator::PrintRead(uintptr_t address,
1156 unsigned reg_code) {
1157 USE(size); // Size is unused here.
1159 // The template is "# x<code>:value <- address".
1160 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1161 clr_reg_name, XRegNameForCode(reg_code),
1162 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1164 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1165 clr_memory_address, address, clr_normal);
1169 void Simulator::PrintReadFP(uintptr_t address,
1171 unsigned reg_code) {
1172 // The template is "# reg:bits (reg:value) <- address".
1175 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)",
1176 clr_fpreg_name, VRegNameForCode(reg_code),
1177 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1178 clr_fpreg_name, SRegNameForCode(reg_code),
1179 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1182 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1183 clr_fpreg_name, VRegNameForCode(reg_code),
1184 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1185 clr_fpreg_name, DRegNameForCode(reg_code),
1186 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1192 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1193 clr_memory_address, address, clr_normal);
1197 void Simulator::PrintWrite(uintptr_t address,
1199 unsigned reg_code) {
1200 // The template is "# reg:value -> address". To keep the trace tidy and
1201 // readable, the value is aligned with the values in the register trace.
1203 case kByteSizeInBytes:
1204 fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s",
1205 clr_reg_name, WRegNameForCode(reg_code),
1206 clr_reg_value, reg<uint8_t>(reg_code), clr_normal);
1208 case kHalfWordSizeInBytes:
1209 fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s",
1210 clr_reg_name, WRegNameForCode(reg_code),
1211 clr_reg_value, reg<uint16_t>(reg_code), clr_normal);
1214 fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s",
1215 clr_reg_name, WRegNameForCode(reg_code),
1216 clr_reg_value, reg<uint32_t>(reg_code), clr_normal);
1219 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1220 clr_reg_name, XRegNameForCode(reg_code),
1221 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1227 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1228 clr_memory_address, address, clr_normal);
1232 void Simulator::PrintWriteFP(uintptr_t address,
1234 unsigned reg_code) {
1235 // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy
1236 // and readable, the value is aligned with the values in the register trace.
1239 fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)",
1240 clr_fpreg_name, VRegNameForCode(reg_code),
1241 clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal,
1242 clr_fpreg_name, SRegNameForCode(reg_code),
1243 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1246 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1247 clr_fpreg_name, VRegNameForCode(reg_code),
1248 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1249 clr_fpreg_name, DRegNameForCode(reg_code),
1250 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1256 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1257 clr_memory_address, address, clr_normal);
1261 // Visitors---------------------------------------------------------------------
1263 void Simulator::VisitUnimplemented(Instruction* instr) {
1264 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1265 reinterpret_cast<void*>(instr), instr->InstructionBits());
1270 void Simulator::VisitUnallocated(Instruction* instr) {
1271 fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1272 reinterpret_cast<void*>(instr), instr->InstructionBits());
1277 void Simulator::VisitPCRelAddressing(Instruction* instr) {
1278 switch (instr->Mask(PCRelAddressingMask)) {
1280 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
1282 case ADRP: // Not implemented in the assembler.
1292 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
1293 switch (instr->Mask(UnconditionalBranchMask)) {
1295 set_lr(instr->following());
1298 set_pc(instr->ImmPCOffsetTarget());
1306 void Simulator::VisitConditionalBranch(Instruction* instr) {
1307 DCHECK(instr->Mask(ConditionalBranchMask) == B_cond);
1308 if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
1309 set_pc(instr->ImmPCOffsetTarget());
1314 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1315 Instruction* target = reg<Instruction*>(instr->Rn());
1316 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1318 set_lr(instr->following());
1319 if (instr->Rn() == 31) {
1320 // BLR XZR is used as a guard for the constant pool. We should never hit
1321 // this, but if we do trap to allow debugging.
1327 case RET: set_pc(target); break;
1328 default: UNIMPLEMENTED();
1333 void Simulator::VisitTestBranch(Instruction* instr) {
1334 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1335 instr->ImmTestBranchBit40();
1336 bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
1337 switch (instr->Mask(TestBranchMask)) {
1339 case TBNZ: take_branch = !take_branch; break;
1340 default: UNIMPLEMENTED();
1343 set_pc(instr->ImmPCOffsetTarget());
1348 void Simulator::VisitCompareBranch(Instruction* instr) {
1349 unsigned rt = instr->Rt();
1350 bool take_branch = false;
1351 switch (instr->Mask(CompareBranchMask)) {
1352 case CBZ_w: take_branch = (wreg(rt) == 0); break;
1353 case CBZ_x: take_branch = (xreg(rt) == 0); break;
1354 case CBNZ_w: take_branch = (wreg(rt) != 0); break;
1355 case CBNZ_x: take_branch = (xreg(rt) != 0); break;
1356 default: UNIMPLEMENTED();
1359 set_pc(instr->ImmPCOffsetTarget());
1364 template<typename T>
1365 void Simulator::AddSubHelper(Instruction* instr, T op2) {
1366 bool set_flags = instr->FlagsUpdate();
1368 Instr operation = instr->Mask(AddSubOpMask);
1370 switch (operation) {
1373 new_val = AddWithCarry<T>(set_flags,
1374 reg<T>(instr->Rn(), instr->RnMode()),
1380 new_val = AddWithCarry<T>(set_flags,
1381 reg<T>(instr->Rn(), instr->RnMode()),
1386 default: UNREACHABLE();
1389 set_reg<T>(instr->Rd(), new_val, instr->RdMode());
1393 void Simulator::VisitAddSubShifted(Instruction* instr) {
1394 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1395 unsigned shift_amount = instr->ImmDPShift();
1397 if (instr->SixtyFourBits()) {
1398 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1399 AddSubHelper(instr, op2);
1401 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1402 AddSubHelper(instr, op2);
1407 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1408 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1409 if (instr->SixtyFourBits()) {
1410 AddSubHelper<int64_t>(instr, op2);
1412 AddSubHelper<int32_t>(instr, op2);
1417 void Simulator::VisitAddSubExtended(Instruction* instr) {
1418 Extend ext = static_cast<Extend>(instr->ExtendMode());
1419 unsigned left_shift = instr->ImmExtendShift();
1420 if (instr->SixtyFourBits()) {
1421 int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
1422 AddSubHelper(instr, op2);
1424 int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
1425 AddSubHelper(instr, op2);
1430 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1431 if (instr->SixtyFourBits()) {
1432 AddSubWithCarry<int64_t>(instr);
1434 AddSubWithCarry<int32_t>(instr);
1439 void Simulator::VisitLogicalShifted(Instruction* instr) {
1440 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1441 unsigned shift_amount = instr->ImmDPShift();
1443 if (instr->SixtyFourBits()) {
1444 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1445 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1446 LogicalHelper<int64_t>(instr, op2);
1448 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1449 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1450 LogicalHelper<int32_t>(instr, op2);
1455 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1456 if (instr->SixtyFourBits()) {
1457 LogicalHelper<int64_t>(instr, instr->ImmLogical());
1459 LogicalHelper<int32_t>(instr, instr->ImmLogical());
1464 template<typename T>
1465 void Simulator::LogicalHelper(Instruction* instr, T op2) {
1466 T op1 = reg<T>(instr->Rn());
1468 bool update_flags = false;
1470 // Switch on the logical operation, stripping out the NOT bit, as it has a
1471 // different meaning for logical immediate instructions.
1472 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1473 case ANDS: update_flags = true; // Fall through.
1474 case AND: result = op1 & op2; break;
1475 case ORR: result = op1 | op2; break;
1476 case EOR: result = op1 ^ op2; break;
1482 nzcv().SetN(CalcNFlag(result));
1483 nzcv().SetZ(CalcZFlag(result));
1486 LogSystemRegister(NZCV);
1489 set_reg<T>(instr->Rd(), result, instr->RdMode());
1493 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1494 if (instr->SixtyFourBits()) {
1495 ConditionalCompareHelper(instr, xreg(instr->Rm()));
1497 ConditionalCompareHelper(instr, wreg(instr->Rm()));
1502 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1503 if (instr->SixtyFourBits()) {
1504 ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp());
1506 ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp());
1511 template<typename T>
1512 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
1513 T op1 = reg<T>(instr->Rn());
1515 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1516 // If the condition passes, set the status flags to the result of comparing
1518 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1519 AddWithCarry<T>(true, op1, ~op2, 1);
1521 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN);
1522 AddWithCarry<T>(true, op1, op2, 0);
1525 // If the condition fails, set the status flags to the nzcv immediate.
1526 nzcv().SetFlags(instr->Nzcv());
1527 LogSystemRegister(NZCV);
1532 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1533 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1534 LoadStoreHelper(instr, offset, Offset);
1538 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1539 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1543 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1544 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1548 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1549 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1553 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1554 Extend ext = static_cast<Extend>(instr->ExtendMode());
1555 DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1556 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1558 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount);
1559 LoadStoreHelper(instr, offset, Offset);
1563 void Simulator::LoadStoreHelper(Instruction* instr,
1565 AddrMode addrmode) {
1566 unsigned srcdst = instr->Rt();
1567 unsigned addr_reg = instr->Rn();
1568 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1569 uintptr_t stack = 0;
1571 // Handle the writeback for stores before the store. On a CPU the writeback
1572 // and the store are atomic, but when running on the simulator it is possible
1573 // to be interrupted in between. The simulator is not thread safe and V8 does
1574 // not require it to be to run JavaScript therefore the profiler may sample
1575 // the "simulated" CPU in the middle of load/store with writeback. The code
1576 // below ensures that push operations are safe even when interrupted: the
1577 // stack pointer will be decremented before adding an element to the stack.
1578 if (instr->IsStore()) {
1579 LoadStoreWriteBack(addr_reg, offset, addrmode);
1581 // For store the address post writeback is used to check access below the
1586 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
1588 // Use _no_log variants to suppress the register trace (LOG_REGS,
1589 // LOG_FP_REGS). We will print a more detailed log.
1590 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break;
1591 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break;
1592 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break;
1593 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break;
1594 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1595 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1596 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1597 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1598 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break;
1599 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break;
1600 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break;
1602 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break;
1603 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break;
1604 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break;
1605 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break;
1606 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break;
1607 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break;
1609 default: UNIMPLEMENTED();
1612 // Print a detailed trace (including the memory address) instead of the basic
1613 // register:value trace generated by set_*reg().
1614 size_t access_size = 1 << instr->SizeLS();
1615 if (instr->IsLoad()) {
1616 if ((op == LDR_s) || (op == LDR_d)) {
1617 LogReadFP(address, access_size, srcdst);
1619 LogRead(address, access_size, srcdst);
1622 if ((op == STR_s) || (op == STR_d)) {
1623 LogWriteFP(address, access_size, srcdst);
1625 LogWrite(address, access_size, srcdst);
1629 // Handle the writeback for loads after the load to ensure safe pop
1630 // operation even when interrupted in the middle of it. The stack pointer
1631 // is only updated after the load so pop(fp) will never break the invariant
1632 // sp <= fp expected while walking the stack in the sampler.
1633 if (instr->IsLoad()) {
1634 // For loads the address pre writeback is used to check access below the
1638 LoadStoreWriteBack(addr_reg, offset, addrmode);
1641 // Accesses below the stack pointer (but above the platform stack limit) are
1642 // not allowed in the ABI.
1643 CheckMemoryAccess(address, stack);
1647 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1648 LoadStorePairHelper(instr, Offset);
1652 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1653 LoadStorePairHelper(instr, PreIndex);
1657 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1658 LoadStorePairHelper(instr, PostIndex);
1662 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
1663 LoadStorePairHelper(instr, Offset);
1667 void Simulator::LoadStorePairHelper(Instruction* instr,
1668 AddrMode addrmode) {
1669 unsigned rt = instr->Rt();
1670 unsigned rt2 = instr->Rt2();
1671 unsigned addr_reg = instr->Rn();
1672 size_t access_size = 1 << instr->SizeLSPair();
1673 int64_t offset = instr->ImmLSPair() * access_size;
1674 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1675 uintptr_t address2 = address + access_size;
1676 uintptr_t stack = 0;
1678 // Handle the writeback for stores before the store. On a CPU the writeback
1679 // and the store are atomic, but when running on the simulator it is possible
1680 // to be interrupted in between. The simulator is not thread safe and V8 does
1681 // not require it to be to run JavaScript therefore the profiler may sample
1682 // the "simulated" CPU in the middle of load/store with writeback. The code
1683 // below ensures that push operations are safe even when interrupted: the
1684 // stack pointer will be decremented before adding an element to the stack.
1685 if (instr->IsStore()) {
1686 LoadStoreWriteBack(addr_reg, offset, addrmode);
1688 // For store the address post writeback is used to check access below the
1693 LoadStorePairOp op =
1694 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1696 // 'rt' and 'rt2' can only be aliased for stores.
1697 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1700 // Use _no_log variants to suppress the register trace (LOG_REGS,
1701 // LOG_FP_REGS). We will print a more detailed log.
1703 DCHECK(access_size == kWRegSize);
1704 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1705 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
1709 DCHECK(access_size == kSRegSize);
1710 set_sreg_no_log(rt, MemoryRead<float>(address));
1711 set_sreg_no_log(rt2, MemoryRead<float>(address2));
1715 DCHECK(access_size == kXRegSize);
1716 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1717 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
1721 DCHECK(access_size == kDRegSize);
1722 set_dreg_no_log(rt, MemoryRead<double>(address));
1723 set_dreg_no_log(rt2, MemoryRead<double>(address2));
1727 DCHECK(access_size == kWRegSize);
1728 set_xreg_no_log(rt, MemoryRead<int32_t>(address));
1729 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
1733 DCHECK(access_size == kWRegSize);
1734 MemoryWrite<uint32_t>(address, wreg(rt));
1735 MemoryWrite<uint32_t>(address2, wreg(rt2));
1739 DCHECK(access_size == kSRegSize);
1740 MemoryWrite<float>(address, sreg(rt));
1741 MemoryWrite<float>(address2, sreg(rt2));
1745 DCHECK(access_size == kXRegSize);
1746 MemoryWrite<uint64_t>(address, xreg(rt));
1747 MemoryWrite<uint64_t>(address2, xreg(rt2));
1751 DCHECK(access_size == kDRegSize);
1752 MemoryWrite<double>(address, dreg(rt));
1753 MemoryWrite<double>(address2, dreg(rt2));
1756 default: UNREACHABLE();
1759 // Print a detailed trace (including the memory address) instead of the basic
1760 // register:value trace generated by set_*reg().
1761 if (instr->IsLoad()) {
1762 if ((op == LDP_s) || (op == LDP_d)) {
1763 LogReadFP(address, access_size, rt);
1764 LogReadFP(address2, access_size, rt2);
1766 LogRead(address, access_size, rt);
1767 LogRead(address2, access_size, rt2);
1770 if ((op == STP_s) || (op == STP_d)) {
1771 LogWriteFP(address, access_size, rt);
1772 LogWriteFP(address2, access_size, rt2);
1774 LogWrite(address, access_size, rt);
1775 LogWrite(address2, access_size, rt2);
1779 // Handle the writeback for loads after the load to ensure safe pop
1780 // operation even when interrupted in the middle of it. The stack pointer
1781 // is only updated after the load so pop(fp) will never break the invariant
1782 // sp <= fp expected while walking the stack in the sampler.
1783 if (instr->IsLoad()) {
1784 // For loads the address pre writeback is used to check access below the
1788 LoadStoreWriteBack(addr_reg, offset, addrmode);
1791 // Accesses below the stack pointer (but above the platform stack limit) are
1792 // not allowed in the ABI.
1793 CheckMemoryAccess(address, stack);
1797 void Simulator::VisitLoadLiteral(Instruction* instr) {
1798 uintptr_t address = instr->LiteralAddress();
1799 unsigned rt = instr->Rt();
1801 switch (instr->Mask(LoadLiteralMask)) {
1802 // Use _no_log variants to suppress the register trace (LOG_REGS,
1803 // LOG_FP_REGS), then print a more detailed log.
1805 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1806 LogRead(address, kWRegSize, rt);
1809 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1810 LogRead(address, kXRegSize, rt);
1813 set_sreg_no_log(rt, MemoryRead<float>(address));
1814 LogReadFP(address, kSRegSize, rt);
1817 set_dreg_no_log(rt, MemoryRead<double>(address));
1818 LogReadFP(address, kDRegSize, rt);
1820 default: UNREACHABLE();
1825 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset,
1826 AddrMode addrmode) {
1827 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1828 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1829 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
1830 // When the base register is SP the stack pointer is required to be
1831 // quadword aligned prior to the address calculation and write-backs.
1832 // Misalignment will cause a stack alignment fault.
1833 FATAL("ALIGNMENT EXCEPTION");
1836 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1844 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
1846 AddrMode addrmode) {
1847 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1848 DCHECK(offset != 0);
1849 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1850 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
1855 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
1856 if ((address >= stack_limit_) && (address < stack)) {
1857 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
1858 fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n",
1859 static_cast<uint64_t>(stack));
1860 fprintf(stream_, " access was here: 0x%016" PRIx64 "\n",
1861 static_cast<uint64_t>(address));
1862 fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n",
1863 static_cast<uint64_t>(stack_limit_));
1864 fprintf(stream_, "\n");
1865 FATAL("ACCESS BELOW STACK POINTER");
1870 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
1871 MoveWideImmediateOp mov_op =
1872 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1873 int64_t new_xn_val = 0;
1875 bool is_64_bits = instr->SixtyFourBits() == 1;
1876 // Shift is limited for W operations.
1877 DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2));
1879 // Get the shifted immediate.
1880 int64_t shift = instr->ShiftMoveWide() * 16;
1881 int64_t shifted_imm16 = instr->ImmMoveWide() << shift;
1883 // Compute the new value.
1887 new_xn_val = ~shifted_imm16;
1888 if (!is_64_bits) new_xn_val &= kWRegMask;
1893 unsigned reg_code = instr->Rd();
1894 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1896 new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
1901 new_xn_val = shifted_imm16;
1908 // Update the destination register.
1909 set_xreg(instr->Rd(), new_xn_val);
1913 void Simulator::VisitConditionalSelect(Instruction* instr) {
1914 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1915 uint64_t new_val = xreg(instr->Rm());
1916 switch (instr->Mask(ConditionalSelectMask)) {
1917 case CSEL_w: set_wreg(instr->Rd(), new_val); break;
1918 case CSEL_x: set_xreg(instr->Rd(), new_val); break;
1919 case CSINC_w: set_wreg(instr->Rd(), new_val + 1); break;
1920 case CSINC_x: set_xreg(instr->Rd(), new_val + 1); break;
1921 case CSINV_w: set_wreg(instr->Rd(), ~new_val); break;
1922 case CSINV_x: set_xreg(instr->Rd(), ~new_val); break;
1923 case CSNEG_w: set_wreg(instr->Rd(), -new_val); break;
1924 case CSNEG_x: set_xreg(instr->Rd(), -new_val); break;
1925 default: UNIMPLEMENTED();
1928 if (instr->SixtyFourBits()) {
1929 set_xreg(instr->Rd(), xreg(instr->Rn()));
1931 set_wreg(instr->Rd(), wreg(instr->Rn()));
1937 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
1938 unsigned dst = instr->Rd();
1939 unsigned src = instr->Rn();
1941 switch (instr->Mask(DataProcessing1SourceMask)) {
1942 case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSizeInBits)); break;
1943 case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSizeInBits)); break;
1944 case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break;
1945 case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break;
1946 case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break;
1947 case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break;
1948 case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break;
1949 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits));
1951 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits));
1954 set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits));
1958 set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits));
1961 default: UNIMPLEMENTED();
1966 uint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) {
1967 DCHECK((num_bits == kWRegSizeInBits) || (num_bits == kXRegSizeInBits));
1968 uint64_t result = 0;
1969 for (unsigned i = 0; i < num_bits; i++) {
1970 result = (result << 1) | (value & 1);
1977 uint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) {
1978 // Split the 64-bit value into an 8-bit array, where b[0] is the least
1979 // significant byte, and b[7] is the most significant.
1981 uint64_t mask = 0xff00000000000000UL;
1982 for (int i = 7; i >= 0; i--) {
1983 bytes[i] = (value & mask) >> (i * 8);
1987 // Permutation tables for REV instructions.
1988 // permute_table[Reverse16] is used by REV16_x, REV16_w
1989 // permute_table[Reverse32] is used by REV32_x, REV_w
1990 // permute_table[Reverse64] is used by REV_x
1991 DCHECK((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2));
1992 static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1},
1993 {4, 5, 6, 7, 0, 1, 2, 3},
1994 {0, 1, 2, 3, 4, 5, 6, 7} };
1995 uint64_t result = 0;
1996 for (int i = 0; i < 8; i++) {
1998 result |= bytes[permute_table[mode][i]];
2004 template <typename T>
2005 void Simulator::DataProcessing2Source(Instruction* instr) {
2006 Shift shift_op = NO_SHIFT;
2008 switch (instr->Mask(DataProcessing2SourceMask)) {
2011 T rn = reg<T>(instr->Rn());
2012 T rm = reg<T>(instr->Rm());
2013 if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) {
2014 result = std::numeric_limits<T>::min();
2015 } else if (rm == 0) {
2016 // Division by zero can be trapped, but not on A-class processors.
2025 typedef typename make_unsigned<T>::type unsignedT;
2026 unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn()));
2027 unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm()));
2029 // Division by zero can be trapped, but not on A-class processors.
2037 case LSLV_x: shift_op = LSL; break;
2039 case LSRV_x: shift_op = LSR; break;
2041 case ASRV_x: shift_op = ASR; break;
2043 case RORV_x: shift_op = ROR; break;
2044 default: UNIMPLEMENTED();
2047 if (shift_op != NO_SHIFT) {
2048 // Shift distance encoded in the least-significant five/six bits of the
2050 unsigned shift = wreg(instr->Rm());
2051 if (sizeof(T) == kWRegSize) {
2052 shift &= kShiftAmountWRegMask;
2054 shift &= kShiftAmountXRegMask;
2056 result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift);
2058 set_reg<T>(instr->Rd(), result);
2062 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
2063 if (instr->SixtyFourBits()) {
2064 DataProcessing2Source<int64_t>(instr);
2066 DataProcessing2Source<int32_t>(instr);
2071 // The algorithm used is described in section 8.2 of
2072 // Hacker's Delight, by Henry S. Warren, Jr.
2073 // It assumes that a right shift on a signed integer is an arithmetic shift.
2074 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
2075 uint64_t u0, v0, w0;
2076 int64_t u1, v1, w1, w2, t;
2078 u0 = u & 0xffffffffL;
2080 v0 = v & 0xffffffffL;
2084 t = u1 * v0 + (w0 >> 32);
2085 w1 = t & 0xffffffffL;
2089 return u1 * v1 + w2 + (w1 >> 32);
2093 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
2095 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2096 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
2097 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
2098 int64_t rn_s32 = reg<int32_t>(instr->Rn());
2099 int64_t rm_s32 = reg<int32_t>(instr->Rm());
2100 switch (instr->Mask(DataProcessing3SourceMask)) {
2103 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
2107 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
2109 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
2110 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
2111 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
2112 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
2114 DCHECK(instr->Ra() == kZeroRegCode);
2115 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
2117 default: UNIMPLEMENTED();
2120 if (instr->SixtyFourBits()) {
2121 set_xreg(instr->Rd(), result);
2123 set_wreg(instr->Rd(), result);
2128 template <typename T>
2129 void Simulator::BitfieldHelper(Instruction* instr) {
2130 typedef typename make_unsigned<T>::type unsignedT;
2131 T reg_size = sizeof(T) * 8;
2132 T R = instr->ImmR();
2133 T S = instr->ImmS();
2137 mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1
2138 : static_cast<T>(-1);
2140 mask = ((1L << (S + 1)) - 1);
2141 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
2145 // inzero indicates if the extracted bitfield is inserted into the
2146 // destination register value or in zero.
2147 // If extend is true, extend the sign of the extracted bitfield.
2148 bool inzero = false;
2149 bool extend = false;
2150 switch (instr->Mask(BitfieldMask)) {
2167 T dst = inzero ? 0 : reg<T>(instr->Rd());
2168 T src = reg<T>(instr->Rn());
2169 // Rotate source bitfield into place.
2170 T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R));
2171 // Determine the sign extension.
2172 T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1;
2173 T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0)
2176 // Merge sign extension, dest/zero and bitfield.
2177 result = signbits | (result & mask) | (dst & ~mask);
2179 set_reg<T>(instr->Rd(), result);
2183 void Simulator::VisitBitfield(Instruction* instr) {
2184 if (instr->SixtyFourBits()) {
2185 BitfieldHelper<int64_t>(instr);
2187 BitfieldHelper<int32_t>(instr);
2192 void Simulator::VisitExtract(Instruction* instr) {
2193 if (instr->SixtyFourBits()) {
2194 Extract<uint64_t>(instr);
2196 Extract<uint32_t>(instr);
2201 void Simulator::VisitFPImmediate(Instruction* instr) {
2202 AssertSupportedFPCR();
2204 unsigned dest = instr->Rd();
2205 switch (instr->Mask(FPImmediateMask)) {
2206 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
2207 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
2208 default: UNREACHABLE();
2213 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
2214 AssertSupportedFPCR();
2216 unsigned dst = instr->Rd();
2217 unsigned src = instr->Rn();
2219 FPRounding round = fpcr().RMode();
2221 switch (instr->Mask(FPIntegerConvertMask)) {
2222 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
2223 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
2224 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
2225 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
2226 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
2227 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
2228 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
2229 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
2231 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
2234 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
2237 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
2240 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
2243 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
2246 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
2249 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
2252 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
2254 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
2255 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
2256 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
2257 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
2258 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
2259 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
2260 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
2261 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
2262 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
2263 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
2264 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
2265 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
2266 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
2267 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
2268 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
2269 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
2270 case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
2271 case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
2272 case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
2273 case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
2275 // A 32-bit input can be handled in the same way as a 64-bit input, since
2276 // the sign- or zero-extension will not affect the conversion.
2277 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
2278 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
2279 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
2281 set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2284 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
2285 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
2286 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
2288 set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2292 default: UNREACHABLE();
2297 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2298 AssertSupportedFPCR();
2300 unsigned dst = instr->Rd();
2301 unsigned src = instr->Rn();
2302 int fbits = 64 - instr->FPScale();
2304 FPRounding round = fpcr().RMode();
2306 switch (instr->Mask(FPFixedPointConvertMask)) {
2307 // A 32-bit input can be handled in the same way as a 64-bit input, since
2308 // the sign- or zero-extension will not affect the conversion.
2309 case SCVTF_dx_fixed:
2310 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2312 case SCVTF_dw_fixed:
2313 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2315 case UCVTF_dx_fixed:
2316 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2318 case UCVTF_dw_fixed: {
2320 UFixedToDouble(reg<uint32_t>(src), fbits, round));
2323 case SCVTF_sx_fixed:
2324 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2326 case SCVTF_sw_fixed:
2327 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2329 case UCVTF_sx_fixed:
2330 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2332 case UCVTF_sw_fixed: {
2334 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2337 default: UNREACHABLE();
2342 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
2343 value = FPRoundInt(value, rmode);
2344 if (value >= kWMaxInt) {
2346 } else if (value < kWMinInt) {
2349 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
2353 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
2354 value = FPRoundInt(value, rmode);
2355 if (value >= kXMaxInt) {
2357 } else if (value < kXMinInt) {
2360 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
2364 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
2365 value = FPRoundInt(value, rmode);
2366 if (value >= kWMaxUInt) {
2368 } else if (value < 0.0) {
2371 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
2375 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
2376 value = FPRoundInt(value, rmode);
2377 if (value >= kXMaxUInt) {
2379 } else if (value < 0.0) {
2382 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
2386 void Simulator::VisitFPCompare(Instruction* instr) {
2387 AssertSupportedFPCR();
2389 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2391 double fn_val = fpreg(reg_size, instr->Rn());
2393 switch (instr->Mask(FPCompareMask)) {
2395 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
2397 case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
2398 default: UNIMPLEMENTED();
2403 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2404 AssertSupportedFPCR();
2406 switch (instr->Mask(FPConditionalCompareMask)) {
2409 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2410 // If the condition passes, set the status flags to the result of
2411 // comparing the operands.
2412 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2414 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
2416 // If the condition fails, set the status flags to the nzcv immediate.
2417 nzcv().SetFlags(instr->Nzcv());
2418 LogSystemRegister(NZCV);
2422 default: UNIMPLEMENTED();
2427 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2428 AssertSupportedFPCR();
2431 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2432 selected = instr->Rn();
2434 selected = instr->Rm();
2437 switch (instr->Mask(FPConditionalSelectMask)) {
2438 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2439 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2440 default: UNIMPLEMENTED();
2445 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2446 AssertSupportedFPCR();
2448 unsigned fd = instr->Rd();
2449 unsigned fn = instr->Rn();
2451 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2452 case FMOV_s: set_sreg(fd, sreg(fn)); break;
2453 case FMOV_d: set_dreg(fd, dreg(fn)); break;
2454 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break;
2455 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break;
2456 case FNEG_s: set_sreg(fd, -sreg(fn)); break;
2457 case FNEG_d: set_dreg(fd, -dreg(fn)); break;
2458 case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break;
2459 case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break;
2460 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break;
2461 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break;
2463 set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break;
2465 set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break;
2466 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
2467 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
2468 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
2469 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
2470 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
2471 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
2472 default: UNIMPLEMENTED();
2477 // Assemble the specified IEEE-754 components into the target type and apply
2478 // appropriate rounding.
2479 // sign: 0 = positive, 1 = negative
2480 // exponent: Unbiased IEEE-754 exponent.
2481 // mantissa: The mantissa of the input. The top bit (which is not encoded for
2482 // normal IEEE-754 values) must not be omitted. This bit has the
2483 // value 'pow(2, exponent)'.
2485 // The input value is assumed to be a normalized value. That is, the input may
2486 // not be infinity or NaN. If the source value is subnormal, it must be
2487 // normalized before calling this function such that the highest set bit in the
2488 // mantissa has the value 'pow(2, exponent)'.
2490 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
2491 // calling a templated FPRound.
2492 template <class T, int ebits, int mbits>
2493 static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
2494 FPRounding round_mode) {
2495 DCHECK((sign == 0) || (sign == 1));
2497 // Only the FPTieEven rounding mode is implemented.
2498 DCHECK(round_mode == FPTieEven);
2501 // Rounding can promote subnormals to normals, and normals to infinities. For
2502 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
2503 // encodable as a float, but rounding based on the low-order mantissa bits
2504 // could make it overflow. With ties-to-even rounding, this value would become
2507 // ---- Rounding Method ----
2509 // The exponent is irrelevant in the rounding operation, so we treat the
2510 // lowest-order bit that will fit into the result ('onebit') as having
2511 // the value '1'. Similarly, the highest-order bit that won't fit into
2512 // the result ('halfbit') has the value '0.5'. The 'point' sits between
2513 // 'onebit' and 'halfbit':
2515 // These bits fit into the result.
2516 // |---------------------|
2517 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2523 // For subnormal outputs, the range of representable bits is smaller and
2524 // the position of onebit and halfbit depends on the exponent of the
2525 // input, but the method is otherwise similar.
2529 // | halfbit(frac) halfbit(adjusted)
2532 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
2533 // 0b00.0... -> 0b00.0... -> 0b00
2534 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
2535 // 0b00.1... -> 0b00.1... -> 0b01
2536 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
2537 // 0b01.0... -> 0b01.0... -> 0b01
2538 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
2539 // 0b01.1... -> 0b01.1... -> 0b10
2540 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
2541 // 0b10.0... -> 0b10.0... -> 0b10
2542 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
2543 // 0b10.1... -> 0b10.1... -> 0b11
2544 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
2548 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
2550 // mantissa = (mantissa >> shift) + halfbit(adjusted);
2552 static const int mantissa_offset = 0;
2553 static const int exponent_offset = mantissa_offset + mbits;
2554 static const int sign_offset = exponent_offset + ebits;
2555 STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1));
2557 // Bail out early for zero inputs.
2558 if (mantissa == 0) {
2559 return sign << sign_offset;
2562 // If all bits in the exponent are set, the value is infinite or NaN.
2563 // This is true for all binary IEEE-754 formats.
2564 static const int infinite_exponent = (1 << ebits) - 1;
2565 static const int max_normal_exponent = infinite_exponent - 1;
2567 // Apply the exponent bias to encode it for the result. Doing this early makes
2568 // it easy to detect values that will be infinite or subnormal.
2569 exponent += max_normal_exponent >> 1;
2571 if (exponent > max_normal_exponent) {
2572 // Overflow: The input is too large for the result type to represent. The
2573 // FPTieEven rounding mode handles overflows using infinities.
2574 exponent = infinite_exponent;
2576 return (sign << sign_offset) |
2577 (exponent << exponent_offset) |
2578 (mantissa << mantissa_offset);
2581 // Calculate the shift required to move the top mantissa bit to the proper
2582 // place in the destination type.
2583 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
2584 int shift = highest_significant_bit - mbits;
2586 if (exponent <= 0) {
2587 // The output will be subnormal (before rounding).
2589 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
2590 // is necessary because the exponent of a subnormal value (encoded as 0) is
2591 // the same as the exponent of the smallest normal value (encoded as 1).
2592 shift += -exponent + 1;
2594 // Handle inputs that would produce a zero output.
2596 // Shifts higher than highest_significant_bit+1 will always produce a zero
2597 // result. A shift of exactly highest_significant_bit+1 might produce a
2598 // non-zero result after rounding.
2599 if (shift > (highest_significant_bit + 1)) {
2600 // The result will always be +/-0.0.
2601 return sign << sign_offset;
2604 // Properly encode the exponent for a subnormal output.
2607 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
2609 mantissa &= ~(1UL << highest_significant_bit);
2613 // We have to shift the mantissa to the right. Some precision is lost, so we
2614 // need to apply rounding.
2615 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
2616 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
2617 uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
2618 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
2620 T result = (sign << sign_offset) |
2621 (exponent << exponent_offset) |
2622 ((mantissa >> shift) << mantissa_offset);
2624 // A very large mantissa can overflow during rounding. If this happens, the
2625 // exponent should be incremented and the mantissa set to 1.0 (encoded as
2626 // 0). Applying halfbit_adjusted after assembling the float has the nice
2627 // side-effect that this case is handled for free.
2629 // This also handles cases where a very large finite value overflows to
2630 // infinity, or where a very large subnormal value overflows to become
2632 return result + halfbit_adjusted;
2634 // We have to shift the mantissa to the left (or not at all). The input
2635 // mantissa is exactly representable in the output mantissa, so apply no
2636 // rounding correction.
2637 return (sign << sign_offset) |
2638 (exponent << exponent_offset) |
2639 ((mantissa << -shift) << mantissa_offset);
2644 // See FPRound for a description of this function.
2645 static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
2646 uint64_t mantissa, FPRounding round_mode) {
2648 FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
2652 return rawbits_to_double(bits);
2656 // See FPRound for a description of this function.
2657 static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
2658 uint64_t mantissa, FPRounding round_mode) {
2660 FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
2664 return rawbits_to_float(bits);
2668 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
2670 return UFixedToDouble(src, fbits, round);
2672 // This works for all negative values, including INT64_MIN.
2673 return -UFixedToDouble(-src, fbits, round);
2678 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
2679 // An input of 0 is a special case because the result is effectively
2680 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2685 // Calculate the exponent. The highest significant bit will have the value
2687 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2688 const int64_t exponent = highest_significant_bit - fbits;
2690 return FPRoundToDouble(0, exponent, src, round);
2694 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
2696 return UFixedToFloat(src, fbits, round);
2698 // This works for all negative values, including INT64_MIN.
2699 return -UFixedToFloat(-src, fbits, round);
2704 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
2705 // An input of 0 is a special case because the result is effectively
2706 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2711 // Calculate the exponent. The highest significant bit will have the value
2713 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2714 const int32_t exponent = highest_significant_bit - fbits;
2716 return FPRoundToFloat(0, exponent, src, round);
2720 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
2721 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
2722 (value == kFP64NegativeInfinity)) {
2724 } else if (std::isnan(value)) {
2725 return FPProcessNaN(value);
2728 double int_result = floor(value);
2729 double error = value - int_result;
2730 switch (round_mode) {
2732 // Take care of correctly handling the range ]-0.5, -0.0], which must
2734 if ((-0.5 < value) && (value < 0.0)) {
2737 } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
2738 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2739 // result is positive, round up.
2745 // Take care of correctly handling the range [-0.5, -0.0], which must
2747 if ((-0.5 <= value) && (value < 0.0)) {
2750 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2751 // result is odd, round up.
2752 } else if ((error > 0.5) ||
2753 ((error == 0.5) && (fmod(int_result, 2) != 0))) {
2759 // If value > 0 then we take floor(value)
2760 // otherwise, ceil(value)
2762 int_result = ceil(value);
2766 case FPNegativeInfinity: {
2767 // We always use floor(value).
2770 default: UNIMPLEMENTED();
2776 double Simulator::FPToDouble(float value) {
2777 switch (std::fpclassify(value)) {
2779 if (fpcr().DN()) return kFP64DefaultNaN;
2781 // Convert NaNs as the processor would:
2782 // - The sign is propagated.
2783 // - The payload (mantissa) is transferred entirely, except that the top
2784 // bit is forced to '1', making the result a quiet NaN. The unused
2785 // (low-order) payload bits are set to 0.
2786 uint32_t raw = float_to_rawbits(value);
2788 uint64_t sign = raw >> 31;
2789 uint64_t exponent = (1 << 11) - 1;
2790 uint64_t payload = unsigned_bitextract_64(21, 0, raw);
2791 payload <<= (52 - 23); // The unused low-order bits should be 0.
2792 payload |= (1L << 51); // Force a quiet NaN.
2794 return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
2801 // All other inputs are preserved in a standard cast, because every value
2802 // representable using an IEEE-754 float is also representable using an
2804 return static_cast<double>(value);
2809 return static_cast<double>(value);
2813 float Simulator::FPToFloat(double value, FPRounding round_mode) {
2814 // Only the FPTieEven rounding mode is implemented.
2815 DCHECK(round_mode == FPTieEven);
2818 switch (std::fpclassify(value)) {
2820 if (fpcr().DN()) return kFP32DefaultNaN;
2822 // Convert NaNs as the processor would:
2823 // - The sign is propagated.
2824 // - The payload (mantissa) is transferred as much as possible, except
2825 // that the top bit is forced to '1', making the result a quiet NaN.
2826 uint64_t raw = double_to_rawbits(value);
2828 uint32_t sign = raw >> 63;
2829 uint32_t exponent = (1 << 8) - 1;
2830 uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw);
2831 payload |= (1 << 22); // Force a quiet NaN.
2833 return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
2838 // In a C++ cast, any value representable in the target type will be
2839 // unchanged. This is always the case for +/-0.0 and infinities.
2840 return static_cast<float>(value);
2844 case FP_SUBNORMAL: {
2845 // Convert double-to-float as the processor would, assuming that FPCR.FZ
2846 // (flush-to-zero) is not set.
2847 uint64_t raw = double_to_rawbits(value);
2848 // Extract the IEEE-754 double components.
2849 uint32_t sign = raw >> 63;
2850 // Extract the exponent and remove the IEEE-754 encoding bias.
2851 int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023;
2852 // Extract the mantissa and add the implicit '1' bit.
2853 uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
2854 if (std::fpclassify(value) == FP_NORMAL) {
2855 mantissa |= (1UL << 52);
2857 return FPRoundToFloat(sign, exponent, mantissa, round_mode);
2866 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2867 AssertSupportedFPCR();
2869 unsigned fd = instr->Rd();
2870 unsigned fn = instr->Rn();
2871 unsigned fm = instr->Rm();
2873 // Fmaxnm and Fminnm have special NaN handling.
2874 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2875 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return;
2876 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return;
2877 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return;
2878 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return;
2880 break; // Fall through.
2883 if (FPProcessNaNs(instr)) return;
2885 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2886 case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break;
2887 case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break;
2888 case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break;
2889 case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break;
2890 case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break;
2891 case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break;
2892 case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break;
2893 case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break;
2894 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
2895 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
2896 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
2897 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
2902 // These were handled before the standard FPProcessNaNs() stage.
2904 default: UNIMPLEMENTED();
2909 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2910 AssertSupportedFPCR();
2912 unsigned fd = instr->Rd();
2913 unsigned fn = instr->Rn();
2914 unsigned fm = instr->Rm();
2915 unsigned fa = instr->Ra();
2917 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2918 // fd = fa +/- (fn * fm)
2919 case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
2920 case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
2921 case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
2922 case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
2923 // Negated variants of the above.
2925 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2928 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2931 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2934 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2936 default: UNIMPLEMENTED();
2941 template <typename T>
2942 T Simulator::FPAdd(T op1, T op2) {
2943 // NaNs should be handled elsewhere.
2944 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2946 if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
2947 // inf + -inf returns the default NaN.
2948 return FPDefaultNaN<T>();
2950 // Other cases should be handled by standard arithmetic.
2956 template <typename T>
2957 T Simulator::FPDiv(T op1, T op2) {
2958 // NaNs should be handled elsewhere.
2959 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2961 if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
2962 // inf / inf and 0.0 / 0.0 return the default NaN.
2963 return FPDefaultNaN<T>();
2965 // Other cases should be handled by standard arithmetic.
2971 template <typename T>
2972 T Simulator::FPMax(T a, T b) {
2973 // NaNs should be handled elsewhere.
2974 DCHECK(!std::isnan(a) && !std::isnan(b));
2976 if ((a == 0.0) && (b == 0.0) &&
2977 (copysign(1.0, a) != copysign(1.0, b))) {
2978 // a and b are zero, and the sign differs: return +0.0.
2981 return (a > b) ? a : b;
2986 template <typename T>
2987 T Simulator::FPMaxNM(T a, T b) {
2988 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2989 a = kFP64NegativeInfinity;
2990 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2991 b = kFP64NegativeInfinity;
2994 T result = FPProcessNaNs(a, b);
2995 return std::isnan(result) ? result : FPMax(a, b);
2998 template <typename T>
2999 T Simulator::FPMin(T a, T b) {
3000 // NaNs should be handled elsewhere.
3001 DCHECK(!std::isnan(a) && !std::isnan(b));
3003 if ((a == 0.0) && (b == 0.0) &&
3004 (copysign(1.0, a) != copysign(1.0, b))) {
3005 // a and b are zero, and the sign differs: return -0.0.
3008 return (a < b) ? a : b;
3013 template <typename T>
3014 T Simulator::FPMinNM(T a, T b) {
3015 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3016 a = kFP64PositiveInfinity;
3017 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3018 b = kFP64PositiveInfinity;
3021 T result = FPProcessNaNs(a, b);
3022 return std::isnan(result) ? result : FPMin(a, b);
3026 template <typename T>
3027 T Simulator::FPMul(T op1, T op2) {
3028 // NaNs should be handled elsewhere.
3029 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3031 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
3032 // inf * 0.0 returns the default NaN.
3033 return FPDefaultNaN<T>();
3035 // Other cases should be handled by standard arithmetic.
3041 template<typename T>
3042 T Simulator::FPMulAdd(T a, T op1, T op2) {
3043 T result = FPProcessNaNs3(a, op1, op2);
3045 T sign_a = copysign(1.0, a);
3046 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
3047 bool isinf_prod = std::isinf(op1) || std::isinf(op2);
3048 bool operation_generates_nan =
3049 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0
3050 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
3051 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
3053 if (std::isnan(result)) {
3054 // Generated NaNs override quiet NaNs propagated from a.
3055 if (operation_generates_nan && IsQuietNaN(a)) {
3056 return FPDefaultNaN<T>();
3062 // If the operation would produce a NaN, return the default NaN.
3063 if (operation_generates_nan) {
3064 return FPDefaultNaN<T>();
3067 // Work around broken fma implementations for exact zero results: The sign of
3068 // exact 0.0 results is positive unless both a and op1 * op2 are negative.
3069 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
3070 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
3073 result = FusedMultiplyAdd(op1, op2, a);
3074 DCHECK(!std::isnan(result));
3076 // Work around broken fma implementations for rounded zero results: If a is
3077 // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
3078 if ((a == 0.0) && (result == 0.0)) {
3079 return copysign(0.0, sign_prod);
3086 template <typename T>
3087 T Simulator::FPSqrt(T op) {
3088 if (std::isnan(op)) {
3089 return FPProcessNaN(op);
3090 } else if (op < 0.0) {
3091 return FPDefaultNaN<T>();
3093 return std::sqrt(op);
3098 template <typename T>
3099 T Simulator::FPSub(T op1, T op2) {
3100 // NaNs should be handled elsewhere.
3101 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3103 if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
3104 // inf - inf returns the default NaN.
3105 return FPDefaultNaN<T>();
3107 // Other cases should be handled by standard arithmetic.
3113 template <typename T>
3114 T Simulator::FPProcessNaN(T op) {
3115 DCHECK(std::isnan(op));
3116 return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
3120 template <typename T>
3121 T Simulator::FPProcessNaNs(T op1, T op2) {
3122 if (IsSignallingNaN(op1)) {
3123 return FPProcessNaN(op1);
3124 } else if (IsSignallingNaN(op2)) {
3125 return FPProcessNaN(op2);
3126 } else if (std::isnan(op1)) {
3127 DCHECK(IsQuietNaN(op1));
3128 return FPProcessNaN(op1);
3129 } else if (std::isnan(op2)) {
3130 DCHECK(IsQuietNaN(op2));
3131 return FPProcessNaN(op2);
3138 template <typename T>
3139 T Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
3140 if (IsSignallingNaN(op1)) {
3141 return FPProcessNaN(op1);
3142 } else if (IsSignallingNaN(op2)) {
3143 return FPProcessNaN(op2);
3144 } else if (IsSignallingNaN(op3)) {
3145 return FPProcessNaN(op3);
3146 } else if (std::isnan(op1)) {
3147 DCHECK(IsQuietNaN(op1));
3148 return FPProcessNaN(op1);
3149 } else if (std::isnan(op2)) {
3150 DCHECK(IsQuietNaN(op2));
3151 return FPProcessNaN(op2);
3152 } else if (std::isnan(op3)) {
3153 DCHECK(IsQuietNaN(op3));
3154 return FPProcessNaN(op3);
3161 bool Simulator::FPProcessNaNs(Instruction* instr) {
3162 unsigned fd = instr->Rd();
3163 unsigned fn = instr->Rn();
3164 unsigned fm = instr->Rm();
3167 if (instr->Mask(FP64) == FP64) {
3168 double result = FPProcessNaNs(dreg(fn), dreg(fm));
3169 if (std::isnan(result)) {
3170 set_dreg(fd, result);
3174 float result = FPProcessNaNs(sreg(fn), sreg(fm));
3175 if (std::isnan(result)) {
3176 set_sreg(fd, result);
3185 void Simulator::VisitSystem(Instruction* instr) {
3186 // Some system instructions hijack their Op and Cp fields to represent a
3187 // range of immediates instead of indicating a different instruction. This
3188 // makes the decoding tricky.
3189 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3190 switch (instr->Mask(SystemSysRegMask)) {
3192 switch (instr->ImmSystemRegister()) {
3193 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
3194 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
3195 default: UNIMPLEMENTED();
3200 switch (instr->ImmSystemRegister()) {
3202 nzcv().SetRawValue(xreg(instr->Rt()));
3203 LogSystemRegister(NZCV);
3206 fpcr().SetRawValue(xreg(instr->Rt()));
3207 LogSystemRegister(FPCR);
3209 default: UNIMPLEMENTED();
3214 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3215 DCHECK(instr->Mask(SystemHintMask) == HINT);
3216 switch (instr->ImmHint()) {
3218 default: UNIMPLEMENTED();
3220 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3221 __sync_synchronize();
3228 bool Simulator::GetValue(const char* desc, int64_t* value) {
3229 int regnum = CodeFromName(desc);
3231 unsigned code = regnum;
3232 if (code == kZeroRegCode) {
3233 // Catch the zero register and return 0.
3236 } else if (code == kSPRegInternalCode) {
3237 // Translate the stack pointer code to 31, for Reg31IsStackPointer.
3240 if (desc[0] == 'w') {
3241 *value = wreg(code, Reg31IsStackPointer);
3243 *value = xreg(code, Reg31IsStackPointer);
3246 } else if (strncmp(desc, "0x", 2) == 0) {
3247 return SScanF(desc + 2, "%" SCNx64,
3248 reinterpret_cast<uint64_t*>(value)) == 1;
3250 return SScanF(desc, "%" SCNu64,
3251 reinterpret_cast<uint64_t*>(value)) == 1;
3256 bool Simulator::PrintValue(const char* desc) {
3257 if (strcmp(desc, "csp") == 0) {
3258 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3259 PrintF(stream_, "%s csp:%s 0x%016" PRIx64 "%s\n",
3260 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3262 } else if (strcmp(desc, "wcsp") == 0) {
3263 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3264 PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n",
3265 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3269 int i = CodeFromName(desc);
3270 STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters);
3271 if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false;
3273 if (desc[0] == 'v') {
3274 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3275 clr_fpreg_name, VRegNameForCode(i),
3276 clr_fpreg_value, double_to_rawbits(dreg(i)),
3278 clr_fpreg_name, DRegNameForCode(i),
3279 clr_fpreg_value, dreg(i),
3280 clr_fpreg_name, SRegNameForCode(i),
3281 clr_fpreg_value, sreg(i),
3284 } else if (desc[0] == 'd') {
3285 PrintF(stream_, "%s %s:%s %g%s\n",
3286 clr_fpreg_name, DRegNameForCode(i),
3287 clr_fpreg_value, dreg(i),
3290 } else if (desc[0] == 's') {
3291 PrintF(stream_, "%s %s:%s %g%s\n",
3292 clr_fpreg_name, SRegNameForCode(i),
3293 clr_fpreg_value, sreg(i),
3296 } else if (desc[0] == 'w') {
3297 PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n",
3298 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3301 // X register names have a wide variety of starting characters, but anything
3302 // else will be an X register.
3303 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n",
3304 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
3310 void Simulator::Debug() {
3311 #define COMMAND_SIZE 63
3312 #define ARG_SIZE 255
3315 #define XSTR(a) STR(a)
3317 char cmd[COMMAND_SIZE + 1];
3318 char arg1[ARG_SIZE + 1];
3319 char arg2[ARG_SIZE + 1];
3320 char* argv[3] = { cmd, arg1, arg2 };
3322 // Make sure to have a proper terminating character if reaching the limit.
3323 cmd[COMMAND_SIZE] = 0;
3328 bool cleared_log_disasm_bit = false;
3331 // Disassemble the next instruction to execute before doing anything else.
3332 PrintInstructionsAt(pc_, 1);
3333 // Read the command line.
3334 char* line = ReadLine("sim> ");
3338 // Repeat last command by default.
3339 char* last_input = last_debugger_input();
3340 if (strcmp(line, "\n") == 0 && (last_input != NULL)) {
3344 // Update the latest command ran
3345 set_last_debugger_input(line);
3348 // Use sscanf to parse the individual parts of the command line. At the
3349 // moment no command expects more than two parameters.
3350 int argc = SScanF(line,
3351 "%" XSTR(COMMAND_SIZE) "s "
3352 "%" XSTR(ARG_SIZE) "s "
3353 "%" XSTR(ARG_SIZE) "s",
3356 // stepi / si ------------------------------------------------------------
3357 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
3358 // We are about to execute instructions, after which by default we
3359 // should increment the pc_. If it was set when reaching this debug
3360 // instruction, it has not been cleared because this instruction has not
3361 // completed yet. So clear it manually.
3362 pc_modified_ = false;
3365 ExecuteInstruction();
3367 int64_t number_of_instructions_to_execute = 1;
3368 GetValue(arg1, &number_of_instructions_to_execute);
3370 set_log_parameters(log_parameters() | LOG_DISASM);
3371 while (number_of_instructions_to_execute-- > 0) {
3372 ExecuteInstruction();
3374 set_log_parameters(log_parameters() & ~LOG_DISASM);
3378 // If it was necessary, the pc has already been updated or incremented
3379 // when executing the instruction. So we do not want it to be updated
3380 // again. It will be cleared when exiting.
3381 pc_modified_ = true;
3383 // next / n --------------------------------------------------------------
3384 } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
3385 // Tell the simulator to break after the next executed BL.
3386 break_on_next_ = true;
3390 // continue / cont / c ---------------------------------------------------
3391 } else if ((strcmp(cmd, "continue") == 0) ||
3392 (strcmp(cmd, "cont") == 0) ||
3393 (strcmp(cmd, "c") == 0)) {
3394 // Leave the debugger shell.
3397 // disassemble / disasm / di ---------------------------------------------
3398 } else if (strcmp(cmd, "disassemble") == 0 ||
3399 strcmp(cmd, "disasm") == 0 ||
3400 strcmp(cmd, "di") == 0) {
3401 int64_t n_of_instrs_to_disasm = 10; // default value.
3402 int64_t address = reinterpret_cast<int64_t>(pc_); // default value.
3403 if (argc >= 2) { // disasm <n of instrs>
3404 GetValue(arg1, &n_of_instrs_to_disasm);
3406 if (argc >= 3) { // disasm <n of instrs> <address>
3407 GetValue(arg2, &address);
3411 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3412 n_of_instrs_to_disasm);
3415 // print / p -------------------------------------------------------------
3416 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3418 if (strcmp(arg1, "all") == 0) {
3422 if (!PrintValue(arg1)) {
3423 PrintF("%s unrecognized\n", arg1);
3428 "print <register>\n"
3429 " Print the content of a register. (alias 'p')\n"
3430 " 'print all' will print all registers.\n"
3431 " Use 'printobject' to get more details about the value.\n");
3434 // printobject / po ------------------------------------------------------
3435 } else if ((strcmp(cmd, "printobject") == 0) ||
3436 (strcmp(cmd, "po") == 0)) {
3439 OFStream os(stdout);
3440 if (GetValue(arg1, &value)) {
3441 Object* obj = reinterpret_cast<Object*>(value);
3442 os << arg1 << ": \n";
3447 os << Brief(obj) << "\n";
3450 os << arg1 << " unrecognized\n";
3453 PrintF("printobject <value>\n"
3454 "printobject <register>\n"
3455 " Print details about the value. (alias 'po')\n");
3458 // stack / mem ----------------------------------------------------------
3459 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
3460 int64_t* cur = NULL;
3461 int64_t* end = NULL;
3464 if (strcmp(cmd, "stack") == 0) {
3465 cur = reinterpret_cast<int64_t*>(jssp());
3469 if (!GetValue(arg1, &value)) {
3470 PrintF("%s unrecognized\n", arg1);
3473 cur = reinterpret_cast<int64_t*>(value);
3478 if (argc == next_arg) {
3480 } else if (argc == next_arg + 1) {
3481 if (!GetValue(argv[next_arg], &words)) {
3482 PrintF("%s unrecognized\n", argv[next_arg]);
3483 PrintF("Printing 10 double words by default");
3492 PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64,
3493 reinterpret_cast<uint64_t>(cur), *cur, *cur);
3494 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
3495 int64_t value = *cur;
3496 Heap* current_heap = v8::internal::Isolate::Current()->heap();
3497 if (((value & 1) == 0) || current_heap->Contains(obj)) {
3499 if ((value & kSmiTagMask) == 0) {
3500 STATIC_ASSERT(kSmiValueSize == 32);
3501 int32_t untagged = (value >> kSmiShift) & 0xffffffff;
3502 PrintF("smi %" PRId32, untagged);
3512 // trace / t -------------------------------------------------------------
3513 } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
3514 if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
3515 (LOG_DISASM | LOG_REGS)) {
3516 PrintF("Enabling disassembly and registers tracing\n");
3517 set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
3519 PrintF("Disabling disassembly and registers tracing\n");
3520 set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
3523 // break / b -------------------------------------------------------------
3524 } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
3527 if (GetValue(arg1, &value)) {
3528 SetBreakpoint(reinterpret_cast<Instruction*>(value));
3530 PrintF("%s unrecognized\n", arg1);
3534 PrintF("Use `break <address>` to set or disable a breakpoint\n");
3537 // gdb -------------------------------------------------------------------
3538 } else if (strcmp(cmd, "gdb") == 0) {
3539 PrintF("Relinquishing control to gdb.\n");
3540 base::OS::DebugBreak();
3541 PrintF("Regaining control from gdb.\n");
3543 // sysregs ---------------------------------------------------------------
3544 } else if (strcmp(cmd, "sysregs") == 0) {
3545 PrintSystemRegisters();
3547 // help / h --------------------------------------------------------------
3548 } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3552 " Step <n> instructions.\n"
3554 " Continue execution until a BL instruction is reached.\n"
3555 " At this point a breakpoint is set just after this BL.\n"
3556 " Then execution is resumed. It will probably later hit the\n"
3557 " breakpoint just set.\n"
3558 "continue / cont / c\n"
3559 " Continue execution from here.\n"
3560 "disassemble / disasm / di\n"
3561 " disassemble <n> <address>\n"
3562 " Disassemble <n> instructions from current <address>.\n"
3563 " By default <n> is 20 and <address> is the current pc.\n"
3565 " print <register>\n"
3566 " Print the content of a register.\n"
3567 " 'print all' will print all registers.\n"
3568 " Use 'printobject' to get more details about the value.\n"
3569 "printobject / po\n"
3570 " printobject <value>\n"
3571 " printobject <register>\n"
3572 " Print details about the value.\n"
3574 " stack [<words>]\n"
3575 " Dump stack content, default dump 10 words\n"
3577 " mem <address> [<words>]\n"
3578 " Dump memory content, default dump 10 words\n"
3580 " Toggle disassembly and register tracing\n"
3582 " break : list all breakpoints\n"
3583 " break <address> : set / enable / disable a breakpoint.\n"
3587 " Print all system registers (including NZCV).\n");
3589 PrintF("Unknown command: %s\n", cmd);
3590 PrintF("Use 'help' for more information.\n");
3593 if (cleared_log_disasm_bit == true) {
3594 set_log_parameters(log_parameters_ | LOG_DISASM);
3600 void Simulator::VisitException(Instruction* instr) {
3601 switch (instr->Mask(ExceptionMask)) {
3603 if (instr->ImmException() == kImmExceptionIsDebug) {
3604 // Read the arguments encoded inline in the instruction stream.
3606 uint32_t parameters;
3609 pc_->InstructionAtOffset(kDebugCodeOffset),
3612 pc_->InstructionAtOffset(kDebugParamsOffset),
3613 sizeof(parameters));
3614 char const *message =
3615 reinterpret_cast<char const*>(
3616 pc_->InstructionAtOffset(kDebugMessageOffset));
3618 // Always print something when we hit a debug point that breaks.
3619 // We are going to break, so printing something is not an issue in
3621 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3622 if (message != NULL) {
3624 "# %sDebugger hit %d: %s%s%s\n",
3632 "# %sDebugger hit %d.%s\n",
3640 switch (parameters & kDebuggerTracingDirectivesMask) {
3642 set_log_parameters(log_parameters() | parameters);
3643 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3644 if (parameters & LOG_REGS) { PrintRegisters(); }
3645 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); }
3648 set_log_parameters(log_parameters() & ~parameters);
3650 case TRACE_OVERRIDE:
3651 set_log_parameters(parameters);
3654 // We don't support a one-shot LOG_DISASM.
3655 DCHECK((parameters & LOG_DISASM) == 0);
3656 // Don't print information that is already being traced.
3657 parameters &= ~log_parameters();
3658 // Print the requested information.
3659 if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3660 if (parameters & LOG_REGS) PrintRegisters();
3661 if (parameters & LOG_FP_REGS) PrintFPRegisters();
3664 // The stop parameters are inlined in the code. Skip them:
3665 // - Skip to the end of the message string.
3666 size_t size = kDebugMessageOffset + strlen(message) + 1;
3667 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize));
3668 // - Verify that the unreachable marker is present.
3669 DCHECK(pc_->Mask(ExceptionMask) == HLT);
3670 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable);
3671 // - Skip past the unreachable marker.
3672 set_pc(pc_->following());
3674 // Check if the debugger should break.
3675 if (parameters & BREAK) Debug();
3677 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3678 DoRuntimeCall(instr);
3679 } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3682 } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3683 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3684 reinterpret_cast<void*>(pc_));
3688 base::OS::DebugBreak();
3699 void Simulator::DoPrintf(Instruction* instr) {
3700 DCHECK((instr->Mask(ExceptionMask) == HLT) &&
3701 (instr->ImmException() == kImmExceptionIsPrintf));
3703 // Read the arguments encoded inline in the instruction stream.
3705 uint32_t arg_pattern_list;
3706 STATIC_ASSERT(sizeof(*instr) == 1);
3708 instr + kPrintfArgCountOffset,
3710 memcpy(&arg_pattern_list,
3711 instr + kPrintfArgPatternListOffset,
3712 sizeof(arg_pattern_list));
3714 DCHECK(arg_count <= kPrintfMaxArgCount);
3715 DCHECK((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
3717 // We need to call the host printf function with a set of arguments defined by
3718 // arg_pattern_list. Because we don't know the types and sizes of the
3719 // arguments, this is very difficult to do in a robust and portable way. To
3720 // work around the problem, we pick apart the format string, and print one
3721 // format placeholder at a time.
3723 // Allocate space for the format string. We take a copy, so we can modify it.
3724 // Leave enough space for one extra character per expected argument (plus the
3725 // '\0' termination).
3726 const char * format_base = reg<const char *>(0);
3727 DCHECK(format_base != NULL);
3728 size_t length = strlen(format_base) + 1;
3729 char * const format = new char[length + arg_count];
3731 // A list of chunks, each with exactly one format placeholder.
3732 const char * chunks[kPrintfMaxArgCount];
3734 // Copy the format string and search for format placeholders.
3735 uint32_t placeholder_count = 0;
3736 char * format_scratch = format;
3737 for (size_t i = 0; i < length; i++) {
3738 if (format_base[i] != '%') {
3739 *format_scratch++ = format_base[i];
3741 if (format_base[i + 1] == '%') {
3742 // Ignore explicit "%%" sequences.
3743 *format_scratch++ = format_base[i];
3745 if (placeholder_count == 0) {
3746 // The first chunk is passed to printf using "%s", so we need to
3747 // unescape "%%" sequences in this chunk. (Just skip the next '%'.)
3750 // Otherwise, pass through "%%" unchanged.
3751 *format_scratch++ = format_base[++i];
3754 CHECK(placeholder_count < arg_count);
3755 // Insert '\0' before placeholders, and store their locations.
3756 *format_scratch++ = '\0';
3757 chunks[placeholder_count++] = format_scratch;
3758 *format_scratch++ = format_base[i];
3762 DCHECK(format_scratch <= (format + length + arg_count));
3763 CHECK(placeholder_count == arg_count);
3765 // Finally, call printf with each chunk, passing the appropriate register
3766 // argument. Normally, printf returns the number of bytes transmitted, so we
3767 // can emulate a single printf call by adding the result from each chunk. If
3768 // any call returns a negative (error) value, though, just return that value.
3770 fprintf(stream_, "%s", clr_printf);
3772 // Because '\0' is inserted before each placeholder, the first string in
3773 // 'format' contains no format placeholders and should be printed literally.
3774 int result = fprintf(stream_, "%s", format);
3775 int pcs_r = 1; // Start at x1. x0 holds the format string.
3776 int pcs_f = 0; // Start at d0.
3778 for (uint32_t i = 0; i < placeholder_count; i++) {
3779 int part_result = -1;
3781 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
3782 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
3783 switch (arg_pattern) {
3785 part_result = fprintf(stream_, chunks[i], wreg(pcs_r++));
3788 part_result = fprintf(stream_, chunks[i], xreg(pcs_r++));
3791 part_result = fprintf(stream_, chunks[i], dreg(pcs_f++));
3793 default: UNREACHABLE();
3796 if (part_result < 0) {
3797 // Handle error values.
3798 result = part_result;
3802 result += part_result;
3806 fprintf(stream_, "%s", clr_normal);
3809 CorruptAllCallerSavedCPURegisters();
3812 // Printf returns its result in x0 (just like the C library's printf).
3813 set_xreg(0, result);
3815 // The printf parameters are inlined in the code, so skip them.
3816 set_pc(instr->InstructionAtOffset(kPrintfLength));
3818 // Set LR as if we'd just called a native printf function.
3825 #endif // USE_SIMULATOR
3827 } } // namespace v8::internal
3829 #endif // V8_TARGET_ARCH_ARM64