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