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