1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdlib.h> 29 #include <math.h> 30 #include <cstdarg> 31 #include "v8.h" 32 33 #if defined(V8_TARGET_ARCH_ARM) 34 35 #include "disasm.h" 36 #include "assembler.h" 37 #include "arm/constants-arm.h" 38 #include "arm/simulator-arm.h" 39 40 #if defined(USE_SIMULATOR) 41 42 // Only build the simulator if not compiling for real ARM hardware. 43 namespace v8 { 44 namespace internal { 45 46 // This macro provides a platform independent use of sscanf. The reason for 47 // SScanF not being implemented in a platform independent way through 48 // ::v8::internal::OS in the same way as SNPrintF is that the 49 // Windows C Run-Time Library does not provide vsscanf. 50 #define SScanF sscanf // NOLINT 51 52 // The ArmDebugger class is used by the simulator while debugging simulated ARM 53 // code. 54 class ArmDebugger { 55 public: 56 explicit ArmDebugger(Simulator* sim) : sim_(sim) { } 57 ~ArmDebugger(); 58 59 void Stop(Instruction* instr); 60 void Debug(); 61 62 private: 63 static const Instr kBreakpointInstr = 64 (al | (7*B25) | (1*B24) | kBreakpoint); 65 static const Instr kNopInstr = (al | (13*B21)); 66 67 Simulator* sim_; 68 69 int32_t GetRegisterValue(int regnum); 70 double GetRegisterPairDoubleValue(int regnum); 71 double GetVFPDoubleRegisterValue(int regnum); 72 bool GetValue(const char* desc, int32_t* value); 73 bool GetVFPSingleValue(const char* desc, float* value); 74 bool GetVFPDoubleValue(const char* desc, double* value); 75 76 // Set or delete a breakpoint. Returns true if successful. 77 bool SetBreakpoint(Instruction* breakpc); 78 bool DeleteBreakpoint(Instruction* breakpc); 79 80 // Undo and redo all breakpoints. This is needed to bracket disassembly and 81 // execution to skip past breakpoints when run from the debugger. 82 void UndoBreakpoints(); 83 void RedoBreakpoints(); 84 }; 85 86 87 ArmDebugger::~ArmDebugger() { 88 } 89 90 91 92 #ifdef GENERATED_CODE_COVERAGE 93 static FILE* coverage_log = NULL; 94 95 96 static void InitializeCoverage() { 97 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 98 if (file_name != NULL) { 99 coverage_log = fopen(file_name, "aw+"); 100 } 101 } 102 103 104 void ArmDebugger::Stop(Instruction* instr) { 105 // Get the stop code. 106 uint32_t code = instr->SvcValue() & kStopCodeMask; 107 // Retrieve the encoded address, which comes just after this stop. 108 char** msg_address = 109 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); 110 char* msg = *msg_address; 111 ASSERT(msg != NULL); 112 113 // Update this stop description. 114 if (isWatchedStop(code) && !watched_stops[code].desc) { 115 watched_stops[code].desc = msg; 116 } 117 118 if (strlen(msg) > 0) { 119 if (coverage_log != NULL) { 120 fprintf(coverage_log, "%s\n", msg); 121 fflush(coverage_log); 122 } 123 // Overwrite the instruction and address with nops. 124 instr->SetInstructionBits(kNopInstr); 125 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr); 126 } 127 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 128 } 129 130 #else // ndef GENERATED_CODE_COVERAGE 131 132 static void InitializeCoverage() { 133 } 134 135 136 void ArmDebugger::Stop(Instruction* instr) { 137 // Get the stop code. 138 uint32_t code = instr->SvcValue() & kStopCodeMask; 139 // Retrieve the encoded address, which comes just after this stop. 140 char* msg = *reinterpret_cast<char**>(sim_->get_pc() 141 + Instruction::kInstrSize); 142 // Update this stop description. 143 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) { 144 sim_->watched_stops[code].desc = msg; 145 } 146 // Print the stop message and code if it is not the default code. 147 if (code != kMaxStopCode) { 148 PrintF("Simulator hit stop %u: %s\n", code, msg); 149 } else { 150 PrintF("Simulator hit %s\n", msg); 151 } 152 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 153 Debug(); 154 } 155 #endif 156 157 158 int32_t ArmDebugger::GetRegisterValue(int regnum) { 159 if (regnum == kPCRegister) { 160 return sim_->get_pc(); 161 } else { 162 return sim_->get_register(regnum); 163 } 164 } 165 166 167 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) { 168 return sim_->get_double_from_register_pair(regnum); 169 } 170 171 172 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { 173 return sim_->get_double_from_d_register(regnum); 174 } 175 176 177 bool ArmDebugger::GetValue(const char* desc, int32_t* value) { 178 int regnum = Registers::Number(desc); 179 if (regnum != kNoRegister) { 180 *value = GetRegisterValue(regnum); 181 return true; 182 } else { 183 if (strncmp(desc, "0x", 2) == 0) { 184 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; 185 } else { 186 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; 187 } 188 } 189 return false; 190 } 191 192 193 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) { 194 bool is_double; 195 int regnum = VFPRegisters::Number(desc, &is_double); 196 if (regnum != kNoRegister && !is_double) { 197 *value = sim_->get_float_from_s_register(regnum); 198 return true; 199 } 200 return false; 201 } 202 203 204 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) { 205 bool is_double; 206 int regnum = VFPRegisters::Number(desc, &is_double); 207 if (regnum != kNoRegister && is_double) { 208 *value = sim_->get_double_from_d_register(regnum); 209 return true; 210 } 211 return false; 212 } 213 214 215 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) { 216 // Check if a breakpoint can be set. If not return without any side-effects. 217 if (sim_->break_pc_ != NULL) { 218 return false; 219 } 220 221 // Set the breakpoint. 222 sim_->break_pc_ = breakpc; 223 sim_->break_instr_ = breakpc->InstructionBits(); 224 // Not setting the breakpoint instruction in the code itself. It will be set 225 // when the debugger shell continues. 226 return true; 227 } 228 229 230 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) { 231 if (sim_->break_pc_ != NULL) { 232 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 233 } 234 235 sim_->break_pc_ = NULL; 236 sim_->break_instr_ = 0; 237 return true; 238 } 239 240 241 void ArmDebugger::UndoBreakpoints() { 242 if (sim_->break_pc_ != NULL) { 243 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 244 } 245 } 246 247 248 void ArmDebugger::RedoBreakpoints() { 249 if (sim_->break_pc_ != NULL) { 250 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 251 } 252 } 253 254 255 void ArmDebugger::Debug() { 256 intptr_t last_pc = -1; 257 bool done = false; 258 259 #define COMMAND_SIZE 63 260 #define ARG_SIZE 255 261 262 #define STR(a) #a 263 #define XSTR(a) STR(a) 264 265 char cmd[COMMAND_SIZE + 1]; 266 char arg1[ARG_SIZE + 1]; 267 char arg2[ARG_SIZE + 1]; 268 char* argv[3] = { cmd, arg1, arg2 }; 269 270 // make sure to have a proper terminating character if reaching the limit 271 cmd[COMMAND_SIZE] = 0; 272 arg1[ARG_SIZE] = 0; 273 arg2[ARG_SIZE] = 0; 274 275 // Undo all set breakpoints while running in the debugger shell. This will 276 // make them invisible to all commands. 277 UndoBreakpoints(); 278 279 while (!done) { 280 if (last_pc != sim_->get_pc()) { 281 disasm::NameConverter converter; 282 disasm::Disassembler dasm(converter); 283 // use a reasonably large buffer 284 v8::internal::EmbeddedVector<char, 256> buffer; 285 dasm.InstructionDecode(buffer, 286 reinterpret_cast<byte*>(sim_->get_pc())); 287 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start()); 288 last_pc = sim_->get_pc(); 289 } 290 char* line = ReadLine("sim> "); 291 if (line == NULL) { 292 break; 293 } else { 294 char* last_input = sim_->last_debugger_input(); 295 if (strcmp(line, "\n") == 0 && last_input != NULL) { 296 line = last_input; 297 } else { 298 // Ownership is transferred to sim_; 299 sim_->set_last_debugger_input(line); 300 } 301 // Use sscanf to parse the individual parts of the command line. At the 302 // moment no command expects more than two parameters. 303 int argc = SScanF(line, 304 "%" XSTR(COMMAND_SIZE) "s " 305 "%" XSTR(ARG_SIZE) "s " 306 "%" XSTR(ARG_SIZE) "s", 307 cmd, arg1, arg2); 308 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 309 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 310 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 311 // Execute the one instruction we broke at with breakpoints disabled. 312 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 313 // Leave the debugger shell. 314 done = true; 315 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 316 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) { 317 int32_t value; 318 float svalue; 319 double dvalue; 320 if (strcmp(arg1, "all") == 0) { 321 for (int i = 0; i < kNumRegisters; i++) { 322 value = GetRegisterValue(i); 323 PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value); 324 if ((argc == 3 && strcmp(arg2, "fp") == 0) && 325 i < 8 && 326 (i % 2) == 0) { 327 dvalue = GetRegisterPairDoubleValue(i); 328 PrintF(" (%f)\n", dvalue); 329 } else { 330 PrintF("\n"); 331 } 332 } 333 for (int i = 0; i < kNumVFPDoubleRegisters; i++) { 334 dvalue = GetVFPDoubleRegisterValue(i); 335 uint64_t as_words = BitCast<uint64_t>(dvalue); 336 PrintF("%3s: %f 0x%08x %08x\n", 337 VFPRegisters::Name(i, true), 338 dvalue, 339 static_cast<uint32_t>(as_words >> 32), 340 static_cast<uint32_t>(as_words & 0xffffffff)); 341 } 342 } else { 343 if (GetValue(arg1, &value)) { 344 PrintF("%s: 0x%08x %d \n", arg1, value, value); 345 } else if (GetVFPSingleValue(arg1, &svalue)) { 346 uint32_t as_word = BitCast<uint32_t>(svalue); 347 PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word); 348 } else if (GetVFPDoubleValue(arg1, &dvalue)) { 349 uint64_t as_words = BitCast<uint64_t>(dvalue); 350 PrintF("%s: %f 0x%08x %08x\n", 351 arg1, 352 dvalue, 353 static_cast<uint32_t>(as_words >> 32), 354 static_cast<uint32_t>(as_words & 0xffffffff)); 355 } else { 356 PrintF("%s unrecognized\n", arg1); 357 } 358 } 359 } else { 360 PrintF("print <register>\n"); 361 } 362 } else if ((strcmp(cmd, "po") == 0) 363 || (strcmp(cmd, "printobject") == 0)) { 364 if (argc == 2) { 365 int32_t value; 366 if (GetValue(arg1, &value)) { 367 Object* obj = reinterpret_cast<Object*>(value); 368 PrintF("%s: \n", arg1); 369 #ifdef DEBUG 370 obj->PrintLn(); 371 #else 372 obj->ShortPrint(); 373 PrintF("\n"); 374 #endif 375 } else { 376 PrintF("%s unrecognized\n", arg1); 377 } 378 } else { 379 PrintF("printobject <value>\n"); 380 } 381 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 382 int32_t* cur = NULL; 383 int32_t* end = NULL; 384 int next_arg = 1; 385 386 if (strcmp(cmd, "stack") == 0) { 387 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp)); 388 } else { // "mem" 389 int32_t value; 390 if (!GetValue(arg1, &value)) { 391 PrintF("%s unrecognized\n", arg1); 392 continue; 393 } 394 cur = reinterpret_cast<int32_t*>(value); 395 next_arg++; 396 } 397 398 int32_t words; 399 if (argc == next_arg) { 400 words = 10; 401 } else if (argc == next_arg + 1) { 402 if (!GetValue(argv[next_arg], &words)) { 403 words = 10; 404 } 405 } 406 end = cur + words; 407 408 while (cur < end) { 409 PrintF(" 0x%08x: 0x%08x %10d", 410 reinterpret_cast<intptr_t>(cur), *cur, *cur); 411 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 412 int value = *cur; 413 Heap* current_heap = v8::internal::Isolate::Current()->heap(); 414 if (current_heap->Contains(obj) || ((value & 1) == 0)) { 415 PrintF(" ("); 416 if ((value & 1) == 0) { 417 PrintF("smi %d", value / 2); 418 } else { 419 obj->ShortPrint(); 420 } 421 PrintF(")"); 422 } 423 PrintF("\n"); 424 cur++; 425 } 426 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) { 427 disasm::NameConverter converter; 428 disasm::Disassembler dasm(converter); 429 // use a reasonably large buffer 430 v8::internal::EmbeddedVector<char, 256> buffer; 431 432 byte* prev = NULL; 433 byte* cur = NULL; 434 byte* end = NULL; 435 436 if (argc == 1) { 437 cur = reinterpret_cast<byte*>(sim_->get_pc()); 438 end = cur + (10 * Instruction::kInstrSize); 439 } else if (argc == 2) { 440 int regnum = Registers::Number(arg1); 441 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) { 442 // The argument is an address or a register name. 443 int32_t value; 444 if (GetValue(arg1, &value)) { 445 cur = reinterpret_cast<byte*>(value); 446 // Disassemble 10 instructions at <arg1>. 447 end = cur + (10 * Instruction::kInstrSize); 448 } 449 } else { 450 // The argument is the number of instructions. 451 int32_t value; 452 if (GetValue(arg1, &value)) { 453 cur = reinterpret_cast<byte*>(sim_->get_pc()); 454 // Disassemble <arg1> instructions. 455 end = cur + (value * Instruction::kInstrSize); 456 } 457 } 458 } else { 459 int32_t value1; 460 int32_t value2; 461 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 462 cur = reinterpret_cast<byte*>(value1); 463 end = cur + (value2 * Instruction::kInstrSize); 464 } 465 } 466 467 while (cur < end) { 468 prev = cur; 469 cur += dasm.InstructionDecode(buffer, cur); 470 PrintF(" 0x%08x %s\n", 471 reinterpret_cast<intptr_t>(prev), buffer.start()); 472 } 473 } else if (strcmp(cmd, "gdb") == 0) { 474 PrintF("relinquishing control to gdb\n"); 475 v8::internal::OS::DebugBreak(); 476 PrintF("regaining control from gdb\n"); 477 } else if (strcmp(cmd, "break") == 0) { 478 if (argc == 2) { 479 int32_t value; 480 if (GetValue(arg1, &value)) { 481 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 482 PrintF("setting breakpoint failed\n"); 483 } 484 } else { 485 PrintF("%s unrecognized\n", arg1); 486 } 487 } else { 488 PrintF("break <address>\n"); 489 } 490 } else if (strcmp(cmd, "del") == 0) { 491 if (!DeleteBreakpoint(NULL)) { 492 PrintF("deleting breakpoint failed\n"); 493 } 494 } else if (strcmp(cmd, "flags") == 0) { 495 PrintF("N flag: %d; ", sim_->n_flag_); 496 PrintF("Z flag: %d; ", sim_->z_flag_); 497 PrintF("C flag: %d; ", sim_->c_flag_); 498 PrintF("V flag: %d\n", sim_->v_flag_); 499 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_); 500 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_); 501 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_); 502 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_); 503 PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_); 504 } else if (strcmp(cmd, "stop") == 0) { 505 int32_t value; 506 intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize; 507 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 508 Instruction* msg_address = 509 reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize); 510 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 511 // Remove the current stop. 512 if (sim_->isStopInstruction(stop_instr)) { 513 stop_instr->SetInstructionBits(kNopInstr); 514 msg_address->SetInstructionBits(kNopInstr); 515 } else { 516 PrintF("Not at debugger stop.\n"); 517 } 518 } else if (argc == 3) { 519 // Print information about all/the specified breakpoint(s). 520 if (strcmp(arg1, "info") == 0) { 521 if (strcmp(arg2, "all") == 0) { 522 PrintF("Stop information:\n"); 523 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 524 sim_->PrintStopInfo(i); 525 } 526 } else if (GetValue(arg2, &value)) { 527 sim_->PrintStopInfo(value); 528 } else { 529 PrintF("Unrecognized argument.\n"); 530 } 531 } else if (strcmp(arg1, "enable") == 0) { 532 // Enable all/the specified breakpoint(s). 533 if (strcmp(arg2, "all") == 0) { 534 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 535 sim_->EnableStop(i); 536 } 537 } else if (GetValue(arg2, &value)) { 538 sim_->EnableStop(value); 539 } else { 540 PrintF("Unrecognized argument.\n"); 541 } 542 } else if (strcmp(arg1, "disable") == 0) { 543 // Disable all/the specified breakpoint(s). 544 if (strcmp(arg2, "all") == 0) { 545 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 546 sim_->DisableStop(i); 547 } 548 } else if (GetValue(arg2, &value)) { 549 sim_->DisableStop(value); 550 } else { 551 PrintF("Unrecognized argument.\n"); 552 } 553 } 554 } else { 555 PrintF("Wrong usage. Use help command for more information.\n"); 556 } 557 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) { 558 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim; 559 PrintF("Trace of executed instructions is %s\n", 560 ::v8::internal::FLAG_trace_sim ? "on" : "off"); 561 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 562 PrintF("cont\n"); 563 PrintF(" continue execution (alias 'c')\n"); 564 PrintF("stepi\n"); 565 PrintF(" step one instruction (alias 'si')\n"); 566 PrintF("print <register>\n"); 567 PrintF(" print register content (alias 'p')\n"); 568 PrintF(" use register name 'all' to print all registers\n"); 569 PrintF(" add argument 'fp' to print register pair double values\n"); 570 PrintF("printobject <register>\n"); 571 PrintF(" print an object from a register (alias 'po')\n"); 572 PrintF("flags\n"); 573 PrintF(" print flags\n"); 574 PrintF("stack [<words>]\n"); 575 PrintF(" dump stack content, default dump 10 words)\n"); 576 PrintF("mem <address> [<words>]\n"); 577 PrintF(" dump memory content, default dump 10 words)\n"); 578 PrintF("disasm [<instructions>]\n"); 579 PrintF("disasm [<address/register>]\n"); 580 PrintF("disasm [[<address/register>] <instructions>]\n"); 581 PrintF(" disassemble code, default is 10 instructions\n"); 582 PrintF(" from pc (alias 'di')\n"); 583 PrintF("gdb\n"); 584 PrintF(" enter gdb\n"); 585 PrintF("break <address>\n"); 586 PrintF(" set a break point on the address\n"); 587 PrintF("del\n"); 588 PrintF(" delete the breakpoint\n"); 589 PrintF("trace (alias 't')\n"); 590 PrintF(" toogle the tracing of all executed statements\n"); 591 PrintF("stop feature:\n"); 592 PrintF(" Description:\n"); 593 PrintF(" Stops are debug instructions inserted by\n"); 594 PrintF(" the Assembler::stop() function.\n"); 595 PrintF(" When hitting a stop, the Simulator will\n"); 596 PrintF(" stop and and give control to the ArmDebugger.\n"); 597 PrintF(" The first %d stop codes are watched:\n", 598 Simulator::kNumOfWatchedStops); 599 PrintF(" - They can be enabled / disabled: the Simulator\n"); 600 PrintF(" will / won't stop when hitting them.\n"); 601 PrintF(" - The Simulator keeps track of how many times they \n"); 602 PrintF(" are met. (See the info command.) Going over a\n"); 603 PrintF(" disabled stop still increases its counter. \n"); 604 PrintF(" Commands:\n"); 605 PrintF(" stop info all/<code> : print infos about number <code>\n"); 606 PrintF(" or all stop(s).\n"); 607 PrintF(" stop enable/disable all/<code> : enables / disables\n"); 608 PrintF(" all or number <code> stop(s)\n"); 609 PrintF(" stop unstop\n"); 610 PrintF(" ignore the stop instruction at the current location\n"); 611 PrintF(" from now on\n"); 612 } else { 613 PrintF("Unknown command: %s\n", cmd); 614 } 615 } 616 } 617 618 // Add all the breakpoints back to stop execution and enter the debugger 619 // shell when hit. 620 RedoBreakpoints(); 621 622 #undef COMMAND_SIZE 623 #undef ARG_SIZE 624 625 #undef STR 626 #undef XSTR 627 } 628 629 630 static bool ICacheMatch(void* one, void* two) { 631 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); 632 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); 633 return one == two; 634 } 635 636 637 static uint32_t ICacheHash(void* key) { 638 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 639 } 640 641 642 static bool AllOnOnePage(uintptr_t start, int size) { 643 intptr_t start_page = (start & ~CachePage::kPageMask); 644 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 645 return start_page == end_page; 646 } 647 648 649 void Simulator::set_last_debugger_input(char* input) { 650 DeleteArray(last_debugger_input_); 651 last_debugger_input_ = input; 652 } 653 654 655 void Simulator::FlushICache(v8::internal::HashMap* i_cache, 656 void* start_addr, 657 size_t size) { 658 intptr_t start = reinterpret_cast<intptr_t>(start_addr); 659 int intra_line = (start & CachePage::kLineMask); 660 start -= intra_line; 661 size += intra_line; 662 size = ((size - 1) | CachePage::kLineMask) + 1; 663 int offset = (start & CachePage::kPageMask); 664 while (!AllOnOnePage(start, size - 1)) { 665 int bytes_to_flush = CachePage::kPageSize - offset; 666 FlushOnePage(i_cache, start, bytes_to_flush); 667 start += bytes_to_flush; 668 size -= bytes_to_flush; 669 ASSERT_EQ(0, start & CachePage::kPageMask); 670 offset = 0; 671 } 672 if (size != 0) { 673 FlushOnePage(i_cache, start, size); 674 } 675 } 676 677 678 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) { 679 v8::internal::HashMap::Entry* entry = i_cache->Lookup(page, 680 ICacheHash(page), 681 true); 682 if (entry->value == NULL) { 683 CachePage* new_page = new CachePage(); 684 entry->value = new_page; 685 } 686 return reinterpret_cast<CachePage*>(entry->value); 687 } 688 689 690 // Flush from start up to and not including start + size. 691 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, 692 intptr_t start, 693 int size) { 694 ASSERT(size <= CachePage::kPageSize); 695 ASSERT(AllOnOnePage(start, size - 1)); 696 ASSERT((start & CachePage::kLineMask) == 0); 697 ASSERT((size & CachePage::kLineMask) == 0); 698 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 699 int offset = (start & CachePage::kPageMask); 700 CachePage* cache_page = GetCachePage(i_cache, page); 701 char* valid_bytemap = cache_page->ValidityByte(offset); 702 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 703 } 704 705 706 void Simulator::CheckICache(v8::internal::HashMap* i_cache, 707 Instruction* instr) { 708 intptr_t address = reinterpret_cast<intptr_t>(instr); 709 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 710 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 711 int offset = (address & CachePage::kPageMask); 712 CachePage* cache_page = GetCachePage(i_cache, page); 713 char* cache_valid_byte = cache_page->ValidityByte(offset); 714 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 715 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 716 if (cache_hit) { 717 // Check that the data in memory matches the contents of the I-cache. 718 CHECK(memcmp(reinterpret_cast<void*>(instr), 719 cache_page->CachedData(offset), 720 Instruction::kInstrSize) == 0); 721 } else { 722 // Cache miss. Load memory into the cache. 723 memcpy(cached_line, line, CachePage::kLineLength); 724 *cache_valid_byte = CachePage::LINE_VALID; 725 } 726 } 727 728 729 void Simulator::Initialize(Isolate* isolate) { 730 if (isolate->simulator_initialized()) return; 731 isolate->set_simulator_initialized(true); 732 ::v8::internal::ExternalReference::set_redirector(isolate, 733 &RedirectExternalReference); 734 } 735 736 737 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { 738 i_cache_ = isolate_->simulator_i_cache(); 739 if (i_cache_ == NULL) { 740 i_cache_ = new v8::internal::HashMap(&ICacheMatch); 741 isolate_->set_simulator_i_cache(i_cache_); 742 } 743 Initialize(isolate); 744 // Set up simulator support first. Some of this information is needed to 745 // setup the architecture state. 746 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack 747 stack_ = reinterpret_cast<char*>(malloc(stack_size)); 748 pc_modified_ = false; 749 icount_ = 0; 750 break_pc_ = NULL; 751 break_instr_ = 0; 752 753 // Set up architecture state. 754 // All registers are initialized to zero to start with. 755 for (int i = 0; i < num_registers; i++) { 756 registers_[i] = 0; 757 } 758 n_flag_ = false; 759 z_flag_ = false; 760 c_flag_ = false; 761 v_flag_ = false; 762 763 // Initializing VFP registers. 764 // All registers are initialized to zero to start with 765 // even though s_registers_ & d_registers_ share the same 766 // physical registers in the target. 767 for (int i = 0; i < num_s_registers; i++) { 768 vfp_register[i] = 0; 769 } 770 n_flag_FPSCR_ = false; 771 z_flag_FPSCR_ = false; 772 c_flag_FPSCR_ = false; 773 v_flag_FPSCR_ = false; 774 FPSCR_rounding_mode_ = RZ; 775 776 inv_op_vfp_flag_ = false; 777 div_zero_vfp_flag_ = false; 778 overflow_vfp_flag_ = false; 779 underflow_vfp_flag_ = false; 780 inexact_vfp_flag_ = false; 781 782 // The sp is initialized to point to the bottom (high address) of the 783 // allocated stack area. To be safe in potential stack underflows we leave 784 // some buffer below. 785 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 786 // The lr and pc are initialized to a known bad value that will cause an 787 // access violation if the simulator ever tries to execute it. 788 registers_[pc] = bad_lr; 789 registers_[lr] = bad_lr; 790 InitializeCoverage(); 791 792 last_debugger_input_ = NULL; 793 } 794 795 796 // When the generated code calls an external reference we need to catch that in 797 // the simulator. The external reference will be a function compiled for the 798 // host architecture. We need to call that function instead of trying to 799 // execute it with the simulator. We do that by redirecting the external 800 // reference to a svc (Supervisor Call) instruction that is handled by 801 // the simulator. We write the original destination of the jump just at a known 802 // offset from the svc instruction so the simulator knows what to call. 803 class Redirection { 804 public: 805 Redirection(void* external_function, ExternalReference::Type type) 806 : external_function_(external_function), 807 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), 808 type_(type), 809 next_(NULL) { 810 Isolate* isolate = Isolate::Current(); 811 next_ = isolate->simulator_redirection(); 812 Simulator::current(isolate)-> 813 FlushICache(isolate->simulator_i_cache(), 814 reinterpret_cast<void*>(&swi_instruction_), 815 Instruction::kInstrSize); 816 isolate->set_simulator_redirection(this); 817 } 818 819 void* address_of_swi_instruction() { 820 return reinterpret_cast<void*>(&swi_instruction_); 821 } 822 823 void* external_function() { return external_function_; } 824 ExternalReference::Type type() { return type_; } 825 826 static Redirection* Get(void* external_function, 827 ExternalReference::Type type) { 828 Isolate* isolate = Isolate::Current(); 829 Redirection* current = isolate->simulator_redirection(); 830 for (; current != NULL; current = current->next_) { 831 if (current->external_function_ == external_function) return current; 832 } 833 return new Redirection(external_function, type); 834 } 835 836 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 837 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 838 char* addr_of_redirection = 839 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 840 return reinterpret_cast<Redirection*>(addr_of_redirection); 841 } 842 843 private: 844 void* external_function_; 845 uint32_t swi_instruction_; 846 ExternalReference::Type type_; 847 Redirection* next_; 848 }; 849 850 851 void* Simulator::RedirectExternalReference(void* external_function, 852 ExternalReference::Type type) { 853 Redirection* redirection = Redirection::Get(external_function, type); 854 return redirection->address_of_swi_instruction(); 855 } 856 857 858 // Get the active Simulator for the current thread. 859 Simulator* Simulator::current(Isolate* isolate) { 860 v8::internal::Isolate::PerIsolateThreadData* isolate_data = 861 isolate->FindOrAllocatePerThreadDataForThisThread(); 862 ASSERT(isolate_data != NULL); 863 864 Simulator* sim = isolate_data->simulator(); 865 if (sim == NULL) { 866 // TODO(146): delete the simulator object when a thread/isolate goes away. 867 sim = new Simulator(isolate); 868 isolate_data->set_simulator(sim); 869 } 870 return sim; 871 } 872 873 874 // Sets the register in the architecture state. It will also deal with updating 875 // Simulator internal state for special registers such as PC. 876 void Simulator::set_register(int reg, int32_t value) { 877 ASSERT((reg >= 0) && (reg < num_registers)); 878 if (reg == pc) { 879 pc_modified_ = true; 880 } 881 registers_[reg] = value; 882 } 883 884 885 // Get the register from the architecture state. This function does handle 886 // the special case of accessing the PC register. 887 int32_t Simulator::get_register(int reg) const { 888 ASSERT((reg >= 0) && (reg < num_registers)); 889 // Stupid code added to avoid bug in GCC. 890 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949 891 if (reg >= num_registers) return 0; 892 // End stupid code. 893 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 894 } 895 896 897 double Simulator::get_double_from_register_pair(int reg) { 898 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0)); 899 900 double dm_val = 0.0; 901 // Read the bits from the unsigned integer register_[] array 902 // into the double precision floating point value and return it. 903 char buffer[2 * sizeof(vfp_register[0])]; 904 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); 905 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); 906 return(dm_val); 907 } 908 909 910 void Simulator::set_dw_register(int dreg, const int* dbl) { 911 ASSERT((dreg >= 0) && (dreg < num_d_registers)); 912 registers_[dreg] = dbl[0]; 913 registers_[dreg + 1] = dbl[1]; 914 } 915 916 917 // Raw access to the PC register. 918 void Simulator::set_pc(int32_t value) { 919 pc_modified_ = true; 920 registers_[pc] = value; 921 } 922 923 924 bool Simulator::has_bad_pc() const { 925 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc)); 926 } 927 928 929 // Raw access to the PC register without the special adjustment when reading. 930 int32_t Simulator::get_pc() const { 931 return registers_[pc]; 932 } 933 934 935 // Getting from and setting into VFP registers. 936 void Simulator::set_s_register(int sreg, unsigned int value) { 937 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 938 vfp_register[sreg] = value; 939 } 940 941 942 unsigned int Simulator::get_s_register(int sreg) const { 943 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 944 return vfp_register[sreg]; 945 } 946 947 948 void Simulator::set_s_register_from_float(int sreg, const float flt) { 949 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 950 // Read the bits from the single precision floating point value 951 // into the unsigned integer element of vfp_register[] given by index=sreg. 952 char buffer[sizeof(vfp_register[0])]; 953 memcpy(buffer, &flt, sizeof(vfp_register[0])); 954 memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0])); 955 } 956 957 958 void Simulator::set_s_register_from_sinteger(int sreg, const int sint) { 959 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 960 // Read the bits from the integer value into the unsigned integer element of 961 // vfp_register[] given by index=sreg. 962 char buffer[sizeof(vfp_register[0])]; 963 memcpy(buffer, &sint, sizeof(vfp_register[0])); 964 memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0])); 965 } 966 967 968 void Simulator::set_d_register_from_double(int dreg, const double& dbl) { 969 ASSERT((dreg >= 0) && (dreg < num_d_registers)); 970 // Read the bits from the double precision floating point value into the two 971 // consecutive unsigned integer elements of vfp_register[] given by index 972 // 2*sreg and 2*sreg+1. 973 char buffer[2 * sizeof(vfp_register[0])]; 974 memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0])); 975 memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0])); 976 } 977 978 979 float Simulator::get_float_from_s_register(int sreg) { 980 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 981 982 float sm_val = 0.0; 983 // Read the bits from the unsigned integer vfp_register[] array 984 // into the single precision floating point value and return it. 985 char buffer[sizeof(vfp_register[0])]; 986 memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0])); 987 memcpy(&sm_val, buffer, sizeof(vfp_register[0])); 988 return(sm_val); 989 } 990 991 992 int Simulator::get_sinteger_from_s_register(int sreg) { 993 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 994 995 int sm_val = 0; 996 // Read the bits from the unsigned integer vfp_register[] array 997 // into the single precision floating point value and return it. 998 char buffer[sizeof(vfp_register[0])]; 999 memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0])); 1000 memcpy(&sm_val, buffer, sizeof(vfp_register[0])); 1001 return(sm_val); 1002 } 1003 1004 1005 double Simulator::get_double_from_d_register(int dreg) { 1006 ASSERT((dreg >= 0) && (dreg < num_d_registers)); 1007 1008 double dm_val = 0.0; 1009 // Read the bits from the unsigned integer vfp_register[] array 1010 // into the double precision floating point value and return it. 1011 char buffer[2 * sizeof(vfp_register[0])]; 1012 memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0])); 1013 memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0])); 1014 return(dm_val); 1015 } 1016 1017 1018 // For use in calls that take two double values, constructed either 1019 // from r0-r3 or d0 and d1. 1020 void Simulator::GetFpArgs(double* x, double* y) { 1021 if (use_eabi_hardfloat()) { 1022 *x = vfp_register[0]; 1023 *y = vfp_register[1]; 1024 } else { 1025 // We use a char buffer to get around the strict-aliasing rules which 1026 // otherwise allow the compiler to optimize away the copy. 1027 char buffer[sizeof(*x)]; 1028 // Registers 0 and 1 -> x. 1029 memcpy(buffer, registers_, sizeof(*x)); 1030 memcpy(x, buffer, sizeof(*x)); 1031 // Registers 2 and 3 -> y. 1032 memcpy(buffer, registers_ + 2, sizeof(*y)); 1033 memcpy(y, buffer, sizeof(*y)); 1034 } 1035 } 1036 1037 // For use in calls that take one double value, constructed either 1038 // from r0 and r1 or d0. 1039 void Simulator::GetFpArgs(double* x) { 1040 if (use_eabi_hardfloat()) { 1041 *x = vfp_register[0]; 1042 } else { 1043 // We use a char buffer to get around the strict-aliasing rules which 1044 // otherwise allow the compiler to optimize away the copy. 1045 char buffer[sizeof(*x)]; 1046 // Registers 0 and 1 -> x. 1047 memcpy(buffer, registers_, sizeof(*x)); 1048 memcpy(x, buffer, sizeof(*x)); 1049 } 1050 } 1051 1052 1053 // For use in calls that take one double value constructed either 1054 // from r0 and r1 or d0 and one integer value. 1055 void Simulator::GetFpArgs(double* x, int32_t* y) { 1056 if (use_eabi_hardfloat()) { 1057 *x = vfp_register[0]; 1058 *y = registers_[1]; 1059 } else { 1060 // We use a char buffer to get around the strict-aliasing rules which 1061 // otherwise allow the compiler to optimize away the copy. 1062 char buffer[sizeof(*x)]; 1063 // Registers 0 and 1 -> x. 1064 memcpy(buffer, registers_, sizeof(*x)); 1065 memcpy(x, buffer, sizeof(*x)); 1066 // Register 2 -> y. 1067 memcpy(buffer, registers_ + 2, sizeof(*y)); 1068 memcpy(y, buffer, sizeof(*y)); 1069 } 1070 } 1071 1072 1073 // The return value is either in r0/r1 or d0. 1074 void Simulator::SetFpResult(const double& result) { 1075 if (use_eabi_hardfloat()) { 1076 char buffer[2 * sizeof(vfp_register[0])]; 1077 memcpy(buffer, &result, sizeof(buffer)); 1078 // Copy result to d0. 1079 memcpy(vfp_register, buffer, sizeof(buffer)); 1080 } else { 1081 char buffer[2 * sizeof(registers_[0])]; 1082 memcpy(buffer, &result, sizeof(buffer)); 1083 // Copy result to r0 and r1. 1084 memcpy(registers_, buffer, sizeof(buffer)); 1085 } 1086 } 1087 1088 1089 void Simulator::TrashCallerSaveRegisters() { 1090 // We don't trash the registers with the return value. 1091 registers_[2] = 0x50Bad4U; 1092 registers_[3] = 0x50Bad4U; 1093 registers_[12] = 0x50Bad4U; 1094 } 1095 1096 // Some Operating Systems allow unaligned access on ARMv7 targets. We 1097 // assume that unaligned accesses are not allowed unless the v8 build system 1098 // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero. 1099 // The following statements below describes the behavior of the ARM CPUs 1100 // that don't support unaligned access. 1101 // Some ARM platforms raise an interrupt on detecting unaligned access. 1102 // On others it does a funky rotation thing. For now we 1103 // simply disallow unaligned reads. Note that simulator runs have the runtime 1104 // system running directly on the host system and only generated code is 1105 // executed in the simulator. Since the host is typically IA32 we will not 1106 // get the correct ARM-like behaviour on unaligned accesses for those ARM 1107 // targets that don't support unaligned loads and stores. 1108 1109 1110 int Simulator::ReadW(int32_t addr, Instruction* instr) { 1111 #if V8_TARGET_CAN_READ_UNALIGNED 1112 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1113 return *ptr; 1114 #else 1115 if ((addr & 3) == 0) { 1116 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1117 return *ptr; 1118 } 1119 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1120 addr, 1121 reinterpret_cast<intptr_t>(instr)); 1122 UNIMPLEMENTED(); 1123 return 0; 1124 #endif 1125 } 1126 1127 1128 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { 1129 #if V8_TARGET_CAN_READ_UNALIGNED 1130 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1131 *ptr = value; 1132 return; 1133 #else 1134 if ((addr & 3) == 0) { 1135 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1136 *ptr = value; 1137 return; 1138 } 1139 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1140 addr, 1141 reinterpret_cast<intptr_t>(instr)); 1142 UNIMPLEMENTED(); 1143 #endif 1144 } 1145 1146 1147 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { 1148 #if V8_TARGET_CAN_READ_UNALIGNED 1149 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1150 return *ptr; 1151 #else 1152 if ((addr & 1) == 0) { 1153 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1154 return *ptr; 1155 } 1156 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1157 addr, 1158 reinterpret_cast<intptr_t>(instr)); 1159 UNIMPLEMENTED(); 1160 return 0; 1161 #endif 1162 } 1163 1164 1165 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) { 1166 #if V8_TARGET_CAN_READ_UNALIGNED 1167 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1168 return *ptr; 1169 #else 1170 if ((addr & 1) == 0) { 1171 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1172 return *ptr; 1173 } 1174 PrintF("Unaligned signed halfword read at 0x%08x\n", addr); 1175 UNIMPLEMENTED(); 1176 return 0; 1177 #endif 1178 } 1179 1180 1181 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { 1182 #if V8_TARGET_CAN_READ_UNALIGNED 1183 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1184 *ptr = value; 1185 return; 1186 #else 1187 if ((addr & 1) == 0) { 1188 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1189 *ptr = value; 1190 return; 1191 } 1192 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1193 addr, 1194 reinterpret_cast<intptr_t>(instr)); 1195 UNIMPLEMENTED(); 1196 #endif 1197 } 1198 1199 1200 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { 1201 #if V8_TARGET_CAN_READ_UNALIGNED 1202 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1203 *ptr = value; 1204 return; 1205 #else 1206 if ((addr & 1) == 0) { 1207 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1208 *ptr = value; 1209 return; 1210 } 1211 PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1212 addr, 1213 reinterpret_cast<intptr_t>(instr)); 1214 UNIMPLEMENTED(); 1215 #endif 1216 } 1217 1218 1219 uint8_t Simulator::ReadBU(int32_t addr) { 1220 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1221 return *ptr; 1222 } 1223 1224 1225 int8_t Simulator::ReadB(int32_t addr) { 1226 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1227 return *ptr; 1228 } 1229 1230 1231 void Simulator::WriteB(int32_t addr, uint8_t value) { 1232 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1233 *ptr = value; 1234 } 1235 1236 1237 void Simulator::WriteB(int32_t addr, int8_t value) { 1238 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1239 *ptr = value; 1240 } 1241 1242 1243 int32_t* Simulator::ReadDW(int32_t addr) { 1244 #if V8_TARGET_CAN_READ_UNALIGNED 1245 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1246 return ptr; 1247 #else 1248 if ((addr & 3) == 0) { 1249 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1250 return ptr; 1251 } 1252 PrintF("Unaligned read at 0x%08x\n", addr); 1253 UNIMPLEMENTED(); 1254 return 0; 1255 #endif 1256 } 1257 1258 1259 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) { 1260 #if V8_TARGET_CAN_READ_UNALIGNED 1261 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1262 *ptr++ = value1; 1263 *ptr = value2; 1264 return; 1265 #else 1266 if ((addr & 3) == 0) { 1267 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1268 *ptr++ = value1; 1269 *ptr = value2; 1270 return; 1271 } 1272 PrintF("Unaligned write at 0x%08x\n", addr); 1273 UNIMPLEMENTED(); 1274 #endif 1275 } 1276 1277 1278 // Returns the limit of the stack area to enable checking for stack overflows. 1279 uintptr_t Simulator::StackLimit() const { 1280 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when 1281 // pushing values. 1282 return reinterpret_cast<uintptr_t>(stack_) + 1024; 1283 } 1284 1285 1286 // Unsupported instructions use Format to print an error and stop execution. 1287 void Simulator::Format(Instruction* instr, const char* format) { 1288 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", 1289 reinterpret_cast<intptr_t>(instr), format); 1290 UNIMPLEMENTED(); 1291 } 1292 1293 1294 // Checks if the current instruction should be executed based on its 1295 // condition bits. 1296 bool Simulator::ConditionallyExecute(Instruction* instr) { 1297 switch (instr->ConditionField()) { 1298 case eq: return z_flag_; 1299 case ne: return !z_flag_; 1300 case cs: return c_flag_; 1301 case cc: return !c_flag_; 1302 case mi: return n_flag_; 1303 case pl: return !n_flag_; 1304 case vs: return v_flag_; 1305 case vc: return !v_flag_; 1306 case hi: return c_flag_ && !z_flag_; 1307 case ls: return !c_flag_ || z_flag_; 1308 case ge: return n_flag_ == v_flag_; 1309 case lt: return n_flag_ != v_flag_; 1310 case gt: return !z_flag_ && (n_flag_ == v_flag_); 1311 case le: return z_flag_ || (n_flag_ != v_flag_); 1312 case al: return true; 1313 default: UNREACHABLE(); 1314 } 1315 return false; 1316 } 1317 1318 1319 // Calculate and set the Negative and Zero flags. 1320 void Simulator::SetNZFlags(int32_t val) { 1321 n_flag_ = (val < 0); 1322 z_flag_ = (val == 0); 1323 } 1324 1325 1326 // Set the Carry flag. 1327 void Simulator::SetCFlag(bool val) { 1328 c_flag_ = val; 1329 } 1330 1331 1332 // Set the oVerflow flag. 1333 void Simulator::SetVFlag(bool val) { 1334 v_flag_ = val; 1335 } 1336 1337 1338 // Calculate C flag value for additions. 1339 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) { 1340 uint32_t uleft = static_cast<uint32_t>(left); 1341 uint32_t uright = static_cast<uint32_t>(right); 1342 uint32_t urest = 0xffffffffU - uleft; 1343 1344 return (uright > urest) || 1345 (carry && (((uright + 1) > urest) || (uright > (urest - 1)))); 1346 } 1347 1348 1349 // Calculate C flag value for subtractions. 1350 bool Simulator::BorrowFrom(int32_t left, int32_t right) { 1351 uint32_t uleft = static_cast<uint32_t>(left); 1352 uint32_t uright = static_cast<uint32_t>(right); 1353 1354 return (uright > uleft); 1355 } 1356 1357 1358 // Calculate V flag value for additions and subtractions. 1359 bool Simulator::OverflowFrom(int32_t alu_out, 1360 int32_t left, int32_t right, bool addition) { 1361 bool overflow; 1362 if (addition) { 1363 // operands have the same sign 1364 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) 1365 // and operands and result have different sign 1366 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 1367 } else { 1368 // operands have different signs 1369 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) 1370 // and first operand and result have different signs 1371 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 1372 } 1373 return overflow; 1374 } 1375 1376 1377 // Support for VFP comparisons. 1378 void Simulator::Compute_FPSCR_Flags(double val1, double val2) { 1379 if (isnan(val1) || isnan(val2)) { 1380 n_flag_FPSCR_ = false; 1381 z_flag_FPSCR_ = false; 1382 c_flag_FPSCR_ = true; 1383 v_flag_FPSCR_ = true; 1384 // All non-NaN cases. 1385 } else if (val1 == val2) { 1386 n_flag_FPSCR_ = false; 1387 z_flag_FPSCR_ = true; 1388 c_flag_FPSCR_ = true; 1389 v_flag_FPSCR_ = false; 1390 } else if (val1 < val2) { 1391 n_flag_FPSCR_ = true; 1392 z_flag_FPSCR_ = false; 1393 c_flag_FPSCR_ = false; 1394 v_flag_FPSCR_ = false; 1395 } else { 1396 // Case when (val1 > val2). 1397 n_flag_FPSCR_ = false; 1398 z_flag_FPSCR_ = false; 1399 c_flag_FPSCR_ = true; 1400 v_flag_FPSCR_ = false; 1401 } 1402 } 1403 1404 1405 void Simulator::Copy_FPSCR_to_APSR() { 1406 n_flag_ = n_flag_FPSCR_; 1407 z_flag_ = z_flag_FPSCR_; 1408 c_flag_ = c_flag_FPSCR_; 1409 v_flag_ = v_flag_FPSCR_; 1410 } 1411 1412 1413 // Addressing Mode 1 - Data-processing operands: 1414 // Get the value based on the shifter_operand with register. 1415 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) { 1416 ShiftOp shift = instr->ShiftField(); 1417 int shift_amount = instr->ShiftAmountValue(); 1418 int32_t result = get_register(instr->RmValue()); 1419 if (instr->Bit(4) == 0) { 1420 // by immediate 1421 if ((shift == ROR) && (shift_amount == 0)) { 1422 UNIMPLEMENTED(); 1423 return result; 1424 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 1425 shift_amount = 32; 1426 } 1427 switch (shift) { 1428 case ASR: { 1429 if (shift_amount == 0) { 1430 if (result < 0) { 1431 result = 0xffffffff; 1432 *carry_out = true; 1433 } else { 1434 result = 0; 1435 *carry_out = false; 1436 } 1437 } else { 1438 result >>= (shift_amount - 1); 1439 *carry_out = (result & 1) == 1; 1440 result >>= 1; 1441 } 1442 break; 1443 } 1444 1445 case LSL: { 1446 if (shift_amount == 0) { 1447 *carry_out = c_flag_; 1448 } else { 1449 result <<= (shift_amount - 1); 1450 *carry_out = (result < 0); 1451 result <<= 1; 1452 } 1453 break; 1454 } 1455 1456 case LSR: { 1457 if (shift_amount == 0) { 1458 result = 0; 1459 *carry_out = c_flag_; 1460 } else { 1461 uint32_t uresult = static_cast<uint32_t>(result); 1462 uresult >>= (shift_amount - 1); 1463 *carry_out = (uresult & 1) == 1; 1464 uresult >>= 1; 1465 result = static_cast<int32_t>(uresult); 1466 } 1467 break; 1468 } 1469 1470 case ROR: { 1471 UNIMPLEMENTED(); 1472 break; 1473 } 1474 1475 default: { 1476 UNREACHABLE(); 1477 break; 1478 } 1479 } 1480 } else { 1481 // by register 1482 int rs = instr->RsValue(); 1483 shift_amount = get_register(rs) &0xff; 1484 switch (shift) { 1485 case ASR: { 1486 if (shift_amount == 0) { 1487 *carry_out = c_flag_; 1488 } else if (shift_amount < 32) { 1489 result >>= (shift_amount - 1); 1490 *carry_out = (result & 1) == 1; 1491 result >>= 1; 1492 } else { 1493 ASSERT(shift_amount >= 32); 1494 if (result < 0) { 1495 *carry_out = true; 1496 result = 0xffffffff; 1497 } else { 1498 *carry_out = false; 1499 result = 0; 1500 } 1501 } 1502 break; 1503 } 1504 1505 case LSL: { 1506 if (shift_amount == 0) { 1507 *carry_out = c_flag_; 1508 } else if (shift_amount < 32) { 1509 result <<= (shift_amount - 1); 1510 *carry_out = (result < 0); 1511 result <<= 1; 1512 } else if (shift_amount == 32) { 1513 *carry_out = (result & 1) == 1; 1514 result = 0; 1515 } else { 1516 ASSERT(shift_amount > 32); 1517 *carry_out = false; 1518 result = 0; 1519 } 1520 break; 1521 } 1522 1523 case LSR: { 1524 if (shift_amount == 0) { 1525 *carry_out = c_flag_; 1526 } else if (shift_amount < 32) { 1527 uint32_t uresult = static_cast<uint32_t>(result); 1528 uresult >>= (shift_amount - 1); 1529 *carry_out = (uresult & 1) == 1; 1530 uresult >>= 1; 1531 result = static_cast<int32_t>(uresult); 1532 } else if (shift_amount == 32) { 1533 *carry_out = (result < 0); 1534 result = 0; 1535 } else { 1536 *carry_out = false; 1537 result = 0; 1538 } 1539 break; 1540 } 1541 1542 case ROR: { 1543 UNIMPLEMENTED(); 1544 break; 1545 } 1546 1547 default: { 1548 UNREACHABLE(); 1549 break; 1550 } 1551 } 1552 } 1553 return result; 1554 } 1555 1556 1557 // Addressing Mode 1 - Data-processing operands: 1558 // Get the value based on the shifter_operand with immediate. 1559 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) { 1560 int rotate = instr->RotateValue() * 2; 1561 int immed8 = instr->Immed8Value(); 1562 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); 1563 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); 1564 return imm; 1565 } 1566 1567 1568 static int count_bits(int bit_vector) { 1569 int count = 0; 1570 while (bit_vector != 0) { 1571 if ((bit_vector & 1) != 0) { 1572 count++; 1573 } 1574 bit_vector >>= 1; 1575 } 1576 return count; 1577 } 1578 1579 1580 void Simulator::ProcessPUW(Instruction* instr, 1581 int num_regs, 1582 int reg_size, 1583 intptr_t* start_address, 1584 intptr_t* end_address) { 1585 int rn = instr->RnValue(); 1586 int32_t rn_val = get_register(rn); 1587 switch (instr->PUField()) { 1588 case da_x: { 1589 UNIMPLEMENTED(); 1590 break; 1591 } 1592 case ia_x: { 1593 *start_address = rn_val; 1594 *end_address = rn_val + (num_regs * reg_size) - reg_size; 1595 rn_val = rn_val + (num_regs * reg_size); 1596 break; 1597 } 1598 case db_x: { 1599 *start_address = rn_val - (num_regs * reg_size); 1600 *end_address = rn_val - reg_size; 1601 rn_val = *start_address; 1602 break; 1603 } 1604 case ib_x: { 1605 *start_address = rn_val + reg_size; 1606 *end_address = rn_val + (num_regs * reg_size); 1607 rn_val = *end_address; 1608 break; 1609 } 1610 default: { 1611 UNREACHABLE(); 1612 break; 1613 } 1614 } 1615 if (instr->HasW()) { 1616 set_register(rn, rn_val); 1617 } 1618 } 1619 1620 // Addressing Mode 4 - Load and Store Multiple 1621 void Simulator::HandleRList(Instruction* instr, bool load) { 1622 int rlist = instr->RlistValue(); 1623 int num_regs = count_bits(rlist); 1624 1625 intptr_t start_address = 0; 1626 intptr_t end_address = 0; 1627 ProcessPUW(instr, num_regs, kPointerSize, &start_address, &end_address); 1628 1629 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); 1630 // Catch null pointers a little earlier. 1631 ASSERT(start_address > 8191 || start_address < 0); 1632 int reg = 0; 1633 while (rlist != 0) { 1634 if ((rlist & 1) != 0) { 1635 if (load) { 1636 set_register(reg, *address); 1637 } else { 1638 *address = get_register(reg); 1639 } 1640 address += 1; 1641 } 1642 reg++; 1643 rlist >>= 1; 1644 } 1645 ASSERT(end_address == ((intptr_t)address) - 4); 1646 } 1647 1648 1649 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers. 1650 void Simulator::HandleVList(Instruction* instr) { 1651 VFPRegPrecision precision = 1652 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision; 1653 int operand_size = (precision == kSinglePrecision) ? 4 : 8; 1654 1655 bool load = (instr->VLValue() == 0x1); 1656 1657 int vd; 1658 int num_regs; 1659 vd = instr->VFPDRegValue(precision); 1660 if (precision == kSinglePrecision) { 1661 num_regs = instr->Immed8Value(); 1662 } else { 1663 num_regs = instr->Immed8Value() / 2; 1664 } 1665 1666 intptr_t start_address = 0; 1667 intptr_t end_address = 0; 1668 ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address); 1669 1670 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); 1671 for (int reg = vd; reg < vd + num_regs; reg++) { 1672 if (precision == kSinglePrecision) { 1673 if (load) { 1674 set_s_register_from_sinteger( 1675 reg, ReadW(reinterpret_cast<int32_t>(address), instr)); 1676 } else { 1677 WriteW(reinterpret_cast<int32_t>(address), 1678 get_sinteger_from_s_register(reg), instr); 1679 } 1680 address += 1; 1681 } else { 1682 if (load) { 1683 set_s_register_from_sinteger( 1684 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr)); 1685 set_s_register_from_sinteger( 1686 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr)); 1687 } else { 1688 WriteW(reinterpret_cast<int32_t>(address), 1689 get_sinteger_from_s_register(2 * reg), instr); 1690 WriteW(reinterpret_cast<int32_t>(address + 1), 1691 get_sinteger_from_s_register(2 * reg + 1), instr); 1692 } 1693 address += 2; 1694 } 1695 } 1696 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address); 1697 } 1698 1699 1700 // Calls into the V8 runtime are based on this very simple interface. 1701 // Note: To be able to return two values from some calls the code in runtime.cc 1702 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 1703 // 64-bit value. With the code below we assume that all runtime calls return 1704 // 64 bits of result. If they don't, the r1 result register contains a bogus 1705 // value, which is fine because it is caller-saved. 1706 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 1707 int32_t arg1, 1708 int32_t arg2, 1709 int32_t arg3, 1710 int32_t arg4, 1711 int32_t arg5); 1712 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, 1713 int32_t arg1, 1714 int32_t arg2, 1715 int32_t arg3); 1716 1717 // This signature supports direct call in to API function native callback 1718 // (refer to InvocationCallback in v8.h). 1719 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); 1720 1721 // This signature supports direct call to accessor getter callback. 1722 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, 1723 int32_t arg1); 1724 1725 // Software interrupt instructions are used by the simulator to call into the 1726 // C-based V8 runtime. 1727 void Simulator::SoftwareInterrupt(Instruction* instr) { 1728 int svc = instr->SvcValue(); 1729 switch (svc) { 1730 case kCallRtRedirected: { 1731 // Check if stack is aligned. Error if not aligned is reported below to 1732 // include information on the function called. 1733 bool stack_aligned = 1734 (get_register(sp) 1735 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; 1736 Redirection* redirection = Redirection::FromSwiInstruction(instr); 1737 int32_t arg0 = get_register(r0); 1738 int32_t arg1 = get_register(r1); 1739 int32_t arg2 = get_register(r2); 1740 int32_t arg3 = get_register(r3); 1741 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); 1742 int32_t arg4 = stack_pointer[0]; 1743 int32_t arg5 = stack_pointer[1]; 1744 bool fp_call = 1745 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 1746 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 1747 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 1748 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 1749 if (use_eabi_hardfloat()) { 1750 // With the hard floating point calling convention, double 1751 // arguments are passed in VFP registers. Fetch the arguments 1752 // from there and call the builtin using soft floating point 1753 // convention. 1754 switch (redirection->type()) { 1755 case ExternalReference::BUILTIN_FP_FP_CALL: 1756 case ExternalReference::BUILTIN_COMPARE_CALL: 1757 arg0 = vfp_register[0]; 1758 arg1 = vfp_register[1]; 1759 arg2 = vfp_register[2]; 1760 arg3 = vfp_register[3]; 1761 break; 1762 case ExternalReference::BUILTIN_FP_CALL: 1763 arg0 = vfp_register[0]; 1764 arg1 = vfp_register[1]; 1765 break; 1766 case ExternalReference::BUILTIN_FP_INT_CALL: 1767 arg0 = vfp_register[0]; 1768 arg1 = vfp_register[1]; 1769 arg2 = get_register(0); 1770 break; 1771 default: 1772 break; 1773 } 1774 } 1775 // This is dodgy but it works because the C entry stubs are never moved. 1776 // See comment in codegen-arm.cc and bug 1242173. 1777 int32_t saved_lr = get_register(lr); 1778 intptr_t external = 1779 reinterpret_cast<intptr_t>(redirection->external_function()); 1780 if (fp_call) { 1781 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1782 SimulatorRuntimeFPCall target = 1783 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1784 double dval0, dval1; 1785 int32_t ival; 1786 switch (redirection->type()) { 1787 case ExternalReference::BUILTIN_FP_FP_CALL: 1788 case ExternalReference::BUILTIN_COMPARE_CALL: 1789 GetFpArgs(&dval0, &dval1); 1790 PrintF("Call to host function at %p with args %f, %f", 1791 FUNCTION_ADDR(target), dval0, dval1); 1792 break; 1793 case ExternalReference::BUILTIN_FP_CALL: 1794 GetFpArgs(&dval0); 1795 PrintF("Call to host function at %p with arg %f", 1796 FUNCTION_ADDR(target), dval0); 1797 break; 1798 case ExternalReference::BUILTIN_FP_INT_CALL: 1799 GetFpArgs(&dval0, &ival); 1800 PrintF("Call to host function at %p with args %f, %d", 1801 FUNCTION_ADDR(target), dval0, ival); 1802 break; 1803 default: 1804 UNREACHABLE(); 1805 break; 1806 } 1807 if (!stack_aligned) { 1808 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1809 } 1810 PrintF("\n"); 1811 } 1812 CHECK(stack_aligned); 1813 if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) { 1814 SimulatorRuntimeFPCall target = 1815 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1816 double result = target(arg0, arg1, arg2, arg3); 1817 SetFpResult(result); 1818 } else { 1819 SimulatorRuntimeCall target = 1820 reinterpret_cast<SimulatorRuntimeCall>(external); 1821 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 1822 int32_t lo_res = static_cast<int32_t>(result); 1823 int32_t hi_res = static_cast<int32_t>(result >> 32); 1824 if (::v8::internal::FLAG_trace_sim) { 1825 PrintF("Returned %08x\n", lo_res); 1826 } 1827 set_register(r0, lo_res); 1828 set_register(r1, hi_res); 1829 } 1830 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 1831 SimulatorRuntimeDirectApiCall target = 1832 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 1833 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1834 PrintF("Call to host function at %p args %08x", 1835 FUNCTION_ADDR(target), arg0); 1836 if (!stack_aligned) { 1837 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1838 } 1839 PrintF("\n"); 1840 } 1841 CHECK(stack_aligned); 1842 v8::Handle<v8::Value> result = target(arg0); 1843 if (::v8::internal::FLAG_trace_sim) { 1844 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); 1845 } 1846 set_register(r0, (int32_t) *result); 1847 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 1848 SimulatorRuntimeDirectGetterCall target = 1849 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 1850 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1851 PrintF("Call to host function at %p args %08x %08x", 1852 FUNCTION_ADDR(target), arg0, arg1); 1853 if (!stack_aligned) { 1854 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1855 } 1856 PrintF("\n"); 1857 } 1858 CHECK(stack_aligned); 1859 v8::Handle<v8::Value> result = target(arg0, arg1); 1860 if (::v8::internal::FLAG_trace_sim) { 1861 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); 1862 } 1863 set_register(r0, (int32_t) *result); 1864 } else { 1865 // builtin call. 1866 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); 1867 SimulatorRuntimeCall target = 1868 reinterpret_cast<SimulatorRuntimeCall>(external); 1869 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1870 PrintF( 1871 "Call to host function at %p" 1872 "args %08x, %08x, %08x, %08x, %08x, %08x", 1873 FUNCTION_ADDR(target), 1874 arg0, 1875 arg1, 1876 arg2, 1877 arg3, 1878 arg4, 1879 arg5); 1880 if (!stack_aligned) { 1881 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1882 } 1883 PrintF("\n"); 1884 } 1885 CHECK(stack_aligned); 1886 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 1887 int32_t lo_res = static_cast<int32_t>(result); 1888 int32_t hi_res = static_cast<int32_t>(result >> 32); 1889 if (::v8::internal::FLAG_trace_sim) { 1890 PrintF("Returned %08x\n", lo_res); 1891 } 1892 set_register(r0, lo_res); 1893 set_register(r1, hi_res); 1894 } 1895 set_register(lr, saved_lr); 1896 set_pc(get_register(lr)); 1897 break; 1898 } 1899 case kBreakpoint: { 1900 ArmDebugger dbg(this); 1901 dbg.Debug(); 1902 break; 1903 } 1904 // stop uses all codes greater than 1 << 23. 1905 default: { 1906 if (svc >= (1 << 23)) { 1907 uint32_t code = svc & kStopCodeMask; 1908 if (isWatchedStop(code)) { 1909 IncreaseStopCounter(code); 1910 } 1911 // Stop if it is enabled, otherwise go on jumping over the stop 1912 // and the message address. 1913 if (isEnabledStop(code)) { 1914 ArmDebugger dbg(this); 1915 dbg.Stop(instr); 1916 } else { 1917 set_pc(get_pc() + 2 * Instruction::kInstrSize); 1918 } 1919 } else { 1920 // This is not a valid svc code. 1921 UNREACHABLE(); 1922 break; 1923 } 1924 } 1925 } 1926 } 1927 1928 1929 // Stop helper functions. 1930 bool Simulator::isStopInstruction(Instruction* instr) { 1931 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); 1932 } 1933 1934 1935 bool Simulator::isWatchedStop(uint32_t code) { 1936 ASSERT(code <= kMaxStopCode); 1937 return code < kNumOfWatchedStops; 1938 } 1939 1940 1941 bool Simulator::isEnabledStop(uint32_t code) { 1942 ASSERT(code <= kMaxStopCode); 1943 // Unwatched stops are always enabled. 1944 return !isWatchedStop(code) || 1945 !(watched_stops[code].count & kStopDisabledBit); 1946 } 1947 1948 1949 void Simulator::EnableStop(uint32_t code) { 1950 ASSERT(isWatchedStop(code)); 1951 if (!isEnabledStop(code)) { 1952 watched_stops[code].count &= ~kStopDisabledBit; 1953 } 1954 } 1955 1956 1957 void Simulator::DisableStop(uint32_t code) { 1958 ASSERT(isWatchedStop(code)); 1959 if (isEnabledStop(code)) { 1960 watched_stops[code].count |= kStopDisabledBit; 1961 } 1962 } 1963 1964 1965 void Simulator::IncreaseStopCounter(uint32_t code) { 1966 ASSERT(code <= kMaxStopCode); 1967 ASSERT(isWatchedStop(code)); 1968 if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) { 1969 PrintF("Stop counter for code %i has overflowed.\n" 1970 "Enabling this code and reseting the counter to 0.\n", code); 1971 watched_stops[code].count = 0; 1972 EnableStop(code); 1973 } else { 1974 watched_stops[code].count++; 1975 } 1976 } 1977 1978 1979 // Print a stop status. 1980 void Simulator::PrintStopInfo(uint32_t code) { 1981 ASSERT(code <= kMaxStopCode); 1982 if (!isWatchedStop(code)) { 1983 PrintF("Stop not watched."); 1984 } else { 1985 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled"; 1986 int32_t count = watched_stops[code].count & ~kStopDisabledBit; 1987 // Don't print the state of unused breakpoints. 1988 if (count != 0) { 1989 if (watched_stops[code].desc) { 1990 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", 1991 code, code, state, count, watched_stops[code].desc); 1992 } else { 1993 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", 1994 code, code, state, count); 1995 } 1996 } 1997 } 1998 } 1999 2000 2001 // Handle execution based on instruction types. 2002 2003 // Instruction types 0 and 1 are both rolled into one function because they 2004 // only differ in the handling of the shifter_operand. 2005 void Simulator::DecodeType01(Instruction* instr) { 2006 int type = instr->TypeValue(); 2007 if ((type == 0) && instr->IsSpecialType0()) { 2008 // multiply instruction or extra loads and stores 2009 if (instr->Bits(7, 4) == 9) { 2010 if (instr->Bit(24) == 0) { 2011 // Raw field decoding here. Multiply instructions have their Rd in 2012 // funny places. 2013 int rn = instr->RnValue(); 2014 int rm = instr->RmValue(); 2015 int rs = instr->RsValue(); 2016 int32_t rs_val = get_register(rs); 2017 int32_t rm_val = get_register(rm); 2018 if (instr->Bit(23) == 0) { 2019 if (instr->Bit(21) == 0) { 2020 // The MUL instruction description (A 4.1.33) refers to Rd as being 2021 // the destination for the operation, but it confusingly uses the 2022 // Rn field to encode it. 2023 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 2024 int rd = rn; // Remap the rn field to the Rd register. 2025 int32_t alu_out = rm_val * rs_val; 2026 set_register(rd, alu_out); 2027 if (instr->HasS()) { 2028 SetNZFlags(alu_out); 2029 } 2030 } else { 2031 // The MLA instruction description (A 4.1.28) refers to the order 2032 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 2033 // Rn field to encode the Rd register and the Rd field to encode 2034 // the Rn register. 2035 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 2036 } 2037 } else { 2038 // The signed/long multiply instructions use the terms RdHi and RdLo 2039 // when referring to the target registers. They are mapped to the Rn 2040 // and Rd fields as follows: 2041 // RdLo == Rd 2042 // RdHi == Rn (This is confusingly stored in variable rd here 2043 // because the mul instruction from above uses the 2044 // Rn field to encode the Rd register. Good luck figuring 2045 // this out without reading the ARM instruction manual 2046 // at a very detailed level.) 2047 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm"); 2048 int rd_hi = rn; // Remap the rn field to the RdHi register. 2049 int rd_lo = instr->RdValue(); 2050 int32_t hi_res = 0; 2051 int32_t lo_res = 0; 2052 if (instr->Bit(22) == 1) { 2053 int64_t left_op = static_cast<int32_t>(rm_val); 2054 int64_t right_op = static_cast<int32_t>(rs_val); 2055 uint64_t result = left_op * right_op; 2056 hi_res = static_cast<int32_t>(result >> 32); 2057 lo_res = static_cast<int32_t>(result & 0xffffffff); 2058 } else { 2059 // unsigned multiply 2060 uint64_t left_op = static_cast<uint32_t>(rm_val); 2061 uint64_t right_op = static_cast<uint32_t>(rs_val); 2062 uint64_t result = left_op * right_op; 2063 hi_res = static_cast<int32_t>(result >> 32); 2064 lo_res = static_cast<int32_t>(result & 0xffffffff); 2065 } 2066 set_register(rd_lo, lo_res); 2067 set_register(rd_hi, hi_res); 2068 if (instr->HasS()) { 2069 UNIMPLEMENTED(); 2070 } 2071 } 2072 } else { 2073 UNIMPLEMENTED(); // Not used by V8. 2074 } 2075 } else { 2076 // extra load/store instructions 2077 int rd = instr->RdValue(); 2078 int rn = instr->RnValue(); 2079 int32_t rn_val = get_register(rn); 2080 int32_t addr = 0; 2081 if (instr->Bit(22) == 0) { 2082 int rm = instr->RmValue(); 2083 int32_t rm_val = get_register(rm); 2084 switch (instr->PUField()) { 2085 case da_x: { 2086 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 2087 ASSERT(!instr->HasW()); 2088 addr = rn_val; 2089 rn_val -= rm_val; 2090 set_register(rn, rn_val); 2091 break; 2092 } 2093 case ia_x: { 2094 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 2095 ASSERT(!instr->HasW()); 2096 addr = rn_val; 2097 rn_val += rm_val; 2098 set_register(rn, rn_val); 2099 break; 2100 } 2101 case db_x: { 2102 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 2103 rn_val -= rm_val; 2104 addr = rn_val; 2105 if (instr->HasW()) { 2106 set_register(rn, rn_val); 2107 } 2108 break; 2109 } 2110 case ib_x: { 2111 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 2112 rn_val += rm_val; 2113 addr = rn_val; 2114 if (instr->HasW()) { 2115 set_register(rn, rn_val); 2116 } 2117 break; 2118 } 2119 default: { 2120 // The PU field is a 2-bit field. 2121 UNREACHABLE(); 2122 break; 2123 } 2124 } 2125 } else { 2126 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue(); 2127 switch (instr->PUField()) { 2128 case da_x: { 2129 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 2130 ASSERT(!instr->HasW()); 2131 addr = rn_val; 2132 rn_val -= imm_val; 2133 set_register(rn, rn_val); 2134 break; 2135 } 2136 case ia_x: { 2137 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 2138 ASSERT(!instr->HasW()); 2139 addr = rn_val; 2140 rn_val += imm_val; 2141 set_register(rn, rn_val); 2142 break; 2143 } 2144 case db_x: { 2145 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 2146 rn_val -= imm_val; 2147 addr = rn_val; 2148 if (instr->HasW()) { 2149 set_register(rn, rn_val); 2150 } 2151 break; 2152 } 2153 case ib_x: { 2154 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 2155 rn_val += imm_val; 2156 addr = rn_val; 2157 if (instr->HasW()) { 2158 set_register(rn, rn_val); 2159 } 2160 break; 2161 } 2162 default: { 2163 // The PU field is a 2-bit field. 2164 UNREACHABLE(); 2165 break; 2166 } 2167 } 2168 } 2169 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) { 2170 ASSERT((rd % 2) == 0); 2171 if (instr->HasH()) { 2172 // The strd instruction. 2173 int32_t value1 = get_register(rd); 2174 int32_t value2 = get_register(rd+1); 2175 WriteDW(addr, value1, value2); 2176 } else { 2177 // The ldrd instruction. 2178 int* rn_data = ReadDW(addr); 2179 set_dw_register(rd, rn_data); 2180 } 2181 } else if (instr->HasH()) { 2182 if (instr->HasSign()) { 2183 if (instr->HasL()) { 2184 int16_t val = ReadH(addr, instr); 2185 set_register(rd, val); 2186 } else { 2187 int16_t val = get_register(rd); 2188 WriteH(addr, val, instr); 2189 } 2190 } else { 2191 if (instr->HasL()) { 2192 uint16_t val = ReadHU(addr, instr); 2193 set_register(rd, val); 2194 } else { 2195 uint16_t val = get_register(rd); 2196 WriteH(addr, val, instr); 2197 } 2198 } 2199 } else { 2200 // signed byte loads 2201 ASSERT(instr->HasSign()); 2202 ASSERT(instr->HasL()); 2203 int8_t val = ReadB(addr); 2204 set_register(rd, val); 2205 } 2206 return; 2207 } 2208 } else if ((type == 0) && instr->IsMiscType0()) { 2209 if (instr->Bits(22, 21) == 1) { 2210 int rm = instr->RmValue(); 2211 switch (instr->BitField(7, 4)) { 2212 case BX: 2213 set_pc(get_register(rm)); 2214 break; 2215 case BLX: { 2216 uint32_t old_pc = get_pc(); 2217 set_pc(get_register(rm)); 2218 set_register(lr, old_pc + Instruction::kInstrSize); 2219 break; 2220 } 2221 case BKPT: { 2222 ArmDebugger dbg(this); 2223 PrintF("Simulator hit BKPT.\n"); 2224 dbg.Debug(); 2225 break; 2226 } 2227 default: 2228 UNIMPLEMENTED(); 2229 } 2230 } else if (instr->Bits(22, 21) == 3) { 2231 int rm = instr->RmValue(); 2232 int rd = instr->RdValue(); 2233 switch (instr->BitField(7, 4)) { 2234 case CLZ: { 2235 uint32_t bits = get_register(rm); 2236 int leading_zeros = 0; 2237 if (bits == 0) { 2238 leading_zeros = 32; 2239 } else { 2240 while ((bits & 0x80000000u) == 0) { 2241 bits <<= 1; 2242 leading_zeros++; 2243 } 2244 } 2245 set_register(rd, leading_zeros); 2246 break; 2247 } 2248 default: 2249 UNIMPLEMENTED(); 2250 } 2251 } else { 2252 PrintF("%08x\n", instr->InstructionBits()); 2253 UNIMPLEMENTED(); 2254 } 2255 } else { 2256 int rd = instr->RdValue(); 2257 int rn = instr->RnValue(); 2258 int32_t rn_val = get_register(rn); 2259 int32_t shifter_operand = 0; 2260 bool shifter_carry_out = 0; 2261 if (type == 0) { 2262 shifter_operand = GetShiftRm(instr, &shifter_carry_out); 2263 } else { 2264 ASSERT(instr->TypeValue() == 1); 2265 shifter_operand = GetImm(instr, &shifter_carry_out); 2266 } 2267 int32_t alu_out; 2268 2269 switch (instr->OpcodeField()) { 2270 case AND: { 2271 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); 2272 // Format(instr, "and'cond's 'rd, 'rn, 'imm"); 2273 alu_out = rn_val & shifter_operand; 2274 set_register(rd, alu_out); 2275 if (instr->HasS()) { 2276 SetNZFlags(alu_out); 2277 SetCFlag(shifter_carry_out); 2278 } 2279 break; 2280 } 2281 2282 case EOR: { 2283 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm"); 2284 // Format(instr, "eor'cond's 'rd, 'rn, 'imm"); 2285 alu_out = rn_val ^ shifter_operand; 2286 set_register(rd, alu_out); 2287 if (instr->HasS()) { 2288 SetNZFlags(alu_out); 2289 SetCFlag(shifter_carry_out); 2290 } 2291 break; 2292 } 2293 2294 case SUB: { 2295 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm"); 2296 // Format(instr, "sub'cond's 'rd, 'rn, 'imm"); 2297 alu_out = rn_val - shifter_operand; 2298 set_register(rd, alu_out); 2299 if (instr->HasS()) { 2300 SetNZFlags(alu_out); 2301 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2302 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2303 } 2304 break; 2305 } 2306 2307 case RSB: { 2308 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm"); 2309 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm"); 2310 alu_out = shifter_operand - rn_val; 2311 set_register(rd, alu_out); 2312 if (instr->HasS()) { 2313 SetNZFlags(alu_out); 2314 SetCFlag(!BorrowFrom(shifter_operand, rn_val)); 2315 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); 2316 } 2317 break; 2318 } 2319 2320 case ADD: { 2321 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm"); 2322 // Format(instr, "add'cond's 'rd, 'rn, 'imm"); 2323 alu_out = rn_val + shifter_operand; 2324 set_register(rd, alu_out); 2325 if (instr->HasS()) { 2326 SetNZFlags(alu_out); 2327 SetCFlag(CarryFrom(rn_val, shifter_operand)); 2328 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2329 } 2330 break; 2331 } 2332 2333 case ADC: { 2334 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); 2335 // Format(instr, "adc'cond's 'rd, 'rn, 'imm"); 2336 alu_out = rn_val + shifter_operand + GetCarry(); 2337 set_register(rd, alu_out); 2338 if (instr->HasS()) { 2339 SetNZFlags(alu_out); 2340 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry())); 2341 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2342 } 2343 break; 2344 } 2345 2346 case SBC: { 2347 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); 2348 Format(instr, "sbc'cond's 'rd, 'rn, 'imm"); 2349 break; 2350 } 2351 2352 case RSC: { 2353 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); 2354 Format(instr, "rsc'cond's 'rd, 'rn, 'imm"); 2355 break; 2356 } 2357 2358 case TST: { 2359 if (instr->HasS()) { 2360 // Format(instr, "tst'cond 'rn, 'shift_rm"); 2361 // Format(instr, "tst'cond 'rn, 'imm"); 2362 alu_out = rn_val & shifter_operand; 2363 SetNZFlags(alu_out); 2364 SetCFlag(shifter_carry_out); 2365 } else { 2366 // Format(instr, "movw'cond 'rd, 'imm"). 2367 alu_out = instr->ImmedMovwMovtValue(); 2368 set_register(rd, alu_out); 2369 } 2370 break; 2371 } 2372 2373 case TEQ: { 2374 if (instr->HasS()) { 2375 // Format(instr, "teq'cond 'rn, 'shift_rm"); 2376 // Format(instr, "teq'cond 'rn, 'imm"); 2377 alu_out = rn_val ^ shifter_operand; 2378 SetNZFlags(alu_out); 2379 SetCFlag(shifter_carry_out); 2380 } else { 2381 // Other instructions matching this pattern are handled in the 2382 // miscellaneous instructions part above. 2383 UNREACHABLE(); 2384 } 2385 break; 2386 } 2387 2388 case CMP: { 2389 if (instr->HasS()) { 2390 // Format(instr, "cmp'cond 'rn, 'shift_rm"); 2391 // Format(instr, "cmp'cond 'rn, 'imm"); 2392 alu_out = rn_val - shifter_operand; 2393 SetNZFlags(alu_out); 2394 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2395 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2396 } else { 2397 // Format(instr, "movt'cond 'rd, 'imm"). 2398 alu_out = (get_register(rd) & 0xffff) | 2399 (instr->ImmedMovwMovtValue() << 16); 2400 set_register(rd, alu_out); 2401 } 2402 break; 2403 } 2404 2405 case CMN: { 2406 if (instr->HasS()) { 2407 // Format(instr, "cmn'cond 'rn, 'shift_rm"); 2408 // Format(instr, "cmn'cond 'rn, 'imm"); 2409 alu_out = rn_val + shifter_operand; 2410 SetNZFlags(alu_out); 2411 SetCFlag(!CarryFrom(rn_val, shifter_operand)); 2412 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2413 } else { 2414 // Other instructions matching this pattern are handled in the 2415 // miscellaneous instructions part above. 2416 UNREACHABLE(); 2417 } 2418 break; 2419 } 2420 2421 case ORR: { 2422 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); 2423 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); 2424 alu_out = rn_val | shifter_operand; 2425 set_register(rd, alu_out); 2426 if (instr->HasS()) { 2427 SetNZFlags(alu_out); 2428 SetCFlag(shifter_carry_out); 2429 } 2430 break; 2431 } 2432 2433 case MOV: { 2434 // Format(instr, "mov'cond's 'rd, 'shift_rm"); 2435 // Format(instr, "mov'cond's 'rd, 'imm"); 2436 alu_out = shifter_operand; 2437 set_register(rd, alu_out); 2438 if (instr->HasS()) { 2439 SetNZFlags(alu_out); 2440 SetCFlag(shifter_carry_out); 2441 } 2442 break; 2443 } 2444 2445 case BIC: { 2446 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm"); 2447 // Format(instr, "bic'cond's 'rd, 'rn, 'imm"); 2448 alu_out = rn_val & ~shifter_operand; 2449 set_register(rd, alu_out); 2450 if (instr->HasS()) { 2451 SetNZFlags(alu_out); 2452 SetCFlag(shifter_carry_out); 2453 } 2454 break; 2455 } 2456 2457 case MVN: { 2458 // Format(instr, "mvn'cond's 'rd, 'shift_rm"); 2459 // Format(instr, "mvn'cond's 'rd, 'imm"); 2460 alu_out = ~shifter_operand; 2461 set_register(rd, alu_out); 2462 if (instr->HasS()) { 2463 SetNZFlags(alu_out); 2464 SetCFlag(shifter_carry_out); 2465 } 2466 break; 2467 } 2468 2469 default: { 2470 UNREACHABLE(); 2471 break; 2472 } 2473 } 2474 } 2475 } 2476 2477 2478 void Simulator::DecodeType2(Instruction* instr) { 2479 int rd = instr->RdValue(); 2480 int rn = instr->RnValue(); 2481 int32_t rn_val = get_register(rn); 2482 int32_t im_val = instr->Offset12Value(); 2483 int32_t addr = 0; 2484 switch (instr->PUField()) { 2485 case da_x: { 2486 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 2487 ASSERT(!instr->HasW()); 2488 addr = rn_val; 2489 rn_val -= im_val; 2490 set_register(rn, rn_val); 2491 break; 2492 } 2493 case ia_x: { 2494 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 2495 ASSERT(!instr->HasW()); 2496 addr = rn_val; 2497 rn_val += im_val; 2498 set_register(rn, rn_val); 2499 break; 2500 } 2501 case db_x: { 2502 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 2503 rn_val -= im_val; 2504 addr = rn_val; 2505 if (instr->HasW()) { 2506 set_register(rn, rn_val); 2507 } 2508 break; 2509 } 2510 case ib_x: { 2511 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 2512 rn_val += im_val; 2513 addr = rn_val; 2514 if (instr->HasW()) { 2515 set_register(rn, rn_val); 2516 } 2517 break; 2518 } 2519 default: { 2520 UNREACHABLE(); 2521 break; 2522 } 2523 } 2524 if (instr->HasB()) { 2525 if (instr->HasL()) { 2526 byte val = ReadBU(addr); 2527 set_register(rd, val); 2528 } else { 2529 byte val = get_register(rd); 2530 WriteB(addr, val); 2531 } 2532 } else { 2533 if (instr->HasL()) { 2534 set_register(rd, ReadW(addr, instr)); 2535 } else { 2536 WriteW(addr, get_register(rd), instr); 2537 } 2538 } 2539 } 2540 2541 2542 void Simulator::DecodeType3(Instruction* instr) { 2543 int rd = instr->RdValue(); 2544 int rn = instr->RnValue(); 2545 int32_t rn_val = get_register(rn); 2546 bool shifter_carry_out = 0; 2547 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); 2548 int32_t addr = 0; 2549 switch (instr->PUField()) { 2550 case da_x: { 2551 ASSERT(!instr->HasW()); 2552 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 2553 UNIMPLEMENTED(); 2554 break; 2555 } 2556 case ia_x: { 2557 if (instr->HasW()) { 2558 ASSERT(instr->Bits(5, 4) == 0x1); 2559 2560 if (instr->Bit(22) == 0x1) { // USAT. 2561 int32_t sat_pos = instr->Bits(20, 16); 2562 int32_t sat_val = (1 << sat_pos) - 1; 2563 int32_t shift = instr->Bits(11, 7); 2564 int32_t shift_type = instr->Bit(6); 2565 int32_t rm_val = get_register(instr->RmValue()); 2566 if (shift_type == 0) { // LSL 2567 rm_val <<= shift; 2568 } else { // ASR 2569 rm_val >>= shift; 2570 } 2571 // If saturation occurs, the Q flag should be set in the CPSR. 2572 // There is no Q flag yet, and no instruction (MRS) to read the 2573 // CPSR directly. 2574 if (rm_val > sat_val) { 2575 rm_val = sat_val; 2576 } else if (rm_val < 0) { 2577 rm_val = 0; 2578 } 2579 set_register(rd, rm_val); 2580 } else { // SSAT. 2581 UNIMPLEMENTED(); 2582 } 2583 return; 2584 } else { 2585 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 2586 UNIMPLEMENTED(); 2587 } 2588 break; 2589 } 2590 case db_x: { 2591 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 2592 addr = rn_val - shifter_operand; 2593 if (instr->HasW()) { 2594 set_register(rn, addr); 2595 } 2596 break; 2597 } 2598 case ib_x: { 2599 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 2600 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 2601 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 2602 uint32_t msbit = widthminus1 + lsbit; 2603 if (msbit <= 31) { 2604 if (instr->Bit(22)) { 2605 // ubfx - unsigned bitfield extract. 2606 uint32_t rm_val = 2607 static_cast<uint32_t>(get_register(instr->RmValue())); 2608 uint32_t extr_val = rm_val << (31 - msbit); 2609 extr_val = extr_val >> (31 - widthminus1); 2610 set_register(instr->RdValue(), extr_val); 2611 } else { 2612 // sbfx - signed bitfield extract. 2613 int32_t rm_val = get_register(instr->RmValue()); 2614 int32_t extr_val = rm_val << (31 - msbit); 2615 extr_val = extr_val >> (31 - widthminus1); 2616 set_register(instr->RdValue(), extr_val); 2617 } 2618 } else { 2619 UNREACHABLE(); 2620 } 2621 return; 2622 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { 2623 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); 2624 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); 2625 if (msbit >= lsbit) { 2626 // bfc or bfi - bitfield clear/insert. 2627 uint32_t rd_val = 2628 static_cast<uint32_t>(get_register(instr->RdValue())); 2629 uint32_t bitcount = msbit - lsbit + 1; 2630 uint32_t mask = (1 << bitcount) - 1; 2631 rd_val &= ~(mask << lsbit); 2632 if (instr->RmValue() != 15) { 2633 // bfi - bitfield insert. 2634 uint32_t rm_val = 2635 static_cast<uint32_t>(get_register(instr->RmValue())); 2636 rm_val &= mask; 2637 rd_val |= rm_val << lsbit; 2638 } 2639 set_register(instr->RdValue(), rd_val); 2640 } else { 2641 UNREACHABLE(); 2642 } 2643 return; 2644 } else { 2645 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 2646 addr = rn_val + shifter_operand; 2647 if (instr->HasW()) { 2648 set_register(rn, addr); 2649 } 2650 } 2651 break; 2652 } 2653 default: { 2654 UNREACHABLE(); 2655 break; 2656 } 2657 } 2658 if (instr->HasB()) { 2659 if (instr->HasL()) { 2660 uint8_t byte = ReadB(addr); 2661 set_register(rd, byte); 2662 } else { 2663 uint8_t byte = get_register(rd); 2664 WriteB(addr, byte); 2665 } 2666 } else { 2667 if (instr->HasL()) { 2668 set_register(rd, ReadW(addr, instr)); 2669 } else { 2670 WriteW(addr, get_register(rd), instr); 2671 } 2672 } 2673 } 2674 2675 2676 void Simulator::DecodeType4(Instruction* instr) { 2677 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode 2678 if (instr->HasL()) { 2679 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 2680 HandleRList(instr, true); 2681 } else { 2682 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 2683 HandleRList(instr, false); 2684 } 2685 } 2686 2687 2688 void Simulator::DecodeType5(Instruction* instr) { 2689 // Format(instr, "b'l'cond 'target"); 2690 int off = (instr->SImmed24Value() << 2); 2691 intptr_t pc_address = get_pc(); 2692 if (instr->HasLink()) { 2693 set_register(lr, pc_address + Instruction::kInstrSize); 2694 } 2695 int pc_reg = get_register(pc); 2696 set_pc(pc_reg + off); 2697 } 2698 2699 2700 void Simulator::DecodeType6(Instruction* instr) { 2701 DecodeType6CoprocessorIns(instr); 2702 } 2703 2704 2705 void Simulator::DecodeType7(Instruction* instr) { 2706 if (instr->Bit(24) == 1) { 2707 SoftwareInterrupt(instr); 2708 } else { 2709 DecodeTypeVFP(instr); 2710 } 2711 } 2712 2713 2714 // void Simulator::DecodeTypeVFP(Instruction* instr) 2715 // The Following ARMv7 VFPv instructions are currently supported. 2716 // vmov :Sn = Rt 2717 // vmov :Rt = Sn 2718 // vcvt: Dd = Sm 2719 // vcvt: Sd = Dm 2720 // Dd = vabs(Dm) 2721 // Dd = vneg(Dm) 2722 // Dd = vadd(Dn, Dm) 2723 // Dd = vsub(Dn, Dm) 2724 // Dd = vmul(Dn, Dm) 2725 // Dd = vdiv(Dn, Dm) 2726 // vcmp(Dd, Dm) 2727 // vmrs 2728 // Dd = vsqrt(Dm) 2729 void Simulator::DecodeTypeVFP(Instruction* instr) { 2730 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); 2731 ASSERT(instr->Bits(11, 9) == 0x5); 2732 2733 // Obtain double precision register codes. 2734 int vm = instr->VFPMRegValue(kDoublePrecision); 2735 int vd = instr->VFPDRegValue(kDoublePrecision); 2736 int vn = instr->VFPNRegValue(kDoublePrecision); 2737 2738 if (instr->Bit(4) == 0) { 2739 if (instr->Opc1Value() == 0x7) { 2740 // Other data processing instructions 2741 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { 2742 // vmov register to register. 2743 if (instr->SzValue() == 0x1) { 2744 int m = instr->VFPMRegValue(kDoublePrecision); 2745 int d = instr->VFPDRegValue(kDoublePrecision); 2746 set_d_register_from_double(d, get_double_from_d_register(m)); 2747 } else { 2748 int m = instr->VFPMRegValue(kSinglePrecision); 2749 int d = instr->VFPDRegValue(kSinglePrecision); 2750 set_s_register_from_float(d, get_float_from_s_register(m)); 2751 } 2752 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { 2753 // vabs 2754 double dm_value = get_double_from_d_register(vm); 2755 double dd_value = fabs(dm_value); 2756 set_d_register_from_double(vd, dd_value); 2757 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { 2758 // vneg 2759 double dm_value = get_double_from_d_register(vm); 2760 double dd_value = -dm_value; 2761 set_d_register_from_double(vd, dd_value); 2762 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { 2763 DecodeVCVTBetweenDoubleAndSingle(instr); 2764 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { 2765 DecodeVCVTBetweenFloatingPointAndInteger(instr); 2766 } else if (((instr->Opc2Value() >> 1) == 0x6) && 2767 (instr->Opc3Value() & 0x1)) { 2768 DecodeVCVTBetweenFloatingPointAndInteger(instr); 2769 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 2770 (instr->Opc3Value() & 0x1)) { 2771 DecodeVCMP(instr); 2772 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { 2773 // vsqrt 2774 double dm_value = get_double_from_d_register(vm); 2775 double dd_value = sqrt(dm_value); 2776 set_d_register_from_double(vd, dd_value); 2777 } else if (instr->Opc3Value() == 0x0) { 2778 // vmov immediate. 2779 if (instr->SzValue() == 0x1) { 2780 set_d_register_from_double(vd, instr->DoubleImmedVmov()); 2781 } else { 2782 UNREACHABLE(); // Not used by v8. 2783 } 2784 } else { 2785 UNREACHABLE(); // Not used by V8. 2786 } 2787 } else if (instr->Opc1Value() == 0x3) { 2788 if (instr->SzValue() != 0x1) { 2789 UNREACHABLE(); // Not used by V8. 2790 } 2791 2792 if (instr->Opc3Value() & 0x1) { 2793 // vsub 2794 double dn_value = get_double_from_d_register(vn); 2795 double dm_value = get_double_from_d_register(vm); 2796 double dd_value = dn_value - dm_value; 2797 set_d_register_from_double(vd, dd_value); 2798 } else { 2799 // vadd 2800 double dn_value = get_double_from_d_register(vn); 2801 double dm_value = get_double_from_d_register(vm); 2802 double dd_value = dn_value + dm_value; 2803 set_d_register_from_double(vd, dd_value); 2804 } 2805 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { 2806 // vmul 2807 if (instr->SzValue() != 0x1) { 2808 UNREACHABLE(); // Not used by V8. 2809 } 2810 2811 double dn_value = get_double_from_d_register(vn); 2812 double dm_value = get_double_from_d_register(vm); 2813 double dd_value = dn_value * dm_value; 2814 set_d_register_from_double(vd, dd_value); 2815 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { 2816 // vdiv 2817 if (instr->SzValue() != 0x1) { 2818 UNREACHABLE(); // Not used by V8. 2819 } 2820 2821 double dn_value = get_double_from_d_register(vn); 2822 double dm_value = get_double_from_d_register(vm); 2823 double dd_value = dn_value / dm_value; 2824 div_zero_vfp_flag_ = (dm_value == 0); 2825 set_d_register_from_double(vd, dd_value); 2826 } else { 2827 UNIMPLEMENTED(); // Not used by V8. 2828 } 2829 } else { 2830 if ((instr->VCValue() == 0x0) && 2831 (instr->VAValue() == 0x0)) { 2832 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); 2833 } else if ((instr->VLValue() == 0x1) && 2834 (instr->VCValue() == 0x0) && 2835 (instr->VAValue() == 0x7) && 2836 (instr->Bits(19, 16) == 0x1)) { 2837 // vmrs 2838 uint32_t rt = instr->RtValue(); 2839 if (rt == 0xF) { 2840 Copy_FPSCR_to_APSR(); 2841 } else { 2842 // Emulate FPSCR from the Simulator flags. 2843 uint32_t fpscr = (n_flag_FPSCR_ << 31) | 2844 (z_flag_FPSCR_ << 30) | 2845 (c_flag_FPSCR_ << 29) | 2846 (v_flag_FPSCR_ << 28) | 2847 (inexact_vfp_flag_ << 4) | 2848 (underflow_vfp_flag_ << 3) | 2849 (overflow_vfp_flag_ << 2) | 2850 (div_zero_vfp_flag_ << 1) | 2851 (inv_op_vfp_flag_ << 0) | 2852 (FPSCR_rounding_mode_); 2853 set_register(rt, fpscr); 2854 } 2855 } else if ((instr->VLValue() == 0x0) && 2856 (instr->VCValue() == 0x0) && 2857 (instr->VAValue() == 0x7) && 2858 (instr->Bits(19, 16) == 0x1)) { 2859 // vmsr 2860 uint32_t rt = instr->RtValue(); 2861 if (rt == pc) { 2862 UNREACHABLE(); 2863 } else { 2864 uint32_t rt_value = get_register(rt); 2865 n_flag_FPSCR_ = (rt_value >> 31) & 1; 2866 z_flag_FPSCR_ = (rt_value >> 30) & 1; 2867 c_flag_FPSCR_ = (rt_value >> 29) & 1; 2868 v_flag_FPSCR_ = (rt_value >> 28) & 1; 2869 inexact_vfp_flag_ = (rt_value >> 4) & 1; 2870 underflow_vfp_flag_ = (rt_value >> 3) & 1; 2871 overflow_vfp_flag_ = (rt_value >> 2) & 1; 2872 div_zero_vfp_flag_ = (rt_value >> 1) & 1; 2873 inv_op_vfp_flag_ = (rt_value >> 0) & 1; 2874 FPSCR_rounding_mode_ = 2875 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask); 2876 } 2877 } else { 2878 UNIMPLEMENTED(); // Not used by V8. 2879 } 2880 } 2881 } 2882 2883 2884 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( 2885 Instruction* instr) { 2886 ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && 2887 (instr->VAValue() == 0x0)); 2888 2889 int t = instr->RtValue(); 2890 int n = instr->VFPNRegValue(kSinglePrecision); 2891 bool to_arm_register = (instr->VLValue() == 0x1); 2892 2893 if (to_arm_register) { 2894 int32_t int_value = get_sinteger_from_s_register(n); 2895 set_register(t, int_value); 2896 } else { 2897 int32_t rs_val = get_register(t); 2898 set_s_register_from_sinteger(n, rs_val); 2899 } 2900 } 2901 2902 2903 void Simulator::DecodeVCMP(Instruction* instr) { 2904 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 2905 ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && 2906 (instr->Opc3Value() & 0x1)); 2907 // Comparison. 2908 2909 VFPRegPrecision precision = kSinglePrecision; 2910 if (instr->SzValue() == 1) { 2911 precision = kDoublePrecision; 2912 } 2913 2914 int d = instr->VFPDRegValue(precision); 2915 int m = 0; 2916 if (instr->Opc2Value() == 0x4) { 2917 m = instr->VFPMRegValue(precision); 2918 } 2919 2920 if (precision == kDoublePrecision) { 2921 double dd_value = get_double_from_d_register(d); 2922 double dm_value = 0.0; 2923 if (instr->Opc2Value() == 0x4) { 2924 dm_value = get_double_from_d_register(m); 2925 } 2926 2927 // Raise exceptions for quiet NaNs if necessary. 2928 if (instr->Bit(7) == 1) { 2929 if (isnan(dd_value)) { 2930 inv_op_vfp_flag_ = true; 2931 } 2932 } 2933 2934 Compute_FPSCR_Flags(dd_value, dm_value); 2935 } else { 2936 UNIMPLEMENTED(); // Not used by V8. 2937 } 2938 } 2939 2940 2941 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { 2942 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); 2943 ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); 2944 2945 VFPRegPrecision dst_precision = kDoublePrecision; 2946 VFPRegPrecision src_precision = kSinglePrecision; 2947 if (instr->SzValue() == 1) { 2948 dst_precision = kSinglePrecision; 2949 src_precision = kDoublePrecision; 2950 } 2951 2952 int dst = instr->VFPDRegValue(dst_precision); 2953 int src = instr->VFPMRegValue(src_precision); 2954 2955 if (dst_precision == kSinglePrecision) { 2956 double val = get_double_from_d_register(src); 2957 set_s_register_from_float(dst, static_cast<float>(val)); 2958 } else { 2959 float val = get_float_from_s_register(src); 2960 set_d_register_from_double(dst, static_cast<double>(val)); 2961 } 2962 } 2963 2964 bool get_inv_op_vfp_flag(VFPRoundingMode mode, 2965 double val, 2966 bool unsigned_) { 2967 ASSERT((mode == RN) || (mode == RM) || (mode == RZ)); 2968 double max_uint = static_cast<double>(0xffffffffu); 2969 double max_int = static_cast<double>(kMaxInt); 2970 double min_int = static_cast<double>(kMinInt); 2971 2972 // Check for NaN. 2973 if (val != val) { 2974 return true; 2975 } 2976 2977 // Check for overflow. This code works because 32bit integers can be 2978 // exactly represented by ieee-754 64bit floating-point values. 2979 switch (mode) { 2980 case RN: 2981 return unsigned_ ? (val >= (max_uint + 0.5)) || 2982 (val < -0.5) 2983 : (val >= (max_int + 0.5)) || 2984 (val < (min_int - 0.5)); 2985 2986 case RM: 2987 return unsigned_ ? (val >= (max_uint + 1.0)) || 2988 (val < 0) 2989 : (val >= (max_int + 1.0)) || 2990 (val < min_int); 2991 2992 case RZ: 2993 return unsigned_ ? (val >= (max_uint + 1.0)) || 2994 (val <= -1) 2995 : (val >= (max_int + 1.0)) || 2996 (val <= (min_int - 1.0)); 2997 default: 2998 UNREACHABLE(); 2999 return true; 3000 } 3001 } 3002 3003 3004 // We call this function only if we had a vfp invalid exception. 3005 // It returns the correct saturated value. 3006 int VFPConversionSaturate(double val, bool unsigned_res) { 3007 if (val != val) { 3008 return 0; 3009 } else { 3010 if (unsigned_res) { 3011 return (val < 0) ? 0 : 0xffffffffu; 3012 } else { 3013 return (val < 0) ? kMinInt : kMaxInt; 3014 } 3015 } 3016 } 3017 3018 3019 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { 3020 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) && 3021 (instr->Bits(27, 23) == 0x1D)); 3022 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || 3023 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); 3024 3025 // Conversion between floating-point and integer. 3026 bool to_integer = (instr->Bit(18) == 1); 3027 3028 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision 3029 : kSinglePrecision; 3030 3031 if (to_integer) { 3032 // We are playing with code close to the C++ standard's limits below, 3033 // hence the very simple code and heavy checks. 3034 // 3035 // Note: 3036 // C++ defines default type casting from floating point to integer as 3037 // (close to) rounding toward zero ("fractional part discarded"). 3038 3039 int dst = instr->VFPDRegValue(kSinglePrecision); 3040 int src = instr->VFPMRegValue(src_precision); 3041 3042 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding 3043 // mode or the default Round to Zero mode. 3044 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_ 3045 : RZ; 3046 ASSERT((mode == RM) || (mode == RZ) || (mode == RN)); 3047 3048 bool unsigned_integer = (instr->Bit(16) == 0); 3049 bool double_precision = (src_precision == kDoublePrecision); 3050 3051 double val = double_precision ? get_double_from_d_register(src) 3052 : get_float_from_s_register(src); 3053 3054 int temp = unsigned_integer ? static_cast<uint32_t>(val) 3055 : static_cast<int32_t>(val); 3056 3057 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer); 3058 3059 double abs_diff = 3060 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) 3061 : fabs(val - temp); 3062 3063 inexact_vfp_flag_ = (abs_diff != 0); 3064 3065 if (inv_op_vfp_flag_) { 3066 temp = VFPConversionSaturate(val, unsigned_integer); 3067 } else { 3068 switch (mode) { 3069 case RN: { 3070 int val_sign = (val > 0) ? 1 : -1; 3071 if (abs_diff > 0.5) { 3072 temp += val_sign; 3073 } else if (abs_diff == 0.5) { 3074 // Round to even if exactly halfway. 3075 temp = ((temp % 2) == 0) ? temp : temp + val_sign; 3076 } 3077 break; 3078 } 3079 3080 case RM: 3081 temp = temp > val ? temp - 1 : temp; 3082 break; 3083 3084 case RZ: 3085 // Nothing to do. 3086 break; 3087 3088 default: 3089 UNREACHABLE(); 3090 } 3091 } 3092 3093 // Update the destination register. 3094 set_s_register_from_sinteger(dst, temp); 3095 3096 } else { 3097 bool unsigned_integer = (instr->Bit(7) == 0); 3098 3099 int dst = instr->VFPDRegValue(src_precision); 3100 int src = instr->VFPMRegValue(kSinglePrecision); 3101 3102 int val = get_sinteger_from_s_register(src); 3103 3104 if (src_precision == kDoublePrecision) { 3105 if (unsigned_integer) { 3106 set_d_register_from_double(dst, 3107 static_cast<double>((uint32_t)val)); 3108 } else { 3109 set_d_register_from_double(dst, static_cast<double>(val)); 3110 } 3111 } else { 3112 if (unsigned_integer) { 3113 set_s_register_from_float(dst, 3114 static_cast<float>((uint32_t)val)); 3115 } else { 3116 set_s_register_from_float(dst, static_cast<float>(val)); 3117 } 3118 } 3119 } 3120 } 3121 3122 3123 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr) 3124 // Decode Type 6 coprocessor instructions. 3125 // Dm = vmov(Rt, Rt2) 3126 // <Rt, Rt2> = vmov(Dm) 3127 // Ddst = MEM(Rbase + 4*offset). 3128 // MEM(Rbase + 4*offset) = Dsrc. 3129 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { 3130 ASSERT((instr->TypeValue() == 6)); 3131 3132 if (instr->CoprocessorValue() == 0xA) { 3133 switch (instr->OpcodeValue()) { 3134 case 0x8: 3135 case 0xA: 3136 case 0xC: 3137 case 0xE: { // Load and store single precision float to memory. 3138 int rn = instr->RnValue(); 3139 int vd = instr->VFPDRegValue(kSinglePrecision); 3140 int offset = instr->Immed8Value(); 3141 if (!instr->HasU()) { 3142 offset = -offset; 3143 } 3144 3145 int32_t address = get_register(rn) + 4 * offset; 3146 if (instr->HasL()) { 3147 // Load double from memory: vldr. 3148 set_s_register_from_sinteger(vd, ReadW(address, instr)); 3149 } else { 3150 // Store double to memory: vstr. 3151 WriteW(address, get_sinteger_from_s_register(vd), instr); 3152 } 3153 break; 3154 } 3155 case 0x4: 3156 case 0x5: 3157 case 0x6: 3158 case 0x7: 3159 case 0x9: 3160 case 0xB: 3161 // Load/store multiple single from memory: vldm/vstm. 3162 HandleVList(instr); 3163 break; 3164 default: 3165 UNIMPLEMENTED(); // Not used by V8. 3166 } 3167 } else if (instr->CoprocessorValue() == 0xB) { 3168 switch (instr->OpcodeValue()) { 3169 case 0x2: 3170 // Load and store double to two GP registers 3171 if (instr->Bits(7, 4) != 0x1) { 3172 UNIMPLEMENTED(); // Not used by V8. 3173 } else { 3174 int rt = instr->RtValue(); 3175 int rn = instr->RnValue(); 3176 int vm = instr->VmValue(); 3177 if (instr->HasL()) { 3178 int32_t rt_int_value = get_sinteger_from_s_register(2*vm); 3179 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1); 3180 3181 set_register(rt, rt_int_value); 3182 set_register(rn, rn_int_value); 3183 } else { 3184 int32_t rs_val = get_register(rt); 3185 int32_t rn_val = get_register(rn); 3186 3187 set_s_register_from_sinteger(2*vm, rs_val); 3188 set_s_register_from_sinteger((2*vm+1), rn_val); 3189 } 3190 } 3191 break; 3192 case 0x8: 3193 case 0xC: { // Load and store double to memory. 3194 int rn = instr->RnValue(); 3195 int vd = instr->VdValue(); 3196 int offset = instr->Immed8Value(); 3197 if (!instr->HasU()) { 3198 offset = -offset; 3199 } 3200 int32_t address = get_register(rn) + 4 * offset; 3201 if (instr->HasL()) { 3202 // Load double from memory: vldr. 3203 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); 3204 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); 3205 } else { 3206 // Store double to memory: vstr. 3207 WriteW(address, get_sinteger_from_s_register(2*vd), instr); 3208 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); 3209 } 3210 break; 3211 } 3212 case 0x4: 3213 case 0x5: 3214 case 0x9: 3215 // Load/store multiple double from memory: vldm/vstm. 3216 HandleVList(instr); 3217 break; 3218 default: 3219 UNIMPLEMENTED(); // Not used by V8. 3220 } 3221 } else { 3222 UNIMPLEMENTED(); // Not used by V8. 3223 } 3224 } 3225 3226 3227 // Executes the current instruction. 3228 void Simulator::InstructionDecode(Instruction* instr) { 3229 if (v8::internal::FLAG_check_icache) { 3230 CheckICache(isolate_->simulator_i_cache(), instr); 3231 } 3232 pc_modified_ = false; 3233 if (::v8::internal::FLAG_trace_sim) { 3234 disasm::NameConverter converter; 3235 disasm::Disassembler dasm(converter); 3236 // use a reasonably large buffer 3237 v8::internal::EmbeddedVector<char, 256> buffer; 3238 dasm.InstructionDecode(buffer, 3239 reinterpret_cast<byte*>(instr)); 3240 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); 3241 } 3242 if (instr->ConditionField() == kSpecialCondition) { 3243 UNIMPLEMENTED(); 3244 } else if (ConditionallyExecute(instr)) { 3245 switch (instr->TypeValue()) { 3246 case 0: 3247 case 1: { 3248 DecodeType01(instr); 3249 break; 3250 } 3251 case 2: { 3252 DecodeType2(instr); 3253 break; 3254 } 3255 case 3: { 3256 DecodeType3(instr); 3257 break; 3258 } 3259 case 4: { 3260 DecodeType4(instr); 3261 break; 3262 } 3263 case 5: { 3264 DecodeType5(instr); 3265 break; 3266 } 3267 case 6: { 3268 DecodeType6(instr); 3269 break; 3270 } 3271 case 7: { 3272 DecodeType7(instr); 3273 break; 3274 } 3275 default: { 3276 UNIMPLEMENTED(); 3277 break; 3278 } 3279 } 3280 // If the instruction is a non taken conditional stop, we need to skip the 3281 // inlined message address. 3282 } else if (instr->IsStop()) { 3283 set_pc(get_pc() + 2 * Instruction::kInstrSize); 3284 } 3285 if (!pc_modified_) { 3286 set_register(pc, reinterpret_cast<int32_t>(instr) 3287 + Instruction::kInstrSize); 3288 } 3289 } 3290 3291 3292 void Simulator::Execute() { 3293 // Get the PC to simulate. Cannot use the accessor here as we need the 3294 // raw PC value and not the one used as input to arithmetic instructions. 3295 int program_counter = get_pc(); 3296 3297 if (::v8::internal::FLAG_stop_sim_at == 0) { 3298 // Fast version of the dispatch loop without checking whether the simulator 3299 // should be stopping at a particular executed instruction. 3300 while (program_counter != end_sim_pc) { 3301 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3302 icount_++; 3303 InstructionDecode(instr); 3304 program_counter = get_pc(); 3305 } 3306 } else { 3307 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 3308 // we reach the particular instuction count. 3309 while (program_counter != end_sim_pc) { 3310 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3311 icount_++; 3312 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 3313 ArmDebugger dbg(this); 3314 dbg.Debug(); 3315 } else { 3316 InstructionDecode(instr); 3317 } 3318 program_counter = get_pc(); 3319 } 3320 } 3321 } 3322 3323 3324 int32_t Simulator::Call(byte* entry, int argument_count, ...) { 3325 va_list parameters; 3326 va_start(parameters, argument_count); 3327 // Set up arguments 3328 3329 // First four arguments passed in registers. 3330 ASSERT(argument_count >= 4); 3331 set_register(r0, va_arg(parameters, int32_t)); 3332 set_register(r1, va_arg(parameters, int32_t)); 3333 set_register(r2, va_arg(parameters, int32_t)); 3334 set_register(r3, va_arg(parameters, int32_t)); 3335 3336 // Remaining arguments passed on stack. 3337 int original_stack = get_register(sp); 3338 // Compute position of stack on entry to generated code. 3339 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)); 3340 if (OS::ActivationFrameAlignment() != 0) { 3341 entry_stack &= -OS::ActivationFrameAlignment(); 3342 } 3343 // Store remaining arguments on stack, from low to high memory. 3344 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 3345 for (int i = 4; i < argument_count; i++) { 3346 stack_argument[i - 4] = va_arg(parameters, int32_t); 3347 } 3348 va_end(parameters); 3349 set_register(sp, entry_stack); 3350 3351 // Prepare to execute the code at entry 3352 set_register(pc, reinterpret_cast<int32_t>(entry)); 3353 // Put down marker for end of simulation. The simulator will stop simulation 3354 // when the PC reaches this value. By saving the "end simulation" value into 3355 // the LR the simulation stops when returning to this call point. 3356 set_register(lr, end_sim_pc); 3357 3358 // Remember the values of callee-saved registers. 3359 // The code below assumes that r9 is not used as sb (static base) in 3360 // simulator code and therefore is regarded as a callee-saved register. 3361 int32_t r4_val = get_register(r4); 3362 int32_t r5_val = get_register(r5); 3363 int32_t r6_val = get_register(r6); 3364 int32_t r7_val = get_register(r7); 3365 int32_t r8_val = get_register(r8); 3366 int32_t r9_val = get_register(r9); 3367 int32_t r10_val = get_register(r10); 3368 int32_t r11_val = get_register(r11); 3369 3370 // Set up the callee-saved registers with a known value. To be able to check 3371 // that they are preserved properly across JS execution. 3372 int32_t callee_saved_value = icount_; 3373 set_register(r4, callee_saved_value); 3374 set_register(r5, callee_saved_value); 3375 set_register(r6, callee_saved_value); 3376 set_register(r7, callee_saved_value); 3377 set_register(r8, callee_saved_value); 3378 set_register(r9, callee_saved_value); 3379 set_register(r10, callee_saved_value); 3380 set_register(r11, callee_saved_value); 3381 3382 // Start the simulation 3383 Execute(); 3384 3385 // Check that the callee-saved registers have been preserved. 3386 CHECK_EQ(callee_saved_value, get_register(r4)); 3387 CHECK_EQ(callee_saved_value, get_register(r5)); 3388 CHECK_EQ(callee_saved_value, get_register(r6)); 3389 CHECK_EQ(callee_saved_value, get_register(r7)); 3390 CHECK_EQ(callee_saved_value, get_register(r8)); 3391 CHECK_EQ(callee_saved_value, get_register(r9)); 3392 CHECK_EQ(callee_saved_value, get_register(r10)); 3393 CHECK_EQ(callee_saved_value, get_register(r11)); 3394 3395 // Restore callee-saved registers with the original value. 3396 set_register(r4, r4_val); 3397 set_register(r5, r5_val); 3398 set_register(r6, r6_val); 3399 set_register(r7, r7_val); 3400 set_register(r8, r8_val); 3401 set_register(r9, r9_val); 3402 set_register(r10, r10_val); 3403 set_register(r11, r11_val); 3404 3405 // Pop stack passed arguments. 3406 CHECK_EQ(entry_stack, get_register(sp)); 3407 set_register(sp, original_stack); 3408 3409 int32_t result = get_register(r0); 3410 return result; 3411 } 3412 3413 3414 uintptr_t Simulator::PushAddress(uintptr_t address) { 3415 int new_sp = get_register(sp) - sizeof(uintptr_t); 3416 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 3417 *stack_slot = address; 3418 set_register(sp, new_sp); 3419 return new_sp; 3420 } 3421 3422 3423 uintptr_t Simulator::PopAddress() { 3424 int current_sp = get_register(sp); 3425 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 3426 uintptr_t address = *stack_slot; 3427 set_register(sp, current_sp + sizeof(uintptr_t)); 3428 return address; 3429 } 3430 3431 } } // namespace v8::internal 3432 3433 #endif // USE_SIMULATOR 3434 3435 #endif // V8_TARGET_ARCH_ARM 3436