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