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