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