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