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