1 // Copyright 2012 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 <stdarg.h> 6 #include <stdlib.h> 7 #include <cmath> 8 9 #if V8_TARGET_ARCH_ARM 10 11 #include "src/arm/constants-arm.h" 12 #include "src/arm/simulator-arm.h" 13 #include "src/assembler.h" 14 #include "src/base/bits.h" 15 #include "src/codegen.h" 16 #include "src/disasm.h" 17 #include "src/runtime/runtime-utils.h" 18 19 #if defined(USE_SIMULATOR) 20 21 // Only build the simulator if not compiling for real ARM hardware. 22 namespace v8 { 23 namespace internal { 24 25 // static 26 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ = 27 LAZY_INSTANCE_INITIALIZER; 28 29 // This macro provides a platform independent use of sscanf. The reason for 30 // SScanF not being implemented in a platform independent way through 31 // ::v8::internal::OS in the same way as SNPrintF is that the 32 // Windows C Run-Time Library does not provide vsscanf. 33 #define SScanF sscanf // NOLINT 34 35 // The ArmDebugger class is used by the simulator while debugging simulated ARM 36 // code. 37 class ArmDebugger { 38 public: 39 explicit ArmDebugger(Simulator* sim) : sim_(sim) { } 40 41 void Stop(Instruction* instr); 42 void Debug(); 43 44 private: 45 static const Instr kBreakpointInstr = 46 (al | (7*B25) | (1*B24) | kBreakpoint); 47 static const Instr kNopInstr = (al | (13*B21)); 48 49 Simulator* sim_; 50 51 int32_t GetRegisterValue(int regnum); 52 double GetRegisterPairDoubleValue(int regnum); 53 double GetVFPDoubleRegisterValue(int regnum); 54 bool GetValue(const char* desc, int32_t* value); 55 bool GetVFPSingleValue(const char* desc, float* value); 56 bool GetVFPDoubleValue(const char* desc, double* value); 57 58 // Set or delete a breakpoint. Returns true if successful. 59 bool SetBreakpoint(Instruction* breakpc); 60 bool DeleteBreakpoint(Instruction* breakpc); 61 62 // Undo and redo all breakpoints. This is needed to bracket disassembly and 63 // execution to skip past breakpoints when run from the debugger. 64 void UndoBreakpoints(); 65 void RedoBreakpoints(); 66 }; 67 68 void ArmDebugger::Stop(Instruction* instr) { 69 // Get the stop code. 70 uint32_t code = instr->SvcValue() & kStopCodeMask; 71 // Print the stop message and code if it is not the default code. 72 if (code != kMaxStopCode) { 73 PrintF("Simulator hit stop %u\n", code); 74 } else { 75 PrintF("Simulator hit\n"); 76 } 77 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 78 Debug(); 79 } 80 81 int32_t ArmDebugger::GetRegisterValue(int regnum) { 82 if (regnum == kPCRegister) { 83 return sim_->get_pc(); 84 } else { 85 return sim_->get_register(regnum); 86 } 87 } 88 89 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) { 90 return sim_->get_double_from_register_pair(regnum); 91 } 92 93 94 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { 95 return sim_->get_double_from_d_register(regnum); 96 } 97 98 99 bool ArmDebugger::GetValue(const char* desc, int32_t* value) { 100 int regnum = Registers::Number(desc); 101 if (regnum != kNoRegister) { 102 *value = GetRegisterValue(regnum); 103 return true; 104 } else { 105 if (strncmp(desc, "0x", 2) == 0) { 106 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; 107 } else { 108 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; 109 } 110 } 111 return false; 112 } 113 114 115 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) { 116 bool is_double; 117 int regnum = VFPRegisters::Number(desc, &is_double); 118 if (regnum != kNoRegister && !is_double) { 119 *value = sim_->get_float_from_s_register(regnum); 120 return true; 121 } 122 return false; 123 } 124 125 126 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) { 127 bool is_double; 128 int regnum = VFPRegisters::Number(desc, &is_double); 129 if (regnum != kNoRegister && is_double) { 130 *value = sim_->get_double_from_d_register(regnum); 131 return true; 132 } 133 return false; 134 } 135 136 137 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) { 138 // Check if a breakpoint can be set. If not return without any side-effects. 139 if (sim_->break_pc_ != NULL) { 140 return false; 141 } 142 143 // Set the breakpoint. 144 sim_->break_pc_ = breakpc; 145 sim_->break_instr_ = breakpc->InstructionBits(); 146 // Not setting the breakpoint instruction in the code itself. It will be set 147 // when the debugger shell continues. 148 return true; 149 } 150 151 152 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) { 153 if (sim_->break_pc_ != NULL) { 154 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 155 } 156 157 sim_->break_pc_ = NULL; 158 sim_->break_instr_ = 0; 159 return true; 160 } 161 162 163 void ArmDebugger::UndoBreakpoints() { 164 if (sim_->break_pc_ != NULL) { 165 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 166 } 167 } 168 169 170 void ArmDebugger::RedoBreakpoints() { 171 if (sim_->break_pc_ != NULL) { 172 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 173 } 174 } 175 176 177 void ArmDebugger::Debug() { 178 intptr_t last_pc = -1; 179 bool done = false; 180 181 #define COMMAND_SIZE 63 182 #define ARG_SIZE 255 183 184 #define STR(a) #a 185 #define XSTR(a) STR(a) 186 187 char cmd[COMMAND_SIZE + 1]; 188 char arg1[ARG_SIZE + 1]; 189 char arg2[ARG_SIZE + 1]; 190 char* argv[3] = { cmd, arg1, arg2 }; 191 192 // make sure to have a proper terminating character if reaching the limit 193 cmd[COMMAND_SIZE] = 0; 194 arg1[ARG_SIZE] = 0; 195 arg2[ARG_SIZE] = 0; 196 197 // Undo all set breakpoints while running in the debugger shell. This will 198 // make them invisible to all commands. 199 UndoBreakpoints(); 200 201 while (!done && !sim_->has_bad_pc()) { 202 if (last_pc != sim_->get_pc()) { 203 disasm::NameConverter converter; 204 disasm::Disassembler dasm(converter); 205 // use a reasonably large buffer 206 v8::internal::EmbeddedVector<char, 256> buffer; 207 dasm.InstructionDecode(buffer, 208 reinterpret_cast<byte*>(sim_->get_pc())); 209 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start()); 210 last_pc = sim_->get_pc(); 211 } 212 char* line = ReadLine("sim> "); 213 if (line == NULL) { 214 break; 215 } else { 216 char* last_input = sim_->last_debugger_input(); 217 if (strcmp(line, "\n") == 0 && last_input != NULL) { 218 line = last_input; 219 } else { 220 // Ownership is transferred to sim_; 221 sim_->set_last_debugger_input(line); 222 } 223 // Use sscanf to parse the individual parts of the command line. At the 224 // moment no command expects more than two parameters. 225 int argc = SScanF(line, 226 "%" XSTR(COMMAND_SIZE) "s " 227 "%" XSTR(ARG_SIZE) "s " 228 "%" XSTR(ARG_SIZE) "s", 229 cmd, arg1, arg2); 230 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 231 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 232 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 233 // Execute the one instruction we broke at with breakpoints disabled. 234 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 235 // Leave the debugger shell. 236 done = true; 237 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 238 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) { 239 int32_t value; 240 float svalue; 241 double dvalue; 242 if (strcmp(arg1, "all") == 0) { 243 for (int i = 0; i < kNumRegisters; i++) { 244 value = GetRegisterValue(i); 245 PrintF( 246 "%3s: 0x%08x %10d", 247 RegisterConfiguration::Crankshaft()->GetGeneralRegisterName( 248 i), 249 value, value); 250 if ((argc == 3 && strcmp(arg2, "fp") == 0) && 251 i < 8 && 252 (i % 2) == 0) { 253 dvalue = GetRegisterPairDoubleValue(i); 254 PrintF(" (%f)\n", dvalue); 255 } else { 256 PrintF("\n"); 257 } 258 } 259 for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) { 260 dvalue = GetVFPDoubleRegisterValue(i); 261 uint64_t as_words = bit_cast<uint64_t>(dvalue); 262 PrintF("%3s: %f 0x%08x %08x\n", 263 VFPRegisters::Name(i, true), 264 dvalue, 265 static_cast<uint32_t>(as_words >> 32), 266 static_cast<uint32_t>(as_words & 0xffffffff)); 267 } 268 } else { 269 if (GetValue(arg1, &value)) { 270 PrintF("%s: 0x%08x %d \n", arg1, value, value); 271 } else if (GetVFPSingleValue(arg1, &svalue)) { 272 uint32_t as_word = bit_cast<uint32_t>(svalue); 273 PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word); 274 } else if (GetVFPDoubleValue(arg1, &dvalue)) { 275 uint64_t as_words = bit_cast<uint64_t>(dvalue); 276 PrintF("%s: %f 0x%08x %08x\n", 277 arg1, 278 dvalue, 279 static_cast<uint32_t>(as_words >> 32), 280 static_cast<uint32_t>(as_words & 0xffffffff)); 281 } else { 282 PrintF("%s unrecognized\n", arg1); 283 } 284 } 285 } else { 286 PrintF("print <register>\n"); 287 } 288 } else if ((strcmp(cmd, "po") == 0) 289 || (strcmp(cmd, "printobject") == 0)) { 290 if (argc == 2) { 291 int32_t value; 292 OFStream os(stdout); 293 if (GetValue(arg1, &value)) { 294 Object* obj = reinterpret_cast<Object*>(value); 295 os << arg1 << ": \n"; 296 #ifdef DEBUG 297 obj->Print(os); 298 os << "\n"; 299 #else 300 os << Brief(obj) << "\n"; 301 #endif 302 } else { 303 os << arg1 << " unrecognized\n"; 304 } 305 } else { 306 PrintF("printobject <value>\n"); 307 } 308 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 309 int32_t* cur = NULL; 310 int32_t* end = NULL; 311 int next_arg = 1; 312 313 if (strcmp(cmd, "stack") == 0) { 314 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp)); 315 } else { // "mem" 316 int32_t value; 317 if (!GetValue(arg1, &value)) { 318 PrintF("%s unrecognized\n", arg1); 319 continue; 320 } 321 cur = reinterpret_cast<int32_t*>(value); 322 next_arg++; 323 } 324 325 int32_t words; 326 if (argc == next_arg) { 327 words = 10; 328 } else { 329 if (!GetValue(argv[next_arg], &words)) { 330 words = 10; 331 } 332 } 333 end = cur + words; 334 335 while (cur < end) { 336 PrintF(" 0x%08" V8PRIxPTR ": 0x%08x %10d", 337 reinterpret_cast<intptr_t>(cur), *cur, *cur); 338 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 339 int value = *cur; 340 Heap* current_heap = sim_->isolate_->heap(); 341 if (((value & 1) == 0) || 342 current_heap->ContainsSlow(obj->address())) { 343 PrintF(" ("); 344 if ((value & 1) == 0) { 345 PrintF("smi %d", value / 2); 346 } else { 347 obj->ShortPrint(); 348 } 349 PrintF(")"); 350 } 351 PrintF("\n"); 352 cur++; 353 } 354 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) { 355 disasm::NameConverter converter; 356 disasm::Disassembler dasm(converter); 357 // use a reasonably large buffer 358 v8::internal::EmbeddedVector<char, 256> buffer; 359 360 byte* prev = NULL; 361 byte* cur = NULL; 362 byte* end = NULL; 363 364 if (argc == 1) { 365 cur = reinterpret_cast<byte*>(sim_->get_pc()); 366 end = cur + (10 * Instruction::kInstrSize); 367 } else if (argc == 2) { 368 int regnum = Registers::Number(arg1); 369 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) { 370 // The argument is an address or a register name. 371 int32_t value; 372 if (GetValue(arg1, &value)) { 373 cur = reinterpret_cast<byte*>(value); 374 // Disassemble 10 instructions at <arg1>. 375 end = cur + (10 * Instruction::kInstrSize); 376 } 377 } else { 378 // The argument is the number of instructions. 379 int32_t value; 380 if (GetValue(arg1, &value)) { 381 cur = reinterpret_cast<byte*>(sim_->get_pc()); 382 // Disassemble <arg1> instructions. 383 end = cur + (value * Instruction::kInstrSize); 384 } 385 } 386 } else { 387 int32_t value1; 388 int32_t value2; 389 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 390 cur = reinterpret_cast<byte*>(value1); 391 end = cur + (value2 * Instruction::kInstrSize); 392 } 393 } 394 395 while (cur < end) { 396 prev = cur; 397 cur += dasm.InstructionDecode(buffer, cur); 398 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(prev), 399 buffer.start()); 400 } 401 } else if (strcmp(cmd, "gdb") == 0) { 402 PrintF("relinquishing control to gdb\n"); 403 v8::base::OS::DebugBreak(); 404 PrintF("regaining control from gdb\n"); 405 } else if (strcmp(cmd, "break") == 0) { 406 if (argc == 2) { 407 int32_t value; 408 if (GetValue(arg1, &value)) { 409 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 410 PrintF("setting breakpoint failed\n"); 411 } 412 } else { 413 PrintF("%s unrecognized\n", arg1); 414 } 415 } else { 416 PrintF("break <address>\n"); 417 } 418 } else if (strcmp(cmd, "del") == 0) { 419 if (!DeleteBreakpoint(NULL)) { 420 PrintF("deleting breakpoint failed\n"); 421 } 422 } else if (strcmp(cmd, "flags") == 0) { 423 PrintF("N flag: %d; ", sim_->n_flag_); 424 PrintF("Z flag: %d; ", sim_->z_flag_); 425 PrintF("C flag: %d; ", sim_->c_flag_); 426 PrintF("V flag: %d\n", sim_->v_flag_); 427 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_); 428 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_); 429 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_); 430 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_); 431 PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_); 432 } else if (strcmp(cmd, "stop") == 0) { 433 int32_t value; 434 intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize; 435 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 436 Instruction* msg_address = 437 reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize); 438 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 439 // Remove the current stop. 440 if (sim_->isStopInstruction(stop_instr)) { 441 stop_instr->SetInstructionBits(kNopInstr); 442 msg_address->SetInstructionBits(kNopInstr); 443 } else { 444 PrintF("Not at debugger stop.\n"); 445 } 446 } else if (argc == 3) { 447 // Print information about all/the specified breakpoint(s). 448 if (strcmp(arg1, "info") == 0) { 449 if (strcmp(arg2, "all") == 0) { 450 PrintF("Stop information:\n"); 451 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 452 sim_->PrintStopInfo(i); 453 } 454 } else if (GetValue(arg2, &value)) { 455 sim_->PrintStopInfo(value); 456 } else { 457 PrintF("Unrecognized argument.\n"); 458 } 459 } else if (strcmp(arg1, "enable") == 0) { 460 // Enable all/the specified breakpoint(s). 461 if (strcmp(arg2, "all") == 0) { 462 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 463 sim_->EnableStop(i); 464 } 465 } else if (GetValue(arg2, &value)) { 466 sim_->EnableStop(value); 467 } else { 468 PrintF("Unrecognized argument.\n"); 469 } 470 } else if (strcmp(arg1, "disable") == 0) { 471 // Disable all/the specified breakpoint(s). 472 if (strcmp(arg2, "all") == 0) { 473 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 474 sim_->DisableStop(i); 475 } 476 } else if (GetValue(arg2, &value)) { 477 sim_->DisableStop(value); 478 } else { 479 PrintF("Unrecognized argument.\n"); 480 } 481 } 482 } else { 483 PrintF("Wrong usage. Use help command for more information.\n"); 484 } 485 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) { 486 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim; 487 PrintF("Trace of executed instructions is %s\n", 488 ::v8::internal::FLAG_trace_sim ? "on" : "off"); 489 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 490 PrintF("cont\n"); 491 PrintF(" continue execution (alias 'c')\n"); 492 PrintF("stepi\n"); 493 PrintF(" step one instruction (alias 'si')\n"); 494 PrintF("print <register>\n"); 495 PrintF(" print register content (alias 'p')\n"); 496 PrintF(" use register name 'all' to print all registers\n"); 497 PrintF(" add argument 'fp' to print register pair double values\n"); 498 PrintF("printobject <register>\n"); 499 PrintF(" print an object from a register (alias 'po')\n"); 500 PrintF("flags\n"); 501 PrintF(" print flags\n"); 502 PrintF("stack [<words>]\n"); 503 PrintF(" dump stack content, default dump 10 words)\n"); 504 PrintF("mem <address> [<words>]\n"); 505 PrintF(" dump memory content, default dump 10 words)\n"); 506 PrintF("disasm [<instructions>]\n"); 507 PrintF("disasm [<address/register>]\n"); 508 PrintF("disasm [[<address/register>] <instructions>]\n"); 509 PrintF(" disassemble code, default is 10 instructions\n"); 510 PrintF(" from pc (alias 'di')\n"); 511 PrintF("gdb\n"); 512 PrintF(" enter gdb\n"); 513 PrintF("break <address>\n"); 514 PrintF(" set a break point on the address\n"); 515 PrintF("del\n"); 516 PrintF(" delete the breakpoint\n"); 517 PrintF("trace (alias 't')\n"); 518 PrintF(" toogle the tracing of all executed statements\n"); 519 PrintF("stop feature:\n"); 520 PrintF(" Description:\n"); 521 PrintF(" Stops are debug instructions inserted by\n"); 522 PrintF(" the Assembler::stop() function.\n"); 523 PrintF(" When hitting a stop, the Simulator will\n"); 524 PrintF(" stop and and give control to the ArmDebugger.\n"); 525 PrintF(" The first %d stop codes are watched:\n", 526 Simulator::kNumOfWatchedStops); 527 PrintF(" - They can be enabled / disabled: the Simulator\n"); 528 PrintF(" will / won't stop when hitting them.\n"); 529 PrintF(" - The Simulator keeps track of how many times they \n"); 530 PrintF(" are met. (See the info command.) Going over a\n"); 531 PrintF(" disabled stop still increases its counter. \n"); 532 PrintF(" Commands:\n"); 533 PrintF(" stop info all/<code> : print infos about number <code>\n"); 534 PrintF(" or all stop(s).\n"); 535 PrintF(" stop enable/disable all/<code> : enables / disables\n"); 536 PrintF(" all or number <code> stop(s)\n"); 537 PrintF(" stop unstop\n"); 538 PrintF(" ignore the stop instruction at the current location\n"); 539 PrintF(" from now on\n"); 540 } else { 541 PrintF("Unknown command: %s\n", cmd); 542 } 543 } 544 } 545 546 // Add all the breakpoints back to stop execution and enter the debugger 547 // shell when hit. 548 RedoBreakpoints(); 549 550 #undef COMMAND_SIZE 551 #undef ARG_SIZE 552 553 #undef STR 554 #undef XSTR 555 } 556 557 558 static bool ICacheMatch(void* one, void* two) { 559 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); 560 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); 561 return one == two; 562 } 563 564 565 static uint32_t ICacheHash(void* key) { 566 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 567 } 568 569 570 static bool AllOnOnePage(uintptr_t start, int size) { 571 intptr_t start_page = (start & ~CachePage::kPageMask); 572 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 573 return start_page == end_page; 574 } 575 576 void Simulator::set_last_debugger_input(char* input) { 577 DeleteArray(last_debugger_input_); 578 last_debugger_input_ = input; 579 } 580 581 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache, 582 void* start_addr, size_t size) { 583 intptr_t start = reinterpret_cast<intptr_t>(start_addr); 584 int intra_line = (start & CachePage::kLineMask); 585 start -= intra_line; 586 size += intra_line; 587 size = ((size - 1) | CachePage::kLineMask) + 1; 588 int offset = (start & CachePage::kPageMask); 589 while (!AllOnOnePage(start, size - 1)) { 590 int bytes_to_flush = CachePage::kPageSize - offset; 591 FlushOnePage(i_cache, start, bytes_to_flush); 592 start += bytes_to_flush; 593 size -= bytes_to_flush; 594 DCHECK_EQ(0, start & CachePage::kPageMask); 595 offset = 0; 596 } 597 if (size != 0) { 598 FlushOnePage(i_cache, start, size); 599 } 600 } 601 602 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache, 603 void* page) { 604 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page)); 605 if (entry->value == NULL) { 606 CachePage* new_page = new CachePage(); 607 entry->value = new_page; 608 } 609 return reinterpret_cast<CachePage*>(entry->value); 610 } 611 612 613 // Flush from start up to and not including start + size. 614 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache, 615 intptr_t start, int size) { 616 DCHECK(size <= CachePage::kPageSize); 617 DCHECK(AllOnOnePage(start, size - 1)); 618 DCHECK((start & CachePage::kLineMask) == 0); 619 DCHECK((size & CachePage::kLineMask) == 0); 620 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 621 int offset = (start & CachePage::kPageMask); 622 CachePage* cache_page = GetCachePage(i_cache, page); 623 char* valid_bytemap = cache_page->ValidityByte(offset); 624 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 625 } 626 627 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache, 628 Instruction* instr) { 629 intptr_t address = reinterpret_cast<intptr_t>(instr); 630 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 631 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 632 int offset = (address & CachePage::kPageMask); 633 CachePage* cache_page = GetCachePage(i_cache, page); 634 char* cache_valid_byte = cache_page->ValidityByte(offset); 635 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 636 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 637 if (cache_hit) { 638 // Check that the data in memory matches the contents of the I-cache. 639 CHECK_EQ(0, 640 memcmp(reinterpret_cast<void*>(instr), 641 cache_page->CachedData(offset), Instruction::kInstrSize)); 642 } else { 643 // Cache miss. Load memory into the cache. 644 memcpy(cached_line, line, CachePage::kLineLength); 645 *cache_valid_byte = CachePage::LINE_VALID; 646 } 647 } 648 649 650 void Simulator::Initialize(Isolate* isolate) { 651 if (isolate->simulator_initialized()) return; 652 isolate->set_simulator_initialized(true); 653 ::v8::internal::ExternalReference::set_redirector(isolate, 654 &RedirectExternalReference); 655 } 656 657 658 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { 659 i_cache_ = isolate_->simulator_i_cache(); 660 if (i_cache_ == NULL) { 661 i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch); 662 isolate_->set_simulator_i_cache(i_cache_); 663 } 664 Initialize(isolate); 665 // Set up simulator support first. Some of this information is needed to 666 // setup the architecture state. 667 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack 668 stack_ = reinterpret_cast<char*>(malloc(stack_size)); 669 pc_modified_ = false; 670 icount_ = 0; 671 break_pc_ = NULL; 672 break_instr_ = 0; 673 674 // Set up architecture state. 675 // All registers are initialized to zero to start with. 676 for (int i = 0; i < num_registers; i++) { 677 registers_[i] = 0; 678 } 679 n_flag_ = false; 680 z_flag_ = false; 681 c_flag_ = false; 682 v_flag_ = false; 683 684 // Initializing VFP registers. 685 // All registers are initialized to zero to start with 686 // even though s_registers_ & d_registers_ share the same 687 // physical registers in the target. 688 for (int i = 0; i < num_d_registers * 2; i++) { 689 vfp_registers_[i] = 0; 690 } 691 n_flag_FPSCR_ = false; 692 z_flag_FPSCR_ = false; 693 c_flag_FPSCR_ = false; 694 v_flag_FPSCR_ = false; 695 FPSCR_rounding_mode_ = RN; 696 FPSCR_default_NaN_mode_ = false; 697 698 inv_op_vfp_flag_ = false; 699 div_zero_vfp_flag_ = false; 700 overflow_vfp_flag_ = false; 701 underflow_vfp_flag_ = false; 702 inexact_vfp_flag_ = false; 703 704 // The sp is initialized to point to the bottom (high address) of the 705 // allocated stack area. To be safe in potential stack underflows we leave 706 // some buffer below. 707 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 708 // The lr and pc are initialized to a known bad value that will cause an 709 // access violation if the simulator ever tries to execute it. 710 registers_[pc] = bad_lr; 711 registers_[lr] = bad_lr; 712 713 last_debugger_input_ = NULL; 714 } 715 716 Simulator::~Simulator() { 717 global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_); 718 free(stack_); 719 } 720 721 // When the generated code calls an external reference we need to catch that in 722 // the simulator. The external reference will be a function compiled for the 723 // host architecture. We need to call that function instead of trying to 724 // execute it with the simulator. We do that by redirecting the external 725 // reference to a svc (Supervisor Call) instruction that is handled by 726 // the simulator. We write the original destination of the jump just at a known 727 // offset from the svc instruction so the simulator knows what to call. 728 class Redirection { 729 public: 730 Redirection(Isolate* isolate, void* external_function, 731 ExternalReference::Type type) 732 : external_function_(external_function), 733 swi_instruction_(al | (0xf * B24) | kCallRtRedirected), 734 type_(type), 735 next_(NULL) { 736 next_ = isolate->simulator_redirection(); 737 Simulator::current(isolate)-> 738 FlushICache(isolate->simulator_i_cache(), 739 reinterpret_cast<void*>(&swi_instruction_), 740 Instruction::kInstrSize); 741 isolate->set_simulator_redirection(this); 742 } 743 744 void* address_of_swi_instruction() { 745 return reinterpret_cast<void*>(&swi_instruction_); 746 } 747 748 void* external_function() { return external_function_; } 749 ExternalReference::Type type() { return type_; } 750 751 static Redirection* Get(Isolate* isolate, void* external_function, 752 ExternalReference::Type type) { 753 Redirection* current = isolate->simulator_redirection(); 754 for (; current != NULL; current = current->next_) { 755 if (current->external_function_ == external_function) { 756 DCHECK_EQ(current->type(), type); 757 return current; 758 } 759 } 760 return new Redirection(isolate, external_function, type); 761 } 762 763 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 764 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 765 char* addr_of_redirection = 766 addr_of_swi - offsetof(Redirection, swi_instruction_); 767 return reinterpret_cast<Redirection*>(addr_of_redirection); 768 } 769 770 static void* ReverseRedirection(int32_t reg) { 771 Redirection* redirection = FromSwiInstruction( 772 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg))); 773 return redirection->external_function(); 774 } 775 776 static void DeleteChain(Redirection* redirection) { 777 while (redirection != nullptr) { 778 Redirection* next = redirection->next_; 779 delete redirection; 780 redirection = next; 781 } 782 } 783 784 private: 785 void* external_function_; 786 uint32_t swi_instruction_; 787 ExternalReference::Type type_; 788 Redirection* next_; 789 }; 790 791 792 // static 793 void Simulator::TearDown(base::CustomMatcherHashMap* i_cache, 794 Redirection* first) { 795 Redirection::DeleteChain(first); 796 if (i_cache != nullptr) { 797 for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr; 798 entry = i_cache->Next(entry)) { 799 delete static_cast<CachePage*>(entry->value); 800 } 801 delete i_cache; 802 } 803 } 804 805 806 void* Simulator::RedirectExternalReference(Isolate* isolate, 807 void* external_function, 808 ExternalReference::Type type) { 809 Redirection* redirection = Redirection::Get(isolate, external_function, type); 810 return redirection->address_of_swi_instruction(); 811 } 812 813 814 // Get the active Simulator for the current thread. 815 Simulator* Simulator::current(Isolate* isolate) { 816 v8::internal::Isolate::PerIsolateThreadData* isolate_data = 817 isolate->FindOrAllocatePerThreadDataForThisThread(); 818 DCHECK(isolate_data != NULL); 819 820 Simulator* sim = isolate_data->simulator(); 821 if (sim == NULL) { 822 // TODO(146): delete the simulator object when a thread/isolate goes away. 823 sim = new Simulator(isolate); 824 isolate_data->set_simulator(sim); 825 } 826 return sim; 827 } 828 829 830 // Sets the register in the architecture state. It will also deal with updating 831 // Simulator internal state for special registers such as PC. 832 void Simulator::set_register(int reg, int32_t value) { 833 DCHECK((reg >= 0) && (reg < num_registers)); 834 if (reg == pc) { 835 pc_modified_ = true; 836 } 837 registers_[reg] = value; 838 } 839 840 841 // Get the register from the architecture state. This function does handle 842 // the special case of accessing the PC register. 843 int32_t Simulator::get_register(int reg) const { 844 DCHECK((reg >= 0) && (reg < num_registers)); 845 // Stupid code added to avoid bug in GCC. 846 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949 847 if (reg >= num_registers) return 0; 848 // End stupid code. 849 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 850 } 851 852 853 double Simulator::get_double_from_register_pair(int reg) { 854 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); 855 856 double dm_val = 0.0; 857 // Read the bits from the unsigned integer register_[] array 858 // into the double precision floating point value and return it. 859 char buffer[2 * sizeof(vfp_registers_[0])]; 860 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); 861 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); 862 return(dm_val); 863 } 864 865 866 void Simulator::set_register_pair_from_double(int reg, double* value) { 867 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); 868 memcpy(registers_ + reg, value, sizeof(*value)); 869 } 870 871 872 void Simulator::set_dw_register(int dreg, const int* dbl) { 873 DCHECK((dreg >= 0) && (dreg < num_d_registers)); 874 registers_[dreg] = dbl[0]; 875 registers_[dreg + 1] = dbl[1]; 876 } 877 878 879 void Simulator::get_d_register(int dreg, uint64_t* value) { 880 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); 881 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value)); 882 } 883 884 885 void Simulator::set_d_register(int dreg, const uint64_t* value) { 886 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); 887 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value)); 888 } 889 890 891 void Simulator::get_d_register(int dreg, uint32_t* value) { 892 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); 893 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2); 894 } 895 896 897 void Simulator::set_d_register(int dreg, const uint32_t* value) { 898 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters())); 899 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2); 900 } 901 902 template <typename T> 903 void Simulator::get_q_register(int qreg, T* value) { 904 DCHECK((qreg >= 0) && (qreg < num_q_registers)); 905 memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size); 906 } 907 908 template <typename T> 909 void Simulator::set_q_register(int qreg, const T* value) { 910 DCHECK((qreg >= 0) && (qreg < num_q_registers)); 911 memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size); 912 } 913 914 915 // Raw access to the PC register. 916 void Simulator::set_pc(int32_t value) { 917 pc_modified_ = true; 918 registers_[pc] = value; 919 } 920 921 922 bool Simulator::has_bad_pc() const { 923 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); 924 } 925 926 927 // Raw access to the PC register without the special adjustment when reading. 928 int32_t Simulator::get_pc() const { 929 return registers_[pc]; 930 } 931 932 933 // Getting from and setting into VFP registers. 934 void Simulator::set_s_register(int sreg, unsigned int value) { 935 DCHECK((sreg >= 0) && (sreg < num_s_registers)); 936 vfp_registers_[sreg] = value; 937 } 938 939 940 unsigned int Simulator::get_s_register(int sreg) const { 941 DCHECK((sreg >= 0) && (sreg < num_s_registers)); 942 return vfp_registers_[sreg]; 943 } 944 945 946 template<class InputType, int register_size> 947 void Simulator::SetVFPRegister(int reg_index, const InputType& value) { 948 DCHECK(reg_index >= 0); 949 if (register_size == 1) DCHECK(reg_index < num_s_registers); 950 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters()); 951 952 char buffer[register_size * sizeof(vfp_registers_[0])]; 953 memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0])); 954 memcpy(&vfp_registers_[reg_index * register_size], buffer, 955 register_size * sizeof(vfp_registers_[0])); 956 } 957 958 959 template<class ReturnType, int register_size> 960 ReturnType Simulator::GetFromVFPRegister(int reg_index) { 961 DCHECK(reg_index >= 0); 962 if (register_size == 1) DCHECK(reg_index < num_s_registers); 963 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters()); 964 965 ReturnType value = 0; 966 char buffer[register_size * sizeof(vfp_registers_[0])]; 967 memcpy(buffer, &vfp_registers_[register_size * reg_index], 968 register_size * sizeof(vfp_registers_[0])); 969 memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0])); 970 return value; 971 } 972 973 void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask, 974 uint32_t value) { 975 // Only CPSR_f is implemented. Of that, only N, Z, C and V are implemented. 976 if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) { 977 n_flag_ = ((value & (1 << 31)) != 0); 978 z_flag_ = ((value & (1 << 30)) != 0); 979 c_flag_ = ((value & (1 << 29)) != 0); 980 v_flag_ = ((value & (1 << 28)) != 0); 981 } else { 982 UNIMPLEMENTED(); 983 } 984 } 985 986 uint32_t Simulator::GetFromSpecialRegister(SRegister reg) { 987 uint32_t result = 0; 988 // Only CPSR_f is implemented. 989 if (reg == CPSR) { 990 if (n_flag_) result |= (1 << 31); 991 if (z_flag_) result |= (1 << 30); 992 if (c_flag_) result |= (1 << 29); 993 if (v_flag_) result |= (1 << 28); 994 } else { 995 UNIMPLEMENTED(); 996 } 997 return result; 998 } 999 1000 // Runtime FP routines take: 1001 // - two double arguments 1002 // - one double argument and zero or one integer arguments. 1003 // All are consructed here from r0-r3 or d0, d1 and r0. 1004 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { 1005 if (use_eabi_hardfloat()) { 1006 *x = get_double_from_d_register(0); 1007 *y = get_double_from_d_register(1); 1008 *z = get_register(0); 1009 } else { 1010 // Registers 0 and 1 -> x. 1011 *x = get_double_from_register_pair(0); 1012 // Register 2 and 3 -> y. 1013 *y = get_double_from_register_pair(2); 1014 // Register 2 -> z 1015 *z = get_register(2); 1016 } 1017 } 1018 1019 1020 // The return value is either in r0/r1 or d0. 1021 void Simulator::SetFpResult(const double& result) { 1022 if (use_eabi_hardfloat()) { 1023 char buffer[2 * sizeof(vfp_registers_[0])]; 1024 memcpy(buffer, &result, sizeof(buffer)); 1025 // Copy result to d0. 1026 memcpy(vfp_registers_, buffer, sizeof(buffer)); 1027 } else { 1028 char buffer[2 * sizeof(registers_[0])]; 1029 memcpy(buffer, &result, sizeof(buffer)); 1030 // Copy result to r0 and r1. 1031 memcpy(registers_, buffer, sizeof(buffer)); 1032 } 1033 } 1034 1035 1036 void Simulator::TrashCallerSaveRegisters() { 1037 // We don't trash the registers with the return value. 1038 registers_[2] = 0x50Bad4U; 1039 registers_[3] = 0x50Bad4U; 1040 registers_[12] = 0x50Bad4U; 1041 } 1042 1043 1044 int Simulator::ReadW(int32_t addr, Instruction* instr) { 1045 // All supported ARM targets allow unaligned accesses, so we don't need to 1046 // check the alignment here. 1047 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1048 local_monitor_.NotifyLoad(addr); 1049 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1050 return *ptr; 1051 } 1052 1053 int Simulator::ReadExW(int32_t addr, Instruction* instr) { 1054 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1055 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word); 1056 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr, 1057 &global_monitor_processor_); 1058 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1059 return *ptr; 1060 } 1061 1062 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { 1063 // All supported ARM targets allow unaligned accesses, so we don't need to 1064 // check the alignment here. 1065 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1066 local_monitor_.NotifyStore(addr); 1067 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1068 &global_monitor_processor_); 1069 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1070 *ptr = value; 1071 } 1072 1073 int Simulator::WriteExW(int32_t addr, int value, Instruction* instr) { 1074 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1075 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) && 1076 global_monitor_.Pointer()->NotifyStoreExcl_Locked( 1077 addr, &global_monitor_processor_)) { 1078 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1079 *ptr = value; 1080 return 0; 1081 } else { 1082 return 1; 1083 } 1084 } 1085 1086 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { 1087 // All supported ARM targets allow unaligned accesses, so we don't need to 1088 // check the alignment here. 1089 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1090 local_monitor_.NotifyLoad(addr); 1091 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1092 return *ptr; 1093 } 1094 1095 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) { 1096 // All supported ARM targets allow unaligned accesses, so we don't need to 1097 // check the alignment here. 1098 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1099 local_monitor_.NotifyLoad(addr); 1100 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1101 return *ptr; 1102 } 1103 1104 uint16_t Simulator::ReadExHU(int32_t addr, Instruction* instr) { 1105 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1106 local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord); 1107 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr, 1108 &global_monitor_processor_); 1109 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1110 return *ptr; 1111 } 1112 1113 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { 1114 // All supported ARM targets allow unaligned accesses, so we don't need to 1115 // check the alignment here. 1116 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1117 local_monitor_.NotifyStore(addr); 1118 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1119 &global_monitor_processor_); 1120 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1121 *ptr = value; 1122 } 1123 1124 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { 1125 // All supported ARM targets allow unaligned accesses, so we don't need to 1126 // check the alignment here. 1127 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1128 local_monitor_.NotifyStore(addr); 1129 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1130 &global_monitor_processor_); 1131 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1132 *ptr = value; 1133 } 1134 1135 int Simulator::WriteExH(int32_t addr, uint16_t value, Instruction* instr) { 1136 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1137 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) && 1138 global_monitor_.Pointer()->NotifyStoreExcl_Locked( 1139 addr, &global_monitor_processor_)) { 1140 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1141 *ptr = value; 1142 return 0; 1143 } else { 1144 return 1; 1145 } 1146 } 1147 1148 uint8_t Simulator::ReadBU(int32_t addr) { 1149 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1150 local_monitor_.NotifyLoad(addr); 1151 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1152 return *ptr; 1153 } 1154 1155 int8_t Simulator::ReadB(int32_t addr) { 1156 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1157 local_monitor_.NotifyLoad(addr); 1158 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1159 return *ptr; 1160 } 1161 1162 uint8_t Simulator::ReadExBU(int32_t addr) { 1163 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1164 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte); 1165 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr, 1166 &global_monitor_processor_); 1167 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1168 return *ptr; 1169 } 1170 1171 void Simulator::WriteB(int32_t addr, uint8_t value) { 1172 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1173 local_monitor_.NotifyStore(addr); 1174 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1175 &global_monitor_processor_); 1176 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1177 *ptr = value; 1178 } 1179 1180 void Simulator::WriteB(int32_t addr, int8_t value) { 1181 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1182 local_monitor_.NotifyStore(addr); 1183 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1184 &global_monitor_processor_); 1185 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1186 *ptr = value; 1187 } 1188 1189 int Simulator::WriteExB(int32_t addr, uint8_t value) { 1190 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1191 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) && 1192 global_monitor_.Pointer()->NotifyStoreExcl_Locked( 1193 addr, &global_monitor_processor_)) { 1194 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1195 *ptr = value; 1196 return 0; 1197 } else { 1198 return 1; 1199 } 1200 } 1201 1202 int32_t* Simulator::ReadDW(int32_t addr) { 1203 // All supported ARM targets allow unaligned accesses, so we don't need to 1204 // check the alignment here. 1205 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1206 local_monitor_.NotifyLoad(addr); 1207 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1208 return ptr; 1209 } 1210 1211 1212 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) { 1213 // All supported ARM targets allow unaligned accesses, so we don't need to 1214 // check the alignment here. 1215 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1216 local_monitor_.NotifyStore(addr); 1217 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1218 &global_monitor_processor_); 1219 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1220 *ptr++ = value1; 1221 *ptr = value2; 1222 } 1223 1224 1225 // Returns the limit of the stack area to enable checking for stack overflows. 1226 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const { 1227 // The simulator uses a separate JS stack. If we have exhausted the C stack, 1228 // we also drop down the JS limit to reflect the exhaustion on the JS stack. 1229 if (GetCurrentStackPosition() < c_limit) { 1230 return reinterpret_cast<uintptr_t>(get_sp()); 1231 } 1232 1233 // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes 1234 // to prevent overrunning the stack when pushing values. 1235 return reinterpret_cast<uintptr_t>(stack_) + 1024; 1236 } 1237 1238 1239 // Unsupported instructions use Format to print an error and stop execution. 1240 void Simulator::Format(Instruction* instr, const char* format) { 1241 PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n", 1242 reinterpret_cast<intptr_t>(instr), format); 1243 UNIMPLEMENTED(); 1244 } 1245 1246 1247 // Checks if the current instruction should be executed based on its 1248 // condition bits. 1249 bool Simulator::ConditionallyExecute(Instruction* instr) { 1250 switch (instr->ConditionField()) { 1251 case eq: return z_flag_; 1252 case ne: return !z_flag_; 1253 case cs: return c_flag_; 1254 case cc: return !c_flag_; 1255 case mi: return n_flag_; 1256 case pl: return !n_flag_; 1257 case vs: return v_flag_; 1258 case vc: return !v_flag_; 1259 case hi: return c_flag_ && !z_flag_; 1260 case ls: return !c_flag_ || z_flag_; 1261 case ge: return n_flag_ == v_flag_; 1262 case lt: return n_flag_ != v_flag_; 1263 case gt: return !z_flag_ && (n_flag_ == v_flag_); 1264 case le: return z_flag_ || (n_flag_ != v_flag_); 1265 case al: return true; 1266 default: UNREACHABLE(); 1267 } 1268 return false; 1269 } 1270 1271 1272 // Calculate and set the Negative and Zero flags. 1273 void Simulator::SetNZFlags(int32_t val) { 1274 n_flag_ = (val < 0); 1275 z_flag_ = (val == 0); 1276 } 1277 1278 1279 // Set the Carry flag. 1280 void Simulator::SetCFlag(bool val) { 1281 c_flag_ = val; 1282 } 1283 1284 1285 // Set the oVerflow flag. 1286 void Simulator::SetVFlag(bool val) { 1287 v_flag_ = val; 1288 } 1289 1290 1291 // Calculate C flag value for additions. 1292 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) { 1293 uint32_t uleft = static_cast<uint32_t>(left); 1294 uint32_t uright = static_cast<uint32_t>(right); 1295 uint32_t urest = 0xffffffffU - uleft; 1296 1297 return (uright > urest) || 1298 (carry && (((uright + 1) > urest) || (uright > (urest - 1)))); 1299 } 1300 1301 1302 // Calculate C flag value for subtractions. 1303 bool Simulator::BorrowFrom(int32_t left, int32_t right, int32_t carry) { 1304 uint32_t uleft = static_cast<uint32_t>(left); 1305 uint32_t uright = static_cast<uint32_t>(right); 1306 1307 return (uright > uleft) || 1308 (!carry && (((uright + 1) > uleft) || (uright > (uleft - 1)))); 1309 } 1310 1311 1312 // Calculate V flag value for additions and subtractions. 1313 bool Simulator::OverflowFrom(int32_t alu_out, 1314 int32_t left, int32_t right, bool addition) { 1315 bool overflow; 1316 if (addition) { 1317 // operands have the same sign 1318 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) 1319 // and operands and result have different sign 1320 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 1321 } else { 1322 // operands have different signs 1323 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) 1324 // and first operand and result have different signs 1325 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 1326 } 1327 return overflow; 1328 } 1329 1330 1331 // Support for VFP comparisons. 1332 void Simulator::Compute_FPSCR_Flags(float val1, float val2) { 1333 if (std::isnan(val1) || std::isnan(val2)) { 1334 n_flag_FPSCR_ = false; 1335 z_flag_FPSCR_ = false; 1336 c_flag_FPSCR_ = true; 1337 v_flag_FPSCR_ = true; 1338 // All non-NaN cases. 1339 } else if (val1 == val2) { 1340 n_flag_FPSCR_ = false; 1341 z_flag_FPSCR_ = true; 1342 c_flag_FPSCR_ = true; 1343 v_flag_FPSCR_ = false; 1344 } else if (val1 < val2) { 1345 n_flag_FPSCR_ = true; 1346 z_flag_FPSCR_ = false; 1347 c_flag_FPSCR_ = false; 1348 v_flag_FPSCR_ = false; 1349 } else { 1350 // Case when (val1 > val2). 1351 n_flag_FPSCR_ = false; 1352 z_flag_FPSCR_ = false; 1353 c_flag_FPSCR_ = true; 1354 v_flag_FPSCR_ = false; 1355 } 1356 } 1357 1358 1359 void Simulator::Compute_FPSCR_Flags(double val1, double val2) { 1360 if (std::isnan(val1) || std::isnan(val2)) { 1361 n_flag_FPSCR_ = false; 1362 z_flag_FPSCR_ = false; 1363 c_flag_FPSCR_ = true; 1364 v_flag_FPSCR_ = true; 1365 // All non-NaN cases. 1366 } else if (val1 == val2) { 1367 n_flag_FPSCR_ = false; 1368 z_flag_FPSCR_ = true; 1369 c_flag_FPSCR_ = true; 1370 v_flag_FPSCR_ = false; 1371 } else if (val1 < val2) { 1372 n_flag_FPSCR_ = true; 1373 z_flag_FPSCR_ = false; 1374 c_flag_FPSCR_ = false; 1375 v_flag_FPSCR_ = false; 1376 } else { 1377 // Case when (val1 > val2). 1378 n_flag_FPSCR_ = false; 1379 z_flag_FPSCR_ = false; 1380 c_flag_FPSCR_ = true; 1381 v_flag_FPSCR_ = false; 1382 } 1383 } 1384 1385 1386 void Simulator::Copy_FPSCR_to_APSR() { 1387 n_flag_ = n_flag_FPSCR_; 1388 z_flag_ = z_flag_FPSCR_; 1389 c_flag_ = c_flag_FPSCR_; 1390 v_flag_ = v_flag_FPSCR_; 1391 } 1392 1393 1394 // Addressing Mode 1 - Data-processing operands: 1395 // Get the value based on the shifter_operand with register. 1396 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) { 1397 ShiftOp shift = instr->ShiftField(); 1398 int shift_amount = instr->ShiftAmountValue(); 1399 int32_t result = get_register(instr->RmValue()); 1400 if (instr->Bit(4) == 0) { 1401 // by immediate 1402 if ((shift == ROR) && (shift_amount == 0)) { 1403 UNIMPLEMENTED(); 1404 return result; 1405 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 1406 shift_amount = 32; 1407 } 1408 switch (shift) { 1409 case ASR: { 1410 if (shift_amount == 0) { 1411 if (result < 0) { 1412 result = 0xffffffff; 1413 *carry_out = true; 1414 } else { 1415 result = 0; 1416 *carry_out = false; 1417 } 1418 } else { 1419 result >>= (shift_amount - 1); 1420 *carry_out = (result & 1) == 1; 1421 result >>= 1; 1422 } 1423 break; 1424 } 1425 1426 case LSL: { 1427 if (shift_amount == 0) { 1428 *carry_out = c_flag_; 1429 } else { 1430 result <<= (shift_amount - 1); 1431 *carry_out = (result < 0); 1432 result <<= 1; 1433 } 1434 break; 1435 } 1436 1437 case LSR: { 1438 if (shift_amount == 0) { 1439 result = 0; 1440 *carry_out = c_flag_; 1441 } else { 1442 uint32_t uresult = static_cast<uint32_t>(result); 1443 uresult >>= (shift_amount - 1); 1444 *carry_out = (uresult & 1) == 1; 1445 uresult >>= 1; 1446 result = static_cast<int32_t>(uresult); 1447 } 1448 break; 1449 } 1450 1451 case ROR: { 1452 if (shift_amount == 0) { 1453 *carry_out = c_flag_; 1454 } else { 1455 uint32_t left = static_cast<uint32_t>(result) >> shift_amount; 1456 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount); 1457 result = right | left; 1458 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0; 1459 } 1460 break; 1461 } 1462 1463 default: { 1464 UNREACHABLE(); 1465 break; 1466 } 1467 } 1468 } else { 1469 // by register 1470 int rs = instr->RsValue(); 1471 shift_amount = get_register(rs) &0xff; 1472 switch (shift) { 1473 case ASR: { 1474 if (shift_amount == 0) { 1475 *carry_out = c_flag_; 1476 } else if (shift_amount < 32) { 1477 result >>= (shift_amount - 1); 1478 *carry_out = (result & 1) == 1; 1479 result >>= 1; 1480 } else { 1481 DCHECK(shift_amount >= 32); 1482 if (result < 0) { 1483 *carry_out = true; 1484 result = 0xffffffff; 1485 } else { 1486 *carry_out = false; 1487 result = 0; 1488 } 1489 } 1490 break; 1491 } 1492 1493 case LSL: { 1494 if (shift_amount == 0) { 1495 *carry_out = c_flag_; 1496 } else if (shift_amount < 32) { 1497 result <<= (shift_amount - 1); 1498 *carry_out = (result < 0); 1499 result <<= 1; 1500 } else if (shift_amount == 32) { 1501 *carry_out = (result & 1) == 1; 1502 result = 0; 1503 } else { 1504 DCHECK(shift_amount > 32); 1505 *carry_out = false; 1506 result = 0; 1507 } 1508 break; 1509 } 1510 1511 case LSR: { 1512 if (shift_amount == 0) { 1513 *carry_out = c_flag_; 1514 } else if (shift_amount < 32) { 1515 uint32_t uresult = static_cast<uint32_t>(result); 1516 uresult >>= (shift_amount - 1); 1517 *carry_out = (uresult & 1) == 1; 1518 uresult >>= 1; 1519 result = static_cast<int32_t>(uresult); 1520 } else if (shift_amount == 32) { 1521 *carry_out = (result < 0); 1522 result = 0; 1523 } else { 1524 *carry_out = false; 1525 result = 0; 1526 } 1527 break; 1528 } 1529 1530 case ROR: { 1531 if (shift_amount == 0) { 1532 *carry_out = c_flag_; 1533 } else { 1534 uint32_t left = static_cast<uint32_t>(result) >> shift_amount; 1535 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount); 1536 result = right | left; 1537 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0; 1538 } 1539 break; 1540 } 1541 1542 default: { 1543 UNREACHABLE(); 1544 break; 1545 } 1546 } 1547 } 1548 return result; 1549 } 1550 1551 1552 // Addressing Mode 1 - Data-processing operands: 1553 // Get the value based on the shifter_operand with immediate. 1554 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) { 1555 int rotate = instr->RotateValue() * 2; 1556 int immed8 = instr->Immed8Value(); 1557 int imm = base::bits::RotateRight32(immed8, rotate); 1558 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); 1559 return imm; 1560 } 1561 1562 1563 static int count_bits(int bit_vector) { 1564 int count = 0; 1565 while (bit_vector != 0) { 1566 if ((bit_vector & 1) != 0) { 1567 count++; 1568 } 1569 bit_vector >>= 1; 1570 } 1571 return count; 1572 } 1573 1574 1575 int32_t Simulator::ProcessPU(Instruction* instr, 1576 int num_regs, 1577 int reg_size, 1578 intptr_t* start_address, 1579 intptr_t* end_address) { 1580 int rn = instr->RnValue(); 1581 int32_t rn_val = get_register(rn); 1582 switch (instr->PUField()) { 1583 case da_x: { 1584 UNIMPLEMENTED(); 1585 break; 1586 } 1587 case ia_x: { 1588 *start_address = rn_val; 1589 *end_address = rn_val + (num_regs * reg_size) - reg_size; 1590 rn_val = rn_val + (num_regs * reg_size); 1591 break; 1592 } 1593 case db_x: { 1594 *start_address = rn_val - (num_regs * reg_size); 1595 *end_address = rn_val - reg_size; 1596 rn_val = *start_address; 1597 break; 1598 } 1599 case ib_x: { 1600 *start_address = rn_val + reg_size; 1601 *end_address = rn_val + (num_regs * reg_size); 1602 rn_val = *end_address; 1603 break; 1604 } 1605 default: { 1606 UNREACHABLE(); 1607 break; 1608 } 1609 } 1610 return rn_val; 1611 } 1612 1613 1614 // Addressing Mode 4 - Load and Store Multiple 1615 void Simulator::HandleRList(Instruction* instr, bool load) { 1616 int rlist = instr->RlistValue(); 1617 int num_regs = count_bits(rlist); 1618 1619 intptr_t start_address = 0; 1620 intptr_t end_address = 0; 1621 int32_t rn_val = 1622 ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address); 1623 1624 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); 1625 // Catch null pointers a little earlier. 1626 DCHECK(start_address > 8191 || start_address < 0); 1627 int reg = 0; 1628 while (rlist != 0) { 1629 if ((rlist & 1) != 0) { 1630 if (load) { 1631 set_register(reg, *address); 1632 } else { 1633 *address = get_register(reg); 1634 } 1635 address += 1; 1636 } 1637 reg++; 1638 rlist >>= 1; 1639 } 1640 DCHECK(end_address == ((intptr_t)address) - 4); 1641 if (instr->HasW()) { 1642 set_register(instr->RnValue(), rn_val); 1643 } 1644 } 1645 1646 1647 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers. 1648 void Simulator::HandleVList(Instruction* instr) { 1649 VFPRegPrecision precision = 1650 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision; 1651 int operand_size = (precision == kSinglePrecision) ? 4 : 8; 1652 1653 bool load = (instr->VLValue() == 0x1); 1654 1655 int vd; 1656 int num_regs; 1657 vd = instr->VFPDRegValue(precision); 1658 if (precision == kSinglePrecision) { 1659 num_regs = instr->Immed8Value(); 1660 } else { 1661 num_regs = instr->Immed8Value() / 2; 1662 } 1663 1664 intptr_t start_address = 0; 1665 intptr_t end_address = 0; 1666 int32_t rn_val = 1667 ProcessPU(instr, num_regs, operand_size, &start_address, &end_address); 1668 1669 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); 1670 for (int reg = vd; reg < vd + num_regs; reg++) { 1671 if (precision == kSinglePrecision) { 1672 if (load) { 1673 set_s_register_from_sinteger( 1674 reg, ReadW(reinterpret_cast<int32_t>(address), instr)); 1675 } else { 1676 WriteW(reinterpret_cast<int32_t>(address), 1677 get_sinteger_from_s_register(reg), instr); 1678 } 1679 address += 1; 1680 } else { 1681 if (load) { 1682 int32_t data[] = { 1683 ReadW(reinterpret_cast<int32_t>(address), instr), 1684 ReadW(reinterpret_cast<int32_t>(address + 1), instr) 1685 }; 1686 set_d_register(reg, reinterpret_cast<uint32_t*>(data)); 1687 } else { 1688 uint32_t data[2]; 1689 get_d_register(reg, data); 1690 WriteW(reinterpret_cast<int32_t>(address), data[0], instr); 1691 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); 1692 } 1693 address += 2; 1694 } 1695 } 1696 DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address); 1697 if (instr->HasW()) { 1698 set_register(instr->RnValue(), rn_val); 1699 } 1700 } 1701 1702 1703 // Calls into the V8 runtime are based on this very simple interface. 1704 // Note: To be able to return two values from some calls the code in runtime.cc 1705 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 1706 // 64-bit value. With the code below we assume that all runtime calls return 1707 // 64 bits of result. If they don't, the r1 result register contains a bogus 1708 // value, which is fine because it is caller-saved. 1709 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 1710 int32_t arg1, 1711 int32_t arg2, 1712 int32_t arg3, 1713 int32_t arg4, 1714 int32_t arg5); 1715 1716 typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int32_t arg0, int32_t arg1, 1717 int32_t arg2, int32_t arg3, 1718 int32_t arg4); 1719 1720 // These prototypes handle the four types of FP calls. 1721 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1); 1722 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); 1723 typedef double (*SimulatorRuntimeFPCall)(double darg0); 1724 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0); 1725 1726 // This signature supports direct call in to API function native callback 1727 // (refer to InvocationCallback in v8.h). 1728 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0); 1729 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1); 1730 1731 // This signature supports direct call to accessor getter callback. 1732 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1); 1733 typedef void (*SimulatorRuntimeProfilingGetterCall)( 1734 int32_t arg0, int32_t arg1, void* arg2); 1735 1736 // Software interrupt instructions are used by the simulator to call into the 1737 // C-based V8 runtime. 1738 void Simulator::SoftwareInterrupt(Instruction* instr) { 1739 int svc = instr->SvcValue(); 1740 switch (svc) { 1741 case kCallRtRedirected: { 1742 // Check if stack is aligned. Error if not aligned is reported below to 1743 // include information on the function called. 1744 bool stack_aligned = 1745 (get_register(sp) 1746 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; 1747 Redirection* redirection = Redirection::FromSwiInstruction(instr); 1748 int32_t arg0 = get_register(r0); 1749 int32_t arg1 = get_register(r1); 1750 int32_t arg2 = get_register(r2); 1751 int32_t arg3 = get_register(r3); 1752 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); 1753 int32_t arg4 = stack_pointer[0]; 1754 int32_t arg5 = stack_pointer[1]; 1755 bool fp_call = 1756 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 1757 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 1758 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 1759 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 1760 // This is dodgy but it works because the C entry stubs are never moved. 1761 // See comment in codegen-arm.cc and bug 1242173. 1762 int32_t saved_lr = get_register(lr); 1763 intptr_t external = 1764 reinterpret_cast<intptr_t>(redirection->external_function()); 1765 if (fp_call) { 1766 double dval0, dval1; // one or two double parameters 1767 int32_t ival; // zero or one integer parameters 1768 int64_t iresult = 0; // integer return value 1769 double dresult = 0; // double return value 1770 GetFpArgs(&dval0, &dval1, &ival); 1771 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1772 SimulatorRuntimeCall generic_target = 1773 reinterpret_cast<SimulatorRuntimeCall>(external); 1774 switch (redirection->type()) { 1775 case ExternalReference::BUILTIN_FP_FP_CALL: 1776 case ExternalReference::BUILTIN_COMPARE_CALL: 1777 PrintF("Call to host function at %p with args %f, %f", 1778 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0, 1779 dval1); 1780 break; 1781 case ExternalReference::BUILTIN_FP_CALL: 1782 PrintF("Call to host function at %p with arg %f", 1783 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0); 1784 break; 1785 case ExternalReference::BUILTIN_FP_INT_CALL: 1786 PrintF("Call to host function at %p with args %f, %d", 1787 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0, 1788 ival); 1789 break; 1790 default: 1791 UNREACHABLE(); 1792 break; 1793 } 1794 if (!stack_aligned) { 1795 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1796 } 1797 PrintF("\n"); 1798 } 1799 CHECK(stack_aligned); 1800 switch (redirection->type()) { 1801 case ExternalReference::BUILTIN_COMPARE_CALL: { 1802 SimulatorRuntimeCompareCall target = 1803 reinterpret_cast<SimulatorRuntimeCompareCall>(external); 1804 iresult = target(dval0, dval1); 1805 set_register(r0, static_cast<int32_t>(iresult)); 1806 set_register(r1, static_cast<int32_t>(iresult >> 32)); 1807 break; 1808 } 1809 case ExternalReference::BUILTIN_FP_FP_CALL: { 1810 SimulatorRuntimeFPFPCall target = 1811 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 1812 dresult = target(dval0, dval1); 1813 SetFpResult(dresult); 1814 break; 1815 } 1816 case ExternalReference::BUILTIN_FP_CALL: { 1817 SimulatorRuntimeFPCall target = 1818 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1819 dresult = target(dval0); 1820 SetFpResult(dresult); 1821 break; 1822 } 1823 case ExternalReference::BUILTIN_FP_INT_CALL: { 1824 SimulatorRuntimeFPIntCall target = 1825 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 1826 dresult = target(dval0, ival); 1827 SetFpResult(dresult); 1828 break; 1829 } 1830 default: 1831 UNREACHABLE(); 1832 break; 1833 } 1834 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1835 switch (redirection->type()) { 1836 case ExternalReference::BUILTIN_COMPARE_CALL: 1837 PrintF("Returned %08x\n", static_cast<int32_t>(iresult)); 1838 break; 1839 case ExternalReference::BUILTIN_FP_FP_CALL: 1840 case ExternalReference::BUILTIN_FP_CALL: 1841 case ExternalReference::BUILTIN_FP_INT_CALL: 1842 PrintF("Returned %f\n", dresult); 1843 break; 1844 default: 1845 UNREACHABLE(); 1846 break; 1847 } 1848 } 1849 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 1850 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1851 PrintF("Call to host function at %p args %08x", 1852 reinterpret_cast<void*>(external), arg0); 1853 if (!stack_aligned) { 1854 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1855 } 1856 PrintF("\n"); 1857 } 1858 CHECK(stack_aligned); 1859 SimulatorRuntimeDirectApiCall target = 1860 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 1861 target(arg0); 1862 } else if ( 1863 redirection->type() == ExternalReference::PROFILING_API_CALL) { 1864 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1865 PrintF("Call to host function at %p args %08x %08x", 1866 reinterpret_cast<void*>(external), arg0, arg1); 1867 if (!stack_aligned) { 1868 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1869 } 1870 PrintF("\n"); 1871 } 1872 CHECK(stack_aligned); 1873 SimulatorRuntimeProfilingApiCall target = 1874 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 1875 target(arg0, Redirection::ReverseRedirection(arg1)); 1876 } else if ( 1877 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 1878 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1879 PrintF("Call to host function at %p args %08x %08x", 1880 reinterpret_cast<void*>(external), arg0, arg1); 1881 if (!stack_aligned) { 1882 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1883 } 1884 PrintF("\n"); 1885 } 1886 CHECK(stack_aligned); 1887 SimulatorRuntimeDirectGetterCall target = 1888 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 1889 target(arg0, arg1); 1890 } else if ( 1891 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) { 1892 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1893 PrintF("Call to host function at %p args %08x %08x %08x", 1894 reinterpret_cast<void*>(external), arg0, arg1, arg2); 1895 if (!stack_aligned) { 1896 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1897 } 1898 PrintF("\n"); 1899 } 1900 CHECK(stack_aligned); 1901 SimulatorRuntimeProfilingGetterCall target = 1902 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>( 1903 external); 1904 target(arg0, arg1, Redirection::ReverseRedirection(arg2)); 1905 } else if (redirection->type() == 1906 ExternalReference::BUILTIN_CALL_TRIPLE) { 1907 // builtin call returning ObjectTriple. 1908 SimulatorRuntimeTripleCall target = 1909 reinterpret_cast<SimulatorRuntimeTripleCall>(external); 1910 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1911 PrintF( 1912 "Call to host triple returning runtime function %p " 1913 "args %08x, %08x, %08x, %08x, %08x", 1914 static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4, 1915 arg5); 1916 if (!stack_aligned) { 1917 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1918 } 1919 PrintF("\n"); 1920 } 1921 CHECK(stack_aligned); 1922 // arg0 is a hidden argument pointing to the return location, so don't 1923 // pass it to the target function. 1924 ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5); 1925 if (::v8::internal::FLAG_trace_sim) { 1926 PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x), 1927 static_cast<void*>(result.y), static_cast<void*>(result.z)); 1928 } 1929 // Return is passed back in address pointed to by hidden first argument. 1930 ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0); 1931 *sim_result = result; 1932 set_register(r0, arg0); 1933 } else { 1934 // builtin call. 1935 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL || 1936 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR); 1937 SimulatorRuntimeCall target = 1938 reinterpret_cast<SimulatorRuntimeCall>(external); 1939 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1940 PrintF( 1941 "Call to host function at %p " 1942 "args %08x, %08x, %08x, %08x, %08x, %08x", 1943 static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3, 1944 arg4, arg5); 1945 if (!stack_aligned) { 1946 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1947 } 1948 PrintF("\n"); 1949 } 1950 CHECK(stack_aligned); 1951 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 1952 int32_t lo_res = static_cast<int32_t>(result); 1953 int32_t hi_res = static_cast<int32_t>(result >> 32); 1954 if (::v8::internal::FLAG_trace_sim) { 1955 PrintF("Returned %08x\n", lo_res); 1956 } 1957 set_register(r0, lo_res); 1958 set_register(r1, hi_res); 1959 } 1960 set_register(lr, saved_lr); 1961 set_pc(get_register(lr)); 1962 break; 1963 } 1964 case kBreakpoint: { 1965 ArmDebugger dbg(this); 1966 dbg.Debug(); 1967 break; 1968 } 1969 // stop uses all codes greater than 1 << 23. 1970 default: { 1971 if (svc >= (1 << 23)) { 1972 uint32_t code = svc & kStopCodeMask; 1973 if (isWatchedStop(code)) { 1974 IncreaseStopCounter(code); 1975 } 1976 // Stop if it is enabled, otherwise go on jumping over the stop 1977 // and the message address. 1978 if (isEnabledStop(code)) { 1979 ArmDebugger dbg(this); 1980 dbg.Stop(instr); 1981 } else { 1982 set_pc(get_pc() + 2 * Instruction::kInstrSize); 1983 } 1984 } else { 1985 // This is not a valid svc code. 1986 UNREACHABLE(); 1987 break; 1988 } 1989 } 1990 } 1991 } 1992 1993 1994 float Simulator::canonicalizeNaN(float value) { 1995 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation 1996 // choices" of the ARM Reference Manual. 1997 const uint32_t kDefaultNaN = 0x7FC00000u; 1998 if (FPSCR_default_NaN_mode_ && std::isnan(value)) { 1999 value = bit_cast<float>(kDefaultNaN); 2000 } 2001 return value; 2002 } 2003 2004 2005 double Simulator::canonicalizeNaN(double value) { 2006 // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation 2007 // choices" of the ARM Reference Manual. 2008 const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000); 2009 if (FPSCR_default_NaN_mode_ && std::isnan(value)) { 2010 value = bit_cast<double>(kDefaultNaN); 2011 } 2012 return value; 2013 } 2014 2015 2016 // Stop helper functions. 2017 bool Simulator::isStopInstruction(Instruction* instr) { 2018 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); 2019 } 2020 2021 2022 bool Simulator::isWatchedStop(uint32_t code) { 2023 DCHECK(code <= kMaxStopCode); 2024 return code < kNumOfWatchedStops; 2025 } 2026 2027 2028 bool Simulator::isEnabledStop(uint32_t code) { 2029 DCHECK(code <= kMaxStopCode); 2030 // Unwatched stops are always enabled. 2031 return !isWatchedStop(code) || 2032 !(watched_stops_[code].count & kStopDisabledBit); 2033 } 2034 2035 2036 void Simulator::EnableStop(uint32_t code) { 2037 DCHECK(isWatchedStop(code)); 2038 if (!isEnabledStop(code)) { 2039 watched_stops_[code].count &= ~kStopDisabledBit; 2040 } 2041 } 2042 2043 2044 void Simulator::DisableStop(uint32_t code) { 2045 DCHECK(isWatchedStop(code)); 2046 if (isEnabledStop(code)) { 2047 watched_stops_[code].count |= kStopDisabledBit; 2048 } 2049 } 2050 2051 2052 void Simulator::IncreaseStopCounter(uint32_t code) { 2053 DCHECK(code <= kMaxStopCode); 2054 DCHECK(isWatchedStop(code)); 2055 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) { 2056 PrintF("Stop counter for code %i has overflowed.\n" 2057 "Enabling this code and reseting the counter to 0.\n", code); 2058 watched_stops_[code].count = 0; 2059 EnableStop(code); 2060 } else { 2061 watched_stops_[code].count++; 2062 } 2063 } 2064 2065 2066 // Print a stop status. 2067 void Simulator::PrintStopInfo(uint32_t code) { 2068 DCHECK(code <= kMaxStopCode); 2069 if (!isWatchedStop(code)) { 2070 PrintF("Stop not watched."); 2071 } else { 2072 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled"; 2073 int32_t count = watched_stops_[code].count & ~kStopDisabledBit; 2074 // Don't print the state of unused breakpoints. 2075 if (count != 0) { 2076 if (watched_stops_[code].desc) { 2077 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", 2078 code, code, state, count, watched_stops_[code].desc); 2079 } else { 2080 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", 2081 code, code, state, count); 2082 } 2083 } 2084 } 2085 } 2086 2087 2088 // Handle execution based on instruction types. 2089 2090 // Instruction types 0 and 1 are both rolled into one function because they 2091 // only differ in the handling of the shifter_operand. 2092 void Simulator::DecodeType01(Instruction* instr) { 2093 int type = instr->TypeValue(); 2094 if ((type == 0) && instr->IsSpecialType0()) { 2095 // multiply instruction or extra loads and stores 2096 if (instr->Bits(7, 4) == 9) { 2097 if (instr->Bit(24) == 0) { 2098 // Raw field decoding here. Multiply instructions have their Rd in 2099 // funny places. 2100 int rn = instr->RnValue(); 2101 int rm = instr->RmValue(); 2102 int rs = instr->RsValue(); 2103 int32_t rs_val = get_register(rs); 2104 int32_t rm_val = get_register(rm); 2105 if (instr->Bit(23) == 0) { 2106 if (instr->Bit(21) == 0) { 2107 // The MUL instruction description (A 4.1.33) refers to Rd as being 2108 // the destination for the operation, but it confusingly uses the 2109 // Rn field to encode it. 2110 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 2111 int rd = rn; // Remap the rn field to the Rd register. 2112 int32_t alu_out = rm_val * rs_val; 2113 set_register(rd, alu_out); 2114 if (instr->HasS()) { 2115 SetNZFlags(alu_out); 2116 } 2117 } else { 2118 int rd = instr->RdValue(); 2119 int32_t acc_value = get_register(rd); 2120 if (instr->Bit(22) == 0) { 2121 // The MLA instruction description (A 4.1.28) refers to the order 2122 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 2123 // Rn field to encode the Rd register and the Rd field to encode 2124 // the Rn register. 2125 // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 2126 int32_t mul_out = rm_val * rs_val; 2127 int32_t result = acc_value + mul_out; 2128 set_register(rn, result); 2129 } else { 2130 // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd"); 2131 int32_t mul_out = rm_val * rs_val; 2132 int32_t result = acc_value - mul_out; 2133 set_register(rn, result); 2134 } 2135 } 2136 } else { 2137 // The signed/long multiply instructions use the terms RdHi and RdLo 2138 // when referring to the target registers. They are mapped to the Rn 2139 // and Rd fields as follows: 2140 // RdLo == Rd 2141 // RdHi == Rn (This is confusingly stored in variable rd here 2142 // because the mul instruction from above uses the 2143 // Rn field to encode the Rd register. Good luck figuring 2144 // this out without reading the ARM instruction manual 2145 // at a very detailed level.) 2146 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm"); 2147 int rd_hi = rn; // Remap the rn field to the RdHi register. 2148 int rd_lo = instr->RdValue(); 2149 int32_t hi_res = 0; 2150 int32_t lo_res = 0; 2151 if (instr->Bit(22) == 1) { 2152 int64_t left_op = static_cast<int32_t>(rm_val); 2153 int64_t right_op = static_cast<int32_t>(rs_val); 2154 uint64_t result = left_op * right_op; 2155 hi_res = static_cast<int32_t>(result >> 32); 2156 lo_res = static_cast<int32_t>(result & 0xffffffff); 2157 } else { 2158 // unsigned multiply 2159 uint64_t left_op = static_cast<uint32_t>(rm_val); 2160 uint64_t right_op = static_cast<uint32_t>(rs_val); 2161 uint64_t result = left_op * right_op; 2162 hi_res = static_cast<int32_t>(result >> 32); 2163 lo_res = static_cast<int32_t>(result & 0xffffffff); 2164 } 2165 set_register(rd_lo, lo_res); 2166 set_register(rd_hi, hi_res); 2167 if (instr->HasS()) { 2168 UNIMPLEMENTED(); 2169 } 2170 } 2171 } else { 2172 if (instr->Bits(24, 23) == 3) { 2173 if (instr->Bit(20) == 1) { 2174 // ldrex 2175 int rt = instr->RtValue(); 2176 int rn = instr->RnValue(); 2177 int32_t addr = get_register(rn); 2178 switch (instr->Bits(22, 21)) { 2179 case 0: { 2180 // Format(instr, "ldrex'cond 'rt, ['rn]"); 2181 int value = ReadExW(addr, instr); 2182 set_register(rt, value); 2183 break; 2184 } 2185 case 2: { 2186 // Format(instr, "ldrexb'cond 'rt, ['rn]"); 2187 uint8_t value = ReadExBU(addr); 2188 set_register(rt, value); 2189 break; 2190 } 2191 case 3: { 2192 // Format(instr, "ldrexh'cond 'rt, ['rn]"); 2193 uint16_t value = ReadExHU(addr, instr); 2194 set_register(rt, value); 2195 break; 2196 } 2197 default: 2198 UNREACHABLE(); 2199 break; 2200 } 2201 } else { 2202 // The instruction is documented as strex rd, rt, [rn], but the 2203 // "rt" register is using the rm bits. 2204 int rd = instr->RdValue(); 2205 int rt = instr->RmValue(); 2206 int rn = instr->RnValue(); 2207 int32_t addr = get_register(rn); 2208 switch (instr->Bits(22, 21)) { 2209 case 0: { 2210 // Format(instr, "strex'cond 'rd, 'rm, ['rn]"); 2211 int value = get_register(rt); 2212 int status = WriteExW(addr, value, instr); 2213 set_register(rd, status); 2214 break; 2215 } 2216 case 2: { 2217 // Format(instr, "strexb'cond 'rd, 'rm, ['rn]"); 2218 uint8_t value = get_register(rt); 2219 int status = WriteExB(addr, value); 2220 set_register(rd, status); 2221 break; 2222 } 2223 case 3: { 2224 // Format(instr, "strexh'cond 'rd, 'rm, ['rn]"); 2225 uint16_t value = get_register(rt); 2226 int status = WriteExH(addr, value, instr); 2227 set_register(rd, status); 2228 break; 2229 } 2230 default: 2231 UNREACHABLE(); 2232 break; 2233 } 2234 } 2235 } else { 2236 UNIMPLEMENTED(); // Not used by V8. 2237 } 2238 } 2239 } else { 2240 // extra load/store instructions 2241 int rd = instr->RdValue(); 2242 int rn = instr->RnValue(); 2243 int32_t rn_val = get_register(rn); 2244 int32_t addr = 0; 2245 if (instr->Bit(22) == 0) { 2246 int rm = instr->RmValue(); 2247 int32_t rm_val = get_register(rm); 2248 switch (instr->PUField()) { 2249 case da_x: { 2250 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 2251 DCHECK(!instr->HasW()); 2252 addr = rn_val; 2253 rn_val -= rm_val; 2254 set_register(rn, rn_val); 2255 break; 2256 } 2257 case ia_x: { 2258 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 2259 DCHECK(!instr->HasW()); 2260 addr = rn_val; 2261 rn_val += rm_val; 2262 set_register(rn, rn_val); 2263 break; 2264 } 2265 case db_x: { 2266 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 2267 rn_val -= rm_val; 2268 addr = rn_val; 2269 if (instr->HasW()) { 2270 set_register(rn, rn_val); 2271 } 2272 break; 2273 } 2274 case ib_x: { 2275 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 2276 rn_val += rm_val; 2277 addr = rn_val; 2278 if (instr->HasW()) { 2279 set_register(rn, rn_val); 2280 } 2281 break; 2282 } 2283 default: { 2284 // The PU field is a 2-bit field. 2285 UNREACHABLE(); 2286 break; 2287 } 2288 } 2289 } else { 2290 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); 2291 switch (instr->PUField()) { 2292 case da_x: { 2293 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 2294 DCHECK(!instr->HasW()); 2295 addr = rn_val; 2296 rn_val -= imm_val; 2297 set_register(rn, rn_val); 2298 break; 2299 } 2300 case ia_x: { 2301 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 2302 DCHECK(!instr->HasW()); 2303 addr = rn_val; 2304 rn_val += imm_val; 2305 set_register(rn, rn_val); 2306 break; 2307 } 2308 case db_x: { 2309 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 2310 rn_val -= imm_val; 2311 addr = rn_val; 2312 if (instr->HasW()) { 2313 set_register(rn, rn_val); 2314 } 2315 break; 2316 } 2317 case ib_x: { 2318 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 2319 rn_val += imm_val; 2320 addr = rn_val; 2321 if (instr->HasW()) { 2322 set_register(rn, rn_val); 2323 } 2324 break; 2325 } 2326 default: { 2327 // The PU field is a 2-bit field. 2328 UNREACHABLE(); 2329 break; 2330 } 2331 } 2332 } 2333 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) { 2334 DCHECK((rd % 2) == 0); 2335 if (instr->HasH()) { 2336 // The strd instruction. 2337 int32_t value1 = get_register(rd); 2338 int32_t value2 = get_register(rd+1); 2339 WriteDW(addr, value1, value2); 2340 } else { 2341 // The ldrd instruction. 2342 int* rn_data = ReadDW(addr); 2343 set_dw_register(rd, rn_data); 2344 } 2345 } else if (instr->HasH()) { 2346 if (instr->HasSign()) { 2347 if (instr->HasL()) { 2348 int16_t val = ReadH(addr, instr); 2349 set_register(rd, val); 2350 } else { 2351 int16_t val = get_register(rd); 2352 WriteH(addr, val, instr); 2353 } 2354 } else { 2355 if (instr->HasL()) { 2356 uint16_t val = ReadHU(addr, instr); 2357 set_register(rd, val); 2358 } else { 2359 uint16_t val = get_register(rd); 2360 WriteH(addr, val, instr); 2361 } 2362 } 2363 } else { 2364 // signed byte loads 2365 DCHECK(instr->HasSign()); 2366 DCHECK(instr->HasL()); 2367 int8_t val = ReadB(addr); 2368 set_register(rd, val); 2369 } 2370 return; 2371 } 2372 } else if ((type == 0) && instr->IsMiscType0()) { 2373 if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) && 2374 (instr->Bits(15, 4) == 0xf00)) { 2375 // MSR 2376 int rm = instr->RmValue(); 2377 DCHECK_NE(pc, rm); // UNPREDICTABLE 2378 SRegisterFieldMask sreg_and_mask = 2379 instr->BitField(22, 22) | instr->BitField(19, 16); 2380 SetSpecialRegister(sreg_and_mask, get_register(rm)); 2381 } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) && 2382 (instr->Bits(11, 0) == 0)) { 2383 // MRS 2384 int rd = instr->RdValue(); 2385 DCHECK_NE(pc, rd); // UNPREDICTABLE 2386 SRegister sreg = static_cast<SRegister>(instr->BitField(22, 22)); 2387 set_register(rd, GetFromSpecialRegister(sreg)); 2388 } else if (instr->Bits(22, 21) == 1) { 2389 int rm = instr->RmValue(); 2390 switch (instr->BitField(7, 4)) { 2391 case BX: 2392 set_pc(get_register(rm)); 2393 break; 2394 case BLX: { 2395 uint32_t old_pc = get_pc(); 2396 set_pc(get_register(rm)); 2397 set_register(lr, old_pc + Instruction::kInstrSize); 2398 break; 2399 } 2400 case BKPT: { 2401 ArmDebugger dbg(this); 2402 PrintF("Simulator hit BKPT.\n"); 2403 dbg.Debug(); 2404 break; 2405 } 2406 default: 2407 UNIMPLEMENTED(); 2408 } 2409 } else if (instr->Bits(22, 21) == 3) { 2410 int rm = instr->RmValue(); 2411 int rd = instr->RdValue(); 2412 switch (instr->BitField(7, 4)) { 2413 case CLZ: { 2414 uint32_t bits = get_register(rm); 2415 int leading_zeros = 0; 2416 if (bits == 0) { 2417 leading_zeros = 32; 2418 } else { 2419 while ((bits & 0x80000000u) == 0) { 2420 bits <<= 1; 2421 leading_zeros++; 2422 } 2423 } 2424 set_register(rd, leading_zeros); 2425 break; 2426 } 2427 default: 2428 UNIMPLEMENTED(); 2429 } 2430 } else { 2431 PrintF("%08x\n", instr->InstructionBits()); 2432 UNIMPLEMENTED(); 2433 } 2434 } else if ((type == 1) && instr->IsNopType1()) { 2435 // NOP. 2436 } else { 2437 int rd = instr->RdValue(); 2438 int rn = instr->RnValue(); 2439 int32_t rn_val = get_register(rn); 2440 int32_t shifter_operand = 0; 2441 bool shifter_carry_out = 0; 2442 if (type == 0) { 2443 shifter_operand = GetShiftRm(instr, &shifter_carry_out); 2444 } else { 2445 DCHECK(instr->TypeValue() == 1); 2446 shifter_operand = GetImm(instr, &shifter_carry_out); 2447 } 2448 int32_t alu_out; 2449 2450 switch (instr->OpcodeField()) { 2451 case AND: { 2452 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); 2453 // Format(instr, "and'cond's 'rd, 'rn, 'imm"); 2454 alu_out = rn_val & shifter_operand; 2455 set_register(rd, alu_out); 2456 if (instr->HasS()) { 2457 SetNZFlags(alu_out); 2458 SetCFlag(shifter_carry_out); 2459 } 2460 break; 2461 } 2462 2463 case EOR: { 2464 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm"); 2465 // Format(instr, "eor'cond's 'rd, 'rn, 'imm"); 2466 alu_out = rn_val ^ shifter_operand; 2467 set_register(rd, alu_out); 2468 if (instr->HasS()) { 2469 SetNZFlags(alu_out); 2470 SetCFlag(shifter_carry_out); 2471 } 2472 break; 2473 } 2474 2475 case SUB: { 2476 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm"); 2477 // Format(instr, "sub'cond's 'rd, 'rn, 'imm"); 2478 alu_out = rn_val - shifter_operand; 2479 set_register(rd, alu_out); 2480 if (instr->HasS()) { 2481 SetNZFlags(alu_out); 2482 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2483 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2484 } 2485 break; 2486 } 2487 2488 case RSB: { 2489 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm"); 2490 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm"); 2491 alu_out = shifter_operand - rn_val; 2492 set_register(rd, alu_out); 2493 if (instr->HasS()) { 2494 SetNZFlags(alu_out); 2495 SetCFlag(!BorrowFrom(shifter_operand, rn_val)); 2496 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); 2497 } 2498 break; 2499 } 2500 2501 case ADD: { 2502 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm"); 2503 // Format(instr, "add'cond's 'rd, 'rn, 'imm"); 2504 alu_out = rn_val + shifter_operand; 2505 set_register(rd, alu_out); 2506 if (instr->HasS()) { 2507 SetNZFlags(alu_out); 2508 SetCFlag(CarryFrom(rn_val, shifter_operand)); 2509 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2510 } 2511 break; 2512 } 2513 2514 case ADC: { 2515 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); 2516 // Format(instr, "adc'cond's 'rd, 'rn, 'imm"); 2517 alu_out = rn_val + shifter_operand + GetCarry(); 2518 set_register(rd, alu_out); 2519 if (instr->HasS()) { 2520 SetNZFlags(alu_out); 2521 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry())); 2522 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2523 } 2524 break; 2525 } 2526 2527 case SBC: { 2528 // Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); 2529 // Format(instr, "sbc'cond's 'rd, 'rn, 'imm"); 2530 alu_out = (rn_val - shifter_operand) - (GetCarry() ? 0 : 1); 2531 set_register(rd, alu_out); 2532 if (instr->HasS()) { 2533 SetNZFlags(alu_out); 2534 SetCFlag(!BorrowFrom(rn_val, shifter_operand, GetCarry())); 2535 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2536 } 2537 break; 2538 } 2539 2540 case RSC: { 2541 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); 2542 Format(instr, "rsc'cond's 'rd, 'rn, 'imm"); 2543 break; 2544 } 2545 2546 case TST: { 2547 if (instr->HasS()) { 2548 // Format(instr, "tst'cond 'rn, 'shift_rm"); 2549 // Format(instr, "tst'cond 'rn, 'imm"); 2550 alu_out = rn_val & shifter_operand; 2551 SetNZFlags(alu_out); 2552 SetCFlag(shifter_carry_out); 2553 } else { 2554 // Format(instr, "movw'cond 'rd, 'imm"). 2555 alu_out = instr->ImmedMovwMovtValue(); 2556 set_register(rd, alu_out); 2557 } 2558 break; 2559 } 2560 2561 case TEQ: { 2562 if (instr->HasS()) { 2563 // Format(instr, "teq'cond 'rn, 'shift_rm"); 2564 // Format(instr, "teq'cond 'rn, 'imm"); 2565 alu_out = rn_val ^ shifter_operand; 2566 SetNZFlags(alu_out); 2567 SetCFlag(shifter_carry_out); 2568 } else { 2569 // Other instructions matching this pattern are handled in the 2570 // miscellaneous instructions part above. 2571 UNREACHABLE(); 2572 } 2573 break; 2574 } 2575 2576 case CMP: { 2577 if (instr->HasS()) { 2578 // Format(instr, "cmp'cond 'rn, 'shift_rm"); 2579 // Format(instr, "cmp'cond 'rn, 'imm"); 2580 alu_out = rn_val - shifter_operand; 2581 SetNZFlags(alu_out); 2582 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2583 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2584 } else { 2585 // Format(instr, "movt'cond 'rd, 'imm"). 2586 alu_out = (get_register(rd) & 0xffff) | 2587 (instr->ImmedMovwMovtValue() << 16); 2588 set_register(rd, alu_out); 2589 } 2590 break; 2591 } 2592 2593 case CMN: { 2594 if (instr->HasS()) { 2595 // Format(instr, "cmn'cond 'rn, 'shift_rm"); 2596 // Format(instr, "cmn'cond 'rn, 'imm"); 2597 alu_out = rn_val + shifter_operand; 2598 SetNZFlags(alu_out); 2599 SetCFlag(CarryFrom(rn_val, shifter_operand)); 2600 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2601 } else { 2602 // Other instructions matching this pattern are handled in the 2603 // miscellaneous instructions part above. 2604 UNREACHABLE(); 2605 } 2606 break; 2607 } 2608 2609 case ORR: { 2610 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); 2611 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); 2612 alu_out = rn_val | shifter_operand; 2613 set_register(rd, alu_out); 2614 if (instr->HasS()) { 2615 SetNZFlags(alu_out); 2616 SetCFlag(shifter_carry_out); 2617 } 2618 break; 2619 } 2620 2621 case MOV: { 2622 // Format(instr, "mov'cond's 'rd, 'shift_rm"); 2623 // Format(instr, "mov'cond's 'rd, 'imm"); 2624 alu_out = shifter_operand; 2625 set_register(rd, alu_out); 2626 if (instr->HasS()) { 2627 SetNZFlags(alu_out); 2628 SetCFlag(shifter_carry_out); 2629 } 2630 break; 2631 } 2632 2633 case BIC: { 2634 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm"); 2635 // Format(instr, "bic'cond's 'rd, 'rn, 'imm"); 2636 alu_out = rn_val & ~shifter_operand; 2637 set_register(rd, alu_out); 2638 if (instr->HasS()) { 2639 SetNZFlags(alu_out); 2640 SetCFlag(shifter_carry_out); 2641 } 2642 break; 2643 } 2644 2645 case MVN: { 2646 // Format(instr, "mvn'cond's 'rd, 'shift_rm"); 2647 // Format(instr, "mvn'cond's 'rd, 'imm"); 2648 alu_out = ~shifter_operand; 2649 set_register(rd, alu_out); 2650 if (instr->HasS()) { 2651 SetNZFlags(alu_out); 2652 SetCFlag(shifter_carry_out); 2653 } 2654 break; 2655 } 2656 2657 default: { 2658 UNREACHABLE(); 2659 break; 2660 } 2661 } 2662 } 2663 } 2664 2665 2666 void Simulator::DecodeType2(Instruction* instr) { 2667 int rd = instr->RdValue(); 2668 int rn = instr->RnValue(); 2669 int32_t rn_val = get_register(rn); 2670 int32_t im_val = instr->Offset12Value(); 2671 int32_t addr = 0; 2672 switch (instr->PUField()) { 2673 case da_x: { 2674 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 2675 DCHECK(!instr->HasW()); 2676 addr = rn_val; 2677 rn_val -= im_val; 2678 set_register(rn, rn_val); 2679 break; 2680 } 2681 case ia_x: { 2682 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 2683 DCHECK(!instr->HasW()); 2684 addr = rn_val; 2685 rn_val += im_val; 2686 set_register(rn, rn_val); 2687 break; 2688 } 2689 case db_x: { 2690 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 2691 rn_val -= im_val; 2692 addr = rn_val; 2693 if (instr->HasW()) { 2694 set_register(rn, rn_val); 2695 } 2696 break; 2697 } 2698 case ib_x: { 2699 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 2700 rn_val += im_val; 2701 addr = rn_val; 2702 if (instr->HasW()) { 2703 set_register(rn, rn_val); 2704 } 2705 break; 2706 } 2707 default: { 2708 UNREACHABLE(); 2709 break; 2710 } 2711 } 2712 if (instr->HasB()) { 2713 if (instr->HasL()) { 2714 byte val = ReadBU(addr); 2715 set_register(rd, val); 2716 } else { 2717 byte val = get_register(rd); 2718 WriteB(addr, val); 2719 } 2720 } else { 2721 if (instr->HasL()) { 2722 set_register(rd, ReadW(addr, instr)); 2723 } else { 2724 WriteW(addr, get_register(rd), instr); 2725 } 2726 } 2727 } 2728 2729 2730 void Simulator::DecodeType3(Instruction* instr) { 2731 int rd = instr->RdValue(); 2732 int rn = instr->RnValue(); 2733 int32_t rn_val = get_register(rn); 2734 bool shifter_carry_out = 0; 2735 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); 2736 int32_t addr = 0; 2737 switch (instr->PUField()) { 2738 case da_x: { 2739 DCHECK(!instr->HasW()); 2740 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 2741 UNIMPLEMENTED(); 2742 break; 2743 } 2744 case ia_x: { 2745 if (instr->Bit(4) == 0) { 2746 // Memop. 2747 } else { 2748 if (instr->Bit(5) == 0) { 2749 switch (instr->Bits(22, 21)) { 2750 case 0: 2751 if (instr->Bit(20) == 0) { 2752 if (instr->Bit(6) == 0) { 2753 // Pkhbt. 2754 uint32_t rn_val = get_register(rn); 2755 uint32_t rm_val = get_register(instr->RmValue()); 2756 int32_t shift = instr->Bits(11, 7); 2757 rm_val <<= shift; 2758 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U)); 2759 } else { 2760 // Pkhtb. 2761 uint32_t rn_val = get_register(rn); 2762 int32_t rm_val = get_register(instr->RmValue()); 2763 int32_t shift = instr->Bits(11, 7); 2764 if (shift == 0) { 2765 shift = 32; 2766 } 2767 rm_val >>= shift; 2768 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF)); 2769 } 2770 } else { 2771 UNIMPLEMENTED(); 2772 } 2773 break; 2774 case 1: 2775 UNIMPLEMENTED(); 2776 break; 2777 case 2: 2778 UNIMPLEMENTED(); 2779 break; 2780 case 3: { 2781 // Usat. 2782 int32_t sat_pos = instr->Bits(20, 16); 2783 int32_t sat_val = (1 << sat_pos) - 1; 2784 int32_t shift = instr->Bits(11, 7); 2785 int32_t shift_type = instr->Bit(6); 2786 int32_t rm_val = get_register(instr->RmValue()); 2787 if (shift_type == 0) { // LSL 2788 rm_val <<= shift; 2789 } else { // ASR 2790 rm_val >>= shift; 2791 } 2792 // If saturation occurs, the Q flag should be set in the CPSR. 2793 // There is no Q flag yet, and no instruction (MRS) to read the 2794 // CPSR directly. 2795 if (rm_val > sat_val) { 2796 rm_val = sat_val; 2797 } else if (rm_val < 0) { 2798 rm_val = 0; 2799 } 2800 set_register(rd, rm_val); 2801 break; 2802 } 2803 } 2804 } else { 2805 switch (instr->Bits(22, 21)) { 2806 case 0: 2807 UNIMPLEMENTED(); 2808 break; 2809 case 1: 2810 if (instr->Bits(9, 6) == 1) { 2811 if (instr->Bit(20) == 0) { 2812 if (instr->Bits(19, 16) == 0xF) { 2813 // Sxtb. 2814 int32_t rm_val = get_register(instr->RmValue()); 2815 int32_t rotate = instr->Bits(11, 10); 2816 switch (rotate) { 2817 case 0: 2818 break; 2819 case 1: 2820 rm_val = (rm_val >> 8) | (rm_val << 24); 2821 break; 2822 case 2: 2823 rm_val = (rm_val >> 16) | (rm_val << 16); 2824 break; 2825 case 3: 2826 rm_val = (rm_val >> 24) | (rm_val << 8); 2827 break; 2828 } 2829 set_register(rd, static_cast<int8_t>(rm_val)); 2830 } else { 2831 // Sxtab. 2832 int32_t rn_val = get_register(rn); 2833 int32_t rm_val = get_register(instr->RmValue()); 2834 int32_t rotate = instr->Bits(11, 10); 2835 switch (rotate) { 2836 case 0: 2837 break; 2838 case 1: 2839 rm_val = (rm_val >> 8) | (rm_val << 24); 2840 break; 2841 case 2: 2842 rm_val = (rm_val >> 16) | (rm_val << 16); 2843 break; 2844 case 3: 2845 rm_val = (rm_val >> 24) | (rm_val << 8); 2846 break; 2847 } 2848 set_register(rd, rn_val + static_cast<int8_t>(rm_val)); 2849 } 2850 } else { 2851 if (instr->Bits(19, 16) == 0xF) { 2852 // Sxth. 2853 int32_t rm_val = get_register(instr->RmValue()); 2854 int32_t rotate = instr->Bits(11, 10); 2855 switch (rotate) { 2856 case 0: 2857 break; 2858 case 1: 2859 rm_val = (rm_val >> 8) | (rm_val << 24); 2860 break; 2861 case 2: 2862 rm_val = (rm_val >> 16) | (rm_val << 16); 2863 break; 2864 case 3: 2865 rm_val = (rm_val >> 24) | (rm_val << 8); 2866 break; 2867 } 2868 set_register(rd, static_cast<int16_t>(rm_val)); 2869 } else { 2870 // Sxtah. 2871 int32_t rn_val = get_register(rn); 2872 int32_t rm_val = get_register(instr->RmValue()); 2873 int32_t rotate = instr->Bits(11, 10); 2874 switch (rotate) { 2875 case 0: 2876 break; 2877 case 1: 2878 rm_val = (rm_val >> 8) | (rm_val << 24); 2879 break; 2880 case 2: 2881 rm_val = (rm_val >> 16) | (rm_val << 16); 2882 break; 2883 case 3: 2884 rm_val = (rm_val >> 24) | (rm_val << 8); 2885 break; 2886 } 2887 set_register(rd, rn_val + static_cast<int16_t>(rm_val)); 2888 } 2889 } 2890 } else { 2891 UNREACHABLE(); 2892 } 2893 break; 2894 case 2: 2895 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { 2896 if (instr->Bits(19, 16) == 0xF) { 2897 // Uxtb16. 2898 uint32_t rm_val = get_register(instr->RmValue()); 2899 int32_t rotate = instr->Bits(11, 10); 2900 switch (rotate) { 2901 case 0: 2902 break; 2903 case 1: 2904 rm_val = (rm_val >> 8) | (rm_val << 24); 2905 break; 2906 case 2: 2907 rm_val = (rm_val >> 16) | (rm_val << 16); 2908 break; 2909 case 3: 2910 rm_val = (rm_val >> 24) | (rm_val << 8); 2911 break; 2912 } 2913 set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000)); 2914 } else { 2915 UNIMPLEMENTED(); 2916 } 2917 } else { 2918 UNIMPLEMENTED(); 2919 } 2920 break; 2921 case 3: 2922 if ((instr->Bits(9, 6) == 1)) { 2923 if (instr->Bit(20) == 0) { 2924 if (instr->Bits(19, 16) == 0xF) { 2925 // Uxtb. 2926 uint32_t rm_val = get_register(instr->RmValue()); 2927 int32_t rotate = instr->Bits(11, 10); 2928 switch (rotate) { 2929 case 0: 2930 break; 2931 case 1: 2932 rm_val = (rm_val >> 8) | (rm_val << 24); 2933 break; 2934 case 2: 2935 rm_val = (rm_val >> 16) | (rm_val << 16); 2936 break; 2937 case 3: 2938 rm_val = (rm_val >> 24) | (rm_val << 8); 2939 break; 2940 } 2941 set_register(rd, (rm_val & 0xFF)); 2942 } else { 2943 // Uxtab. 2944 uint32_t rn_val = get_register(rn); 2945 uint32_t rm_val = get_register(instr->RmValue()); 2946 int32_t rotate = instr->Bits(11, 10); 2947 switch (rotate) { 2948 case 0: 2949 break; 2950 case 1: 2951 rm_val = (rm_val >> 8) | (rm_val << 24); 2952 break; 2953 case 2: 2954 rm_val = (rm_val >> 16) | (rm_val << 16); 2955 break; 2956 case 3: 2957 rm_val = (rm_val >> 24) | (rm_val << 8); 2958 break; 2959 } 2960 set_register(rd, rn_val + (rm_val & 0xFF)); 2961 } 2962 } else { 2963 if (instr->Bits(19, 16) == 0xF) { 2964 // Uxth. 2965 uint32_t rm_val = get_register(instr->RmValue()); 2966 int32_t rotate = instr->Bits(11, 10); 2967 switch (rotate) { 2968 case 0: 2969 break; 2970 case 1: 2971 rm_val = (rm_val >> 8) | (rm_val << 24); 2972 break; 2973 case 2: 2974 rm_val = (rm_val >> 16) | (rm_val << 16); 2975 break; 2976 case 3: 2977 rm_val = (rm_val >> 24) | (rm_val << 8); 2978 break; 2979 } 2980 set_register(rd, (rm_val & 0xFFFF)); 2981 } else { 2982 // Uxtah. 2983 uint32_t rn_val = get_register(rn); 2984 uint32_t rm_val = get_register(instr->RmValue()); 2985 int32_t rotate = instr->Bits(11, 10); 2986 switch (rotate) { 2987 case 0: 2988 break; 2989 case 1: 2990 rm_val = (rm_val >> 8) | (rm_val << 24); 2991 break; 2992 case 2: 2993 rm_val = (rm_val >> 16) | (rm_val << 16); 2994 break; 2995 case 3: 2996 rm_val = (rm_val >> 24) | (rm_val << 8); 2997 break; 2998 } 2999 set_register(rd, rn_val + (rm_val & 0xFFFF)); 3000 } 3001 } 3002 } else { 3003 // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001 3004 if ((instr->Bits(20, 16) == 0x1f) && 3005 (instr->Bits(11, 4) == 0xf3)) { 3006 // Rbit. 3007 uint32_t rm_val = get_register(instr->RmValue()); 3008 set_register(rd, base::bits::ReverseBits(rm_val)); 3009 } else { 3010 UNIMPLEMENTED(); 3011 } 3012 } 3013 break; 3014 } 3015 } 3016 return; 3017 } 3018 break; 3019 } 3020 case db_x: { 3021 if (instr->Bits(22, 20) == 0x5) { 3022 if (instr->Bits(7, 4) == 0x1) { 3023 int rm = instr->RmValue(); 3024 int32_t rm_val = get_register(rm); 3025 int rs = instr->RsValue(); 3026 int32_t rs_val = get_register(rs); 3027 if (instr->Bits(15, 12) == 0xF) { 3028 // SMMUL (in V8 notation matching ARM ISA format) 3029 // Format(instr, "smmul'cond 'rn, 'rm, 'rs"); 3030 rn_val = base::bits::SignedMulHigh32(rm_val, rs_val); 3031 } else { 3032 // SMMLA (in V8 notation matching ARM ISA format) 3033 // Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd"); 3034 int rd = instr->RdValue(); 3035 int32_t rd_val = get_register(rd); 3036 rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val); 3037 } 3038 set_register(rn, rn_val); 3039 return; 3040 } 3041 } 3042 if (instr->Bits(5, 4) == 0x1) { 3043 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) { 3044 // (s/u)div (in V8 notation matching ARM ISA format) rn = rm/rs 3045 // Format(instr, "'(s/u)div'cond'b 'rn, 'rm, 'rs); 3046 int rm = instr->RmValue(); 3047 int32_t rm_val = get_register(rm); 3048 int rs = instr->RsValue(); 3049 int32_t rs_val = get_register(rs); 3050 int32_t ret_val = 0; 3051 // udiv 3052 if (instr->Bit(21) == 0x1) { 3053 ret_val = bit_cast<int32_t>(base::bits::UnsignedDiv32( 3054 bit_cast<uint32_t>(rm_val), bit_cast<uint32_t>(rs_val))); 3055 } else { 3056 ret_val = base::bits::SignedDiv32(rm_val, rs_val); 3057 } 3058 set_register(rn, ret_val); 3059 return; 3060 } 3061 } 3062 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 3063 addr = rn_val - shifter_operand; 3064 if (instr->HasW()) { 3065 set_register(rn, addr); 3066 } 3067 break; 3068 } 3069 case ib_x: { 3070 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 3071 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 3072 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 3073 uint32_t msbit = widthminus1 + lsbit; 3074 if (msbit <= 31) { 3075 if (instr->Bit(22)) { 3076 // ubfx - unsigned bitfield extract. 3077 uint32_t rm_val = 3078 static_cast<uint32_t>(get_register(instr->RmValue())); 3079 uint32_t extr_val = rm_val << (31 - msbit); 3080 extr_val = extr_val >> (31 - widthminus1); 3081 set_register(instr->RdValue(), extr_val); 3082 } else { 3083 // sbfx - signed bitfield extract. 3084 int32_t rm_val = get_register(instr->RmValue()); 3085 int32_t extr_val = rm_val << (31 - msbit); 3086 extr_val = extr_val >> (31 - widthminus1); 3087 set_register(instr->RdValue(), extr_val); 3088 } 3089 } else { 3090 UNREACHABLE(); 3091 } 3092 return; 3093 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 3094 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 3095 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 3096 if (msbit >= lsbit) { 3097 // bfc or bfi - bitfield clear/insert. 3098 uint32_t rd_val = 3099 static_cast<uint32_t>(get_register(instr->RdValue())); 3100 uint32_t bitcount = msbit - lsbit + 1; 3101 uint32_t mask = 0xffffffffu >> (32 - bitcount); 3102 rd_val &= ~(mask << lsbit); 3103 if (instr->RmValue() != 15) { 3104 // bfi - bitfield insert. 3105 uint32_t rm_val = 3106 static_cast<uint32_t>(get_register(instr->RmValue())); 3107 rm_val &= mask; 3108 rd_val |= rm_val << lsbit; 3109 } 3110 set_register(instr->RdValue(), rd_val); 3111 } else { 3112 UNREACHABLE(); 3113 } 3114 return; 3115 } else { 3116 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 3117 addr = rn_val + shifter_operand; 3118 if (instr->HasW()) { 3119 set_register(rn, addr); 3120 } 3121 } 3122 break; 3123 } 3124 default: { 3125 UNREACHABLE(); 3126 break; 3127 } 3128 } 3129 if (instr->HasB()) { 3130 if (instr->HasL()) { 3131 uint8_t byte = ReadB(addr); 3132 set_register(rd, byte); 3133 } else { 3134 uint8_t byte = get_register(rd); 3135 WriteB(addr, byte); 3136 } 3137 } else { 3138 if (instr->HasL()) { 3139 set_register(rd, ReadW(addr, instr)); 3140 } else { 3141 WriteW(addr, get_register(rd), instr); 3142 } 3143 } 3144 } 3145 3146 3147 void Simulator::DecodeType4(Instruction* instr) { 3148 DCHECK(instr->Bit(22) == 0); // only allowed to be set in privileged mode 3149 if (instr->HasL()) { 3150 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 3151 HandleRList(instr, true); 3152 } else { 3153 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 3154 HandleRList(instr, false); 3155 } 3156 } 3157 3158 3159 void Simulator::DecodeType5(Instruction* instr) { 3160 // Format(instr, "b'l'cond 'target"); 3161 int off = (instr->SImmed24Value() << 2); 3162 intptr_t pc_address = get_pc(); 3163 if (instr->HasLink()) { 3164 set_register(lr, pc_address + Instruction::kInstrSize); 3165 } 3166 int pc_reg = get_register(pc); 3167 set_pc(pc_reg + off); 3168 } 3169 3170 3171 void Simulator::DecodeType6(Instruction* instr) { 3172 DecodeType6CoprocessorIns(instr); 3173 } 3174 3175 3176 void Simulator::DecodeType7(Instruction* instr) { 3177 if (instr->Bit(24) == 1) { 3178 SoftwareInterrupt(instr); 3179 } else { 3180 switch (instr->CoprocessorValue()) { 3181 case 10: // Fall through. 3182 case 11: 3183 DecodeTypeVFP(instr); 3184 break; 3185 case 15: 3186 DecodeTypeCP15(instr); 3187 break; 3188 default: 3189 UNIMPLEMENTED(); 3190 } 3191 } 3192 } 3193 3194 3195 // void Simulator::DecodeTypeVFP(Instruction* instr) 3196 // The Following ARMv7 VFPv instructions are currently supported. 3197 // vmov :Sn = Rt 3198 // vmov :Rt = Sn 3199 // vcvt: Dd = Sm 3200 // vcvt: Sd = Dm 3201 // vcvt.f64.s32 Dd, Dd, #<fbits> 3202 // Dd = vabs(Dm) 3203 // Sd = vabs(Sm) 3204 // Dd = vneg(Dm) 3205 // Sd = vneg(Sm) 3206 // Dd = vadd(Dn, Dm) 3207 // Sd = vadd(Sn, Sm) 3208 // Dd = vsub(Dn, Dm) 3209 // Sd = vsub(Sn, Sm) 3210 // Dd = vmul(Dn, Dm) 3211 // Sd = vmul(Sn, Sm) 3212 // Dd = vdiv(Dn, Dm) 3213 // Sd = vdiv(Sn, Sm) 3214 // vcmp(Dd, Dm) 3215 // vcmp(Sd, Sm) 3216 // Dd = vsqrt(Dm) 3217 // Sd = vsqrt(Sm) 3218 // vmrs 3219 // vdup.size Qd, Rt. 3220 void Simulator::DecodeTypeVFP(Instruction* instr) { 3221 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 3222 DCHECK(instr->Bits(11, 9) == 0x5); 3223 3224 // Obtain single precision register codes. 3225 int m = instr->VFPMRegValue(kSinglePrecision); 3226 int d = instr->VFPDRegValue(kSinglePrecision); 3227 int n = instr->VFPNRegValue(kSinglePrecision); 3228 // Obtain double precision register codes. 3229 int vm = instr->VFPMRegValue(kDoublePrecision); 3230 int vd = instr->VFPDRegValue(kDoublePrecision); 3231 int vn = instr->VFPNRegValue(kDoublePrecision); 3232 3233 if (instr->Bit(4) == 0) { 3234 if (instr->Opc1Value() == 0x7) { 3235 // Other data processing instructions 3236 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 3237 // vmov register to register. 3238 if (instr->SzValue() == 0x1) { 3239 uint32_t data[2]; 3240 get_d_register(vm, data); 3241 set_d_register(vd, data); 3242 } else { 3243 set_s_register(d, get_s_register(m)); 3244 } 3245 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 3246 // vabs 3247 if (instr->SzValue() == 0x1) { 3248 double dm_value = get_double_from_d_register(vm); 3249 double dd_value = std::fabs(dm_value); 3250 dd_value = canonicalizeNaN(dd_value); 3251 set_d_register_from_double(vd, dd_value); 3252 } else { 3253 float sm_value = get_float_from_s_register(m); 3254 float sd_value = std::fabs(sm_value); 3255 sd_value = canonicalizeNaN(sd_value); 3256 set_s_register_from_float(d, sd_value); 3257 } 3258 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 3259 // vneg 3260 if (instr->SzValue() == 0x1) { 3261 double dm_value = get_double_from_d_register(vm); 3262 double dd_value = -dm_value; 3263 dd_value = canonicalizeNaN(dd_value); 3264 set_d_register_from_double(vd, dd_value); 3265 } else { 3266 float sm_value = get_float_from_s_register(m); 3267 float sd_value = -sm_value; 3268 sd_value = canonicalizeNaN(sd_value); 3269 set_s_register_from_float(d, sd_value); 3270 } 3271 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 3272 DecodeVCVTBetweenDoubleAndSingle(instr); 3273 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 3274 DecodeVCVTBetweenFloatingPointAndInteger(instr); 3275 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && 3276 (instr->Bit(8) == 1)) { 3277 // vcvt.f64.s32 Dd, Dd, #<fbits> 3278 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); 3279 int fixed_value = get_sinteger_from_s_register(vd * 2); 3280 double divide = 1 << fraction_bits; 3281 set_d_register_from_double(vd, fixed_value / divide); 3282 } else if (((instr->Opc2Value() >> 1) == 0x6) && 3283 (instr->Opc3Value() & 0x1)) { 3284 DecodeVCVTBetweenFloatingPointAndInteger(instr); 3285 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 3286 (instr->Opc3Value() & 0x1)) { 3287 DecodeVCMP(instr); 3288 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 3289 // vsqrt 3290 lazily_initialize_fast_sqrt(isolate_); 3291 if (instr->SzValue() == 0x1) { 3292 double dm_value = get_double_from_d_register(vm); 3293 double dd_value = fast_sqrt(dm_value, isolate_); 3294 dd_value = canonicalizeNaN(dd_value); 3295 set_d_register_from_double(vd, dd_value); 3296 } else { 3297 float sm_value = get_float_from_s_register(m); 3298 float sd_value = fast_sqrt(sm_value, isolate_); 3299 sd_value = canonicalizeNaN(sd_value); 3300 set_s_register_from_float(d, sd_value); 3301 } 3302 } else if (instr->Opc3Value() == 0x0) { 3303 // vmov immediate. 3304 if (instr->SzValue() == 0x1) { 3305 set_d_register_from_double(vd, instr->DoubleImmedVmov()); 3306 } else { 3307 set_s_register_from_float(d, instr->DoubleImmedVmov()); 3308 } 3309 } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) { 3310 // vrintz - truncate 3311 if (instr->SzValue() == 0x1) { 3312 double dm_value = get_double_from_d_register(vm); 3313 double dd_value = trunc(dm_value); 3314 dd_value = canonicalizeNaN(dd_value); 3315 set_d_register_from_double(vd, dd_value); 3316 } else { 3317 float sm_value = get_float_from_s_register(m); 3318 float sd_value = truncf(sm_value); 3319 sd_value = canonicalizeNaN(sd_value); 3320 set_s_register_from_float(d, sd_value); 3321 } 3322 } else { 3323 UNREACHABLE(); // Not used by V8. 3324 } 3325 } else if (instr->Opc1Value() == 0x3) { 3326 if (instr->Opc3Value() & 0x1) { 3327 // vsub 3328 if (instr->SzValue() == 0x1) { 3329 double dn_value = get_double_from_d_register(vn); 3330 double dm_value = get_double_from_d_register(vm); 3331 double dd_value = dn_value - dm_value; 3332 dd_value = canonicalizeNaN(dd_value); 3333 set_d_register_from_double(vd, dd_value); 3334 } else { 3335 float sn_value = get_float_from_s_register(n); 3336 float sm_value = get_float_from_s_register(m); 3337 float sd_value = sn_value - sm_value; 3338 sd_value = canonicalizeNaN(sd_value); 3339 set_s_register_from_float(d, sd_value); 3340 } 3341 } else { 3342 // vadd 3343 if (instr->SzValue() == 0x1) { 3344 double dn_value = get_double_from_d_register(vn); 3345 double dm_value = get_double_from_d_register(vm); 3346 double dd_value = dn_value + dm_value; 3347 dd_value = canonicalizeNaN(dd_value); 3348 set_d_register_from_double(vd, dd_value); 3349 } else { 3350 float sn_value = get_float_from_s_register(n); 3351 float sm_value = get_float_from_s_register(m); 3352 float sd_value = sn_value + sm_value; 3353 sd_value = canonicalizeNaN(sd_value); 3354 set_s_register_from_float(d, sd_value); 3355 } 3356 } 3357 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 3358 // vmul 3359 if (instr->SzValue() == 0x1) { 3360 double dn_value = get_double_from_d_register(vn); 3361 double dm_value = get_double_from_d_register(vm); 3362 double dd_value = dn_value * dm_value; 3363 dd_value = canonicalizeNaN(dd_value); 3364 set_d_register_from_double(vd, dd_value); 3365 } else { 3366 float sn_value = get_float_from_s_register(n); 3367 float sm_value = get_float_from_s_register(m); 3368 float sd_value = sn_value * sm_value; 3369 sd_value = canonicalizeNaN(sd_value); 3370 set_s_register_from_float(d, sd_value); 3371 } 3372 } else if ((instr->Opc1Value() == 0x0)) { 3373 // vmla, vmls 3374 const bool is_vmls = (instr->Opc3Value() & 0x1); 3375 if (instr->SzValue() == 0x1) { 3376 const double dd_val = get_double_from_d_register(vd); 3377 const double dn_val = get_double_from_d_register(vn); 3378 const double dm_val = get_double_from_d_register(vm); 3379 3380 // Note: we do the mul and add/sub in separate steps to avoid getting a 3381 // result with too high precision. 3382 set_d_register_from_double(vd, dn_val * dm_val); 3383 if (is_vmls) { 3384 set_d_register_from_double( 3385 vd, canonicalizeNaN(dd_val - get_double_from_d_register(vd))); 3386 } else { 3387 set_d_register_from_double( 3388 vd, canonicalizeNaN(dd_val + get_double_from_d_register(vd))); 3389 } 3390 } else { 3391 const float sd_val = get_float_from_s_register(d); 3392 const float sn_val = get_float_from_s_register(n); 3393 const float sm_val = get_float_from_s_register(m); 3394 3395 // Note: we do the mul and add/sub in separate steps to avoid getting a 3396 // result with too high precision. 3397 set_s_register_from_float(d, sn_val * sm_val); 3398 if (is_vmls) { 3399 set_s_register_from_float( 3400 d, canonicalizeNaN(sd_val - get_float_from_s_register(d))); 3401 } else { 3402 set_s_register_from_float( 3403 d, canonicalizeNaN(sd_val + get_float_from_s_register(d))); 3404 } 3405 } 3406 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 3407 // vdiv 3408 if (instr->SzValue() == 0x1) { 3409 double dn_value = get_double_from_d_register(vn); 3410 double dm_value = get_double_from_d_register(vm); 3411 double dd_value = dn_value / dm_value; 3412 div_zero_vfp_flag_ = (dm_value == 0); 3413 dd_value = canonicalizeNaN(dd_value); 3414 set_d_register_from_double(vd, dd_value); 3415 } else { 3416 float sn_value = get_float_from_s_register(n); 3417 float sm_value = get_float_from_s_register(m); 3418 float sd_value = sn_value / sm_value; 3419 div_zero_vfp_flag_ = (sm_value == 0); 3420 sd_value = canonicalizeNaN(sd_value); 3421 set_s_register_from_float(d, sd_value); 3422 } 3423 } else { 3424 UNIMPLEMENTED(); // Not used by V8. 3425 } 3426 } else { 3427 if ((instr->VCValue() == 0x0) && 3428 (instr->VAValue() == 0x0)) { 3429 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 3430 } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) { 3431 if (instr->Bit(23) == 0) { 3432 // vmov (ARM core register to scalar) 3433 int vd = instr->VFPNRegValue(kDoublePrecision); 3434 int rt = instr->RtValue(); 3435 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5); 3436 if ((opc1_opc2 & 0xb) == 0) { 3437 // NeonS32/NeonU32 3438 uint32_t data[2]; 3439 get_d_register(vd, data); 3440 data[instr->Bit(21)] = get_register(rt); 3441 set_d_register(vd, data); 3442 } else { 3443 uint64_t data; 3444 get_d_register(vd, &data); 3445 uint64_t rt_value = get_register(rt); 3446 if ((opc1_opc2 & 0x8) != 0) { 3447 // NeonS8 / NeonU8 3448 int i = opc1_opc2 & 0x7; 3449 int shift = i * kBitsPerByte; 3450 const uint64_t mask = 0xFF; 3451 data &= ~(mask << shift); 3452 data |= (rt_value & mask) << shift; 3453 set_d_register(vd, &data); 3454 } else if ((opc1_opc2 & 0x1) != 0) { 3455 // NeonS16 / NeonU16 3456 int i = (opc1_opc2 >> 1) & 0x3; 3457 int shift = i * kBitsPerByte * kShortSize; 3458 const uint64_t mask = 0xFFFF; 3459 data &= ~(mask << shift); 3460 data |= (rt_value & mask) << shift; 3461 set_d_register(vd, &data); 3462 } else { 3463 UNREACHABLE(); // Not used by V8. 3464 } 3465 } 3466 } else { 3467 // vdup.size Qd, Rt. 3468 NeonSize size = Neon32; 3469 if (instr->Bit(5) != 0) 3470 size = Neon16; 3471 else if (instr->Bit(22) != 0) 3472 size = Neon8; 3473 int vd = instr->VFPNRegValue(kSimd128Precision); 3474 int rt = instr->RtValue(); 3475 uint32_t rt_value = get_register(rt); 3476 uint32_t q_data[4]; 3477 switch (size) { 3478 case Neon8: { 3479 rt_value &= 0xFF; 3480 uint8_t* dst = reinterpret_cast<uint8_t*>(q_data); 3481 for (int i = 0; i < 16; i++) { 3482 dst[i] = rt_value; 3483 } 3484 break; 3485 } 3486 case Neon16: { 3487 // Perform pairwise op. 3488 rt_value &= 0xFFFFu; 3489 uint32_t rt_rt = (rt_value << 16) | (rt_value & 0xFFFFu); 3490 for (int i = 0; i < 4; i++) { 3491 q_data[i] = rt_rt; 3492 } 3493 break; 3494 } 3495 case Neon32: { 3496 for (int i = 0; i < 4; i++) { 3497 q_data[i] = rt_value; 3498 } 3499 break; 3500 } 3501 default: 3502 UNREACHABLE(); 3503 break; 3504 } 3505 set_q_register(vd, q_data); 3506 } 3507 } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) { 3508 // vmov (scalar to ARM core register) 3509 int vn = instr->VFPNRegValue(kDoublePrecision); 3510 int rt = instr->RtValue(); 3511 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5); 3512 uint64_t data; 3513 get_d_register(vn, &data); 3514 if ((opc1_opc2 & 0xb) == 0) { 3515 // NeonS32 / NeonU32 3516 int32_t int_data[2]; 3517 memcpy(int_data, &data, sizeof(int_data)); 3518 set_register(rt, int_data[instr->Bit(21)]); 3519 } else { 3520 uint64_t data; 3521 get_d_register(vn, &data); 3522 bool u = instr->Bit(23) != 0; 3523 if ((opc1_opc2 & 0x8) != 0) { 3524 // NeonS8 / NeonU8 3525 int i = opc1_opc2 & 0x7; 3526 int shift = i * kBitsPerByte; 3527 uint32_t scalar = (data >> shift) & 0xFFu; 3528 if (!u && (scalar & 0x80) != 0) scalar |= 0xffffff00; 3529 set_register(rt, scalar); 3530 } else if ((opc1_opc2 & 0x1) != 0) { 3531 // NeonS16 / NeonU16 3532 int i = (opc1_opc2 >> 1) & 0x3; 3533 int shift = i * kBitsPerByte * kShortSize; 3534 uint32_t scalar = (data >> shift) & 0xFFFFu; 3535 if (!u && (scalar & 0x8000) != 0) scalar |= 0xffff0000; 3536 set_register(rt, scalar); 3537 } else { 3538 UNREACHABLE(); // Not used by V8. 3539 } 3540 } 3541 } else if ((instr->VLValue() == 0x1) && 3542 (instr->VCValue() == 0x0) && 3543 (instr->VAValue() == 0x7) && 3544 (instr->Bits(19, 16) == 0x1)) { 3545 // vmrs 3546 uint32_t rt = instr->RtValue(); 3547 if (rt == 0xF) { 3548 Copy_FPSCR_to_APSR(); 3549 } else { 3550 // Emulate FPSCR from the Simulator flags. 3551 uint32_t fpscr = (n_flag_FPSCR_ << 31) | 3552 (z_flag_FPSCR_ << 30) | 3553 (c_flag_FPSCR_ << 29) | 3554 (v_flag_FPSCR_ << 28) | 3555 (FPSCR_default_NaN_mode_ << 25) | 3556 (inexact_vfp_flag_ << 4) | 3557 (underflow_vfp_flag_ << 3) | 3558 (overflow_vfp_flag_ << 2) | 3559 (div_zero_vfp_flag_ << 1) | 3560 (inv_op_vfp_flag_ << 0) | 3561 (FPSCR_rounding_mode_); 3562 set_register(rt, fpscr); 3563 } 3564 } else if ((instr->VLValue() == 0x0) && 3565 (instr->VCValue() == 0x0) && 3566 (instr->VAValue() == 0x7) && 3567 (instr->Bits(19, 16) == 0x1)) { 3568 // vmsr 3569 uint32_t rt = instr->RtValue(); 3570 if (rt == pc) { 3571 UNREACHABLE(); 3572 } else { 3573 uint32_t rt_value = get_register(rt); 3574 n_flag_FPSCR_ = (rt_value >> 31) & 1; 3575 z_flag_FPSCR_ = (rt_value >> 30) & 1; 3576 c_flag_FPSCR_ = (rt_value >> 29) & 1; 3577 v_flag_FPSCR_ = (rt_value >> 28) & 1; 3578 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1; 3579 inexact_vfp_flag_ = (rt_value >> 4) & 1; 3580 underflow_vfp_flag_ = (rt_value >> 3) & 1; 3581 overflow_vfp_flag_ = (rt_value >> 2) & 1; 3582 div_zero_vfp_flag_ = (rt_value >> 1) & 1; 3583 inv_op_vfp_flag_ = (rt_value >> 0) & 1; 3584 FPSCR_rounding_mode_ = 3585 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); 3586 } 3587 } else { 3588 UNIMPLEMENTED(); // Not used by V8. 3589 } 3590 } 3591 } 3592 3593 void Simulator::DecodeTypeCP15(Instruction* instr) { 3594 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0)); 3595 DCHECK(instr->CoprocessorValue() == 15); 3596 3597 if (instr->Bit(4) == 1) { 3598 // mcr 3599 int crn = instr->Bits(19, 16); 3600 int crm = instr->Bits(3, 0); 3601 int opc1 = instr->Bits(23, 21); 3602 int opc2 = instr->Bits(7, 5); 3603 if ((opc1 == 0) && (crn == 7)) { 3604 // ARMv6 memory barrier operations. 3605 // Details available in ARM DDI 0406C.b, B3-1750. 3606 if (((crm == 10) && (opc2 == 5)) || // CP15DMB 3607 ((crm == 10) && (opc2 == 4)) || // CP15DSB 3608 ((crm == 5) && (opc2 == 4))) { // CP15ISB 3609 // These are ignored by the simulator for now. 3610 } else { 3611 UNIMPLEMENTED(); 3612 } 3613 } 3614 } else { 3615 UNIMPLEMENTED(); 3616 } 3617 } 3618 3619 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 3620 Instruction* instr) { 3621 DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 3622 (instr->VAValue() == 0x0)); 3623 3624 int t = instr->RtValue(); 3625 int n = instr->VFPNRegValue(kSinglePrecision); 3626 bool to_arm_register = (instr->VLValue() == 0x1); 3627 3628 if (to_arm_register) { 3629 int32_t int_value = get_sinteger_from_s_register(n); 3630 set_register(t, int_value); 3631 } else { 3632 int32_t rs_val = get_register(t); 3633 set_s_register_from_sinteger(n, rs_val); 3634 } 3635 } 3636 3637 3638 void Simulator::DecodeVCMP(Instruction* instr) { 3639 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 3640 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 3641 (instr->Opc3Value() & 0x1)); 3642 // Comparison. 3643 3644 VFPRegPrecision precision = kSinglePrecision; 3645 if (instr->SzValue() == 0x1) { 3646 precision = kDoublePrecision; 3647 } 3648 3649 int d = instr->VFPDRegValue(precision); 3650 int m = 0; 3651 if (instr->Opc2Value() == 0x4) { 3652 m = instr->VFPMRegValue(precision); 3653 } 3654 3655 if (precision == kDoublePrecision) { 3656 double dd_value = get_double_from_d_register(d); 3657 double dm_value = 0.0; 3658 if (instr->Opc2Value() == 0x4) { 3659 dm_value = get_double_from_d_register(m); 3660 } 3661 3662 // Raise exceptions for quiet NaNs if necessary. 3663 if (instr->Bit(7) == 1) { 3664 if (std::isnan(dd_value)) { 3665 inv_op_vfp_flag_ = true; 3666 } 3667 } 3668 3669 Compute_FPSCR_Flags(dd_value, dm_value); 3670 } else { 3671 float sd_value = get_float_from_s_register(d); 3672 float sm_value = 0.0; 3673 if (instr->Opc2Value() == 0x4) { 3674 sm_value = get_float_from_s_register(m); 3675 } 3676 3677 // Raise exceptions for quiet NaNs if necessary. 3678 if (instr->Bit(7) == 1) { 3679 if (std::isnan(sd_value)) { 3680 inv_op_vfp_flag_ = true; 3681 } 3682 } 3683 3684 Compute_FPSCR_Flags(sd_value, sm_value); 3685 } 3686 } 3687 3688 3689 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 3690 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 3691 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 3692 3693 VFPRegPrecision dst_precision = kDoublePrecision; 3694 VFPRegPrecision src_precision = kSinglePrecision; 3695 if (instr->SzValue() == 1) { 3696 dst_precision = kSinglePrecision; 3697 src_precision = kDoublePrecision; 3698 } 3699 3700 int dst = instr->VFPDRegValue(dst_precision); 3701 int src = instr->VFPMRegValue(src_precision); 3702 3703 if (dst_precision == kSinglePrecision) { 3704 double val = get_double_from_d_register(src); 3705 set_s_register_from_float(dst, static_cast<float>(val)); 3706 } else { 3707 float val = get_float_from_s_register(src); 3708 set_d_register_from_double(dst, static_cast<double>(val)); 3709 } 3710 } 3711 3712 bool get_inv_op_vfp_flag(VFPRoundingMode mode, 3713 double val, 3714 bool unsigned_) { 3715 DCHECK((mode == RN) || (mode == RM) || (mode == RZ)); 3716 double max_uint = static_cast<double>(0xffffffffu); 3717 double max_int = static_cast<double>(kMaxInt); 3718 double min_int = static_cast<double>(kMinInt); 3719 3720 // Check for NaN. 3721 if (val != val) { 3722 return true; 3723 } 3724 3725 // Check for overflow. This code works because 32bit integers can be 3726 // exactly represented by ieee-754 64bit floating-point values. 3727 switch (mode) { 3728 case RN: 3729 return unsigned_ ? (val >= (max_uint + 0.5)) || 3730 (val < -0.5) 3731 : (val >= (max_int + 0.5)) || 3732 (val < (min_int - 0.5)); 3733 3734 case RM: 3735 return unsigned_ ? (val >= (max_uint + 1.0)) || 3736 (val < 0) 3737 : (val >= (max_int + 1.0)) || 3738 (val < min_int); 3739 3740 case RZ: 3741 return unsigned_ ? (val >= (max_uint + 1.0)) || 3742 (val <= -1) 3743 : (val >= (max_int + 1.0)) || 3744 (val <= (min_int - 1.0)); 3745 default: 3746 UNREACHABLE(); 3747 return true; 3748 } 3749 } 3750 3751 3752 // We call this function only if we had a vfp invalid exception. 3753 // It returns the correct saturated value. 3754 int VFPConversionSaturate(double val, bool unsigned_res) { 3755 if (val != val) { 3756 return 0; 3757 } else { 3758 if (unsigned_res) { 3759 return (val < 0) ? 0 : 0xffffffffu; 3760 } else { 3761 return (val < 0) ? kMinInt : kMaxInt; 3762 } 3763 } 3764 } 3765 3766 int32_t Simulator::ConvertDoubleToInt(double val, bool unsigned_integer, 3767 VFPRoundingMode mode) { 3768 int32_t result = 3769 unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val); 3770 3771 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer); 3772 3773 double abs_diff = unsigned_integer 3774 ? std::fabs(val - static_cast<uint32_t>(result)) 3775 : std::fabs(val - result); 3776 3777 inexact_vfp_flag_ = (abs_diff != 0); 3778 3779 if (inv_op_vfp_flag_) { 3780 result = VFPConversionSaturate(val, unsigned_integer); 3781 } else { 3782 switch (mode) { 3783 case RN: { 3784 int val_sign = (val > 0) ? 1 : -1; 3785 if (abs_diff > 0.5) { 3786 result += val_sign; 3787 } else if (abs_diff == 0.5) { 3788 // Round to even if exactly halfway. 3789 result = ((result % 2) == 0) ? result : result + val_sign; 3790 } 3791 break; 3792 } 3793 3794 case RM: 3795 result = result > val ? result - 1 : result; 3796 break; 3797 3798 case RZ: 3799 // Nothing to do. 3800 break; 3801 3802 default: 3803 UNREACHABLE(); 3804 } 3805 } 3806 return result; 3807 } 3808 3809 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 3810 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) && 3811 (instr->Bits(27, 23) == 0x1D)); 3812 DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 3813 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 3814 3815 // Conversion between floating-point and integer. 3816 bool to_integer = (instr->Bit(18) == 1); 3817 3818 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision 3819 : kSinglePrecision; 3820 3821 if (to_integer) { 3822 // We are playing with code close to the C++ standard's limits below, 3823 // hence the very simple code and heavy checks. 3824 // 3825 // Note: 3826 // C++ defines default type casting from floating point to integer as 3827 // (close to) rounding toward zero ("fractional part discarded"). 3828 3829 int dst = instr->VFPDRegValue(kSinglePrecision); 3830 int src = instr->VFPMRegValue(src_precision); 3831 3832 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding 3833 // mode or the default Round to Zero mode. 3834 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_ 3835 : RZ; 3836 DCHECK((mode == RM) || (mode == RZ) || (mode == RN)); 3837 3838 bool unsigned_integer = (instr->Bit(16) == 0); 3839 bool double_precision = (src_precision == kDoublePrecision); 3840 3841 double val = double_precision ? get_double_from_d_register(src) 3842 : get_float_from_s_register(src); 3843 3844 int32_t temp = ConvertDoubleToInt(val, unsigned_integer, mode); 3845 3846 // Update the destination register. 3847 set_s_register_from_sinteger(dst, temp); 3848 3849 } else { 3850 bool unsigned_integer = (instr->Bit(7) == 0); 3851 3852 int dst = instr->VFPDRegValue(src_precision); 3853 int src = instr->VFPMRegValue(kSinglePrecision); 3854 3855 int val = get_sinteger_from_s_register(src); 3856 3857 if (src_precision == kDoublePrecision) { 3858 if (unsigned_integer) { 3859 set_d_register_from_double( 3860 dst, static_cast<double>(static_cast<uint32_t>(val))); 3861 } else { 3862 set_d_register_from_double(dst, static_cast<double>(val)); 3863 } 3864 } else { 3865 if (unsigned_integer) { 3866 set_s_register_from_float( 3867 dst, static_cast<float>(static_cast<uint32_t>(val))); 3868 } else { 3869 set_s_register_from_float(dst, static_cast<float>(val)); 3870 } 3871 } 3872 } 3873 } 3874 3875 3876 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr) 3877 // Decode Type 6 coprocessor instructions. 3878 // Dm = vmov(Rt, Rt2) 3879 // <Rt, Rt2> = vmov(Dm) 3880 // Ddst = MEM(Rbase + 4*offset). 3881 // MEM(Rbase + 4*offset) = Dsrc. 3882 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { 3883 DCHECK((instr->TypeValue() == 6)); 3884 3885 if (instr->CoprocessorValue() == 0xA) { 3886 switch (instr->OpcodeValue()) { 3887 case 0x8: 3888 case 0xA: 3889 case 0xC: 3890 case 0xE: { // Load and store single precision float to memory. 3891 int rn = instr->RnValue(); 3892 int vd = instr->VFPDRegValue(kSinglePrecision); 3893 int offset = instr->Immed8Value(); 3894 if (!instr->HasU()) { 3895 offset = -offset; 3896 } 3897 3898 int32_t address = get_register(rn) + 4 * offset; 3899 // Load and store address for singles must be at least four-byte 3900 // aligned. 3901 DCHECK((address % 4) == 0); 3902 if (instr->HasL()) { 3903 // Load single from memory: vldr. 3904 set_s_register_from_sinteger(vd, ReadW(address, instr)); 3905 } else { 3906 // Store single to memory: vstr. 3907 WriteW(address, get_sinteger_from_s_register(vd), instr); 3908 } 3909 break; 3910 } 3911 case 0x4: 3912 case 0x5: 3913 case 0x6: 3914 case 0x7: 3915 case 0x9: 3916 case 0xB: 3917 // Load/store multiple single from memory: vldm/vstm. 3918 HandleVList(instr); 3919 break; 3920 default: 3921 UNIMPLEMENTED(); // Not used by V8. 3922 } 3923 } else if (instr->CoprocessorValue() == 0xB) { 3924 switch (instr->OpcodeValue()) { 3925 case 0x2: 3926 // Load and store double to two GP registers 3927 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { 3928 UNIMPLEMENTED(); // Not used by V8. 3929 } else { 3930 int rt = instr->RtValue(); 3931 int rn = instr->RnValue(); 3932 int vm = instr->VFPMRegValue(kDoublePrecision); 3933 if (instr->HasL()) { 3934 uint32_t data[2]; 3935 get_d_register(vm, data); 3936 set_register(rt, data[0]); 3937 set_register(rn, data[1]); 3938 } else { 3939 int32_t data[] = { get_register(rt), get_register(rn) }; 3940 set_d_register(vm, reinterpret_cast<uint32_t*>(data)); 3941 } 3942 } 3943 break; 3944 case 0x8: 3945 case 0xA: 3946 case 0xC: 3947 case 0xE: { // Load and store double to memory. 3948 int rn = instr->RnValue(); 3949 int vd = instr->VFPDRegValue(kDoublePrecision); 3950 int offset = instr->Immed8Value(); 3951 if (!instr->HasU()) { 3952 offset = -offset; 3953 } 3954 int32_t address = get_register(rn) + 4 * offset; 3955 // Load and store address for doubles must be at least four-byte 3956 // aligned. 3957 DCHECK((address % 4) == 0); 3958 if (instr->HasL()) { 3959 // Load double from memory: vldr. 3960 int32_t data[] = { 3961 ReadW(address, instr), 3962 ReadW(address + 4, instr) 3963 }; 3964 set_d_register(vd, reinterpret_cast<uint32_t*>(data)); 3965 } else { 3966 // Store double to memory: vstr. 3967 uint32_t data[2]; 3968 get_d_register(vd, data); 3969 WriteW(address, data[0], instr); 3970 WriteW(address + 4, data[1], instr); 3971 } 3972 break; 3973 } 3974 case 0x4: 3975 case 0x5: 3976 case 0x6: 3977 case 0x7: 3978 case 0x9: 3979 case 0xB: 3980 // Load/store multiple double from memory: vldm/vstm. 3981 HandleVList(instr); 3982 break; 3983 default: 3984 UNIMPLEMENTED(); // Not used by V8. 3985 } 3986 } else { 3987 UNIMPLEMENTED(); // Not used by V8. 3988 } 3989 } 3990 3991 // Templated operations for NEON instructions. 3992 // TODO(bbudge) Add more templates for use in DecodeSpecialCondition. 3993 template <typename T> 3994 int64_t Widen(T value) { 3995 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); 3996 return static_cast<int64_t>(value); 3997 } 3998 3999 template <typename T> 4000 T Clamp(int64_t value) { 4001 static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); 4002 int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min()); 4003 int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max()); 4004 int64_t clamped = std::max(min, std::min(max, value)); 4005 return static_cast<T>(clamped); 4006 } 4007 4008 template <typename T> 4009 void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) { 4010 static const int kLanes = 16 / sizeof(T); 4011 T src1[kLanes], src2[kLanes]; 4012 simulator->get_q_register(Vn, src1); 4013 simulator->get_q_register(Vm, src2); 4014 for (int i = 0; i < kLanes; i++) { 4015 src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i])); 4016 } 4017 simulator->set_q_register(Vd, src1); 4018 } 4019 4020 template <typename T> 4021 void SubSaturate(Simulator* simulator, int Vd, int Vm, int Vn) { 4022 static const int kLanes = 16 / sizeof(T); 4023 T src1[kLanes], src2[kLanes]; 4024 simulator->get_q_register(Vn, src1); 4025 simulator->get_q_register(Vm, src2); 4026 for (int i = 0; i < kLanes; i++) { 4027 src1[i] = Clamp<T>(Widen(src1[i]) - Widen(src2[i])); 4028 } 4029 simulator->set_q_register(Vd, src1); 4030 } 4031 4032 void Simulator::DecodeSpecialCondition(Instruction* instr) { 4033 switch (instr->SpecialValue()) { 4034 case 4: { 4035 int Vd, Vm, Vn; 4036 if (instr->Bit(6) == 0) { 4037 Vd = instr->VFPDRegValue(kDoublePrecision); 4038 Vm = instr->VFPMRegValue(kDoublePrecision); 4039 Vn = instr->VFPNRegValue(kDoublePrecision); 4040 } else { 4041 Vd = instr->VFPDRegValue(kSimd128Precision); 4042 Vm = instr->VFPMRegValue(kSimd128Precision); 4043 Vn = instr->VFPNRegValue(kSimd128Precision); 4044 } 4045 switch (instr->Bits(11, 8)) { 4046 case 0x0: { 4047 if (instr->Bit(4) == 1) { 4048 // vqadd.s<size> Qd, Qm, Qn. 4049 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4050 switch (size) { 4051 case Neon8: 4052 AddSaturate<int8_t>(this, Vd, Vm, Vn); 4053 break; 4054 case Neon16: 4055 AddSaturate<int16_t>(this, Vd, Vm, Vn); 4056 break; 4057 case Neon32: 4058 AddSaturate<int32_t>(this, Vd, Vm, Vn); 4059 break; 4060 default: 4061 UNREACHABLE(); 4062 break; 4063 } 4064 } else { 4065 UNIMPLEMENTED(); 4066 } 4067 break; 4068 } 4069 case 0x1: { 4070 if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 && 4071 instr->Bit(4) == 1) { 4072 // vmov Qd, Qm. 4073 // vorr, Qd, Qm, Qn. 4074 uint32_t src1[4]; 4075 get_q_register(Vm, src1); 4076 if (Vm != Vn) { 4077 uint32_t src2[4]; 4078 get_q_register(Vn, src2); 4079 for (int i = 0; i < 4; i++) { 4080 src1[i] = src1[i] | src2[i]; 4081 } 4082 } 4083 set_q_register(Vd, src1); 4084 } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 && 4085 instr->Bit(4) == 1) { 4086 // vand Qd, Qm, Qn. 4087 uint32_t src1[4], src2[4]; 4088 get_q_register(Vn, src1); 4089 get_q_register(Vm, src2); 4090 for (int i = 0; i < 4; i++) { 4091 src1[i] = src1[i] & src2[i]; 4092 } 4093 set_q_register(Vd, src1); 4094 } else { 4095 UNIMPLEMENTED(); 4096 } 4097 break; 4098 } 4099 case 0x2: { 4100 if (instr->Bit(4) == 1) { 4101 // vqsub.s<size> Qd, Qm, Qn. 4102 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4103 switch (size) { 4104 case Neon8: 4105 SubSaturate<int8_t>(this, Vd, Vm, Vn); 4106 break; 4107 case Neon16: 4108 SubSaturate<int16_t>(this, Vd, Vm, Vn); 4109 break; 4110 case Neon32: 4111 SubSaturate<int32_t>(this, Vd, Vm, Vn); 4112 break; 4113 default: 4114 UNREACHABLE(); 4115 break; 4116 } 4117 } else { 4118 UNIMPLEMENTED(); 4119 } 4120 break; 4121 } 4122 case 0x3: { 4123 // vcge/vcgt.s<size> Qd, Qm, Qn. 4124 bool ge = instr->Bit(4) == 1; 4125 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4126 switch (size) { 4127 case Neon8: { 4128 int8_t src1[16], src2[16]; 4129 get_q_register(Vn, src1); 4130 get_q_register(Vm, src2); 4131 for (int i = 0; i < 16; i++) { 4132 if (ge) 4133 src1[i] = src1[i] >= src2[i] ? 0xFF : 0; 4134 else 4135 src1[i] = src1[i] > src2[i] ? 0xFF : 0; 4136 } 4137 set_q_register(Vd, src1); 4138 break; 4139 } 4140 case Neon16: { 4141 int16_t src1[8], src2[8]; 4142 get_q_register(Vn, src1); 4143 get_q_register(Vm, src2); 4144 for (int i = 0; i < 8; i++) { 4145 if (ge) 4146 src1[i] = src1[i] >= src2[i] ? 0xFFFF : 0; 4147 else 4148 src1[i] = src1[i] > src2[i] ? 0xFFFF : 0; 4149 } 4150 set_q_register(Vd, src1); 4151 break; 4152 } 4153 case Neon32: { 4154 int32_t src1[4], src2[4]; 4155 get_q_register(Vn, src1); 4156 get_q_register(Vm, src2); 4157 for (int i = 0; i < 4; i++) { 4158 if (ge) 4159 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0; 4160 else 4161 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0; 4162 } 4163 set_q_register(Vd, src1); 4164 break; 4165 } 4166 default: 4167 UNREACHABLE(); 4168 break; 4169 } 4170 break; 4171 } 4172 case 0x6: { 4173 // vmin/vmax.s<size> Qd, Qm, Qn. 4174 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4175 bool min = instr->Bit(4) != 0; 4176 switch (size) { 4177 case Neon8: { 4178 int8_t src1[16], src2[16]; 4179 get_q_register(Vn, src1); 4180 get_q_register(Vm, src2); 4181 for (int i = 0; i < 16; i++) { 4182 if (min) 4183 src1[i] = std::min(src1[i], src2[i]); 4184 else 4185 src1[i] = std::max(src1[i], src2[i]); 4186 } 4187 set_q_register(Vd, src1); 4188 break; 4189 } 4190 case Neon16: { 4191 int16_t src1[8], src2[8]; 4192 get_q_register(Vn, src1); 4193 get_q_register(Vm, src2); 4194 for (int i = 0; i < 8; i++) { 4195 if (min) 4196 src1[i] = std::min(src1[i], src2[i]); 4197 else 4198 src1[i] = std::max(src1[i], src2[i]); 4199 } 4200 set_q_register(Vd, src1); 4201 break; 4202 } 4203 case Neon32: { 4204 int32_t src1[4], src2[4]; 4205 get_q_register(Vn, src1); 4206 get_q_register(Vm, src2); 4207 for (int i = 0; i < 4; i++) { 4208 if (min) 4209 src1[i] = std::min(src1[i], src2[i]); 4210 else 4211 src1[i] = std::max(src1[i], src2[i]); 4212 } 4213 set_q_register(Vd, src1); 4214 break; 4215 } 4216 default: 4217 UNREACHABLE(); 4218 break; 4219 } 4220 break; 4221 } 4222 case 0x8: { 4223 // vadd/vtst 4224 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4225 if (instr->Bit(4) == 0) { 4226 // vadd.i<size> Qd, Qm, Qn. 4227 switch (size) { 4228 case Neon8: { 4229 uint8_t src1[16], src2[16]; 4230 get_q_register(Vn, src1); 4231 get_q_register(Vm, src2); 4232 for (int i = 0; i < 16; i++) { 4233 src1[i] += src2[i]; 4234 } 4235 set_q_register(Vd, src1); 4236 break; 4237 } 4238 case Neon16: { 4239 uint16_t src1[8], src2[8]; 4240 get_q_register(Vn, src1); 4241 get_q_register(Vm, src2); 4242 for (int i = 0; i < 8; i++) { 4243 src1[i] += src2[i]; 4244 } 4245 set_q_register(Vd, src1); 4246 break; 4247 } 4248 case Neon32: { 4249 uint32_t src1[4], src2[4]; 4250 get_q_register(Vn, src1); 4251 get_q_register(Vm, src2); 4252 for (int i = 0; i < 4; i++) { 4253 src1[i] += src2[i]; 4254 } 4255 set_q_register(Vd, src1); 4256 break; 4257 } 4258 default: 4259 UNREACHABLE(); 4260 break; 4261 } 4262 } else { 4263 // vtst.i<size> Qd, Qm, Qn. 4264 switch (size) { 4265 case Neon8: { 4266 uint8_t src1[16], src2[16]; 4267 get_q_register(Vn, src1); 4268 get_q_register(Vm, src2); 4269 for (int i = 0; i < 16; i++) { 4270 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFu : 0; 4271 } 4272 set_q_register(Vd, src1); 4273 break; 4274 } 4275 case Neon16: { 4276 uint16_t src1[8], src2[8]; 4277 get_q_register(Vn, src1); 4278 get_q_register(Vm, src2); 4279 for (int i = 0; i < 8; i++) { 4280 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFu : 0; 4281 } 4282 set_q_register(Vd, src1); 4283 break; 4284 } 4285 case Neon32: { 4286 uint32_t src1[4], src2[4]; 4287 get_q_register(Vn, src1); 4288 get_q_register(Vm, src2); 4289 for (int i = 0; i < 4; i++) { 4290 src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFFFFFu : 0; 4291 } 4292 set_q_register(Vd, src1); 4293 break; 4294 } 4295 default: 4296 UNREACHABLE(); 4297 break; 4298 } 4299 } 4300 break; 4301 } 4302 case 0x9: { 4303 if (instr->Bit(6) == 1 && instr->Bit(4) == 1) { 4304 // vmul.i<size> Qd, Qm, Qn. 4305 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4306 switch (size) { 4307 case Neon8: { 4308 uint8_t src1[16], src2[16]; 4309 get_q_register(Vn, src1); 4310 get_q_register(Vm, src2); 4311 for (int i = 0; i < 16; i++) { 4312 src1[i] *= src2[i]; 4313 } 4314 set_q_register(Vd, src1); 4315 break; 4316 } 4317 case Neon16: { 4318 uint16_t src1[8], src2[8]; 4319 get_q_register(Vn, src1); 4320 get_q_register(Vm, src2); 4321 for (int i = 0; i < 8; i++) { 4322 src1[i] *= src2[i]; 4323 } 4324 set_q_register(Vd, src1); 4325 break; 4326 } 4327 case Neon32: { 4328 uint32_t src1[4], src2[4]; 4329 get_q_register(Vn, src1); 4330 get_q_register(Vm, src2); 4331 for (int i = 0; i < 4; i++) { 4332 src1[i] *= src2[i]; 4333 } 4334 set_q_register(Vd, src1); 4335 break; 4336 } 4337 default: 4338 UNREACHABLE(); 4339 break; 4340 } 4341 } else { 4342 UNIMPLEMENTED(); 4343 } 4344 break; 4345 } 4346 case 0xd: { 4347 if (instr->Bit(4) == 0) { 4348 float src1[4], src2[4]; 4349 get_q_register(Vn, src1); 4350 get_q_register(Vm, src2); 4351 for (int i = 0; i < 4; i++) { 4352 if (instr->Bit(21) == 0) { 4353 // vadd.f32 Qd, Qm, Qn. 4354 src1[i] = src1[i] + src2[i]; 4355 } else { 4356 // vsub.f32 Qd, Qm, Qn. 4357 src1[i] = src1[i] - src2[i]; 4358 } 4359 } 4360 set_q_register(Vd, src1); 4361 } else { 4362 UNIMPLEMENTED(); 4363 } 4364 break; 4365 } 4366 case 0xe: { 4367 if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) { 4368 // vceq.f32. 4369 float src1[4], src2[4]; 4370 get_q_register(Vn, src1); 4371 get_q_register(Vm, src2); 4372 uint32_t dst[4]; 4373 for (int i = 0; i < 4; i++) { 4374 dst[i] = (src1[i] == src2[i]) ? 0xFFFFFFFF : 0; 4375 } 4376 set_q_register(Vd, dst); 4377 } else { 4378 UNIMPLEMENTED(); 4379 } 4380 break; 4381 } 4382 case 0xf: { 4383 if (instr->Bit(20) == 0 && instr->Bit(6) == 1) { 4384 float src1[4], src2[4]; 4385 get_q_register(Vn, src1); 4386 get_q_register(Vm, src2); 4387 if (instr->Bit(4) == 1) { 4388 if (instr->Bit(21) == 0) { 4389 // vrecps.f32 Qd, Qm, Qn. 4390 for (int i = 0; i < 4; i++) { 4391 src1[i] = 2.0f - src1[i] * src2[i]; 4392 } 4393 } else { 4394 // vrsqrts.f32 Qd, Qm, Qn. 4395 for (int i = 0; i < 4; i++) { 4396 src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f; 4397 } 4398 } 4399 } else { 4400 if (instr->Bit(21) == 1) { 4401 // vmin.f32 Qd, Qm, Qn. 4402 for (int i = 0; i < 4; i++) { 4403 src1[i] = std::min(src1[i], src2[i]); 4404 } 4405 } else { 4406 // vmax.f32 Qd, Qm, Qn. 4407 for (int i = 0; i < 4; i++) { 4408 src1[i] = std::max(src1[i], src2[i]); 4409 } 4410 } 4411 } 4412 set_q_register(Vd, src1); 4413 } else { 4414 UNIMPLEMENTED(); 4415 } 4416 break; 4417 } 4418 default: 4419 UNIMPLEMENTED(); 4420 break; 4421 } 4422 break; 4423 } 4424 case 5: 4425 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 4426 (instr->Bit(4) == 1)) { 4427 // vmovl signed 4428 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED(); 4429 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 4430 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 4431 int imm3 = instr->Bits(21, 19); 4432 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); 4433 int esize = 8 * imm3; 4434 int elements = 64 / esize; 4435 int8_t from[8]; 4436 get_d_register(Vm, reinterpret_cast<uint64_t*>(from)); 4437 int16_t to[8]; 4438 int e = 0; 4439 while (e < elements) { 4440 to[e] = from[e]; 4441 e++; 4442 } 4443 set_q_register(Vd, reinterpret_cast<uint64_t*>(to)); 4444 } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) { 4445 // vext. 4446 int imm4 = instr->Bits(11, 8); 4447 int Vd = instr->VFPDRegValue(kSimd128Precision); 4448 int Vm = instr->VFPMRegValue(kSimd128Precision); 4449 int Vn = instr->VFPNRegValue(kSimd128Precision); 4450 uint8_t src1[16], src2[16], dst[16]; 4451 get_q_register(Vn, src1); 4452 get_q_register(Vm, src2); 4453 int boundary = kSimd128Size - imm4; 4454 int i = 0; 4455 for (; i < boundary; i++) { 4456 dst[i] = src1[i + imm4]; 4457 } 4458 for (; i < 16; i++) { 4459 dst[i] = src2[i - boundary]; 4460 } 4461 set_q_register(Vd, dst); 4462 } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) { 4463 // vshl.i<size> Qd, Qm, shift 4464 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); 4465 int shift = instr->Bits(21, 16) - size; 4466 int Vd = instr->VFPDRegValue(kSimd128Precision); 4467 int Vm = instr->VFPMRegValue(kSimd128Precision); 4468 NeonSize ns = static_cast<NeonSize>(size / 16); 4469 switch (ns) { 4470 case Neon8: { 4471 uint8_t src[16]; 4472 get_q_register(Vm, src); 4473 for (int i = 0; i < 16; i++) { 4474 src[i] <<= shift; 4475 } 4476 set_q_register(Vd, src); 4477 break; 4478 } 4479 case Neon16: { 4480 uint16_t src[8]; 4481 get_q_register(Vm, src); 4482 for (int i = 0; i < 8; i++) { 4483 src[i] <<= shift; 4484 } 4485 set_q_register(Vd, src); 4486 break; 4487 } 4488 case Neon32: { 4489 uint32_t src[4]; 4490 get_q_register(Vm, src); 4491 for (int i = 0; i < 4; i++) { 4492 src[i] <<= shift; 4493 } 4494 set_q_register(Vd, src); 4495 break; 4496 } 4497 default: 4498 UNREACHABLE(); 4499 break; 4500 } 4501 } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { 4502 // vshr.s<size> Qd, Qm, shift 4503 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); 4504 int shift = 2 * size - instr->Bits(21, 16); 4505 int Vd = instr->VFPDRegValue(kSimd128Precision); 4506 int Vm = instr->VFPMRegValue(kSimd128Precision); 4507 NeonSize ns = static_cast<NeonSize>(size / 16); 4508 switch (ns) { 4509 case Neon8: { 4510 int8_t src[16]; 4511 get_q_register(Vm, src); 4512 for (int i = 0; i < 16; i++) { 4513 src[i] = ArithmeticShiftRight(src[i], shift); 4514 } 4515 set_q_register(Vd, src); 4516 break; 4517 } 4518 case Neon16: { 4519 int16_t src[8]; 4520 get_q_register(Vm, src); 4521 for (int i = 0; i < 8; i++) { 4522 src[i] = ArithmeticShiftRight(src[i], shift); 4523 } 4524 set_q_register(Vd, src); 4525 break; 4526 } 4527 case Neon32: { 4528 int32_t src[4]; 4529 get_q_register(Vm, src); 4530 for (int i = 0; i < 4; i++) { 4531 src[i] = ArithmeticShiftRight(src[i], shift); 4532 } 4533 set_q_register(Vd, src); 4534 break; 4535 } 4536 default: 4537 UNREACHABLE(); 4538 break; 4539 } 4540 } else { 4541 UNIMPLEMENTED(); 4542 } 4543 break; 4544 case 6: { 4545 int Vd, Vm, Vn; 4546 if (instr->Bit(6) == 0) { 4547 Vd = instr->VFPDRegValue(kDoublePrecision); 4548 Vm = instr->VFPMRegValue(kDoublePrecision); 4549 Vn = instr->VFPNRegValue(kDoublePrecision); 4550 } else { 4551 Vd = instr->VFPDRegValue(kSimd128Precision); 4552 Vm = instr->VFPMRegValue(kSimd128Precision); 4553 Vn = instr->VFPNRegValue(kSimd128Precision); 4554 } 4555 switch (instr->Bits(11, 8)) { 4556 case 0x0: { 4557 if (instr->Bit(4) == 1) { 4558 // vqadd.u<size> Qd, Qm, Qn. 4559 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4560 switch (size) { 4561 case Neon8: 4562 AddSaturate<uint8_t>(this, Vd, Vm, Vn); 4563 break; 4564 case Neon16: 4565 AddSaturate<uint16_t>(this, Vd, Vm, Vn); 4566 break; 4567 case Neon32: 4568 AddSaturate<uint32_t>(this, Vd, Vm, Vn); 4569 break; 4570 default: 4571 UNREACHABLE(); 4572 break; 4573 } 4574 } else { 4575 UNIMPLEMENTED(); 4576 } 4577 break; 4578 } 4579 case 0x1: { 4580 if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) { 4581 // vbsl.size Qd, Qm, Qn. 4582 uint32_t dst[4], src1[4], src2[4]; 4583 get_q_register(Vd, dst); 4584 get_q_register(Vn, src1); 4585 get_q_register(Vm, src2); 4586 for (int i = 0; i < 4; i++) { 4587 dst[i] = (dst[i] & src1[i]) | (~dst[i] & src2[i]); 4588 } 4589 set_q_register(Vd, dst); 4590 } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) { 4591 if (instr->Bit(6) == 0) { 4592 // veor Dd, Dn, Dm 4593 uint64_t src1, src2; 4594 get_d_register(Vn, &src1); 4595 get_d_register(Vm, &src2); 4596 src1 ^= src2; 4597 set_d_register(Vd, &src1); 4598 4599 } else { 4600 // veor Qd, Qn, Qm 4601 uint32_t src1[4], src2[4]; 4602 get_q_register(Vn, src1); 4603 get_q_register(Vm, src2); 4604 for (int i = 0; i < 4; i++) src1[i] ^= src2[i]; 4605 set_q_register(Vd, src1); 4606 } 4607 } else { 4608 UNIMPLEMENTED(); 4609 } 4610 break; 4611 } 4612 case 0x2: { 4613 if (instr->Bit(4) == 1) { 4614 // vqsub.u<size> Qd, Qm, Qn. 4615 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4616 switch (size) { 4617 case Neon8: 4618 SubSaturate<uint8_t>(this, Vd, Vm, Vn); 4619 break; 4620 case Neon16: 4621 SubSaturate<uint16_t>(this, Vd, Vm, Vn); 4622 break; 4623 case Neon32: 4624 SubSaturate<uint32_t>(this, Vd, Vm, Vn); 4625 break; 4626 default: 4627 UNREACHABLE(); 4628 break; 4629 } 4630 } else { 4631 UNIMPLEMENTED(); 4632 } 4633 break; 4634 } 4635 case 0x3: { 4636 // vcge/vcgt.u<size> Qd, Qm, Qn. 4637 bool ge = instr->Bit(4) == 1; 4638 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4639 switch (size) { 4640 case Neon8: { 4641 uint8_t src1[16], src2[16]; 4642 get_q_register(Vn, src1); 4643 get_q_register(Vm, src2); 4644 for (int i = 0; i < 16; i++) { 4645 if (ge) 4646 src1[i] = src1[i] >= src2[i] ? 0xFFu : 0; 4647 else 4648 src1[i] = src1[i] > src2[i] ? 0xFFu : 0; 4649 } 4650 set_q_register(Vd, src1); 4651 break; 4652 } 4653 case Neon16: { 4654 uint16_t src1[8], src2[8]; 4655 get_q_register(Vn, src1); 4656 get_q_register(Vm, src2); 4657 for (int i = 0; i < 8; i++) { 4658 if (ge) 4659 src1[i] = src1[i] >= src2[i] ? 0xFFFFu : 0; 4660 else 4661 src1[i] = src1[i] > src2[i] ? 0xFFFFu : 0; 4662 } 4663 set_q_register(Vd, src1); 4664 break; 4665 } 4666 case Neon32: { 4667 uint32_t src1[4], src2[4]; 4668 get_q_register(Vn, src1); 4669 get_q_register(Vm, src2); 4670 for (int i = 0; i < 4; i++) { 4671 if (ge) 4672 src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0; 4673 else 4674 src1[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0; 4675 } 4676 set_q_register(Vd, src1); 4677 break; 4678 } 4679 default: 4680 UNREACHABLE(); 4681 break; 4682 } 4683 break; 4684 } 4685 case 0x6: { 4686 // vmin/vmax.u<size> Qd, Qm, Qn. 4687 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4688 bool min = instr->Bit(4) != 0; 4689 switch (size) { 4690 case Neon8: { 4691 uint8_t src1[16], src2[16]; 4692 get_q_register(Vn, src1); 4693 get_q_register(Vm, src2); 4694 for (int i = 0; i < 16; i++) { 4695 if (min) 4696 src1[i] = std::min(src1[i], src2[i]); 4697 else 4698 src1[i] = std::max(src1[i], src2[i]); 4699 } 4700 set_q_register(Vd, src1); 4701 break; 4702 } 4703 case Neon16: { 4704 uint16_t src1[8], src2[8]; 4705 get_q_register(Vn, src1); 4706 get_q_register(Vm, src2); 4707 for (int i = 0; i < 8; i++) { 4708 if (min) 4709 src1[i] = std::min(src1[i], src2[i]); 4710 else 4711 src1[i] = std::max(src1[i], src2[i]); 4712 } 4713 set_q_register(Vd, src1); 4714 break; 4715 } 4716 case Neon32: { 4717 uint32_t src1[4], src2[4]; 4718 get_q_register(Vn, src1); 4719 get_q_register(Vm, src2); 4720 for (int i = 0; i < 4; i++) { 4721 if (min) 4722 src1[i] = std::min(src1[i], src2[i]); 4723 else 4724 src1[i] = std::max(src1[i], src2[i]); 4725 } 4726 set_q_register(Vd, src1); 4727 break; 4728 } 4729 default: 4730 UNREACHABLE(); 4731 break; 4732 } 4733 break; 4734 } 4735 case 0x8: { 4736 if (instr->Bit(4) == 0) { 4737 // vsub.size Qd, Qm, Qn. 4738 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4739 switch (size) { 4740 case Neon8: { 4741 uint8_t src1[16], src2[16]; 4742 get_q_register(Vn, src1); 4743 get_q_register(Vm, src2); 4744 for (int i = 0; i < 16; i++) { 4745 src1[i] -= src2[i]; 4746 } 4747 set_q_register(Vd, src1); 4748 break; 4749 } 4750 case Neon16: { 4751 uint16_t src1[8], src2[8]; 4752 get_q_register(Vn, src1); 4753 get_q_register(Vm, src2); 4754 for (int i = 0; i < 8; i++) { 4755 src1[i] -= src2[i]; 4756 } 4757 set_q_register(Vd, src1); 4758 break; 4759 } 4760 case Neon32: { 4761 uint32_t src1[4], src2[4]; 4762 get_q_register(Vn, src1); 4763 get_q_register(Vm, src2); 4764 for (int i = 0; i < 4; i++) { 4765 src1[i] -= src2[i]; 4766 } 4767 set_q_register(Vd, src1); 4768 break; 4769 } 4770 default: 4771 UNREACHABLE(); 4772 break; 4773 } 4774 } else { 4775 // vceq.size Qd, Qm, Qn. 4776 NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20)); 4777 switch (size) { 4778 case Neon8: { 4779 uint8_t src1[16], src2[16]; 4780 get_q_register(Vn, src1); 4781 get_q_register(Vm, src2); 4782 for (int i = 0; i < 16; i++) { 4783 src1[i] = (src1[i] == src2[i]) ? 0xFFu : 0; 4784 } 4785 set_q_register(Vd, src1); 4786 break; 4787 } 4788 case Neon16: { 4789 uint16_t src1[8], src2[8]; 4790 get_q_register(Vn, src1); 4791 get_q_register(Vm, src2); 4792 for (int i = 0; i < 8; i++) { 4793 src1[i] = (src1[i] == src2[i]) ? 0xFFFFu : 0; 4794 } 4795 set_q_register(Vd, src1); 4796 break; 4797 } 4798 case Neon32: { 4799 uint32_t src1[4], src2[4]; 4800 get_q_register(Vn, src1); 4801 get_q_register(Vm, src2); 4802 for (int i = 0; i < 4; i++) { 4803 src1[i] = (src1[i] == src2[i]) ? 0xFFFFFFFFu : 0; 4804 } 4805 set_q_register(Vd, src1); 4806 break; 4807 } 4808 default: 4809 UNREACHABLE(); 4810 break; 4811 } 4812 } 4813 break; 4814 } 4815 case 0xd: { 4816 if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) { 4817 // vmul.f32 Qd, Qn, Qm 4818 float src1[4], src2[4]; 4819 get_q_register(Vn, src1); 4820 get_q_register(Vm, src2); 4821 for (int i = 0; i < 4; i++) { 4822 src1[i] = src1[i] * src2[i]; 4823 } 4824 set_q_register(Vd, src1); 4825 } else { 4826 UNIMPLEMENTED(); 4827 } 4828 break; 4829 } 4830 case 0xe: { 4831 if (instr->Bit(20) == 0 && instr->Bit(4) == 0) { 4832 // vcge/vcgt.f32 Qd, Qm, Qn 4833 bool ge = instr->Bit(21) == 0; 4834 float src1[4], src2[4]; 4835 get_q_register(Vn, src1); 4836 get_q_register(Vm, src2); 4837 uint32_t dst[4]; 4838 for (int i = 0; i < 4; i++) { 4839 if (ge) { 4840 dst[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0; 4841 } else { 4842 dst[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0; 4843 } 4844 } 4845 set_q_register(Vd, dst); 4846 } else { 4847 UNIMPLEMENTED(); 4848 } 4849 break; 4850 } 4851 default: 4852 UNREACHABLE(); 4853 break; 4854 } 4855 break; 4856 } 4857 case 7: 4858 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && 4859 (instr->Bit(4) == 1)) { 4860 // vmovl unsigned 4861 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED(); 4862 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1); 4863 int Vm = (instr->Bit(5) << 4) | instr->VmValue(); 4864 int imm3 = instr->Bits(21, 19); 4865 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED(); 4866 int esize = 8 * imm3; 4867 int elements = 64 / esize; 4868 uint8_t from[8]; 4869 get_d_register(Vm, reinterpret_cast<uint64_t*>(from)); 4870 uint16_t to[8]; 4871 int e = 0; 4872 while (e < elements) { 4873 to[e] = from[e]; 4874 e++; 4875 } 4876 set_q_register(Vd, reinterpret_cast<uint64_t*>(to)); 4877 } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) { 4878 if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 && 4879 instr->Bit(6) == 1) { 4880 // vcvt.<Td>.<Tm> Qd, Qm. 4881 int Vd = instr->VFPDRegValue(kSimd128Precision); 4882 int Vm = instr->VFPMRegValue(kSimd128Precision); 4883 uint32_t q_data[4]; 4884 get_q_register(Vm, q_data); 4885 int op = instr->Bits(8, 7); 4886 for (int i = 0; i < 4; i++) { 4887 switch (op) { 4888 case 0: 4889 // f32 <- s32, round towards nearest. 4890 q_data[i] = bit_cast<uint32_t>(std::round( 4891 static_cast<float>(bit_cast<int32_t>(q_data[i])))); 4892 break; 4893 case 1: 4894 // f32 <- u32, round towards nearest. 4895 q_data[i] = bit_cast<uint32_t>( 4896 std::round(static_cast<float>(q_data[i]))); 4897 break; 4898 case 2: 4899 // s32 <- f32, round to zero. 4900 q_data[i] = static_cast<uint32_t>( 4901 ConvertDoubleToInt(bit_cast<float>(q_data[i]), false, RZ)); 4902 break; 4903 case 3: 4904 // u32 <- f32, round to zero. 4905 q_data[i] = static_cast<uint32_t>( 4906 ConvertDoubleToInt(bit_cast<float>(q_data[i]), true, RZ)); 4907 break; 4908 } 4909 } 4910 set_q_register(Vd, q_data); 4911 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) { 4912 if (instr->Bit(6) == 0) { 4913 // vswp Dd, Dm. 4914 uint64_t dval, mval; 4915 int vd = instr->VFPDRegValue(kDoublePrecision); 4916 int vm = instr->VFPMRegValue(kDoublePrecision); 4917 get_d_register(vd, &dval); 4918 get_d_register(vm, &mval); 4919 set_d_register(vm, &dval); 4920 set_d_register(vd, &mval); 4921 } else { 4922 // vswp Qd, Qm. 4923 uint32_t dval[4], mval[4]; 4924 int vd = instr->VFPDRegValue(kSimd128Precision); 4925 int vm = instr->VFPMRegValue(kSimd128Precision); 4926 get_q_register(vd, dval); 4927 get_q_register(vm, mval); 4928 set_q_register(vm, dval); 4929 set_q_register(vd, mval); 4930 } 4931 } else if (instr->Bits(11, 7) == 0x18) { 4932 // vdup.32 Qd, Sm. 4933 int vd = instr->VFPDRegValue(kSimd128Precision); 4934 int vm = instr->VFPMRegValue(kDoublePrecision); 4935 int index = instr->Bit(19); 4936 uint32_t s_data = get_s_register(vm * 2 + index); 4937 uint32_t q_data[4]; 4938 for (int i = 0; i < 4; i++) q_data[i] = s_data; 4939 set_q_register(vd, q_data); 4940 } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) { 4941 // vmvn Qd, Qm. 4942 int vd = instr->VFPDRegValue(kSimd128Precision); 4943 int vm = instr->VFPMRegValue(kSimd128Precision); 4944 uint32_t q_data[4]; 4945 get_q_register(vm, q_data); 4946 for (int i = 0; i < 4; i++) q_data[i] = ~q_data[i]; 4947 set_q_register(vd, q_data); 4948 } else if (instr->Bits(11, 10) == 0x2) { 4949 // vtb[l,x] Dd, <list>, Dm. 4950 int vd = instr->VFPDRegValue(kDoublePrecision); 4951 int vn = instr->VFPNRegValue(kDoublePrecision); 4952 int vm = instr->VFPMRegValue(kDoublePrecision); 4953 int table_len = (instr->Bits(9, 8) + 1) * kDoubleSize; 4954 bool vtbx = instr->Bit(6) != 0; // vtbl / vtbx 4955 uint64_t destination = 0, indices = 0, result = 0; 4956 get_d_register(vd, &destination); 4957 get_d_register(vm, &indices); 4958 for (int i = 0; i < kDoubleSize; i++) { 4959 int shift = i * kBitsPerByte; 4960 int index = (indices >> shift) & 0xFF; 4961 if (index < table_len) { 4962 uint64_t table; 4963 get_d_register(vn + index / kDoubleSize, &table); 4964 result |= 4965 ((table >> ((index % kDoubleSize) * kBitsPerByte)) & 0xFF) 4966 << shift; 4967 } else if (vtbx) { 4968 result |= destination & (0xFFull << shift); 4969 } 4970 } 4971 set_d_register(vd, &result); 4972 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) { 4973 // vzip.<size> Qd, Qm. 4974 NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); 4975 int Vd = instr->VFPDRegValue(kSimd128Precision); 4976 int Vm = instr->VFPMRegValue(kSimd128Precision); 4977 switch (size) { 4978 case Neon8: { 4979 uint8_t src1[16], src2[16], dst1[16], dst2[16]; 4980 get_q_register(Vd, src1); 4981 get_q_register(Vm, src2); 4982 for (int i = 0; i < 8; i++) { 4983 dst1[i * 2] = src1[i]; 4984 dst1[i * 2 + 1] = src2[i]; 4985 dst2[i * 2] = src1[i + 8]; 4986 dst2[i * 2 + 1] = src2[i + 8]; 4987 } 4988 set_q_register(Vd, dst1); 4989 set_q_register(Vm, dst2); 4990 break; 4991 } 4992 case Neon16: { 4993 uint16_t src1[8], src2[8], dst1[8], dst2[8]; 4994 get_q_register(Vd, src1); 4995 get_q_register(Vm, src2); 4996 for (int i = 0; i < 8; i += 2) { 4997 dst1[i] = src1[i / 2]; 4998 dst1[i + 1] = src2[i / 2]; 4999 dst2[i] = src1[i / 2 + 4]; 5000 dst2[i + 1] = src2[i / 2 + 4]; 5001 } 5002 set_q_register(Vd, dst1); 5003 set_q_register(Vm, dst2); 5004 break; 5005 } 5006 case Neon32: { 5007 uint32_t src1[4], src2[4], dst1[4], dst2[4]; 5008 get_q_register(Vd, src1); 5009 get_q_register(Vm, src2); 5010 for (int i = 0; i < 2; i++) { 5011 dst1[i * 2] = src1[i]; 5012 dst1[i * 2 + 1] = src2[i]; 5013 dst2[i * 2] = src1[i + 2]; 5014 dst2[i * 2 + 1] = src2[i + 2]; 5015 } 5016 set_q_register(Vd, dst1); 5017 set_q_register(Vm, dst2); 5018 break; 5019 } 5020 default: 5021 UNREACHABLE(); 5022 break; 5023 } 5024 } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) { 5025 // vrev<op>.size Qd, Qm 5026 int Vd = instr->VFPDRegValue(kSimd128Precision); 5027 int Vm = instr->VFPMRegValue(kSimd128Precision); 5028 NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); 5029 NeonSize op = static_cast<NeonSize>(static_cast<int>(Neon64) - 5030 instr->Bits(8, 7)); 5031 switch (op) { 5032 case Neon16: { 5033 DCHECK_EQ(Neon8, size); 5034 uint8_t src[16]; 5035 get_q_register(Vm, src); 5036 for (int i = 0; i < 16; i += 2) { 5037 std::swap(src[i], src[i + 1]); 5038 } 5039 set_q_register(Vd, src); 5040 break; 5041 } 5042 case Neon32: { 5043 switch (size) { 5044 case Neon16: { 5045 uint16_t src[8]; 5046 get_q_register(Vm, src); 5047 for (int i = 0; i < 8; i += 2) { 5048 std::swap(src[i], src[i + 1]); 5049 } 5050 set_q_register(Vd, src); 5051 break; 5052 } 5053 case Neon8: { 5054 uint8_t src[16]; 5055 get_q_register(Vm, src); 5056 for (int i = 0; i < 4; i++) { 5057 std::swap(src[i * 4], src[i * 4 + 3]); 5058 std::swap(src[i * 4 + 1], src[i * 4 + 2]); 5059 } 5060 set_q_register(Vd, src); 5061 break; 5062 } 5063 default: 5064 UNREACHABLE(); 5065 break; 5066 } 5067 break; 5068 } 5069 case Neon64: { 5070 switch (size) { 5071 case Neon32: { 5072 uint32_t src[4]; 5073 get_q_register(Vm, src); 5074 std::swap(src[0], src[1]); 5075 std::swap(src[2], src[3]); 5076 set_q_register(Vd, src); 5077 break; 5078 } 5079 case Neon16: { 5080 uint16_t src[8]; 5081 get_q_register(Vm, src); 5082 for (int i = 0; i < 4; i++) { 5083 std::swap(src[i * 4], src[i * 4 + 3]); 5084 std::swap(src[i * 4 + 1], src[i * 4 + 2]); 5085 } 5086 set_q_register(Vd, src); 5087 break; 5088 } 5089 case Neon8: { 5090 uint8_t src[16]; 5091 get_q_register(Vm, src); 5092 for (int i = 0; i < 4; i++) { 5093 std::swap(src[i], src[7 - i]); 5094 std::swap(src[i + 8], src[15 - i]); 5095 } 5096 set_q_register(Vd, src); 5097 break; 5098 } 5099 default: 5100 UNREACHABLE(); 5101 break; 5102 } 5103 break; 5104 } 5105 default: 5106 UNREACHABLE(); 5107 break; 5108 } 5109 } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) { 5110 int Vd = instr->VFPDRegValue(kSimd128Precision); 5111 int Vm = instr->VFPMRegValue(kSimd128Precision); 5112 NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18)); 5113 if (instr->Bits(9, 6) == 0xd) { 5114 // vabs<type>.<size> Qd, Qm 5115 if (instr->Bit(10) != 0) { 5116 // floating point (clear sign bits) 5117 uint32_t src[4]; 5118 get_q_register(Vm, src); 5119 for (int i = 0; i < 4; i++) { 5120 src[i] &= ~0x80000000; 5121 } 5122 set_q_register(Vd, src); 5123 } else { 5124 // signed integer 5125 switch (size) { 5126 case Neon8: { 5127 int8_t src[16]; 5128 get_q_register(Vm, src); 5129 for (int i = 0; i < 16; i++) { 5130 src[i] = std::abs(src[i]); 5131 } 5132 set_q_register(Vd, src); 5133 break; 5134 } 5135 case Neon16: { 5136 int16_t src[8]; 5137 get_q_register(Vm, src); 5138 for (int i = 0; i < 8; i++) { 5139 src[i] = std::abs(src[i]); 5140 } 5141 set_q_register(Vd, src); 5142 break; 5143 } 5144 case Neon32: { 5145 int32_t src[4]; 5146 get_q_register(Vm, src); 5147 for (int i = 0; i < 4; i++) { 5148 src[i] = std::abs(src[i]); 5149 } 5150 set_q_register(Vd, src); 5151 break; 5152 } 5153 default: 5154 UNIMPLEMENTED(); 5155 break; 5156 } 5157 } 5158 } else if (instr->Bits(9, 6) == 0xf) { 5159 // vneg<type>.<size> Qd, Qm (signed integer) 5160 if (instr->Bit(10) != 0) { 5161 // floating point (toggle sign bits) 5162 uint32_t src[4]; 5163 get_q_register(Vm, src); 5164 for (int i = 0; i < 4; i++) { 5165 src[i] ^= 0x80000000; 5166 } 5167 set_q_register(Vd, src); 5168 } else { 5169 // signed integer 5170 switch (size) { 5171 case Neon8: { 5172 int8_t src[16]; 5173 get_q_register(Vm, src); 5174 for (int i = 0; i < 16; i++) { 5175 src[i] = -src[i]; 5176 } 5177 set_q_register(Vd, src); 5178 break; 5179 } 5180 case Neon16: 5181 int16_t src[8]; 5182 get_q_register(Vm, src); 5183 for (int i = 0; i < 8; i++) { 5184 src[i] = -src[i]; 5185 } 5186 set_q_register(Vd, src); 5187 break; 5188 case Neon32: { 5189 int32_t src[4]; 5190 get_q_register(Vm, src); 5191 for (int i = 0; i < 4; i++) { 5192 src[i] = -src[i]; 5193 } 5194 set_q_register(Vd, src); 5195 break; 5196 } 5197 default: 5198 UNIMPLEMENTED(); 5199 break; 5200 } 5201 } 5202 } else { 5203 UNIMPLEMENTED(); 5204 } 5205 } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) { 5206 // vrecpe/vrsqrte.f32 Qd, Qm. 5207 int Vd = instr->VFPDRegValue(kSimd128Precision); 5208 int Vm = instr->VFPMRegValue(kSimd128Precision); 5209 uint32_t src[4]; 5210 get_q_register(Vm, src); 5211 if (instr->Bit(7) == 0) { 5212 for (int i = 0; i < 4; i++) { 5213 float denom = bit_cast<float>(src[i]); 5214 div_zero_vfp_flag_ = (denom == 0); 5215 float result = 1.0f / denom; 5216 result = canonicalizeNaN(result); 5217 src[i] = bit_cast<uint32_t>(result); 5218 } 5219 } else { 5220 lazily_initialize_fast_sqrt(isolate_); 5221 for (int i = 0; i < 4; i++) { 5222 float radicand = bit_cast<float>(src[i]); 5223 float result = 1.0f / fast_sqrt(radicand, isolate_); 5224 result = canonicalizeNaN(result); 5225 src[i] = bit_cast<uint32_t>(result); 5226 } 5227 } 5228 set_q_register(Vd, src); 5229 } else { 5230 UNIMPLEMENTED(); 5231 } 5232 } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { 5233 // vshr.u<size> Qd, Qm, shift 5234 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); 5235 int shift = 2 * size - instr->Bits(21, 16); 5236 int Vd = instr->VFPDRegValue(kSimd128Precision); 5237 int Vm = instr->VFPMRegValue(kSimd128Precision); 5238 NeonSize ns = static_cast<NeonSize>(size / 16); 5239 switch (ns) { 5240 case Neon8: { 5241 uint8_t src[16]; 5242 get_q_register(Vm, src); 5243 for (int i = 0; i < 16; i++) { 5244 src[i] >>= shift; 5245 } 5246 set_q_register(Vd, src); 5247 break; 5248 } 5249 case Neon16: { 5250 uint16_t src[8]; 5251 get_q_register(Vm, src); 5252 for (int i = 0; i < 8; i++) { 5253 src[i] >>= shift; 5254 } 5255 set_q_register(Vd, src); 5256 break; 5257 } 5258 case Neon32: { 5259 uint32_t src[4]; 5260 get_q_register(Vm, src); 5261 for (int i = 0; i < 4; i++) { 5262 src[i] >>= shift; 5263 } 5264 set_q_register(Vd, src); 5265 break; 5266 } 5267 default: 5268 UNREACHABLE(); 5269 break; 5270 } 5271 } else { 5272 UNIMPLEMENTED(); 5273 } 5274 break; 5275 case 8: 5276 if (instr->Bits(21, 20) == 0) { 5277 // vst1 5278 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 5279 int Rn = instr->VnValue(); 5280 int type = instr->Bits(11, 8); 5281 int Rm = instr->VmValue(); 5282 int32_t address = get_register(Rn); 5283 int regs = 0; 5284 switch (type) { 5285 case nlt_1: 5286 regs = 1; 5287 break; 5288 case nlt_2: 5289 regs = 2; 5290 break; 5291 case nlt_3: 5292 regs = 3; 5293 break; 5294 case nlt_4: 5295 regs = 4; 5296 break; 5297 default: 5298 UNIMPLEMENTED(); 5299 break; 5300 } 5301 int r = 0; 5302 while (r < regs) { 5303 uint32_t data[2]; 5304 get_d_register(Vd + r, data); 5305 WriteW(address, data[0], instr); 5306 WriteW(address + 4, data[1], instr); 5307 address += 8; 5308 r++; 5309 } 5310 if (Rm != 15) { 5311 if (Rm == 13) { 5312 set_register(Rn, address); 5313 } else { 5314 set_register(Rn, get_register(Rn) + get_register(Rm)); 5315 } 5316 } 5317 } else if (instr->Bits(21, 20) == 2) { 5318 // vld1 5319 int Vd = (instr->Bit(22) << 4) | instr->VdValue(); 5320 int Rn = instr->VnValue(); 5321 int type = instr->Bits(11, 8); 5322 int Rm = instr->VmValue(); 5323 int32_t address = get_register(Rn); 5324 int regs = 0; 5325 switch (type) { 5326 case nlt_1: 5327 regs = 1; 5328 break; 5329 case nlt_2: 5330 regs = 2; 5331 break; 5332 case nlt_3: 5333 regs = 3; 5334 break; 5335 case nlt_4: 5336 regs = 4; 5337 break; 5338 default: 5339 UNIMPLEMENTED(); 5340 break; 5341 } 5342 int r = 0; 5343 while (r < regs) { 5344 uint32_t data[2]; 5345 data[0] = ReadW(address, instr); 5346 data[1] = ReadW(address + 4, instr); 5347 set_d_register(Vd + r, data); 5348 address += 8; 5349 r++; 5350 } 5351 if (Rm != 15) { 5352 if (Rm == 13) { 5353 set_register(Rn, address); 5354 } else { 5355 set_register(Rn, get_register(Rn) + get_register(Rm)); 5356 } 5357 } 5358 } else { 5359 UNIMPLEMENTED(); 5360 } 5361 break; 5362 case 0xA: 5363 case 0xB: 5364 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { 5365 // pld: ignore instruction. 5366 } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) { 5367 // dsb, dmb, isb: ignore instruction for now. 5368 // TODO(binji): implement 5369 // Also refer to the ARMv6 CP15 equivalents in DecodeTypeCP15. 5370 } else { 5371 UNIMPLEMENTED(); 5372 } 5373 break; 5374 case 0x1D: 5375 if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 && 5376 instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2) { 5377 if (instr->SzValue() == 0x1) { 5378 int vm = instr->VFPMRegValue(kDoublePrecision); 5379 int vd = instr->VFPDRegValue(kDoublePrecision); 5380 double dm_value = get_double_from_d_register(vm); 5381 double dd_value = 0.0; 5382 int rounding_mode = instr->Bits(17, 16); 5383 switch (rounding_mode) { 5384 case 0x0: // vrinta - round with ties to away from zero 5385 dd_value = round(dm_value); 5386 break; 5387 case 0x1: { // vrintn - round with ties to even 5388 dd_value = nearbyint(dm_value); 5389 break; 5390 } 5391 case 0x2: // vrintp - ceil 5392 dd_value = ceil(dm_value); 5393 break; 5394 case 0x3: // vrintm - floor 5395 dd_value = floor(dm_value); 5396 break; 5397 default: 5398 UNREACHABLE(); // Case analysis is exhaustive. 5399 break; 5400 } 5401 dd_value = canonicalizeNaN(dd_value); 5402 set_d_register_from_double(vd, dd_value); 5403 } else { 5404 int m = instr->VFPMRegValue(kSinglePrecision); 5405 int d = instr->VFPDRegValue(kSinglePrecision); 5406 float sm_value = get_float_from_s_register(m); 5407 float sd_value = 0.0; 5408 int rounding_mode = instr->Bits(17, 16); 5409 switch (rounding_mode) { 5410 case 0x0: // vrinta - round with ties to away from zero 5411 sd_value = roundf(sm_value); 5412 break; 5413 case 0x1: { // vrintn - round with ties to even 5414 sd_value = nearbyintf(sm_value); 5415 break; 5416 } 5417 case 0x2: // vrintp - ceil 5418 sd_value = ceilf(sm_value); 5419 break; 5420 case 0x3: // vrintm - floor 5421 sd_value = floorf(sm_value); 5422 break; 5423 default: 5424 UNREACHABLE(); // Case analysis is exhaustive. 5425 break; 5426 } 5427 sd_value = canonicalizeNaN(sd_value); 5428 set_s_register_from_float(d, sd_value); 5429 } 5430 } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) && 5431 (instr->Bit(4) == 0x0)) { 5432 if (instr->SzValue() == 0x1) { 5433 int m = instr->VFPMRegValue(kDoublePrecision); 5434 int n = instr->VFPNRegValue(kDoublePrecision); 5435 int d = instr->VFPDRegValue(kDoublePrecision); 5436 double dn_value = get_double_from_d_register(n); 5437 double dm_value = get_double_from_d_register(m); 5438 double dd_value; 5439 if (instr->Bit(6) == 0x1) { // vminnm 5440 if ((dn_value < dm_value) || std::isnan(dm_value)) { 5441 dd_value = dn_value; 5442 } else if ((dm_value < dn_value) || std::isnan(dn_value)) { 5443 dd_value = dm_value; 5444 } else { 5445 DCHECK_EQ(dn_value, dm_value); 5446 // Make sure that we pick the most negative sign for +/-0. 5447 dd_value = std::signbit(dn_value) ? dn_value : dm_value; 5448 } 5449 } else { // vmaxnm 5450 if ((dn_value > dm_value) || std::isnan(dm_value)) { 5451 dd_value = dn_value; 5452 } else if ((dm_value > dn_value) || std::isnan(dn_value)) { 5453 dd_value = dm_value; 5454 } else { 5455 DCHECK_EQ(dn_value, dm_value); 5456 // Make sure that we pick the most positive sign for +/-0. 5457 dd_value = std::signbit(dn_value) ? dm_value : dn_value; 5458 } 5459 } 5460 dd_value = canonicalizeNaN(dd_value); 5461 set_d_register_from_double(d, dd_value); 5462 } else { 5463 int m = instr->VFPMRegValue(kSinglePrecision); 5464 int n = instr->VFPNRegValue(kSinglePrecision); 5465 int d = instr->VFPDRegValue(kSinglePrecision); 5466 float sn_value = get_float_from_s_register(n); 5467 float sm_value = get_float_from_s_register(m); 5468 float sd_value; 5469 if (instr->Bit(6) == 0x1) { // vminnm 5470 if ((sn_value < sm_value) || std::isnan(sm_value)) { 5471 sd_value = sn_value; 5472 } else if ((sm_value < sn_value) || std::isnan(sn_value)) { 5473 sd_value = sm_value; 5474 } else { 5475 DCHECK_EQ(sn_value, sm_value); 5476 // Make sure that we pick the most negative sign for +/-0. 5477 sd_value = std::signbit(sn_value) ? sn_value : sm_value; 5478 } 5479 } else { // vmaxnm 5480 if ((sn_value > sm_value) || std::isnan(sm_value)) { 5481 sd_value = sn_value; 5482 } else if ((sm_value > sn_value) || std::isnan(sn_value)) { 5483 sd_value = sm_value; 5484 } else { 5485 DCHECK_EQ(sn_value, sm_value); 5486 // Make sure that we pick the most positive sign for +/-0. 5487 sd_value = std::signbit(sn_value) ? sm_value : sn_value; 5488 } 5489 } 5490 sd_value = canonicalizeNaN(sd_value); 5491 set_s_register_from_float(d, sd_value); 5492 } 5493 } else { 5494 UNIMPLEMENTED(); 5495 } 5496 break; 5497 case 0x1C: 5498 if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) && 5499 (instr->Bit(4) == 0)) { 5500 // VSEL* (floating-point) 5501 bool condition_holds; 5502 switch (instr->Bits(21, 20)) { 5503 case 0x0: // VSELEQ 5504 condition_holds = (z_flag_ == 1); 5505 break; 5506 case 0x1: // VSELVS 5507 condition_holds = (v_flag_ == 1); 5508 break; 5509 case 0x2: // VSELGE 5510 condition_holds = (n_flag_ == v_flag_); 5511 break; 5512 case 0x3: // VSELGT 5513 condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_)); 5514 break; 5515 default: 5516 UNREACHABLE(); // Case analysis is exhaustive. 5517 break; 5518 } 5519 if (instr->SzValue() == 0x1) { 5520 int n = instr->VFPNRegValue(kDoublePrecision); 5521 int m = instr->VFPMRegValue(kDoublePrecision); 5522 int d = instr->VFPDRegValue(kDoublePrecision); 5523 double result = get_double_from_d_register(condition_holds ? n : m); 5524 set_d_register_from_double(d, result); 5525 } else { 5526 int n = instr->VFPNRegValue(kSinglePrecision); 5527 int m = instr->VFPMRegValue(kSinglePrecision); 5528 int d = instr->VFPDRegValue(kSinglePrecision); 5529 float result = get_float_from_s_register(condition_holds ? n : m); 5530 set_s_register_from_float(d, result); 5531 } 5532 } else { 5533 UNIMPLEMENTED(); 5534 } 5535 break; 5536 default: 5537 UNIMPLEMENTED(); 5538 break; 5539 } 5540 } 5541 5542 5543 // Executes the current instruction. 5544 void Simulator::InstructionDecode(Instruction* instr) { 5545 if (v8::internal::FLAG_check_icache) { 5546 CheckICache(isolate_->simulator_i_cache(), instr); 5547 } 5548 pc_modified_ = false; 5549 if (::v8::internal::FLAG_trace_sim) { 5550 disasm::NameConverter converter; 5551 disasm::Disassembler dasm(converter); 5552 // use a reasonably large buffer 5553 v8::internal::EmbeddedVector<char, 256> buffer; 5554 dasm.InstructionDecode(buffer, 5555 reinterpret_cast<byte*>(instr)); 5556 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(instr), 5557 buffer.start()); 5558 } 5559 if (instr->ConditionField() == kSpecialCondition) { 5560 DecodeSpecialCondition(instr); 5561 } else if (ConditionallyExecute(instr)) { 5562 switch (instr->TypeValue()) { 5563 case 0: 5564 case 1: { 5565 DecodeType01(instr); 5566 break; 5567 } 5568 case 2: { 5569 DecodeType2(instr); 5570 break; 5571 } 5572 case 3: { 5573 DecodeType3(instr); 5574 break; 5575 } 5576 case 4: { 5577 DecodeType4(instr); 5578 break; 5579 } 5580 case 5: { 5581 DecodeType5(instr); 5582 break; 5583 } 5584 case 6: { 5585 DecodeType6(instr); 5586 break; 5587 } 5588 case 7: { 5589 DecodeType7(instr); 5590 break; 5591 } 5592 default: { 5593 UNIMPLEMENTED(); 5594 break; 5595 } 5596 } 5597 // If the instruction is a non taken conditional stop, we need to skip the 5598 // inlined message address. 5599 } else if (instr->IsStop()) { 5600 set_pc(get_pc() + 2 * Instruction::kInstrSize); 5601 } 5602 if (!pc_modified_) { 5603 set_register(pc, reinterpret_cast<int32_t>(instr) 5604 + Instruction::kInstrSize); 5605 } 5606 } 5607 5608 5609 void Simulator::Execute() { 5610 // Get the PC to simulate. Cannot use the accessor here as we need the 5611 // raw PC value and not the one used as input to arithmetic instructions. 5612 int program_counter = get_pc(); 5613 5614 if (::v8::internal::FLAG_stop_sim_at == 0) { 5615 // Fast version of the dispatch loop without checking whether the simulator 5616 // should be stopping at a particular executed instruction. 5617 while (program_counter != end_sim_pc) { 5618 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 5619 icount_++; 5620 InstructionDecode(instr); 5621 program_counter = get_pc(); 5622 } 5623 } else { 5624 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 5625 // we reach the particular instuction count. 5626 while (program_counter != end_sim_pc) { 5627 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 5628 icount_++; 5629 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 5630 ArmDebugger dbg(this); 5631 dbg.Debug(); 5632 } else { 5633 InstructionDecode(instr); 5634 } 5635 program_counter = get_pc(); 5636 } 5637 } 5638 } 5639 5640 5641 void Simulator::CallInternal(byte* entry) { 5642 // Adjust JS-based stack limit to C-based stack limit. 5643 isolate_->stack_guard()->AdjustStackLimitForSimulator(); 5644 5645 // Prepare to execute the code at entry 5646 set_register(pc, reinterpret_cast<int32_t>(entry)); 5647 // Put down marker for end of simulation. The simulator will stop simulation 5648 // when the PC reaches this value. By saving the "end simulation" value into 5649 // the LR the simulation stops when returning to this call point. 5650 set_register(lr, end_sim_pc); 5651 5652 // Remember the values of callee-saved registers. 5653 // The code below assumes that r9 is not used as sb (static base) in 5654 // simulator code and therefore is regarded as a callee-saved register. 5655 int32_t r4_val = get_register(r4); 5656 int32_t r5_val = get_register(r5); 5657 int32_t r6_val = get_register(r6); 5658 int32_t r7_val = get_register(r7); 5659 int32_t r8_val = get_register(r8); 5660 int32_t r9_val = get_register(r9); 5661 int32_t r10_val = get_register(r10); 5662 int32_t r11_val = get_register(r11); 5663 5664 // Set up the callee-saved registers with a known value. To be able to check 5665 // that they are preserved properly across JS execution. 5666 int32_t callee_saved_value = icount_; 5667 set_register(r4, callee_saved_value); 5668 set_register(r5, callee_saved_value); 5669 set_register(r6, callee_saved_value); 5670 set_register(r7, callee_saved_value); 5671 set_register(r8, callee_saved_value); 5672 set_register(r9, callee_saved_value); 5673 set_register(r10, callee_saved_value); 5674 set_register(r11, callee_saved_value); 5675 5676 // Start the simulation 5677 Execute(); 5678 5679 // Check that the callee-saved registers have been preserved. 5680 CHECK_EQ(callee_saved_value, get_register(r4)); 5681 CHECK_EQ(callee_saved_value, get_register(r5)); 5682 CHECK_EQ(callee_saved_value, get_register(r6)); 5683 CHECK_EQ(callee_saved_value, get_register(r7)); 5684 CHECK_EQ(callee_saved_value, get_register(r8)); 5685 CHECK_EQ(callee_saved_value, get_register(r9)); 5686 CHECK_EQ(callee_saved_value, get_register(r10)); 5687 CHECK_EQ(callee_saved_value, get_register(r11)); 5688 5689 // Restore callee-saved registers with the original value. 5690 set_register(r4, r4_val); 5691 set_register(r5, r5_val); 5692 set_register(r6, r6_val); 5693 set_register(r7, r7_val); 5694 set_register(r8, r8_val); 5695 set_register(r9, r9_val); 5696 set_register(r10, r10_val); 5697 set_register(r11, r11_val); 5698 } 5699 5700 5701 int32_t Simulator::Call(byte* entry, int argument_count, ...) { 5702 va_list parameters; 5703 va_start(parameters, argument_count); 5704 // Set up arguments 5705 5706 // First four arguments passed in registers. 5707 DCHECK(argument_count >= 4); 5708 set_register(r0, va_arg(parameters, int32_t)); 5709 set_register(r1, va_arg(parameters, int32_t)); 5710 set_register(r2, va_arg(parameters, int32_t)); 5711 set_register(r3, va_arg(parameters, int32_t)); 5712 5713 // Remaining arguments passed on stack. 5714 int original_stack = get_register(sp); 5715 // Compute position of stack on entry to generated code. 5716 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)); 5717 if (base::OS::ActivationFrameAlignment() != 0) { 5718 entry_stack &= -base::OS::ActivationFrameAlignment(); 5719 } 5720 // Store remaining arguments on stack, from low to high memory. 5721 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 5722 for (int i = 4; i < argument_count; i++) { 5723 stack_argument[i - 4] = va_arg(parameters, int32_t); 5724 } 5725 va_end(parameters); 5726 set_register(sp, entry_stack); 5727 5728 CallInternal(entry); 5729 5730 // Pop stack passed arguments. 5731 CHECK_EQ(entry_stack, get_register(sp)); 5732 set_register(sp, original_stack); 5733 5734 int32_t result = get_register(r0); 5735 return result; 5736 } 5737 5738 5739 void Simulator::CallFP(byte* entry, double d0, double d1) { 5740 if (use_eabi_hardfloat()) { 5741 set_d_register_from_double(0, d0); 5742 set_d_register_from_double(1, d1); 5743 } else { 5744 set_register_pair_from_double(0, &d0); 5745 set_register_pair_from_double(2, &d1); 5746 } 5747 CallInternal(entry); 5748 } 5749 5750 5751 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) { 5752 CallFP(entry, d0, d1); 5753 int32_t result = get_register(r0); 5754 return result; 5755 } 5756 5757 5758 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) { 5759 CallFP(entry, d0, d1); 5760 if (use_eabi_hardfloat()) { 5761 return get_double_from_d_register(0); 5762 } else { 5763 return get_double_from_register_pair(0); 5764 } 5765 } 5766 5767 5768 uintptr_t Simulator::PushAddress(uintptr_t address) { 5769 int new_sp = get_register(sp) - sizeof(uintptr_t); 5770 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 5771 *stack_slot = address; 5772 set_register(sp, new_sp); 5773 return new_sp; 5774 } 5775 5776 5777 uintptr_t Simulator::PopAddress() { 5778 int current_sp = get_register(sp); 5779 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 5780 uintptr_t address = *stack_slot; 5781 set_register(sp, current_sp + sizeof(uintptr_t)); 5782 return address; 5783 } 5784 5785 Simulator::LocalMonitor::LocalMonitor() 5786 : access_state_(MonitorAccess::Open), 5787 tagged_addr_(0), 5788 size_(TransactionSize::None) {} 5789 5790 void Simulator::LocalMonitor::Clear() { 5791 access_state_ = MonitorAccess::Open; 5792 tagged_addr_ = 0; 5793 size_ = TransactionSize::None; 5794 } 5795 5796 void Simulator::LocalMonitor::NotifyLoad(int32_t addr) { 5797 if (access_state_ == MonitorAccess::Exclusive) { 5798 // A load could cause a cache eviction which will affect the monitor. As a 5799 // result, it's most strict to unconditionally clear the local monitor on 5800 // load. 5801 Clear(); 5802 } 5803 } 5804 5805 void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr, 5806 TransactionSize size) { 5807 access_state_ = MonitorAccess::Exclusive; 5808 tagged_addr_ = addr; 5809 size_ = size; 5810 } 5811 5812 void Simulator::LocalMonitor::NotifyStore(int32_t addr) { 5813 if (access_state_ == MonitorAccess::Exclusive) { 5814 // It is implementation-defined whether a non-exclusive store to an address 5815 // covered by the local monitor during exclusive access transitions to open 5816 // or exclusive access. See ARM DDI 0406C.b, A3.4.1. 5817 // 5818 // However, a store could cause a cache eviction which will affect the 5819 // monitor. As a result, it's most strict to unconditionally clear the 5820 // local monitor on store. 5821 Clear(); 5822 } 5823 } 5824 5825 bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr, 5826 TransactionSize size) { 5827 if (access_state_ == MonitorAccess::Exclusive) { 5828 // It is allowed for a processor to require that the address matches 5829 // exactly (A3.4.5), so this comparison does not mask addr. 5830 if (addr == tagged_addr_ && size_ == size) { 5831 Clear(); 5832 return true; 5833 } else { 5834 // It is implementation-defined whether an exclusive store to a 5835 // non-tagged address will update memory. Behavior is unpredictable if 5836 // the transaction size of the exclusive store differs from that of the 5837 // exclusive load. See ARM DDI 0406C.b, A3.4.5. 5838 Clear(); 5839 return false; 5840 } 5841 } else { 5842 DCHECK(access_state_ == MonitorAccess::Open); 5843 return false; 5844 } 5845 } 5846 5847 Simulator::GlobalMonitor::Processor::Processor() 5848 : access_state_(MonitorAccess::Open), 5849 tagged_addr_(0), 5850 next_(nullptr), 5851 prev_(nullptr), 5852 failure_counter_(0) {} 5853 5854 void Simulator::GlobalMonitor::Processor::Clear_Locked() { 5855 access_state_ = MonitorAccess::Open; 5856 tagged_addr_ = 0; 5857 } 5858 5859 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) { 5860 access_state_ = MonitorAccess::Exclusive; 5861 tagged_addr_ = addr; 5862 } 5863 5864 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked( 5865 int32_t addr, bool is_requesting_processor) { 5866 if (access_state_ == MonitorAccess::Exclusive) { 5867 // It is implementation-defined whether a non-exclusive store by the 5868 // requesting processor to an address covered by the global monitor 5869 // during exclusive access transitions to open or exclusive access. 5870 // 5871 // For any other processor, the access state always transitions to open 5872 // access. 5873 // 5874 // See ARM DDI 0406C.b, A3.4.2. 5875 // 5876 // However, similar to the local monitor, it is possible that a store 5877 // caused a cache eviction, which can affect the montior, so 5878 // conservatively, we always clear the monitor. 5879 Clear_Locked(); 5880 } 5881 } 5882 5883 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked( 5884 int32_t addr, bool is_requesting_processor) { 5885 if (access_state_ == MonitorAccess::Exclusive) { 5886 if (is_requesting_processor) { 5887 // It is allowed for a processor to require that the address matches 5888 // exactly (A3.4.5), so this comparison does not mask addr. 5889 if (addr == tagged_addr_) { 5890 // The access state for the requesting processor after a successful 5891 // exclusive store is implementation-defined, but according to the ARM 5892 // DDI, this has no effect on the subsequent operation of the global 5893 // monitor. 5894 Clear_Locked(); 5895 // Introduce occasional strex failures. This is to simulate the 5896 // behavior of hardware, which can randomly fail due to background 5897 // cache evictions. 5898 if (failure_counter_++ >= kMaxFailureCounter) { 5899 failure_counter_ = 0; 5900 return false; 5901 } else { 5902 return true; 5903 } 5904 } 5905 } else if ((addr & kExclusiveTaggedAddrMask) == 5906 (tagged_addr_ & kExclusiveTaggedAddrMask)) { 5907 // Check the masked addresses when responding to a successful lock by 5908 // another processor so the implementation is more conservative (i.e. the 5909 // granularity of locking is as large as possible.) 5910 Clear_Locked(); 5911 return false; 5912 } 5913 } 5914 return false; 5915 } 5916 5917 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {} 5918 5919 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr, 5920 Processor* processor) { 5921 processor->NotifyLoadExcl_Locked(addr); 5922 PrependProcessor_Locked(processor); 5923 } 5924 5925 void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr, 5926 Processor* processor) { 5927 // Notify each processor of the store operation. 5928 for (Processor* iter = head_; iter; iter = iter->next_) { 5929 bool is_requesting_processor = iter == processor; 5930 iter->NotifyStore_Locked(addr, is_requesting_processor); 5931 } 5932 } 5933 5934 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr, 5935 Processor* processor) { 5936 DCHECK(IsProcessorInLinkedList_Locked(processor)); 5937 if (processor->NotifyStoreExcl_Locked(addr, true)) { 5938 // Notify the other processors that this StoreExcl succeeded. 5939 for (Processor* iter = head_; iter; iter = iter->next_) { 5940 if (iter != processor) { 5941 iter->NotifyStoreExcl_Locked(addr, false); 5942 } 5943 } 5944 return true; 5945 } else { 5946 return false; 5947 } 5948 } 5949 5950 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked( 5951 Processor* processor) const { 5952 return head_ == processor || processor->next_ || processor->prev_; 5953 } 5954 5955 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) { 5956 if (IsProcessorInLinkedList_Locked(processor)) { 5957 return; 5958 } 5959 5960 if (head_) { 5961 head_->prev_ = processor; 5962 } 5963 processor->prev_ = nullptr; 5964 processor->next_ = head_; 5965 head_ = processor; 5966 } 5967 5968 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) { 5969 base::LockGuard<base::Mutex> lock_guard(&mutex); 5970 if (!IsProcessorInLinkedList_Locked(processor)) { 5971 return; 5972 } 5973 5974 if (processor->prev_) { 5975 processor->prev_->next_ = processor->next_; 5976 } else { 5977 head_ = processor->next_; 5978 } 5979 if (processor->next_) { 5980 processor->next_->prev_ = processor->prev_; 5981 } 5982 processor->prev_ = nullptr; 5983 processor->next_ = nullptr; 5984 } 5985 5986 } // namespace internal 5987 } // namespace v8 5988 5989 #endif // USE_SIMULATOR 5990 5991 #endif // V8_TARGET_ARCH_ARM 5992