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.
9 #if V8_TARGET_ARCH_ARM64
11 #include "src/arm64/decoder-arm64-inl.h"
12 #include "src/arm64/simulator-arm64.h"
13 #include "src/assembler.h"
14 #include "src/codegen.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() {
225 // Adjust JS-based stack limit to C-based stack limit.
226 isolate_->stack_guard()->AdjustStackLimitForSimulator();
229 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
230 CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count());
232 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
233 uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters];
235 CPURegList register_list = kCalleeSaved;
236 CPURegList fpregister_list = kCalleeSavedFP;
238 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
239 // x31 is not a caller saved register, so no need to specify if we want
240 // the stack or zero.
241 saved_registers[i] = xreg(register_list.PopLowestIndex().code());
243 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
244 saved_fpregisters[i] =
245 dreg_bits(fpregister_list.PopLowestIndex().code());
247 int64_t original_stack = sp();
249 // Start the simulation!
252 CHECK_EQ(original_stack, sp());
253 // Check that callee-saved registers have been preserved.
254 register_list = kCalleeSaved;
255 fpregister_list = kCalleeSavedFP;
256 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
257 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
259 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) {
260 DCHECK(saved_fpregisters[i] ==
261 dreg_bits(fpregister_list.PopLowestIndex().code()));
264 // Corrupt caller saved register minus the return regiters.
266 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
268 register_list = kCallerSaved;
269 register_list.Remove(x0);
270 register_list.Remove(x1);
272 // In theory d0 to d7 can be used for return values, but V8 only uses d0
274 fpregister_list = kCallerSavedFP;
275 fpregister_list.Remove(d0);
277 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
278 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
284 // The least significant byte of the curruption value holds the corresponding
286 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
287 if (list->type() == CPURegister::kRegister) {
288 while (!list->IsEmpty()) {
289 unsigned code = list->PopLowestIndex().code();
290 set_xreg(code, value | code);
293 DCHECK(list->type() == CPURegister::kFPRegister);
294 while (!list->IsEmpty()) {
295 unsigned code = list->PopLowestIndex().code();
296 set_dreg_bits(code, value | code);
302 void Simulator::CorruptAllCallerSavedCPURegisters() {
303 // Corrupt alters its parameter so copy them first.
304 CPURegList register_list = kCallerSaved;
305 CPURegList fpregister_list = kCallerSavedFP;
307 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
308 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue);
313 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
314 uintptr_t Simulator::PushAddress(uintptr_t address) {
315 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
316 intptr_t new_sp = sp() - 2 * kXRegSize;
317 uintptr_t* alignment_slot =
318 reinterpret_cast<uintptr_t*>(new_sp + kXRegSize);
319 memcpy(alignment_slot, &kSlotsZapValue, kPointerSize);
320 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
321 memcpy(stack_slot, &address, kPointerSize);
327 uintptr_t Simulator::PopAddress() {
328 intptr_t current_sp = sp();
329 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
330 uintptr_t address = *stack_slot;
331 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
332 set_sp(current_sp + 2 * kXRegSize);
337 // Returns the limit of the stack area to enable checking for stack overflows.
338 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
339 // The simulator uses a separate JS stack. If we have exhausted the C stack,
340 // we also drop down the JS limit to reflect the exhaustion on the JS stack.
341 if (GetCurrentStackPosition() < c_limit) {
342 return reinterpret_cast<uintptr_t>(get_sp());
345 // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
346 // to prevent overrunning the stack when pushing values.
347 return stack_limit_ + 1024;
351 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
352 Isolate* isolate, FILE* stream)
354 last_debugger_input_(NULL),
355 log_parameters_(NO_PARAM),
357 // Setup the decoder.
358 decoder_->AppendVisitor(this);
362 if (FLAG_trace_sim) {
363 decoder_->InsertVisitorBefore(print_disasm_, this);
364 log_parameters_ = LOG_ALL;
367 if (FLAG_log_instruction_stats) {
368 instrument_ = new Instrument(FLAG_log_instruction_file,
369 FLAG_log_instruction_period);
370 decoder_->AppendVisitor(instrument_);
375 Simulator::Simulator()
377 last_debugger_input_(NULL),
378 log_parameters_(NO_PARAM),
381 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats);
385 void Simulator::Init(FILE* stream) {
388 // Allocate and setup the simulator stack.
389 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
390 stack_ = reinterpret_cast<uintptr_t>(new byte[stack_size_]);
391 stack_limit_ = stack_ + stack_protection_size_;
392 uintptr_t tos = stack_ + stack_size_ - stack_protection_size_;
393 // The stack pointer must be 16-byte aligned.
394 set_sp(tos & ~0xfUL);
397 print_disasm_ = new PrintDisassembler(stream_);
399 // The debugger needs to disassemble code without the simulator executing an
400 // instruction, so we create a dedicated decoder.
401 disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>();
402 disassembler_decoder_->AppendVisitor(print_disasm_);
406 void Simulator::ResetState() {
407 // Reset the system registers.
408 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
409 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
411 // Reset registers to 0.
413 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
414 set_xreg(i, 0xbadbeef);
416 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
417 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
418 set_dreg_bits(i, 0x7ff000007f800001UL);
420 // Returning to address 0 exits the Simulator.
421 set_lr(kEndOfSimAddress);
423 // Reset debug helpers.
424 breakpoints_.empty();
425 break_on_next_ = false;
429 Simulator::~Simulator() {
430 delete[] reinterpret_cast<byte*>(stack_);
431 if (FLAG_log_instruction_stats) {
434 delete disassembler_decoder_;
435 delete print_disasm_;
436 DeleteArray(last_debugger_input_);
441 void Simulator::Run() {
442 pc_modified_ = false;
443 while (pc_ != kEndOfSimAddress) {
444 ExecuteInstruction();
449 void Simulator::RunFrom(Instruction* start) {
455 // When the generated code calls an external reference we need to catch that in
456 // the simulator. The external reference will be a function compiled for the
457 // host architecture. We need to call that function instead of trying to
458 // execute it with the simulator. We do that by redirecting the external
459 // reference to a svc (Supervisor Call) instruction that is handled by
460 // the simulator. We write the original destination of the jump just at a known
461 // offset from the svc instruction so the simulator knows what to call.
464 Redirection(void* external_function, ExternalReference::Type type)
465 : external_function_(external_function),
468 redirect_call_.SetInstructionBits(
469 HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall));
470 Isolate* isolate = Isolate::Current();
471 next_ = isolate->simulator_redirection();
472 // TODO(all): Simulator flush I cache
473 isolate->set_simulator_redirection(this);
476 void* address_of_redirect_call() {
477 return reinterpret_cast<void*>(&redirect_call_);
480 template <typename T>
481 T external_function() { return reinterpret_cast<T>(external_function_); }
483 ExternalReference::Type type() { return type_; }
485 static Redirection* Get(void* external_function,
486 ExternalReference::Type type) {
487 Isolate* isolate = Isolate::Current();
488 Redirection* current = isolate->simulator_redirection();
489 for (; current != NULL; current = current->next_) {
490 if (current->external_function_ == external_function) {
491 DCHECK_EQ(current->type(), type);
495 return new Redirection(external_function, type);
498 static Redirection* FromHltInstruction(Instruction* redirect_call) {
499 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call);
500 char* addr_of_redirection =
501 addr_of_hlt - offsetof(Redirection, redirect_call_);
502 return reinterpret_cast<Redirection*>(addr_of_redirection);
505 static void* ReverseRedirection(int64_t reg) {
506 Redirection* redirection =
507 FromHltInstruction(reinterpret_cast<Instruction*>(reg));
508 return redirection->external_function<void*>();
511 static void DeleteChain(Redirection* redirection) {
512 while (redirection != nullptr) {
513 Redirection* next = redirection->next_;
520 void* external_function_;
521 Instruction redirect_call_;
522 ExternalReference::Type type_;
528 void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
529 Redirection::DeleteChain(first);
533 // Calls into the V8 runtime are based on this very simple interface.
534 // Note: To be able to return two values from some calls the code in runtime.cc
535 // uses the ObjectPair structure.
536 // The simulator assumes all runtime calls return two 64-bits values. If they
537 // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
544 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
553 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
554 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
555 typedef double (*SimulatorRuntimeFPCall)(double arg1);
556 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
558 // This signature supports direct call in to API function native callback
559 // (refer to InvocationCallback in v8.h).
560 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
561 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
563 // This signature supports direct call to accessor getter callback.
564 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
565 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
568 void Simulator::DoRuntimeCall(Instruction* instr) {
569 Redirection* redirection = Redirection::FromHltInstruction(instr);
571 // The called C code might itself call simulated code, so any
572 // caller-saved registers (including lr) could still be clobbered by a
574 Instruction* return_address = lr();
576 int64_t external = redirection->external_function<int64_t>();
578 TraceSim("Call to host function at %p\n",
579 redirection->external_function<void*>());
581 // SP must be 16-byte-aligned at the call interface.
582 bool stack_alignment_exception = ((sp() & 0xf) != 0);
583 if (stack_alignment_exception) {
584 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
585 FATAL("ALIGNMENT EXCEPTION");
588 switch (redirection->type()) {
590 TraceSim("Type: Unknown.\n");
594 case ExternalReference::BUILTIN_CALL: {
595 // Object* f(v8::internal::Arguments).
596 TraceSim("Type: BUILTIN_CALL\n");
597 SimulatorRuntimeCall target =
598 reinterpret_cast<SimulatorRuntimeCall>(external);
600 // We don't know how many arguments are being passed, but we can
601 // pass 8 without touching the stack. They will be ignored by the
602 // host function if they aren't used.
603 TraceSim("Arguments: "
604 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
605 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
606 "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
607 "0x%016" PRIx64 ", 0x%016" PRIx64,
608 xreg(0), xreg(1), xreg(2), xreg(3),
609 xreg(4), xreg(5), xreg(6), xreg(7));
610 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
611 xreg(4), xreg(5), xreg(6), xreg(7));
612 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n",
613 result.res0, result.res1);
615 CorruptAllCallerSavedCPURegisters();
617 set_xreg(0, result.res0);
618 set_xreg(1, result.res1);
622 case ExternalReference::DIRECT_API_CALL: {
623 // void f(v8::FunctionCallbackInfo&)
624 TraceSim("Type: DIRECT_API_CALL\n");
625 SimulatorRuntimeDirectApiCall target =
626 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
627 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
629 TraceSim("No return value.");
631 CorruptAllCallerSavedCPURegisters();
636 case ExternalReference::BUILTIN_COMPARE_CALL: {
637 // int f(double, double)
638 TraceSim("Type: BUILTIN_COMPARE_CALL\n");
639 SimulatorRuntimeCompareCall target =
640 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
641 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
642 int64_t result = target(dreg(0), dreg(1));
643 TraceSim("Returned: %" PRId64 "\n", result);
645 CorruptAllCallerSavedCPURegisters();
651 case ExternalReference::BUILTIN_FP_CALL: {
653 TraceSim("Type: BUILTIN_FP_CALL\n");
654 SimulatorRuntimeFPCall target =
655 reinterpret_cast<SimulatorRuntimeFPCall>(external);
656 TraceSim("Argument: %f\n", dreg(0));
657 double result = target(dreg(0));
658 TraceSim("Returned: %f\n", result);
660 CorruptAllCallerSavedCPURegisters();
666 case ExternalReference::BUILTIN_FP_FP_CALL: {
667 // double f(double, double)
668 TraceSim("Type: BUILTIN_FP_FP_CALL\n");
669 SimulatorRuntimeFPFPCall target =
670 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
671 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
672 double result = target(dreg(0), dreg(1));
673 TraceSim("Returned: %f\n", result);
675 CorruptAllCallerSavedCPURegisters();
681 case ExternalReference::BUILTIN_FP_INT_CALL: {
682 // double f(double, int)
683 TraceSim("Type: BUILTIN_FP_INT_CALL\n");
684 SimulatorRuntimeFPIntCall target =
685 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
686 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
687 double result = target(dreg(0), wreg(0));
688 TraceSim("Returned: %f\n", result);
690 CorruptAllCallerSavedCPURegisters();
696 case ExternalReference::DIRECT_GETTER_CALL: {
697 // void f(Local<String> property, PropertyCallbackInfo& info)
698 TraceSim("Type: DIRECT_GETTER_CALL\n");
699 SimulatorRuntimeDirectGetterCall target =
700 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
701 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
703 target(xreg(0), xreg(1));
704 TraceSim("No return value.");
706 CorruptAllCallerSavedCPURegisters();
711 case ExternalReference::PROFILING_API_CALL: {
712 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
713 TraceSim("Type: PROFILING_API_CALL\n");
714 SimulatorRuntimeProfilingApiCall target =
715 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
716 void* arg1 = Redirection::ReverseRedirection(xreg(1));
717 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
718 target(xreg(0), arg1);
719 TraceSim("No return value.");
721 CorruptAllCallerSavedCPURegisters();
726 case ExternalReference::PROFILING_GETTER_CALL: {
727 // void f(Local<String> property, PropertyCallbackInfo& info,
728 // AccessorNameGetterCallback callback)
729 TraceSim("Type: PROFILING_GETTER_CALL\n");
730 SimulatorRuntimeProfilingGetterCall target =
731 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
733 void* arg2 = Redirection::ReverseRedirection(xreg(2));
734 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
735 xreg(0), xreg(1), arg2);
736 target(xreg(0), xreg(1), arg2);
737 TraceSim("No return value.");
739 CorruptAllCallerSavedCPURegisters();
745 set_lr(return_address);
746 set_pc(return_address);
750 void* Simulator::RedirectExternalReference(void* external_function,
751 ExternalReference::Type type) {
752 Redirection* redirection = Redirection::Get(external_function, type);
753 return redirection->address_of_redirect_call();
757 const char* Simulator::xreg_names[] = {
758 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
759 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
760 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23",
761 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"};
763 const char* Simulator::wreg_names[] = {
764 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
765 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
766 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
767 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"};
769 const char* Simulator::sreg_names[] = {
770 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
771 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
772 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
773 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
775 const char* Simulator::dreg_names[] = {
776 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
777 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
778 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
779 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
781 const char* Simulator::vreg_names[] = {
782 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
783 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
784 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
785 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
788 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
789 STATIC_ASSERT(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1));
790 DCHECK(code < kNumberOfRegisters);
791 // The modulo operator has no effect here, but it silences a broken GCC
792 // warning about out-of-bounds array accesses.
793 code %= kNumberOfRegisters;
795 // If the code represents the stack pointer, index the name after zr.
796 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
797 code = kZeroRegCode + 1;
799 return wreg_names[code];
803 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
804 STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1));
805 DCHECK(code < kNumberOfRegisters);
806 code %= kNumberOfRegisters;
808 // If the code represents the stack pointer, index the name after zr.
809 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
810 code = kZeroRegCode + 1;
812 return xreg_names[code];
816 const char* Simulator::SRegNameForCode(unsigned code) {
817 STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters);
818 DCHECK(code < kNumberOfFPRegisters);
819 return sreg_names[code % kNumberOfFPRegisters];
823 const char* Simulator::DRegNameForCode(unsigned code) {
824 STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters);
825 DCHECK(code < kNumberOfFPRegisters);
826 return dreg_names[code % kNumberOfFPRegisters];
830 const char* Simulator::VRegNameForCode(unsigned code) {
831 STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters);
832 DCHECK(code < kNumberOfFPRegisters);
833 return vreg_names[code % kNumberOfFPRegisters];
837 int Simulator::CodeFromName(const char* name) {
838 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
839 if ((strcmp(xreg_names[i], name) == 0) ||
840 (strcmp(wreg_names[i], name) == 0)) {
844 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
845 if ((strcmp(vreg_names[i], name) == 0) ||
846 (strcmp(dreg_names[i], name) == 0) ||
847 (strcmp(sreg_names[i], name) == 0)) {
851 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
852 return kSPRegInternalCode;
858 // Helpers ---------------------------------------------------------------------
859 template <typename T>
860 T Simulator::AddWithCarry(bool set_flags,
864 typedef typename make_unsigned<T>::type unsignedT;
865 DCHECK((carry_in == 0) || (carry_in == 1));
867 T signed_sum = src1 + src2 + carry_in;
868 T result = signed_sum;
872 // Compute the C flag
873 unsignedT u1 = static_cast<unsignedT>(src1);
874 unsignedT u2 = static_cast<unsignedT>(src2);
875 unsignedT urest = std::numeric_limits<unsignedT>::max() - u1;
876 C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1))));
878 // Overflow iff the sign bit is the same for the two inputs and different
880 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
882 N = CalcNFlag(result);
883 Z = CalcZFlag(result);
890 LogSystemRegister(NZCV);
897 void Simulator::AddSubWithCarry(Instruction* instr) {
898 T op2 = reg<T>(instr->Rm());
901 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
905 new_val = AddWithCarry<T>(instr->FlagsUpdate(),
910 set_reg<T>(instr->Rd(), new_val);
913 template <typename T>
914 T Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) {
915 typedef typename make_unsigned<T>::type unsignedT;
921 switch (shift_type) {
923 return value << amount;
925 return static_cast<unsignedT>(value) >> amount;
927 return value >> amount;
929 unsignedT mask = (static_cast<unsignedT>(1) << amount) - 1;
930 return (static_cast<unsignedT>(value) >> amount) |
931 ((value & mask) << (sizeof(mask) * 8 - amount));
940 template <typename T>
941 T Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) {
942 const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8;
943 const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8;
944 const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8;
946 switch (extend_type) {
951 value &= kHalfWordMask;
957 value = (value << kSignExtendBShift) >> kSignExtendBShift;
960 value = (value << kSignExtendHShift) >> kSignExtendHShift;
963 value = (value << kSignExtendWShift) >> kSignExtendWShift;
971 return value << left_shift;
975 template <typename T>
976 void Simulator::Extract(Instruction* instr) {
977 unsigned lsb = instr->ImmS();
978 T op2 = reg<T>(instr->Rm());
982 T op1 = reg<T>(instr->Rn());
983 result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb));
985 set_reg<T>(instr->Rd(), result);
989 template<> double Simulator::FPDefaultNaN<double>() const {
990 return kFP64DefaultNaN;
994 template<> float Simulator::FPDefaultNaN<float>() const {
995 return kFP32DefaultNaN;
999 void Simulator::FPCompare(double val0, double val1) {
1000 AssertSupportedFPCR();
1002 // TODO(jbramley): This assumes that the C++ implementation handles
1003 // comparisons in the way that we expect (as per AssertSupportedFPCR()).
1004 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
1005 nzcv().SetRawValue(FPUnorderedFlag);
1006 } else if (val0 < val1) {
1007 nzcv().SetRawValue(FPLessThanFlag);
1008 } else if (val0 > val1) {
1009 nzcv().SetRawValue(FPGreaterThanFlag);
1010 } else if (val0 == val1) {
1011 nzcv().SetRawValue(FPEqualFlag);
1015 LogSystemRegister(NZCV);
1019 void Simulator::SetBreakpoint(Instruction* location) {
1020 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1021 if (breakpoints_.at(i).location == location) {
1023 "Existing breakpoint at %p was %s\n",
1024 reinterpret_cast<void*>(location),
1025 breakpoints_.at(i).enabled ? "disabled" : "enabled");
1026 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
1030 Breakpoint new_breakpoint = {location, true};
1031 breakpoints_.push_back(new_breakpoint);
1033 "Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
1037 void Simulator::ListBreakpoints() {
1038 PrintF(stream_, "Breakpoints:\n");
1039 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1040 PrintF(stream_, "%p : %s\n",
1041 reinterpret_cast<void*>(breakpoints_.at(i).location),
1042 breakpoints_.at(i).enabled ? "enabled" : "disabled");
1047 void Simulator::CheckBreakpoints() {
1048 bool hit_a_breakpoint = false;
1049 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1050 if ((breakpoints_.at(i).location == pc_) &&
1051 breakpoints_.at(i).enabled) {
1052 hit_a_breakpoint = true;
1053 // Disable this breakpoint.
1054 breakpoints_.at(i).enabled = false;
1057 if (hit_a_breakpoint) {
1058 PrintF(stream_, "Hit and disabled a breakpoint at %p.\n",
1059 reinterpret_cast<void*>(pc_));
1065 void Simulator::CheckBreakNext() {
1066 // If the current instruction is a BL, insert a breakpoint just after it.
1067 if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
1068 SetBreakpoint(pc_->following());
1069 break_on_next_ = false;
1074 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1075 Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
1076 for (Instruction* pc = start; pc < end; pc = pc->following()) {
1077 disassembler_decoder_->Decode(pc);
1082 void Simulator::PrintSystemRegisters() {
1083 PrintSystemRegister(NZCV);
1084 PrintSystemRegister(FPCR);
1088 void Simulator::PrintRegisters() {
1089 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1095 void Simulator::PrintFPRegisters() {
1096 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
1102 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
1103 // Don't print writes into xzr.
1104 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1108 // The template is "# x<code>:value".
1109 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n",
1110 clr_reg_name, XRegNameForCode(code, r31mode),
1111 clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal);
1115 void Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) {
1116 // The template is "# v<code>:bits (d<code>:value, ...)".
1119 DCHECK((sizes & kPrintAllFPRegValues) == sizes);
1121 // Print the raw bits.
1122 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (",
1123 clr_fpreg_name, VRegNameForCode(code),
1124 clr_fpreg_value, fpreg<uint64_t>(code), clr_normal);
1126 // Print all requested value interpretations.
1127 bool need_separator = false;
1128 if (sizes & kPrintDRegValue) {
1129 fprintf(stream_, "%s%s%s: %s%g%s",
1130 need_separator ? ", " : "",
1131 clr_fpreg_name, DRegNameForCode(code),
1132 clr_fpreg_value, fpreg<double>(code), clr_normal);
1133 need_separator = true;
1136 if (sizes & kPrintSRegValue) {
1137 fprintf(stream_, "%s%s%s: %s%g%s",
1138 need_separator ? ", " : "",
1139 clr_fpreg_name, SRegNameForCode(code),
1140 clr_fpreg_value, fpreg<float>(code), clr_normal);
1141 need_separator = true;
1144 // End the value list.
1145 fprintf(stream_, ")\n");
1149 void Simulator::PrintSystemRegister(SystemRegister id) {
1152 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1153 clr_flag_name, clr_flag_value,
1154 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
1158 static const char * rmode[] = {
1159 "0b00 (Round to Nearest)",
1160 "0b01 (Round towards Plus Infinity)",
1161 "0b10 (Round towards Minus Infinity)",
1162 "0b11 (Round towards Zero)"
1164 DCHECK(fpcr().RMode() < arraysize(rmode));
1166 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1167 clr_flag_name, clr_flag_value,
1168 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1178 void Simulator::PrintRead(uintptr_t address,
1180 unsigned reg_code) {
1181 USE(size); // Size is unused here.
1183 // The template is "# x<code>:value <- address".
1184 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1185 clr_reg_name, XRegNameForCode(reg_code),
1186 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1188 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1189 clr_memory_address, address, clr_normal);
1193 void Simulator::PrintReadFP(uintptr_t address,
1195 unsigned reg_code) {
1196 // The template is "# reg:bits (reg:value) <- address".
1199 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)",
1200 clr_fpreg_name, VRegNameForCode(reg_code),
1201 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1202 clr_fpreg_name, SRegNameForCode(reg_code),
1203 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1206 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1207 clr_fpreg_name, VRegNameForCode(reg_code),
1208 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1209 clr_fpreg_name, DRegNameForCode(reg_code),
1210 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1216 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1217 clr_memory_address, address, clr_normal);
1221 void Simulator::PrintWrite(uintptr_t address,
1223 unsigned reg_code) {
1224 // The template is "# reg:value -> address". To keep the trace tidy and
1225 // readable, the value is aligned with the values in the register trace.
1227 case kByteSizeInBytes:
1228 fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s",
1229 clr_reg_name, WRegNameForCode(reg_code),
1230 clr_reg_value, reg<uint8_t>(reg_code), clr_normal);
1232 case kHalfWordSizeInBytes:
1233 fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s",
1234 clr_reg_name, WRegNameForCode(reg_code),
1235 clr_reg_value, reg<uint16_t>(reg_code), clr_normal);
1238 fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s",
1239 clr_reg_name, WRegNameForCode(reg_code),
1240 clr_reg_value, reg<uint32_t>(reg_code), clr_normal);
1243 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1244 clr_reg_name, XRegNameForCode(reg_code),
1245 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1251 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1252 clr_memory_address, address, clr_normal);
1256 void Simulator::PrintWriteFP(uintptr_t address,
1258 unsigned reg_code) {
1259 // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy
1260 // and readable, the value is aligned with the values in the register trace.
1263 fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)",
1264 clr_fpreg_name, VRegNameForCode(reg_code),
1265 clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal,
1266 clr_fpreg_name, SRegNameForCode(reg_code),
1267 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1270 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1271 clr_fpreg_name, VRegNameForCode(reg_code),
1272 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1273 clr_fpreg_name, DRegNameForCode(reg_code),
1274 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1280 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1281 clr_memory_address, address, clr_normal);
1285 // Visitors---------------------------------------------------------------------
1287 void Simulator::VisitUnimplemented(Instruction* instr) {
1288 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1289 reinterpret_cast<void*>(instr), instr->InstructionBits());
1294 void Simulator::VisitUnallocated(Instruction* instr) {
1295 fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1296 reinterpret_cast<void*>(instr), instr->InstructionBits());
1301 void Simulator::VisitPCRelAddressing(Instruction* instr) {
1302 switch (instr->Mask(PCRelAddressingMask)) {
1304 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
1306 case ADRP: // Not implemented in the assembler.
1316 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
1317 switch (instr->Mask(UnconditionalBranchMask)) {
1319 set_lr(instr->following());
1322 set_pc(instr->ImmPCOffsetTarget());
1330 void Simulator::VisitConditionalBranch(Instruction* instr) {
1331 DCHECK(instr->Mask(ConditionalBranchMask) == B_cond);
1332 if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
1333 set_pc(instr->ImmPCOffsetTarget());
1338 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1339 Instruction* target = reg<Instruction*>(instr->Rn());
1340 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1342 set_lr(instr->following());
1343 if (instr->Rn() == 31) {
1344 // BLR XZR is used as a guard for the constant pool. We should never hit
1345 // this, but if we do trap to allow debugging.
1351 case RET: set_pc(target); break;
1352 default: UNIMPLEMENTED();
1357 void Simulator::VisitTestBranch(Instruction* instr) {
1358 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1359 instr->ImmTestBranchBit40();
1360 bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0);
1361 switch (instr->Mask(TestBranchMask)) {
1363 case TBNZ: take_branch = !take_branch; break;
1364 default: UNIMPLEMENTED();
1367 set_pc(instr->ImmPCOffsetTarget());
1372 void Simulator::VisitCompareBranch(Instruction* instr) {
1373 unsigned rt = instr->Rt();
1374 bool take_branch = false;
1375 switch (instr->Mask(CompareBranchMask)) {
1376 case CBZ_w: take_branch = (wreg(rt) == 0); break;
1377 case CBZ_x: take_branch = (xreg(rt) == 0); break;
1378 case CBNZ_w: take_branch = (wreg(rt) != 0); break;
1379 case CBNZ_x: take_branch = (xreg(rt) != 0); break;
1380 default: UNIMPLEMENTED();
1383 set_pc(instr->ImmPCOffsetTarget());
1388 template<typename T>
1389 void Simulator::AddSubHelper(Instruction* instr, T op2) {
1390 bool set_flags = instr->FlagsUpdate();
1392 Instr operation = instr->Mask(AddSubOpMask);
1394 switch (operation) {
1397 new_val = AddWithCarry<T>(set_flags,
1398 reg<T>(instr->Rn(), instr->RnMode()),
1404 new_val = AddWithCarry<T>(set_flags,
1405 reg<T>(instr->Rn(), instr->RnMode()),
1410 default: UNREACHABLE();
1413 set_reg<T>(instr->Rd(), new_val, instr->RdMode());
1417 void Simulator::VisitAddSubShifted(Instruction* instr) {
1418 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1419 unsigned shift_amount = instr->ImmDPShift();
1421 if (instr->SixtyFourBits()) {
1422 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1423 AddSubHelper(instr, op2);
1425 int32_t op2 = static_cast<int32_t>(
1426 ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount));
1427 AddSubHelper(instr, op2);
1432 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1433 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1434 if (instr->SixtyFourBits()) {
1435 AddSubHelper<int64_t>(instr, op2);
1437 AddSubHelper<int32_t>(instr, static_cast<int32_t>(op2));
1442 void Simulator::VisitAddSubExtended(Instruction* instr) {
1443 Extend ext = static_cast<Extend>(instr->ExtendMode());
1444 unsigned left_shift = instr->ImmExtendShift();
1445 if (instr->SixtyFourBits()) {
1446 int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
1447 AddSubHelper(instr, op2);
1449 int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
1450 AddSubHelper(instr, op2);
1455 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1456 if (instr->SixtyFourBits()) {
1457 AddSubWithCarry<int64_t>(instr);
1459 AddSubWithCarry<int32_t>(instr);
1464 void Simulator::VisitLogicalShifted(Instruction* instr) {
1465 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1466 unsigned shift_amount = instr->ImmDPShift();
1468 if (instr->SixtyFourBits()) {
1469 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1470 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1471 LogicalHelper<int64_t>(instr, op2);
1473 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1474 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1475 LogicalHelper<int32_t>(instr, op2);
1480 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1481 if (instr->SixtyFourBits()) {
1482 LogicalHelper<int64_t>(instr, instr->ImmLogical());
1484 LogicalHelper<int32_t>(instr, static_cast<int32_t>(instr->ImmLogical()));
1489 template<typename T>
1490 void Simulator::LogicalHelper(Instruction* instr, T op2) {
1491 T op1 = reg<T>(instr->Rn());
1493 bool update_flags = false;
1495 // Switch on the logical operation, stripping out the NOT bit, as it has a
1496 // different meaning for logical immediate instructions.
1497 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1498 case ANDS: update_flags = true; // Fall through.
1499 case AND: result = op1 & op2; break;
1500 case ORR: result = op1 | op2; break;
1501 case EOR: result = op1 ^ op2; break;
1507 nzcv().SetN(CalcNFlag(result));
1508 nzcv().SetZ(CalcZFlag(result));
1511 LogSystemRegister(NZCV);
1514 set_reg<T>(instr->Rd(), result, instr->RdMode());
1518 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1519 if (instr->SixtyFourBits()) {
1520 ConditionalCompareHelper(instr, xreg(instr->Rm()));
1522 ConditionalCompareHelper(instr, wreg(instr->Rm()));
1527 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1528 if (instr->SixtyFourBits()) {
1529 ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp());
1531 ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp());
1536 template<typename T>
1537 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
1538 T op1 = reg<T>(instr->Rn());
1540 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1541 // If the condition passes, set the status flags to the result of comparing
1543 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1544 AddWithCarry<T>(true, op1, ~op2, 1);
1546 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN);
1547 AddWithCarry<T>(true, op1, op2, 0);
1550 // If the condition fails, set the status flags to the nzcv immediate.
1551 nzcv().SetFlags(instr->Nzcv());
1552 LogSystemRegister(NZCV);
1557 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1558 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1559 LoadStoreHelper(instr, offset, Offset);
1563 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1564 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1568 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1569 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1573 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1574 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1578 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1579 Extend ext = static_cast<Extend>(instr->ExtendMode());
1580 DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1581 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1583 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount);
1584 LoadStoreHelper(instr, offset, Offset);
1588 void Simulator::LoadStoreHelper(Instruction* instr,
1590 AddrMode addrmode) {
1591 unsigned srcdst = instr->Rt();
1592 unsigned addr_reg = instr->Rn();
1593 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1594 uintptr_t stack = 0;
1596 // Handle the writeback for stores before the store. On a CPU the writeback
1597 // and the store are atomic, but when running on the simulator it is possible
1598 // to be interrupted in between. The simulator is not thread safe and V8 does
1599 // not require it to be to run JavaScript therefore the profiler may sample
1600 // the "simulated" CPU in the middle of load/store with writeback. The code
1601 // below ensures that push operations are safe even when interrupted: the
1602 // stack pointer will be decremented before adding an element to the stack.
1603 if (instr->IsStore()) {
1604 LoadStoreWriteBack(addr_reg, offset, addrmode);
1606 // For store the address post writeback is used to check access below the
1611 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
1613 // Use _no_log variants to suppress the register trace (LOG_REGS,
1614 // LOG_FP_REGS). We will print a more detailed log.
1615 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break;
1616 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break;
1617 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break;
1618 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break;
1619 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1620 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1621 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1622 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1623 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break;
1624 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break;
1625 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break;
1627 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break;
1628 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break;
1629 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break;
1630 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break;
1631 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break;
1632 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break;
1634 default: UNIMPLEMENTED();
1637 // Print a detailed trace (including the memory address) instead of the basic
1638 // register:value trace generated by set_*reg().
1639 size_t access_size = 1 << instr->SizeLS();
1640 if (instr->IsLoad()) {
1641 if ((op == LDR_s) || (op == LDR_d)) {
1642 LogReadFP(address, access_size, srcdst);
1644 LogRead(address, access_size, srcdst);
1647 if ((op == STR_s) || (op == STR_d)) {
1648 LogWriteFP(address, access_size, srcdst);
1650 LogWrite(address, access_size, srcdst);
1654 // Handle the writeback for loads after the load to ensure safe pop
1655 // operation even when interrupted in the middle of it. The stack pointer
1656 // is only updated after the load so pop(fp) will never break the invariant
1657 // sp <= fp expected while walking the stack in the sampler.
1658 if (instr->IsLoad()) {
1659 // For loads the address pre writeback is used to check access below the
1663 LoadStoreWriteBack(addr_reg, offset, addrmode);
1666 // Accesses below the stack pointer (but above the platform stack limit) are
1667 // not allowed in the ABI.
1668 CheckMemoryAccess(address, stack);
1672 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1673 LoadStorePairHelper(instr, Offset);
1677 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1678 LoadStorePairHelper(instr, PreIndex);
1682 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1683 LoadStorePairHelper(instr, PostIndex);
1687 void Simulator::LoadStorePairHelper(Instruction* instr,
1688 AddrMode addrmode) {
1689 unsigned rt = instr->Rt();
1690 unsigned rt2 = instr->Rt2();
1691 unsigned addr_reg = instr->Rn();
1692 size_t access_size = 1 << instr->SizeLSPair();
1693 int64_t offset = instr->ImmLSPair() * access_size;
1694 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1695 uintptr_t address2 = address + access_size;
1696 uintptr_t stack = 0;
1698 // Handle the writeback for stores before the store. On a CPU the writeback
1699 // and the store are atomic, but when running on the simulator it is possible
1700 // to be interrupted in between. The simulator is not thread safe and V8 does
1701 // not require it to be to run JavaScript therefore the profiler may sample
1702 // the "simulated" CPU in the middle of load/store with writeback. The code
1703 // below ensures that push operations are safe even when interrupted: the
1704 // stack pointer will be decremented before adding an element to the stack.
1705 if (instr->IsStore()) {
1706 LoadStoreWriteBack(addr_reg, offset, addrmode);
1708 // For store the address post writeback is used to check access below the
1713 LoadStorePairOp op =
1714 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1716 // 'rt' and 'rt2' can only be aliased for stores.
1717 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1720 // Use _no_log variants to suppress the register trace (LOG_REGS,
1721 // LOG_FP_REGS). We will print a more detailed log.
1723 DCHECK(access_size == kWRegSize);
1724 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1725 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
1729 DCHECK(access_size == kSRegSize);
1730 set_sreg_no_log(rt, MemoryRead<float>(address));
1731 set_sreg_no_log(rt2, MemoryRead<float>(address2));
1735 DCHECK(access_size == kXRegSize);
1736 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1737 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
1741 DCHECK(access_size == kDRegSize);
1742 set_dreg_no_log(rt, MemoryRead<double>(address));
1743 set_dreg_no_log(rt2, MemoryRead<double>(address2));
1747 DCHECK(access_size == kWRegSize);
1748 set_xreg_no_log(rt, MemoryRead<int32_t>(address));
1749 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
1753 DCHECK(access_size == kWRegSize);
1754 MemoryWrite<uint32_t>(address, wreg(rt));
1755 MemoryWrite<uint32_t>(address2, wreg(rt2));
1759 DCHECK(access_size == kSRegSize);
1760 MemoryWrite<float>(address, sreg(rt));
1761 MemoryWrite<float>(address2, sreg(rt2));
1765 DCHECK(access_size == kXRegSize);
1766 MemoryWrite<uint64_t>(address, xreg(rt));
1767 MemoryWrite<uint64_t>(address2, xreg(rt2));
1771 DCHECK(access_size == kDRegSize);
1772 MemoryWrite<double>(address, dreg(rt));
1773 MemoryWrite<double>(address2, dreg(rt2));
1776 default: UNREACHABLE();
1779 // Print a detailed trace (including the memory address) instead of the basic
1780 // register:value trace generated by set_*reg().
1781 if (instr->IsLoad()) {
1782 if ((op == LDP_s) || (op == LDP_d)) {
1783 LogReadFP(address, access_size, rt);
1784 LogReadFP(address2, access_size, rt2);
1786 LogRead(address, access_size, rt);
1787 LogRead(address2, access_size, rt2);
1790 if ((op == STP_s) || (op == STP_d)) {
1791 LogWriteFP(address, access_size, rt);
1792 LogWriteFP(address2, access_size, rt2);
1794 LogWrite(address, access_size, rt);
1795 LogWrite(address2, access_size, rt2);
1799 // Handle the writeback for loads after the load to ensure safe pop
1800 // operation even when interrupted in the middle of it. The stack pointer
1801 // is only updated after the load so pop(fp) will never break the invariant
1802 // sp <= fp expected while walking the stack in the sampler.
1803 if (instr->IsLoad()) {
1804 // For loads the address pre writeback is used to check access below the
1808 LoadStoreWriteBack(addr_reg, offset, addrmode);
1811 // Accesses below the stack pointer (but above the platform stack limit) are
1812 // not allowed in the ABI.
1813 CheckMemoryAccess(address, stack);
1817 void Simulator::VisitLoadLiteral(Instruction* instr) {
1818 uintptr_t address = instr->LiteralAddress();
1819 unsigned rt = instr->Rt();
1821 switch (instr->Mask(LoadLiteralMask)) {
1822 // Use _no_log variants to suppress the register trace (LOG_REGS,
1823 // LOG_FP_REGS), then print a more detailed log.
1825 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1826 LogRead(address, kWRegSize, rt);
1829 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1830 LogRead(address, kXRegSize, rt);
1833 set_sreg_no_log(rt, MemoryRead<float>(address));
1834 LogReadFP(address, kSRegSize, rt);
1837 set_dreg_no_log(rt, MemoryRead<double>(address));
1838 LogReadFP(address, kDRegSize, rt);
1840 default: UNREACHABLE();
1845 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset,
1846 AddrMode addrmode) {
1847 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1848 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1849 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
1850 // When the base register is SP the stack pointer is required to be
1851 // quadword aligned prior to the address calculation and write-backs.
1852 // Misalignment will cause a stack alignment fault.
1853 FATAL("ALIGNMENT EXCEPTION");
1856 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1864 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
1866 AddrMode addrmode) {
1867 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1868 DCHECK(offset != 0);
1869 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1870 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
1875 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
1876 if ((address >= stack_limit_) && (address < stack)) {
1877 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
1878 fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n",
1879 static_cast<uint64_t>(stack));
1880 fprintf(stream_, " access was here: 0x%016" PRIx64 "\n",
1881 static_cast<uint64_t>(address));
1882 fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n",
1883 static_cast<uint64_t>(stack_limit_));
1884 fprintf(stream_, "\n");
1885 FATAL("ACCESS BELOW STACK POINTER");
1890 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
1891 MoveWideImmediateOp mov_op =
1892 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1893 int64_t new_xn_val = 0;
1895 bool is_64_bits = instr->SixtyFourBits() == 1;
1896 // Shift is limited for W operations.
1897 DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2));
1899 // Get the shifted immediate.
1900 int64_t shift = instr->ShiftMoveWide() * 16;
1901 int64_t shifted_imm16 = static_cast<int64_t>(instr->ImmMoveWide()) << shift;
1903 // Compute the new value.
1907 new_xn_val = ~shifted_imm16;
1908 if (!is_64_bits) new_xn_val &= kWRegMask;
1913 unsigned reg_code = instr->Rd();
1914 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1916 new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16;
1921 new_xn_val = shifted_imm16;
1928 // Update the destination register.
1929 set_xreg(instr->Rd(), new_xn_val);
1933 void Simulator::VisitConditionalSelect(Instruction* instr) {
1934 uint64_t new_val = xreg(instr->Rn());
1935 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1936 new_val = xreg(instr->Rm());
1937 switch (instr->Mask(ConditionalSelectMask)) {
1953 default: UNIMPLEMENTED();
1956 if (instr->SixtyFourBits()) {
1957 set_xreg(instr->Rd(), new_val);
1959 set_wreg(instr->Rd(), static_cast<uint32_t>(new_val));
1964 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
1965 unsigned dst = instr->Rd();
1966 unsigned src = instr->Rn();
1968 switch (instr->Mask(DataProcessing1SourceMask)) {
1970 set_wreg(dst, ReverseBits(wreg(src)));
1973 set_xreg(dst, ReverseBits(xreg(src)));
1976 set_wreg(dst, ReverseBytes(wreg(src), 1));
1979 set_xreg(dst, ReverseBytes(xreg(src), 1));
1982 set_wreg(dst, ReverseBytes(wreg(src), 2));
1985 set_xreg(dst, ReverseBytes(xreg(src), 2));
1988 set_xreg(dst, ReverseBytes(xreg(src), 3));
1990 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits));
1992 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits));
1995 set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits));
1999 set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits));
2002 default: UNIMPLEMENTED();
2007 template <typename T>
2008 void Simulator::DataProcessing2Source(Instruction* instr) {
2009 Shift shift_op = NO_SHIFT;
2011 switch (instr->Mask(DataProcessing2SourceMask)) {
2014 T rn = reg<T>(instr->Rn());
2015 T rm = reg<T>(instr->Rm());
2016 if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) {
2017 result = std::numeric_limits<T>::min();
2018 } else if (rm == 0) {
2019 // Division by zero can be trapped, but not on A-class processors.
2028 typedef typename make_unsigned<T>::type unsignedT;
2029 unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn()));
2030 unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm()));
2032 // Division by zero can be trapped, but not on A-class processors.
2040 case LSLV_x: shift_op = LSL; break;
2042 case LSRV_x: shift_op = LSR; break;
2044 case ASRV_x: shift_op = ASR; break;
2046 case RORV_x: shift_op = ROR; break;
2047 default: UNIMPLEMENTED();
2050 if (shift_op != NO_SHIFT) {
2051 // Shift distance encoded in the least-significant five/six bits of the
2053 unsigned shift = wreg(instr->Rm());
2054 if (sizeof(T) == kWRegSize) {
2055 shift &= kShiftAmountWRegMask;
2057 shift &= kShiftAmountXRegMask;
2059 result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift);
2061 set_reg<T>(instr->Rd(), result);
2065 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
2066 if (instr->SixtyFourBits()) {
2067 DataProcessing2Source<int64_t>(instr);
2069 DataProcessing2Source<int32_t>(instr);
2074 // The algorithm used is described in section 8.2 of
2075 // Hacker's Delight, by Henry S. Warren, Jr.
2076 // It assumes that a right shift on a signed integer is an arithmetic shift.
2077 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
2078 uint64_t u0, v0, w0;
2079 int64_t u1, v1, w1, w2, t;
2081 u0 = u & 0xffffffffL;
2083 v0 = v & 0xffffffffL;
2087 t = u1 * v0 + (w0 >> 32);
2088 w1 = t & 0xffffffffL;
2092 return u1 * v1 + w2 + (w1 >> 32);
2096 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
2098 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2099 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
2100 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
2101 int64_t rn_s32 = reg<int32_t>(instr->Rn());
2102 int64_t rm_s32 = reg<int32_t>(instr->Rm());
2103 switch (instr->Mask(DataProcessing3SourceMask)) {
2106 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
2110 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
2112 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
2113 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
2114 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
2115 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
2117 DCHECK(instr->Ra() == kZeroRegCode);
2118 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
2120 default: UNIMPLEMENTED();
2123 if (instr->SixtyFourBits()) {
2124 set_xreg(instr->Rd(), result);
2126 set_wreg(instr->Rd(), static_cast<int32_t>(result));
2131 template <typename T>
2132 void Simulator::BitfieldHelper(Instruction* instr) {
2133 typedef typename make_unsigned<T>::type unsignedT;
2134 T reg_size = sizeof(T) * 8;
2135 T R = instr->ImmR();
2136 T S = instr->ImmS();
2140 mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1
2141 : static_cast<T>(-1);
2143 uint64_t umask = ((1L << (S + 1)) - 1);
2144 umask = (umask >> R) | (umask << (reg_size - R));
2145 mask = static_cast<T>(umask);
2149 // inzero indicates if the extracted bitfield is inserted into the
2150 // destination register value or in zero.
2151 // If extend is true, extend the sign of the extracted bitfield.
2152 bool inzero = false;
2153 bool extend = false;
2154 switch (instr->Mask(BitfieldMask)) {
2171 T dst = inzero ? 0 : reg<T>(instr->Rd());
2172 T src = reg<T>(instr->Rn());
2173 // Rotate source bitfield into place.
2174 T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R));
2175 // Determine the sign extension.
2176 T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1;
2177 T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0)
2180 // Merge sign extension, dest/zero and bitfield.
2181 result = signbits | (result & mask) | (dst & ~mask);
2183 set_reg<T>(instr->Rd(), result);
2187 void Simulator::VisitBitfield(Instruction* instr) {
2188 if (instr->SixtyFourBits()) {
2189 BitfieldHelper<int64_t>(instr);
2191 BitfieldHelper<int32_t>(instr);
2196 void Simulator::VisitExtract(Instruction* instr) {
2197 if (instr->SixtyFourBits()) {
2198 Extract<uint64_t>(instr);
2200 Extract<uint32_t>(instr);
2205 void Simulator::VisitFPImmediate(Instruction* instr) {
2206 AssertSupportedFPCR();
2208 unsigned dest = instr->Rd();
2209 switch (instr->Mask(FPImmediateMask)) {
2210 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
2211 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
2212 default: UNREACHABLE();
2217 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
2218 AssertSupportedFPCR();
2220 unsigned dst = instr->Rd();
2221 unsigned src = instr->Rn();
2223 FPRounding round = fpcr().RMode();
2225 switch (instr->Mask(FPIntegerConvertMask)) {
2226 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
2227 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
2228 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
2229 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
2230 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
2231 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
2232 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
2233 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
2235 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
2238 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
2241 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
2244 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
2247 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
2250 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
2253 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
2256 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
2258 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
2259 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
2260 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
2261 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
2262 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
2263 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
2264 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
2265 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
2266 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
2267 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
2268 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
2269 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
2270 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
2271 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
2272 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
2273 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
2274 case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
2275 case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
2276 case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
2277 case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
2279 // A 32-bit input can be handled in the same way as a 64-bit input, since
2280 // the sign- or zero-extension will not affect the conversion.
2281 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
2282 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
2283 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
2285 set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2288 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
2289 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
2290 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
2292 set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2296 default: UNREACHABLE();
2301 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2302 AssertSupportedFPCR();
2304 unsigned dst = instr->Rd();
2305 unsigned src = instr->Rn();
2306 int fbits = 64 - instr->FPScale();
2308 FPRounding round = fpcr().RMode();
2310 switch (instr->Mask(FPFixedPointConvertMask)) {
2311 // A 32-bit input can be handled in the same way as a 64-bit input, since
2312 // the sign- or zero-extension will not affect the conversion.
2313 case SCVTF_dx_fixed:
2314 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2316 case SCVTF_dw_fixed:
2317 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2319 case UCVTF_dx_fixed:
2320 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2322 case UCVTF_dw_fixed: {
2324 UFixedToDouble(reg<uint32_t>(src), fbits, round));
2327 case SCVTF_sx_fixed:
2328 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2330 case SCVTF_sw_fixed:
2331 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2333 case UCVTF_sx_fixed:
2334 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2336 case UCVTF_sw_fixed: {
2338 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2341 default: UNREACHABLE();
2346 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
2347 value = FPRoundInt(value, rmode);
2348 if (value >= kWMaxInt) {
2350 } else if (value < kWMinInt) {
2353 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
2357 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
2358 value = FPRoundInt(value, rmode);
2359 if (value >= kXMaxInt) {
2361 } else if (value < kXMinInt) {
2364 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
2368 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
2369 value = FPRoundInt(value, rmode);
2370 if (value >= kWMaxUInt) {
2372 } else if (value < 0.0) {
2375 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
2379 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
2380 value = FPRoundInt(value, rmode);
2381 if (value >= kXMaxUInt) {
2383 } else if (value < 0.0) {
2386 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
2390 void Simulator::VisitFPCompare(Instruction* instr) {
2391 AssertSupportedFPCR();
2393 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2395 double fn_val = fpreg(reg_size, instr->Rn());
2397 switch (instr->Mask(FPCompareMask)) {
2399 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
2401 case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
2402 default: UNIMPLEMENTED();
2407 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2408 AssertSupportedFPCR();
2410 switch (instr->Mask(FPConditionalCompareMask)) {
2413 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2414 // If the condition passes, set the status flags to the result of
2415 // comparing the operands.
2416 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2418 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
2420 // If the condition fails, set the status flags to the nzcv immediate.
2421 nzcv().SetFlags(instr->Nzcv());
2422 LogSystemRegister(NZCV);
2426 default: UNIMPLEMENTED();
2431 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2432 AssertSupportedFPCR();
2435 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2436 selected = instr->Rn();
2438 selected = instr->Rm();
2441 switch (instr->Mask(FPConditionalSelectMask)) {
2442 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2443 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2444 default: UNIMPLEMENTED();
2449 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2450 AssertSupportedFPCR();
2452 unsigned fd = instr->Rd();
2453 unsigned fn = instr->Rn();
2455 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2456 case FMOV_s: set_sreg(fd, sreg(fn)); break;
2457 case FMOV_d: set_dreg(fd, dreg(fn)); break;
2458 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break;
2459 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break;
2460 case FNEG_s: set_sreg(fd, -sreg(fn)); break;
2461 case FNEG_d: set_dreg(fd, -dreg(fn)); break;
2462 case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break;
2463 case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break;
2464 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break;
2465 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break;
2467 set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break;
2469 set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break;
2471 set_sreg(fd, FPRoundInt(sreg(fn), FPPositiveInfinity));
2474 set_dreg(fd, FPRoundInt(dreg(fn), FPPositiveInfinity));
2476 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
2477 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
2478 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
2479 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
2480 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
2481 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
2482 default: UNIMPLEMENTED();
2487 // Assemble the specified IEEE-754 components into the target type and apply
2488 // appropriate rounding.
2489 // sign: 0 = positive, 1 = negative
2490 // exponent: Unbiased IEEE-754 exponent.
2491 // mantissa: The mantissa of the input. The top bit (which is not encoded for
2492 // normal IEEE-754 values) must not be omitted. This bit has the
2493 // value 'pow(2, exponent)'.
2495 // The input value is assumed to be a normalized value. That is, the input may
2496 // not be infinity or NaN. If the source value is subnormal, it must be
2497 // normalized before calling this function such that the highest set bit in the
2498 // mantissa has the value 'pow(2, exponent)'.
2500 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
2501 // calling a templated FPRound.
2502 template <class T, int ebits, int mbits>
2503 static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
2504 FPRounding round_mode) {
2505 DCHECK((sign == 0) || (sign == 1));
2507 // Only the FPTieEven rounding mode is implemented.
2508 DCHECK(round_mode == FPTieEven);
2511 // Rounding can promote subnormals to normals, and normals to infinities. For
2512 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
2513 // encodable as a float, but rounding based on the low-order mantissa bits
2514 // could make it overflow. With ties-to-even rounding, this value would become
2517 // ---- Rounding Method ----
2519 // The exponent is irrelevant in the rounding operation, so we treat the
2520 // lowest-order bit that will fit into the result ('onebit') as having
2521 // the value '1'. Similarly, the highest-order bit that won't fit into
2522 // the result ('halfbit') has the value '0.5'. The 'point' sits between
2523 // 'onebit' and 'halfbit':
2525 // These bits fit into the result.
2526 // |---------------------|
2527 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2533 // For subnormal outputs, the range of representable bits is smaller and
2534 // the position of onebit and halfbit depends on the exponent of the
2535 // input, but the method is otherwise similar.
2539 // | halfbit(frac) halfbit(adjusted)
2542 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
2543 // 0b00.0... -> 0b00.0... -> 0b00
2544 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
2545 // 0b00.1... -> 0b00.1... -> 0b01
2546 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
2547 // 0b01.0... -> 0b01.0... -> 0b01
2548 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
2549 // 0b01.1... -> 0b01.1... -> 0b10
2550 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
2551 // 0b10.0... -> 0b10.0... -> 0b10
2552 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
2553 // 0b10.1... -> 0b10.1... -> 0b11
2554 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
2558 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
2560 // mantissa = (mantissa >> shift) + halfbit(adjusted);
2562 static const int mantissa_offset = 0;
2563 static const int exponent_offset = mantissa_offset + mbits;
2564 static const int sign_offset = exponent_offset + ebits;
2565 STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1));
2567 // Bail out early for zero inputs.
2568 if (mantissa == 0) {
2569 return static_cast<T>(sign << sign_offset);
2572 // If all bits in the exponent are set, the value is infinite or NaN.
2573 // This is true for all binary IEEE-754 formats.
2574 static const int infinite_exponent = (1 << ebits) - 1;
2575 static const int max_normal_exponent = infinite_exponent - 1;
2577 // Apply the exponent bias to encode it for the result. Doing this early makes
2578 // it easy to detect values that will be infinite or subnormal.
2579 exponent += max_normal_exponent >> 1;
2581 if (exponent > max_normal_exponent) {
2582 // Overflow: The input is too large for the result type to represent. The
2583 // FPTieEven rounding mode handles overflows using infinities.
2584 exponent = infinite_exponent;
2586 return static_cast<T>((sign << sign_offset) |
2587 (exponent << exponent_offset) |
2588 (mantissa << mantissa_offset));
2591 // Calculate the shift required to move the top mantissa bit to the proper
2592 // place in the destination type.
2593 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
2594 int shift = highest_significant_bit - mbits;
2596 if (exponent <= 0) {
2597 // The output will be subnormal (before rounding).
2599 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
2600 // is necessary because the exponent of a subnormal value (encoded as 0) is
2601 // the same as the exponent of the smallest normal value (encoded as 1).
2602 shift += -exponent + 1;
2604 // Handle inputs that would produce a zero output.
2606 // Shifts higher than highest_significant_bit+1 will always produce a zero
2607 // result. A shift of exactly highest_significant_bit+1 might produce a
2608 // non-zero result after rounding.
2609 if (shift > (highest_significant_bit + 1)) {
2610 // The result will always be +/-0.0.
2611 return static_cast<T>(sign << sign_offset);
2614 // Properly encode the exponent for a subnormal output.
2617 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
2619 mantissa &= ~(1UL << highest_significant_bit);
2623 // We have to shift the mantissa to the right. Some precision is lost, so we
2624 // need to apply rounding.
2625 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
2626 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
2627 uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
2628 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
2631 static_cast<T>((sign << sign_offset) | (exponent << exponent_offset) |
2632 ((mantissa >> shift) << mantissa_offset));
2634 // A very large mantissa can overflow during rounding. If this happens, the
2635 // exponent should be incremented and the mantissa set to 1.0 (encoded as
2636 // 0). Applying halfbit_adjusted after assembling the float has the nice
2637 // side-effect that this case is handled for free.
2639 // This also handles cases where a very large finite value overflows to
2640 // infinity, or where a very large subnormal value overflows to become
2642 return result + halfbit_adjusted;
2644 // We have to shift the mantissa to the left (or not at all). The input
2645 // mantissa is exactly representable in the output mantissa, so apply no
2646 // rounding correction.
2647 return static_cast<T>((sign << sign_offset) |
2648 (exponent << exponent_offset) |
2649 ((mantissa << -shift) << mantissa_offset));
2654 // See FPRound for a description of this function.
2655 static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
2656 uint64_t mantissa, FPRounding round_mode) {
2658 FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
2662 return rawbits_to_double(bits);
2666 // See FPRound for a description of this function.
2667 static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
2668 uint64_t mantissa, FPRounding round_mode) {
2670 FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
2674 return rawbits_to_float(bits);
2678 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
2680 return UFixedToDouble(src, fbits, round);
2682 // This works for all negative values, including INT64_MIN.
2683 return -UFixedToDouble(-src, fbits, round);
2688 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
2689 // An input of 0 is a special case because the result is effectively
2690 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2695 // Calculate the exponent. The highest significant bit will have the value
2697 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2698 const int64_t exponent = highest_significant_bit - fbits;
2700 return FPRoundToDouble(0, exponent, src, round);
2704 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
2706 return UFixedToFloat(src, fbits, round);
2708 // This works for all negative values, including INT64_MIN.
2709 return -UFixedToFloat(-src, fbits, round);
2714 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
2715 // An input of 0 is a special case because the result is effectively
2716 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2721 // Calculate the exponent. The highest significant bit will have the value
2723 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2724 const int32_t exponent = highest_significant_bit - fbits;
2726 return FPRoundToFloat(0, exponent, src, round);
2730 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
2731 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
2732 (value == kFP64NegativeInfinity)) {
2734 } else if (std::isnan(value)) {
2735 return FPProcessNaN(value);
2738 double int_result = floor(value);
2739 double error = value - int_result;
2740 switch (round_mode) {
2742 // Take care of correctly handling the range ]-0.5, -0.0], which must
2744 if ((-0.5 < value) && (value < 0.0)) {
2747 } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
2748 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2749 // result is positive, round up.
2755 // Take care of correctly handling the range [-0.5, -0.0], which must
2757 if ((-0.5 <= value) && (value < 0.0)) {
2760 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2761 // result is odd, round up.
2762 } else if ((error > 0.5) ||
2763 ((error == 0.5) && (fmod(int_result, 2) != 0))) {
2769 // If value > 0 then we take floor(value)
2770 // otherwise, ceil(value)
2772 int_result = ceil(value);
2776 case FPNegativeInfinity: {
2777 // We always use floor(value).
2780 case FPPositiveInfinity: {
2781 int_result = ceil(value);
2784 default: UNIMPLEMENTED();
2790 double Simulator::FPToDouble(float value) {
2791 switch (std::fpclassify(value)) {
2793 if (fpcr().DN()) return kFP64DefaultNaN;
2795 // Convert NaNs as the processor would:
2796 // - The sign is propagated.
2797 // - The payload (mantissa) is transferred entirely, except that the top
2798 // bit is forced to '1', making the result a quiet NaN. The unused
2799 // (low-order) payload bits are set to 0.
2800 uint32_t raw = float_to_rawbits(value);
2802 uint64_t sign = raw >> 31;
2803 uint64_t exponent = (1 << 11) - 1;
2804 uint64_t payload = unsigned_bitextract_64(21, 0, raw);
2805 payload <<= (52 - 23); // The unused low-order bits should be 0.
2806 payload |= (1L << 51); // Force a quiet NaN.
2808 return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
2815 // All other inputs are preserved in a standard cast, because every value
2816 // representable using an IEEE-754 float is also representable using an
2818 return static_cast<double>(value);
2823 return static_cast<double>(value);
2827 float Simulator::FPToFloat(double value, FPRounding round_mode) {
2828 // Only the FPTieEven rounding mode is implemented.
2829 DCHECK(round_mode == FPTieEven);
2832 switch (std::fpclassify(value)) {
2834 if (fpcr().DN()) return kFP32DefaultNaN;
2836 // Convert NaNs as the processor would:
2837 // - The sign is propagated.
2838 // - The payload (mantissa) is transferred as much as possible, except
2839 // that the top bit is forced to '1', making the result a quiet NaN.
2840 uint64_t raw = double_to_rawbits(value);
2842 uint32_t sign = raw >> 63;
2843 uint32_t exponent = (1 << 8) - 1;
2845 static_cast<uint32_t>(unsigned_bitextract_64(50, 52 - 23, raw));
2846 payload |= (1 << 22); // Force a quiet NaN.
2848 return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
2853 // In a C++ cast, any value representable in the target type will be
2854 // unchanged. This is always the case for +/-0.0 and infinities.
2855 return static_cast<float>(value);
2859 case FP_SUBNORMAL: {
2860 // Convert double-to-float as the processor would, assuming that FPCR.FZ
2861 // (flush-to-zero) is not set.
2862 uint64_t raw = double_to_rawbits(value);
2863 // Extract the IEEE-754 double components.
2864 uint32_t sign = raw >> 63;
2865 // Extract the exponent and remove the IEEE-754 encoding bias.
2867 static_cast<int32_t>(unsigned_bitextract_64(62, 52, raw)) - 1023;
2868 // Extract the mantissa and add the implicit '1' bit.
2869 uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
2870 if (std::fpclassify(value) == FP_NORMAL) {
2871 mantissa |= (1UL << 52);
2873 return FPRoundToFloat(sign, exponent, mantissa, round_mode);
2882 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2883 AssertSupportedFPCR();
2885 unsigned fd = instr->Rd();
2886 unsigned fn = instr->Rn();
2887 unsigned fm = instr->Rm();
2889 // Fmaxnm and Fminnm have special NaN handling.
2890 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2891 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return;
2892 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return;
2893 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return;
2894 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return;
2896 break; // Fall through.
2899 if (FPProcessNaNs(instr)) return;
2901 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2902 case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break;
2903 case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break;
2904 case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break;
2905 case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break;
2906 case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break;
2907 case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break;
2908 case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break;
2909 case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break;
2910 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
2911 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
2912 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
2913 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
2918 // These were handled before the standard FPProcessNaNs() stage.
2920 default: UNIMPLEMENTED();
2925 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2926 AssertSupportedFPCR();
2928 unsigned fd = instr->Rd();
2929 unsigned fn = instr->Rn();
2930 unsigned fm = instr->Rm();
2931 unsigned fa = instr->Ra();
2933 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2934 // fd = fa +/- (fn * fm)
2935 case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
2936 case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
2937 case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
2938 case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
2939 // Negated variants of the above.
2941 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2944 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2947 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2950 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2952 default: UNIMPLEMENTED();
2957 template <typename T>
2958 T Simulator::FPAdd(T op1, T op2) {
2959 // NaNs should be handled elsewhere.
2960 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2962 if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
2963 // inf + -inf returns the default NaN.
2964 return FPDefaultNaN<T>();
2966 // Other cases should be handled by standard arithmetic.
2972 template <typename T>
2973 T Simulator::FPDiv(T op1, T op2) {
2974 // NaNs should be handled elsewhere.
2975 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2977 if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
2978 // inf / inf and 0.0 / 0.0 return the default NaN.
2979 return FPDefaultNaN<T>();
2981 // Other cases should be handled by standard arithmetic.
2987 template <typename T>
2988 T Simulator::FPMax(T a, T b) {
2989 // NaNs should be handled elsewhere.
2990 DCHECK(!std::isnan(a) && !std::isnan(b));
2992 if ((a == 0.0) && (b == 0.0) &&
2993 (copysign(1.0, a) != copysign(1.0, b))) {
2994 // a and b are zero, and the sign differs: return +0.0.
2997 return (a > b) ? a : b;
3002 template <typename T>
3003 T Simulator::FPMaxNM(T a, T b) {
3004 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3005 a = kFP64NegativeInfinity;
3006 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3007 b = kFP64NegativeInfinity;
3010 T result = FPProcessNaNs(a, b);
3011 return std::isnan(result) ? result : FPMax(a, b);
3014 template <typename T>
3015 T Simulator::FPMin(T a, T b) {
3016 // NaNs should be handled elsewhere.
3017 DCHECK(!std::isnan(a) && !std::isnan(b));
3019 if ((a == 0.0) && (b == 0.0) &&
3020 (copysign(1.0, a) != copysign(1.0, b))) {
3021 // a and b are zero, and the sign differs: return -0.0.
3024 return (a < b) ? a : b;
3029 template <typename T>
3030 T Simulator::FPMinNM(T a, T b) {
3031 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3032 a = kFP64PositiveInfinity;
3033 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3034 b = kFP64PositiveInfinity;
3037 T result = FPProcessNaNs(a, b);
3038 return std::isnan(result) ? result : FPMin(a, b);
3042 template <typename T>
3043 T Simulator::FPMul(T op1, T op2) {
3044 // NaNs should be handled elsewhere.
3045 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3047 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
3048 // inf * 0.0 returns the default NaN.
3049 return FPDefaultNaN<T>();
3051 // Other cases should be handled by standard arithmetic.
3057 template<typename T>
3058 T Simulator::FPMulAdd(T a, T op1, T op2) {
3059 T result = FPProcessNaNs3(a, op1, op2);
3061 T sign_a = copysign(1.0, a);
3062 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
3063 bool isinf_prod = std::isinf(op1) || std::isinf(op2);
3064 bool operation_generates_nan =
3065 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0
3066 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
3067 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
3069 if (std::isnan(result)) {
3070 // Generated NaNs override quiet NaNs propagated from a.
3071 if (operation_generates_nan && IsQuietNaN(a)) {
3072 return FPDefaultNaN<T>();
3078 // If the operation would produce a NaN, return the default NaN.
3079 if (operation_generates_nan) {
3080 return FPDefaultNaN<T>();
3083 // Work around broken fma implementations for exact zero results: The sign of
3084 // exact 0.0 results is positive unless both a and op1 * op2 are negative.
3085 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
3086 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
3089 result = FusedMultiplyAdd(op1, op2, a);
3090 DCHECK(!std::isnan(result));
3092 // Work around broken fma implementations for rounded zero results: If a is
3093 // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
3094 if ((a == 0.0) && (result == 0.0)) {
3095 return copysign(0.0, sign_prod);
3102 template <typename T>
3103 T Simulator::FPSqrt(T op) {
3104 if (std::isnan(op)) {
3105 return FPProcessNaN(op);
3106 } else if (op < 0.0) {
3107 return FPDefaultNaN<T>();
3109 return fast_sqrt(op);
3114 template <typename T>
3115 T Simulator::FPSub(T op1, T op2) {
3116 // NaNs should be handled elsewhere.
3117 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3119 if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
3120 // inf - inf returns the default NaN.
3121 return FPDefaultNaN<T>();
3123 // Other cases should be handled by standard arithmetic.
3129 template <typename T>
3130 T Simulator::FPProcessNaN(T op) {
3131 DCHECK(std::isnan(op));
3132 return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
3136 template <typename T>
3137 T Simulator::FPProcessNaNs(T op1, T op2) {
3138 if (IsSignallingNaN(op1)) {
3139 return FPProcessNaN(op1);
3140 } else if (IsSignallingNaN(op2)) {
3141 return FPProcessNaN(op2);
3142 } else if (std::isnan(op1)) {
3143 DCHECK(IsQuietNaN(op1));
3144 return FPProcessNaN(op1);
3145 } else if (std::isnan(op2)) {
3146 DCHECK(IsQuietNaN(op2));
3147 return FPProcessNaN(op2);
3154 template <typename T>
3155 T Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
3156 if (IsSignallingNaN(op1)) {
3157 return FPProcessNaN(op1);
3158 } else if (IsSignallingNaN(op2)) {
3159 return FPProcessNaN(op2);
3160 } else if (IsSignallingNaN(op3)) {
3161 return FPProcessNaN(op3);
3162 } else if (std::isnan(op1)) {
3163 DCHECK(IsQuietNaN(op1));
3164 return FPProcessNaN(op1);
3165 } else if (std::isnan(op2)) {
3166 DCHECK(IsQuietNaN(op2));
3167 return FPProcessNaN(op2);
3168 } else if (std::isnan(op3)) {
3169 DCHECK(IsQuietNaN(op3));
3170 return FPProcessNaN(op3);
3177 bool Simulator::FPProcessNaNs(Instruction* instr) {
3178 unsigned fd = instr->Rd();
3179 unsigned fn = instr->Rn();
3180 unsigned fm = instr->Rm();
3183 if (instr->Mask(FP64) == FP64) {
3184 double result = FPProcessNaNs(dreg(fn), dreg(fm));
3185 if (std::isnan(result)) {
3186 set_dreg(fd, result);
3190 float result = FPProcessNaNs(sreg(fn), sreg(fm));
3191 if (std::isnan(result)) {
3192 set_sreg(fd, result);
3201 void Simulator::VisitSystem(Instruction* instr) {
3202 // Some system instructions hijack their Op and Cp fields to represent a
3203 // range of immediates instead of indicating a different instruction. This
3204 // makes the decoding tricky.
3205 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3206 switch (instr->Mask(SystemSysRegMask)) {
3208 switch (instr->ImmSystemRegister()) {
3209 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
3210 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
3211 default: UNIMPLEMENTED();
3216 switch (instr->ImmSystemRegister()) {
3218 nzcv().SetRawValue(wreg(instr->Rt()));
3219 LogSystemRegister(NZCV);
3222 fpcr().SetRawValue(wreg(instr->Rt()));
3223 LogSystemRegister(FPCR);
3225 default: UNIMPLEMENTED();
3230 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3231 DCHECK(instr->Mask(SystemHintMask) == HINT);
3232 switch (instr->ImmHint()) {
3234 default: UNIMPLEMENTED();
3236 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3237 __sync_synchronize();
3244 bool Simulator::GetValue(const char* desc, int64_t* value) {
3245 int regnum = CodeFromName(desc);
3247 unsigned code = regnum;
3248 if (code == kZeroRegCode) {
3249 // Catch the zero register and return 0.
3252 } else if (code == kSPRegInternalCode) {
3253 // Translate the stack pointer code to 31, for Reg31IsStackPointer.
3256 if (desc[0] == 'w') {
3257 *value = wreg(code, Reg31IsStackPointer);
3259 *value = xreg(code, Reg31IsStackPointer);
3262 } else if (strncmp(desc, "0x", 2) == 0) {
3263 return SScanF(desc + 2, "%" SCNx64,
3264 reinterpret_cast<uint64_t*>(value)) == 1;
3266 return SScanF(desc, "%" SCNu64,
3267 reinterpret_cast<uint64_t*>(value)) == 1;
3272 bool Simulator::PrintValue(const char* desc) {
3273 if (strcmp(desc, "csp") == 0) {
3274 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3275 PrintF(stream_, "%s csp:%s 0x%016" PRIx64 "%s\n",
3276 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3278 } else if (strcmp(desc, "wcsp") == 0) {
3279 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3280 PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n",
3281 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3285 int i = CodeFromName(desc);
3286 STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters);
3287 if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false;
3289 if (desc[0] == 'v') {
3290 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3291 clr_fpreg_name, VRegNameForCode(i),
3292 clr_fpreg_value, double_to_rawbits(dreg(i)),
3294 clr_fpreg_name, DRegNameForCode(i),
3295 clr_fpreg_value, dreg(i),
3296 clr_fpreg_name, SRegNameForCode(i),
3297 clr_fpreg_value, sreg(i),
3300 } else if (desc[0] == 'd') {
3301 PrintF(stream_, "%s %s:%s %g%s\n",
3302 clr_fpreg_name, DRegNameForCode(i),
3303 clr_fpreg_value, dreg(i),
3306 } else if (desc[0] == 's') {
3307 PrintF(stream_, "%s %s:%s %g%s\n",
3308 clr_fpreg_name, SRegNameForCode(i),
3309 clr_fpreg_value, sreg(i),
3312 } else if (desc[0] == 'w') {
3313 PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n",
3314 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3317 // X register names have a wide variety of starting characters, but anything
3318 // else will be an X register.
3319 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n",
3320 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
3326 void Simulator::Debug() {
3327 #define COMMAND_SIZE 63
3328 #define ARG_SIZE 255
3331 #define XSTR(a) STR(a)
3333 char cmd[COMMAND_SIZE + 1];
3334 char arg1[ARG_SIZE + 1];
3335 char arg2[ARG_SIZE + 1];
3336 char* argv[3] = { cmd, arg1, arg2 };
3338 // Make sure to have a proper terminating character if reaching the limit.
3339 cmd[COMMAND_SIZE] = 0;
3344 bool cleared_log_disasm_bit = false;
3347 // Disassemble the next instruction to execute before doing anything else.
3348 PrintInstructionsAt(pc_, 1);
3349 // Read the command line.
3350 char* line = ReadLine("sim> ");
3354 // Repeat last command by default.
3355 char* last_input = last_debugger_input();
3356 if (strcmp(line, "\n") == 0 && (last_input != NULL)) {
3360 // Update the latest command ran
3361 set_last_debugger_input(line);
3364 // Use sscanf to parse the individual parts of the command line. At the
3365 // moment no command expects more than two parameters.
3366 int argc = SScanF(line,
3367 "%" XSTR(COMMAND_SIZE) "s "
3368 "%" XSTR(ARG_SIZE) "s "
3369 "%" XSTR(ARG_SIZE) "s",
3372 // stepi / si ------------------------------------------------------------
3373 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
3374 // We are about to execute instructions, after which by default we
3375 // should increment the pc_. If it was set when reaching this debug
3376 // instruction, it has not been cleared because this instruction has not
3377 // completed yet. So clear it manually.
3378 pc_modified_ = false;
3381 ExecuteInstruction();
3383 int64_t number_of_instructions_to_execute = 1;
3384 GetValue(arg1, &number_of_instructions_to_execute);
3386 set_log_parameters(log_parameters() | LOG_DISASM);
3387 while (number_of_instructions_to_execute-- > 0) {
3388 ExecuteInstruction();
3390 set_log_parameters(log_parameters() & ~LOG_DISASM);
3394 // If it was necessary, the pc has already been updated or incremented
3395 // when executing the instruction. So we do not want it to be updated
3396 // again. It will be cleared when exiting.
3397 pc_modified_ = true;
3399 // next / n --------------------------------------------------------------
3400 } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) {
3401 // Tell the simulator to break after the next executed BL.
3402 break_on_next_ = true;
3406 // continue / cont / c ---------------------------------------------------
3407 } else if ((strcmp(cmd, "continue") == 0) ||
3408 (strcmp(cmd, "cont") == 0) ||
3409 (strcmp(cmd, "c") == 0)) {
3410 // Leave the debugger shell.
3413 // disassemble / disasm / di ---------------------------------------------
3414 } else if (strcmp(cmd, "disassemble") == 0 ||
3415 strcmp(cmd, "disasm") == 0 ||
3416 strcmp(cmd, "di") == 0) {
3417 int64_t n_of_instrs_to_disasm = 10; // default value.
3418 int64_t address = reinterpret_cast<int64_t>(pc_); // default value.
3419 if (argc >= 2) { // disasm <n of instrs>
3420 GetValue(arg1, &n_of_instrs_to_disasm);
3422 if (argc >= 3) { // disasm <n of instrs> <address>
3423 GetValue(arg2, &address);
3427 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3428 n_of_instrs_to_disasm);
3431 // print / p -------------------------------------------------------------
3432 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3434 if (strcmp(arg1, "all") == 0) {
3438 if (!PrintValue(arg1)) {
3439 PrintF("%s unrecognized\n", arg1);
3444 "print <register>\n"
3445 " Print the content of a register. (alias 'p')\n"
3446 " 'print all' will print all registers.\n"
3447 " Use 'printobject' to get more details about the value.\n");
3450 // printobject / po ------------------------------------------------------
3451 } else if ((strcmp(cmd, "printobject") == 0) ||
3452 (strcmp(cmd, "po") == 0)) {
3455 OFStream os(stdout);
3456 if (GetValue(arg1, &value)) {
3457 Object* obj = reinterpret_cast<Object*>(value);
3458 os << arg1 << ": \n";
3463 os << Brief(obj) << "\n";
3466 os << arg1 << " unrecognized\n";
3469 PrintF("printobject <value>\n"
3470 "printobject <register>\n"
3471 " Print details about the value. (alias 'po')\n");
3474 // stack / mem ----------------------------------------------------------
3475 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
3476 int64_t* cur = NULL;
3477 int64_t* end = NULL;
3480 if (strcmp(cmd, "stack") == 0) {
3481 cur = reinterpret_cast<int64_t*>(jssp());
3485 if (!GetValue(arg1, &value)) {
3486 PrintF("%s unrecognized\n", arg1);
3489 cur = reinterpret_cast<int64_t*>(value);
3494 if (argc == next_arg) {
3496 } else if (argc == next_arg + 1) {
3497 if (!GetValue(argv[next_arg], &words)) {
3498 PrintF("%s unrecognized\n", argv[next_arg]);
3499 PrintF("Printing 10 double words by default");
3508 PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64,
3509 reinterpret_cast<uint64_t>(cur), *cur, *cur);
3510 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
3511 int64_t value = *cur;
3512 Heap* current_heap = v8::internal::Isolate::Current()->heap();
3513 if (((value & 1) == 0) || current_heap->Contains(obj)) {
3515 if ((value & kSmiTagMask) == 0) {
3516 STATIC_ASSERT(kSmiValueSize == 32);
3517 int32_t untagged = (value >> kSmiShift) & 0xffffffff;
3518 PrintF("smi %" PRId32, untagged);
3528 // trace / t -------------------------------------------------------------
3529 } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) {
3530 if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
3531 (LOG_DISASM | LOG_REGS)) {
3532 PrintF("Enabling disassembly and registers tracing\n");
3533 set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
3535 PrintF("Disabling disassembly and registers tracing\n");
3536 set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
3539 // break / b -------------------------------------------------------------
3540 } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) {
3543 if (GetValue(arg1, &value)) {
3544 SetBreakpoint(reinterpret_cast<Instruction*>(value));
3546 PrintF("%s unrecognized\n", arg1);
3550 PrintF("Use `break <address>` to set or disable a breakpoint\n");
3553 // gdb -------------------------------------------------------------------
3554 } else if (strcmp(cmd, "gdb") == 0) {
3555 PrintF("Relinquishing control to gdb.\n");
3556 base::OS::DebugBreak();
3557 PrintF("Regaining control from gdb.\n");
3559 // sysregs ---------------------------------------------------------------
3560 } else if (strcmp(cmd, "sysregs") == 0) {
3561 PrintSystemRegisters();
3563 // help / h --------------------------------------------------------------
3564 } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) {
3568 " Step <n> instructions.\n"
3570 " Continue execution until a BL instruction is reached.\n"
3571 " At this point a breakpoint is set just after this BL.\n"
3572 " Then execution is resumed. It will probably later hit the\n"
3573 " breakpoint just set.\n"
3574 "continue / cont / c\n"
3575 " Continue execution from here.\n"
3576 "disassemble / disasm / di\n"
3577 " disassemble <n> <address>\n"
3578 " Disassemble <n> instructions from current <address>.\n"
3579 " By default <n> is 20 and <address> is the current pc.\n"
3581 " print <register>\n"
3582 " Print the content of a register.\n"
3583 " 'print all' will print all registers.\n"
3584 " Use 'printobject' to get more details about the value.\n"
3585 "printobject / po\n"
3586 " printobject <value>\n"
3587 " printobject <register>\n"
3588 " Print details about the value.\n"
3590 " stack [<words>]\n"
3591 " Dump stack content, default dump 10 words\n"
3593 " mem <address> [<words>]\n"
3594 " Dump memory content, default dump 10 words\n"
3596 " Toggle disassembly and register tracing\n"
3598 " break : list all breakpoints\n"
3599 " break <address> : set / enable / disable a breakpoint.\n"
3603 " Print all system registers (including NZCV).\n");
3605 PrintF("Unknown command: %s\n", cmd);
3606 PrintF("Use 'help' for more information.\n");
3609 if (cleared_log_disasm_bit == true) {
3610 set_log_parameters(log_parameters_ | LOG_DISASM);
3616 void Simulator::VisitException(Instruction* instr) {
3617 switch (instr->Mask(ExceptionMask)) {
3619 if (instr->ImmException() == kImmExceptionIsDebug) {
3620 // Read the arguments encoded inline in the instruction stream.
3622 uint32_t parameters;
3625 pc_->InstructionAtOffset(kDebugCodeOffset),
3628 pc_->InstructionAtOffset(kDebugParamsOffset),
3629 sizeof(parameters));
3630 char const *message =
3631 reinterpret_cast<char const*>(
3632 pc_->InstructionAtOffset(kDebugMessageOffset));
3634 // Always print something when we hit a debug point that breaks.
3635 // We are going to break, so printing something is not an issue in
3637 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3638 if (message != NULL) {
3640 "# %sDebugger hit %d: %s%s%s\n",
3648 "# %sDebugger hit %d.%s\n",
3656 switch (parameters & kDebuggerTracingDirectivesMask) {
3658 set_log_parameters(log_parameters() | parameters);
3659 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3660 if (parameters & LOG_REGS) { PrintRegisters(); }
3661 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); }
3664 set_log_parameters(log_parameters() & ~parameters);
3666 case TRACE_OVERRIDE:
3667 set_log_parameters(parameters);
3670 // We don't support a one-shot LOG_DISASM.
3671 DCHECK((parameters & LOG_DISASM) == 0);
3672 // Don't print information that is already being traced.
3673 parameters &= ~log_parameters();
3674 // Print the requested information.
3675 if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3676 if (parameters & LOG_REGS) PrintRegisters();
3677 if (parameters & LOG_FP_REGS) PrintFPRegisters();
3680 // The stop parameters are inlined in the code. Skip them:
3681 // - Skip to the end of the message string.
3682 size_t size = kDebugMessageOffset + strlen(message) + 1;
3683 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize));
3684 // - Verify that the unreachable marker is present.
3685 DCHECK(pc_->Mask(ExceptionMask) == HLT);
3686 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable);
3687 // - Skip past the unreachable marker.
3688 set_pc(pc_->following());
3690 // Check if the debugger should break.
3691 if (parameters & BREAK) Debug();
3693 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3694 DoRuntimeCall(instr);
3695 } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3698 } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3699 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3700 reinterpret_cast<void*>(pc_));
3704 base::OS::DebugBreak();
3715 void Simulator::DoPrintf(Instruction* instr) {
3716 DCHECK((instr->Mask(ExceptionMask) == HLT) &&
3717 (instr->ImmException() == kImmExceptionIsPrintf));
3719 // Read the arguments encoded inline in the instruction stream.
3721 uint32_t arg_pattern_list;
3722 STATIC_ASSERT(sizeof(*instr) == 1);
3724 instr + kPrintfArgCountOffset,
3726 memcpy(&arg_pattern_list,
3727 instr + kPrintfArgPatternListOffset,
3728 sizeof(arg_pattern_list));
3730 DCHECK(arg_count <= kPrintfMaxArgCount);
3731 DCHECK((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
3733 // We need to call the host printf function with a set of arguments defined by
3734 // arg_pattern_list. Because we don't know the types and sizes of the
3735 // arguments, this is very difficult to do in a robust and portable way. To
3736 // work around the problem, we pick apart the format string, and print one
3737 // format placeholder at a time.
3739 // Allocate space for the format string. We take a copy, so we can modify it.
3740 // Leave enough space for one extra character per expected argument (plus the
3741 // '\0' termination).
3742 const char * format_base = reg<const char *>(0);
3743 DCHECK(format_base != NULL);
3744 size_t length = strlen(format_base) + 1;
3745 char * const format = new char[length + arg_count];
3747 // A list of chunks, each with exactly one format placeholder.
3748 const char * chunks[kPrintfMaxArgCount];
3750 // Copy the format string and search for format placeholders.
3751 uint32_t placeholder_count = 0;
3752 char * format_scratch = format;
3753 for (size_t i = 0; i < length; i++) {
3754 if (format_base[i] != '%') {
3755 *format_scratch++ = format_base[i];
3757 if (format_base[i + 1] == '%') {
3758 // Ignore explicit "%%" sequences.
3759 *format_scratch++ = format_base[i];
3761 if (placeholder_count == 0) {
3762 // The first chunk is passed to printf using "%s", so we need to
3763 // unescape "%%" sequences in this chunk. (Just skip the next '%'.)
3766 // Otherwise, pass through "%%" unchanged.
3767 *format_scratch++ = format_base[++i];
3770 CHECK(placeholder_count < arg_count);
3771 // Insert '\0' before placeholders, and store their locations.
3772 *format_scratch++ = '\0';
3773 chunks[placeholder_count++] = format_scratch;
3774 *format_scratch++ = format_base[i];
3778 DCHECK(format_scratch <= (format + length + arg_count));
3779 CHECK(placeholder_count == arg_count);
3781 // Finally, call printf with each chunk, passing the appropriate register
3782 // argument. Normally, printf returns the number of bytes transmitted, so we
3783 // can emulate a single printf call by adding the result from each chunk. If
3784 // any call returns a negative (error) value, though, just return that value.
3786 fprintf(stream_, "%s", clr_printf);
3788 // Because '\0' is inserted before each placeholder, the first string in
3789 // 'format' contains no format placeholders and should be printed literally.
3790 int result = fprintf(stream_, "%s", format);
3791 int pcs_r = 1; // Start at x1. x0 holds the format string.
3792 int pcs_f = 0; // Start at d0.
3794 for (uint32_t i = 0; i < placeholder_count; i++) {
3795 int part_result = -1;
3797 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
3798 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
3799 switch (arg_pattern) {
3801 part_result = fprintf(stream_, chunks[i], wreg(pcs_r++));
3804 part_result = fprintf(stream_, chunks[i], xreg(pcs_r++));
3807 part_result = fprintf(stream_, chunks[i], dreg(pcs_f++));
3809 default: UNREACHABLE();
3812 if (part_result < 0) {
3813 // Handle error values.
3814 result = part_result;
3818 result += part_result;
3822 fprintf(stream_, "%s", clr_normal);
3825 CorruptAllCallerSavedCPURegisters();
3828 // Printf returns its result in x0 (just like the C library's printf).
3829 set_xreg(0, result);
3831 // The printf parameters are inlined in the code, so skip them.
3832 set_pc(instr->InstructionAtOffset(kPrintfLength));
3834 // Set LR as if we'd just called a native printf function.
3841 #endif // USE_SIMULATOR
3843 } // namespace internal
3846 #endif // V8_TARGET_ARCH_ARM64