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