1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <limits.h> 6 #include <stdarg.h> 7 #include <stdlib.h> 8 #include <cmath> 9 10 #include "src/v8.h" 11 12 #if V8_TARGET_ARCH_MIPS 13 14 #include "src/assembler.h" 15 #include "src/base/bits.h" 16 #include "src/disasm.h" 17 #include "src/mips/constants-mips.h" 18 #include "src/mips/simulator-mips.h" 19 #include "src/ostreams.h" 20 21 22 // Only build the simulator if not compiling for real MIPS hardware. 23 #if defined(USE_SIMULATOR) 24 25 namespace v8 { 26 namespace internal { 27 28 // Utils functions. 29 bool HaveSameSign(int32_t a, int32_t b) { 30 return ((a ^ b) >= 0); 31 } 32 33 34 uint32_t get_fcsr_condition_bit(uint32_t cc) { 35 if (cc == 0) { 36 return 23; 37 } else { 38 return 24 + cc; 39 } 40 } 41 42 43 // This macro provides a platform independent use of sscanf. The reason for 44 // SScanF not being implemented in a platform independent was through 45 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time 46 // Library does not provide vsscanf. 47 #define SScanF sscanf // NOLINT 48 49 // The MipsDebugger class is used by the simulator while debugging simulated 50 // code. 51 class MipsDebugger { 52 public: 53 explicit MipsDebugger(Simulator* sim) : sim_(sim) { } 54 ~MipsDebugger(); 55 56 void Stop(Instruction* instr); 57 void Debug(); 58 // Print all registers with a nice formatting. 59 void PrintAllRegs(); 60 void PrintAllRegsIncludingFPU(); 61 62 private: 63 // We set the breakpoint code to 0xfffff to easily recognize it. 64 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; 65 static const Instr kNopInstr = 0x0; 66 67 Simulator* sim_; 68 69 int32_t GetRegisterValue(int regnum); 70 int32_t GetFPURegisterValue32(int regnum); 71 int64_t GetFPURegisterValue64(int regnum); 72 float GetFPURegisterValueFloat(int regnum); 73 double GetFPURegisterValueDouble(int regnum); 74 bool GetValue(const char* desc, int32_t* value); 75 bool GetValue(const char* desc, int64_t* value); 76 77 // Set or delete a breakpoint. Returns true if successful. 78 bool SetBreakpoint(Instruction* breakpc); 79 bool DeleteBreakpoint(Instruction* breakpc); 80 81 // Undo and redo all breakpoints. This is needed to bracket disassembly and 82 // execution to skip past breakpoints when run from the debugger. 83 void UndoBreakpoints(); 84 void RedoBreakpoints(); 85 }; 86 87 88 MipsDebugger::~MipsDebugger() { 89 } 90 91 92 #ifdef GENERATED_CODE_COVERAGE 93 static FILE* coverage_log = NULL; 94 95 96 static void InitializeCoverage() { 97 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 98 if (file_name != NULL) { 99 coverage_log = fopen(file_name, "aw+"); 100 } 101 } 102 103 104 void MipsDebugger::Stop(Instruction* instr) { 105 // Get the stop code. 106 uint32_t code = instr->Bits(25, 6); 107 // Retrieve the encoded address, which comes just after this stop. 108 char** msg_address = 109 reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); 110 char* msg = *msg_address; 111 DCHECK(msg != NULL); 112 113 // Update this stop description. 114 if (!watched_stops_[code].desc) { 115 watched_stops_[code].desc = msg; 116 } 117 118 if (strlen(msg) > 0) { 119 if (coverage_log != NULL) { 120 fprintf(coverage_log, "%s\n", str); 121 fflush(coverage_log); 122 } 123 // Overwrite the instruction and address with nops. 124 instr->SetInstructionBits(kNopInstr); 125 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); 126 } 127 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize); 128 } 129 130 131 #else // GENERATED_CODE_COVERAGE 132 133 #define UNSUPPORTED() printf("Unsupported instruction.\n"); 134 135 static void InitializeCoverage() {} 136 137 138 void MipsDebugger::Stop(Instruction* instr) { 139 // Get the stop code. 140 uint32_t code = instr->Bits(25, 6); 141 // Retrieve the encoded address, which comes just after this stop. 142 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + 143 Instruction::kInstrSize); 144 // Update this stop description. 145 if (!sim_->watched_stops_[code].desc) { 146 sim_->watched_stops_[code].desc = msg; 147 } 148 PrintF("Simulator hit %s (%u)\n", msg, code); 149 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 150 Debug(); 151 } 152 #endif // GENERATED_CODE_COVERAGE 153 154 155 int32_t MipsDebugger::GetRegisterValue(int regnum) { 156 if (regnum == kNumSimuRegisters) { 157 return sim_->get_pc(); 158 } else { 159 return sim_->get_register(regnum); 160 } 161 } 162 163 164 int32_t MipsDebugger::GetFPURegisterValue32(int regnum) { 165 if (regnum == kNumFPURegisters) { 166 return sim_->get_pc(); 167 } else { 168 return sim_->get_fpu_register_word(regnum); 169 } 170 } 171 172 173 int64_t MipsDebugger::GetFPURegisterValue64(int regnum) { 174 if (regnum == kNumFPURegisters) { 175 return sim_->get_pc(); 176 } else { 177 return sim_->get_fpu_register(regnum); 178 } 179 } 180 181 182 float MipsDebugger::GetFPURegisterValueFloat(int regnum) { 183 if (regnum == kNumFPURegisters) { 184 return sim_->get_pc(); 185 } else { 186 return sim_->get_fpu_register_float(regnum); 187 } 188 } 189 190 191 double MipsDebugger::GetFPURegisterValueDouble(int regnum) { 192 if (regnum == kNumFPURegisters) { 193 return sim_->get_pc(); 194 } else { 195 return sim_->get_fpu_register_double(regnum); 196 } 197 } 198 199 200 bool MipsDebugger::GetValue(const char* desc, int32_t* value) { 201 int regnum = Registers::Number(desc); 202 int fpuregnum = FPURegisters::Number(desc); 203 204 if (regnum != kInvalidRegister) { 205 *value = GetRegisterValue(regnum); 206 return true; 207 } else if (fpuregnum != kInvalidFPURegister) { 208 *value = GetFPURegisterValue32(fpuregnum); 209 return true; 210 } else if (strncmp(desc, "0x", 2) == 0) { 211 return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1; 212 } else { 213 return SScanF(desc, "%i", value) == 1; 214 } 215 return false; 216 } 217 218 219 bool MipsDebugger::GetValue(const char* desc, int64_t* value) { 220 int regnum = Registers::Number(desc); 221 int fpuregnum = FPURegisters::Number(desc); 222 223 if (regnum != kInvalidRegister) { 224 *value = GetRegisterValue(regnum); 225 return true; 226 } else if (fpuregnum != kInvalidFPURegister) { 227 *value = GetFPURegisterValue64(fpuregnum); 228 return true; 229 } else if (strncmp(desc, "0x", 2) == 0) { 230 return SScanF(desc + 2, "%" SCNx64, 231 reinterpret_cast<uint64_t*>(value)) == 1; 232 } else { 233 return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1; 234 } 235 return false; 236 } 237 238 239 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) { 240 // Check if a breakpoint can be set. If not return without any side-effects. 241 if (sim_->break_pc_ != NULL) { 242 return false; 243 } 244 245 // Set the breakpoint. 246 sim_->break_pc_ = breakpc; 247 sim_->break_instr_ = breakpc->InstructionBits(); 248 // Not setting the breakpoint instruction in the code itself. It will be set 249 // when the debugger shell continues. 250 return true; 251 } 252 253 254 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) { 255 if (sim_->break_pc_ != NULL) { 256 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 257 } 258 259 sim_->break_pc_ = NULL; 260 sim_->break_instr_ = 0; 261 return true; 262 } 263 264 265 void MipsDebugger::UndoBreakpoints() { 266 if (sim_->break_pc_ != NULL) { 267 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 268 } 269 } 270 271 272 void MipsDebugger::RedoBreakpoints() { 273 if (sim_->break_pc_ != NULL) { 274 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 275 } 276 } 277 278 279 void MipsDebugger::PrintAllRegs() { 280 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 281 282 PrintF("\n"); 283 // at, v0, a0. 284 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 285 REG_INFO(1), REG_INFO(2), REG_INFO(4)); 286 // v1, a1. 287 PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 288 "", REG_INFO(3), REG_INFO(5)); 289 // a2. 290 PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6)); 291 // a3. 292 PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7)); 293 PrintF("\n"); 294 // t0-t7, s0-s7 295 for (int i = 0; i < 8; i++) { 296 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 297 REG_INFO(8+i), REG_INFO(16+i)); 298 } 299 PrintF("\n"); 300 // t8, k0, LO. 301 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 302 REG_INFO(24), REG_INFO(26), REG_INFO(32)); 303 // t9, k1, HI. 304 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 305 REG_INFO(25), REG_INFO(27), REG_INFO(33)); 306 // sp, fp, gp. 307 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 308 REG_INFO(29), REG_INFO(30), REG_INFO(28)); 309 // pc. 310 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 311 REG_INFO(31), REG_INFO(34)); 312 313 #undef REG_INFO 314 #undef FPU_REG_INFO 315 } 316 317 318 void MipsDebugger::PrintAllRegsIncludingFPU() { 319 #define FPU_REG_INFO32(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \ 320 GetFPURegisterValue32(n+1), \ 321 GetFPURegisterValue32(n), \ 322 GetFPURegisterValueDouble(n) 323 324 #define FPU_REG_INFO64(n) FPURegisters::Name(n), \ 325 GetFPURegisterValue64(n), \ 326 GetFPURegisterValueDouble(n) 327 328 PrintAllRegs(); 329 330 PrintF("\n\n"); 331 // f0, f1, f2, ... f31. 332 // This must be a compile-time switch, 333 // compiler will throw out warnings otherwise. 334 if (kFpuMode == kFP64) { 335 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(0) ); 336 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(1) ); 337 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(2) ); 338 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(3) ); 339 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(4) ); 340 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(5) ); 341 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(6) ); 342 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(7) ); 343 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(8) ); 344 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(9) ); 345 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(10)); 346 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(11)); 347 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(12)); 348 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(13)); 349 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(14)); 350 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(15)); 351 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(16)); 352 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(17)); 353 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(18)); 354 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(19)); 355 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(20)); 356 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(21)); 357 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(22)); 358 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(23)); 359 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(24)); 360 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(25)); 361 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(26)); 362 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(27)); 363 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(28)); 364 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(29)); 365 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(30)); 366 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(31)); 367 } else { 368 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(0) ); 369 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(2) ); 370 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(4) ); 371 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(6) ); 372 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(8) ); 373 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(10)); 374 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(12)); 375 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(14)); 376 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(16)); 377 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(18)); 378 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(20)); 379 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(22)); 380 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(24)); 381 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(26)); 382 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(28)); 383 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(30)); 384 } 385 386 #undef REG_INFO 387 #undef FPU_REG_INFO32 388 #undef FPU_REG_INFO64 389 } 390 391 392 void MipsDebugger::Debug() { 393 intptr_t last_pc = -1; 394 bool done = false; 395 396 #define COMMAND_SIZE 63 397 #define ARG_SIZE 255 398 399 #define STR(a) #a 400 #define XSTR(a) STR(a) 401 402 char cmd[COMMAND_SIZE + 1]; 403 char arg1[ARG_SIZE + 1]; 404 char arg2[ARG_SIZE + 1]; 405 char* argv[3] = { cmd, arg1, arg2 }; 406 407 // Make sure to have a proper terminating character if reaching the limit. 408 cmd[COMMAND_SIZE] = 0; 409 arg1[ARG_SIZE] = 0; 410 arg2[ARG_SIZE] = 0; 411 412 // Undo all set breakpoints while running in the debugger shell. This will 413 // make them invisible to all commands. 414 UndoBreakpoints(); 415 416 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) { 417 if (last_pc != sim_->get_pc()) { 418 disasm::NameConverter converter; 419 disasm::Disassembler dasm(converter); 420 // Use a reasonably large buffer. 421 v8::internal::EmbeddedVector<char, 256> buffer; 422 dasm.InstructionDecode(buffer, 423 reinterpret_cast<byte*>(sim_->get_pc())); 424 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start()); 425 last_pc = sim_->get_pc(); 426 } 427 char* line = ReadLine("sim> "); 428 if (line == NULL) { 429 break; 430 } else { 431 char* last_input = sim_->last_debugger_input(); 432 if (strcmp(line, "\n") == 0 && last_input != NULL) { 433 line = last_input; 434 } else { 435 // Ownership is transferred to sim_; 436 sim_->set_last_debugger_input(line); 437 } 438 // Use sscanf to parse the individual parts of the command line. At the 439 // moment no command expects more than two parameters. 440 int argc = SScanF(line, 441 "%" XSTR(COMMAND_SIZE) "s " 442 "%" XSTR(ARG_SIZE) "s " 443 "%" XSTR(ARG_SIZE) "s", 444 cmd, arg1, arg2); 445 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 446 Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc()); 447 if (!(instr->IsTrap()) || 448 instr->InstructionBits() == rtCallRedirInstr) { 449 sim_->InstructionDecode( 450 reinterpret_cast<Instruction*>(sim_->get_pc())); 451 } else { 452 // Allow si to jump over generated breakpoints. 453 PrintF("/!\\ Jumping over generated breakpoint.\n"); 454 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); 455 } 456 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 457 // Execute the one instruction we broke at with breakpoints disabled. 458 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 459 // Leave the debugger shell. 460 done = true; 461 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 462 if (argc == 2) { 463 if (strcmp(arg1, "all") == 0) { 464 PrintAllRegs(); 465 } else if (strcmp(arg1, "allf") == 0) { 466 PrintAllRegsIncludingFPU(); 467 } else { 468 int regnum = Registers::Number(arg1); 469 int fpuregnum = FPURegisters::Number(arg1); 470 471 if (regnum != kInvalidRegister) { 472 int32_t value; 473 value = GetRegisterValue(regnum); 474 PrintF("%s: 0x%08x %d \n", arg1, value, value); 475 } else if (fpuregnum != kInvalidFPURegister) { 476 if (IsFp64Mode()) { 477 int64_t value; 478 double dvalue; 479 value = GetFPURegisterValue64(fpuregnum); 480 dvalue = GetFPURegisterValueDouble(fpuregnum); 481 PrintF("%3s: 0x%016llx %16.4e\n", 482 FPURegisters::Name(fpuregnum), value, dvalue); 483 } else { 484 if (fpuregnum % 2 == 1) { 485 int32_t value; 486 float fvalue; 487 value = GetFPURegisterValue32(fpuregnum); 488 fvalue = GetFPURegisterValueFloat(fpuregnum); 489 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); 490 } else { 491 double dfvalue; 492 int32_t lvalue1 = GetFPURegisterValue32(fpuregnum); 493 int32_t lvalue2 = GetFPURegisterValue32(fpuregnum + 1); 494 dfvalue = GetFPURegisterValueDouble(fpuregnum); 495 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", 496 FPURegisters::Name(fpuregnum+1), 497 FPURegisters::Name(fpuregnum), 498 lvalue1, 499 lvalue2, 500 dfvalue); 501 } 502 } 503 } else { 504 PrintF("%s unrecognized\n", arg1); 505 } 506 } 507 } else { 508 if (argc == 3) { 509 if (strcmp(arg2, "single") == 0) { 510 int32_t value; 511 float fvalue; 512 int fpuregnum = FPURegisters::Number(arg1); 513 514 if (fpuregnum != kInvalidFPURegister) { 515 value = GetFPURegisterValue32(fpuregnum); 516 fvalue = GetFPURegisterValueFloat(fpuregnum); 517 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); 518 } else { 519 PrintF("%s unrecognized\n", arg1); 520 } 521 } else { 522 PrintF("print <fpu register> single\n"); 523 } 524 } else { 525 PrintF("print <register> or print <fpu register> single\n"); 526 } 527 } 528 } else if ((strcmp(cmd, "po") == 0) 529 || (strcmp(cmd, "printobject") == 0)) { 530 if (argc == 2) { 531 int32_t value; 532 OFStream os(stdout); 533 if (GetValue(arg1, &value)) { 534 Object* obj = reinterpret_cast<Object*>(value); 535 os << arg1 << ": \n"; 536 #ifdef DEBUG 537 obj->Print(os); 538 os << "\n"; 539 #else 540 os << Brief(obj) << "\n"; 541 #endif 542 } else { 543 os << arg1 << " unrecognized\n"; 544 } 545 } else { 546 PrintF("printobject <value>\n"); 547 } 548 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 549 int32_t* cur = NULL; 550 int32_t* end = NULL; 551 int next_arg = 1; 552 553 if (strcmp(cmd, "stack") == 0) { 554 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp)); 555 } else { // Command "mem". 556 int32_t value; 557 if (!GetValue(arg1, &value)) { 558 PrintF("%s unrecognized\n", arg1); 559 continue; 560 } 561 cur = reinterpret_cast<int32_t*>(value); 562 next_arg++; 563 } 564 565 // TODO(palfia): optimize this. 566 if (IsFp64Mode()) { 567 int64_t words; 568 if (argc == next_arg) { 569 words = 10; 570 } else { 571 if (!GetValue(argv[next_arg], &words)) { 572 words = 10; 573 } 574 } 575 end = cur + words; 576 } else { 577 int32_t words; 578 if (argc == next_arg) { 579 words = 10; 580 } else { 581 if (!GetValue(argv[next_arg], &words)) { 582 words = 10; 583 } 584 } 585 end = cur + words; 586 } 587 588 while (cur < end) { 589 PrintF(" 0x%08x: 0x%08x %10d", 590 reinterpret_cast<intptr_t>(cur), *cur, *cur); 591 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 592 int value = *cur; 593 Heap* current_heap = v8::internal::Isolate::Current()->heap(); 594 if (((value & 1) == 0) || current_heap->Contains(obj)) { 595 PrintF(" ("); 596 if ((value & 1) == 0) { 597 PrintF("smi %d", value / 2); 598 } else { 599 obj->ShortPrint(); 600 } 601 PrintF(")"); 602 } 603 PrintF("\n"); 604 cur++; 605 } 606 607 } else if ((strcmp(cmd, "disasm") == 0) || 608 (strcmp(cmd, "dpc") == 0) || 609 (strcmp(cmd, "di") == 0)) { 610 disasm::NameConverter converter; 611 disasm::Disassembler dasm(converter); 612 // Use a reasonably large buffer. 613 v8::internal::EmbeddedVector<char, 256> buffer; 614 615 byte* cur = NULL; 616 byte* end = NULL; 617 618 if (argc == 1) { 619 cur = reinterpret_cast<byte*>(sim_->get_pc()); 620 end = cur + (10 * Instruction::kInstrSize); 621 } else if (argc == 2) { 622 int regnum = Registers::Number(arg1); 623 if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) { 624 // The argument is an address or a register name. 625 int32_t value; 626 if (GetValue(arg1, &value)) { 627 cur = reinterpret_cast<byte*>(value); 628 // Disassemble 10 instructions at <arg1>. 629 end = cur + (10 * Instruction::kInstrSize); 630 } 631 } else { 632 // The argument is the number of instructions. 633 int32_t value; 634 if (GetValue(arg1, &value)) { 635 cur = reinterpret_cast<byte*>(sim_->get_pc()); 636 // Disassemble <arg1> instructions. 637 end = cur + (value * Instruction::kInstrSize); 638 } 639 } 640 } else { 641 int32_t value1; 642 int32_t value2; 643 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 644 cur = reinterpret_cast<byte*>(value1); 645 end = cur + (value2 * Instruction::kInstrSize); 646 } 647 } 648 649 while (cur < end) { 650 dasm.InstructionDecode(buffer, cur); 651 PrintF(" 0x%08x %s\n", 652 reinterpret_cast<intptr_t>(cur), buffer.start()); 653 cur += Instruction::kInstrSize; 654 } 655 } else if (strcmp(cmd, "gdb") == 0) { 656 PrintF("relinquishing control to gdb\n"); 657 v8::base::OS::DebugBreak(); 658 PrintF("regaining control from gdb\n"); 659 } else if (strcmp(cmd, "break") == 0) { 660 if (argc == 2) { 661 int32_t value; 662 if (GetValue(arg1, &value)) { 663 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 664 PrintF("setting breakpoint failed\n"); 665 } 666 } else { 667 PrintF("%s unrecognized\n", arg1); 668 } 669 } else { 670 PrintF("break <address>\n"); 671 } 672 } else if (strcmp(cmd, "del") == 0) { 673 if (!DeleteBreakpoint(NULL)) { 674 PrintF("deleting breakpoint failed\n"); 675 } 676 } else if (strcmp(cmd, "flags") == 0) { 677 PrintF("No flags on MIPS !\n"); 678 } else if (strcmp(cmd, "stop") == 0) { 679 int32_t value; 680 intptr_t stop_pc = sim_->get_pc() - 681 2 * Instruction::kInstrSize; 682 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 683 Instruction* msg_address = 684 reinterpret_cast<Instruction*>(stop_pc + 685 Instruction::kInstrSize); 686 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 687 // Remove the current stop. 688 if (sim_->IsStopInstruction(stop_instr)) { 689 stop_instr->SetInstructionBits(kNopInstr); 690 msg_address->SetInstructionBits(kNopInstr); 691 } else { 692 PrintF("Not at debugger stop.\n"); 693 } 694 } else if (argc == 3) { 695 // Print information about all/the specified breakpoint(s). 696 if (strcmp(arg1, "info") == 0) { 697 if (strcmp(arg2, "all") == 0) { 698 PrintF("Stop information:\n"); 699 for (uint32_t i = kMaxWatchpointCode + 1; 700 i <= kMaxStopCode; 701 i++) { 702 sim_->PrintStopInfo(i); 703 } 704 } else if (GetValue(arg2, &value)) { 705 sim_->PrintStopInfo(value); 706 } else { 707 PrintF("Unrecognized argument.\n"); 708 } 709 } else if (strcmp(arg1, "enable") == 0) { 710 // Enable all/the specified breakpoint(s). 711 if (strcmp(arg2, "all") == 0) { 712 for (uint32_t i = kMaxWatchpointCode + 1; 713 i <= kMaxStopCode; 714 i++) { 715 sim_->EnableStop(i); 716 } 717 } else if (GetValue(arg2, &value)) { 718 sim_->EnableStop(value); 719 } else { 720 PrintF("Unrecognized argument.\n"); 721 } 722 } else if (strcmp(arg1, "disable") == 0) { 723 // Disable all/the specified breakpoint(s). 724 if (strcmp(arg2, "all") == 0) { 725 for (uint32_t i = kMaxWatchpointCode + 1; 726 i <= kMaxStopCode; 727 i++) { 728 sim_->DisableStop(i); 729 } 730 } else if (GetValue(arg2, &value)) { 731 sim_->DisableStop(value); 732 } else { 733 PrintF("Unrecognized argument.\n"); 734 } 735 } 736 } else { 737 PrintF("Wrong usage. Use help command for more information.\n"); 738 } 739 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { 740 // Print registers and disassemble. 741 PrintAllRegs(); 742 PrintF("\n"); 743 744 disasm::NameConverter converter; 745 disasm::Disassembler dasm(converter); 746 // Use a reasonably large buffer. 747 v8::internal::EmbeddedVector<char, 256> buffer; 748 749 byte* cur = NULL; 750 byte* end = NULL; 751 752 if (argc == 1) { 753 cur = reinterpret_cast<byte*>(sim_->get_pc()); 754 end = cur + (10 * Instruction::kInstrSize); 755 } else if (argc == 2) { 756 int32_t value; 757 if (GetValue(arg1, &value)) { 758 cur = reinterpret_cast<byte*>(value); 759 // no length parameter passed, assume 10 instructions 760 end = cur + (10 * Instruction::kInstrSize); 761 } 762 } else { 763 int32_t value1; 764 int32_t value2; 765 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 766 cur = reinterpret_cast<byte*>(value1); 767 end = cur + (value2 * Instruction::kInstrSize); 768 } 769 } 770 771 while (cur < end) { 772 dasm.InstructionDecode(buffer, cur); 773 PrintF(" 0x%08x %s\n", 774 reinterpret_cast<intptr_t>(cur), buffer.start()); 775 cur += Instruction::kInstrSize; 776 } 777 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 778 PrintF("cont\n"); 779 PrintF(" continue execution (alias 'c')\n"); 780 PrintF("stepi\n"); 781 PrintF(" step one instruction (alias 'si')\n"); 782 PrintF("print <register>\n"); 783 PrintF(" print register content (alias 'p')\n"); 784 PrintF(" use register name 'all' to print all registers\n"); 785 PrintF("printobject <register>\n"); 786 PrintF(" print an object from a register (alias 'po')\n"); 787 PrintF("stack [<words>]\n"); 788 PrintF(" dump stack content, default dump 10 words)\n"); 789 PrintF("mem <address> [<words>]\n"); 790 PrintF(" dump memory content, default dump 10 words)\n"); 791 PrintF("flags\n"); 792 PrintF(" print flags\n"); 793 PrintF("disasm [<instructions>]\n"); 794 PrintF("disasm [<address/register>]\n"); 795 PrintF("disasm [[<address/register>] <instructions>]\n"); 796 PrintF(" disassemble code, default is 10 instructions\n"); 797 PrintF(" from pc (alias 'di')\n"); 798 PrintF("gdb\n"); 799 PrintF(" enter gdb\n"); 800 PrintF("break <address>\n"); 801 PrintF(" set a break point on the address\n"); 802 PrintF("del\n"); 803 PrintF(" delete the breakpoint\n"); 804 PrintF("stop feature:\n"); 805 PrintF(" Description:\n"); 806 PrintF(" Stops are debug instructions inserted by\n"); 807 PrintF(" the Assembler::stop() function.\n"); 808 PrintF(" When hitting a stop, the Simulator will\n"); 809 PrintF(" stop and and give control to the Debugger.\n"); 810 PrintF(" All stop codes are watched:\n"); 811 PrintF(" - They can be enabled / disabled: the Simulator\n"); 812 PrintF(" will / won't stop when hitting them.\n"); 813 PrintF(" - The Simulator keeps track of how many times they \n"); 814 PrintF(" are met. (See the info command.) Going over a\n"); 815 PrintF(" disabled stop still increases its counter. \n"); 816 PrintF(" Commands:\n"); 817 PrintF(" stop info all/<code> : print infos about number <code>\n"); 818 PrintF(" or all stop(s).\n"); 819 PrintF(" stop enable/disable all/<code> : enables / disables\n"); 820 PrintF(" all or number <code> stop(s)\n"); 821 PrintF(" stop unstop\n"); 822 PrintF(" ignore the stop instruction at the current location\n"); 823 PrintF(" from now on\n"); 824 } else { 825 PrintF("Unknown command: %s\n", cmd); 826 } 827 } 828 } 829 830 // Add all the breakpoints back to stop execution and enter the debugger 831 // shell when hit. 832 RedoBreakpoints(); 833 834 #undef COMMAND_SIZE 835 #undef ARG_SIZE 836 837 #undef STR 838 #undef XSTR 839 } 840 841 842 static bool ICacheMatch(void* one, void* two) { 843 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); 844 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); 845 return one == two; 846 } 847 848 849 static uint32_t ICacheHash(void* key) { 850 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 851 } 852 853 854 static bool AllOnOnePage(uintptr_t start, int size) { 855 intptr_t start_page = (start & ~CachePage::kPageMask); 856 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 857 return start_page == end_page; 858 } 859 860 861 void Simulator::set_last_debugger_input(char* input) { 862 DeleteArray(last_debugger_input_); 863 last_debugger_input_ = input; 864 } 865 866 867 void Simulator::FlushICache(v8::internal::HashMap* i_cache, 868 void* start_addr, 869 size_t size) { 870 intptr_t start = reinterpret_cast<intptr_t>(start_addr); 871 int intra_line = (start & CachePage::kLineMask); 872 start -= intra_line; 873 size += intra_line; 874 size = ((size - 1) | CachePage::kLineMask) + 1; 875 int offset = (start & CachePage::kPageMask); 876 while (!AllOnOnePage(start, size - 1)) { 877 int bytes_to_flush = CachePage::kPageSize - offset; 878 FlushOnePage(i_cache, start, bytes_to_flush); 879 start += bytes_to_flush; 880 size -= bytes_to_flush; 881 DCHECK_EQ(0, start & CachePage::kPageMask); 882 offset = 0; 883 } 884 if (size != 0) { 885 FlushOnePage(i_cache, start, size); 886 } 887 } 888 889 890 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) { 891 v8::internal::HashMap::Entry* entry = i_cache->Lookup(page, 892 ICacheHash(page), 893 true); 894 if (entry->value == NULL) { 895 CachePage* new_page = new CachePage(); 896 entry->value = new_page; 897 } 898 return reinterpret_cast<CachePage*>(entry->value); 899 } 900 901 902 // Flush from start up to and not including start + size. 903 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, 904 intptr_t start, 905 int size) { 906 DCHECK(size <= CachePage::kPageSize); 907 DCHECK(AllOnOnePage(start, size - 1)); 908 DCHECK((start & CachePage::kLineMask) == 0); 909 DCHECK((size & CachePage::kLineMask) == 0); 910 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 911 int offset = (start & CachePage::kPageMask); 912 CachePage* cache_page = GetCachePage(i_cache, page); 913 char* valid_bytemap = cache_page->ValidityByte(offset); 914 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 915 } 916 917 918 void Simulator::CheckICache(v8::internal::HashMap* i_cache, 919 Instruction* instr) { 920 intptr_t address = reinterpret_cast<intptr_t>(instr); 921 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 922 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 923 int offset = (address & CachePage::kPageMask); 924 CachePage* cache_page = GetCachePage(i_cache, page); 925 char* cache_valid_byte = cache_page->ValidityByte(offset); 926 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 927 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 928 if (cache_hit) { 929 // Check that the data in memory matches the contents of the I-cache. 930 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr), 931 cache_page->CachedData(offset), 932 Instruction::kInstrSize)); 933 } else { 934 // Cache miss. Load memory into the cache. 935 memcpy(cached_line, line, CachePage::kLineLength); 936 *cache_valid_byte = CachePage::LINE_VALID; 937 } 938 } 939 940 941 void Simulator::Initialize(Isolate* isolate) { 942 if (isolate->simulator_initialized()) return; 943 isolate->set_simulator_initialized(true); 944 ::v8::internal::ExternalReference::set_redirector(isolate, 945 &RedirectExternalReference); 946 } 947 948 949 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { 950 i_cache_ = isolate_->simulator_i_cache(); 951 if (i_cache_ == NULL) { 952 i_cache_ = new v8::internal::HashMap(&ICacheMatch); 953 isolate_->set_simulator_i_cache(i_cache_); 954 } 955 Initialize(isolate); 956 // Set up simulator support first. Some of this information is needed to 957 // setup the architecture state. 958 stack_ = reinterpret_cast<char*>(malloc(stack_size_)); 959 pc_modified_ = false; 960 icount_ = 0; 961 break_count_ = 0; 962 break_pc_ = NULL; 963 break_instr_ = 0; 964 965 // Set up architecture state. 966 // All registers are initialized to zero to start with. 967 for (int i = 0; i < kNumSimuRegisters; i++) { 968 registers_[i] = 0; 969 } 970 for (int i = 0; i < kNumFPURegisters; i++) { 971 FPUregisters_[i] = 0; 972 } 973 FCSR_ = 0; 974 975 // The sp is initialized to point to the bottom (high address) of the 976 // allocated stack area. To be safe in potential stack underflows we leave 977 // some buffer below. 978 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64; 979 // The ra and pc are initialized to a known bad value that will cause an 980 // access violation if the simulator ever tries to execute it. 981 registers_[pc] = bad_ra; 982 registers_[ra] = bad_ra; 983 InitializeCoverage(); 984 for (int i = 0; i < kNumExceptions; i++) { 985 exceptions[i] = 0; 986 } 987 988 last_debugger_input_ = NULL; 989 } 990 991 992 Simulator::~Simulator() { 993 } 994 995 996 // When the generated code calls an external reference we need to catch that in 997 // the simulator. The external reference will be a function compiled for the 998 // host architecture. We need to call that function instead of trying to 999 // execute it with the simulator. We do that by redirecting the external 1000 // reference to a swi (software-interrupt) instruction that is handled by 1001 // the simulator. We write the original destination of the jump just at a known 1002 // offset from the swi instruction so the simulator knows what to call. 1003 class Redirection { 1004 public: 1005 Redirection(void* external_function, ExternalReference::Type type) 1006 : external_function_(external_function), 1007 swi_instruction_(rtCallRedirInstr), 1008 type_(type), 1009 next_(NULL) { 1010 Isolate* isolate = Isolate::Current(); 1011 next_ = isolate->simulator_redirection(); 1012 Simulator::current(isolate)-> 1013 FlushICache(isolate->simulator_i_cache(), 1014 reinterpret_cast<void*>(&swi_instruction_), 1015 Instruction::kInstrSize); 1016 isolate->set_simulator_redirection(this); 1017 } 1018 1019 void* address_of_swi_instruction() { 1020 return reinterpret_cast<void*>(&swi_instruction_); 1021 } 1022 1023 void* external_function() { return external_function_; } 1024 ExternalReference::Type type() { return type_; } 1025 1026 static Redirection* Get(void* external_function, 1027 ExternalReference::Type type) { 1028 Isolate* isolate = Isolate::Current(); 1029 Redirection* current = isolate->simulator_redirection(); 1030 for (; current != NULL; current = current->next_) { 1031 if (current->external_function_ == external_function) return current; 1032 } 1033 return new Redirection(external_function, type); 1034 } 1035 1036 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 1037 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 1038 char* addr_of_redirection = 1039 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 1040 return reinterpret_cast<Redirection*>(addr_of_redirection); 1041 } 1042 1043 static void* ReverseRedirection(int32_t reg) { 1044 Redirection* redirection = FromSwiInstruction( 1045 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg))); 1046 return redirection->external_function(); 1047 } 1048 1049 private: 1050 void* external_function_; 1051 uint32_t swi_instruction_; 1052 ExternalReference::Type type_; 1053 Redirection* next_; 1054 }; 1055 1056 1057 void* Simulator::RedirectExternalReference(void* external_function, 1058 ExternalReference::Type type) { 1059 Redirection* redirection = Redirection::Get(external_function, type); 1060 return redirection->address_of_swi_instruction(); 1061 } 1062 1063 1064 // Get the active Simulator for the current thread. 1065 Simulator* Simulator::current(Isolate* isolate) { 1066 v8::internal::Isolate::PerIsolateThreadData* isolate_data = 1067 isolate->FindOrAllocatePerThreadDataForThisThread(); 1068 DCHECK(isolate_data != NULL); 1069 DCHECK(isolate_data != NULL); 1070 1071 Simulator* sim = isolate_data->simulator(); 1072 if (sim == NULL) { 1073 // TODO(146): delete the simulator object when a thread/isolate goes away. 1074 sim = new Simulator(isolate); 1075 isolate_data->set_simulator(sim); 1076 } 1077 return sim; 1078 } 1079 1080 1081 // Sets the register in the architecture state. It will also deal with updating 1082 // Simulator internal state for special registers such as PC. 1083 void Simulator::set_register(int reg, int32_t value) { 1084 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 1085 if (reg == pc) { 1086 pc_modified_ = true; 1087 } 1088 1089 // Zero register always holds 0. 1090 registers_[reg] = (reg == 0) ? 0 : value; 1091 } 1092 1093 1094 void Simulator::set_dw_register(int reg, const int* dbl) { 1095 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 1096 registers_[reg] = dbl[0]; 1097 registers_[reg + 1] = dbl[1]; 1098 } 1099 1100 1101 void Simulator::set_fpu_register(int fpureg, int64_t value) { 1102 DCHECK(IsFp64Mode()); 1103 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1104 FPUregisters_[fpureg] = value; 1105 } 1106 1107 1108 void Simulator::set_fpu_register_word(int fpureg, int32_t value) { 1109 // Set ONLY lower 32-bits, leaving upper bits untouched. 1110 // TODO(plind): big endian issue. 1111 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1112 int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]); 1113 *pword = value; 1114 } 1115 1116 1117 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) { 1118 // Set ONLY upper 32-bits, leaving lower bits untouched. 1119 // TODO(plind): big endian issue. 1120 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1121 int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1; 1122 *phiword = value; 1123 } 1124 1125 1126 void Simulator::set_fpu_register_float(int fpureg, float value) { 1127 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1128 *bit_cast<float*>(&FPUregisters_[fpureg]) = value; 1129 } 1130 1131 1132 void Simulator::set_fpu_register_double(int fpureg, double value) { 1133 if (IsFp64Mode()) { 1134 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1135 *bit_cast<double*>(&FPUregisters_[fpureg]) = value; 1136 } else { 1137 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 1138 int64_t i64 = bit_cast<int64_t>(value); 1139 set_fpu_register_word(fpureg, i64 & 0xffffffff); 1140 set_fpu_register_word(fpureg + 1, i64 >> 32); 1141 } 1142 } 1143 1144 1145 // Get the register from the architecture state. This function does handle 1146 // the special case of accessing the PC register. 1147 int32_t Simulator::get_register(int reg) const { 1148 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 1149 if (reg == 0) 1150 return 0; 1151 else 1152 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 1153 } 1154 1155 1156 double Simulator::get_double_from_register_pair(int reg) { 1157 // TODO(plind): bad ABI stuff, refactor or remove. 1158 DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0)); 1159 1160 double dm_val = 0.0; 1161 // Read the bits from the unsigned integer register_[] array 1162 // into the double precision floating point value and return it. 1163 char buffer[2 * sizeof(registers_[0])]; 1164 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); 1165 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); 1166 return(dm_val); 1167 } 1168 1169 1170 int64_t Simulator::get_fpu_register(int fpureg) const { 1171 DCHECK(IsFp64Mode()); 1172 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1173 return FPUregisters_[fpureg]; 1174 } 1175 1176 1177 int32_t Simulator::get_fpu_register_word(int fpureg) const { 1178 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1179 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); 1180 } 1181 1182 1183 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const { 1184 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1185 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); 1186 } 1187 1188 1189 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const { 1190 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1191 return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff); 1192 } 1193 1194 1195 float Simulator::get_fpu_register_float(int fpureg) const { 1196 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1197 return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg])); 1198 } 1199 1200 1201 double Simulator::get_fpu_register_double(int fpureg) const { 1202 if (IsFp64Mode()) { 1203 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1204 return *bit_cast<double*>(&FPUregisters_[fpureg]); 1205 } else { 1206 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 1207 int64_t i64; 1208 i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg)); 1209 i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32; 1210 return bit_cast<double>(i64); 1211 } 1212 } 1213 1214 1215 // Runtime FP routines take up to two double arguments and zero 1216 // or one integer arguments. All are constructed here, 1217 // from a0-a3 or f12 and f14. 1218 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { 1219 if (!IsMipsSoftFloatABI) { 1220 *x = get_fpu_register_double(12); 1221 *y = get_fpu_register_double(14); 1222 *z = get_register(a2); 1223 } else { 1224 // TODO(plind): bad ABI stuff, refactor or remove. 1225 // We use a char buffer to get around the strict-aliasing rules which 1226 // otherwise allow the compiler to optimize away the copy. 1227 char buffer[sizeof(*x)]; 1228 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1229 1230 // Registers a0 and a1 -> x. 1231 reg_buffer[0] = get_register(a0); 1232 reg_buffer[1] = get_register(a1); 1233 memcpy(x, buffer, sizeof(buffer)); 1234 // Registers a2 and a3 -> y. 1235 reg_buffer[0] = get_register(a2); 1236 reg_buffer[1] = get_register(a3); 1237 memcpy(y, buffer, sizeof(buffer)); 1238 // Register 2 -> z. 1239 reg_buffer[0] = get_register(a2); 1240 memcpy(z, buffer, sizeof(*z)); 1241 } 1242 } 1243 1244 1245 // The return value is either in v0/v1 or f0. 1246 void Simulator::SetFpResult(const double& result) { 1247 if (!IsMipsSoftFloatABI) { 1248 set_fpu_register_double(0, result); 1249 } else { 1250 char buffer[2 * sizeof(registers_[0])]; 1251 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1252 memcpy(buffer, &result, sizeof(buffer)); 1253 // Copy result to v0 and v1. 1254 set_register(v0, reg_buffer[0]); 1255 set_register(v1, reg_buffer[1]); 1256 } 1257 } 1258 1259 1260 // Helper functions for setting and testing the FCSR register's bits. 1261 void Simulator::set_fcsr_bit(uint32_t cc, bool value) { 1262 if (value) { 1263 FCSR_ |= (1 << cc); 1264 } else { 1265 FCSR_ &= ~(1 << cc); 1266 } 1267 } 1268 1269 1270 bool Simulator::test_fcsr_bit(uint32_t cc) { 1271 return FCSR_ & (1 << cc); 1272 } 1273 1274 1275 // Sets the rounding error codes in FCSR based on the result of the rounding. 1276 // Returns true if the operation was invalid. 1277 bool Simulator::set_fcsr_round_error(double original, double rounded) { 1278 bool ret = false; 1279 double max_int32 = std::numeric_limits<int32_t>::max(); 1280 double min_int32 = std::numeric_limits<int32_t>::min(); 1281 1282 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1283 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1284 ret = true; 1285 } 1286 1287 if (original != rounded) { 1288 set_fcsr_bit(kFCSRInexactFlagBit, true); 1289 } 1290 1291 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 1292 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1293 ret = true; 1294 } 1295 1296 if (rounded > max_int32 || rounded < min_int32) { 1297 set_fcsr_bit(kFCSROverflowFlagBit, true); 1298 // The reference is not really clear but it seems this is required: 1299 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1300 ret = true; 1301 } 1302 1303 return ret; 1304 } 1305 1306 1307 // Raw access to the PC register. 1308 void Simulator::set_pc(int32_t value) { 1309 pc_modified_ = true; 1310 registers_[pc] = value; 1311 } 1312 1313 1314 bool Simulator::has_bad_pc() const { 1315 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); 1316 } 1317 1318 1319 // Raw access to the PC register without the special adjustment when reading. 1320 int32_t Simulator::get_pc() const { 1321 return registers_[pc]; 1322 } 1323 1324 1325 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an 1326 // interrupt is caused. On others it does a funky rotation thing. For now we 1327 // simply disallow unaligned reads, but at some point we may want to move to 1328 // emulating the rotate behaviour. Note that simulator runs have the runtime 1329 // system running directly on the host system and only generated code is 1330 // executed in the simulator. Since the host is typically IA32 we will not 1331 // get the correct MIPS-like behaviour on unaligned accesses. 1332 1333 int Simulator::ReadW(int32_t addr, Instruction* instr) { 1334 if (addr >=0 && addr < 0x400) { 1335 // This has to be a NULL-dereference, drop into debugger. 1336 PrintF("Memory read from bad address: 0x%08x, pc=0x%08x\n", 1337 addr, reinterpret_cast<intptr_t>(instr)); 1338 MipsDebugger dbg(this); 1339 dbg.Debug(); 1340 } 1341 if ((addr & kPointerAlignmentMask) == 0) { 1342 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1343 return *ptr; 1344 } 1345 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1346 addr, 1347 reinterpret_cast<intptr_t>(instr)); 1348 MipsDebugger dbg(this); 1349 dbg.Debug(); 1350 return 0; 1351 } 1352 1353 1354 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { 1355 if (addr >= 0 && addr < 0x400) { 1356 // This has to be a NULL-dereference, drop into debugger. 1357 PrintF("Memory write to bad address: 0x%08x, pc=0x%08x\n", 1358 addr, reinterpret_cast<intptr_t>(instr)); 1359 MipsDebugger dbg(this); 1360 dbg.Debug(); 1361 } 1362 if ((addr & kPointerAlignmentMask) == 0) { 1363 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1364 *ptr = value; 1365 return; 1366 } 1367 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1368 addr, 1369 reinterpret_cast<intptr_t>(instr)); 1370 MipsDebugger dbg(this); 1371 dbg.Debug(); 1372 } 1373 1374 1375 double Simulator::ReadD(int32_t addr, Instruction* instr) { 1376 if ((addr & kDoubleAlignmentMask) == 0) { 1377 double* ptr = reinterpret_cast<double*>(addr); 1378 return *ptr; 1379 } 1380 PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1381 addr, 1382 reinterpret_cast<intptr_t>(instr)); 1383 base::OS::Abort(); 1384 return 0; 1385 } 1386 1387 1388 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) { 1389 if ((addr & kDoubleAlignmentMask) == 0) { 1390 double* ptr = reinterpret_cast<double*>(addr); 1391 *ptr = value; 1392 return; 1393 } 1394 PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1395 addr, 1396 reinterpret_cast<intptr_t>(instr)); 1397 base::OS::Abort(); 1398 } 1399 1400 1401 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { 1402 if ((addr & 1) == 0) { 1403 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1404 return *ptr; 1405 } 1406 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1407 addr, 1408 reinterpret_cast<intptr_t>(instr)); 1409 base::OS::Abort(); 1410 return 0; 1411 } 1412 1413 1414 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) { 1415 if ((addr & 1) == 0) { 1416 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1417 return *ptr; 1418 } 1419 PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1420 addr, 1421 reinterpret_cast<intptr_t>(instr)); 1422 base::OS::Abort(); 1423 return 0; 1424 } 1425 1426 1427 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { 1428 if ((addr & 1) == 0) { 1429 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1430 *ptr = value; 1431 return; 1432 } 1433 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1434 addr, 1435 reinterpret_cast<intptr_t>(instr)); 1436 base::OS::Abort(); 1437 } 1438 1439 1440 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { 1441 if ((addr & 1) == 0) { 1442 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1443 *ptr = value; 1444 return; 1445 } 1446 PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1447 addr, 1448 reinterpret_cast<intptr_t>(instr)); 1449 base::OS::Abort(); 1450 } 1451 1452 1453 uint32_t Simulator::ReadBU(int32_t addr) { 1454 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1455 return *ptr & 0xff; 1456 } 1457 1458 1459 int32_t Simulator::ReadB(int32_t addr) { 1460 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1461 return *ptr; 1462 } 1463 1464 1465 void Simulator::WriteB(int32_t addr, uint8_t value) { 1466 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1467 *ptr = value; 1468 } 1469 1470 1471 void Simulator::WriteB(int32_t addr, int8_t value) { 1472 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1473 *ptr = value; 1474 } 1475 1476 1477 // Returns the limit of the stack area to enable checking for stack overflows. 1478 uintptr_t Simulator::StackLimit() const { 1479 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when 1480 // pushing values. 1481 return reinterpret_cast<uintptr_t>(stack_) + 1024; 1482 } 1483 1484 1485 // Unsupported instructions use Format to print an error and stop execution. 1486 void Simulator::Format(Instruction* instr, const char* format) { 1487 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", 1488 reinterpret_cast<intptr_t>(instr), format); 1489 UNIMPLEMENTED_MIPS(); 1490 } 1491 1492 1493 // Calls into the V8 runtime are based on this very simple interface. 1494 // Note: To be able to return two values from some calls the code in runtime.cc 1495 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 1496 // 64-bit value. With the code below we assume that all runtime calls return 1497 // 64 bits of result. If they don't, the v1 result register contains a bogus 1498 // value, which is fine because it is caller-saved. 1499 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 1500 int32_t arg1, 1501 int32_t arg2, 1502 int32_t arg3, 1503 int32_t arg4, 1504 int32_t arg5); 1505 1506 // These prototypes handle the four types of FP calls. 1507 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1); 1508 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); 1509 typedef double (*SimulatorRuntimeFPCall)(double darg0); 1510 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0); 1511 1512 // This signature supports direct call in to API function native callback 1513 // (refer to InvocationCallback in v8.h). 1514 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0); 1515 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1); 1516 1517 // This signature supports direct call to accessor getter callback. 1518 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1); 1519 typedef void (*SimulatorRuntimeProfilingGetterCall)( 1520 int32_t arg0, int32_t arg1, void* arg2); 1521 1522 // Software interrupt instructions are used by the simulator to call into the 1523 // C-based V8 runtime. They are also used for debugging with simulator. 1524 void Simulator::SoftwareInterrupt(Instruction* instr) { 1525 // There are several instructions that could get us here, 1526 // the break_ instruction, or several variants of traps. All 1527 // Are "SPECIAL" class opcode, and are distinuished by function. 1528 int32_t func = instr->FunctionFieldRaw(); 1529 uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; 1530 1531 // We first check if we met a call_rt_redirected. 1532 if (instr->InstructionBits() == rtCallRedirInstr) { 1533 Redirection* redirection = Redirection::FromSwiInstruction(instr); 1534 int32_t arg0 = get_register(a0); 1535 int32_t arg1 = get_register(a1); 1536 int32_t arg2 = get_register(a2); 1537 int32_t arg3 = get_register(a3); 1538 1539 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); 1540 // Args 4 and 5 are on the stack after the reserved space for args 0..3. 1541 int32_t arg4 = stack_pointer[4]; 1542 int32_t arg5 = stack_pointer[5]; 1543 1544 bool fp_call = 1545 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 1546 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 1547 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 1548 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 1549 1550 if (!IsMipsSoftFloatABI) { 1551 // With the hard floating point calling convention, double 1552 // arguments are passed in FPU registers. Fetch the arguments 1553 // from there and call the builtin using soft floating point 1554 // convention. 1555 switch (redirection->type()) { 1556 case ExternalReference::BUILTIN_FP_FP_CALL: 1557 case ExternalReference::BUILTIN_COMPARE_CALL: 1558 if (IsFp64Mode()) { 1559 arg0 = get_fpu_register_word(f12); 1560 arg1 = get_fpu_register_hi_word(f12); 1561 arg2 = get_fpu_register_word(f14); 1562 arg3 = get_fpu_register_hi_word(f14); 1563 } else { 1564 arg0 = get_fpu_register_word(f12); 1565 arg1 = get_fpu_register_word(f13); 1566 arg2 = get_fpu_register_word(f14); 1567 arg3 = get_fpu_register_word(f15); 1568 } 1569 break; 1570 case ExternalReference::BUILTIN_FP_CALL: 1571 if (IsFp64Mode()) { 1572 arg0 = get_fpu_register_word(f12); 1573 arg1 = get_fpu_register_hi_word(f12); 1574 } else { 1575 arg0 = get_fpu_register_word(f12); 1576 arg1 = get_fpu_register_word(f13); 1577 } 1578 break; 1579 case ExternalReference::BUILTIN_FP_INT_CALL: 1580 if (IsFp64Mode()) { 1581 arg0 = get_fpu_register_word(f12); 1582 arg1 = get_fpu_register_hi_word(f12); 1583 } else { 1584 arg0 = get_fpu_register_word(f12); 1585 arg1 = get_fpu_register_word(f13); 1586 } 1587 arg2 = get_register(a2); 1588 break; 1589 default: 1590 break; 1591 } 1592 } 1593 1594 // This is dodgy but it works because the C entry stubs are never moved. 1595 // See comment in codegen-arm.cc and bug 1242173. 1596 int32_t saved_ra = get_register(ra); 1597 1598 intptr_t external = 1599 reinterpret_cast<intptr_t>(redirection->external_function()); 1600 1601 // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware 1602 // FPU, or gcc soft-float routines. Hardware FPU is simulated in this 1603 // simulator. Soft-float has additional abstraction of ExternalReference, 1604 // to support serialization. 1605 if (fp_call) { 1606 double dval0, dval1; // one or two double parameters 1607 int32_t ival; // zero or one integer parameters 1608 int64_t iresult = 0; // integer return value 1609 double dresult = 0; // double return value 1610 GetFpArgs(&dval0, &dval1, &ival); 1611 SimulatorRuntimeCall generic_target = 1612 reinterpret_cast<SimulatorRuntimeCall>(external); 1613 if (::v8::internal::FLAG_trace_sim) { 1614 switch (redirection->type()) { 1615 case ExternalReference::BUILTIN_FP_FP_CALL: 1616 case ExternalReference::BUILTIN_COMPARE_CALL: 1617 PrintF("Call to host function at %p with args %f, %f", 1618 FUNCTION_ADDR(generic_target), dval0, dval1); 1619 break; 1620 case ExternalReference::BUILTIN_FP_CALL: 1621 PrintF("Call to host function at %p with arg %f", 1622 FUNCTION_ADDR(generic_target), dval0); 1623 break; 1624 case ExternalReference::BUILTIN_FP_INT_CALL: 1625 PrintF("Call to host function at %p with args %f, %d", 1626 FUNCTION_ADDR(generic_target), dval0, ival); 1627 break; 1628 default: 1629 UNREACHABLE(); 1630 break; 1631 } 1632 } 1633 switch (redirection->type()) { 1634 case ExternalReference::BUILTIN_COMPARE_CALL: { 1635 SimulatorRuntimeCompareCall target = 1636 reinterpret_cast<SimulatorRuntimeCompareCall>(external); 1637 iresult = target(dval0, dval1); 1638 set_register(v0, static_cast<int32_t>(iresult)); 1639 set_register(v1, static_cast<int32_t>(iresult >> 32)); 1640 break; 1641 } 1642 case ExternalReference::BUILTIN_FP_FP_CALL: { 1643 SimulatorRuntimeFPFPCall target = 1644 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 1645 dresult = target(dval0, dval1); 1646 SetFpResult(dresult); 1647 break; 1648 } 1649 case ExternalReference::BUILTIN_FP_CALL: { 1650 SimulatorRuntimeFPCall target = 1651 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1652 dresult = target(dval0); 1653 SetFpResult(dresult); 1654 break; 1655 } 1656 case ExternalReference::BUILTIN_FP_INT_CALL: { 1657 SimulatorRuntimeFPIntCall target = 1658 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 1659 dresult = target(dval0, ival); 1660 SetFpResult(dresult); 1661 break; 1662 } 1663 default: 1664 UNREACHABLE(); 1665 break; 1666 } 1667 if (::v8::internal::FLAG_trace_sim) { 1668 switch (redirection->type()) { 1669 case ExternalReference::BUILTIN_COMPARE_CALL: 1670 PrintF("Returned %08x\n", static_cast<int32_t>(iresult)); 1671 break; 1672 case ExternalReference::BUILTIN_FP_FP_CALL: 1673 case ExternalReference::BUILTIN_FP_CALL: 1674 case ExternalReference::BUILTIN_FP_INT_CALL: 1675 PrintF("Returned %f\n", dresult); 1676 break; 1677 default: 1678 UNREACHABLE(); 1679 break; 1680 } 1681 } 1682 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 1683 if (::v8::internal::FLAG_trace_sim) { 1684 PrintF("Call to host function at %p args %08x\n", 1685 reinterpret_cast<void*>(external), arg0); 1686 } 1687 SimulatorRuntimeDirectApiCall target = 1688 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 1689 target(arg0); 1690 } else if ( 1691 redirection->type() == ExternalReference::PROFILING_API_CALL) { 1692 if (::v8::internal::FLAG_trace_sim) { 1693 PrintF("Call to host function at %p args %08x %08x\n", 1694 reinterpret_cast<void*>(external), arg0, arg1); 1695 } 1696 SimulatorRuntimeProfilingApiCall target = 1697 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 1698 target(arg0, Redirection::ReverseRedirection(arg1)); 1699 } else if ( 1700 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 1701 if (::v8::internal::FLAG_trace_sim) { 1702 PrintF("Call to host function at %p args %08x %08x\n", 1703 reinterpret_cast<void*>(external), arg0, arg1); 1704 } 1705 SimulatorRuntimeDirectGetterCall target = 1706 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 1707 target(arg0, arg1); 1708 } else if ( 1709 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) { 1710 if (::v8::internal::FLAG_trace_sim) { 1711 PrintF("Call to host function at %p args %08x %08x %08x\n", 1712 reinterpret_cast<void*>(external), arg0, arg1, arg2); 1713 } 1714 SimulatorRuntimeProfilingGetterCall target = 1715 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); 1716 target(arg0, arg1, Redirection::ReverseRedirection(arg2)); 1717 } else { 1718 SimulatorRuntimeCall target = 1719 reinterpret_cast<SimulatorRuntimeCall>(external); 1720 if (::v8::internal::FLAG_trace_sim) { 1721 PrintF( 1722 "Call to host function at %p " 1723 "args %08x, %08x, %08x, %08x, %08x, %08x\n", 1724 FUNCTION_ADDR(target), 1725 arg0, 1726 arg1, 1727 arg2, 1728 arg3, 1729 arg4, 1730 arg5); 1731 } 1732 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 1733 set_register(v0, static_cast<int32_t>(result)); 1734 set_register(v1, static_cast<int32_t>(result >> 32)); 1735 } 1736 if (::v8::internal::FLAG_trace_sim) { 1737 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); 1738 } 1739 set_register(ra, saved_ra); 1740 set_pc(get_register(ra)); 1741 1742 } else if (func == BREAK && code <= kMaxStopCode) { 1743 if (IsWatchpoint(code)) { 1744 PrintWatchpoint(code); 1745 } else { 1746 IncreaseStopCounter(code); 1747 HandleStop(code, instr); 1748 } 1749 } else { 1750 // All remaining break_ codes, and all traps are handled here. 1751 MipsDebugger dbg(this); 1752 dbg.Debug(); 1753 } 1754 } 1755 1756 1757 // Stop helper functions. 1758 bool Simulator::IsWatchpoint(uint32_t code) { 1759 return (code <= kMaxWatchpointCode); 1760 } 1761 1762 1763 void Simulator::PrintWatchpoint(uint32_t code) { 1764 MipsDebugger dbg(this); 1765 ++break_count_; 1766 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" 1767 "----------------------------------", 1768 code, break_count_, icount_); 1769 dbg.PrintAllRegs(); // Print registers and continue running. 1770 } 1771 1772 1773 void Simulator::HandleStop(uint32_t code, Instruction* instr) { 1774 // Stop if it is enabled, otherwise go on jumping over the stop 1775 // and the message address. 1776 if (IsEnabledStop(code)) { 1777 MipsDebugger dbg(this); 1778 dbg.Stop(instr); 1779 } else { 1780 set_pc(get_pc() + 2 * Instruction::kInstrSize); 1781 } 1782 } 1783 1784 1785 bool Simulator::IsStopInstruction(Instruction* instr) { 1786 int32_t func = instr->FunctionFieldRaw(); 1787 uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6)); 1788 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode; 1789 } 1790 1791 1792 bool Simulator::IsEnabledStop(uint32_t code) { 1793 DCHECK(code <= kMaxStopCode); 1794 DCHECK(code > kMaxWatchpointCode); 1795 return !(watched_stops_[code].count & kStopDisabledBit); 1796 } 1797 1798 1799 void Simulator::EnableStop(uint32_t code) { 1800 if (!IsEnabledStop(code)) { 1801 watched_stops_[code].count &= ~kStopDisabledBit; 1802 } 1803 } 1804 1805 1806 void Simulator::DisableStop(uint32_t code) { 1807 if (IsEnabledStop(code)) { 1808 watched_stops_[code].count |= kStopDisabledBit; 1809 } 1810 } 1811 1812 1813 void Simulator::IncreaseStopCounter(uint32_t code) { 1814 DCHECK(code <= kMaxStopCode); 1815 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) { 1816 PrintF("Stop counter for code %i has overflowed.\n" 1817 "Enabling this code and reseting the counter to 0.\n", code); 1818 watched_stops_[code].count = 0; 1819 EnableStop(code); 1820 } else { 1821 watched_stops_[code].count++; 1822 } 1823 } 1824 1825 1826 // Print a stop status. 1827 void Simulator::PrintStopInfo(uint32_t code) { 1828 if (code <= kMaxWatchpointCode) { 1829 PrintF("That is a watchpoint, not a stop.\n"); 1830 return; 1831 } else if (code > kMaxStopCode) { 1832 PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1); 1833 return; 1834 } 1835 const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled"; 1836 int32_t count = watched_stops_[code].count & ~kStopDisabledBit; 1837 // Don't print the state of unused breakpoints. 1838 if (count != 0) { 1839 if (watched_stops_[code].desc) { 1840 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", 1841 code, code, state, count, watched_stops_[code].desc); 1842 } else { 1843 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", 1844 code, code, state, count); 1845 } 1846 } 1847 } 1848 1849 1850 void Simulator::SignalExceptions() { 1851 for (int i = 1; i < kNumExceptions; i++) { 1852 if (exceptions[i] != 0) { 1853 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); 1854 } 1855 } 1856 } 1857 1858 1859 // Handle execution based on instruction types. 1860 1861 void Simulator::ConfigureTypeRegister(Instruction* instr, 1862 int32_t* alu_out, 1863 int64_t* i64hilo, 1864 uint64_t* u64hilo, 1865 int32_t* next_pc, 1866 int32_t* return_addr_reg, 1867 bool* do_interrupt) { 1868 // Every local variable declared here needs to be const. 1869 // This is to make sure that changed values are sent back to 1870 // DecodeTypeRegister correctly. 1871 1872 // Instruction fields. 1873 const Opcode op = instr->OpcodeFieldRaw(); 1874 const int32_t rs_reg = instr->RsValue(); 1875 const int32_t rs = get_register(rs_reg); 1876 const uint32_t rs_u = static_cast<uint32_t>(rs); 1877 const int32_t rt_reg = instr->RtValue(); 1878 const int32_t rt = get_register(rt_reg); 1879 const uint32_t rt_u = static_cast<uint32_t>(rt); 1880 const int32_t rd_reg = instr->RdValue(); 1881 const uint32_t sa = instr->SaValue(); 1882 1883 const int32_t fs_reg = instr->FsValue(); 1884 1885 1886 // ---------- Configuration. 1887 switch (op) { 1888 case COP1: // Coprocessor instructions. 1889 switch (instr->RsFieldRaw()) { 1890 case CFC1: 1891 // At the moment only FCSR is supported. 1892 DCHECK(fs_reg == kFCSRRegister); 1893 *alu_out = FCSR_; 1894 break; 1895 case MFC1: 1896 *alu_out = get_fpu_register_word(fs_reg); 1897 break; 1898 case MFHC1: 1899 *alu_out = get_fpu_register_hi_word(fs_reg); 1900 break; 1901 case CTC1: 1902 case MTC1: 1903 case MTHC1: 1904 case S: 1905 case D: 1906 case W: 1907 case L: 1908 case PS: 1909 // Do everything in the execution step. 1910 break; 1911 default: 1912 // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here. 1913 UNREACHABLE(); 1914 } 1915 break; 1916 case COP1X: 1917 break; 1918 case SPECIAL: 1919 switch (instr->FunctionFieldRaw()) { 1920 case JR: 1921 case JALR: 1922 *next_pc = get_register(instr->RsValue()); 1923 *return_addr_reg = instr->RdValue(); 1924 break; 1925 case SLL: 1926 *alu_out = rt << sa; 1927 break; 1928 case SRL: 1929 if (rs_reg == 0) { 1930 // Regular logical right shift of a word by a fixed number of 1931 // bits instruction. RS field is always equal to 0. 1932 *alu_out = rt_u >> sa; 1933 } else { 1934 // Logical right-rotate of a word by a fixed number of bits. This 1935 // is special case of SRL instruction, added in MIPS32 Release 2. 1936 // RS field is equal to 00001. 1937 *alu_out = (rt_u >> sa) | (rt_u << (32 - sa)); 1938 } 1939 break; 1940 case SRA: 1941 *alu_out = rt >> sa; 1942 break; 1943 case SLLV: 1944 *alu_out = rt << rs; 1945 break; 1946 case SRLV: 1947 if (sa == 0) { 1948 // Regular logical right-shift of a word by a variable number of 1949 // bits instruction. SA field is always equal to 0. 1950 *alu_out = rt_u >> rs; 1951 } else { 1952 // Logical right-rotate of a word by a variable number of bits. 1953 // This is special case od SRLV instruction, added in MIPS32 1954 // Release 2. SA field is equal to 00001. 1955 *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u)); 1956 } 1957 break; 1958 case SRAV: 1959 *alu_out = rt >> rs; 1960 break; 1961 case MFHI: // MFHI == CLZ on R6. 1962 if (!IsMipsArchVariant(kMips32r6)) { 1963 DCHECK(instr->SaValue() == 0); 1964 *alu_out = get_register(HI); 1965 } else { 1966 // MIPS spec: If no bits were set in GPR rs, the result written to 1967 // GPR rd is 32. 1968 DCHECK(instr->SaValue() == 1); 1969 *alu_out = base::bits::CountLeadingZeros32(rs_u); 1970 } 1971 break; 1972 case MFLO: 1973 *alu_out = get_register(LO); 1974 break; 1975 case MULT: // MULT == MUL_MUH. 1976 if (!IsMipsArchVariant(kMips32r6)) { 1977 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); 1978 } else { 1979 switch (instr->SaValue()) { 1980 case MUL_OP: 1981 case MUH_OP: 1982 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); 1983 break; 1984 default: 1985 UNIMPLEMENTED_MIPS(); 1986 break; 1987 } 1988 } 1989 break; 1990 case MULTU: // MULTU == MUL_MUH_U. 1991 if (!IsMipsArchVariant(kMips32r6)) { 1992 *u64hilo = static_cast<uint64_t>(rs_u) * 1993 static_cast<uint64_t>(rt_u); 1994 } else { 1995 switch (instr->SaValue()) { 1996 case MUL_OP: 1997 case MUH_OP: 1998 *u64hilo = static_cast<uint64_t>(rs_u) * 1999 static_cast<uint64_t>(rt_u); 2000 break; 2001 default: 2002 UNIMPLEMENTED_MIPS(); 2003 break; 2004 } 2005 } 2006 break; 2007 case ADD: 2008 if (HaveSameSign(rs, rt)) { 2009 if (rs > 0) { 2010 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); 2011 } else if (rs < 0) { 2012 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt); 2013 } 2014 } 2015 *alu_out = rs + rt; 2016 break; 2017 case ADDU: 2018 *alu_out = rs + rt; 2019 break; 2020 case SUB: 2021 if (!HaveSameSign(rs, rt)) { 2022 if (rs > 0) { 2023 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt); 2024 } else if (rs < 0) { 2025 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt); 2026 } 2027 } 2028 *alu_out = rs - rt; 2029 break; 2030 case SUBU: 2031 *alu_out = rs - rt; 2032 break; 2033 case AND: 2034 *alu_out = rs & rt; 2035 break; 2036 case OR: 2037 *alu_out = rs | rt; 2038 break; 2039 case XOR: 2040 *alu_out = rs ^ rt; 2041 break; 2042 case NOR: 2043 *alu_out = ~(rs | rt); 2044 break; 2045 case SLT: 2046 *alu_out = rs < rt ? 1 : 0; 2047 break; 2048 case SLTU: 2049 *alu_out = rs_u < rt_u ? 1 : 0; 2050 break; 2051 // Break and trap instructions. 2052 case BREAK: 2053 *do_interrupt = true; 2054 break; 2055 case TGE: 2056 *do_interrupt = rs >= rt; 2057 break; 2058 case TGEU: 2059 *do_interrupt = rs_u >= rt_u; 2060 break; 2061 case TLT: 2062 *do_interrupt = rs < rt; 2063 break; 2064 case TLTU: 2065 *do_interrupt = rs_u < rt_u; 2066 break; 2067 case TEQ: 2068 *do_interrupt = rs == rt; 2069 break; 2070 case TNE: 2071 *do_interrupt = rs != rt; 2072 break; 2073 case MOVN: 2074 case MOVZ: 2075 case MOVCI: 2076 // No action taken on decode. 2077 break; 2078 case DIV: 2079 case DIVU: 2080 // div and divu never raise exceptions. 2081 break; 2082 default: 2083 UNREACHABLE(); 2084 } 2085 break; 2086 case SPECIAL2: 2087 switch (instr->FunctionFieldRaw()) { 2088 case MUL: 2089 *alu_out = rs_u * rt_u; // Only the lower 32 bits are kept. 2090 break; 2091 case CLZ: 2092 // MIPS32 spec: If no bits were set in GPR rs, the result written to 2093 // GPR rd is 32. 2094 *alu_out = base::bits::CountLeadingZeros32(rs_u); 2095 break; 2096 default: 2097 UNREACHABLE(); 2098 } 2099 break; 2100 case SPECIAL3: 2101 switch (instr->FunctionFieldRaw()) { 2102 case INS: { // Mips32r2 instruction. 2103 // Interpret rd field as 5-bit msb of insert. 2104 uint16_t msb = rd_reg; 2105 // Interpret sa field as 5-bit lsb of insert. 2106 uint16_t lsb = sa; 2107 uint16_t size = msb - lsb + 1; 2108 uint32_t mask = (1 << size) - 1; 2109 *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb); 2110 break; 2111 } 2112 case EXT: { // Mips32r2 instruction. 2113 // Interpret rd field as 5-bit msb of extract. 2114 uint16_t msb = rd_reg; 2115 // Interpret sa field as 5-bit lsb of extract. 2116 uint16_t lsb = sa; 2117 uint16_t size = msb + 1; 2118 uint32_t mask = (1 << size) - 1; 2119 *alu_out = (rs_u & (mask << lsb)) >> lsb; 2120 break; 2121 } 2122 default: 2123 UNREACHABLE(); 2124 } 2125 break; 2126 default: 2127 UNREACHABLE(); 2128 } 2129 } 2130 2131 2132 void Simulator::DecodeTypeRegister(Instruction* instr) { 2133 // Instruction fields. 2134 const Opcode op = instr->OpcodeFieldRaw(); 2135 const int32_t rs_reg = instr->RsValue(); 2136 const int32_t rs = get_register(rs_reg); 2137 const uint32_t rs_u = static_cast<uint32_t>(rs); 2138 const int32_t rt_reg = instr->RtValue(); 2139 const int32_t rt = get_register(rt_reg); 2140 const uint32_t rt_u = static_cast<uint32_t>(rt); 2141 const int32_t rd_reg = instr->RdValue(); 2142 2143 const int32_t fr_reg = instr->FrValue(); 2144 const int32_t fs_reg = instr->FsValue(); 2145 const int32_t ft_reg = instr->FtValue(); 2146 const int32_t fd_reg = instr->FdValue(); 2147 int64_t i64hilo = 0; 2148 uint64_t u64hilo = 0; 2149 2150 // ALU output. 2151 // It should not be used as is. Instructions using it should always 2152 // initialize it first. 2153 int32_t alu_out = 0x12345678; 2154 2155 // For break and trap instructions. 2156 bool do_interrupt = false; 2157 2158 // For jr and jalr. 2159 // Get current pc. 2160 int32_t current_pc = get_pc(); 2161 // Next pc 2162 int32_t next_pc = 0; 2163 int32_t return_addr_reg = 31; 2164 2165 // Set up the variables if needed before executing the instruction. 2166 ConfigureTypeRegister(instr, 2167 &alu_out, 2168 &i64hilo, 2169 &u64hilo, 2170 &next_pc, 2171 &return_addr_reg, 2172 &do_interrupt); 2173 2174 // ---------- Raise exceptions triggered. 2175 SignalExceptions(); 2176 2177 // ---------- Execution. 2178 switch (op) { 2179 case COP1: 2180 switch (instr->RsFieldRaw()) { 2181 case CFC1: 2182 set_register(rt_reg, alu_out); 2183 break; 2184 case MFC1: 2185 set_register(rt_reg, alu_out); 2186 break; 2187 case MFHC1: 2188 set_register(rt_reg, alu_out); 2189 break; 2190 case CTC1: 2191 // At the moment only FCSR is supported. 2192 DCHECK(fs_reg == kFCSRRegister); 2193 FCSR_ = registers_[rt_reg]; 2194 break; 2195 case MTC1: 2196 // Hardware writes upper 32-bits to zero on mtc1. 2197 set_fpu_register_hi_word(fs_reg, 0); 2198 set_fpu_register_word(fs_reg, registers_[rt_reg]); 2199 break; 2200 case MTHC1: 2201 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); 2202 break; 2203 case S: 2204 float f; 2205 switch (instr->FunctionFieldRaw()) { 2206 case CVT_D_S: 2207 f = get_fpu_register_float(fs_reg); 2208 set_fpu_register_double(fd_reg, static_cast<double>(f)); 2209 break; 2210 default: 2211 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 2212 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 2213 UNREACHABLE(); 2214 } 2215 break; 2216 case D: 2217 double ft, fs; 2218 uint32_t cc, fcsr_cc; 2219 int64_t i64; 2220 fs = get_fpu_register_double(fs_reg); 2221 ft = get_fpu_register_double(ft_reg); 2222 cc = instr->FCccValue(); 2223 fcsr_cc = get_fcsr_condition_bit(cc); 2224 switch (instr->FunctionFieldRaw()) { 2225 case ADD_D: 2226 set_fpu_register_double(fd_reg, fs + ft); 2227 break; 2228 case SUB_D: 2229 set_fpu_register_double(fd_reg, fs - ft); 2230 break; 2231 case MUL_D: 2232 set_fpu_register_double(fd_reg, fs * ft); 2233 break; 2234 case DIV_D: 2235 set_fpu_register_double(fd_reg, fs / ft); 2236 break; 2237 case ABS_D: 2238 set_fpu_register_double(fd_reg, fabs(fs)); 2239 break; 2240 case MOV_D: 2241 set_fpu_register_double(fd_reg, fs); 2242 break; 2243 case NEG_D: 2244 set_fpu_register_double(fd_reg, -fs); 2245 break; 2246 case SQRT_D: 2247 set_fpu_register_double(fd_reg, sqrt(fs)); 2248 break; 2249 case C_UN_D: 2250 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2251 break; 2252 case C_EQ_D: 2253 set_fcsr_bit(fcsr_cc, (fs == ft)); 2254 break; 2255 case C_UEQ_D: 2256 set_fcsr_bit(fcsr_cc, 2257 (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2258 break; 2259 case C_OLT_D: 2260 set_fcsr_bit(fcsr_cc, (fs < ft)); 2261 break; 2262 case C_ULT_D: 2263 set_fcsr_bit(fcsr_cc, 2264 (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2265 break; 2266 case C_OLE_D: 2267 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2268 break; 2269 case C_ULE_D: 2270 set_fcsr_bit(fcsr_cc, 2271 (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2272 break; 2273 case CVT_W_D: // Convert double to word. 2274 // Rounding modes are not yet supported. 2275 DCHECK((FCSR_ & 3) == 0); 2276 // In rounding mode 0 it should behave like ROUND. 2277 case ROUND_W_D: // Round double to word (round half to even). 2278 { 2279 double rounded = std::floor(fs + 0.5); 2280 int32_t result = static_cast<int32_t>(rounded); 2281 if ((result & 1) != 0 && result - fs == 0.5) { 2282 // If the number is halfway between two integers, 2283 // round to the even one. 2284 result--; 2285 } 2286 set_fpu_register_word(fd_reg, result); 2287 if (set_fcsr_round_error(fs, rounded)) { 2288 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2289 } 2290 } 2291 break; 2292 case TRUNC_W_D: // Truncate double to word (round towards 0). 2293 { 2294 double rounded = trunc(fs); 2295 int32_t result = static_cast<int32_t>(rounded); 2296 set_fpu_register_word(fd_reg, result); 2297 if (set_fcsr_round_error(fs, rounded)) { 2298 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2299 } 2300 } 2301 break; 2302 case FLOOR_W_D: // Round double to word towards negative infinity. 2303 { 2304 double rounded = std::floor(fs); 2305 int32_t result = static_cast<int32_t>(rounded); 2306 set_fpu_register_word(fd_reg, result); 2307 if (set_fcsr_round_error(fs, rounded)) { 2308 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2309 } 2310 } 2311 break; 2312 case CEIL_W_D: // Round double to word towards positive infinity. 2313 { 2314 double rounded = std::ceil(fs); 2315 int32_t result = static_cast<int32_t>(rounded); 2316 set_fpu_register_word(fd_reg, result); 2317 if (set_fcsr_round_error(fs, rounded)) { 2318 set_fpu_register_word(fd_reg, kFPUInvalidResult); 2319 } 2320 } 2321 break; 2322 case CVT_S_D: // Convert double to float (single). 2323 set_fpu_register_float(fd_reg, static_cast<float>(fs)); 2324 break; 2325 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. 2326 double rounded = trunc(fs); 2327 i64 = static_cast<int64_t>(rounded); 2328 if (IsFp64Mode()) { 2329 set_fpu_register(fd_reg, i64); 2330 } else { 2331 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2332 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2333 } 2334 break; 2335 } 2336 case TRUNC_L_D: { // Mips32r2 instruction. 2337 double rounded = trunc(fs); 2338 i64 = static_cast<int64_t>(rounded); 2339 if (IsFp64Mode()) { 2340 set_fpu_register(fd_reg, i64); 2341 } else { 2342 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2343 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2344 } 2345 break; 2346 } 2347 case ROUND_L_D: { // Mips32r2 instruction. 2348 double rounded = 2349 fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5); 2350 i64 = static_cast<int64_t>(rounded); 2351 if (IsFp64Mode()) { 2352 set_fpu_register(fd_reg, i64); 2353 } else { 2354 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2355 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2356 } 2357 break; 2358 } 2359 case FLOOR_L_D: // Mips32r2 instruction. 2360 i64 = static_cast<int64_t>(std::floor(fs)); 2361 if (IsFp64Mode()) { 2362 set_fpu_register(fd_reg, i64); 2363 } else { 2364 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2365 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2366 } 2367 break; 2368 case CEIL_L_D: // Mips32r2 instruction. 2369 i64 = static_cast<int64_t>(std::ceil(fs)); 2370 if (IsFp64Mode()) { 2371 set_fpu_register(fd_reg, i64); 2372 } else { 2373 set_fpu_register_word(fd_reg, i64 & 0xffffffff); 2374 set_fpu_register_word(fd_reg + 1, i64 >> 32); 2375 } 2376 break; 2377 case C_F_D: 2378 UNIMPLEMENTED_MIPS(); 2379 break; 2380 default: 2381 UNREACHABLE(); 2382 } 2383 break; 2384 case W: 2385 switch (instr->FunctionFieldRaw()) { 2386 case CVT_S_W: // Convert word to float (single). 2387 alu_out = get_fpu_register_signed_word(fs_reg); 2388 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); 2389 break; 2390 case CVT_D_W: // Convert word to double. 2391 alu_out = get_fpu_register_signed_word(fs_reg); 2392 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); 2393 break; 2394 default: // Mips64r6 CMP.S instructions unimplemented. 2395 UNREACHABLE(); 2396 } 2397 break; 2398 case L: 2399 fs = get_fpu_register_double(fs_reg); 2400 ft = get_fpu_register_double(ft_reg); 2401 switch (instr->FunctionFieldRaw()) { 2402 case CVT_D_L: // Mips32r2 instruction. 2403 // Watch the signs here, we want 2 32-bit vals 2404 // to make a sign-64. 2405 if (IsFp64Mode()) { 2406 i64 = get_fpu_register(fs_reg); 2407 } else { 2408 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg)); 2409 i64 |= static_cast<int64_t>( 2410 get_fpu_register_word(fs_reg + 1)) << 32; 2411 } 2412 set_fpu_register_double(fd_reg, static_cast<double>(i64)); 2413 break; 2414 case CVT_S_L: 2415 UNIMPLEMENTED_MIPS(); 2416 break; 2417 case CMP_AF: // Mips64r6 CMP.D instructions. 2418 UNIMPLEMENTED_MIPS(); 2419 break; 2420 case CMP_UN: 2421 if (std::isnan(fs) || std::isnan(ft)) { 2422 set_fpu_register(fd_reg, -1); 2423 } else { 2424 set_fpu_register(fd_reg, 0); 2425 } 2426 break; 2427 case CMP_EQ: 2428 if (fs == ft) { 2429 set_fpu_register(fd_reg, -1); 2430 } else { 2431 set_fpu_register(fd_reg, 0); 2432 } 2433 break; 2434 case CMP_UEQ: 2435 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 2436 set_fpu_register(fd_reg, -1); 2437 } else { 2438 set_fpu_register(fd_reg, 0); 2439 } 2440 break; 2441 case CMP_LT: 2442 if (fs < ft) { 2443 set_fpu_register(fd_reg, -1); 2444 } else { 2445 set_fpu_register(fd_reg, 0); 2446 } 2447 break; 2448 case CMP_ULT: 2449 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 2450 set_fpu_register(fd_reg, -1); 2451 } else { 2452 set_fpu_register(fd_reg, 0); 2453 } 2454 break; 2455 case CMP_LE: 2456 if (fs <= ft) { 2457 set_fpu_register(fd_reg, -1); 2458 } else { 2459 set_fpu_register(fd_reg, 0); 2460 } 2461 break; 2462 case CMP_ULE: 2463 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 2464 set_fpu_register(fd_reg, -1); 2465 } else { 2466 set_fpu_register(fd_reg, 0); 2467 } 2468 break; 2469 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED. 2470 UNREACHABLE(); 2471 } 2472 break; 2473 default: 2474 UNREACHABLE(); 2475 } 2476 break; 2477 case COP1X: 2478 switch (instr->FunctionFieldRaw()) { 2479 case MADD_D: 2480 double fr, ft, fs; 2481 fr = get_fpu_register_double(fr_reg); 2482 fs = get_fpu_register_double(fs_reg); 2483 ft = get_fpu_register_double(ft_reg); 2484 set_fpu_register_double(fd_reg, fs * ft + fr); 2485 break; 2486 default: 2487 UNREACHABLE(); 2488 } 2489 break; 2490 case SPECIAL: 2491 switch (instr->FunctionFieldRaw()) { 2492 case JR: { 2493 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 2494 current_pc+Instruction::kInstrSize); 2495 BranchDelayInstructionDecode(branch_delay_instr); 2496 set_pc(next_pc); 2497 pc_modified_ = true; 2498 break; 2499 } 2500 case JALR: { 2501 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 2502 current_pc+Instruction::kInstrSize); 2503 BranchDelayInstructionDecode(branch_delay_instr); 2504 set_register(return_addr_reg, 2505 current_pc + 2 * Instruction::kInstrSize); 2506 set_pc(next_pc); 2507 pc_modified_ = true; 2508 break; 2509 } 2510 // Instructions using HI and LO registers. 2511 case MULT: 2512 if (!IsMipsArchVariant(kMips32r6)) { 2513 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); 2514 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); 2515 } else { 2516 switch (instr->SaValue()) { 2517 case MUL_OP: 2518 set_register(rd_reg, 2519 static_cast<int32_t>(i64hilo & 0xffffffff)); 2520 break; 2521 case MUH_OP: 2522 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32)); 2523 break; 2524 default: 2525 UNIMPLEMENTED_MIPS(); 2526 break; 2527 } 2528 } 2529 break; 2530 case MULTU: 2531 if (!IsMipsArchVariant(kMips32r6)) { 2532 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); 2533 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); 2534 } else { 2535 switch (instr->SaValue()) { 2536 case MUL_OP: 2537 set_register(rd_reg, 2538 static_cast<int32_t>(u64hilo & 0xffffffff)); 2539 break; 2540 case MUH_OP: 2541 set_register(rd_reg, static_cast<int32_t>(u64hilo >> 32)); 2542 break; 2543 default: 2544 UNIMPLEMENTED_MIPS(); 2545 break; 2546 } 2547 } 2548 break; 2549 case DIV: 2550 if (IsMipsArchVariant(kMips32r6)) { 2551 switch (instr->SaValue()) { 2552 case DIV_OP: 2553 if (rs == INT_MIN && rt == -1) { 2554 set_register(rd_reg, INT_MIN); 2555 } else if (rt != 0) { 2556 set_register(rd_reg, rs / rt); 2557 } 2558 break; 2559 case MOD_OP: 2560 if (rs == INT_MIN && rt == -1) { 2561 set_register(rd_reg, 0); 2562 } else if (rt != 0) { 2563 set_register(rd_reg, rs % rt); 2564 } 2565 break; 2566 default: 2567 UNIMPLEMENTED_MIPS(); 2568 break; 2569 } 2570 } else { 2571 // Divide by zero and overflow was not checked in the 2572 // configuration step - div and divu do not raise exceptions. On 2573 // division by 0 the result will be UNPREDICTABLE. On overflow 2574 // (INT_MIN/-1), return INT_MIN which is what the hardware does. 2575 if (rs == INT_MIN && rt == -1) { 2576 set_register(LO, INT_MIN); 2577 set_register(HI, 0); 2578 } else if (rt != 0) { 2579 set_register(LO, rs / rt); 2580 set_register(HI, rs % rt); 2581 } 2582 } 2583 break; 2584 case DIVU: 2585 if (IsMipsArchVariant(kMips32r6)) { 2586 switch (instr->SaValue()) { 2587 case DIV_OP: 2588 if (rt_u != 0) { 2589 set_register(rd_reg, rs_u / rt_u); 2590 } 2591 break; 2592 case MOD_OP: 2593 if (rt_u != 0) { 2594 set_register(rd_reg, rs_u % rt_u); 2595 } 2596 break; 2597 default: 2598 UNIMPLEMENTED_MIPS(); 2599 break; 2600 } 2601 } else { 2602 if (rt_u != 0) { 2603 set_register(LO, rs_u / rt_u); 2604 set_register(HI, rs_u % rt_u); 2605 } 2606 } 2607 break; 2608 // Break and trap instructions. 2609 case BREAK: 2610 case TGE: 2611 case TGEU: 2612 case TLT: 2613 case TLTU: 2614 case TEQ: 2615 case TNE: 2616 if (do_interrupt) { 2617 SoftwareInterrupt(instr); 2618 } 2619 break; 2620 // Conditional moves. 2621 case MOVN: 2622 if (rt) set_register(rd_reg, rs); 2623 break; 2624 case MOVCI: { 2625 uint32_t cc = instr->FBccValue(); 2626 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); 2627 if (instr->Bit(16)) { // Read Tf bit. 2628 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 2629 } else { 2630 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs); 2631 } 2632 break; 2633 } 2634 case MOVZ: 2635 if (!rt) set_register(rd_reg, rs); 2636 break; 2637 default: // For other special opcodes we do the default operation. 2638 set_register(rd_reg, alu_out); 2639 } 2640 break; 2641 case SPECIAL2: 2642 switch (instr->FunctionFieldRaw()) { 2643 case MUL: 2644 set_register(rd_reg, alu_out); 2645 // HI and LO are UNPREDICTABLE after the operation. 2646 set_register(LO, Unpredictable); 2647 set_register(HI, Unpredictable); 2648 break; 2649 default: // For other special2 opcodes we do the default operation. 2650 set_register(rd_reg, alu_out); 2651 } 2652 break; 2653 case SPECIAL3: 2654 switch (instr->FunctionFieldRaw()) { 2655 case INS: 2656 // Ins instr leaves result in Rt, rather than Rd. 2657 set_register(rt_reg, alu_out); 2658 break; 2659 case EXT: 2660 // Ext instr leaves result in Rt, rather than Rd. 2661 set_register(rt_reg, alu_out); 2662 break; 2663 default: 2664 UNREACHABLE(); 2665 } 2666 break; 2667 // Unimplemented opcodes raised an error in the configuration step before, 2668 // so we can use the default here to set the destination register in common 2669 // cases. 2670 default: 2671 set_register(rd_reg, alu_out); 2672 } 2673 } 2674 2675 2676 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). 2677 void Simulator::DecodeTypeImmediate(Instruction* instr) { 2678 // Instruction fields. 2679 Opcode op = instr->OpcodeFieldRaw(); 2680 int32_t rs = get_register(instr->RsValue()); 2681 uint32_t rs_u = static_cast<uint32_t>(rs); 2682 int32_t rt_reg = instr->RtValue(); // Destination register. 2683 int32_t rt = get_register(rt_reg); 2684 int16_t imm16 = instr->Imm16Value(); 2685 2686 int32_t ft_reg = instr->FtValue(); // Destination register. 2687 int64_t ft; 2688 2689 // Zero extended immediate. 2690 uint32_t oe_imm16 = 0xffff & imm16; 2691 // Sign extended immediate. 2692 int32_t se_imm16 = imm16; 2693 2694 // Get current pc. 2695 int32_t current_pc = get_pc(); 2696 // Next pc. 2697 int32_t next_pc = bad_ra; 2698 2699 // Used for conditional branch instructions. 2700 bool do_branch = false; 2701 bool execute_branch_delay_instruction = false; 2702 2703 // Used for arithmetic instructions. 2704 int32_t alu_out = 0; 2705 // Floating point. 2706 double fp_out = 0.0; 2707 uint32_t cc, cc_value, fcsr_cc; 2708 2709 // Used for memory instructions. 2710 int32_t addr = 0x0; 2711 // Value to be written in memory. 2712 uint32_t mem_value = 0x0; 2713 2714 // ---------- Configuration (and execution for REGIMM). 2715 switch (op) { 2716 // ------------- COP1. Coprocessor instructions. 2717 case COP1: 2718 switch (instr->RsFieldRaw()) { 2719 case BC1: // Branch on coprocessor condition. 2720 cc = instr->FBccValue(); 2721 fcsr_cc = get_fcsr_condition_bit(cc); 2722 cc_value = test_fcsr_bit(fcsr_cc); 2723 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; 2724 execute_branch_delay_instruction = true; 2725 // Set next_pc. 2726 if (do_branch) { 2727 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2728 } else { 2729 next_pc = current_pc + kBranchReturnOffset; 2730 } 2731 break; 2732 case BC1EQZ: 2733 ft = get_fpu_register(ft_reg); 2734 do_branch = (ft & 0x1) ? false : true; 2735 execute_branch_delay_instruction = true; 2736 // Set next_pc. 2737 if (do_branch) { 2738 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2739 } else { 2740 next_pc = current_pc + kBranchReturnOffset; 2741 } 2742 break; 2743 case BC1NEZ: 2744 ft = get_fpu_register(ft_reg); 2745 do_branch = (ft & 0x1) ? true : false; 2746 execute_branch_delay_instruction = true; 2747 // Set next_pc. 2748 if (do_branch) { 2749 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2750 } else { 2751 next_pc = current_pc + kBranchReturnOffset; 2752 } 2753 break; 2754 default: 2755 UNREACHABLE(); 2756 } 2757 break; 2758 // ------------- REGIMM class. 2759 case REGIMM: 2760 switch (instr->RtFieldRaw()) { 2761 case BLTZ: 2762 do_branch = (rs < 0); 2763 break; 2764 case BLTZAL: 2765 do_branch = rs < 0; 2766 break; 2767 case BGEZ: 2768 do_branch = rs >= 0; 2769 break; 2770 case BGEZAL: 2771 do_branch = rs >= 0; 2772 break; 2773 default: 2774 UNREACHABLE(); 2775 } 2776 switch (instr->RtFieldRaw()) { 2777 case BLTZ: 2778 case BLTZAL: 2779 case BGEZ: 2780 case BGEZAL: 2781 // Branch instructions common part. 2782 execute_branch_delay_instruction = true; 2783 // Set next_pc. 2784 if (do_branch) { 2785 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2786 if (instr->IsLinkingInstruction()) { 2787 set_register(31, current_pc + kBranchReturnOffset); 2788 } 2789 } else { 2790 next_pc = current_pc + kBranchReturnOffset; 2791 } 2792 default: 2793 break; 2794 } 2795 break; // case REGIMM. 2796 // ------------- Branch instructions. 2797 // When comparing to zero, the encoding of rt field is always 0, so we don't 2798 // need to replace rt with zero. 2799 case BEQ: 2800 do_branch = (rs == rt); 2801 break; 2802 case BNE: 2803 do_branch = rs != rt; 2804 break; 2805 case BLEZ: 2806 do_branch = rs <= 0; 2807 break; 2808 case BGTZ: 2809 do_branch = rs > 0; 2810 break; 2811 // ------------- Arithmetic instructions. 2812 case ADDI: 2813 if (HaveSameSign(rs, se_imm16)) { 2814 if (rs > 0) { 2815 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); 2816 } else if (rs < 0) { 2817 exceptions[kIntegerUnderflow] = 2818 rs < (Registers::kMinValue - se_imm16); 2819 } 2820 } 2821 alu_out = rs + se_imm16; 2822 break; 2823 case ADDIU: 2824 alu_out = rs + se_imm16; 2825 break; 2826 case SLTI: 2827 alu_out = (rs < se_imm16) ? 1 : 0; 2828 break; 2829 case SLTIU: 2830 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0; 2831 break; 2832 case ANDI: 2833 alu_out = rs & oe_imm16; 2834 break; 2835 case ORI: 2836 alu_out = rs | oe_imm16; 2837 break; 2838 case XORI: 2839 alu_out = rs ^ oe_imm16; 2840 break; 2841 case LUI: 2842 alu_out = (oe_imm16 << 16); 2843 break; 2844 // ------------- Memory instructions. 2845 case LB: 2846 addr = rs + se_imm16; 2847 alu_out = ReadB(addr); 2848 break; 2849 case LH: 2850 addr = rs + se_imm16; 2851 alu_out = ReadH(addr, instr); 2852 break; 2853 case LWL: { 2854 // al_offset is offset of the effective address within an aligned word. 2855 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 2856 uint8_t byte_shift = kPointerAlignmentMask - al_offset; 2857 uint32_t mask = (1 << byte_shift * 8) - 1; 2858 addr = rs + se_imm16 - al_offset; 2859 alu_out = ReadW(addr, instr); 2860 alu_out <<= byte_shift * 8; 2861 alu_out |= rt & mask; 2862 break; 2863 } 2864 case LW: 2865 addr = rs + se_imm16; 2866 alu_out = ReadW(addr, instr); 2867 break; 2868 case LBU: 2869 addr = rs + se_imm16; 2870 alu_out = ReadBU(addr); 2871 break; 2872 case LHU: 2873 addr = rs + se_imm16; 2874 alu_out = ReadHU(addr, instr); 2875 break; 2876 case LWR: { 2877 // al_offset is offset of the effective address within an aligned word. 2878 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 2879 uint8_t byte_shift = kPointerAlignmentMask - al_offset; 2880 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; 2881 addr = rs + se_imm16 - al_offset; 2882 alu_out = ReadW(addr, instr); 2883 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; 2884 alu_out |= rt & mask; 2885 break; 2886 } 2887 case SB: 2888 addr = rs + se_imm16; 2889 break; 2890 case SH: 2891 addr = rs + se_imm16; 2892 break; 2893 case SWL: { 2894 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 2895 uint8_t byte_shift = kPointerAlignmentMask - al_offset; 2896 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; 2897 addr = rs + se_imm16 - al_offset; 2898 mem_value = ReadW(addr, instr) & mask; 2899 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; 2900 break; 2901 } 2902 case SW: 2903 addr = rs + se_imm16; 2904 break; 2905 case SWR: { 2906 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; 2907 uint32_t mask = (1 << al_offset * 8) - 1; 2908 addr = rs + se_imm16 - al_offset; 2909 mem_value = ReadW(addr, instr); 2910 mem_value = (rt << al_offset * 8) | (mem_value & mask); 2911 break; 2912 } 2913 case LWC1: 2914 addr = rs + se_imm16; 2915 alu_out = ReadW(addr, instr); 2916 break; 2917 case LDC1: 2918 addr = rs + se_imm16; 2919 fp_out = ReadD(addr, instr); 2920 break; 2921 case SWC1: 2922 case SDC1: 2923 addr = rs + se_imm16; 2924 break; 2925 default: 2926 UNREACHABLE(); 2927 } 2928 2929 // ---------- Raise exceptions triggered. 2930 SignalExceptions(); 2931 2932 // ---------- Execution. 2933 switch (op) { 2934 // ------------- Branch instructions. 2935 case BEQ: 2936 case BNE: 2937 case BLEZ: 2938 case BGTZ: 2939 // Branch instructions common part. 2940 execute_branch_delay_instruction = true; 2941 // Set next_pc. 2942 if (do_branch) { 2943 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 2944 if (instr->IsLinkingInstruction()) { 2945 set_register(31, current_pc + 2* Instruction::kInstrSize); 2946 } 2947 } else { 2948 next_pc = current_pc + 2 * Instruction::kInstrSize; 2949 } 2950 break; 2951 // ------------- Arithmetic instructions. 2952 case ADDI: 2953 case ADDIU: 2954 case SLTI: 2955 case SLTIU: 2956 case ANDI: 2957 case ORI: 2958 case XORI: 2959 case LUI: 2960 set_register(rt_reg, alu_out); 2961 break; 2962 // ------------- Memory instructions. 2963 case LB: 2964 case LH: 2965 case LWL: 2966 case LW: 2967 case LBU: 2968 case LHU: 2969 case LWR: 2970 set_register(rt_reg, alu_out); 2971 break; 2972 case SB: 2973 WriteB(addr, static_cast<int8_t>(rt)); 2974 break; 2975 case SH: 2976 WriteH(addr, static_cast<uint16_t>(rt), instr); 2977 break; 2978 case SWL: 2979 WriteW(addr, mem_value, instr); 2980 break; 2981 case SW: 2982 WriteW(addr, rt, instr); 2983 break; 2984 case SWR: 2985 WriteW(addr, mem_value, instr); 2986 break; 2987 case LWC1: 2988 set_fpu_register_hi_word(ft_reg, 0); 2989 set_fpu_register_word(ft_reg, alu_out); 2990 break; 2991 case LDC1: 2992 set_fpu_register_double(ft_reg, fp_out); 2993 break; 2994 case SWC1: 2995 addr = rs + se_imm16; 2996 WriteW(addr, get_fpu_register_word(ft_reg), instr); 2997 break; 2998 case SDC1: 2999 addr = rs + se_imm16; 3000 WriteD(addr, get_fpu_register_double(ft_reg), instr); 3001 break; 3002 default: 3003 break; 3004 } 3005 3006 3007 if (execute_branch_delay_instruction) { 3008 // Execute branch delay slot 3009 // We don't check for end_sim_pc. First it should not be met as the current 3010 // pc is valid. Secondly a jump should always execute its branch delay slot. 3011 Instruction* branch_delay_instr = 3012 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize); 3013 BranchDelayInstructionDecode(branch_delay_instr); 3014 } 3015 3016 // If needed update pc after the branch delay execution. 3017 if (next_pc != bad_ra) { 3018 set_pc(next_pc); 3019 } 3020 } 3021 3022 3023 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). 3024 void Simulator::DecodeTypeJump(Instruction* instr) { 3025 // Get current pc. 3026 int32_t current_pc = get_pc(); 3027 // Get unchanged bits of pc. 3028 int32_t pc_high_bits = current_pc & 0xf0000000; 3029 // Next pc. 3030 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); 3031 3032 // Execute branch delay slot. 3033 // We don't check for end_sim_pc. First it should not be met as the current pc 3034 // is valid. Secondly a jump should always execute its branch delay slot. 3035 Instruction* branch_delay_instr = 3036 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 3037 BranchDelayInstructionDecode(branch_delay_instr); 3038 3039 // Update pc and ra if necessary. 3040 // Do this after the branch delay execution. 3041 if (instr->IsLinkingInstruction()) { 3042 set_register(31, current_pc + 2 * Instruction::kInstrSize); 3043 } 3044 set_pc(next_pc); 3045 pc_modified_ = true; 3046 } 3047 3048 3049 // Executes the current instruction. 3050 void Simulator::InstructionDecode(Instruction* instr) { 3051 if (v8::internal::FLAG_check_icache) { 3052 CheckICache(isolate_->simulator_i_cache(), instr); 3053 } 3054 pc_modified_ = false; 3055 if (::v8::internal::FLAG_trace_sim) { 3056 disasm::NameConverter converter; 3057 disasm::Disassembler dasm(converter); 3058 // Use a reasonably large buffer. 3059 v8::internal::EmbeddedVector<char, 256> buffer; 3060 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); 3061 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), 3062 buffer.start()); 3063 } 3064 3065 switch (instr->InstructionType()) { 3066 case Instruction::kRegisterType: 3067 DecodeTypeRegister(instr); 3068 break; 3069 case Instruction::kImmediateType: 3070 DecodeTypeImmediate(instr); 3071 break; 3072 case Instruction::kJumpType: 3073 DecodeTypeJump(instr); 3074 break; 3075 default: 3076 UNSUPPORTED(); 3077 } 3078 if (!pc_modified_) { 3079 set_register(pc, reinterpret_cast<int32_t>(instr) + 3080 Instruction::kInstrSize); 3081 } 3082 } 3083 3084 3085 3086 void Simulator::Execute() { 3087 // Get the PC to simulate. Cannot use the accessor here as we need the 3088 // raw PC value and not the one used as input to arithmetic instructions. 3089 int program_counter = get_pc(); 3090 if (::v8::internal::FLAG_stop_sim_at == 0) { 3091 // Fast version of the dispatch loop without checking whether the simulator 3092 // should be stopping at a particular executed instruction. 3093 while (program_counter != end_sim_pc) { 3094 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3095 icount_++; 3096 InstructionDecode(instr); 3097 program_counter = get_pc(); 3098 } 3099 } else { 3100 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 3101 // we reach the particular instuction count. 3102 while (program_counter != end_sim_pc) { 3103 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3104 icount_++; 3105 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 3106 MipsDebugger dbg(this); 3107 dbg.Debug(); 3108 } else { 3109 InstructionDecode(instr); 3110 } 3111 program_counter = get_pc(); 3112 } 3113 } 3114 } 3115 3116 3117 void Simulator::CallInternal(byte* entry) { 3118 // Prepare to execute the code at entry. 3119 set_register(pc, reinterpret_cast<int32_t>(entry)); 3120 // Put down marker for end of simulation. The simulator will stop simulation 3121 // when the PC reaches this value. By saving the "end simulation" value into 3122 // the LR the simulation stops when returning to this call point. 3123 set_register(ra, end_sim_pc); 3124 3125 // Remember the values of callee-saved registers. 3126 // The code below assumes that r9 is not used as sb (static base) in 3127 // simulator code and therefore is regarded as a callee-saved register. 3128 int32_t s0_val = get_register(s0); 3129 int32_t s1_val = get_register(s1); 3130 int32_t s2_val = get_register(s2); 3131 int32_t s3_val = get_register(s3); 3132 int32_t s4_val = get_register(s4); 3133 int32_t s5_val = get_register(s5); 3134 int32_t s6_val = get_register(s6); 3135 int32_t s7_val = get_register(s7); 3136 int32_t gp_val = get_register(gp); 3137 int32_t sp_val = get_register(sp); 3138 int32_t fp_val = get_register(fp); 3139 3140 // Set up the callee-saved registers with a known value. To be able to check 3141 // that they are preserved properly across JS execution. 3142 int32_t callee_saved_value = icount_; 3143 set_register(s0, callee_saved_value); 3144 set_register(s1, callee_saved_value); 3145 set_register(s2, callee_saved_value); 3146 set_register(s3, callee_saved_value); 3147 set_register(s4, callee_saved_value); 3148 set_register(s5, callee_saved_value); 3149 set_register(s6, callee_saved_value); 3150 set_register(s7, callee_saved_value); 3151 set_register(gp, callee_saved_value); 3152 set_register(fp, callee_saved_value); 3153 3154 // Start the simulation. 3155 Execute(); 3156 3157 // Check that the callee-saved registers have been preserved. 3158 CHECK_EQ(callee_saved_value, get_register(s0)); 3159 CHECK_EQ(callee_saved_value, get_register(s1)); 3160 CHECK_EQ(callee_saved_value, get_register(s2)); 3161 CHECK_EQ(callee_saved_value, get_register(s3)); 3162 CHECK_EQ(callee_saved_value, get_register(s4)); 3163 CHECK_EQ(callee_saved_value, get_register(s5)); 3164 CHECK_EQ(callee_saved_value, get_register(s6)); 3165 CHECK_EQ(callee_saved_value, get_register(s7)); 3166 CHECK_EQ(callee_saved_value, get_register(gp)); 3167 CHECK_EQ(callee_saved_value, get_register(fp)); 3168 3169 // Restore callee-saved registers with the original value. 3170 set_register(s0, s0_val); 3171 set_register(s1, s1_val); 3172 set_register(s2, s2_val); 3173 set_register(s3, s3_val); 3174 set_register(s4, s4_val); 3175 set_register(s5, s5_val); 3176 set_register(s6, s6_val); 3177 set_register(s7, s7_val); 3178 set_register(gp, gp_val); 3179 set_register(sp, sp_val); 3180 set_register(fp, fp_val); 3181 } 3182 3183 3184 int32_t Simulator::Call(byte* entry, int argument_count, ...) { 3185 va_list parameters; 3186 va_start(parameters, argument_count); 3187 // Set up arguments. 3188 3189 // First four arguments passed in registers. 3190 DCHECK(argument_count >= 4); 3191 set_register(a0, va_arg(parameters, int32_t)); 3192 set_register(a1, va_arg(parameters, int32_t)); 3193 set_register(a2, va_arg(parameters, int32_t)); 3194 set_register(a3, va_arg(parameters, int32_t)); 3195 3196 // Remaining arguments passed on stack. 3197 int original_stack = get_register(sp); 3198 // Compute position of stack on entry to generated code. 3199 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t) 3200 - kCArgsSlotsSize); 3201 if (base::OS::ActivationFrameAlignment() != 0) { 3202 entry_stack &= -base::OS::ActivationFrameAlignment(); 3203 } 3204 // Store remaining arguments on stack, from low to high memory. 3205 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 3206 for (int i = 4; i < argument_count; i++) { 3207 stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t); 3208 } 3209 va_end(parameters); 3210 set_register(sp, entry_stack); 3211 3212 CallInternal(entry); 3213 3214 // Pop stack passed arguments. 3215 CHECK_EQ(entry_stack, get_register(sp)); 3216 set_register(sp, original_stack); 3217 3218 int32_t result = get_register(v0); 3219 return result; 3220 } 3221 3222 3223 double Simulator::CallFP(byte* entry, double d0, double d1) { 3224 if (!IsMipsSoftFloatABI) { 3225 set_fpu_register_double(f12, d0); 3226 set_fpu_register_double(f14, d1); 3227 } else { 3228 int buffer[2]; 3229 DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0)); 3230 memcpy(buffer, &d0, sizeof(d0)); 3231 set_dw_register(a0, buffer); 3232 memcpy(buffer, &d1, sizeof(d1)); 3233 set_dw_register(a2, buffer); 3234 } 3235 CallInternal(entry); 3236 if (!IsMipsSoftFloatABI) { 3237 return get_fpu_register_double(f0); 3238 } else { 3239 return get_double_from_register_pair(v0); 3240 } 3241 } 3242 3243 3244 uintptr_t Simulator::PushAddress(uintptr_t address) { 3245 int new_sp = get_register(sp) - sizeof(uintptr_t); 3246 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 3247 *stack_slot = address; 3248 set_register(sp, new_sp); 3249 return new_sp; 3250 } 3251 3252 3253 uintptr_t Simulator::PopAddress() { 3254 int current_sp = get_register(sp); 3255 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 3256 uintptr_t address = *stack_slot; 3257 set_register(sp, current_sp + sizeof(uintptr_t)); 3258 return address; 3259 } 3260 3261 3262 #undef UNSUPPORTED 3263 3264 } } // namespace v8::internal 3265 3266 #endif // USE_SIMULATOR 3267 3268 #endif // V8_TARGET_ARCH_MIPS 3269