1 // Copyright 2010 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 <cstdarg> 30 #include "v8.h" 31 32 #include "disasm.h" 33 #include "assembler.h" 34 #include "arm/constants-arm.h" 35 #include "arm/simulator-arm.h" 36 37 #if !defined(__arm__) 38 39 // Only build the simulator if not compiling for real ARM hardware. 40 namespace assembler { 41 namespace arm { 42 43 using ::v8::internal::Object; 44 using ::v8::internal::PrintF; 45 using ::v8::internal::OS; 46 using ::v8::internal::ReadLine; 47 using ::v8::internal::DeleteArray; 48 49 // This macro provides a platform independent use of sscanf. The reason for 50 // SScanF not being implemented in a platform independent way through 51 // ::v8::internal::OS in the same way as SNPrintF is that the 52 // Windows C Run-Time Library does not provide vsscanf. 53 #define SScanF sscanf // NOLINT 54 55 // The Debugger class is used by the simulator while debugging simulated ARM 56 // code. 57 class Debugger { 58 public: 59 explicit Debugger(Simulator* sim); 60 ~Debugger(); 61 62 void Stop(Instr* instr); 63 void Debug(); 64 65 private: 66 static const instr_t kBreakpointInstr = 67 ((AL << 28) | (7 << 25) | (1 << 24) | break_point); 68 static const instr_t kNopInstr = 69 ((AL << 28) | (13 << 21)); 70 71 Simulator* sim_; 72 73 int32_t GetRegisterValue(int regnum); 74 bool GetValue(const char* desc, int32_t* value); 75 76 // Set or delete a breakpoint. Returns true if successful. 77 bool SetBreakpoint(Instr* breakpc); 78 bool DeleteBreakpoint(Instr* 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 Debugger::Debugger(Simulator* sim) { 88 sim_ = sim; 89 } 90 91 92 Debugger::~Debugger() { 93 } 94 95 96 97 #ifdef GENERATED_CODE_COVERAGE 98 static FILE* coverage_log = NULL; 99 100 101 static void InitializeCoverage() { 102 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 103 if (file_name != NULL) { 104 coverage_log = fopen(file_name, "aw+"); 105 } 106 } 107 108 109 void Debugger::Stop(Instr* instr) { 110 char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff); 111 if (strlen(str) > 0) { 112 if (coverage_log != NULL) { 113 fprintf(coverage_log, "%s\n", str); 114 fflush(coverage_log); 115 } 116 instr->SetInstructionBits(0xe1a00000); // Overwrite with nop. 117 } 118 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); 119 } 120 121 #else // ndef GENERATED_CODE_COVERAGE 122 123 static void InitializeCoverage() { 124 } 125 126 127 void Debugger::Stop(Instr* instr) { 128 const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff); 129 PrintF("Simulator hit %s\n", str); 130 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); 131 Debug(); 132 } 133 #endif 134 135 136 int32_t Debugger::GetRegisterValue(int regnum) { 137 if (regnum == kPCRegister) { 138 return sim_->get_pc(); 139 } else { 140 return sim_->get_register(regnum); 141 } 142 } 143 144 145 bool Debugger::GetValue(const char* desc, int32_t* value) { 146 int regnum = Registers::Number(desc); 147 if (regnum != kNoRegister) { 148 *value = GetRegisterValue(regnum); 149 return true; 150 } else { 151 return SScanF(desc, "%i", value) == 1; 152 } 153 return false; 154 } 155 156 157 bool Debugger::SetBreakpoint(Instr* breakpc) { 158 // Check if a breakpoint can be set. If not return without any side-effects. 159 if (sim_->break_pc_ != NULL) { 160 return false; 161 } 162 163 // Set the breakpoint. 164 sim_->break_pc_ = breakpc; 165 sim_->break_instr_ = breakpc->InstructionBits(); 166 // Not setting the breakpoint instruction in the code itself. It will be set 167 // when the debugger shell continues. 168 return true; 169 } 170 171 172 bool Debugger::DeleteBreakpoint(Instr* breakpc) { 173 if (sim_->break_pc_ != NULL) { 174 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 175 } 176 177 sim_->break_pc_ = NULL; 178 sim_->break_instr_ = 0; 179 return true; 180 } 181 182 183 void Debugger::UndoBreakpoints() { 184 if (sim_->break_pc_ != NULL) { 185 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 186 } 187 } 188 189 190 void Debugger::RedoBreakpoints() { 191 if (sim_->break_pc_ != NULL) { 192 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 193 } 194 } 195 196 197 void Debugger::Debug() { 198 intptr_t last_pc = -1; 199 bool done = false; 200 201 #define COMMAND_SIZE 63 202 #define ARG_SIZE 255 203 204 #define STR(a) #a 205 #define XSTR(a) STR(a) 206 207 char cmd[COMMAND_SIZE + 1]; 208 char arg1[ARG_SIZE + 1]; 209 char arg2[ARG_SIZE + 1]; 210 211 // make sure to have a proper terminating character if reaching the limit 212 cmd[COMMAND_SIZE] = 0; 213 arg1[ARG_SIZE] = 0; 214 arg2[ARG_SIZE] = 0; 215 216 // Undo all set breakpoints while running in the debugger shell. This will 217 // make them invisible to all commands. 218 UndoBreakpoints(); 219 220 while (!done) { 221 if (last_pc != sim_->get_pc()) { 222 disasm::NameConverter converter; 223 disasm::Disassembler dasm(converter); 224 // use a reasonably large buffer 225 v8::internal::EmbeddedVector<char, 256> buffer; 226 dasm.InstructionDecode(buffer, 227 reinterpret_cast<byte*>(sim_->get_pc())); 228 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start()); 229 last_pc = sim_->get_pc(); 230 } 231 char* line = ReadLine("sim> "); 232 if (line == NULL) { 233 break; 234 } else { 235 // Use sscanf to parse the individual parts of the command line. At the 236 // moment no command expects more than two parameters. 237 int args = SScanF(line, 238 "%" XSTR(COMMAND_SIZE) "s " 239 "%" XSTR(ARG_SIZE) "s " 240 "%" XSTR(ARG_SIZE) "s", 241 cmd, arg1, arg2); 242 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 243 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); 244 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 245 // Execute the one instruction we broke at with breakpoints disabled. 246 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); 247 // Leave the debugger shell. 248 done = true; 249 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 250 if (args == 2) { 251 int32_t value; 252 if (strcmp(arg1, "all") == 0) { 253 for (int i = 0; i < kNumRegisters; i++) { 254 value = GetRegisterValue(i); 255 PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value); 256 } 257 } else { 258 if (GetValue(arg1, &value)) { 259 PrintF("%s: 0x%08x %d \n", arg1, value, value); 260 } else { 261 PrintF("%s unrecognized\n", arg1); 262 } 263 } 264 } else { 265 PrintF("print <register>\n"); 266 } 267 } else if ((strcmp(cmd, "po") == 0) 268 || (strcmp(cmd, "printobject") == 0)) { 269 if (args == 2) { 270 int32_t value; 271 if (GetValue(arg1, &value)) { 272 Object* obj = reinterpret_cast<Object*>(value); 273 PrintF("%s: \n", arg1); 274 #ifdef DEBUG 275 obj->PrintLn(); 276 #else 277 obj->ShortPrint(); 278 PrintF("\n"); 279 #endif 280 } else { 281 PrintF("%s unrecognized\n", arg1); 282 } 283 } else { 284 PrintF("printobject <value>\n"); 285 } 286 } else if (strcmp(cmd, "disasm") == 0) { 287 disasm::NameConverter converter; 288 disasm::Disassembler dasm(converter); 289 // use a reasonably large buffer 290 v8::internal::EmbeddedVector<char, 256> buffer; 291 292 byte* cur = NULL; 293 byte* end = NULL; 294 295 if (args == 1) { 296 cur = reinterpret_cast<byte*>(sim_->get_pc()); 297 end = cur + (10 * Instr::kInstrSize); 298 } else if (args == 2) { 299 int32_t value; 300 if (GetValue(arg1, &value)) { 301 cur = reinterpret_cast<byte*>(value); 302 // no length parameter passed, assume 10 instructions 303 end = cur + (10 * Instr::kInstrSize); 304 } 305 } else { 306 int32_t value1; 307 int32_t value2; 308 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 309 cur = reinterpret_cast<byte*>(value1); 310 end = cur + (value2 * Instr::kInstrSize); 311 } 312 } 313 314 while (cur < end) { 315 dasm.InstructionDecode(buffer, cur); 316 PrintF(" 0x%08x %s\n", cur, buffer.start()); 317 cur += Instr::kInstrSize; 318 } 319 } else if (strcmp(cmd, "gdb") == 0) { 320 PrintF("relinquishing control to gdb\n"); 321 v8::internal::OS::DebugBreak(); 322 PrintF("regaining control from gdb\n"); 323 } else if (strcmp(cmd, "break") == 0) { 324 if (args == 2) { 325 int32_t value; 326 if (GetValue(arg1, &value)) { 327 if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) { 328 PrintF("setting breakpoint failed\n"); 329 } 330 } else { 331 PrintF("%s unrecognized\n", arg1); 332 } 333 } else { 334 PrintF("break <address>\n"); 335 } 336 } else if (strcmp(cmd, "del") == 0) { 337 if (!DeleteBreakpoint(NULL)) { 338 PrintF("deleting breakpoint failed\n"); 339 } 340 } else if (strcmp(cmd, "flags") == 0) { 341 PrintF("N flag: %d; ", sim_->n_flag_); 342 PrintF("Z flag: %d; ", sim_->z_flag_); 343 PrintF("C flag: %d; ", sim_->c_flag_); 344 PrintF("V flag: %d\n", sim_->v_flag_); 345 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_); 346 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_); 347 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_); 348 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_); 349 PrintF("INEXACT flag: %d; ", sim_->inexact_vfp_flag_); 350 } else if (strcmp(cmd, "unstop") == 0) { 351 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; 352 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); 353 if (stop_instr->ConditionField() == special_condition) { 354 stop_instr->SetInstructionBits(kNopInstr); 355 } else { 356 PrintF("Not at debugger stop."); 357 } 358 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) { 359 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim; 360 PrintF("Trace of executed instructions is %s\n", 361 ::v8::internal::FLAG_trace_sim ? "on" : "off"); 362 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 363 PrintF("cont\n"); 364 PrintF(" continue execution (alias 'c')\n"); 365 PrintF("stepi\n"); 366 PrintF(" step one instruction (alias 'si')\n"); 367 PrintF("print <register>\n"); 368 PrintF(" print register content (alias 'p')\n"); 369 PrintF(" use register name 'all' to print all registers\n"); 370 PrintF("printobject <register>\n"); 371 PrintF(" print an object from a register (alias 'po')\n"); 372 PrintF("flags\n"); 373 PrintF(" print flags\n"); 374 PrintF("disasm [<instructions>]\n"); 375 PrintF("disasm [[<address>] <instructions>]\n"); 376 PrintF(" disassemble code, default is 10 instructions from pc\n"); 377 PrintF("gdb\n"); 378 PrintF(" enter gdb\n"); 379 PrintF("break <address>\n"); 380 PrintF(" set a break point on the address\n"); 381 PrintF("del\n"); 382 PrintF(" delete the breakpoint\n"); 383 PrintF("unstop\n"); 384 PrintF(" ignore the stop instruction at the current location"); 385 PrintF(" from now on\n"); 386 PrintF("trace (alias 't')\n"); 387 PrintF(" toogle the tracing of all executed statements"); 388 } else { 389 PrintF("Unknown command: %s\n", cmd); 390 } 391 } 392 DeleteArray(line); 393 } 394 395 // Add all the breakpoints back to stop execution and enter the debugger 396 // shell when hit. 397 RedoBreakpoints(); 398 399 #undef COMMAND_SIZE 400 #undef ARG_SIZE 401 402 #undef STR 403 #undef XSTR 404 } 405 406 407 // Create one simulator per thread and keep it in thread local storage. 408 static v8::internal::Thread::LocalStorageKey simulator_key; 409 410 411 bool Simulator::initialized_ = false; 412 413 414 void Simulator::Initialize() { 415 if (initialized_) return; 416 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); 417 initialized_ = true; 418 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); 419 } 420 421 422 Simulator::Simulator() { 423 Initialize(); 424 // Setup simulator support first. Some of this information is needed to 425 // setup the architecture state. 426 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack 427 stack_ = reinterpret_cast<char*>(malloc(stack_size)); 428 pc_modified_ = false; 429 icount_ = 0; 430 break_pc_ = NULL; 431 break_instr_ = 0; 432 433 // Setup architecture state. 434 // All registers are initialized to zero to start with. 435 for (int i = 0; i < num_registers; i++) { 436 registers_[i] = 0; 437 } 438 n_flag_ = false; 439 z_flag_ = false; 440 c_flag_ = false; 441 v_flag_ = false; 442 443 // Initializing VFP registers. 444 // All registers are initialized to zero to start with 445 // even though s_registers_ & d_registers_ share the same 446 // physical registers in the target. 447 for (int i = 0; i < num_s_registers; i++) { 448 vfp_register[i] = 0; 449 } 450 n_flag_FPSCR_ = false; 451 z_flag_FPSCR_ = false; 452 c_flag_FPSCR_ = false; 453 v_flag_FPSCR_ = false; 454 455 inv_op_vfp_flag_ = false; 456 div_zero_vfp_flag_ = false; 457 overflow_vfp_flag_ = false; 458 underflow_vfp_flag_ = false; 459 inexact_vfp_flag_ = false; 460 461 // The sp is initialized to point to the bottom (high address) of the 462 // allocated stack area. To be safe in potential stack underflows we leave 463 // some buffer below. 464 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 465 // The lr and pc are initialized to a known bad value that will cause an 466 // access violation if the simulator ever tries to execute it. 467 registers_[pc] = bad_lr; 468 registers_[lr] = bad_lr; 469 InitializeCoverage(); 470 } 471 472 473 // When the generated code calls an external reference we need to catch that in 474 // the simulator. The external reference will be a function compiled for the 475 // host architecture. We need to call that function instead of trying to 476 // execute it with the simulator. We do that by redirecting the external 477 // reference to a swi (software-interrupt) instruction that is handled by 478 // the simulator. We write the original destination of the jump just at a known 479 // offset from the swi instruction so the simulator knows what to call. 480 class Redirection { 481 public: 482 Redirection(void* external_function, bool fp_return) 483 : external_function_(external_function), 484 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), 485 fp_return_(fp_return), 486 next_(list_) { 487 list_ = this; 488 } 489 490 void* address_of_swi_instruction() { 491 return reinterpret_cast<void*>(&swi_instruction_); 492 } 493 494 void* external_function() { return external_function_; } 495 bool fp_return() { return fp_return_; } 496 497 static Redirection* Get(void* external_function, bool fp_return) { 498 Redirection* current; 499 for (current = list_; current != NULL; current = current->next_) { 500 if (current->external_function_ == external_function) return current; 501 } 502 return new Redirection(external_function, fp_return); 503 } 504 505 static Redirection* FromSwiInstruction(Instr* swi_instruction) { 506 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 507 char* addr_of_redirection = 508 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 509 return reinterpret_cast<Redirection*>(addr_of_redirection); 510 } 511 512 private: 513 void* external_function_; 514 uint32_t swi_instruction_; 515 bool fp_return_; 516 Redirection* next_; 517 static Redirection* list_; 518 }; 519 520 521 Redirection* Redirection::list_ = NULL; 522 523 524 void* Simulator::RedirectExternalReference(void* external_function, 525 bool fp_return) { 526 Redirection* redirection = Redirection::Get(external_function, fp_return); 527 return redirection->address_of_swi_instruction(); 528 } 529 530 531 // Get the active Simulator for the current thread. 532 Simulator* Simulator::current() { 533 Initialize(); 534 Simulator* sim = reinterpret_cast<Simulator*>( 535 v8::internal::Thread::GetThreadLocal(simulator_key)); 536 if (sim == NULL) { 537 // TODO(146): delete the simulator object when a thread goes away. 538 sim = new Simulator(); 539 v8::internal::Thread::SetThreadLocal(simulator_key, sim); 540 } 541 return sim; 542 } 543 544 545 // Sets the register in the architecture state. It will also deal with updating 546 // Simulator internal state for special registers such as PC. 547 void Simulator::set_register(int reg, int32_t value) { 548 ASSERT((reg >= 0) && (reg < num_registers)); 549 if (reg == pc) { 550 pc_modified_ = true; 551 } 552 registers_[reg] = value; 553 } 554 555 556 // Get the register from the architecture state. This function does handle 557 // the special case of accessing the PC register. 558 int32_t Simulator::get_register(int reg) const { 559 ASSERT((reg >= 0) && (reg < num_registers)); 560 return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0); 561 } 562 563 564 // Raw access to the PC register. 565 void Simulator::set_pc(int32_t value) { 566 pc_modified_ = true; 567 registers_[pc] = value; 568 } 569 570 571 // Raw access to the PC register without the special adjustment when reading. 572 int32_t Simulator::get_pc() const { 573 return registers_[pc]; 574 } 575 576 577 // Getting from and setting into VFP registers. 578 void Simulator::set_s_register(int sreg, unsigned int value) { 579 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 580 vfp_register[sreg] = value; 581 } 582 583 584 unsigned int Simulator::get_s_register(int sreg) const { 585 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 586 return vfp_register[sreg]; 587 } 588 589 590 void Simulator::set_s_register_from_float(int sreg, const float flt) { 591 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 592 // Read the bits from the single precision floating point value 593 // into the unsigned integer element of vfp_register[] given by index=sreg. 594 char buffer[sizeof(vfp_register[0])]; 595 memcpy(buffer, &flt, sizeof(vfp_register[0])); 596 memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0])); 597 } 598 599 600 void Simulator::set_s_register_from_sinteger(int sreg, const int sint) { 601 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 602 // Read the bits from the integer value into the unsigned integer element of 603 // vfp_register[] given by index=sreg. 604 char buffer[sizeof(vfp_register[0])]; 605 memcpy(buffer, &sint, sizeof(vfp_register[0])); 606 memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0])); 607 } 608 609 610 void Simulator::set_d_register_from_double(int dreg, const double& dbl) { 611 ASSERT((dreg >= 0) && (dreg < num_d_registers)); 612 // Read the bits from the double precision floating point value into the two 613 // consecutive unsigned integer elements of vfp_register[] given by index 614 // 2*sreg and 2*sreg+1. 615 char buffer[2 * sizeof(vfp_register[0])]; 616 memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0])); 617 #ifndef BIG_ENDIAN_FLOATING_POINT 618 memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0])); 619 #else 620 memcpy(&vfp_register[dreg * 2], &buffer[4], sizeof(vfp_register[0])); 621 memcpy(&vfp_register[dreg * 2 + 1], &buffer[0], sizeof(vfp_register[0])); 622 #endif 623 } 624 625 626 float Simulator::get_float_from_s_register(int sreg) { 627 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 628 629 float sm_val = 0.0; 630 // Read the bits from the unsigned integer vfp_register[] array 631 // into the single precision floating point value and return it. 632 char buffer[sizeof(vfp_register[0])]; 633 memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0])); 634 memcpy(&sm_val, buffer, sizeof(vfp_register[0])); 635 return(sm_val); 636 } 637 638 639 int Simulator::get_sinteger_from_s_register(int sreg) { 640 ASSERT((sreg >= 0) && (sreg < num_s_registers)); 641 642 int sm_val = 0; 643 // Read the bits from the unsigned integer vfp_register[] array 644 // into the single precision floating point value and return it. 645 char buffer[sizeof(vfp_register[0])]; 646 memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0])); 647 memcpy(&sm_val, buffer, sizeof(vfp_register[0])); 648 return(sm_val); 649 } 650 651 652 double Simulator::get_double_from_d_register(int dreg) { 653 ASSERT((dreg >= 0) && (dreg < num_d_registers)); 654 655 double dm_val = 0.0; 656 // Read the bits from the unsigned integer vfp_register[] array 657 // into the double precision floating point value and return it. 658 char buffer[2 * sizeof(vfp_register[0])]; 659 #ifdef BIG_ENDIAN_FLOATING_POINT 660 memcpy(&buffer[0], &vfp_register[2 * dreg + 1], sizeof(vfp_register[0])); 661 memcpy(&buffer[4], &vfp_register[2 * dreg], sizeof(vfp_register[0])); 662 #else 663 memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0])); 664 #endif 665 memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0])); 666 return(dm_val); 667 } 668 669 670 // For use in calls that take two double values, constructed from r0, r1, r2 671 // and r3. 672 void Simulator::GetFpArgs(double* x, double* y) { 673 // We use a char buffer to get around the strict-aliasing rules which 674 // otherwise allow the compiler to optimize away the copy. 675 char buffer[2 * sizeof(registers_[0])]; 676 // Registers 0 and 1 -> x. 677 memcpy(buffer, registers_, sizeof(buffer)); 678 memcpy(x, buffer, sizeof(buffer)); 679 // Registers 2 and 3 -> y. 680 memcpy(buffer, registers_ + 2, sizeof(buffer)); 681 memcpy(y, buffer, sizeof(buffer)); 682 } 683 684 685 void Simulator::SetFpResult(const double& result) { 686 char buffer[2 * sizeof(registers_[0])]; 687 memcpy(buffer, &result, sizeof(buffer)); 688 // result -> registers 0 and 1. 689 memcpy(registers_, buffer, sizeof(buffer)); 690 } 691 692 693 void Simulator::TrashCallerSaveRegisters() { 694 // We don't trash the registers with the return value. 695 registers_[2] = 0x50Bad4U; 696 registers_[3] = 0x50Bad4U; 697 registers_[12] = 0x50Bad4U; 698 } 699 700 701 // The ARM cannot do unaligned reads and writes. On some ARM platforms an 702 // interrupt is caused. On others it does a funky rotation thing. For now we 703 // simply disallow unaligned reads, but at some point we may want to move to 704 // emulating the rotate behaviour. Note that simulator runs have the runtime 705 // system running directly on the host system and only generated code is 706 // executed in the simulator. Since the host is typically IA32 we will not 707 // get the correct ARM-like behaviour on unaligned accesses. 708 709 int Simulator::ReadW(int32_t addr, Instr* instr) { 710 if ((addr & 3) == 0) { 711 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 712 return *ptr; 713 } 714 PrintF("Unaligned read at 0x%08x\n", addr); 715 UNIMPLEMENTED(); 716 return 0; 717 } 718 719 720 void Simulator::WriteW(int32_t addr, int value, Instr* instr) { 721 if ((addr & 3) == 0) { 722 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 723 *ptr = value; 724 return; 725 } 726 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); 727 UNIMPLEMENTED(); 728 } 729 730 731 uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) { 732 if ((addr & 1) == 0) { 733 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 734 return *ptr; 735 } 736 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); 737 UNIMPLEMENTED(); 738 return 0; 739 } 740 741 742 int16_t Simulator::ReadH(int32_t addr, Instr* instr) { 743 if ((addr & 1) == 0) { 744 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 745 return *ptr; 746 } 747 PrintF("Unaligned signed halfword read at 0x%08x\n", addr); 748 UNIMPLEMENTED(); 749 return 0; 750 } 751 752 753 void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) { 754 if ((addr & 1) == 0) { 755 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 756 *ptr = value; 757 return; 758 } 759 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr); 760 UNIMPLEMENTED(); 761 } 762 763 764 void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) { 765 if ((addr & 1) == 0) { 766 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 767 *ptr = value; 768 return; 769 } 770 PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr); 771 UNIMPLEMENTED(); 772 } 773 774 775 uint8_t Simulator::ReadBU(int32_t addr) { 776 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 777 return *ptr; 778 } 779 780 781 int8_t Simulator::ReadB(int32_t addr) { 782 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 783 return *ptr; 784 } 785 786 787 void Simulator::WriteB(int32_t addr, uint8_t value) { 788 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 789 *ptr = value; 790 } 791 792 793 void Simulator::WriteB(int32_t addr, int8_t value) { 794 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 795 *ptr = value; 796 } 797 798 799 // Returns the limit of the stack area to enable checking for stack overflows. 800 uintptr_t Simulator::StackLimit() const { 801 // Leave a safety margin of 256 bytes to prevent overrunning the stack when 802 // pushing values. 803 return reinterpret_cast<uintptr_t>(stack_) + 256; 804 } 805 806 807 // Unsupported instructions use Format to print an error and stop execution. 808 void Simulator::Format(Instr* instr, const char* format) { 809 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", 810 instr, format); 811 UNIMPLEMENTED(); 812 } 813 814 815 // Checks if the current instruction should be executed based on its 816 // condition bits. 817 bool Simulator::ConditionallyExecute(Instr* instr) { 818 switch (instr->ConditionField()) { 819 case EQ: return z_flag_; 820 case NE: return !z_flag_; 821 case CS: return c_flag_; 822 case CC: return !c_flag_; 823 case MI: return n_flag_; 824 case PL: return !n_flag_; 825 case VS: return v_flag_; 826 case VC: return !v_flag_; 827 case HI: return c_flag_ && !z_flag_; 828 case LS: return !c_flag_ || z_flag_; 829 case GE: return n_flag_ == v_flag_; 830 case LT: return n_flag_ != v_flag_; 831 case GT: return !z_flag_ && (n_flag_ == v_flag_); 832 case LE: return z_flag_ || (n_flag_ != v_flag_); 833 case AL: return true; 834 default: UNREACHABLE(); 835 } 836 return false; 837 } 838 839 840 // Calculate and set the Negative and Zero flags. 841 void Simulator::SetNZFlags(int32_t val) { 842 n_flag_ = (val < 0); 843 z_flag_ = (val == 0); 844 } 845 846 847 // Set the Carry flag. 848 void Simulator::SetCFlag(bool val) { 849 c_flag_ = val; 850 } 851 852 853 // Set the oVerflow flag. 854 void Simulator::SetVFlag(bool val) { 855 v_flag_ = val; 856 } 857 858 859 // Calculate C flag value for additions. 860 bool Simulator::CarryFrom(int32_t left, int32_t right) { 861 uint32_t uleft = static_cast<uint32_t>(left); 862 uint32_t uright = static_cast<uint32_t>(right); 863 uint32_t urest = 0xffffffffU - uleft; 864 865 return (uright > urest); 866 } 867 868 869 // Calculate C flag value for subtractions. 870 bool Simulator::BorrowFrom(int32_t left, int32_t right) { 871 uint32_t uleft = static_cast<uint32_t>(left); 872 uint32_t uright = static_cast<uint32_t>(right); 873 874 return (uright > uleft); 875 } 876 877 878 // Calculate V flag value for additions and subtractions. 879 bool Simulator::OverflowFrom(int32_t alu_out, 880 int32_t left, int32_t right, bool addition) { 881 bool overflow; 882 if (addition) { 883 // operands have the same sign 884 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) 885 // and operands and result have different sign 886 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 887 } else { 888 // operands have different signs 889 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) 890 // and first operand and result have different signs 891 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 892 } 893 return overflow; 894 } 895 896 897 // Support for VFP comparisons. 898 void Simulator::Compute_FPSCR_Flags(double val1, double val2) { 899 if (isnan(val1) || isnan(val2)) { 900 n_flag_FPSCR_ = false; 901 z_flag_FPSCR_ = false; 902 c_flag_FPSCR_ = true; 903 v_flag_FPSCR_ = true; 904 // All non-NaN cases. 905 } else if (val1 == val2) { 906 n_flag_FPSCR_ = false; 907 z_flag_FPSCR_ = true; 908 c_flag_FPSCR_ = true; 909 v_flag_FPSCR_ = false; 910 } else if (val1 < val2) { 911 n_flag_FPSCR_ = true; 912 z_flag_FPSCR_ = false; 913 c_flag_FPSCR_ = false; 914 v_flag_FPSCR_ = false; 915 } else { 916 // Case when (val1 > val2). 917 n_flag_FPSCR_ = false; 918 z_flag_FPSCR_ = false; 919 c_flag_FPSCR_ = true; 920 v_flag_FPSCR_ = false; 921 } 922 } 923 924 925 void Simulator::Copy_FPSCR_to_APSR() { 926 n_flag_ = n_flag_FPSCR_; 927 z_flag_ = z_flag_FPSCR_; 928 c_flag_ = c_flag_FPSCR_; 929 v_flag_ = v_flag_FPSCR_; 930 } 931 932 933 // Addressing Mode 1 - Data-processing operands: 934 // Get the value based on the shifter_operand with register. 935 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { 936 Shift shift = instr->ShiftField(); 937 int shift_amount = instr->ShiftAmountField(); 938 int32_t result = get_register(instr->RmField()); 939 if (instr->Bit(4) == 0) { 940 // by immediate 941 if ((shift == ROR) && (shift_amount == 0)) { 942 UNIMPLEMENTED(); 943 return result; 944 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { 945 shift_amount = 32; 946 } 947 switch (shift) { 948 case ASR: { 949 if (shift_amount == 0) { 950 if (result < 0) { 951 result = 0xffffffff; 952 *carry_out = true; 953 } else { 954 result = 0; 955 *carry_out = false; 956 } 957 } else { 958 result >>= (shift_amount - 1); 959 *carry_out = (result & 1) == 1; 960 result >>= 1; 961 } 962 break; 963 } 964 965 case LSL: { 966 if (shift_amount == 0) { 967 *carry_out = c_flag_; 968 } else { 969 result <<= (shift_amount - 1); 970 *carry_out = (result < 0); 971 result <<= 1; 972 } 973 break; 974 } 975 976 case LSR: { 977 if (shift_amount == 0) { 978 result = 0; 979 *carry_out = c_flag_; 980 } else { 981 uint32_t uresult = static_cast<uint32_t>(result); 982 uresult >>= (shift_amount - 1); 983 *carry_out = (uresult & 1) == 1; 984 uresult >>= 1; 985 result = static_cast<int32_t>(uresult); 986 } 987 break; 988 } 989 990 case ROR: { 991 UNIMPLEMENTED(); 992 break; 993 } 994 995 default: { 996 UNREACHABLE(); 997 break; 998 } 999 } 1000 } else { 1001 // by register 1002 int rs = instr->RsField(); 1003 shift_amount = get_register(rs) &0xff; 1004 switch (shift) { 1005 case ASR: { 1006 if (shift_amount == 0) { 1007 *carry_out = c_flag_; 1008 } else if (shift_amount < 32) { 1009 result >>= (shift_amount - 1); 1010 *carry_out = (result & 1) == 1; 1011 result >>= 1; 1012 } else { 1013 ASSERT(shift_amount >= 32); 1014 if (result < 0) { 1015 *carry_out = true; 1016 result = 0xffffffff; 1017 } else { 1018 *carry_out = false; 1019 result = 0; 1020 } 1021 } 1022 break; 1023 } 1024 1025 case LSL: { 1026 if (shift_amount == 0) { 1027 *carry_out = c_flag_; 1028 } else if (shift_amount < 32) { 1029 result <<= (shift_amount - 1); 1030 *carry_out = (result < 0); 1031 result <<= 1; 1032 } else if (shift_amount == 32) { 1033 *carry_out = (result & 1) == 1; 1034 result = 0; 1035 } else { 1036 ASSERT(shift_amount > 32); 1037 *carry_out = false; 1038 result = 0; 1039 } 1040 break; 1041 } 1042 1043 case LSR: { 1044 if (shift_amount == 0) { 1045 *carry_out = c_flag_; 1046 } else if (shift_amount < 32) { 1047 uint32_t uresult = static_cast<uint32_t>(result); 1048 uresult >>= (shift_amount - 1); 1049 *carry_out = (uresult & 1) == 1; 1050 uresult >>= 1; 1051 result = static_cast<int32_t>(uresult); 1052 } else if (shift_amount == 32) { 1053 *carry_out = (result < 0); 1054 result = 0; 1055 } else { 1056 *carry_out = false; 1057 result = 0; 1058 } 1059 break; 1060 } 1061 1062 case ROR: { 1063 UNIMPLEMENTED(); 1064 break; 1065 } 1066 1067 default: { 1068 UNREACHABLE(); 1069 break; 1070 } 1071 } 1072 } 1073 return result; 1074 } 1075 1076 1077 // Addressing Mode 1 - Data-processing operands: 1078 // Get the value based on the shifter_operand with immediate. 1079 int32_t Simulator::GetImm(Instr* instr, bool* carry_out) { 1080 int rotate = instr->RotateField() * 2; 1081 int immed8 = instr->Immed8Field(); 1082 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); 1083 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); 1084 return imm; 1085 } 1086 1087 1088 static int count_bits(int bit_vector) { 1089 int count = 0; 1090 while (bit_vector != 0) { 1091 if ((bit_vector & 1) != 0) { 1092 count++; 1093 } 1094 bit_vector >>= 1; 1095 } 1096 return count; 1097 } 1098 1099 1100 // Addressing Mode 4 - Load and Store Multiple 1101 void Simulator::HandleRList(Instr* instr, bool load) { 1102 int rn = instr->RnField(); 1103 int32_t rn_val = get_register(rn); 1104 int rlist = instr->RlistField(); 1105 int num_regs = count_bits(rlist); 1106 1107 intptr_t start_address = 0; 1108 intptr_t end_address = 0; 1109 switch (instr->PUField()) { 1110 case 0: { 1111 // Print("da"); 1112 UNIMPLEMENTED(); 1113 break; 1114 } 1115 case 1: { 1116 // Print("ia"); 1117 start_address = rn_val; 1118 end_address = rn_val + (num_regs * 4) - 4; 1119 rn_val = rn_val + (num_regs * 4); 1120 break; 1121 } 1122 case 2: { 1123 // Print("db"); 1124 start_address = rn_val - (num_regs * 4); 1125 end_address = rn_val - 4; 1126 rn_val = start_address; 1127 break; 1128 } 1129 case 3: { 1130 // Print("ib"); 1131 UNIMPLEMENTED(); 1132 break; 1133 } 1134 default: { 1135 UNREACHABLE(); 1136 break; 1137 } 1138 } 1139 if (instr->HasW()) { 1140 set_register(rn, rn_val); 1141 } 1142 intptr_t* address = reinterpret_cast<intptr_t*>(start_address); 1143 int reg = 0; 1144 while (rlist != 0) { 1145 if ((rlist & 1) != 0) { 1146 if (load) { 1147 set_register(reg, *address); 1148 } else { 1149 *address = get_register(reg); 1150 } 1151 address += 1; 1152 } 1153 reg++; 1154 rlist >>= 1; 1155 } 1156 ASSERT(end_address == ((intptr_t)address) - 4); 1157 } 1158 1159 1160 // Calls into the V8 runtime are based on this very simple interface. 1161 // Note: To be able to return two values from some calls the code in runtime.cc 1162 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 1163 // 64-bit value. With the code below we assume that all runtime calls return 1164 // 64 bits of result. If they don't, the r1 result register contains a bogus 1165 // value, which is fine because it is caller-saved. 1166 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 1167 int32_t arg1, 1168 int32_t arg2, 1169 int32_t arg3); 1170 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, 1171 int32_t arg1, 1172 int32_t arg2, 1173 int32_t arg3); 1174 1175 1176 // Software interrupt instructions are used by the simulator to call into the 1177 // C-based V8 runtime. 1178 void Simulator::SoftwareInterrupt(Instr* instr) { 1179 int swi = instr->SwiField(); 1180 switch (swi) { 1181 case call_rt_redirected: { 1182 Redirection* redirection = Redirection::FromSwiInstruction(instr); 1183 int32_t arg0 = get_register(r0); 1184 int32_t arg1 = get_register(r1); 1185 int32_t arg2 = get_register(r2); 1186 int32_t arg3 = get_register(r3); 1187 // This is dodgy but it works because the C entry stubs are never moved. 1188 // See comment in codegen-arm.cc and bug 1242173. 1189 int32_t saved_lr = get_register(lr); 1190 if (redirection->fp_return()) { 1191 intptr_t external = 1192 reinterpret_cast<intptr_t>(redirection->external_function()); 1193 SimulatorRuntimeFPCall target = 1194 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1195 if (::v8::internal::FLAG_trace_sim) { 1196 double x, y; 1197 GetFpArgs(&x, &y); 1198 PrintF("Call to host function at %p with args %f, %f\n", 1199 FUNCTION_ADDR(target), x, y); 1200 } 1201 double result = target(arg0, arg1, arg2, arg3); 1202 SetFpResult(result); 1203 } else { 1204 intptr_t external = 1205 reinterpret_cast<int32_t>(redirection->external_function()); 1206 SimulatorRuntimeCall target = 1207 reinterpret_cast<SimulatorRuntimeCall>(external); 1208 if (::v8::internal::FLAG_trace_sim) { 1209 PrintF( 1210 "Call to host function at %p with args %08x, %08x, %08x, %08x\n", 1211 FUNCTION_ADDR(target), 1212 arg0, 1213 arg1, 1214 arg2, 1215 arg3); 1216 } 1217 int64_t result = target(arg0, arg1, arg2, arg3); 1218 int32_t lo_res = static_cast<int32_t>(result); 1219 int32_t hi_res = static_cast<int32_t>(result >> 32); 1220 if (::v8::internal::FLAG_trace_sim) { 1221 PrintF("Returned %08x\n", lo_res); 1222 } 1223 set_register(r0, lo_res); 1224 set_register(r1, hi_res); 1225 } 1226 set_register(lr, saved_lr); 1227 set_pc(get_register(lr)); 1228 break; 1229 } 1230 case break_point: { 1231 Debugger dbg(this); 1232 dbg.Debug(); 1233 break; 1234 } 1235 default: { 1236 UNREACHABLE(); 1237 break; 1238 } 1239 } 1240 } 1241 1242 1243 // Handle execution based on instruction types. 1244 1245 // Instruction types 0 and 1 are both rolled into one function because they 1246 // only differ in the handling of the shifter_operand. 1247 void Simulator::DecodeType01(Instr* instr) { 1248 int type = instr->TypeField(); 1249 if ((type == 0) && instr->IsSpecialType0()) { 1250 // multiply instruction or extra loads and stores 1251 if (instr->Bits(7, 4) == 9) { 1252 if (instr->Bit(24) == 0) { 1253 // Raw field decoding here. Multiply instructions have their Rd in 1254 // funny places. 1255 int rn = instr->RnField(); 1256 int rm = instr->RmField(); 1257 int rs = instr->RsField(); 1258 int32_t rs_val = get_register(rs); 1259 int32_t rm_val = get_register(rm); 1260 if (instr->Bit(23) == 0) { 1261 if (instr->Bit(21) == 0) { 1262 // The MUL instruction description (A 4.1.33) refers to Rd as being 1263 // the destination for the operation, but it confusingly uses the 1264 // Rn field to encode it. 1265 // Format(instr, "mul'cond's 'rn, 'rm, 'rs"); 1266 int rd = rn; // Remap the rn field to the Rd register. 1267 int32_t alu_out = rm_val * rs_val; 1268 set_register(rd, alu_out); 1269 if (instr->HasS()) { 1270 SetNZFlags(alu_out); 1271 } 1272 } else { 1273 // The MLA instruction description (A 4.1.28) refers to the order 1274 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the 1275 // Rn field to encode the Rd register and the Rd field to encode 1276 // the Rn register. 1277 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd"); 1278 } 1279 } else { 1280 // The signed/long multiply instructions use the terms RdHi and RdLo 1281 // when referring to the target registers. They are mapped to the Rn 1282 // and Rd fields as follows: 1283 // RdLo == Rd 1284 // RdHi == Rn (This is confusingly stored in variable rd here 1285 // because the mul instruction from above uses the 1286 // Rn field to encode the Rd register. Good luck figuring 1287 // this out without reading the ARM instruction manual 1288 // at a very detailed level.) 1289 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm"); 1290 int rd_hi = rn; // Remap the rn field to the RdHi register. 1291 int rd_lo = instr->RdField(); 1292 int32_t hi_res = 0; 1293 int32_t lo_res = 0; 1294 if (instr->Bit(22) == 1) { 1295 int64_t left_op = static_cast<int32_t>(rm_val); 1296 int64_t right_op = static_cast<int32_t>(rs_val); 1297 uint64_t result = left_op * right_op; 1298 hi_res = static_cast<int32_t>(result >> 32); 1299 lo_res = static_cast<int32_t>(result & 0xffffffff); 1300 } else { 1301 // unsigned multiply 1302 uint64_t left_op = static_cast<uint32_t>(rm_val); 1303 uint64_t right_op = static_cast<uint32_t>(rs_val); 1304 uint64_t result = left_op * right_op; 1305 hi_res = static_cast<int32_t>(result >> 32); 1306 lo_res = static_cast<int32_t>(result & 0xffffffff); 1307 } 1308 set_register(rd_lo, lo_res); 1309 set_register(rd_hi, hi_res); 1310 if (instr->HasS()) { 1311 UNIMPLEMENTED(); 1312 } 1313 } 1314 } else { 1315 UNIMPLEMENTED(); // Not used by V8. 1316 } 1317 } else { 1318 // extra load/store instructions 1319 int rd = instr->RdField(); 1320 int rn = instr->RnField(); 1321 int32_t rn_val = get_register(rn); 1322 int32_t addr = 0; 1323 if (instr->Bit(22) == 0) { 1324 int rm = instr->RmField(); 1325 int32_t rm_val = get_register(rm); 1326 switch (instr->PUField()) { 1327 case 0: { 1328 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm"); 1329 ASSERT(!instr->HasW()); 1330 addr = rn_val; 1331 rn_val -= rm_val; 1332 set_register(rn, rn_val); 1333 break; 1334 } 1335 case 1: { 1336 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm"); 1337 ASSERT(!instr->HasW()); 1338 addr = rn_val; 1339 rn_val += rm_val; 1340 set_register(rn, rn_val); 1341 break; 1342 } 1343 case 2: { 1344 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w"); 1345 rn_val -= rm_val; 1346 addr = rn_val; 1347 if (instr->HasW()) { 1348 set_register(rn, rn_val); 1349 } 1350 break; 1351 } 1352 case 3: { 1353 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w"); 1354 rn_val += rm_val; 1355 addr = rn_val; 1356 if (instr->HasW()) { 1357 set_register(rn, rn_val); 1358 } 1359 break; 1360 } 1361 default: { 1362 // The PU field is a 2-bit field. 1363 UNREACHABLE(); 1364 break; 1365 } 1366 } 1367 } else { 1368 int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField(); 1369 switch (instr->PUField()) { 1370 case 0: { 1371 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8"); 1372 ASSERT(!instr->HasW()); 1373 addr = rn_val; 1374 rn_val -= imm_val; 1375 set_register(rn, rn_val); 1376 break; 1377 } 1378 case 1: { 1379 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8"); 1380 ASSERT(!instr->HasW()); 1381 addr = rn_val; 1382 rn_val += imm_val; 1383 set_register(rn, rn_val); 1384 break; 1385 } 1386 case 2: { 1387 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w"); 1388 rn_val -= imm_val; 1389 addr = rn_val; 1390 if (instr->HasW()) { 1391 set_register(rn, rn_val); 1392 } 1393 break; 1394 } 1395 case 3: { 1396 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w"); 1397 rn_val += imm_val; 1398 addr = rn_val; 1399 if (instr->HasW()) { 1400 set_register(rn, rn_val); 1401 } 1402 break; 1403 } 1404 default: { 1405 // The PU field is a 2-bit field. 1406 UNREACHABLE(); 1407 break; 1408 } 1409 } 1410 } 1411 if (instr->HasH()) { 1412 if (instr->HasSign()) { 1413 if (instr->HasL()) { 1414 int16_t val = ReadH(addr, instr); 1415 set_register(rd, val); 1416 } else { 1417 int16_t val = get_register(rd); 1418 WriteH(addr, val, instr); 1419 } 1420 } else { 1421 if (instr->HasL()) { 1422 uint16_t val = ReadHU(addr, instr); 1423 set_register(rd, val); 1424 } else { 1425 uint16_t val = get_register(rd); 1426 WriteH(addr, val, instr); 1427 } 1428 } 1429 } else { 1430 // signed byte loads 1431 ASSERT(instr->HasSign()); 1432 ASSERT(instr->HasL()); 1433 int8_t val = ReadB(addr); 1434 set_register(rd, val); 1435 } 1436 return; 1437 } 1438 } else { 1439 int rd = instr->RdField(); 1440 int rn = instr->RnField(); 1441 int32_t rn_val = get_register(rn); 1442 int32_t shifter_operand = 0; 1443 bool shifter_carry_out = 0; 1444 if (type == 0) { 1445 shifter_operand = GetShiftRm(instr, &shifter_carry_out); 1446 } else { 1447 ASSERT(instr->TypeField() == 1); 1448 shifter_operand = GetImm(instr, &shifter_carry_out); 1449 } 1450 int32_t alu_out; 1451 1452 switch (instr->OpcodeField()) { 1453 case AND: { 1454 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); 1455 // Format(instr, "and'cond's 'rd, 'rn, 'imm"); 1456 alu_out = rn_val & shifter_operand; 1457 set_register(rd, alu_out); 1458 if (instr->HasS()) { 1459 SetNZFlags(alu_out); 1460 SetCFlag(shifter_carry_out); 1461 } 1462 break; 1463 } 1464 1465 case EOR: { 1466 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm"); 1467 // Format(instr, "eor'cond's 'rd, 'rn, 'imm"); 1468 alu_out = rn_val ^ shifter_operand; 1469 set_register(rd, alu_out); 1470 if (instr->HasS()) { 1471 SetNZFlags(alu_out); 1472 SetCFlag(shifter_carry_out); 1473 } 1474 break; 1475 } 1476 1477 case SUB: { 1478 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm"); 1479 // Format(instr, "sub'cond's 'rd, 'rn, 'imm"); 1480 alu_out = rn_val - shifter_operand; 1481 set_register(rd, alu_out); 1482 if (instr->HasS()) { 1483 SetNZFlags(alu_out); 1484 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 1485 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 1486 } 1487 break; 1488 } 1489 1490 case RSB: { 1491 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm"); 1492 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm"); 1493 alu_out = shifter_operand - rn_val; 1494 set_register(rd, alu_out); 1495 if (instr->HasS()) { 1496 SetNZFlags(alu_out); 1497 SetCFlag(!BorrowFrom(shifter_operand, rn_val)); 1498 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); 1499 } 1500 break; 1501 } 1502 1503 case ADD: { 1504 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm"); 1505 // Format(instr, "add'cond's 'rd, 'rn, 'imm"); 1506 alu_out = rn_val + shifter_operand; 1507 set_register(rd, alu_out); 1508 if (instr->HasS()) { 1509 SetNZFlags(alu_out); 1510 SetCFlag(CarryFrom(rn_val, shifter_operand)); 1511 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 1512 } 1513 break; 1514 } 1515 1516 case ADC: { 1517 Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); 1518 Format(instr, "adc'cond's 'rd, 'rn, 'imm"); 1519 break; 1520 } 1521 1522 case SBC: { 1523 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); 1524 Format(instr, "sbc'cond's 'rd, 'rn, 'imm"); 1525 break; 1526 } 1527 1528 case RSC: { 1529 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); 1530 Format(instr, "rsc'cond's 'rd, 'rn, 'imm"); 1531 break; 1532 } 1533 1534 case TST: { 1535 if (instr->HasS()) { 1536 // Format(instr, "tst'cond 'rn, 'shift_rm"); 1537 // Format(instr, "tst'cond 'rn, 'imm"); 1538 alu_out = rn_val & shifter_operand; 1539 SetNZFlags(alu_out); 1540 SetCFlag(shifter_carry_out); 1541 } else { 1542 UNIMPLEMENTED(); 1543 } 1544 break; 1545 } 1546 1547 case TEQ: { 1548 if (instr->HasS()) { 1549 // Format(instr, "teq'cond 'rn, 'shift_rm"); 1550 // Format(instr, "teq'cond 'rn, 'imm"); 1551 alu_out = rn_val ^ shifter_operand; 1552 SetNZFlags(alu_out); 1553 SetCFlag(shifter_carry_out); 1554 } else { 1555 ASSERT(type == 0); 1556 int rm = instr->RmField(); 1557 switch (instr->Bits(7, 4)) { 1558 case BX: 1559 set_pc(get_register(rm)); 1560 break; 1561 case BLX: { 1562 uint32_t old_pc = get_pc(); 1563 set_pc(get_register(rm)); 1564 set_register(lr, old_pc + Instr::kInstrSize); 1565 break; 1566 } 1567 default: 1568 UNIMPLEMENTED(); 1569 } 1570 } 1571 break; 1572 } 1573 1574 case CMP: { 1575 if (instr->HasS()) { 1576 // Format(instr, "cmp'cond 'rn, 'shift_rm"); 1577 // Format(instr, "cmp'cond 'rn, 'imm"); 1578 alu_out = rn_val - shifter_operand; 1579 SetNZFlags(alu_out); 1580 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 1581 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 1582 } else { 1583 UNIMPLEMENTED(); 1584 } 1585 break; 1586 } 1587 1588 case CMN: { 1589 if (instr->HasS()) { 1590 // Format(instr, "cmn'cond 'rn, 'shift_rm"); 1591 // Format(instr, "cmn'cond 'rn, 'imm"); 1592 alu_out = rn_val + shifter_operand; 1593 SetNZFlags(alu_out); 1594 SetCFlag(!CarryFrom(rn_val, shifter_operand)); 1595 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 1596 } else { 1597 ASSERT(type == 0); 1598 int rm = instr->RmField(); 1599 int rd = instr->RdField(); 1600 switch (instr->Bits(7, 4)) { 1601 case CLZ: { 1602 uint32_t bits = get_register(rm); 1603 int leading_zeros = 0; 1604 if (bits == 0) { 1605 leading_zeros = 32; 1606 } else { 1607 while ((bits & 0x80000000u) == 0) { 1608 bits <<= 1; 1609 leading_zeros++; 1610 } 1611 } 1612 set_register(rd, leading_zeros); 1613 break; 1614 } 1615 default: 1616 UNIMPLEMENTED(); 1617 } 1618 } 1619 break; 1620 } 1621 1622 case ORR: { 1623 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); 1624 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); 1625 alu_out = rn_val | shifter_operand; 1626 set_register(rd, alu_out); 1627 if (instr->HasS()) { 1628 SetNZFlags(alu_out); 1629 SetCFlag(shifter_carry_out); 1630 } 1631 break; 1632 } 1633 1634 case MOV: { 1635 // Format(instr, "mov'cond's 'rd, 'shift_rm"); 1636 // Format(instr, "mov'cond's 'rd, 'imm"); 1637 alu_out = shifter_operand; 1638 set_register(rd, alu_out); 1639 if (instr->HasS()) { 1640 SetNZFlags(alu_out); 1641 SetCFlag(shifter_carry_out); 1642 } 1643 break; 1644 } 1645 1646 case BIC: { 1647 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm"); 1648 // Format(instr, "bic'cond's 'rd, 'rn, 'imm"); 1649 alu_out = rn_val & ~shifter_operand; 1650 set_register(rd, alu_out); 1651 if (instr->HasS()) { 1652 SetNZFlags(alu_out); 1653 SetCFlag(shifter_carry_out); 1654 } 1655 break; 1656 } 1657 1658 case MVN: { 1659 // Format(instr, "mvn'cond's 'rd, 'shift_rm"); 1660 // Format(instr, "mvn'cond's 'rd, 'imm"); 1661 alu_out = ~shifter_operand; 1662 set_register(rd, alu_out); 1663 if (instr->HasS()) { 1664 SetNZFlags(alu_out); 1665 SetCFlag(shifter_carry_out); 1666 } 1667 break; 1668 } 1669 1670 default: { 1671 UNREACHABLE(); 1672 break; 1673 } 1674 } 1675 } 1676 } 1677 1678 1679 void Simulator::DecodeType2(Instr* instr) { 1680 int rd = instr->RdField(); 1681 int rn = instr->RnField(); 1682 int32_t rn_val = get_register(rn); 1683 int32_t im_val = instr->Offset12Field(); 1684 int32_t addr = 0; 1685 switch (instr->PUField()) { 1686 case 0: { 1687 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 1688 ASSERT(!instr->HasW()); 1689 addr = rn_val; 1690 rn_val -= im_val; 1691 set_register(rn, rn_val); 1692 break; 1693 } 1694 case 1: { 1695 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 1696 ASSERT(!instr->HasW()); 1697 addr = rn_val; 1698 rn_val += im_val; 1699 set_register(rn, rn_val); 1700 break; 1701 } 1702 case 2: { 1703 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 1704 rn_val -= im_val; 1705 addr = rn_val; 1706 if (instr->HasW()) { 1707 set_register(rn, rn_val); 1708 } 1709 break; 1710 } 1711 case 3: { 1712 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 1713 rn_val += im_val; 1714 addr = rn_val; 1715 if (instr->HasW()) { 1716 set_register(rn, rn_val); 1717 } 1718 break; 1719 } 1720 default: { 1721 UNREACHABLE(); 1722 break; 1723 } 1724 } 1725 if (instr->HasB()) { 1726 if (instr->HasL()) { 1727 byte val = ReadBU(addr); 1728 set_register(rd, val); 1729 } else { 1730 byte val = get_register(rd); 1731 WriteB(addr, val); 1732 } 1733 } else { 1734 if (instr->HasL()) { 1735 set_register(rd, ReadW(addr, instr)); 1736 } else { 1737 WriteW(addr, get_register(rd), instr); 1738 } 1739 } 1740 } 1741 1742 1743 void Simulator::DecodeType3(Instr* instr) { 1744 ASSERT(instr->Bits(6, 4) == 0x5 || instr->Bit(4) == 0); 1745 int rd = instr->RdField(); 1746 int rn = instr->RnField(); 1747 int32_t rn_val = get_register(rn); 1748 bool shifter_carry_out = 0; 1749 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); 1750 int32_t addr = 0; 1751 switch (instr->PUField()) { 1752 case 0: { 1753 ASSERT(!instr->HasW()); 1754 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); 1755 break; 1756 } 1757 case 1: { 1758 ASSERT(!instr->HasW()); 1759 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); 1760 break; 1761 } 1762 case 2: { 1763 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w"); 1764 addr = rn_val - shifter_operand; 1765 if (instr->HasW()) { 1766 set_register(rn, addr); 1767 } 1768 break; 1769 } 1770 case 3: { 1771 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { 1772 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); 1773 uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField()); 1774 uint32_t msbit = widthminus1 + lsbit; 1775 if (msbit <= 31) { 1776 uint32_t rm_val = 1777 static_cast<uint32_t>(get_register(instr->RmField())); 1778 uint32_t extr_val = rm_val << (31 - msbit); 1779 extr_val = extr_val >> (31 - widthminus1); 1780 set_register(instr->RdField(), extr_val); 1781 } else { 1782 UNREACHABLE(); 1783 } 1784 return; 1785 } else { 1786 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); 1787 addr = rn_val + shifter_operand; 1788 if (instr->HasW()) { 1789 set_register(rn, addr); 1790 } 1791 } 1792 break; 1793 } 1794 default: { 1795 UNREACHABLE(); 1796 break; 1797 } 1798 } 1799 if (instr->HasB()) { 1800 if (instr->HasL()) { 1801 uint8_t byte = ReadB(addr); 1802 set_register(rd, byte); 1803 } else { 1804 uint8_t byte = get_register(rd); 1805 WriteB(addr, byte); 1806 } 1807 } else { 1808 if (instr->HasL()) { 1809 set_register(rd, ReadW(addr, instr)); 1810 } else { 1811 WriteW(addr, get_register(rd), instr); 1812 } 1813 } 1814 } 1815 1816 1817 void Simulator::DecodeType4(Instr* instr) { 1818 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode 1819 if (instr->HasL()) { 1820 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); 1821 HandleRList(instr, true); 1822 } else { 1823 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); 1824 HandleRList(instr, false); 1825 } 1826 } 1827 1828 1829 void Simulator::DecodeType5(Instr* instr) { 1830 // Format(instr, "b'l'cond 'target"); 1831 int off = (instr->SImmed24Field() << 2); 1832 intptr_t pc_address = get_pc(); 1833 if (instr->HasLink()) { 1834 set_register(lr, pc_address + Instr::kInstrSize); 1835 } 1836 int pc_reg = get_register(pc); 1837 set_pc(pc_reg + off); 1838 } 1839 1840 1841 void Simulator::DecodeType6(Instr* instr) { 1842 DecodeType6CoprocessorIns(instr); 1843 } 1844 1845 1846 void Simulator::DecodeType7(Instr* instr) { 1847 if (instr->Bit(24) == 1) { 1848 SoftwareInterrupt(instr); 1849 } else { 1850 DecodeTypeVFP(instr); 1851 } 1852 } 1853 1854 1855 void Simulator::DecodeUnconditional(Instr* instr) { 1856 if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 && instr->HasL()) { 1857 // Load halfword instruction, either register or immediate offset. 1858 int rd = instr->RdField(); 1859 int rn = instr->RnField(); 1860 int32_t rn_val = get_register(rn); 1861 int32_t addr = 0; 1862 int32_t offset; 1863 if (instr->Bit(22) == 0) { 1864 // Register offset. 1865 int rm = instr->RmField(); 1866 offset = get_register(rm); 1867 } else { 1868 // Immediate offset 1869 offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4); 1870 } 1871 switch (instr->PUField()) { 1872 case 0: { 1873 // Post index, negative. 1874 ASSERT(!instr->HasW()); 1875 addr = rn_val; 1876 rn_val -= offset; 1877 set_register(rn, rn_val); 1878 break; 1879 } 1880 case 1: { 1881 // Post index, positive. 1882 ASSERT(!instr->HasW()); 1883 addr = rn_val; 1884 rn_val += offset; 1885 set_register(rn, rn_val); 1886 break; 1887 } 1888 case 2: { 1889 // Pre index or offset, negative. 1890 rn_val -= offset; 1891 addr = rn_val; 1892 if (instr->HasW()) { 1893 set_register(rn, rn_val); 1894 } 1895 break; 1896 } 1897 case 3: { 1898 // Pre index or offset, positive. 1899 rn_val += offset; 1900 addr = rn_val; 1901 if (instr->HasW()) { 1902 set_register(rn, rn_val); 1903 } 1904 break; 1905 } 1906 default: { 1907 // The PU field is a 2-bit field. 1908 UNREACHABLE(); 1909 break; 1910 } 1911 } 1912 // Not sign extending, so load as unsigned. 1913 uint16_t halfword = ReadH(addr, instr); 1914 set_register(rd, halfword); 1915 } else { 1916 Debugger dbg(this); 1917 dbg.Stop(instr); 1918 } 1919 } 1920 1921 1922 // void Simulator::DecodeTypeVFP(Instr* instr) 1923 // The Following ARMv7 VFPv instructions are currently supported. 1924 // vmov :Sn = Rt 1925 // vmov :Rt = Sn 1926 // vcvt: Dd = Sm 1927 // vcvt: Sd = Dm 1928 // Dd = vadd(Dn, Dm) 1929 // Dd = vsub(Dn, Dm) 1930 // Dd = vmul(Dn, Dm) 1931 // Dd = vdiv(Dn, Dm) 1932 // vcmp(Dd, Dm) 1933 // VMRS 1934 void Simulator::DecodeTypeVFP(Instr* instr) { 1935 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); 1936 1937 int rt = instr->RtField(); 1938 int vm = instr->VmField(); 1939 int vn = instr->VnField(); 1940 int vd = instr->VdField(); 1941 1942 if (instr->Bit(23) == 1) { 1943 if ((instr->Bits(21, 19) == 0x7) && 1944 (instr->Bits(18, 16) == 0x5) && 1945 (instr->Bits(11, 9) == 0x5) && 1946 (instr->Bit(8) == 1) && 1947 (instr->Bit(6) == 1) && 1948 (instr->Bit(4) == 0)) { 1949 double dm_val = get_double_from_d_register(vm); 1950 int32_t int_value = static_cast<int32_t>(dm_val); 1951 set_s_register_from_sinteger(((vd<<1) | instr->DField()), int_value); 1952 } else if ((instr->Bits(21, 19) == 0x7) && 1953 (instr->Bits(18, 16) == 0x0) && 1954 (instr->Bits(11, 9) == 0x5) && 1955 (instr->Bit(8) == 1) && 1956 (instr->Bit(7) == 1) && 1957 (instr->Bit(6) == 1) && 1958 (instr->Bit(4) == 0)) { 1959 int32_t int_value = get_sinteger_from_s_register(((vm<<1) | 1960 instr->MField())); 1961 double dbl_value = static_cast<double>(int_value); 1962 set_d_register_from_double(vd, dbl_value); 1963 } else if ((instr->Bit(21) == 0x0) && 1964 (instr->Bit(20) == 0x0) && 1965 (instr->Bits(11, 9) == 0x5) && 1966 (instr->Bit(8) == 1) && 1967 (instr->Bit(6) == 0) && 1968 (instr->Bit(4) == 0)) { 1969 double dn_value = get_double_from_d_register(vn); 1970 double dm_value = get_double_from_d_register(vm); 1971 double dd_value = dn_value / dm_value; 1972 set_d_register_from_double(vd, dd_value); 1973 } else if ((instr->Bits(21, 20) == 0x3) && 1974 (instr->Bits(19, 16) == 0x4) && 1975 (instr->Bits(11, 9) == 0x5) && 1976 (instr->Bit(8) == 0x1) && 1977 (instr->Bit(6) == 0x1) && 1978 (instr->Bit(4) == 0x0)) { 1979 double dd_value = get_double_from_d_register(vd); 1980 double dm_value = get_double_from_d_register(vm); 1981 Compute_FPSCR_Flags(dd_value, dm_value); 1982 } else if ((instr->Bits(23, 20) == 0xF) && 1983 (instr->Bits(19, 16) == 0x1) && 1984 (instr->Bits(11, 8) == 0xA) && 1985 (instr->Bits(7, 5) == 0x0) && 1986 (instr->Bit(4) == 0x1) && 1987 (instr->Bits(3, 0) == 0x0)) { 1988 if (instr->Bits(15, 12) == 0xF) 1989 Copy_FPSCR_to_APSR(); 1990 else 1991 UNIMPLEMENTED(); // Not used by V8. 1992 } else { 1993 UNIMPLEMENTED(); // Not used by V8. 1994 } 1995 } else if (instr->Bit(21) == 1) { 1996 if ((instr->Bit(20) == 0x1) && 1997 (instr->Bits(11, 9) == 0x5) && 1998 (instr->Bit(8) == 0x1) && 1999 (instr->Bit(6) == 0) && 2000 (instr->Bit(4) == 0)) { 2001 double dn_value = get_double_from_d_register(vn); 2002 double dm_value = get_double_from_d_register(vm); 2003 double dd_value = dn_value + dm_value; 2004 set_d_register_from_double(vd, dd_value); 2005 } else if ((instr->Bit(20) == 0x1) && 2006 (instr->Bits(11, 9) == 0x5) && 2007 (instr->Bit(8) == 0x1) && 2008 (instr->Bit(6) == 1) && 2009 (instr->Bit(4) == 0)) { 2010 double dn_value = get_double_from_d_register(vn); 2011 double dm_value = get_double_from_d_register(vm); 2012 double dd_value = dn_value - dm_value; 2013 set_d_register_from_double(vd, dd_value); 2014 } else if ((instr->Bit(20) == 0x0) && 2015 (instr->Bits(11, 9) == 0x5) && 2016 (instr->Bit(8) == 0x1) && 2017 (instr->Bit(6) == 0) && 2018 (instr->Bit(4) == 0)) { 2019 double dn_value = get_double_from_d_register(vn); 2020 double dm_value = get_double_from_d_register(vm); 2021 double dd_value = dn_value * dm_value; 2022 set_d_register_from_double(vd, dd_value); 2023 } else { 2024 UNIMPLEMENTED(); // Not used by V8. 2025 } 2026 } else { 2027 if ((instr->Bit(20) == 0x0) && 2028 (instr->Bits(11, 8) == 0xA) && 2029 (instr->Bits(6, 5) == 0x0) && 2030 (instr->Bit(4) == 1) && 2031 (instr->Bits(3, 0) == 0x0)) { 2032 int32_t rs_val = get_register(rt); 2033 set_s_register_from_sinteger(((vn<<1) | instr->NField()), rs_val); 2034 } else if ((instr->Bit(20) == 0x1) && 2035 (instr->Bits(11, 8) == 0xA) && 2036 (instr->Bits(6, 5) == 0x0) && 2037 (instr->Bit(4) == 1) && 2038 (instr->Bits(3, 0) == 0x0)) { 2039 int32_t int_value = get_sinteger_from_s_register(((vn<<1) | 2040 instr->NField())); 2041 set_register(rt, int_value); 2042 } else { 2043 UNIMPLEMENTED(); // Not used by V8. 2044 } 2045 } 2046 } 2047 2048 2049 // void Simulator::DecodeType6CoprocessorIns(Instr* instr) 2050 // Decode Type 6 coprocessor instructions. 2051 // Dm = vmov(Rt, Rt2) 2052 // <Rt, Rt2> = vmov(Dm) 2053 // Ddst = MEM(Rbase + 4*offset). 2054 // MEM(Rbase + 4*offset) = Dsrc. 2055 void Simulator::DecodeType6CoprocessorIns(Instr* instr) { 2056 ASSERT((instr->TypeField() == 6)); 2057 2058 if (instr->CoprocessorField() != 0xB) { 2059 UNIMPLEMENTED(); // Not used by V8. 2060 } else { 2061 switch (instr->OpcodeField()) { 2062 case 0x2: 2063 // Load and store double to two GP registers 2064 if (instr->Bits(7, 4) != 0x1) { 2065 UNIMPLEMENTED(); // Not used by V8. 2066 } else { 2067 int rt = instr->RtField(); 2068 int rn = instr->RnField(); 2069 int vm = instr->VmField(); 2070 if (instr->HasL()) { 2071 int32_t rt_int_value = get_sinteger_from_s_register(2*vm); 2072 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1); 2073 2074 set_register(rt, rt_int_value); 2075 set_register(rn, rn_int_value); 2076 } else { 2077 int32_t rs_val = get_register(rt); 2078 int32_t rn_val = get_register(rn); 2079 2080 set_s_register_from_sinteger(2*vm, rs_val); 2081 set_s_register_from_sinteger((2*vm+1), rn_val); 2082 } 2083 } 2084 break; 2085 case 0x8: 2086 case 0xC: { // Load and store double to memory. 2087 int rn = instr->RnField(); 2088 int vd = instr->VdField(); 2089 int offset = instr->Immed8Field(); 2090 if (!instr->HasU()) { 2091 offset = -offset; 2092 } 2093 int32_t address = get_register(rn) + 4 * offset; 2094 if (instr->HasL()) { 2095 // Load double from memory: vldr. 2096 set_s_register_from_sinteger(2*vd, ReadW(address, instr)); 2097 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); 2098 } else { 2099 // Store double to memory: vstr. 2100 WriteW(address, get_sinteger_from_s_register(2*vd), instr); 2101 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); 2102 } 2103 break; 2104 } 2105 default: 2106 UNIMPLEMENTED(); // Not used by V8. 2107 break; 2108 } 2109 } 2110 } 2111 2112 2113 // Executes the current instruction. 2114 void Simulator::InstructionDecode(Instr* instr) { 2115 pc_modified_ = false; 2116 if (::v8::internal::FLAG_trace_sim) { 2117 disasm::NameConverter converter; 2118 disasm::Disassembler dasm(converter); 2119 // use a reasonably large buffer 2120 v8::internal::EmbeddedVector<char, 256> buffer; 2121 dasm.InstructionDecode(buffer, 2122 reinterpret_cast<byte*>(instr)); 2123 PrintF(" 0x%08x %s\n", instr, buffer.start()); 2124 } 2125 if (instr->ConditionField() == special_condition) { 2126 DecodeUnconditional(instr); 2127 } else if (ConditionallyExecute(instr)) { 2128 switch (instr->TypeField()) { 2129 case 0: 2130 case 1: { 2131 DecodeType01(instr); 2132 break; 2133 } 2134 case 2: { 2135 DecodeType2(instr); 2136 break; 2137 } 2138 case 3: { 2139 DecodeType3(instr); 2140 break; 2141 } 2142 case 4: { 2143 DecodeType4(instr); 2144 break; 2145 } 2146 case 5: { 2147 DecodeType5(instr); 2148 break; 2149 } 2150 case 6: { 2151 DecodeType6(instr); 2152 break; 2153 } 2154 case 7: { 2155 DecodeType7(instr); 2156 break; 2157 } 2158 default: { 2159 UNIMPLEMENTED(); 2160 break; 2161 } 2162 } 2163 } 2164 if (!pc_modified_) { 2165 set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); 2166 } 2167 } 2168 2169 2170 void Simulator::Execute() { 2171 // Get the PC to simulate. Cannot use the accessor here as we need the 2172 // raw PC value and not the one used as input to arithmetic instructions. 2173 int program_counter = get_pc(); 2174 2175 if (::v8::internal::FLAG_stop_sim_at == 0) { 2176 // Fast version of the dispatch loop without checking whether the simulator 2177 // should be stopping at a particular executed instruction. 2178 while (program_counter != end_sim_pc) { 2179 Instr* instr = reinterpret_cast<Instr*>(program_counter); 2180 icount_++; 2181 InstructionDecode(instr); 2182 program_counter = get_pc(); 2183 } 2184 } else { 2185 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 2186 // we reach the particular instuction count. 2187 while (program_counter != end_sim_pc) { 2188 Instr* instr = reinterpret_cast<Instr*>(program_counter); 2189 icount_++; 2190 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 2191 Debugger dbg(this); 2192 dbg.Debug(); 2193 } else { 2194 InstructionDecode(instr); 2195 } 2196 program_counter = get_pc(); 2197 } 2198 } 2199 } 2200 2201 2202 int32_t Simulator::Call(byte* entry, int argument_count, ...) { 2203 va_list parameters; 2204 va_start(parameters, argument_count); 2205 // Setup arguments 2206 2207 // First four arguments passed in registers. 2208 ASSERT(argument_count >= 4); 2209 set_register(r0, va_arg(parameters, int32_t)); 2210 set_register(r1, va_arg(parameters, int32_t)); 2211 set_register(r2, va_arg(parameters, int32_t)); 2212 set_register(r3, va_arg(parameters, int32_t)); 2213 2214 // Remaining arguments passed on stack. 2215 int original_stack = get_register(sp); 2216 // Compute position of stack on entry to generated code. 2217 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)); 2218 if (OS::ActivationFrameAlignment() != 0) { 2219 entry_stack &= -OS::ActivationFrameAlignment(); 2220 } 2221 // Store remaining arguments on stack, from low to high memory. 2222 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 2223 for (int i = 4; i < argument_count; i++) { 2224 stack_argument[i - 4] = va_arg(parameters, int32_t); 2225 } 2226 va_end(parameters); 2227 set_register(sp, entry_stack); 2228 2229 // Prepare to execute the code at entry 2230 set_register(pc, reinterpret_cast<int32_t>(entry)); 2231 // Put down marker for end of simulation. The simulator will stop simulation 2232 // when the PC reaches this value. By saving the "end simulation" value into 2233 // the LR the simulation stops when returning to this call point. 2234 set_register(lr, end_sim_pc); 2235 2236 // Remember the values of callee-saved registers. 2237 // The code below assumes that r9 is not used as sb (static base) in 2238 // simulator code and therefore is regarded as a callee-saved register. 2239 int32_t r4_val = get_register(r4); 2240 int32_t r5_val = get_register(r5); 2241 int32_t r6_val = get_register(r6); 2242 int32_t r7_val = get_register(r7); 2243 int32_t r8_val = get_register(r8); 2244 int32_t r9_val = get_register(r9); 2245 int32_t r10_val = get_register(r10); 2246 int32_t r11_val = get_register(r11); 2247 2248 // Setup the callee-saved registers with a known value. To be able to check 2249 // that they are preserved properly across JS execution. 2250 int32_t callee_saved_value = icount_; 2251 set_register(r4, callee_saved_value); 2252 set_register(r5, callee_saved_value); 2253 set_register(r6, callee_saved_value); 2254 set_register(r7, callee_saved_value); 2255 set_register(r8, callee_saved_value); 2256 set_register(r9, callee_saved_value); 2257 set_register(r10, callee_saved_value); 2258 set_register(r11, callee_saved_value); 2259 2260 // Start the simulation 2261 Execute(); 2262 2263 // Check that the callee-saved registers have been preserved. 2264 CHECK_EQ(callee_saved_value, get_register(r4)); 2265 CHECK_EQ(callee_saved_value, get_register(r5)); 2266 CHECK_EQ(callee_saved_value, get_register(r6)); 2267 CHECK_EQ(callee_saved_value, get_register(r7)); 2268 CHECK_EQ(callee_saved_value, get_register(r8)); 2269 CHECK_EQ(callee_saved_value, get_register(r9)); 2270 CHECK_EQ(callee_saved_value, get_register(r10)); 2271 CHECK_EQ(callee_saved_value, get_register(r11)); 2272 2273 // Restore callee-saved registers with the original value. 2274 set_register(r4, r4_val); 2275 set_register(r5, r5_val); 2276 set_register(r6, r6_val); 2277 set_register(r7, r7_val); 2278 set_register(r8, r8_val); 2279 set_register(r9, r9_val); 2280 set_register(r10, r10_val); 2281 set_register(r11, r11_val); 2282 2283 // Pop stack passed arguments. 2284 CHECK_EQ(entry_stack, get_register(sp)); 2285 set_register(sp, original_stack); 2286 2287 int32_t result = get_register(r0); 2288 return result; 2289 } 2290 2291 2292 uintptr_t Simulator::PushAddress(uintptr_t address) { 2293 int new_sp = get_register(sp) - sizeof(uintptr_t); 2294 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 2295 *stack_slot = address; 2296 set_register(sp, new_sp); 2297 return new_sp; 2298 } 2299 2300 2301 uintptr_t Simulator::PopAddress() { 2302 int current_sp = get_register(sp); 2303 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 2304 uintptr_t address = *stack_slot; 2305 set_register(sp, current_sp + sizeof(uintptr_t)); 2306 return address; 2307 } 2308 2309 2310 } } // namespace assembler::arm 2311 2312 #endif // !defined(__arm__) 2313