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#if V8_TARGET_ARCH_MIPS64 11 12#include "src/assembler.h" 13#include "src/base/bits.h" 14#include "src/codegen.h" 15#include "src/disasm.h" 16#include "src/mips64/constants-mips64.h" 17#include "src/mips64/simulator-mips64.h" 18#include "src/ostreams.h" 19#include "src/runtime/runtime-utils.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// Util functions. 28inline bool HaveSameSign(int64_t a, int64_t b) { return ((a ^ b) >= 0); } 29 30uint32_t get_fcsr_condition_bit(uint32_t cc) { 31 if (cc == 0) { 32 return 23; 33 } else { 34 return 24 + cc; 35 } 36} 37 38 39static int64_t MultiplyHighSigned(int64_t u, int64_t v) { 40 uint64_t u0, v0, w0; 41 int64_t u1, v1, w1, w2, t; 42 43 u0 = u & 0xffffffffL; 44 u1 = u >> 32; 45 v0 = v & 0xffffffffL; 46 v1 = v >> 32; 47 48 w0 = u0 * v0; 49 t = u1 * v0 + (w0 >> 32); 50 w1 = t & 0xffffffffL; 51 w2 = t >> 32; 52 w1 = u0 * v1 + w1; 53 54 return u1 * v1 + w2 + (w1 >> 32); 55} 56 57 58// This macro provides a platform independent use of sscanf. The reason for 59// SScanF not being implemented in a platform independent was through 60// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time 61// Library does not provide vsscanf. 62#define SScanF sscanf // NOLINT 63 64// The MipsDebugger class is used by the simulator while debugging simulated 65// code. 66class MipsDebugger { 67 public: 68 explicit MipsDebugger(Simulator* sim) : sim_(sim) { } 69 70 void Stop(Instruction* instr); 71 void Debug(); 72 // Print all registers with a nice formatting. 73 void PrintAllRegs(); 74 void PrintAllRegsIncludingFPU(); 75 76 private: 77 // We set the breakpoint code to 0xfffff to easily recognize it. 78 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; 79 static const Instr kNopInstr = 0x0; 80 81 Simulator* sim_; 82 83 int64_t GetRegisterValue(int regnum); 84 int64_t GetFPURegisterValue(int regnum); 85 float GetFPURegisterValueFloat(int regnum); 86 double GetFPURegisterValueDouble(int regnum); 87 bool GetValue(const char* desc, int64_t* value); 88 89 // Set or delete a breakpoint. Returns true if successful. 90 bool SetBreakpoint(Instruction* breakpc); 91 bool DeleteBreakpoint(Instruction* breakpc); 92 93 // Undo and redo all breakpoints. This is needed to bracket disassembly and 94 // execution to skip past breakpoints when run from the debugger. 95 void UndoBreakpoints(); 96 void RedoBreakpoints(); 97}; 98 99inline void UNSUPPORTED() { printf("Sim: Unsupported instruction.\n"); } 100 101void MipsDebugger::Stop(Instruction* instr) { 102 // Get the stop code. 103 uint32_t code = instr->Bits(25, 6); 104 PrintF("Simulator hit (%u)\n", code); 105 // TODO(yuyin): 2 -> 3? 106 sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize); 107 Debug(); 108} 109 110int64_t MipsDebugger::GetRegisterValue(int regnum) { 111 if (regnum == kNumSimuRegisters) { 112 return sim_->get_pc(); 113 } else { 114 return sim_->get_register(regnum); 115 } 116} 117 118 119int64_t MipsDebugger::GetFPURegisterValue(int regnum) { 120 if (regnum == kNumFPURegisters) { 121 return sim_->get_pc(); 122 } else { 123 return sim_->get_fpu_register(regnum); 124 } 125} 126 127 128float MipsDebugger::GetFPURegisterValueFloat(int regnum) { 129 if (regnum == kNumFPURegisters) { 130 return sim_->get_pc(); 131 } else { 132 return sim_->get_fpu_register_float(regnum); 133 } 134} 135 136 137double MipsDebugger::GetFPURegisterValueDouble(int regnum) { 138 if (regnum == kNumFPURegisters) { 139 return sim_->get_pc(); 140 } else { 141 return sim_->get_fpu_register_double(regnum); 142 } 143} 144 145 146bool MipsDebugger::GetValue(const char* desc, int64_t* value) { 147 int regnum = Registers::Number(desc); 148 int fpuregnum = FPURegisters::Number(desc); 149 150 if (regnum != kInvalidRegister) { 151 *value = GetRegisterValue(regnum); 152 return true; 153 } else if (fpuregnum != kInvalidFPURegister) { 154 *value = GetFPURegisterValue(fpuregnum); 155 return true; 156 } else if (strncmp(desc, "0x", 2) == 0) { 157 return SScanF(desc + 2, "%" SCNx64, 158 reinterpret_cast<uint64_t*>(value)) == 1; 159 } else { 160 return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1; 161 } 162 return false; 163} 164 165 166bool MipsDebugger::SetBreakpoint(Instruction* breakpc) { 167 // Check if a breakpoint can be set. If not return without any side-effects. 168 if (sim_->break_pc_ != NULL) { 169 return false; 170 } 171 172 // Set the breakpoint. 173 sim_->break_pc_ = breakpc; 174 sim_->break_instr_ = breakpc->InstructionBits(); 175 // Not setting the breakpoint instruction in the code itself. It will be set 176 // when the debugger shell continues. 177 return true; 178} 179 180 181bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) { 182 if (sim_->break_pc_ != NULL) { 183 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 184 } 185 186 sim_->break_pc_ = NULL; 187 sim_->break_instr_ = 0; 188 return true; 189} 190 191 192void MipsDebugger::UndoBreakpoints() { 193 if (sim_->break_pc_ != NULL) { 194 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 195 } 196} 197 198 199void MipsDebugger::RedoBreakpoints() { 200 if (sim_->break_pc_ != NULL) { 201 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 202 } 203} 204 205 206void MipsDebugger::PrintAllRegs() { 207#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 208 209 PrintF("\n"); 210 // at, v0, a0. 211 PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 "\t%3s: 0x%016" PRIx64 " %14" PRId64 212 "\t%3s: 0x%016" PRIx64 " %14" PRId64 "\n", 213 REG_INFO(1), REG_INFO(2), REG_INFO(4)); 214 // v1, a1. 215 PrintF("%34s\t%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64 216 " %14" PRId64 " \n", 217 "", REG_INFO(3), REG_INFO(5)); 218 // a2. 219 PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", "", "", 220 REG_INFO(6)); 221 // a3. 222 PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", "", "", 223 REG_INFO(7)); 224 PrintF("\n"); 225 // a4-t3, s0-s7 226 for (int i = 0; i < 8; i++) { 227 PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64 228 " %14" PRId64 " \n", 229 REG_INFO(8 + i), REG_INFO(16 + i)); 230 } 231 PrintF("\n"); 232 // t8, k0, LO. 233 PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64 234 " %14" PRId64 " \t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", 235 REG_INFO(24), REG_INFO(26), REG_INFO(32)); 236 // t9, k1, HI. 237 PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64 238 " %14" PRId64 " \t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", 239 REG_INFO(25), REG_INFO(27), REG_INFO(33)); 240 // sp, fp, gp. 241 PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64 242 " %14" PRId64 " \t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", 243 REG_INFO(29), REG_INFO(30), REG_INFO(28)); 244 // pc. 245 PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64 246 " %14" PRId64 " \n", 247 REG_INFO(31), REG_INFO(34)); 248 249#undef REG_INFO 250#undef FPU_REG_INFO 251} 252 253 254void MipsDebugger::PrintAllRegsIncludingFPU() { 255#define FPU_REG_INFO(n) FPURegisters::Name(n), \ 256 GetFPURegisterValue(n), \ 257 GetFPURegisterValueDouble(n) 258 259 PrintAllRegs(); 260 261 PrintF("\n\n"); 262 // f0, f1, f2, ... f31. 263 // TODO(plind): consider printing 2 columns for space efficiency. 264 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(0)); 265 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(1)); 266 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(2)); 267 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(3)); 268 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(4)); 269 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(5)); 270 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(6)); 271 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(7)); 272 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(8)); 273 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(9)); 274 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(10)); 275 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(11)); 276 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(12)); 277 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(13)); 278 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(14)); 279 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(15)); 280 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(16)); 281 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(17)); 282 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(18)); 283 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(19)); 284 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(20)); 285 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(21)); 286 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(22)); 287 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(23)); 288 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(24)); 289 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(25)); 290 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(26)); 291 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(27)); 292 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(28)); 293 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(29)); 294 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(30)); 295 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(31)); 296 297#undef REG_INFO 298#undef FPU_REG_INFO 299} 300 301 302void MipsDebugger::Debug() { 303 intptr_t last_pc = -1; 304 bool done = false; 305 306#define COMMAND_SIZE 63 307#define ARG_SIZE 255 308 309#define STR(a) #a 310#define XSTR(a) STR(a) 311 312 char cmd[COMMAND_SIZE + 1]; 313 char arg1[ARG_SIZE + 1]; 314 char arg2[ARG_SIZE + 1]; 315 char* argv[3] = { cmd, arg1, arg2 }; 316 317 // Make sure to have a proper terminating character if reaching the limit. 318 cmd[COMMAND_SIZE] = 0; 319 arg1[ARG_SIZE] = 0; 320 arg2[ARG_SIZE] = 0; 321 322 // Undo all set breakpoints while running in the debugger shell. This will 323 // make them invisible to all commands. 324 UndoBreakpoints(); 325 326 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) { 327 if (last_pc != sim_->get_pc()) { 328 disasm::NameConverter converter; 329 disasm::Disassembler dasm(converter); 330 // Use a reasonably large buffer. 331 v8::internal::EmbeddedVector<char, 256> buffer; 332 dasm.InstructionDecode(buffer, 333 reinterpret_cast<byte*>(sim_->get_pc())); 334 PrintF(" 0x%016" PRIx64 " %s\n", sim_->get_pc(), buffer.start()); 335 last_pc = sim_->get_pc(); 336 } 337 char* line = ReadLine("sim> "); 338 if (line == NULL) { 339 break; 340 } else { 341 char* last_input = sim_->last_debugger_input(); 342 if (strcmp(line, "\n") == 0 && last_input != NULL) { 343 line = last_input; 344 } else { 345 // Ownership is transferred to sim_; 346 sim_->set_last_debugger_input(line); 347 } 348 // Use sscanf to parse the individual parts of the command line. At the 349 // moment no command expects more than two parameters. 350 int argc = SScanF(line, 351 "%" XSTR(COMMAND_SIZE) "s " 352 "%" XSTR(ARG_SIZE) "s " 353 "%" XSTR(ARG_SIZE) "s", 354 cmd, arg1, arg2); 355 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 356 Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc()); 357 if (!(instr->IsTrap()) || 358 instr->InstructionBits() == rtCallRedirInstr) { 359 sim_->InstructionDecode( 360 reinterpret_cast<Instruction*>(sim_->get_pc())); 361 } else { 362 // Allow si to jump over generated breakpoints. 363 PrintF("/!\\ Jumping over generated breakpoint.\n"); 364 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); 365 } 366 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 367 // Execute the one instruction we broke at with breakpoints disabled. 368 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 369 // Leave the debugger shell. 370 done = true; 371 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 372 if (argc == 2) { 373 int64_t value; 374 double dvalue; 375 if (strcmp(arg1, "all") == 0) { 376 PrintAllRegs(); 377 } else if (strcmp(arg1, "allf") == 0) { 378 PrintAllRegsIncludingFPU(); 379 } else { 380 int regnum = Registers::Number(arg1); 381 int fpuregnum = FPURegisters::Number(arg1); 382 383 if (regnum != kInvalidRegister) { 384 value = GetRegisterValue(regnum); 385 PrintF("%s: 0x%08" PRIx64 " %" PRId64 " \n", arg1, value, 386 value); 387 } else if (fpuregnum != kInvalidFPURegister) { 388 value = GetFPURegisterValue(fpuregnum); 389 dvalue = GetFPURegisterValueDouble(fpuregnum); 390 PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", 391 FPURegisters::Name(fpuregnum), value, dvalue); 392 } else { 393 PrintF("%s unrecognized\n", arg1); 394 } 395 } 396 } else { 397 if (argc == 3) { 398 if (strcmp(arg2, "single") == 0) { 399 int64_t value; 400 float fvalue; 401 int fpuregnum = FPURegisters::Number(arg1); 402 403 if (fpuregnum != kInvalidFPURegister) { 404 value = GetFPURegisterValue(fpuregnum); 405 value &= 0xffffffffUL; 406 fvalue = GetFPURegisterValueFloat(fpuregnum); 407 PrintF("%s: 0x%08" PRIx64 " %11.4e\n", arg1, value, fvalue); 408 } else { 409 PrintF("%s unrecognized\n", arg1); 410 } 411 } else { 412 PrintF("print <fpu register> single\n"); 413 } 414 } else { 415 PrintF("print <register> or print <fpu register> single\n"); 416 } 417 } 418 } else if ((strcmp(cmd, "po") == 0) 419 || (strcmp(cmd, "printobject") == 0)) { 420 if (argc == 2) { 421 int64_t value; 422 OFStream os(stdout); 423 if (GetValue(arg1, &value)) { 424 Object* obj = reinterpret_cast<Object*>(value); 425 os << arg1 << ": \n"; 426#ifdef DEBUG 427 obj->Print(os); 428 os << "\n"; 429#else 430 os << Brief(obj) << "\n"; 431#endif 432 } else { 433 os << arg1 << " unrecognized\n"; 434 } 435 } else { 436 PrintF("printobject <value>\n"); 437 } 438 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 439 int64_t* cur = NULL; 440 int64_t* end = NULL; 441 int next_arg = 1; 442 443 if (strcmp(cmd, "stack") == 0) { 444 cur = reinterpret_cast<int64_t*>(sim_->get_register(Simulator::sp)); 445 } else { // Command "mem". 446 int64_t value; 447 if (!GetValue(arg1, &value)) { 448 PrintF("%s unrecognized\n", arg1); 449 continue; 450 } 451 cur = reinterpret_cast<int64_t*>(value); 452 next_arg++; 453 } 454 455 int64_t words; 456 if (argc == next_arg) { 457 words = 10; 458 } else { 459 if (!GetValue(argv[next_arg], &words)) { 460 words = 10; 461 } 462 } 463 end = cur + words; 464 465 while (cur < end) { 466 PrintF(" 0x%012" PRIxPTR " : 0x%016" PRIx64 " %14" PRId64 " ", 467 reinterpret_cast<intptr_t>(cur), *cur, *cur); 468 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 469 int64_t value = *cur; 470 Heap* current_heap = sim_->isolate_->heap(); 471 if (((value & 1) == 0) || 472 current_heap->ContainsSlow(obj->address())) { 473 PrintF(" ("); 474 if ((value & 1) == 0) { 475 PrintF("smi %d", static_cast<int>(value >> 32)); 476 } else { 477 obj->ShortPrint(); 478 } 479 PrintF(")"); 480 } 481 PrintF("\n"); 482 cur++; 483 } 484 485 } else if ((strcmp(cmd, "disasm") == 0) || 486 (strcmp(cmd, "dpc") == 0) || 487 (strcmp(cmd, "di") == 0)) { 488 disasm::NameConverter converter; 489 disasm::Disassembler dasm(converter); 490 // Use a reasonably large buffer. 491 v8::internal::EmbeddedVector<char, 256> buffer; 492 493 byte* cur = NULL; 494 byte* end = NULL; 495 496 if (argc == 1) { 497 cur = reinterpret_cast<byte*>(sim_->get_pc()); 498 end = cur + (10 * Instruction::kInstrSize); 499 } else if (argc == 2) { 500 int regnum = Registers::Number(arg1); 501 if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) { 502 // The argument is an address or a register name. 503 int64_t value; 504 if (GetValue(arg1, &value)) { 505 cur = reinterpret_cast<byte*>(value); 506 // Disassemble 10 instructions at <arg1>. 507 end = cur + (10 * Instruction::kInstrSize); 508 } 509 } else { 510 // The argument is the number of instructions. 511 int64_t value; 512 if (GetValue(arg1, &value)) { 513 cur = reinterpret_cast<byte*>(sim_->get_pc()); 514 // Disassemble <arg1> instructions. 515 end = cur + (value * Instruction::kInstrSize); 516 } 517 } 518 } else { 519 int64_t value1; 520 int64_t value2; 521 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 522 cur = reinterpret_cast<byte*>(value1); 523 end = cur + (value2 * Instruction::kInstrSize); 524 } 525 } 526 527 while (cur < end) { 528 dasm.InstructionDecode(buffer, cur); 529 PrintF(" 0x%08" PRIxPTR " %s\n", reinterpret_cast<intptr_t>(cur), 530 buffer.start()); 531 cur += Instruction::kInstrSize; 532 } 533 } else if (strcmp(cmd, "gdb") == 0) { 534 PrintF("relinquishing control to gdb\n"); 535 v8::base::OS::DebugBreak(); 536 PrintF("regaining control from gdb\n"); 537 } else if (strcmp(cmd, "break") == 0) { 538 if (argc == 2) { 539 int64_t value; 540 if (GetValue(arg1, &value)) { 541 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 542 PrintF("setting breakpoint failed\n"); 543 } 544 } else { 545 PrintF("%s unrecognized\n", arg1); 546 } 547 } else { 548 PrintF("break <address>\n"); 549 } 550 } else if (strcmp(cmd, "del") == 0) { 551 if (!DeleteBreakpoint(NULL)) { 552 PrintF("deleting breakpoint failed\n"); 553 } 554 } else if (strcmp(cmd, "flags") == 0) { 555 PrintF("No flags on MIPS !\n"); 556 } else if (strcmp(cmd, "stop") == 0) { 557 int64_t value; 558 intptr_t stop_pc = sim_->get_pc() - 559 2 * Instruction::kInstrSize; 560 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 561 Instruction* msg_address = 562 reinterpret_cast<Instruction*>(stop_pc + 563 Instruction::kInstrSize); 564 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 565 // Remove the current stop. 566 if (sim_->IsStopInstruction(stop_instr)) { 567 stop_instr->SetInstructionBits(kNopInstr); 568 msg_address->SetInstructionBits(kNopInstr); 569 } else { 570 PrintF("Not at debugger stop.\n"); 571 } 572 } else if (argc == 3) { 573 // Print information about all/the specified breakpoint(s). 574 if (strcmp(arg1, "info") == 0) { 575 if (strcmp(arg2, "all") == 0) { 576 PrintF("Stop information:\n"); 577 for (uint32_t i = kMaxWatchpointCode + 1; 578 i <= kMaxStopCode; 579 i++) { 580 sim_->PrintStopInfo(i); 581 } 582 } else if (GetValue(arg2, &value)) { 583 sim_->PrintStopInfo(value); 584 } else { 585 PrintF("Unrecognized argument.\n"); 586 } 587 } else if (strcmp(arg1, "enable") == 0) { 588 // Enable all/the specified breakpoint(s). 589 if (strcmp(arg2, "all") == 0) { 590 for (uint32_t i = kMaxWatchpointCode + 1; 591 i <= kMaxStopCode; 592 i++) { 593 sim_->EnableStop(i); 594 } 595 } else if (GetValue(arg2, &value)) { 596 sim_->EnableStop(value); 597 } else { 598 PrintF("Unrecognized argument.\n"); 599 } 600 } else if (strcmp(arg1, "disable") == 0) { 601 // Disable all/the specified breakpoint(s). 602 if (strcmp(arg2, "all") == 0) { 603 for (uint32_t i = kMaxWatchpointCode + 1; 604 i <= kMaxStopCode; 605 i++) { 606 sim_->DisableStop(i); 607 } 608 } else if (GetValue(arg2, &value)) { 609 sim_->DisableStop(value); 610 } else { 611 PrintF("Unrecognized argument.\n"); 612 } 613 } 614 } else { 615 PrintF("Wrong usage. Use help command for more information.\n"); 616 } 617 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { 618 // Print registers and disassemble. 619 PrintAllRegs(); 620 PrintF("\n"); 621 622 disasm::NameConverter converter; 623 disasm::Disassembler dasm(converter); 624 // Use a reasonably large buffer. 625 v8::internal::EmbeddedVector<char, 256> buffer; 626 627 byte* cur = NULL; 628 byte* end = NULL; 629 630 if (argc == 1) { 631 cur = reinterpret_cast<byte*>(sim_->get_pc()); 632 end = cur + (10 * Instruction::kInstrSize); 633 } else if (argc == 2) { 634 int64_t value; 635 if (GetValue(arg1, &value)) { 636 cur = reinterpret_cast<byte*>(value); 637 // no length parameter passed, assume 10 instructions 638 end = cur + (10 * Instruction::kInstrSize); 639 } 640 } else { 641 int64_t value1; 642 int64_t value2; 643 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 644 cur = reinterpret_cast<byte*>(value1); 645 end = cur + (value2 * Instruction::kInstrSize); 646 } 647 } 648 649 while (cur < end) { 650 dasm.InstructionDecode(buffer, cur); 651 PrintF(" 0x%08" PRIxPTR " %s\n", reinterpret_cast<intptr_t>(cur), 652 buffer.start()); 653 cur += Instruction::kInstrSize; 654 } 655 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 656 PrintF("cont\n"); 657 PrintF(" continue execution (alias 'c')\n"); 658 PrintF("stepi\n"); 659 PrintF(" step one instruction (alias 'si')\n"); 660 PrintF("print <register>\n"); 661 PrintF(" print register content (alias 'p')\n"); 662 PrintF(" use register name 'all' to print all registers\n"); 663 PrintF("printobject <register>\n"); 664 PrintF(" print an object from a register (alias 'po')\n"); 665 PrintF("stack [<words>]\n"); 666 PrintF(" dump stack content, default dump 10 words)\n"); 667 PrintF("mem <address> [<words>]\n"); 668 PrintF(" dump memory content, default dump 10 words)\n"); 669 PrintF("flags\n"); 670 PrintF(" print flags\n"); 671 PrintF("disasm [<instructions>]\n"); 672 PrintF("disasm [<address/register>]\n"); 673 PrintF("disasm [[<address/register>] <instructions>]\n"); 674 PrintF(" disassemble code, default is 10 instructions\n"); 675 PrintF(" from pc (alias 'di')\n"); 676 PrintF("gdb\n"); 677 PrintF(" enter gdb\n"); 678 PrintF("break <address>\n"); 679 PrintF(" set a break point on the address\n"); 680 PrintF("del\n"); 681 PrintF(" delete the breakpoint\n"); 682 PrintF("stop feature:\n"); 683 PrintF(" Description:\n"); 684 PrintF(" Stops are debug instructions inserted by\n"); 685 PrintF(" the Assembler::stop() function.\n"); 686 PrintF(" When hitting a stop, the Simulator will\n"); 687 PrintF(" stop and and give control to the Debugger.\n"); 688 PrintF(" All stop codes are watched:\n"); 689 PrintF(" - They can be enabled / disabled: the Simulator\n"); 690 PrintF(" will / won't stop when hitting them.\n"); 691 PrintF(" - The Simulator keeps track of how many times they \n"); 692 PrintF(" are met. (See the info command.) Going over a\n"); 693 PrintF(" disabled stop still increases its counter. \n"); 694 PrintF(" Commands:\n"); 695 PrintF(" stop info all/<code> : print infos about number <code>\n"); 696 PrintF(" or all stop(s).\n"); 697 PrintF(" stop enable/disable all/<code> : enables / disables\n"); 698 PrintF(" all or number <code> stop(s)\n"); 699 PrintF(" stop unstop\n"); 700 PrintF(" ignore the stop instruction at the current location\n"); 701 PrintF(" from now on\n"); 702 } else { 703 PrintF("Unknown command: %s\n", cmd); 704 } 705 } 706 } 707 708 // Add all the breakpoints back to stop execution and enter the debugger 709 // shell when hit. 710 RedoBreakpoints(); 711 712#undef COMMAND_SIZE 713#undef ARG_SIZE 714 715#undef STR 716#undef XSTR 717} 718 719 720static bool ICacheMatch(void* one, void* two) { 721 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); 722 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); 723 return one == two; 724} 725 726 727static uint32_t ICacheHash(void* key) { 728 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 729} 730 731 732static bool AllOnOnePage(uintptr_t start, size_t size) { 733 intptr_t start_page = (start & ~CachePage::kPageMask); 734 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 735 return start_page == end_page; 736} 737 738 739void Simulator::set_last_debugger_input(char* input) { 740 DeleteArray(last_debugger_input_); 741 last_debugger_input_ = input; 742} 743 744void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache, 745 void* start_addr, size_t size) { 746 int64_t start = reinterpret_cast<int64_t>(start_addr); 747 int64_t intra_line = (start & CachePage::kLineMask); 748 start -= intra_line; 749 size += intra_line; 750 size = ((size - 1) | CachePage::kLineMask) + 1; 751 int offset = (start & CachePage::kPageMask); 752 while (!AllOnOnePage(start, size - 1)) { 753 int bytes_to_flush = CachePage::kPageSize - offset; 754 FlushOnePage(i_cache, start, bytes_to_flush); 755 start += bytes_to_flush; 756 size -= bytes_to_flush; 757 DCHECK_EQ((int64_t)0, start & CachePage::kPageMask); 758 offset = 0; 759 } 760 if (size != 0) { 761 FlushOnePage(i_cache, start, size); 762 } 763} 764 765CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache, 766 void* page) { 767 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page)); 768 if (entry->value == NULL) { 769 CachePage* new_page = new CachePage(); 770 entry->value = new_page; 771 } 772 return reinterpret_cast<CachePage*>(entry->value); 773} 774 775 776// Flush from start up to and not including start + size. 777void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache, 778 intptr_t start, size_t size) { 779 DCHECK(size <= CachePage::kPageSize); 780 DCHECK(AllOnOnePage(start, size - 1)); 781 DCHECK((start & CachePage::kLineMask) == 0); 782 DCHECK((size & CachePage::kLineMask) == 0); 783 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 784 int offset = (start & CachePage::kPageMask); 785 CachePage* cache_page = GetCachePage(i_cache, page); 786 char* valid_bytemap = cache_page->ValidityByte(offset); 787 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 788} 789 790void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache, 791 Instruction* instr) { 792 int64_t address = reinterpret_cast<int64_t>(instr); 793 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 794 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 795 int offset = (address & CachePage::kPageMask); 796 CachePage* cache_page = GetCachePage(i_cache, page); 797 char* cache_valid_byte = cache_page->ValidityByte(offset); 798 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 799 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 800 if (cache_hit) { 801 // Check that the data in memory matches the contents of the I-cache. 802 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr), 803 cache_page->CachedData(offset), 804 Instruction::kInstrSize)); 805 } else { 806 // Cache miss. Load memory into the cache. 807 memcpy(cached_line, line, CachePage::kLineLength); 808 *cache_valid_byte = CachePage::LINE_VALID; 809 } 810} 811 812 813void Simulator::Initialize(Isolate* isolate) { 814 if (isolate->simulator_initialized()) return; 815 isolate->set_simulator_initialized(true); 816 ::v8::internal::ExternalReference::set_redirector(isolate, 817 &RedirectExternalReference); 818} 819 820 821Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { 822 i_cache_ = isolate_->simulator_i_cache(); 823 if (i_cache_ == NULL) { 824 i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch); 825 isolate_->set_simulator_i_cache(i_cache_); 826 } 827 Initialize(isolate); 828 // Set up simulator support first. Some of this information is needed to 829 // setup the architecture state. 830 stack_size_ = FLAG_sim_stack_size * KB; 831 stack_ = reinterpret_cast<char*>(malloc(stack_size_)); 832 pc_modified_ = false; 833 icount_ = 0; 834 break_count_ = 0; 835 break_pc_ = NULL; 836 break_instr_ = 0; 837 838 // Set up architecture state. 839 // All registers are initialized to zero to start with. 840 for (int i = 0; i < kNumSimuRegisters; i++) { 841 registers_[i] = 0; 842 } 843 for (int i = 0; i < kNumFPURegisters; i++) { 844 FPUregisters_[i] = 0; 845 } 846 847 if (kArchVariant == kMips64r6) { 848 FCSR_ = kFCSRNaN2008FlagMask; 849 } else { 850 FCSR_ = 0; 851 } 852 853 // The sp is initialized to point to the bottom (high address) of the 854 // allocated stack area. To be safe in potential stack underflows we leave 855 // some buffer below. 856 registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64; 857 // The ra and pc are initialized to a known bad value that will cause an 858 // access violation if the simulator ever tries to execute it. 859 registers_[pc] = bad_ra; 860 registers_[ra] = bad_ra; 861 862 last_debugger_input_ = NULL; 863} 864 865 866Simulator::~Simulator() { free(stack_); } 867 868 869// When the generated code calls an external reference we need to catch that in 870// the simulator. The external reference will be a function compiled for the 871// host architecture. We need to call that function instead of trying to 872// execute it with the simulator. We do that by redirecting the external 873// reference to a swi (software-interrupt) instruction that is handled by 874// the simulator. We write the original destination of the jump just at a known 875// offset from the swi instruction so the simulator knows what to call. 876class Redirection { 877 public: 878 Redirection(Isolate* isolate, void* external_function, 879 ExternalReference::Type type) 880 : external_function_(external_function), 881 swi_instruction_(rtCallRedirInstr), 882 type_(type), 883 next_(NULL) { 884 next_ = isolate->simulator_redirection(); 885 Simulator::current(isolate)-> 886 FlushICache(isolate->simulator_i_cache(), 887 reinterpret_cast<void*>(&swi_instruction_), 888 Instruction::kInstrSize); 889 isolate->set_simulator_redirection(this); 890 } 891 892 void* address_of_swi_instruction() { 893 return reinterpret_cast<void*>(&swi_instruction_); 894 } 895 896 void* external_function() { return external_function_; } 897 ExternalReference::Type type() { return type_; } 898 899 static Redirection* Get(Isolate* isolate, void* external_function, 900 ExternalReference::Type type) { 901 Redirection* current = isolate->simulator_redirection(); 902 for (; current != NULL; current = current->next_) { 903 if (current->external_function_ == external_function) return current; 904 } 905 return new Redirection(isolate, external_function, type); 906 } 907 908 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 909 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 910 char* addr_of_redirection = 911 addr_of_swi - offsetof(Redirection, swi_instruction_); 912 return reinterpret_cast<Redirection*>(addr_of_redirection); 913 } 914 915 static void* ReverseRedirection(int64_t reg) { 916 Redirection* redirection = FromSwiInstruction( 917 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg))); 918 return redirection->external_function(); 919 } 920 921 static void DeleteChain(Redirection* redirection) { 922 while (redirection != nullptr) { 923 Redirection* next = redirection->next_; 924 delete redirection; 925 redirection = next; 926 } 927 } 928 929 private: 930 void* external_function_; 931 uint32_t swi_instruction_; 932 ExternalReference::Type type_; 933 Redirection* next_; 934}; 935 936 937// static 938void Simulator::TearDown(base::CustomMatcherHashMap* i_cache, 939 Redirection* first) { 940 Redirection::DeleteChain(first); 941 if (i_cache != nullptr) { 942 for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr; 943 entry = i_cache->Next(entry)) { 944 delete static_cast<CachePage*>(entry->value); 945 } 946 delete i_cache; 947 } 948} 949 950 951void* Simulator::RedirectExternalReference(Isolate* isolate, 952 void* external_function, 953 ExternalReference::Type type) { 954 Redirection* redirection = Redirection::Get(isolate, external_function, type); 955 return redirection->address_of_swi_instruction(); 956} 957 958 959// Get the active Simulator for the current thread. 960Simulator* Simulator::current(Isolate* isolate) { 961 v8::internal::Isolate::PerIsolateThreadData* isolate_data = 962 isolate->FindOrAllocatePerThreadDataForThisThread(); 963 DCHECK(isolate_data != NULL); 964 DCHECK(isolate_data != NULL); 965 966 Simulator* sim = isolate_data->simulator(); 967 if (sim == NULL) { 968 // TODO(146): delete the simulator object when a thread/isolate goes away. 969 sim = new Simulator(isolate); 970 isolate_data->set_simulator(sim); 971 } 972 return sim; 973} 974 975 976// Sets the register in the architecture state. It will also deal with updating 977// Simulator internal state for special registers such as PC. 978void Simulator::set_register(int reg, int64_t value) { 979 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 980 if (reg == pc) { 981 pc_modified_ = true; 982 } 983 984 // Zero register always holds 0. 985 registers_[reg] = (reg == 0) ? 0 : value; 986} 987 988 989void Simulator::set_dw_register(int reg, const int* dbl) { 990 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 991 registers_[reg] = dbl[1]; 992 registers_[reg] = registers_[reg] << 32; 993 registers_[reg] += dbl[0]; 994} 995 996 997void Simulator::set_fpu_register(int fpureg, int64_t value) { 998 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 999 FPUregisters_[fpureg] = value; 1000} 1001 1002 1003void Simulator::set_fpu_register_word(int fpureg, int32_t value) { 1004 // Set ONLY lower 32-bits, leaving upper bits untouched. 1005 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1006 int32_t* pword; 1007 if (kArchEndian == kLittle) { 1008 pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]); 1009 } else { 1010 pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]) + 1; 1011 } 1012 *pword = value; 1013} 1014 1015 1016void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) { 1017 // Set ONLY upper 32-bits, leaving lower bits untouched. 1018 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1019 int32_t* phiword; 1020 if (kArchEndian == kLittle) { 1021 phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1; 1022 } else { 1023 phiword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]); 1024 } 1025 *phiword = value; 1026} 1027 1028 1029void Simulator::set_fpu_register_float(int fpureg, float value) { 1030 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1031 *bit_cast<float*>(&FPUregisters_[fpureg]) = value; 1032} 1033 1034 1035void Simulator::set_fpu_register_double(int fpureg, double value) { 1036 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1037 *bit_cast<double*>(&FPUregisters_[fpureg]) = value; 1038} 1039 1040 1041// Get the register from the architecture state. This function does handle 1042// the special case of accessing the PC register. 1043int64_t Simulator::get_register(int reg) const { 1044 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); 1045 if (reg == 0) 1046 return 0; 1047 else 1048 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 1049} 1050 1051 1052double Simulator::get_double_from_register_pair(int reg) { 1053 // TODO(plind): bad ABI stuff, refactor or remove. 1054 DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0)); 1055 1056 double dm_val = 0.0; 1057 // Read the bits from the unsigned integer register_[] array 1058 // into the double precision floating point value and return it. 1059 char buffer[sizeof(registers_[0])]; 1060 memcpy(buffer, ®isters_[reg], sizeof(registers_[0])); 1061 memcpy(&dm_val, buffer, sizeof(registers_[0])); 1062 return(dm_val); 1063} 1064 1065 1066int64_t Simulator::get_fpu_register(int fpureg) const { 1067 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1068 return FPUregisters_[fpureg]; 1069} 1070 1071 1072int32_t Simulator::get_fpu_register_word(int fpureg) const { 1073 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1074 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); 1075} 1076 1077 1078int32_t Simulator::get_fpu_register_signed_word(int fpureg) const { 1079 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1080 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); 1081} 1082 1083 1084int32_t Simulator::get_fpu_register_hi_word(int fpureg) const { 1085 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1086 return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff); 1087} 1088 1089 1090float Simulator::get_fpu_register_float(int fpureg) const { 1091 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1092 return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg])); 1093} 1094 1095 1096double Simulator::get_fpu_register_double(int fpureg) const { 1097 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); 1098 return *bit_cast<double*>(&FPUregisters_[fpureg]); 1099} 1100 1101 1102// Runtime FP routines take up to two double arguments and zero 1103// or one integer arguments. All are constructed here, 1104// from a0-a3 or f12 and f13 (n64), or f14 (O32). 1105void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { 1106 if (!IsMipsSoftFloatABI) { 1107 const int fparg2 = 13; 1108 *x = get_fpu_register_double(12); 1109 *y = get_fpu_register_double(fparg2); 1110 *z = static_cast<int32_t>(get_register(a2)); 1111 } else { 1112 // TODO(plind): bad ABI stuff, refactor or remove. 1113 // We use a char buffer to get around the strict-aliasing rules which 1114 // otherwise allow the compiler to optimize away the copy. 1115 char buffer[sizeof(*x)]; 1116 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); 1117 1118 // Registers a0 and a1 -> x. 1119 reg_buffer[0] = get_register(a0); 1120 reg_buffer[1] = get_register(a1); 1121 memcpy(x, buffer, sizeof(buffer)); 1122 // Registers a2 and a3 -> y. 1123 reg_buffer[0] = get_register(a2); 1124 reg_buffer[1] = get_register(a3); 1125 memcpy(y, buffer, sizeof(buffer)); 1126 // Register 2 -> z. 1127 reg_buffer[0] = get_register(a2); 1128 memcpy(z, buffer, sizeof(*z)); 1129 } 1130} 1131 1132 1133// The return value is either in v0/v1 or f0. 1134void Simulator::SetFpResult(const double& result) { 1135 if (!IsMipsSoftFloatABI) { 1136 set_fpu_register_double(0, result); 1137 } else { 1138 char buffer[2 * sizeof(registers_[0])]; 1139 int64_t* reg_buffer = reinterpret_cast<int64_t*>(buffer); 1140 memcpy(buffer, &result, sizeof(buffer)); 1141 // Copy result to v0 and v1. 1142 set_register(v0, reg_buffer[0]); 1143 set_register(v1, reg_buffer[1]); 1144 } 1145} 1146 1147 1148// Helper functions for setting and testing the FCSR register's bits. 1149void Simulator::set_fcsr_bit(uint32_t cc, bool value) { 1150 if (value) { 1151 FCSR_ |= (1 << cc); 1152 } else { 1153 FCSR_ &= ~(1 << cc); 1154 } 1155} 1156 1157 1158bool Simulator::test_fcsr_bit(uint32_t cc) { 1159 return FCSR_ & (1 << cc); 1160} 1161 1162 1163void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) { 1164 FCSR_ |= mode & kFPURoundingModeMask; 1165} 1166 1167 1168unsigned int Simulator::get_fcsr_rounding_mode() { 1169 return FCSR_ & kFPURoundingModeMask; 1170} 1171 1172 1173// Sets the rounding error codes in FCSR based on the result of the rounding. 1174// Returns true if the operation was invalid. 1175bool Simulator::set_fcsr_round_error(double original, double rounded) { 1176 bool ret = false; 1177 double max_int32 = std::numeric_limits<int32_t>::max(); 1178 double min_int32 = std::numeric_limits<int32_t>::min(); 1179 1180 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1181 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1182 ret = true; 1183 } 1184 1185 if (original != rounded) { 1186 set_fcsr_bit(kFCSRInexactFlagBit, true); 1187 } 1188 1189 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 1190 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1191 ret = true; 1192 } 1193 1194 if (rounded > max_int32 || rounded < min_int32) { 1195 set_fcsr_bit(kFCSROverflowFlagBit, true); 1196 // The reference is not really clear but it seems this is required: 1197 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1198 ret = true; 1199 } 1200 1201 return ret; 1202} 1203 1204 1205// Sets the rounding error codes in FCSR based on the result of the rounding. 1206// Returns true if the operation was invalid. 1207bool Simulator::set_fcsr_round64_error(double original, double rounded) { 1208 bool ret = false; 1209 // The value of INT64_MAX (2^63-1) can't be represented as double exactly, 1210 // loading the most accurate representation into max_int64, which is 2^63. 1211 double max_int64 = std::numeric_limits<int64_t>::max(); 1212 double min_int64 = std::numeric_limits<int64_t>::min(); 1213 1214 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1215 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1216 ret = true; 1217 } 1218 1219 if (original != rounded) { 1220 set_fcsr_bit(kFCSRInexactFlagBit, true); 1221 } 1222 1223 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { 1224 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1225 ret = true; 1226 } 1227 1228 if (rounded >= max_int64 || rounded < min_int64) { 1229 set_fcsr_bit(kFCSROverflowFlagBit, true); 1230 // The reference is not really clear but it seems this is required: 1231 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1232 ret = true; 1233 } 1234 1235 return ret; 1236} 1237 1238 1239// Sets the rounding error codes in FCSR based on the result of the rounding. 1240// Returns true if the operation was invalid. 1241bool Simulator::set_fcsr_round_error(float original, float rounded) { 1242 bool ret = false; 1243 double max_int32 = std::numeric_limits<int32_t>::max(); 1244 double min_int32 = std::numeric_limits<int32_t>::min(); 1245 1246 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1247 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1248 ret = true; 1249 } 1250 1251 if (original != rounded) { 1252 set_fcsr_bit(kFCSRInexactFlagBit, true); 1253 } 1254 1255 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) { 1256 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1257 ret = true; 1258 } 1259 1260 if (rounded > max_int32 || rounded < min_int32) { 1261 set_fcsr_bit(kFCSROverflowFlagBit, true); 1262 // The reference is not really clear but it seems this is required: 1263 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1264 ret = true; 1265 } 1266 1267 return ret; 1268} 1269 1270void Simulator::set_fpu_register_word_invalid_result(float original, 1271 float rounded) { 1272 if (FCSR_ & kFCSRNaN2008FlagMask) { 1273 double max_int32 = std::numeric_limits<int32_t>::max(); 1274 double min_int32 = std::numeric_limits<int32_t>::min(); 1275 if (std::isnan(original)) { 1276 set_fpu_register_word(fd_reg(), 0); 1277 } else if (rounded > max_int32) { 1278 set_fpu_register_word(fd_reg(), kFPUInvalidResult); 1279 } else if (rounded < min_int32) { 1280 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative); 1281 } else { 1282 UNREACHABLE(); 1283 } 1284 } else { 1285 set_fpu_register_word(fd_reg(), kFPUInvalidResult); 1286 } 1287} 1288 1289 1290void Simulator::set_fpu_register_invalid_result(float original, float rounded) { 1291 if (FCSR_ & kFCSRNaN2008FlagMask) { 1292 double max_int32 = std::numeric_limits<int32_t>::max(); 1293 double min_int32 = std::numeric_limits<int32_t>::min(); 1294 if (std::isnan(original)) { 1295 set_fpu_register(fd_reg(), 0); 1296 } else if (rounded > max_int32) { 1297 set_fpu_register(fd_reg(), kFPUInvalidResult); 1298 } else if (rounded < min_int32) { 1299 set_fpu_register(fd_reg(), kFPUInvalidResultNegative); 1300 } else { 1301 UNREACHABLE(); 1302 } 1303 } else { 1304 set_fpu_register(fd_reg(), kFPUInvalidResult); 1305 } 1306} 1307 1308 1309void Simulator::set_fpu_register_invalid_result64(float original, 1310 float rounded) { 1311 if (FCSR_ & kFCSRNaN2008FlagMask) { 1312 // The value of INT64_MAX (2^63-1) can't be represented as double exactly, 1313 // loading the most accurate representation into max_int64, which is 2^63. 1314 double max_int64 = std::numeric_limits<int64_t>::max(); 1315 double min_int64 = std::numeric_limits<int64_t>::min(); 1316 if (std::isnan(original)) { 1317 set_fpu_register(fd_reg(), 0); 1318 } else if (rounded >= max_int64) { 1319 set_fpu_register(fd_reg(), kFPU64InvalidResult); 1320 } else if (rounded < min_int64) { 1321 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative); 1322 } else { 1323 UNREACHABLE(); 1324 } 1325 } else { 1326 set_fpu_register(fd_reg(), kFPU64InvalidResult); 1327 } 1328} 1329 1330 1331void Simulator::set_fpu_register_word_invalid_result(double original, 1332 double rounded) { 1333 if (FCSR_ & kFCSRNaN2008FlagMask) { 1334 double max_int32 = std::numeric_limits<int32_t>::max(); 1335 double min_int32 = std::numeric_limits<int32_t>::min(); 1336 if (std::isnan(original)) { 1337 set_fpu_register_word(fd_reg(), 0); 1338 } else if (rounded > max_int32) { 1339 set_fpu_register_word(fd_reg(), kFPUInvalidResult); 1340 } else if (rounded < min_int32) { 1341 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative); 1342 } else { 1343 UNREACHABLE(); 1344 } 1345 } else { 1346 set_fpu_register_word(fd_reg(), kFPUInvalidResult); 1347 } 1348} 1349 1350 1351void Simulator::set_fpu_register_invalid_result(double original, 1352 double rounded) { 1353 if (FCSR_ & kFCSRNaN2008FlagMask) { 1354 double max_int32 = std::numeric_limits<int32_t>::max(); 1355 double min_int32 = std::numeric_limits<int32_t>::min(); 1356 if (std::isnan(original)) { 1357 set_fpu_register(fd_reg(), 0); 1358 } else if (rounded > max_int32) { 1359 set_fpu_register(fd_reg(), kFPUInvalidResult); 1360 } else if (rounded < min_int32) { 1361 set_fpu_register(fd_reg(), kFPUInvalidResultNegative); 1362 } else { 1363 UNREACHABLE(); 1364 } 1365 } else { 1366 set_fpu_register(fd_reg(), kFPUInvalidResult); 1367 } 1368} 1369 1370 1371void Simulator::set_fpu_register_invalid_result64(double original, 1372 double rounded) { 1373 if (FCSR_ & kFCSRNaN2008FlagMask) { 1374 // The value of INT64_MAX (2^63-1) can't be represented as double exactly, 1375 // loading the most accurate representation into max_int64, which is 2^63. 1376 double max_int64 = std::numeric_limits<int64_t>::max(); 1377 double min_int64 = std::numeric_limits<int64_t>::min(); 1378 if (std::isnan(original)) { 1379 set_fpu_register(fd_reg(), 0); 1380 } else if (rounded >= max_int64) { 1381 set_fpu_register(fd_reg(), kFPU64InvalidResult); 1382 } else if (rounded < min_int64) { 1383 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative); 1384 } else { 1385 UNREACHABLE(); 1386 } 1387 } else { 1388 set_fpu_register(fd_reg(), kFPU64InvalidResult); 1389 } 1390} 1391 1392 1393// Sets the rounding error codes in FCSR based on the result of the rounding. 1394// Returns true if the operation was invalid. 1395bool Simulator::set_fcsr_round64_error(float original, float rounded) { 1396 bool ret = false; 1397 // The value of INT64_MAX (2^63-1) can't be represented as double exactly, 1398 // loading the most accurate representation into max_int64, which is 2^63. 1399 double max_int64 = std::numeric_limits<int64_t>::max(); 1400 double min_int64 = std::numeric_limits<int64_t>::min(); 1401 1402 if (!std::isfinite(original) || !std::isfinite(rounded)) { 1403 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1404 ret = true; 1405 } 1406 1407 if (original != rounded) { 1408 set_fcsr_bit(kFCSRInexactFlagBit, true); 1409 } 1410 1411 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) { 1412 set_fcsr_bit(kFCSRUnderflowFlagBit, true); 1413 ret = true; 1414 } 1415 1416 if (rounded >= max_int64 || rounded < min_int64) { 1417 set_fcsr_bit(kFCSROverflowFlagBit, true); 1418 // The reference is not really clear but it seems this is required: 1419 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); 1420 ret = true; 1421 } 1422 1423 return ret; 1424} 1425 1426 1427// For cvt instructions only 1428void Simulator::round_according_to_fcsr(double toRound, double& rounded, 1429 int32_t& rounded_int, double fs) { 1430 // 0 RN (round to nearest): Round a result to the nearest 1431 // representable value; if the result is exactly halfway between 1432 // two representable values, round to zero. Behave like round_w_d. 1433 1434 // 1 RZ (round toward zero): Round a result to the closest 1435 // representable value whose absolute value is less than or 1436 // equal to the infinitely accurate result. Behave like trunc_w_d. 1437 1438 // 2 RP (round up, or toward +infinity): Round a result to the 1439 // next representable value up. Behave like ceil_w_d. 1440 1441 // 3 RN (round down, or toward −infinity): Round a result to 1442 // the next representable value down. Behave like floor_w_d. 1443 switch (FCSR_ & 3) { 1444 case kRoundToNearest: 1445 rounded = std::floor(fs + 0.5); 1446 rounded_int = static_cast<int32_t>(rounded); 1447 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { 1448 // If the number is halfway between two integers, 1449 // round to the even one. 1450 rounded_int--; 1451 } 1452 break; 1453 case kRoundToZero: 1454 rounded = trunc(fs); 1455 rounded_int = static_cast<int32_t>(rounded); 1456 break; 1457 case kRoundToPlusInf: 1458 rounded = std::ceil(fs); 1459 rounded_int = static_cast<int32_t>(rounded); 1460 break; 1461 case kRoundToMinusInf: 1462 rounded = std::floor(fs); 1463 rounded_int = static_cast<int32_t>(rounded); 1464 break; 1465 } 1466} 1467 1468 1469void Simulator::round64_according_to_fcsr(double toRound, double& rounded, 1470 int64_t& rounded_int, double fs) { 1471 // 0 RN (round to nearest): Round a result to the nearest 1472 // representable value; if the result is exactly halfway between 1473 // two representable values, round to zero. Behave like round_w_d. 1474 1475 // 1 RZ (round toward zero): Round a result to the closest 1476 // representable value whose absolute value is less than or. 1477 // equal to the infinitely accurate result. Behave like trunc_w_d. 1478 1479 // 2 RP (round up, or toward +infinity): Round a result to the 1480 // next representable value up. Behave like ceil_w_d. 1481 1482 // 3 RN (round down, or toward −infinity): Round a result to 1483 // the next representable value down. Behave like floor_w_d. 1484 switch (FCSR_ & 3) { 1485 case kRoundToNearest: 1486 rounded = std::floor(fs + 0.5); 1487 rounded_int = static_cast<int64_t>(rounded); 1488 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { 1489 // If the number is halfway between two integers, 1490 // round to the even one. 1491 rounded_int--; 1492 } 1493 break; 1494 case kRoundToZero: 1495 rounded = trunc(fs); 1496 rounded_int = static_cast<int64_t>(rounded); 1497 break; 1498 case kRoundToPlusInf: 1499 rounded = std::ceil(fs); 1500 rounded_int = static_cast<int64_t>(rounded); 1501 break; 1502 case kRoundToMinusInf: 1503 rounded = std::floor(fs); 1504 rounded_int = static_cast<int64_t>(rounded); 1505 break; 1506 } 1507} 1508 1509 1510// for cvt instructions only 1511void Simulator::round_according_to_fcsr(float toRound, float& rounded, 1512 int32_t& rounded_int, float fs) { 1513 // 0 RN (round to nearest): Round a result to the nearest 1514 // representable value; if the result is exactly halfway between 1515 // two representable values, round to zero. Behave like round_w_d. 1516 1517 // 1 RZ (round toward zero): Round a result to the closest 1518 // representable value whose absolute value is less than or 1519 // equal to the infinitely accurate result. Behave like trunc_w_d. 1520 1521 // 2 RP (round up, or toward +infinity): Round a result to the 1522 // next representable value up. Behave like ceil_w_d. 1523 1524 // 3 RN (round down, or toward −infinity): Round a result to 1525 // the next representable value down. Behave like floor_w_d. 1526 switch (FCSR_ & 3) { 1527 case kRoundToNearest: 1528 rounded = std::floor(fs + 0.5); 1529 rounded_int = static_cast<int32_t>(rounded); 1530 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { 1531 // If the number is halfway between two integers, 1532 // round to the even one. 1533 rounded_int--; 1534 } 1535 break; 1536 case kRoundToZero: 1537 rounded = trunc(fs); 1538 rounded_int = static_cast<int32_t>(rounded); 1539 break; 1540 case kRoundToPlusInf: 1541 rounded = std::ceil(fs); 1542 rounded_int = static_cast<int32_t>(rounded); 1543 break; 1544 case kRoundToMinusInf: 1545 rounded = std::floor(fs); 1546 rounded_int = static_cast<int32_t>(rounded); 1547 break; 1548 } 1549} 1550 1551 1552void Simulator::round64_according_to_fcsr(float toRound, float& rounded, 1553 int64_t& rounded_int, float fs) { 1554 // 0 RN (round to nearest): Round a result to the nearest 1555 // representable value; if the result is exactly halfway between 1556 // two representable values, round to zero. Behave like round_w_d. 1557 1558 // 1 RZ (round toward zero): Round a result to the closest 1559 // representable value whose absolute value is less than or. 1560 // equal to the infinitely accurate result. Behave like trunc_w_d. 1561 1562 // 2 RP (round up, or toward +infinity): Round a result to the 1563 // next representable value up. Behave like ceil_w_d. 1564 1565 // 3 RN (round down, or toward −infinity): Round a result to 1566 // the next representable value down. Behave like floor_w_d. 1567 switch (FCSR_ & 3) { 1568 case kRoundToNearest: 1569 rounded = std::floor(fs + 0.5); 1570 rounded_int = static_cast<int64_t>(rounded); 1571 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { 1572 // If the number is halfway between two integers, 1573 // round to the even one. 1574 rounded_int--; 1575 } 1576 break; 1577 case kRoundToZero: 1578 rounded = trunc(fs); 1579 rounded_int = static_cast<int64_t>(rounded); 1580 break; 1581 case kRoundToPlusInf: 1582 rounded = std::ceil(fs); 1583 rounded_int = static_cast<int64_t>(rounded); 1584 break; 1585 case kRoundToMinusInf: 1586 rounded = std::floor(fs); 1587 rounded_int = static_cast<int64_t>(rounded); 1588 break; 1589 } 1590} 1591 1592 1593// Raw access to the PC register. 1594void Simulator::set_pc(int64_t value) { 1595 pc_modified_ = true; 1596 registers_[pc] = value; 1597} 1598 1599 1600bool Simulator::has_bad_pc() const { 1601 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); 1602} 1603 1604 1605// Raw access to the PC register without the special adjustment when reading. 1606int64_t Simulator::get_pc() const { 1607 return registers_[pc]; 1608} 1609 1610 1611// The MIPS cannot do unaligned reads and writes. On some MIPS platforms an 1612// interrupt is caused. On others it does a funky rotation thing. For now we 1613// simply disallow unaligned reads, but at some point we may want to move to 1614// emulating the rotate behaviour. Note that simulator runs have the runtime 1615// system running directly on the host system and only generated code is 1616// executed in the simulator. Since the host is typically IA32 we will not 1617// get the correct MIPS-like behaviour on unaligned accesses. 1618 1619// TODO(plind): refactor this messy debug code when we do unaligned access. 1620void Simulator::DieOrDebug() { 1621 if (1) { // Flag for this was removed. 1622 MipsDebugger dbg(this); 1623 dbg.Debug(); 1624 } else { 1625 base::OS::Abort(); 1626 } 1627} 1628 1629void Simulator::TraceRegWr(int64_t value, TraceType t) { 1630 if (::v8::internal::FLAG_trace_sim) { 1631 union { 1632 int64_t fmt_int64; 1633 int32_t fmt_int32[2]; 1634 float fmt_float[2]; 1635 double fmt_double; 1636 } v; 1637 v.fmt_int64 = value; 1638 1639 switch (t) { 1640 case WORD: 1641 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") int32:%" PRId32 1642 " uint32:%" PRIu32, 1643 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0]); 1644 break; 1645 case DWORD: 1646 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") int64:%" PRId64 1647 " uint64:%" PRIu64, 1648 value, icount_, value, value); 1649 break; 1650 case FLOAT: 1651 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") flt:%e", 1652 v.fmt_int64, icount_, v.fmt_float[0]); 1653 break; 1654 case DOUBLE: 1655 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") dbl:%e", 1656 v.fmt_int64, icount_, v.fmt_double); 1657 break; 1658 case FLOAT_DOUBLE: 1659 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") flt:%e dbl:%e", 1660 v.fmt_int64, icount_, v.fmt_float[0], v.fmt_double); 1661 break; 1662 case WORD_DWORD: 1663 SNPrintF(trace_buf_, 1664 "%016" PRIx64 " (%" PRId64 ") int32:%" PRId32 1665 " uint32:%" PRIu32 " int64:%" PRId64 " uint64:%" PRIu64, 1666 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0], 1667 v.fmt_int64, v.fmt_int64); 1668 break; 1669 default: 1670 UNREACHABLE(); 1671 } 1672 } 1673} 1674 1675// TODO(plind): consider making icount_ printing a flag option. 1676void Simulator::TraceMemRd(int64_t addr, int64_t value, TraceType t) { 1677 if (::v8::internal::FLAG_trace_sim) { 1678 union { 1679 int64_t fmt_int64; 1680 int32_t fmt_int32[2]; 1681 float fmt_float[2]; 1682 double fmt_double; 1683 } v; 1684 v.fmt_int64 = value; 1685 1686 switch (t) { 1687 case WORD: 1688 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 1689 ") int32:%" PRId32 " uint32:%" PRIu32, 1690 v.fmt_int64, addr, icount_, v.fmt_int32[0], v.fmt_int32[0]); 1691 break; 1692 case DWORD: 1693 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 1694 ") int64:%" PRId64 " uint64:%" PRIu64, 1695 value, addr, icount_, value, value); 1696 break; 1697 case FLOAT: 1698 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 1699 ") flt:%e", 1700 v.fmt_int64, addr, icount_, v.fmt_float[0]); 1701 break; 1702 case DOUBLE: 1703 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 1704 ") dbl:%e", 1705 v.fmt_int64, addr, icount_, v.fmt_double); 1706 break; 1707 case FLOAT_DOUBLE: 1708 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 1709 ") flt:%e dbl:%e", 1710 v.fmt_int64, addr, icount_, v.fmt_float[0], v.fmt_double); 1711 break; 1712 default: 1713 UNREACHABLE(); 1714 } 1715 } 1716} 1717 1718 1719void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) { 1720 if (::v8::internal::FLAG_trace_sim) { 1721 switch (t) { 1722 case BYTE: 1723 SNPrintF(trace_buf_, " %02" PRIx8 " --> [%016" PRIx64 1724 "] (%" PRId64 ")", 1725 static_cast<uint8_t>(value), addr, icount_); 1726 break; 1727 case HALF: 1728 SNPrintF(trace_buf_, " %04" PRIx16 " --> [%016" PRIx64 1729 "] (%" PRId64 ")", 1730 static_cast<uint16_t>(value), addr, icount_); 1731 break; 1732 case WORD: 1733 SNPrintF(trace_buf_, 1734 " %08" PRIx32 " --> [%016" PRIx64 "] (%" PRId64 ")", 1735 static_cast<uint32_t>(value), addr, icount_); 1736 break; 1737 case DWORD: 1738 SNPrintF(trace_buf_, 1739 "%016" PRIx64 " --> [%016" PRIx64 "] (%" PRId64 " )", 1740 value, addr, icount_); 1741 break; 1742 default: 1743 UNREACHABLE(); 1744 } 1745 } 1746} 1747 1748 1749// TODO(plind): sign-extend and zero-extend not implmented properly 1750// on all the ReadXX functions, I don't think re-interpret cast does it. 1751int32_t Simulator::ReadW(int64_t addr, Instruction* instr, TraceType t) { 1752 if (addr >=0 && addr < 0x400) { 1753 // This has to be a NULL-dereference, drop into debugger. 1754 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR 1755 " \n", 1756 addr, reinterpret_cast<intptr_t>(instr)); 1757 DieOrDebug(); 1758 } 1759 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { 1760 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1761 TraceMemRd(addr, static_cast<int64_t>(*ptr), t); 1762 return *ptr; 1763 } 1764 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, 1765 reinterpret_cast<intptr_t>(instr)); 1766 DieOrDebug(); 1767 return 0; 1768} 1769 1770 1771uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) { 1772 if (addr >=0 && addr < 0x400) { 1773 // This has to be a NULL-dereference, drop into debugger. 1774 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR 1775 " \n", 1776 addr, reinterpret_cast<intptr_t>(instr)); 1777 DieOrDebug(); 1778 } 1779 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { 1780 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 1781 TraceMemRd(addr, static_cast<int64_t>(*ptr), WORD); 1782 return *ptr; 1783 } 1784 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, 1785 reinterpret_cast<intptr_t>(instr)); 1786 DieOrDebug(); 1787 return 0; 1788} 1789 1790 1791void Simulator::WriteW(int64_t addr, int32_t value, Instruction* instr) { 1792 if (addr >= 0 && addr < 0x400) { 1793 // This has to be a NULL-dereference, drop into debugger. 1794 PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR 1795 " \n", 1796 addr, reinterpret_cast<intptr_t>(instr)); 1797 DieOrDebug(); 1798 } 1799 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { 1800 TraceMemWr(addr, value, WORD); 1801 int* ptr = reinterpret_cast<int*>(addr); 1802 *ptr = value; 1803 return; 1804 } 1805 PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, 1806 reinterpret_cast<intptr_t>(instr)); 1807 DieOrDebug(); 1808} 1809 1810 1811int64_t Simulator::Read2W(int64_t addr, Instruction* instr) { 1812 if (addr >=0 && addr < 0x400) { 1813 // This has to be a NULL-dereference, drop into debugger. 1814 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR 1815 " \n", 1816 addr, reinterpret_cast<intptr_t>(instr)); 1817 DieOrDebug(); 1818 } 1819 if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) { 1820 int64_t* ptr = reinterpret_cast<int64_t*>(addr); 1821 TraceMemRd(addr, *ptr); 1822 return *ptr; 1823 } 1824 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, 1825 reinterpret_cast<intptr_t>(instr)); 1826 DieOrDebug(); 1827 return 0; 1828} 1829 1830 1831void Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) { 1832 if (addr >= 0 && addr < 0x400) { 1833 // This has to be a NULL-dereference, drop into debugger. 1834 PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR 1835 "\n", 1836 addr, reinterpret_cast<intptr_t>(instr)); 1837 DieOrDebug(); 1838 } 1839 if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) { 1840 TraceMemWr(addr, value, DWORD); 1841 int64_t* ptr = reinterpret_cast<int64_t*>(addr); 1842 *ptr = value; 1843 return; 1844 } 1845 PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, 1846 reinterpret_cast<intptr_t>(instr)); 1847 DieOrDebug(); 1848} 1849 1850 1851double Simulator::ReadD(int64_t addr, Instruction* instr) { 1852 if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) { 1853 double* ptr = reinterpret_cast<double*>(addr); 1854 return *ptr; 1855 } 1856 PrintF("Unaligned (double) read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", 1857 addr, reinterpret_cast<intptr_t>(instr)); 1858 base::OS::Abort(); 1859 return 0; 1860} 1861 1862 1863void Simulator::WriteD(int64_t addr, double value, Instruction* instr) { 1864 if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) { 1865 double* ptr = reinterpret_cast<double*>(addr); 1866 *ptr = value; 1867 return; 1868 } 1869 PrintF("Unaligned (double) write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR 1870 "\n", 1871 addr, reinterpret_cast<intptr_t>(instr)); 1872 DieOrDebug(); 1873} 1874 1875 1876uint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) { 1877 if ((addr & 1) == 0 || kArchVariant == kMips64r6) { 1878 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1879 TraceMemRd(addr, static_cast<int64_t>(*ptr)); 1880 return *ptr; 1881 } 1882 PrintF("Unaligned unsigned halfword read at 0x%08" PRIx64 1883 " , pc=0x%08" V8PRIxPTR "\n", 1884 addr, reinterpret_cast<intptr_t>(instr)); 1885 DieOrDebug(); 1886 return 0; 1887} 1888 1889 1890int16_t Simulator::ReadH(int64_t addr, Instruction* instr) { 1891 if ((addr & 1) == 0 || kArchVariant == kMips64r6) { 1892 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1893 TraceMemRd(addr, static_cast<int64_t>(*ptr)); 1894 return *ptr; 1895 } 1896 PrintF("Unaligned signed halfword read at 0x%08" PRIx64 1897 " , pc=0x%08" V8PRIxPTR "\n", 1898 addr, reinterpret_cast<intptr_t>(instr)); 1899 DieOrDebug(); 1900 return 0; 1901} 1902 1903 1904void Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) { 1905 if ((addr & 1) == 0 || kArchVariant == kMips64r6) { 1906 TraceMemWr(addr, value, HALF); 1907 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1908 *ptr = value; 1909 return; 1910 } 1911 PrintF("Unaligned unsigned halfword write at 0x%08" PRIx64 1912 " , pc=0x%08" V8PRIxPTR "\n", 1913 addr, reinterpret_cast<intptr_t>(instr)); 1914 DieOrDebug(); 1915} 1916 1917 1918void Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) { 1919 if ((addr & 1) == 0 || kArchVariant == kMips64r6) { 1920 TraceMemWr(addr, value, HALF); 1921 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1922 *ptr = value; 1923 return; 1924 } 1925 PrintF("Unaligned halfword write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR 1926 "\n", 1927 addr, reinterpret_cast<intptr_t>(instr)); 1928 DieOrDebug(); 1929} 1930 1931 1932uint32_t Simulator::ReadBU(int64_t addr) { 1933 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1934 TraceMemRd(addr, static_cast<int64_t>(*ptr)); 1935 return *ptr & 0xff; 1936} 1937 1938 1939int32_t Simulator::ReadB(int64_t addr) { 1940 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1941 TraceMemRd(addr, static_cast<int64_t>(*ptr)); 1942 return *ptr; 1943} 1944 1945 1946void Simulator::WriteB(int64_t addr, uint8_t value) { 1947 TraceMemWr(addr, value, BYTE); 1948 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1949 *ptr = value; 1950} 1951 1952 1953void Simulator::WriteB(int64_t addr, int8_t value) { 1954 TraceMemWr(addr, value, BYTE); 1955 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1956 *ptr = value; 1957} 1958 1959 1960// Returns the limit of the stack area to enable checking for stack overflows. 1961uintptr_t Simulator::StackLimit(uintptr_t c_limit) const { 1962 // The simulator uses a separate JS stack. If we have exhausted the C stack, 1963 // we also drop down the JS limit to reflect the exhaustion on the JS stack. 1964 if (GetCurrentStackPosition() < c_limit) { 1965 return reinterpret_cast<uintptr_t>(get_sp()); 1966 } 1967 1968 // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes 1969 // to prevent overrunning the stack when pushing values. 1970 return reinterpret_cast<uintptr_t>(stack_) + 1024; 1971} 1972 1973 1974// Unsupported instructions use Format to print an error and stop execution. 1975void Simulator::Format(Instruction* instr, const char* format) { 1976 PrintF("Simulator found unsupported instruction:\n 0x%08" PRIxPTR " : %s\n", 1977 reinterpret_cast<intptr_t>(instr), format); 1978 UNIMPLEMENTED_MIPS(); 1979} 1980 1981 1982// Calls into the V8 runtime are based on this very simple interface. 1983// Note: To be able to return two values from some calls the code in runtime.cc 1984// uses the ObjectPair which is essentially two 32-bit values stuffed into a 1985// 64-bit value. With the code below we assume that all runtime calls return 1986// 64 bits of result. If they don't, the v1 result register contains a bogus 1987// value, which is fine because it is caller-saved. 1988 1989typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, 1990 int64_t arg1, 1991 int64_t arg2, 1992 int64_t arg3, 1993 int64_t arg4, 1994 int64_t arg5); 1995 1996typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int64_t arg0, int64_t arg1, 1997 int64_t arg2, int64_t arg3, 1998 int64_t arg4); 1999 2000// These prototypes handle the four types of FP calls. 2001typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1); 2002typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); 2003typedef double (*SimulatorRuntimeFPCall)(double darg0); 2004typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0); 2005 2006// This signature supports direct call in to API function native callback 2007// (refer to InvocationCallback in v8.h). 2008typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); 2009typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); 2010 2011// This signature supports direct call to accessor getter callback. 2012typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); 2013typedef void (*SimulatorRuntimeProfilingGetterCall)( 2014 int64_t arg0, int64_t arg1, void* arg2); 2015 2016// Software interrupt instructions are used by the simulator to call into the 2017// C-based V8 runtime. They are also used for debugging with simulator. 2018void Simulator::SoftwareInterrupt() { 2019 // There are several instructions that could get us here, 2020 // the break_ instruction, or several variants of traps. All 2021 // Are "SPECIAL" class opcode, and are distinuished by function. 2022 int32_t func = instr_.FunctionFieldRaw(); 2023 uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1; 2024 // We first check if we met a call_rt_redirected. 2025 if (instr_.InstructionBits() == rtCallRedirInstr) { 2026 Redirection* redirection = Redirection::FromSwiInstruction(instr_.instr()); 2027 int64_t arg0 = get_register(a0); 2028 int64_t arg1 = get_register(a1); 2029 int64_t arg2 = get_register(a2); 2030 int64_t arg3 = get_register(a3); 2031 int64_t arg4, arg5; 2032 2033 arg4 = get_register(a4); // Abi n64 register a4. 2034 arg5 = get_register(a5); // Abi n64 register a5. 2035 2036 bool fp_call = 2037 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 2038 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 2039 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 2040 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 2041 2042 if (!IsMipsSoftFloatABI) { 2043 // With the hard floating point calling convention, double 2044 // arguments are passed in FPU registers. Fetch the arguments 2045 // from there and call the builtin using soft floating point 2046 // convention. 2047 switch (redirection->type()) { 2048 case ExternalReference::BUILTIN_FP_FP_CALL: 2049 case ExternalReference::BUILTIN_COMPARE_CALL: 2050 arg0 = get_fpu_register(f12); 2051 arg1 = get_fpu_register(f13); 2052 arg2 = get_fpu_register(f14); 2053 arg3 = get_fpu_register(f15); 2054 break; 2055 case ExternalReference::BUILTIN_FP_CALL: 2056 arg0 = get_fpu_register(f12); 2057 arg1 = get_fpu_register(f13); 2058 break; 2059 case ExternalReference::BUILTIN_FP_INT_CALL: 2060 arg0 = get_fpu_register(f12); 2061 arg1 = get_fpu_register(f13); 2062 arg2 = get_register(a2); 2063 break; 2064 default: 2065 break; 2066 } 2067 } 2068 2069 // This is dodgy but it works because the C entry stubs are never moved. 2070 // See comment in codegen-arm.cc and bug 1242173. 2071 int64_t saved_ra = get_register(ra); 2072 2073 intptr_t external = 2074 reinterpret_cast<intptr_t>(redirection->external_function()); 2075 2076 // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware 2077 // FPU, or gcc soft-float routines. Hardware FPU is simulated in this 2078 // simulator. Soft-float has additional abstraction of ExternalReference, 2079 // to support serialization. 2080 if (fp_call) { 2081 double dval0, dval1; // one or two double parameters 2082 int32_t ival; // zero or one integer parameters 2083 int64_t iresult = 0; // integer return value 2084 double dresult = 0; // double return value 2085 GetFpArgs(&dval0, &dval1, &ival); 2086 SimulatorRuntimeCall generic_target = 2087 reinterpret_cast<SimulatorRuntimeCall>(external); 2088 if (::v8::internal::FLAG_trace_sim) { 2089 switch (redirection->type()) { 2090 case ExternalReference::BUILTIN_FP_FP_CALL: 2091 case ExternalReference::BUILTIN_COMPARE_CALL: 2092 PrintF("Call to host function at %p with args %f, %f", 2093 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0, 2094 dval1); 2095 break; 2096 case ExternalReference::BUILTIN_FP_CALL: 2097 PrintF("Call to host function at %p with arg %f", 2098 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0); 2099 break; 2100 case ExternalReference::BUILTIN_FP_INT_CALL: 2101 PrintF("Call to host function at %p with args %f, %d", 2102 static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0, 2103 ival); 2104 break; 2105 default: 2106 UNREACHABLE(); 2107 break; 2108 } 2109 } 2110 switch (redirection->type()) { 2111 case ExternalReference::BUILTIN_COMPARE_CALL: { 2112 SimulatorRuntimeCompareCall target = 2113 reinterpret_cast<SimulatorRuntimeCompareCall>(external); 2114 iresult = target(dval0, dval1); 2115 set_register(v0, static_cast<int64_t>(iresult)); 2116 // set_register(v1, static_cast<int64_t>(iresult >> 32)); 2117 break; 2118 } 2119 case ExternalReference::BUILTIN_FP_FP_CALL: { 2120 SimulatorRuntimeFPFPCall target = 2121 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 2122 dresult = target(dval0, dval1); 2123 SetFpResult(dresult); 2124 break; 2125 } 2126 case ExternalReference::BUILTIN_FP_CALL: { 2127 SimulatorRuntimeFPCall target = 2128 reinterpret_cast<SimulatorRuntimeFPCall>(external); 2129 dresult = target(dval0); 2130 SetFpResult(dresult); 2131 break; 2132 } 2133 case ExternalReference::BUILTIN_FP_INT_CALL: { 2134 SimulatorRuntimeFPIntCall target = 2135 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 2136 dresult = target(dval0, ival); 2137 SetFpResult(dresult); 2138 break; 2139 } 2140 default: 2141 UNREACHABLE(); 2142 break; 2143 } 2144 if (::v8::internal::FLAG_trace_sim) { 2145 switch (redirection->type()) { 2146 case ExternalReference::BUILTIN_COMPARE_CALL: 2147 PrintF("Returned %08x\n", static_cast<int32_t>(iresult)); 2148 break; 2149 case ExternalReference::BUILTIN_FP_FP_CALL: 2150 case ExternalReference::BUILTIN_FP_CALL: 2151 case ExternalReference::BUILTIN_FP_INT_CALL: 2152 PrintF("Returned %f\n", dresult); 2153 break; 2154 default: 2155 UNREACHABLE(); 2156 break; 2157 } 2158 } 2159 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 2160 if (::v8::internal::FLAG_trace_sim) { 2161 PrintF("Call to host function at %p args %08" PRIx64 " \n", 2162 reinterpret_cast<void*>(external), arg0); 2163 } 2164 SimulatorRuntimeDirectApiCall target = 2165 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 2166 target(arg0); 2167 } else if ( 2168 redirection->type() == ExternalReference::PROFILING_API_CALL) { 2169 if (::v8::internal::FLAG_trace_sim) { 2170 PrintF("Call to host function at %p args %08" PRIx64 " %08" PRIx64 2171 " \n", 2172 reinterpret_cast<void*>(external), arg0, arg1); 2173 } 2174 SimulatorRuntimeProfilingApiCall target = 2175 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 2176 target(arg0, Redirection::ReverseRedirection(arg1)); 2177 } else if ( 2178 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 2179 if (::v8::internal::FLAG_trace_sim) { 2180 PrintF("Call to host function at %p args %08" PRIx64 " %08" PRIx64 2181 " \n", 2182 reinterpret_cast<void*>(external), arg0, arg1); 2183 } 2184 SimulatorRuntimeDirectGetterCall target = 2185 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 2186 target(arg0, arg1); 2187 } else if ( 2188 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) { 2189 if (::v8::internal::FLAG_trace_sim) { 2190 PrintF("Call to host function at %p args %08" PRIx64 " %08" PRIx64 2191 " %08" PRIx64 " \n", 2192 reinterpret_cast<void*>(external), arg0, arg1, arg2); 2193 } 2194 SimulatorRuntimeProfilingGetterCall target = 2195 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); 2196 target(arg0, arg1, Redirection::ReverseRedirection(arg2)); 2197 } else if (redirection->type() == ExternalReference::BUILTIN_CALL_TRIPLE) { 2198 // builtin call returning ObjectTriple. 2199 SimulatorRuntimeTripleCall target = 2200 reinterpret_cast<SimulatorRuntimeTripleCall>(external); 2201 if (::v8::internal::FLAG_trace_sim) { 2202 PrintF( 2203 "Call to host triple returning runtime function %p " 2204 "args %016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 2205 ", %016" PRIx64 "\n", 2206 static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4, 2207 arg5); 2208 } 2209 // arg0 is a hidden argument pointing to the return location, so don't 2210 // pass it to the target function. 2211 ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5); 2212 if (::v8::internal::FLAG_trace_sim) { 2213 PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x), 2214 static_cast<void*>(result.y), static_cast<void*>(result.z)); 2215 } 2216 // Return is passed back in address pointed to by hidden first argument. 2217 ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0); 2218 *sim_result = result; 2219 set_register(v0, arg0); 2220 } else { 2221 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL || 2222 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR); 2223 SimulatorRuntimeCall target = 2224 reinterpret_cast<SimulatorRuntimeCall>(external); 2225 if (::v8::internal::FLAG_trace_sim) { 2226 PrintF( 2227 "Call to host function at %p " 2228 "args %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64 2229 " , %08" PRIx64 " , %08" PRIx64 " \n", 2230 static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3, 2231 arg4, arg5); 2232 } 2233 // int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); 2234 // set_register(v0, static_cast<int32_t>(result)); 2235 // set_register(v1, static_cast<int32_t>(result >> 32)); 2236 ObjectPair result = target(arg0, arg1, arg2, arg3, arg4, arg5); 2237 set_register(v0, (int64_t)(result.x)); 2238 set_register(v1, (int64_t)(result.y)); 2239 } 2240 if (::v8::internal::FLAG_trace_sim) { 2241 PrintF("Returned %08" PRIx64 " : %08" PRIx64 " \n", get_register(v1), 2242 get_register(v0)); 2243 } 2244 set_register(ra, saved_ra); 2245 set_pc(get_register(ra)); 2246 2247 } else if (func == BREAK && code <= kMaxStopCode) { 2248 if (IsWatchpoint(code)) { 2249 PrintWatchpoint(code); 2250 } else { 2251 IncreaseStopCounter(code); 2252 HandleStop(code, instr_.instr()); 2253 } 2254 } else { 2255 // All remaining break_ codes, and all traps are handled here. 2256 MipsDebugger dbg(this); 2257 dbg.Debug(); 2258 } 2259} 2260 2261 2262// Stop helper functions. 2263bool Simulator::IsWatchpoint(uint64_t code) { 2264 return (code <= kMaxWatchpointCode); 2265} 2266 2267 2268void Simulator::PrintWatchpoint(uint64_t code) { 2269 MipsDebugger dbg(this); 2270 ++break_count_; 2271 PrintF("\n---- break %" PRId64 " marker: %3d (instr count: %8" PRId64 2272 " ) ----------" 2273 "----------------------------------", 2274 code, break_count_, icount_); 2275 dbg.PrintAllRegs(); // Print registers and continue running. 2276} 2277 2278 2279void Simulator::HandleStop(uint64_t code, Instruction* instr) { 2280 // Stop if it is enabled, otherwise go on jumping over the stop 2281 // and the message address. 2282 if (IsEnabledStop(code)) { 2283 MipsDebugger dbg(this); 2284 dbg.Stop(instr); 2285 } else { 2286 set_pc(get_pc() + 2 * Instruction::kInstrSize); 2287 } 2288} 2289 2290 2291bool Simulator::IsStopInstruction(Instruction* instr) { 2292 int32_t func = instr->FunctionFieldRaw(); 2293 uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6)); 2294 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode; 2295} 2296 2297 2298bool Simulator::IsEnabledStop(uint64_t code) { 2299 DCHECK(code <= kMaxStopCode); 2300 DCHECK(code > kMaxWatchpointCode); 2301 return !(watched_stops_[code].count & kStopDisabledBit); 2302} 2303 2304 2305void Simulator::EnableStop(uint64_t code) { 2306 if (!IsEnabledStop(code)) { 2307 watched_stops_[code].count &= ~kStopDisabledBit; 2308 } 2309} 2310 2311 2312void Simulator::DisableStop(uint64_t code) { 2313 if (IsEnabledStop(code)) { 2314 watched_stops_[code].count |= kStopDisabledBit; 2315 } 2316} 2317 2318 2319void Simulator::IncreaseStopCounter(uint64_t code) { 2320 DCHECK(code <= kMaxStopCode); 2321 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) { 2322 PrintF("Stop counter for code %" PRId64 2323 " has overflowed.\n" 2324 "Enabling this code and reseting the counter to 0.\n", 2325 code); 2326 watched_stops_[code].count = 0; 2327 EnableStop(code); 2328 } else { 2329 watched_stops_[code].count++; 2330 } 2331} 2332 2333 2334// Print a stop status. 2335void Simulator::PrintStopInfo(uint64_t code) { 2336 if (code <= kMaxWatchpointCode) { 2337 PrintF("That is a watchpoint, not a stop.\n"); 2338 return; 2339 } else if (code > kMaxStopCode) { 2340 PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1); 2341 return; 2342 } 2343 const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled"; 2344 int32_t count = watched_stops_[code].count & ~kStopDisabledBit; 2345 // Don't print the state of unused breakpoints. 2346 if (count != 0) { 2347 if (watched_stops_[code].desc) { 2348 PrintF("stop %" PRId64 " - 0x%" PRIx64 " : \t%s, \tcounter = %i, \t%s\n", 2349 code, code, state, count, watched_stops_[code].desc); 2350 } else { 2351 PrintF("stop %" PRId64 " - 0x%" PRIx64 " : \t%s, \tcounter = %i\n", code, 2352 code, state, count); 2353 } 2354 } 2355} 2356 2357 2358void Simulator::SignalException(Exception e) { 2359 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", 2360 static_cast<int>(e)); 2361} 2362 2363// Min/Max template functions for Double and Single arguments. 2364 2365template <typename T> 2366static T FPAbs(T a); 2367 2368template <> 2369double FPAbs<double>(double a) { 2370 return fabs(a); 2371} 2372 2373template <> 2374float FPAbs<float>(float a) { 2375 return fabsf(a); 2376} 2377 2378template <typename T> 2379static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind kind, T& result) { 2380 if (std::isnan(a) && std::isnan(b)) { 2381 result = a; 2382 } else if (std::isnan(a)) { 2383 result = b; 2384 } else if (std::isnan(b)) { 2385 result = a; 2386 } else if (b == a) { 2387 // Handle -0.0 == 0.0 case. 2388 // std::signbit() returns int 0 or 1 so substracting MaxMinKind::kMax 2389 // negates the result. 2390 result = std::signbit(b) - static_cast<int>(kind) ? b : a; 2391 } else { 2392 return false; 2393 } 2394 return true; 2395} 2396 2397template <typename T> 2398static T FPUMin(T a, T b) { 2399 T result; 2400 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) { 2401 return result; 2402 } else { 2403 return b < a ? b : a; 2404 } 2405} 2406 2407template <typename T> 2408static T FPUMax(T a, T b) { 2409 T result; 2410 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, result)) { 2411 return result; 2412 } else { 2413 return b > a ? b : a; 2414 } 2415} 2416 2417template <typename T> 2418static T FPUMinA(T a, T b) { 2419 T result; 2420 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) { 2421 if (FPAbs(a) < FPAbs(b)) { 2422 result = a; 2423 } else if (FPAbs(b) < FPAbs(a)) { 2424 result = b; 2425 } else { 2426 result = a < b ? a : b; 2427 } 2428 } 2429 return result; 2430} 2431 2432template <typename T> 2433static T FPUMaxA(T a, T b) { 2434 T result; 2435 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) { 2436 if (FPAbs(a) > FPAbs(b)) { 2437 result = a; 2438 } else if (FPAbs(b) > FPAbs(a)) { 2439 result = b; 2440 } else { 2441 result = a > b ? a : b; 2442 } 2443 } 2444 return result; 2445} 2446 2447enum class KeepSign : bool { no = false, yes }; 2448 2449template <typename T, typename std::enable_if<std::is_floating_point<T>::value, 2450 int>::type = 0> 2451T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) { 2452 DCHECK(std::isnan(arg)); 2453 T qNaN = std::numeric_limits<T>::quiet_NaN(); 2454 if (keepSign == KeepSign::yes) { 2455 return std::copysign(qNaN, result); 2456 } 2457 return qNaN; 2458} 2459 2460template <typename T> 2461T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) { 2462 if (std::isnan(first)) { 2463 return FPUCanonalizeNaNArg(result, first, keepSign); 2464 } 2465 return result; 2466} 2467 2468template <typename T, typename... Args> 2469T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) { 2470 if (std::isnan(first)) { 2471 return FPUCanonalizeNaNArg(result, first, keepSign); 2472 } 2473 return FPUCanonalizeNaNArgs(result, keepSign, args...); 2474} 2475 2476template <typename Func, typename T, typename... Args> 2477T FPUCanonalizeOperation(Func f, T first, Args... args) { 2478 return FPUCanonalizeOperation(f, KeepSign::no, first, args...); 2479} 2480 2481template <typename Func, typename T, typename... Args> 2482T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) { 2483 T result = f(first, args...); 2484 if (std::isnan(result)) { 2485 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...); 2486 } 2487 return result; 2488} 2489 2490// Handle execution based on instruction types. 2491 2492void Simulator::DecodeTypeRegisterSRsType() { 2493 float fs, ft, fd; 2494 fs = get_fpu_register_float(fs_reg()); 2495 ft = get_fpu_register_float(ft_reg()); 2496 fd = get_fpu_register_float(fd_reg()); 2497 int32_t ft_int = bit_cast<int32_t>(ft); 2498 int32_t fd_int = bit_cast<int32_t>(fd); 2499 uint32_t cc, fcsr_cc; 2500 cc = instr_.FCccValue(); 2501 fcsr_cc = get_fcsr_condition_bit(cc); 2502 switch (instr_.FunctionFieldRaw()) { 2503 case RINT: { 2504 DCHECK(kArchVariant == kMips64r6); 2505 float result, temp_result; 2506 double temp; 2507 float upper = std::ceil(fs); 2508 float lower = std::floor(fs); 2509 switch (get_fcsr_rounding_mode()) { 2510 case kRoundToNearest: 2511 if (upper - fs < fs - lower) { 2512 result = upper; 2513 } else if (upper - fs > fs - lower) { 2514 result = lower; 2515 } else { 2516 temp_result = upper / 2; 2517 float reminder = modf(temp_result, &temp); 2518 if (reminder == 0) { 2519 result = upper; 2520 } else { 2521 result = lower; 2522 } 2523 } 2524 break; 2525 case kRoundToZero: 2526 result = (fs > 0 ? lower : upper); 2527 break; 2528 case kRoundToPlusInf: 2529 result = upper; 2530 break; 2531 case kRoundToMinusInf: 2532 result = lower; 2533 break; 2534 } 2535 SetFPUFloatResult(fd_reg(), result); 2536 if (result != fs) { 2537 set_fcsr_bit(kFCSRInexactFlagBit, true); 2538 } 2539 break; 2540 } 2541 case ADD_S: 2542 SetFPUFloatResult( 2543 fd_reg(), 2544 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, 2545 fs, ft)); 2546 break; 2547 case SUB_S: 2548 SetFPUFloatResult( 2549 fd_reg(), 2550 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, 2551 fs, ft)); 2552 break; 2553 case MADDF_S: 2554 DCHECK(kArchVariant == kMips64r6); 2555 SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd)); 2556 break; 2557 case MSUBF_S: 2558 DCHECK(kArchVariant == kMips64r6); 2559 SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd)); 2560 break; 2561 case MUL_S: 2562 SetFPUFloatResult( 2563 fd_reg(), 2564 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, 2565 fs, ft)); 2566 break; 2567 case DIV_S: 2568 SetFPUFloatResult( 2569 fd_reg(), 2570 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, 2571 fs, ft)); 2572 break; 2573 case ABS_S: 2574 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( 2575 [](float fs) { return FPAbs(fs); }, fs)); 2576 break; 2577 case MOV_S: 2578 SetFPUFloatResult(fd_reg(), fs); 2579 break; 2580 case NEG_S: 2581 SetFPUFloatResult(fd_reg(), 2582 FPUCanonalizeOperation([](float src) { return -src; }, 2583 KeepSign::yes, fs)); 2584 break; 2585 case SQRT_S: 2586 SetFPUFloatResult( 2587 fd_reg(), 2588 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); 2589 break; 2590 case RSQRT_S: 2591 SetFPUFloatResult( 2592 fd_reg(), FPUCanonalizeOperation( 2593 [](float src) { return 1.0 / std::sqrt(src); }, fs)); 2594 break; 2595 case RECIP_S: 2596 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( 2597 [](float src) { return 1.0 / src; }, fs)); 2598 break; 2599 case C_F_D: 2600 set_fcsr_bit(fcsr_cc, false); 2601 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2602 break; 2603 case C_UN_D: 2604 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 2605 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2606 break; 2607 case C_EQ_D: 2608 set_fcsr_bit(fcsr_cc, (fs == ft)); 2609 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2610 break; 2611 case C_UEQ_D: 2612 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 2613 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2614 break; 2615 case C_OLT_D: 2616 set_fcsr_bit(fcsr_cc, (fs < ft)); 2617 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2618 break; 2619 case C_ULT_D: 2620 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 2621 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2622 break; 2623 case C_OLE_D: 2624 set_fcsr_bit(fcsr_cc, (fs <= ft)); 2625 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2626 break; 2627 case C_ULE_D: 2628 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 2629 TraceRegWr(test_fcsr_bit(fcsr_cc)); 2630 break; 2631 case CVT_D_S: 2632 SetFPUDoubleResult(fd_reg(), static_cast<double>(fs)); 2633 break; 2634 case CLASS_S: { // Mips64r6 instruction 2635 // Convert float input to uint32_t for easier bit manipulation 2636 uint32_t classed = bit_cast<uint32_t>(fs); 2637 2638 // Extracting sign, exponent and mantissa from the input float 2639 uint32_t sign = (classed >> 31) & 1; 2640 uint32_t exponent = (classed >> 23) & 0x000000ff; 2641 uint32_t mantissa = classed & 0x007fffff; 2642 uint32_t result; 2643 float fResult; 2644 2645 // Setting flags if input float is negative infinity, 2646 // positive infinity, negative zero or positive zero 2647 bool negInf = (classed == 0xFF800000); 2648 bool posInf = (classed == 0x7F800000); 2649 bool negZero = (classed == 0x80000000); 2650 bool posZero = (classed == 0x00000000); 2651 2652 bool signalingNan; 2653 bool quietNan; 2654 bool negSubnorm; 2655 bool posSubnorm; 2656 bool negNorm; 2657 bool posNorm; 2658 2659 // Setting flags if float is NaN 2660 signalingNan = false; 2661 quietNan = false; 2662 if (!negInf && !posInf && (exponent == 0xff)) { 2663 quietNan = ((mantissa & 0x00200000) == 0) && 2664 ((mantissa & (0x00200000 - 1)) == 0); 2665 signalingNan = !quietNan; 2666 } 2667 2668 // Setting flags if float is subnormal number 2669 posSubnorm = false; 2670 negSubnorm = false; 2671 if ((exponent == 0) && (mantissa != 0)) { 2672 DCHECK(sign == 0 || sign == 1); 2673 posSubnorm = (sign == 0); 2674 negSubnorm = (sign == 1); 2675 } 2676 2677 // Setting flags if float is normal number 2678 posNorm = false; 2679 negNorm = false; 2680 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan && 2681 !quietNan && !negZero && !posZero) { 2682 DCHECK(sign == 0 || sign == 1); 2683 posNorm = (sign == 0); 2684 negNorm = (sign == 1); 2685 } 2686 2687 // Calculating result according to description of CLASS.S instruction 2688 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | 2689 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | 2690 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; 2691 2692 DCHECK(result != 0); 2693 2694 fResult = bit_cast<float>(result); 2695 SetFPUFloatResult(fd_reg(), fResult); 2696 break; 2697 } 2698 case CVT_L_S: { 2699 float rounded; 2700 int64_t result; 2701 round64_according_to_fcsr(fs, rounded, result, fs); 2702 SetFPUResult(fd_reg(), result); 2703 if (set_fcsr_round64_error(fs, rounded)) { 2704 set_fpu_register_invalid_result64(fs, rounded); 2705 } 2706 break; 2707 } 2708 case CVT_W_S: { 2709 float rounded; 2710 int32_t result; 2711 round_according_to_fcsr(fs, rounded, result, fs); 2712 SetFPUWordResult(fd_reg(), result); 2713 if (set_fcsr_round_error(fs, rounded)) { 2714 set_fpu_register_word_invalid_result(fs, rounded); 2715 } 2716 break; 2717 } 2718 case TRUNC_W_S: { // Truncate single to word (round towards 0). 2719 float rounded = trunc(fs); 2720 int32_t result = static_cast<int32_t>(rounded); 2721 SetFPUWordResult(fd_reg(), result); 2722 if (set_fcsr_round_error(fs, rounded)) { 2723 set_fpu_register_word_invalid_result(fs, rounded); 2724 } 2725 } break; 2726 case TRUNC_L_S: { // Mips64r2 instruction. 2727 float rounded = trunc(fs); 2728 int64_t result = static_cast<int64_t>(rounded); 2729 SetFPUResult(fd_reg(), result); 2730 if (set_fcsr_round64_error(fs, rounded)) { 2731 set_fpu_register_invalid_result64(fs, rounded); 2732 } 2733 break; 2734 } 2735 case ROUND_W_S: { 2736 float rounded = std::floor(fs + 0.5); 2737 int32_t result = static_cast<int32_t>(rounded); 2738 if ((result & 1) != 0 && result - fs == 0.5) { 2739 // If the number is halfway between two integers, 2740 // round to the even one. 2741 result--; 2742 } 2743 SetFPUWordResult(fd_reg(), result); 2744 if (set_fcsr_round_error(fs, rounded)) { 2745 set_fpu_register_word_invalid_result(fs, rounded); 2746 } 2747 break; 2748 } 2749 case ROUND_L_S: { // Mips64r2 instruction. 2750 float rounded = std::floor(fs + 0.5); 2751 int64_t result = static_cast<int64_t>(rounded); 2752 if ((result & 1) != 0 && result - fs == 0.5) { 2753 // If the number is halfway between two integers, 2754 // round to the even one. 2755 result--; 2756 } 2757 int64_t i64 = static_cast<int64_t>(result); 2758 SetFPUResult(fd_reg(), i64); 2759 if (set_fcsr_round64_error(fs, rounded)) { 2760 set_fpu_register_invalid_result64(fs, rounded); 2761 } 2762 break; 2763 } 2764 case FLOOR_L_S: { // Mips64r2 instruction. 2765 float rounded = floor(fs); 2766 int64_t result = static_cast<int64_t>(rounded); 2767 SetFPUResult(fd_reg(), result); 2768 if (set_fcsr_round64_error(fs, rounded)) { 2769 set_fpu_register_invalid_result64(fs, rounded); 2770 } 2771 break; 2772 } 2773 case FLOOR_W_S: // Round double to word towards negative infinity. 2774 { 2775 float rounded = std::floor(fs); 2776 int32_t result = static_cast<int32_t>(rounded); 2777 SetFPUWordResult(fd_reg(), result); 2778 if (set_fcsr_round_error(fs, rounded)) { 2779 set_fpu_register_word_invalid_result(fs, rounded); 2780 } 2781 } break; 2782 case CEIL_W_S: // Round double to word towards positive infinity. 2783 { 2784 float rounded = std::ceil(fs); 2785 int32_t result = static_cast<int32_t>(rounded); 2786 SetFPUWordResult(fd_reg(), result); 2787 if (set_fcsr_round_error(fs, rounded)) { 2788 set_fpu_register_invalid_result(fs, rounded); 2789 } 2790 } break; 2791 case CEIL_L_S: { // Mips64r2 instruction. 2792 float rounded = ceil(fs); 2793 int64_t result = static_cast<int64_t>(rounded); 2794 SetFPUResult(fd_reg(), result); 2795 if (set_fcsr_round64_error(fs, rounded)) { 2796 set_fpu_register_invalid_result64(fs, rounded); 2797 } 2798 break; 2799 } 2800 case MINA: 2801 DCHECK(kArchVariant == kMips64r6); 2802 SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs)); 2803 break; 2804 case MAXA: 2805 DCHECK(kArchVariant == kMips64r6); 2806 SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs)); 2807 break; 2808 case MIN: 2809 DCHECK(kArchVariant == kMips64r6); 2810 SetFPUFloatResult(fd_reg(), FPUMin(ft, fs)); 2811 break; 2812 case MAX: 2813 DCHECK(kArchVariant == kMips64r6); 2814 SetFPUFloatResult(fd_reg(), FPUMax(ft, fs)); 2815 break; 2816 case SEL: 2817 DCHECK(kArchVariant == kMips64r6); 2818 SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); 2819 break; 2820 case SELEQZ_C: 2821 DCHECK(kArchVariant == kMips64r6); 2822 SetFPUFloatResult( 2823 fd_reg(), 2824 (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0); 2825 break; 2826 case SELNEZ_C: 2827 DCHECK(kArchVariant == kMips64r6); 2828 SetFPUFloatResult( 2829 fd_reg(), 2830 (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0); 2831 break; 2832 case MOVZ_C: { 2833 DCHECK(kArchVariant == kMips64r2); 2834 if (rt() == 0) { 2835 SetFPUFloatResult(fd_reg(), fs); 2836 } 2837 break; 2838 } 2839 case MOVN_C: { 2840 DCHECK(kArchVariant == kMips64r2); 2841 if (rt() != 0) { 2842 SetFPUFloatResult(fd_reg(), fs); 2843 } 2844 break; 2845 } 2846 case MOVF: { 2847 // Same function field for MOVT.D and MOVF.D 2848 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; 2849 ft_cc = get_fcsr_condition_bit(ft_cc); 2850 2851 if (instr_.Bit(16)) { // Read Tf bit. 2852 // MOVT.D 2853 if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); 2854 } else { 2855 // MOVF.D 2856 if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); 2857 } 2858 break; 2859 } 2860 default: 2861 // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S 2862 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. 2863 UNREACHABLE(); 2864 } 2865} 2866 2867 2868void Simulator::DecodeTypeRegisterDRsType() { 2869 double ft, fs, fd; 2870 uint32_t cc, fcsr_cc; 2871 fs = get_fpu_register_double(fs_reg()); 2872 ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg()) 2873 : 0.0; 2874 fd = get_fpu_register_double(fd_reg()); 2875 cc = instr_.FCccValue(); 2876 fcsr_cc = get_fcsr_condition_bit(cc); 2877 int64_t ft_int = bit_cast<int64_t>(ft); 2878 int64_t fd_int = bit_cast<int64_t>(fd); 2879 switch (instr_.FunctionFieldRaw()) { 2880 case RINT: { 2881 DCHECK(kArchVariant == kMips64r6); 2882 double result, temp, temp_result; 2883 double upper = std::ceil(fs); 2884 double lower = std::floor(fs); 2885 switch (get_fcsr_rounding_mode()) { 2886 case kRoundToNearest: 2887 if (upper - fs < fs - lower) { 2888 result = upper; 2889 } else if (upper - fs > fs - lower) { 2890 result = lower; 2891 } else { 2892 temp_result = upper / 2; 2893 double reminder = modf(temp_result, &temp); 2894 if (reminder == 0) { 2895 result = upper; 2896 } else { 2897 result = lower; 2898 } 2899 } 2900 break; 2901 case kRoundToZero: 2902 result = (fs > 0 ? lower : upper); 2903 break; 2904 case kRoundToPlusInf: 2905 result = upper; 2906 break; 2907 case kRoundToMinusInf: 2908 result = lower; 2909 break; 2910 } 2911 SetFPUDoubleResult(fd_reg(), result); 2912 if (result != fs) { 2913 set_fcsr_bit(kFCSRInexactFlagBit, true); 2914 } 2915 break; 2916 } 2917 case SEL: 2918 DCHECK(kArchVariant == kMips64r6); 2919 SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); 2920 break; 2921 case SELEQZ_C: 2922 DCHECK(kArchVariant == kMips64r6); 2923 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); 2924 break; 2925 case SELNEZ_C: 2926 DCHECK(kArchVariant == kMips64r6); 2927 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); 2928 break; 2929 case MOVZ_C: { 2930 DCHECK(kArchVariant == kMips64r2); 2931 if (rt() == 0) { 2932 SetFPUDoubleResult(fd_reg(), fs); 2933 } 2934 break; 2935 } 2936 case MOVN_C: { 2937 DCHECK(kArchVariant == kMips64r2); 2938 if (rt() != 0) { 2939 SetFPUDoubleResult(fd_reg(), fs); 2940 } 2941 break; 2942 } 2943 case MOVF: { 2944 // Same function field for MOVT.D and MOVF.D 2945 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; 2946 ft_cc = get_fcsr_condition_bit(ft_cc); 2947 if (instr_.Bit(16)) { // Read Tf bit. 2948 // MOVT.D 2949 if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); 2950 } else { 2951 // MOVF.D 2952 if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); 2953 } 2954 break; 2955 } 2956 case MINA: 2957 DCHECK(kArchVariant == kMips64r6); 2958 SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs)); 2959 break; 2960 case MAXA: 2961 DCHECK(kArchVariant == kMips64r6); 2962 SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs)); 2963 break; 2964 case MIN: 2965 DCHECK(kArchVariant == kMips64r6); 2966 SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs)); 2967 break; 2968 case MAX: 2969 DCHECK(kArchVariant == kMips64r6); 2970 SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs)); 2971 break; 2972 case ADD_D: 2973 SetFPUDoubleResult( 2974 fd_reg(), 2975 FPUCanonalizeOperation( 2976 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); 2977 break; 2978 case SUB_D: 2979 SetFPUDoubleResult( 2980 fd_reg(), 2981 FPUCanonalizeOperation( 2982 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); 2983 break; 2984 case MADDF_D: 2985 DCHECK(kArchVariant == kMips64r6); 2986 SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd)); 2987 break; 2988 case MSUBF_D: 2989 DCHECK(kArchVariant == kMips64r6); 2990 SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd)); 2991 break; 2992 case MUL_D: 2993 SetFPUDoubleResult( 2994 fd_reg(), 2995 FPUCanonalizeOperation( 2996 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); 2997 break; 2998 case DIV_D: 2999 SetFPUDoubleResult( 3000 fd_reg(), 3001 FPUCanonalizeOperation( 3002 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); 3003 break; 3004 case ABS_D: 3005 SetFPUDoubleResult( 3006 fd_reg(), 3007 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); 3008 break; 3009 case MOV_D: 3010 SetFPUDoubleResult(fd_reg(), fs); 3011 break; 3012 case NEG_D: 3013 SetFPUDoubleResult(fd_reg(), 3014 FPUCanonalizeOperation([](double src) { return -src; }, 3015 KeepSign::yes, fs)); 3016 break; 3017 case SQRT_D: 3018 SetFPUDoubleResult( 3019 fd_reg(), 3020 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); 3021 break; 3022 case RSQRT_D: 3023 SetFPUDoubleResult( 3024 fd_reg(), FPUCanonalizeOperation( 3025 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); 3026 break; 3027 case RECIP_D: 3028 SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation( 3029 [](double fs) { return 1.0 / fs; }, fs)); 3030 break; 3031 case C_UN_D: 3032 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); 3033 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3034 break; 3035 case C_EQ_D: 3036 set_fcsr_bit(fcsr_cc, (fs == ft)); 3037 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3038 break; 3039 case C_UEQ_D: 3040 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); 3041 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3042 break; 3043 case C_OLT_D: 3044 set_fcsr_bit(fcsr_cc, (fs < ft)); 3045 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3046 break; 3047 case C_ULT_D: 3048 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); 3049 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3050 break; 3051 case C_OLE_D: 3052 set_fcsr_bit(fcsr_cc, (fs <= ft)); 3053 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3054 break; 3055 case C_ULE_D: 3056 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); 3057 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3058 break; 3059 case CVT_W_D: { // Convert double to word. 3060 double rounded; 3061 int32_t result; 3062 round_according_to_fcsr(fs, rounded, result, fs); 3063 SetFPUWordResult(fd_reg(), result); 3064 if (set_fcsr_round_error(fs, rounded)) { 3065 set_fpu_register_word_invalid_result(fs, rounded); 3066 } 3067 break; 3068 } 3069 case ROUND_W_D: // Round double to word (round half to even). 3070 { 3071 double rounded = std::floor(fs + 0.5); 3072 int32_t result = static_cast<int32_t>(rounded); 3073 if ((result & 1) != 0 && result - fs == 0.5) { 3074 // If the number is halfway between two integers, 3075 // round to the even one. 3076 result--; 3077 } 3078 SetFPUWordResult(fd_reg(), result); 3079 if (set_fcsr_round_error(fs, rounded)) { 3080 set_fpu_register_invalid_result(fs, rounded); 3081 } 3082 } break; 3083 case TRUNC_W_D: // Truncate double to word (round towards 0). 3084 { 3085 double rounded = trunc(fs); 3086 int32_t result = static_cast<int32_t>(rounded); 3087 SetFPUWordResult(fd_reg(), result); 3088 if (set_fcsr_round_error(fs, rounded)) { 3089 set_fpu_register_invalid_result(fs, rounded); 3090 } 3091 } break; 3092 case FLOOR_W_D: // Round double to word towards negative infinity. 3093 { 3094 double rounded = std::floor(fs); 3095 int32_t result = static_cast<int32_t>(rounded); 3096 SetFPUWordResult(fd_reg(), result); 3097 if (set_fcsr_round_error(fs, rounded)) { 3098 set_fpu_register_invalid_result(fs, rounded); 3099 } 3100 } break; 3101 case CEIL_W_D: // Round double to word towards positive infinity. 3102 { 3103 double rounded = std::ceil(fs); 3104 int32_t result = static_cast<int32_t>(rounded); 3105 SetFPUWordResult2(fd_reg(), result); 3106 if (set_fcsr_round_error(fs, rounded)) { 3107 set_fpu_register_invalid_result(fs, rounded); 3108 } 3109 } break; 3110 case CVT_S_D: // Convert double to float (single). 3111 SetFPUFloatResult(fd_reg(), static_cast<float>(fs)); 3112 break; 3113 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. 3114 double rounded; 3115 int64_t result; 3116 round64_according_to_fcsr(fs, rounded, result, fs); 3117 SetFPUResult(fd_reg(), result); 3118 if (set_fcsr_round64_error(fs, rounded)) { 3119 set_fpu_register_invalid_result64(fs, rounded); 3120 } 3121 break; 3122 } 3123 case ROUND_L_D: { // Mips64r2 instruction. 3124 double rounded = std::floor(fs + 0.5); 3125 int64_t result = static_cast<int64_t>(rounded); 3126 if ((result & 1) != 0 && result - fs == 0.5) { 3127 // If the number is halfway between two integers, 3128 // round to the even one. 3129 result--; 3130 } 3131 int64_t i64 = static_cast<int64_t>(result); 3132 SetFPUResult(fd_reg(), i64); 3133 if (set_fcsr_round64_error(fs, rounded)) { 3134 set_fpu_register_invalid_result64(fs, rounded); 3135 } 3136 break; 3137 } 3138 case TRUNC_L_D: { // Mips64r2 instruction. 3139 double rounded = trunc(fs); 3140 int64_t result = static_cast<int64_t>(rounded); 3141 SetFPUResult(fd_reg(), result); 3142 if (set_fcsr_round64_error(fs, rounded)) { 3143 set_fpu_register_invalid_result64(fs, rounded); 3144 } 3145 break; 3146 } 3147 case FLOOR_L_D: { // Mips64r2 instruction. 3148 double rounded = floor(fs); 3149 int64_t result = static_cast<int64_t>(rounded); 3150 SetFPUResult(fd_reg(), result); 3151 if (set_fcsr_round64_error(fs, rounded)) { 3152 set_fpu_register_invalid_result64(fs, rounded); 3153 } 3154 break; 3155 } 3156 case CEIL_L_D: { // Mips64r2 instruction. 3157 double rounded = ceil(fs); 3158 int64_t result = static_cast<int64_t>(rounded); 3159 SetFPUResult(fd_reg(), result); 3160 if (set_fcsr_round64_error(fs, rounded)) { 3161 set_fpu_register_invalid_result64(fs, rounded); 3162 } 3163 break; 3164 } 3165 case CLASS_D: { // Mips64r6 instruction 3166 // Convert double input to uint64_t for easier bit manipulation 3167 uint64_t classed = bit_cast<uint64_t>(fs); 3168 3169 // Extracting sign, exponent and mantissa from the input double 3170 uint32_t sign = (classed >> 63) & 1; 3171 uint32_t exponent = (classed >> 52) & 0x00000000000007ff; 3172 uint64_t mantissa = classed & 0x000fffffffffffff; 3173 uint64_t result; 3174 double dResult; 3175 3176 // Setting flags if input double is negative infinity, 3177 // positive infinity, negative zero or positive zero 3178 bool negInf = (classed == 0xFFF0000000000000); 3179 bool posInf = (classed == 0x7FF0000000000000); 3180 bool negZero = (classed == 0x8000000000000000); 3181 bool posZero = (classed == 0x0000000000000000); 3182 3183 bool signalingNan; 3184 bool quietNan; 3185 bool negSubnorm; 3186 bool posSubnorm; 3187 bool negNorm; 3188 bool posNorm; 3189 3190 // Setting flags if double is NaN 3191 signalingNan = false; 3192 quietNan = false; 3193 if (!negInf && !posInf && exponent == 0x7ff) { 3194 quietNan = ((mantissa & 0x0008000000000000) != 0) && 3195 ((mantissa & (0x0008000000000000 - 1)) == 0); 3196 signalingNan = !quietNan; 3197 } 3198 3199 // Setting flags if double is subnormal number 3200 posSubnorm = false; 3201 negSubnorm = false; 3202 if ((exponent == 0) && (mantissa != 0)) { 3203 DCHECK(sign == 0 || sign == 1); 3204 posSubnorm = (sign == 0); 3205 negSubnorm = (sign == 1); 3206 } 3207 3208 // Setting flags if double is normal number 3209 posNorm = false; 3210 negNorm = false; 3211 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan && 3212 !quietNan && !negZero && !posZero) { 3213 DCHECK(sign == 0 || sign == 1); 3214 posNorm = (sign == 0); 3215 negNorm = (sign == 1); 3216 } 3217 3218 // Calculating result according to description of CLASS.D instruction 3219 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | 3220 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | 3221 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; 3222 3223 DCHECK(result != 0); 3224 3225 dResult = bit_cast<double>(result); 3226 SetFPUDoubleResult(fd_reg(), dResult); 3227 break; 3228 } 3229 case C_F_D: { 3230 set_fcsr_bit(fcsr_cc, false); 3231 TraceRegWr(test_fcsr_bit(fcsr_cc)); 3232 break; 3233 } 3234 default: 3235 UNREACHABLE(); 3236 } 3237} 3238 3239 3240void Simulator::DecodeTypeRegisterWRsType() { 3241 float fs = get_fpu_register_float(fs_reg()); 3242 float ft = get_fpu_register_float(ft_reg()); 3243 int64_t alu_out = 0x12345678; 3244 switch (instr_.FunctionFieldRaw()) { 3245 case CVT_S_W: // Convert word to float (single). 3246 alu_out = get_fpu_register_signed_word(fs_reg()); 3247 SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out)); 3248 break; 3249 case CVT_D_W: // Convert word to double. 3250 alu_out = get_fpu_register_signed_word(fs_reg()); 3251 SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out)); 3252 break; 3253 case CMP_AF: 3254 SetFPUWordResult2(fd_reg(), 0); 3255 break; 3256 case CMP_UN: 3257 if (std::isnan(fs) || std::isnan(ft)) { 3258 SetFPUWordResult2(fd_reg(), -1); 3259 } else { 3260 SetFPUWordResult2(fd_reg(), 0); 3261 } 3262 break; 3263 case CMP_EQ: 3264 if (fs == ft) { 3265 SetFPUWordResult2(fd_reg(), -1); 3266 } else { 3267 SetFPUWordResult2(fd_reg(), 0); 3268 } 3269 break; 3270 case CMP_UEQ: 3271 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 3272 SetFPUWordResult2(fd_reg(), -1); 3273 } else { 3274 SetFPUWordResult2(fd_reg(), 0); 3275 } 3276 break; 3277 case CMP_LT: 3278 if (fs < ft) { 3279 SetFPUWordResult2(fd_reg(), -1); 3280 } else { 3281 SetFPUWordResult2(fd_reg(), 0); 3282 } 3283 break; 3284 case CMP_ULT: 3285 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 3286 SetFPUWordResult2(fd_reg(), -1); 3287 } else { 3288 SetFPUWordResult2(fd_reg(), 0); 3289 } 3290 break; 3291 case CMP_LE: 3292 if (fs <= ft) { 3293 SetFPUWordResult2(fd_reg(), -1); 3294 } else { 3295 SetFPUWordResult2(fd_reg(), 0); 3296 } 3297 break; 3298 case CMP_ULE: 3299 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 3300 SetFPUWordResult2(fd_reg(), -1); 3301 } else { 3302 SetFPUWordResult2(fd_reg(), 0); 3303 } 3304 break; 3305 case CMP_OR: 3306 if (!std::isnan(fs) && !std::isnan(ft)) { 3307 SetFPUWordResult2(fd_reg(), -1); 3308 } else { 3309 SetFPUWordResult2(fd_reg(), 0); 3310 } 3311 break; 3312 case CMP_UNE: 3313 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { 3314 SetFPUWordResult2(fd_reg(), -1); 3315 } else { 3316 SetFPUWordResult2(fd_reg(), 0); 3317 } 3318 break; 3319 case CMP_NE: 3320 if (fs != ft) { 3321 SetFPUWordResult2(fd_reg(), -1); 3322 } else { 3323 SetFPUWordResult2(fd_reg(), 0); 3324 } 3325 break; 3326 default: 3327 UNREACHABLE(); 3328 } 3329} 3330 3331 3332void Simulator::DecodeTypeRegisterLRsType() { 3333 double fs = get_fpu_register_double(fs_reg()); 3334 double ft = get_fpu_register_double(ft_reg()); 3335 int64_t i64; 3336 switch (instr_.FunctionFieldRaw()) { 3337 case CVT_D_L: // Mips32r2 instruction. 3338 i64 = get_fpu_register(fs_reg()); 3339 SetFPUDoubleResult(fd_reg(), static_cast<double>(i64)); 3340 break; 3341 case CVT_S_L: 3342 i64 = get_fpu_register(fs_reg()); 3343 SetFPUFloatResult(fd_reg(), static_cast<float>(i64)); 3344 break; 3345 case CMP_AF: 3346 SetFPUResult(fd_reg(), 0); 3347 break; 3348 case CMP_UN: 3349 if (std::isnan(fs) || std::isnan(ft)) { 3350 SetFPUResult(fd_reg(), -1); 3351 } else { 3352 SetFPUResult(fd_reg(), 0); 3353 } 3354 break; 3355 case CMP_EQ: 3356 if (fs == ft) { 3357 SetFPUResult(fd_reg(), -1); 3358 } else { 3359 SetFPUResult(fd_reg(), 0); 3360 } 3361 break; 3362 case CMP_UEQ: 3363 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { 3364 SetFPUResult(fd_reg(), -1); 3365 } else { 3366 SetFPUResult(fd_reg(), 0); 3367 } 3368 break; 3369 case CMP_LT: 3370 if (fs < ft) { 3371 SetFPUResult(fd_reg(), -1); 3372 } else { 3373 SetFPUResult(fd_reg(), 0); 3374 } 3375 break; 3376 case CMP_ULT: 3377 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { 3378 SetFPUResult(fd_reg(), -1); 3379 } else { 3380 SetFPUResult(fd_reg(), 0); 3381 } 3382 break; 3383 case CMP_LE: 3384 if (fs <= ft) { 3385 SetFPUResult(fd_reg(), -1); 3386 } else { 3387 SetFPUResult(fd_reg(), 0); 3388 } 3389 break; 3390 case CMP_ULE: 3391 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { 3392 SetFPUResult(fd_reg(), -1); 3393 } else { 3394 SetFPUResult(fd_reg(), 0); 3395 } 3396 break; 3397 case CMP_OR: 3398 if (!std::isnan(fs) && !std::isnan(ft)) { 3399 SetFPUResult(fd_reg(), -1); 3400 } else { 3401 SetFPUResult(fd_reg(), 0); 3402 } 3403 break; 3404 case CMP_UNE: 3405 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { 3406 SetFPUResult(fd_reg(), -1); 3407 } else { 3408 SetFPUResult(fd_reg(), 0); 3409 } 3410 break; 3411 case CMP_NE: 3412 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { 3413 SetFPUResult(fd_reg(), -1); 3414 } else { 3415 SetFPUResult(fd_reg(), 0); 3416 } 3417 break; 3418 default: 3419 UNREACHABLE(); 3420 } 3421} 3422 3423 3424void Simulator::DecodeTypeRegisterCOP1() { 3425 switch (instr_.RsFieldRaw()) { 3426 case BC1: // Branch on coprocessor condition. 3427 case BC1EQZ: 3428 case BC1NEZ: 3429 UNREACHABLE(); 3430 break; 3431 case CFC1: 3432 // At the moment only FCSR is supported. 3433 DCHECK(fs_reg() == kFCSRRegister); 3434 SetResult(rt_reg(), FCSR_); 3435 break; 3436 case MFC1: 3437 set_register(rt_reg(), 3438 static_cast<int64_t>(get_fpu_register_word(fs_reg()))); 3439 TraceRegWr(get_register(rt_reg()), WORD_DWORD); 3440 break; 3441 case DMFC1: 3442 SetResult(rt_reg(), get_fpu_register(fs_reg())); 3443 break; 3444 case MFHC1: 3445 SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg())); 3446 break; 3447 case CTC1: { 3448 // At the moment only FCSR is supported. 3449 DCHECK(fs_reg() == kFCSRRegister); 3450 uint32_t reg = static_cast<uint32_t>(rt()); 3451 if (kArchVariant == kMips64r6) { 3452 FCSR_ = reg | kFCSRNaN2008FlagMask; 3453 } else { 3454 DCHECK(kArchVariant == kMips64r2); 3455 FCSR_ = reg & ~kFCSRNaN2008FlagMask; 3456 } 3457 TraceRegWr(FCSR_); 3458 break; 3459 } 3460 case MTC1: 3461 // Hardware writes upper 32-bits to zero on mtc1. 3462 set_fpu_register_hi_word(fs_reg(), 0); 3463 set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt())); 3464 TraceRegWr(get_fpu_register(fs_reg()), FLOAT_DOUBLE); 3465 break; 3466 case DMTC1: 3467 SetFPUResult2(fs_reg(), rt()); 3468 break; 3469 case MTHC1: 3470 set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt())); 3471 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); 3472 break; 3473 case S: 3474 DecodeTypeRegisterSRsType(); 3475 break; 3476 case D: 3477 DecodeTypeRegisterDRsType(); 3478 break; 3479 case W: 3480 DecodeTypeRegisterWRsType(); 3481 break; 3482 case L: 3483 DecodeTypeRegisterLRsType(); 3484 break; 3485 default: 3486 UNREACHABLE(); 3487 } 3488} 3489 3490 3491void Simulator::DecodeTypeRegisterCOP1X() { 3492 switch (instr_.FunctionFieldRaw()) { 3493 case MADD_S: { 3494 DCHECK(kArchVariant == kMips64r2); 3495 float fr, ft, fs; 3496 fr = get_fpu_register_float(fr_reg()); 3497 fs = get_fpu_register_float(fs_reg()); 3498 ft = get_fpu_register_float(ft_reg()); 3499 SetFPUFloatResult(fd_reg(), fs * ft + fr); 3500 break; 3501 } 3502 case MSUB_S: { 3503 DCHECK(kArchVariant == kMips64r2); 3504 float fr, ft, fs; 3505 fr = get_fpu_register_float(fr_reg()); 3506 fs = get_fpu_register_float(fs_reg()); 3507 ft = get_fpu_register_float(ft_reg()); 3508 SetFPUFloatResult(fd_reg(), fs * ft - fr); 3509 break; 3510 } 3511 case MADD_D: { 3512 DCHECK(kArchVariant == kMips64r2); 3513 double fr, ft, fs; 3514 fr = get_fpu_register_double(fr_reg()); 3515 fs = get_fpu_register_double(fs_reg()); 3516 ft = get_fpu_register_double(ft_reg()); 3517 SetFPUDoubleResult(fd_reg(), fs * ft + fr); 3518 break; 3519 } 3520 case MSUB_D: { 3521 DCHECK(kArchVariant == kMips64r2); 3522 double fr, ft, fs; 3523 fr = get_fpu_register_double(fr_reg()); 3524 fs = get_fpu_register_double(fs_reg()); 3525 ft = get_fpu_register_double(ft_reg()); 3526 SetFPUDoubleResult(fd_reg(), fs * ft - fr); 3527 break; 3528 } 3529 default: 3530 UNREACHABLE(); 3531 } 3532} 3533 3534 3535void Simulator::DecodeTypeRegisterSPECIAL() { 3536 int64_t i64hilo; 3537 uint64_t u64hilo; 3538 int64_t alu_out; 3539 bool do_interrupt = false; 3540 3541 switch (instr_.FunctionFieldRaw()) { 3542 case SELEQZ_S: 3543 DCHECK(kArchVariant == kMips64r6); 3544 SetResult(rd_reg(), rt() == 0 ? rs() : 0); 3545 break; 3546 case SELNEZ_S: 3547 DCHECK(kArchVariant == kMips64r6); 3548 SetResult(rd_reg(), rt() != 0 ? rs() : 0); 3549 break; 3550 case JR: { 3551 int64_t next_pc = rs(); 3552 int64_t current_pc = get_pc(); 3553 Instruction* branch_delay_instr = 3554 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 3555 BranchDelayInstructionDecode(branch_delay_instr); 3556 set_pc(next_pc); 3557 pc_modified_ = true; 3558 break; 3559 } 3560 case JALR: { 3561 int64_t next_pc = rs(); 3562 int64_t current_pc = get_pc(); 3563 int32_t return_addr_reg = rd_reg(); 3564 Instruction* branch_delay_instr = 3565 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 3566 BranchDelayInstructionDecode(branch_delay_instr); 3567 set_register(return_addr_reg, current_pc + 2 * Instruction::kInstrSize); 3568 set_pc(next_pc); 3569 pc_modified_ = true; 3570 break; 3571 } 3572 case SLL: 3573 SetResult(rd_reg(), static_cast<int32_t>(rt()) << sa()); 3574 break; 3575 case DSLL: 3576 SetResult(rd_reg(), rt() << sa()); 3577 break; 3578 case DSLL32: 3579 SetResult(rd_reg(), rt() << sa() << 32); 3580 break; 3581 case SRL: 3582 if (rs_reg() == 0) { 3583 // Regular logical right shift of a word by a fixed number of 3584 // bits instruction. RS field is always equal to 0. 3585 // Sign-extend the 32-bit result. 3586 alu_out = static_cast<int32_t>(static_cast<uint32_t>(rt_u()) >> sa()); 3587 } else if (rs_reg() == 1) { 3588 // Logical right-rotate of a word by a fixed number of bits. This 3589 // is special case of SRL instruction, added in MIPS32 Release 2. 3590 // RS field is equal to 00001. 3591 alu_out = static_cast<int32_t>( 3592 base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()), 3593 static_cast<const uint32_t>(sa()))); 3594 } else { 3595 UNREACHABLE(); 3596 } 3597 SetResult(rd_reg(), alu_out); 3598 break; 3599 case DSRL: 3600 if (rs_reg() == 0) { 3601 // Regular logical right shift of a word by a fixed number of 3602 // bits instruction. RS field is always equal to 0. 3603 // Sign-extend the 64-bit result. 3604 alu_out = static_cast<int64_t>(rt_u() >> sa()); 3605 } else if (rs_reg() == 1) { 3606 // Logical right-rotate of a word by a fixed number of bits. This 3607 // is special case of SRL instruction, added in MIPS32 Release 2. 3608 // RS field is equal to 00001. 3609 alu_out = static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa())); 3610 } else { 3611 UNREACHABLE(); 3612 } 3613 SetResult(rd_reg(), alu_out); 3614 break; 3615 case DSRL32: 3616 if (rs_reg() == 0) { 3617 // Regular logical right shift of a word by a fixed number of 3618 // bits instruction. RS field is always equal to 0. 3619 // Sign-extend the 64-bit result. 3620 alu_out = static_cast<int64_t>(rt_u() >> sa() >> 32); 3621 } else if (rs_reg() == 1) { 3622 // Logical right-rotate of a word by a fixed number of bits. This 3623 // is special case of SRL instruction, added in MIPS32 Release 2. 3624 // RS field is equal to 00001. 3625 alu_out = 3626 static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa() + 32)); 3627 } else { 3628 UNREACHABLE(); 3629 } 3630 SetResult(rd_reg(), alu_out); 3631 break; 3632 case SRA: 3633 SetResult(rd_reg(), (int32_t)rt() >> sa()); 3634 break; 3635 case DSRA: 3636 SetResult(rd_reg(), rt() >> sa()); 3637 break; 3638 case DSRA32: 3639 SetResult(rd_reg(), rt() >> sa() >> 32); 3640 break; 3641 case SLLV: 3642 SetResult(rd_reg(), (int32_t)rt() << rs()); 3643 break; 3644 case DSLLV: 3645 SetResult(rd_reg(), rt() << rs()); 3646 break; 3647 case SRLV: 3648 if (sa() == 0) { 3649 // Regular logical right-shift of a word by a variable number of 3650 // bits instruction. SA field is always equal to 0. 3651 alu_out = static_cast<int32_t>((uint32_t)rt_u() >> rs()); 3652 } else { 3653 // Logical right-rotate of a word by a variable number of bits. 3654 // This is special case od SRLV instruction, added in MIPS32 3655 // Release 2. SA field is equal to 00001. 3656 alu_out = static_cast<int32_t>( 3657 base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()), 3658 static_cast<const uint32_t>(rs_u()))); 3659 } 3660 SetResult(rd_reg(), alu_out); 3661 break; 3662 case DSRLV: 3663 if (sa() == 0) { 3664 // Regular logical right-shift of a word by a variable number of 3665 // bits instruction. SA field is always equal to 0. 3666 alu_out = static_cast<int64_t>(rt_u() >> rs()); 3667 } else { 3668 // Logical right-rotate of a word by a variable number of bits. 3669 // This is special case od SRLV instruction, added in MIPS32 3670 // Release 2. SA field is equal to 00001. 3671 alu_out = 3672 static_cast<int64_t>(base::bits::RotateRight64(rt_u(), rs_u())); 3673 } 3674 SetResult(rd_reg(), alu_out); 3675 break; 3676 case SRAV: 3677 SetResult(rd_reg(), (int32_t)rt() >> rs()); 3678 break; 3679 case DSRAV: 3680 SetResult(rd_reg(), rt() >> rs()); 3681 break; 3682 case LSA: { 3683 DCHECK(kArchVariant == kMips64r6); 3684 int8_t sa = lsa_sa() + 1; 3685 int32_t _rt = static_cast<int32_t>(rt()); 3686 int32_t _rs = static_cast<int32_t>(rs()); 3687 int32_t res = _rs << sa; 3688 res += _rt; 3689 SetResult(rd_reg(), static_cast<int64_t>(res)); 3690 break; 3691 } 3692 case DLSA: 3693 DCHECK(kArchVariant == kMips64r6); 3694 SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt()); 3695 break; 3696 case MFHI: // MFHI == CLZ on R6. 3697 if (kArchVariant != kMips64r6) { 3698 DCHECK(sa() == 0); 3699 alu_out = get_register(HI); 3700 } else { 3701 // MIPS spec: If no bits were set in GPR rs(), the result written to 3702 // GPR rd() is 32. 3703 DCHECK(sa() == 1); 3704 alu_out = base::bits::CountLeadingZeros32(static_cast<int32_t>(rs_u())); 3705 } 3706 SetResult(rd_reg(), alu_out); 3707 break; 3708 case MFLO: // MFLO == DCLZ on R6. 3709 if (kArchVariant != kMips64r6) { 3710 DCHECK(sa() == 0); 3711 alu_out = get_register(LO); 3712 } else { 3713 // MIPS spec: If no bits were set in GPR rs(), the result written to 3714 // GPR rd() is 64. 3715 DCHECK(sa() == 1); 3716 alu_out = base::bits::CountLeadingZeros64(static_cast<int64_t>(rs_u())); 3717 } 3718 SetResult(rd_reg(), alu_out); 3719 break; 3720 // Instructions using HI and LO registers. 3721 case MULT: { // MULT == D_MUL_MUH. 3722 int32_t rs_lo = static_cast<int32_t>(rs()); 3723 int32_t rt_lo = static_cast<int32_t>(rt()); 3724 i64hilo = static_cast<int64_t>(rs_lo) * static_cast<int64_t>(rt_lo); 3725 if (kArchVariant != kMips64r6) { 3726 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); 3727 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); 3728 } else { 3729 switch (sa()) { 3730 case MUL_OP: 3731 SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); 3732 break; 3733 case MUH_OP: 3734 SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); 3735 break; 3736 default: 3737 UNIMPLEMENTED_MIPS(); 3738 break; 3739 } 3740 } 3741 break; 3742 } 3743 case MULTU: 3744 u64hilo = static_cast<uint64_t>(rs_u() & 0xffffffff) * 3745 static_cast<uint64_t>(rt_u() & 0xffffffff); 3746 if (kArchVariant != kMips64r6) { 3747 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); 3748 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); 3749 } else { 3750 switch (sa()) { 3751 case MUL_OP: 3752 SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); 3753 break; 3754 case MUH_OP: 3755 SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); 3756 break; 3757 default: 3758 UNIMPLEMENTED_MIPS(); 3759 break; 3760 } 3761 } 3762 break; 3763 case DMULT: // DMULT == D_MUL_MUH. 3764 if (kArchVariant != kMips64r6) { 3765 set_register(LO, rs() * rt()); 3766 set_register(HI, MultiplyHighSigned(rs(), rt())); 3767 } else { 3768 switch (sa()) { 3769 case MUL_OP: 3770 SetResult(rd_reg(), rs() * rt()); 3771 break; 3772 case MUH_OP: 3773 SetResult(rd_reg(), MultiplyHighSigned(rs(), rt())); 3774 break; 3775 default: 3776 UNIMPLEMENTED_MIPS(); 3777 break; 3778 } 3779 } 3780 break; 3781 case DMULTU: 3782 UNIMPLEMENTED_MIPS(); 3783 break; 3784 case DIV: 3785 case DDIV: { 3786 const int64_t int_min_value = 3787 instr_.FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN; 3788 switch (kArchVariant) { 3789 case kMips64r2: 3790 // Divide by zero and overflow was not checked in the 3791 // configuration step - div and divu do not raise exceptions. On 3792 // division by 0 the result will be UNPREDICTABLE. On overflow 3793 // (INT_MIN/-1), return INT_MIN which is what the hardware does. 3794 if (rs() == int_min_value && rt() == -1) { 3795 set_register(LO, int_min_value); 3796 set_register(HI, 0); 3797 } else if (rt() != 0) { 3798 set_register(LO, rs() / rt()); 3799 set_register(HI, rs() % rt()); 3800 } 3801 break; 3802 case kMips64r6: 3803 switch (sa()) { 3804 case DIV_OP: 3805 if (rs() == int_min_value && rt() == -1) { 3806 SetResult(rd_reg(), int_min_value); 3807 } else if (rt() != 0) { 3808 SetResult(rd_reg(), rs() / rt()); 3809 } 3810 break; 3811 case MOD_OP: 3812 if (rs() == int_min_value && rt() == -1) { 3813 SetResult(rd_reg(), 0); 3814 } else if (rt() != 0) { 3815 SetResult(rd_reg(), rs() % rt()); 3816 } 3817 break; 3818 default: 3819 UNIMPLEMENTED_MIPS(); 3820 break; 3821 } 3822 break; 3823 default: 3824 break; 3825 } 3826 break; 3827 } 3828 case DIVU: 3829 switch (kArchVariant) { 3830 case kMips64r6: { 3831 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); 3832 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); 3833 switch (sa()) { 3834 case DIV_OP: 3835 if (rt_u_32 != 0) { 3836 SetResult(rd_reg(), rs_u_32 / rt_u_32); 3837 } 3838 break; 3839 case MOD_OP: 3840 if (rt_u() != 0) { 3841 SetResult(rd_reg(), rs_u_32 % rt_u_32); 3842 } 3843 break; 3844 default: 3845 UNIMPLEMENTED_MIPS(); 3846 break; 3847 } 3848 } break; 3849 default: { 3850 if (rt_u() != 0) { 3851 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); 3852 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); 3853 set_register(LO, rs_u_32 / rt_u_32); 3854 set_register(HI, rs_u_32 % rt_u_32); 3855 } 3856 } 3857 } 3858 break; 3859 case DDIVU: 3860 switch (kArchVariant) { 3861 case kMips64r6: { 3862 switch (instr_.SaValue()) { 3863 case DIV_OP: 3864 if (rt_u() != 0) { 3865 SetResult(rd_reg(), rs_u() / rt_u()); 3866 } 3867 break; 3868 case MOD_OP: 3869 if (rt_u() != 0) { 3870 SetResult(rd_reg(), rs_u() % rt_u()); 3871 } 3872 break; 3873 default: 3874 UNIMPLEMENTED_MIPS(); 3875 break; 3876 } 3877 } break; 3878 default: { 3879 if (rt_u() != 0) { 3880 set_register(LO, rs_u() / rt_u()); 3881 set_register(HI, rs_u() % rt_u()); 3882 } 3883 } 3884 } 3885 break; 3886 case ADD: 3887 case DADD: 3888 if (HaveSameSign(rs(), rt())) { 3889 if (rs() > 0) { 3890 if (rs() > (Registers::kMaxValue - rt())) { 3891 SignalException(kIntegerOverflow); 3892 } 3893 } else if (rs() < 0) { 3894 if (rs() < (Registers::kMinValue - rt())) { 3895 SignalException(kIntegerUnderflow); 3896 } 3897 } 3898 } 3899 SetResult(rd_reg(), rs() + rt()); 3900 break; 3901 case ADDU: { 3902 int32_t alu32_out = static_cast<int32_t>(rs() + rt()); 3903 // Sign-extend result of 32bit operation into 64bit register. 3904 SetResult(rd_reg(), static_cast<int64_t>(alu32_out)); 3905 break; 3906 } 3907 case DADDU: 3908 SetResult(rd_reg(), rs() + rt()); 3909 break; 3910 case SUB: 3911 case DSUB: 3912 if (!HaveSameSign(rs(), rt())) { 3913 if (rs() > 0) { 3914 if (rs() > (Registers::kMaxValue + rt())) { 3915 SignalException(kIntegerOverflow); 3916 } 3917 } else if (rs() < 0) { 3918 if (rs() < (Registers::kMinValue + rt())) { 3919 SignalException(kIntegerUnderflow); 3920 } 3921 } 3922 } 3923 SetResult(rd_reg(), rs() - rt()); 3924 break; 3925 case SUBU: { 3926 int32_t alu32_out = static_cast<int32_t>(rs() - rt()); 3927 // Sign-extend result of 32bit operation into 64bit register. 3928 SetResult(rd_reg(), static_cast<int64_t>(alu32_out)); 3929 break; 3930 } 3931 case DSUBU: 3932 SetResult(rd_reg(), rs() - rt()); 3933 break; 3934 case AND: 3935 SetResult(rd_reg(), rs() & rt()); 3936 break; 3937 case OR: 3938 SetResult(rd_reg(), rs() | rt()); 3939 break; 3940 case XOR: 3941 SetResult(rd_reg(), rs() ^ rt()); 3942 break; 3943 case NOR: 3944 SetResult(rd_reg(), ~(rs() | rt())); 3945 break; 3946 case SLT: 3947 SetResult(rd_reg(), rs() < rt() ? 1 : 0); 3948 break; 3949 case SLTU: 3950 SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0); 3951 break; 3952 // Break and trap instructions. 3953 case BREAK: 3954 do_interrupt = true; 3955 break; 3956 case TGE: 3957 do_interrupt = rs() >= rt(); 3958 break; 3959 case TGEU: 3960 do_interrupt = rs_u() >= rt_u(); 3961 break; 3962 case TLT: 3963 do_interrupt = rs() < rt(); 3964 break; 3965 case TLTU: 3966 do_interrupt = rs_u() < rt_u(); 3967 break; 3968 case TEQ: 3969 do_interrupt = rs() == rt(); 3970 break; 3971 case TNE: 3972 do_interrupt = rs() != rt(); 3973 break; 3974 case SYNC: 3975 // TODO(palfia): Ignore sync instruction for now. 3976 break; 3977 // Conditional moves. 3978 case MOVN: 3979 if (rt()) { 3980 SetResult(rd_reg(), rs()); 3981 } 3982 break; 3983 case MOVCI: { 3984 uint32_t cc = instr_.FBccValue(); 3985 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); 3986 if (instr_.Bit(16)) { // Read Tf bit. 3987 if (test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs()); 3988 } else { 3989 if (!test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs()); 3990 } 3991 break; 3992 } 3993 case MOVZ: 3994 if (!rt()) { 3995 SetResult(rd_reg(), rs()); 3996 } 3997 break; 3998 default: 3999 UNREACHABLE(); 4000 } 4001 if (do_interrupt) { 4002 SoftwareInterrupt(); 4003 } 4004} 4005 4006 4007void Simulator::DecodeTypeRegisterSPECIAL2() { 4008 int64_t alu_out; 4009 switch (instr_.FunctionFieldRaw()) { 4010 case MUL: 4011 alu_out = static_cast<int32_t>(rs_u()) * static_cast<int32_t>(rt_u()); 4012 SetResult(rd_reg(), alu_out); 4013 // HI and LO are UNPREDICTABLE after the operation. 4014 set_register(LO, Unpredictable); 4015 set_register(HI, Unpredictable); 4016 break; 4017 case CLZ: 4018 // MIPS32 spec: If no bits were set in GPR rs(), the result written to 4019 // GPR rd is 32. 4020 alu_out = base::bits::CountLeadingZeros32(static_cast<uint32_t>(rs_u())); 4021 SetResult(rd_reg(), alu_out); 4022 break; 4023 case DCLZ: 4024 // MIPS64 spec: If no bits were set in GPR rs(), the result written to 4025 // GPR rd is 64. 4026 alu_out = base::bits::CountLeadingZeros64(static_cast<uint64_t>(rs_u())); 4027 SetResult(rd_reg(), alu_out); 4028 break; 4029 default: 4030 alu_out = 0x12345678; 4031 UNREACHABLE(); 4032 } 4033} 4034 4035 4036void Simulator::DecodeTypeRegisterSPECIAL3() { 4037 int64_t alu_out; 4038 switch (instr_.FunctionFieldRaw()) { 4039 case INS: { // Mips64r2 instruction. 4040 // Interpret rd field as 5-bit msb of insert. 4041 uint16_t msb = rd_reg(); 4042 // Interpret sa field as 5-bit lsb of insert. 4043 uint16_t lsb = sa(); 4044 uint16_t size = msb - lsb + 1; 4045 uint64_t mask = (1ULL << size) - 1; 4046 alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) | 4047 ((rs_u() & mask) << lsb)); 4048 SetResult(rt_reg(), alu_out); 4049 break; 4050 } 4051 case DINS: { // Mips64r2 instruction. 4052 // Interpret rd field as 5-bit msb of insert. 4053 uint16_t msb = rd_reg(); 4054 // Interpret sa field as 5-bit lsb of insert. 4055 uint16_t lsb = sa(); 4056 uint16_t size = msb - lsb + 1; 4057 uint64_t mask = (1ULL << size) - 1; 4058 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb); 4059 SetResult(rt_reg(), alu_out); 4060 break; 4061 } 4062 case EXT: { // Mips64r2 instruction. 4063 // Interpret rd field as 5-bit msb of extract. 4064 uint16_t msb = rd_reg(); 4065 // Interpret sa field as 5-bit lsb of extract. 4066 uint16_t lsb = sa(); 4067 uint16_t size = msb + 1; 4068 uint64_t mask = (1ULL << size) - 1; 4069 alu_out = static_cast<int32_t>((rs_u() & (mask << lsb)) >> lsb); 4070 SetResult(rt_reg(), alu_out); 4071 break; 4072 } 4073 case DEXT: { // Mips64r2 instruction. 4074 // Interpret rd field as 5-bit msb of extract. 4075 uint16_t msb = rd_reg(); 4076 // Interpret sa field as 5-bit lsb of extract. 4077 uint16_t lsb = sa(); 4078 uint16_t size = msb + 1; 4079 uint64_t mask = (1ULL << size) - 1; 4080 alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb); 4081 SetResult(rt_reg(), alu_out); 4082 break; 4083 } 4084 case DEXTM: { 4085 // Interpret rd field as 5-bit msb of extract. 4086 uint16_t msb = rd_reg(); 4087 // Interpret sa field as 5-bit lsb of extract. 4088 uint16_t lsb = sa(); 4089 uint16_t size = msb + 33; 4090 uint64_t mask = (1ULL << size) - 1; 4091 alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb); 4092 SetResult(rt_reg(), alu_out); 4093 break; 4094 } 4095 case DEXTU: { 4096 // Interpret rd field as 5-bit msb of extract. 4097 uint16_t msb = rd_reg(); 4098 // Interpret sa field as 5-bit lsb of extract. 4099 uint16_t lsb = sa() + 32; 4100 uint16_t size = msb + 1; 4101 uint64_t mask = (1ULL << size) - 1; 4102 alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb); 4103 SetResult(rt_reg(), alu_out); 4104 break; 4105 } 4106 case BSHFL: { 4107 int32_t sa = instr_.SaFieldRaw() >> kSaShift; 4108 switch (sa) { 4109 case BITSWAP: { 4110 uint32_t input = static_cast<uint32_t>(rt()); 4111 uint32_t output = 0; 4112 uint8_t i_byte, o_byte; 4113 4114 // Reverse the bit in byte for each individual byte 4115 for (int i = 0; i < 4; i++) { 4116 output = output >> 8; 4117 i_byte = input & 0xff; 4118 4119 // Fast way to reverse bits in byte 4120 // Devised by Sean Anderson, July 13, 2001 4121 o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | 4122 (i_byte * 0x8020LU & 0x88440LU)) * 4123 0x10101LU >> 4124 16); 4125 4126 output = output | (static_cast<uint32_t>(o_byte << 24)); 4127 input = input >> 8; 4128 } 4129 4130 alu_out = static_cast<int64_t>(static_cast<int32_t>(output)); 4131 break; 4132 } 4133 case SEB: { 4134 uint8_t input = static_cast<uint8_t>(rt()); 4135 uint32_t output = input; 4136 uint32_t mask = 0x00000080; 4137 4138 // Extending sign 4139 if (mask & input) { 4140 output |= 0xFFFFFF00; 4141 } 4142 4143 alu_out = static_cast<int32_t>(output); 4144 break; 4145 } 4146 case SEH: { 4147 uint16_t input = static_cast<uint16_t>(rt()); 4148 uint32_t output = input; 4149 uint32_t mask = 0x00008000; 4150 4151 // Extending sign 4152 if (mask & input) { 4153 output |= 0xFFFF0000; 4154 } 4155 4156 alu_out = static_cast<int32_t>(output); 4157 break; 4158 } 4159 case WSBH: { 4160 uint32_t input = static_cast<uint32_t>(rt()); 4161 uint64_t output = 0; 4162 4163 uint32_t mask = 0xFF000000; 4164 for (int i = 0; i < 4; i++) { 4165 uint32_t tmp = mask & input; 4166 if (i % 2 == 0) { 4167 tmp = tmp >> 8; 4168 } else { 4169 tmp = tmp << 8; 4170 } 4171 output = output | tmp; 4172 mask = mask >> 8; 4173 } 4174 mask = 0x80000000; 4175 4176 // Extending sign 4177 if (mask & output) { 4178 output |= 0xFFFFFFFF00000000; 4179 } 4180 4181 alu_out = static_cast<int64_t>(output); 4182 break; 4183 } 4184 default: { 4185 const uint8_t bp2 = instr_.Bp2Value(); 4186 sa >>= kBp2Bits; 4187 switch (sa) { 4188 case ALIGN: { 4189 if (bp2 == 0) { 4190 alu_out = static_cast<int32_t>(rt()); 4191 } else { 4192 uint64_t rt_hi = rt() << (8 * bp2); 4193 uint64_t rs_lo = rs() >> (8 * (4 - bp2)); 4194 alu_out = static_cast<int32_t>(rt_hi | rs_lo); 4195 } 4196 break; 4197 } 4198 default: 4199 alu_out = 0x12345678; 4200 UNREACHABLE(); 4201 break; 4202 } 4203 break; 4204 } 4205 } 4206 SetResult(rd_reg(), alu_out); 4207 break; 4208 } 4209 case DBSHFL: { 4210 int32_t sa = instr_.SaFieldRaw() >> kSaShift; 4211 switch (sa) { 4212 case DBITSWAP: { 4213 switch (sa) { 4214 case DBITSWAP_SA: { // Mips64r6 4215 uint64_t input = static_cast<uint64_t>(rt()); 4216 uint64_t output = 0; 4217 uint8_t i_byte, o_byte; 4218 4219 // Reverse the bit in byte for each individual byte 4220 for (int i = 0; i < 8; i++) { 4221 output = output >> 8; 4222 i_byte = input & 0xff; 4223 4224 // Fast way to reverse bits in byte 4225 // Devised by Sean Anderson, July 13, 2001 4226 o_byte = 4227 static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | 4228 (i_byte * 0x8020LU & 0x88440LU)) * 4229 0x10101LU >> 4230 16); 4231 4232 output = output | ((static_cast<uint64_t>(o_byte) << 56)); 4233 input = input >> 8; 4234 } 4235 4236 alu_out = static_cast<int64_t>(output); 4237 break; 4238 } 4239 } 4240 break; 4241 } 4242 case DSBH: { 4243 uint64_t input = static_cast<uint64_t>(rt()); 4244 uint64_t output = 0; 4245 4246 uint64_t mask = 0xFF00000000000000; 4247 for (int i = 0; i < 8; i++) { 4248 uint64_t tmp = mask & input; 4249 if (i % 2 == 0) 4250 tmp = tmp >> 8; 4251 else 4252 tmp = tmp << 8; 4253 4254 output = output | tmp; 4255 mask = mask >> 8; 4256 } 4257 4258 alu_out = static_cast<int64_t>(output); 4259 break; 4260 } 4261 case DSHD: { 4262 uint64_t input = static_cast<uint64_t>(rt()); 4263 uint64_t output = 0; 4264 4265 uint64_t mask = 0xFFFF000000000000; 4266 for (int i = 0; i < 4; i++) { 4267 uint64_t tmp = mask & input; 4268 if (i == 0) 4269 tmp = tmp >> 48; 4270 else if (i == 1) 4271 tmp = tmp >> 16; 4272 else if (i == 2) 4273 tmp = tmp << 16; 4274 else 4275 tmp = tmp << 48; 4276 output = output | tmp; 4277 mask = mask >> 16; 4278 } 4279 4280 alu_out = static_cast<int64_t>(output); 4281 break; 4282 } 4283 default: { 4284 const uint8_t bp3 = instr_.Bp3Value(); 4285 sa >>= kBp3Bits; 4286 switch (sa) { 4287 case DALIGN: { 4288 if (bp3 == 0) { 4289 alu_out = static_cast<int64_t>(rt()); 4290 } else { 4291 uint64_t rt_hi = rt() << (8 * bp3); 4292 uint64_t rs_lo = rs() >> (8 * (8 - bp3)); 4293 alu_out = static_cast<int64_t>(rt_hi | rs_lo); 4294 } 4295 break; 4296 } 4297 default: 4298 alu_out = 0x12345678; 4299 UNREACHABLE(); 4300 break; 4301 } 4302 break; 4303 } 4304 } 4305 SetResult(rd_reg(), alu_out); 4306 break; 4307 } 4308 default: 4309 UNREACHABLE(); 4310 } 4311} 4312 4313void Simulator::DecodeTypeRegister() { 4314 // ---------- Execution. 4315 switch (instr_.OpcodeFieldRaw()) { 4316 case COP1: 4317 DecodeTypeRegisterCOP1(); 4318 break; 4319 case COP1X: 4320 DecodeTypeRegisterCOP1X(); 4321 break; 4322 case SPECIAL: 4323 DecodeTypeRegisterSPECIAL(); 4324 break; 4325 case SPECIAL2: 4326 DecodeTypeRegisterSPECIAL2(); 4327 break; 4328 case SPECIAL3: 4329 DecodeTypeRegisterSPECIAL3(); 4330 break; 4331 // Unimplemented opcodes raised an error in the configuration step before, 4332 // so we can use the default here to set the destination register in common 4333 // cases. 4334 default: 4335 UNREACHABLE(); 4336 } 4337} 4338 4339 4340// Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). 4341void Simulator::DecodeTypeImmediate() { 4342 // Instruction fields. 4343 Opcode op = instr_.OpcodeFieldRaw(); 4344 int32_t rs_reg = instr_.RsValue(); 4345 int64_t rs = get_register(instr_.RsValue()); 4346 uint64_t rs_u = static_cast<uint64_t>(rs); 4347 int32_t rt_reg = instr_.RtValue(); // Destination register. 4348 int64_t rt = get_register(rt_reg); 4349 int16_t imm16 = instr_.Imm16Value(); 4350 int32_t imm18 = instr_.Imm18Value(); 4351 4352 int32_t ft_reg = instr_.FtValue(); // Destination register. 4353 4354 // Zero extended immediate. 4355 uint64_t oe_imm16 = 0xffff & imm16; 4356 // Sign extended immediate. 4357 int64_t se_imm16 = imm16; 4358 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); 4359 4360 // Next pc. 4361 int64_t next_pc = bad_ra; 4362 4363 // Used for conditional branch instructions. 4364 bool execute_branch_delay_instruction = false; 4365 4366 // Used for arithmetic instructions. 4367 int64_t alu_out = 0; 4368 4369 // Used for memory instructions. 4370 int64_t addr = 0x0; 4371 // Alignment for 32-bit integers used in LWL, LWR, etc. 4372 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; 4373 // Alignment for 64-bit integers used in LDL, LDR, etc. 4374 const int kInt64AlignmentMask = sizeof(uint64_t) - 1; 4375 4376 // Branch instructions common part. 4377 auto BranchAndLinkHelper = 4378 [this, &next_pc, &execute_branch_delay_instruction](bool do_branch) { 4379 execute_branch_delay_instruction = true; 4380 int64_t current_pc = get_pc(); 4381 if (do_branch) { 4382 int16_t imm16 = instr_.Imm16Value(); 4383 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 4384 set_register(31, current_pc + 2 * Instruction::kInstrSize); 4385 } else { 4386 next_pc = current_pc + 2 * Instruction::kInstrSize; 4387 } 4388 }; 4389 4390 auto BranchHelper = [this, &next_pc, 4391 &execute_branch_delay_instruction](bool do_branch) { 4392 execute_branch_delay_instruction = true; 4393 int64_t current_pc = get_pc(); 4394 if (do_branch) { 4395 int16_t imm16 = instr_.Imm16Value(); 4396 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; 4397 } else { 4398 next_pc = current_pc + 2 * Instruction::kInstrSize; 4399 } 4400 }; 4401 4402 auto BranchAndLinkCompactHelper = [this, &next_pc](bool do_branch, int bits) { 4403 int64_t current_pc = get_pc(); 4404 CheckForbiddenSlot(current_pc); 4405 if (do_branch) { 4406 int32_t imm = instr_.ImmValue(bits); 4407 imm <<= 32 - bits; 4408 imm >>= 32 - bits; 4409 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; 4410 set_register(31, current_pc + Instruction::kInstrSize); 4411 } 4412 }; 4413 4414 auto BranchCompactHelper = [this, &next_pc](bool do_branch, int bits) { 4415 int64_t current_pc = get_pc(); 4416 CheckForbiddenSlot(current_pc); 4417 if (do_branch) { 4418 int32_t imm = instr_.ImmValue(bits); 4419 imm <<= 32 - bits; 4420 imm >>= 32 - bits; 4421 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; 4422 } 4423 }; 4424 4425 switch (op) { 4426 // ------------- COP1. Coprocessor instructions. 4427 case COP1: 4428 switch (instr_.RsFieldRaw()) { 4429 case BC1: { // Branch on coprocessor condition. 4430 uint32_t cc = instr_.FBccValue(); 4431 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); 4432 uint32_t cc_value = test_fcsr_bit(fcsr_cc); 4433 bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value; 4434 BranchHelper(do_branch); 4435 break; 4436 } 4437 case BC1EQZ: 4438 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); 4439 break; 4440 case BC1NEZ: 4441 BranchHelper(get_fpu_register(ft_reg) & 0x1); 4442 break; 4443 default: 4444 UNREACHABLE(); 4445 } 4446 break; 4447 // ------------- REGIMM class. 4448 case REGIMM: 4449 switch (instr_.RtFieldRaw()) { 4450 case BLTZ: 4451 BranchHelper(rs < 0); 4452 break; 4453 case BGEZ: 4454 BranchHelper(rs >= 0); 4455 break; 4456 case BLTZAL: 4457 BranchAndLinkHelper(rs < 0); 4458 break; 4459 case BGEZAL: 4460 BranchAndLinkHelper(rs >= 0); 4461 break; 4462 case DAHI: 4463 SetResult(rs_reg, rs + (se_imm16 << 32)); 4464 break; 4465 case DATI: 4466 SetResult(rs_reg, rs + (se_imm16 << 48)); 4467 break; 4468 default: 4469 UNREACHABLE(); 4470 } 4471 break; // case REGIMM. 4472 // ------------- Branch instructions. 4473 // When comparing to zero, the encoding of rt field is always 0, so we don't 4474 // need to replace rt with zero. 4475 case BEQ: 4476 BranchHelper(rs == rt); 4477 break; 4478 case BNE: 4479 BranchHelper(rs != rt); 4480 break; 4481 case POP06: // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6) 4482 if (kArchVariant == kMips64r6) { 4483 if (rt_reg != 0) { 4484 if (rs_reg == 0) { // BLEZALC 4485 BranchAndLinkCompactHelper(rt <= 0, 16); 4486 } else { 4487 if (rs_reg == rt_reg) { // BGEZALC 4488 BranchAndLinkCompactHelper(rt >= 0, 16); 4489 } else { // BGEUC 4490 BranchCompactHelper( 4491 static_cast<uint64_t>(rs) >= static_cast<uint64_t>(rt), 16); 4492 } 4493 } 4494 } else { // BLEZ 4495 BranchHelper(rs <= 0); 4496 } 4497 } else { // BLEZ 4498 BranchHelper(rs <= 0); 4499 } 4500 break; 4501 case POP07: // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6) 4502 if (kArchVariant == kMips64r6) { 4503 if (rt_reg != 0) { 4504 if (rs_reg == 0) { // BGTZALC 4505 BranchAndLinkCompactHelper(rt > 0, 16); 4506 } else { 4507 if (rt_reg == rs_reg) { // BLTZALC 4508 BranchAndLinkCompactHelper(rt < 0, 16); 4509 } else { // BLTUC 4510 BranchCompactHelper( 4511 static_cast<uint64_t>(rs) < static_cast<uint64_t>(rt), 16); 4512 } 4513 } 4514 } else { // BGTZ 4515 BranchHelper(rs > 0); 4516 } 4517 } else { // BGTZ 4518 BranchHelper(rs > 0); 4519 } 4520 break; 4521 case POP26: // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6) 4522 if (kArchVariant == kMips64r6) { 4523 if (rt_reg != 0) { 4524 if (rs_reg == 0) { // BLEZC 4525 BranchCompactHelper(rt <= 0, 16); 4526 } else { 4527 if (rs_reg == rt_reg) { // BGEZC 4528 BranchCompactHelper(rt >= 0, 16); 4529 } else { // BGEC/BLEC 4530 BranchCompactHelper(rs >= rt, 16); 4531 } 4532 } 4533 } 4534 } else { // BLEZL 4535 BranchAndLinkHelper(rs <= 0); 4536 } 4537 break; 4538 case POP27: // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6) 4539 if (kArchVariant == kMips64r6) { 4540 if (rt_reg != 0) { 4541 if (rs_reg == 0) { // BGTZC 4542 BranchCompactHelper(rt > 0, 16); 4543 } else { 4544 if (rs_reg == rt_reg) { // BLTZC 4545 BranchCompactHelper(rt < 0, 16); 4546 } else { // BLTC/BGTC 4547 BranchCompactHelper(rs < rt, 16); 4548 } 4549 } 4550 } 4551 } else { // BGTZL 4552 BranchAndLinkHelper(rs > 0); 4553 } 4554 break; 4555 case POP66: // BEQZC, JIC 4556 if (rs_reg != 0) { // BEQZC 4557 BranchCompactHelper(rs == 0, 21); 4558 } else { // JIC 4559 next_pc = rt + imm16; 4560 } 4561 break; 4562 case POP76: // BNEZC, JIALC 4563 if (rs_reg != 0) { // BNEZC 4564 BranchCompactHelper(rs != 0, 21); 4565 } else { // JIALC 4566 int64_t current_pc = get_pc(); 4567 set_register(31, current_pc + Instruction::kInstrSize); 4568 next_pc = rt + imm16; 4569 } 4570 break; 4571 case BC: 4572 BranchCompactHelper(true, 26); 4573 break; 4574 case BALC: 4575 BranchAndLinkCompactHelper(true, 26); 4576 break; 4577 case POP10: // BOVC, BEQZALC, BEQC / ADDI (pre-r6) 4578 if (kArchVariant == kMips64r6) { 4579 if (rs_reg >= rt_reg) { // BOVC 4580 bool condition = !is_int32(rs) || !is_int32(rt) || !is_int32(rs + rt); 4581 BranchCompactHelper(condition, 16); 4582 } else { 4583 if (rs_reg == 0) { // BEQZALC 4584 BranchAndLinkCompactHelper(rt == 0, 16); 4585 } else { // BEQC 4586 BranchCompactHelper(rt == rs, 16); 4587 } 4588 } 4589 } else { // ADDI 4590 if (HaveSameSign(rs, se_imm16)) { 4591 if (rs > 0) { 4592 if (rs <= Registers::kMaxValue - se_imm16) { 4593 SignalException(kIntegerOverflow); 4594 } 4595 } else if (rs < 0) { 4596 if (rs >= Registers::kMinValue - se_imm16) { 4597 SignalException(kIntegerUnderflow); 4598 } 4599 } 4600 } 4601 SetResult(rt_reg, rs + se_imm16); 4602 } 4603 break; 4604 case POP30: // BNVC, BNEZALC, BNEC / DADDI (pre-r6) 4605 if (kArchVariant == kMips64r6) { 4606 if (rs_reg >= rt_reg) { // BNVC 4607 bool condition = is_int32(rs) && is_int32(rt) && is_int32(rs + rt); 4608 BranchCompactHelper(condition, 16); 4609 } else { 4610 if (rs_reg == 0) { // BNEZALC 4611 BranchAndLinkCompactHelper(rt != 0, 16); 4612 } else { // BNEC 4613 BranchCompactHelper(rt != rs, 16); 4614 } 4615 } 4616 } 4617 break; 4618 // ------------- Arithmetic instructions. 4619 case ADDIU: { 4620 DCHECK(is_int32(rs)); 4621 int32_t alu32_out = static_cast<int32_t>(rs + se_imm16); 4622 // Sign-extend result of 32bit operation into 64bit register. 4623 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); 4624 break; 4625 } 4626 case DADDIU: 4627 SetResult(rt_reg, rs + se_imm16); 4628 break; 4629 case SLTI: 4630 SetResult(rt_reg, rs < se_imm16 ? 1 : 0); 4631 break; 4632 case SLTIU: 4633 SetResult(rt_reg, rs_u < static_cast<uint64_t>(se_imm16) ? 1 : 0); 4634 break; 4635 case ANDI: 4636 SetResult(rt_reg, rs & oe_imm16); 4637 break; 4638 case ORI: 4639 SetResult(rt_reg, rs | oe_imm16); 4640 break; 4641 case XORI: 4642 SetResult(rt_reg, rs ^ oe_imm16); 4643 break; 4644 case LUI: 4645 if (rs_reg != 0) { 4646 // AUI instruction. 4647 DCHECK(kArchVariant == kMips64r6); 4648 int32_t alu32_out = static_cast<int32_t>(rs + (se_imm16 << 16)); 4649 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); 4650 } else { 4651 // LUI instruction. 4652 int32_t alu32_out = static_cast<int32_t>(oe_imm16 << 16); 4653 // Sign-extend result of 32bit operation into 64bit register. 4654 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); 4655 } 4656 break; 4657 case DAUI: 4658 DCHECK(kArchVariant == kMips64r6); 4659 DCHECK(rs_reg != 0); 4660 SetResult(rt_reg, rs + (se_imm16 << 16)); 4661 break; 4662 // ------------- Memory instructions. 4663 case LB: 4664 set_register(rt_reg, ReadB(rs + se_imm16)); 4665 break; 4666 case LH: 4667 set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr())); 4668 break; 4669 case LWL: { 4670 // al_offset is offset of the effective address within an aligned word. 4671 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 4672 uint8_t byte_shift = kInt32AlignmentMask - al_offset; 4673 uint32_t mask = (1 << byte_shift * 8) - 1; 4674 addr = rs + se_imm16 - al_offset; 4675 int32_t val = ReadW(addr, instr_.instr()); 4676 val <<= byte_shift * 8; 4677 val |= rt & mask; 4678 set_register(rt_reg, static_cast<int64_t>(val)); 4679 break; 4680 } 4681 case LW: 4682 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr())); 4683 break; 4684 case LWU: 4685 set_register(rt_reg, ReadWU(rs + se_imm16, instr_.instr())); 4686 break; 4687 case LD: 4688 set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr())); 4689 break; 4690 case LBU: 4691 set_register(rt_reg, ReadBU(rs + se_imm16)); 4692 break; 4693 case LHU: 4694 set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr())); 4695 break; 4696 case LWR: { 4697 // al_offset is offset of the effective address within an aligned word. 4698 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 4699 uint8_t byte_shift = kInt32AlignmentMask - al_offset; 4700 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0; 4701 addr = rs + se_imm16 - al_offset; 4702 alu_out = ReadW(addr, instr_.instr()); 4703 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8; 4704 alu_out |= rt & mask; 4705 set_register(rt_reg, alu_out); 4706 break; 4707 } 4708 case LDL: { 4709 // al_offset is offset of the effective address within an aligned word. 4710 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; 4711 uint8_t byte_shift = kInt64AlignmentMask - al_offset; 4712 uint64_t mask = (1UL << byte_shift * 8) - 1; 4713 addr = rs + se_imm16 - al_offset; 4714 alu_out = Read2W(addr, instr_.instr()); 4715 alu_out <<= byte_shift * 8; 4716 alu_out |= rt & mask; 4717 set_register(rt_reg, alu_out); 4718 break; 4719 } 4720 case LDR: { 4721 // al_offset is offset of the effective address within an aligned word. 4722 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; 4723 uint8_t byte_shift = kInt64AlignmentMask - al_offset; 4724 uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL; 4725 addr = rs + se_imm16 - al_offset; 4726 alu_out = Read2W(addr, instr_.instr()); 4727 alu_out = alu_out >> al_offset * 8; 4728 alu_out |= rt & mask; 4729 set_register(rt_reg, alu_out); 4730 break; 4731 } 4732 case SB: 4733 WriteB(rs + se_imm16, static_cast<int8_t>(rt)); 4734 break; 4735 case SH: 4736 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr()); 4737 break; 4738 case SWL: { 4739 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 4740 uint8_t byte_shift = kInt32AlignmentMask - al_offset; 4741 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0; 4742 addr = rs + se_imm16 - al_offset; 4743 uint64_t mem_value = ReadW(addr, instr_.instr()) & mask; 4744 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8; 4745 WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr()); 4746 break; 4747 } 4748 case SW: 4749 WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr_.instr()); 4750 break; 4751 case SD: 4752 Write2W(rs + se_imm16, rt, instr_.instr()); 4753 break; 4754 case SWR: { 4755 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask; 4756 uint32_t mask = (1 << al_offset * 8) - 1; 4757 addr = rs + se_imm16 - al_offset; 4758 uint64_t mem_value = ReadW(addr, instr_.instr()); 4759 mem_value = (rt << al_offset * 8) | (mem_value & mask); 4760 WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr()); 4761 break; 4762 } 4763 case SDL: { 4764 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; 4765 uint8_t byte_shift = kInt64AlignmentMask - al_offset; 4766 uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0; 4767 addr = rs + se_imm16 - al_offset; 4768 uint64_t mem_value = Read2W(addr, instr_.instr()) & mask; 4769 mem_value |= rt >> byte_shift * 8; 4770 Write2W(addr, mem_value, instr_.instr()); 4771 break; 4772 } 4773 case SDR: { 4774 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; 4775 uint64_t mask = (1UL << al_offset * 8) - 1; 4776 addr = rs + se_imm16 - al_offset; 4777 uint64_t mem_value = Read2W(addr, instr_.instr()); 4778 mem_value = (rt << al_offset * 8) | (mem_value & mask); 4779 Write2W(addr, mem_value, instr_.instr()); 4780 break; 4781 } 4782 case LWC1: 4783 set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits. 4784 set_fpu_register_word(ft_reg, 4785 ReadW(rs + se_imm16, instr_.instr(), FLOAT_DOUBLE)); 4786 break; 4787 case LDC1: 4788 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); 4789 TraceMemRd(addr, get_fpu_register(ft_reg), DOUBLE); 4790 break; 4791 case SWC1: { 4792 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); 4793 WriteW(rs + se_imm16, alu_out_32, instr_.instr()); 4794 break; 4795 } 4796 case SDC1: 4797 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); 4798 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg), DWORD); 4799 break; 4800 // ------------- PC-Relative instructions. 4801 case PCREL: { 4802 // rt field: checking 5-bits. 4803 int32_t imm21 = instr_.Imm21Value(); 4804 int64_t current_pc = get_pc(); 4805 uint8_t rt = (imm21 >> kImm16Bits); 4806 switch (rt) { 4807 case ALUIPC: 4808 addr = current_pc + (se_imm16 << 16); 4809 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; 4810 break; 4811 case AUIPC: 4812 alu_out = current_pc + (se_imm16 << 16); 4813 break; 4814 default: { 4815 int32_t imm19 = instr_.Imm19Value(); 4816 // rt field: checking the most significant 3-bits. 4817 rt = (imm21 >> kImm18Bits); 4818 switch (rt) { 4819 case LDPC: 4820 addr = 4821 (current_pc & static_cast<int64_t>(~0x7)) + (se_imm18 << 3); 4822 alu_out = Read2W(addr, instr_.instr()); 4823 break; 4824 default: { 4825 // rt field: checking the most significant 2-bits. 4826 rt = (imm21 >> kImm19Bits); 4827 switch (rt) { 4828 case LWUPC: { 4829 // Set sign. 4830 imm19 <<= (kOpcodeBits + kRsBits + 2); 4831 imm19 >>= (kOpcodeBits + kRsBits + 2); 4832 addr = current_pc + (imm19 << 2); 4833 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 4834 alu_out = *ptr; 4835 break; 4836 } 4837 case LWPC: { 4838 // Set sign. 4839 imm19 <<= (kOpcodeBits + kRsBits + 2); 4840 imm19 >>= (kOpcodeBits + kRsBits + 2); 4841 addr = current_pc + (imm19 << 2); 4842 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 4843 alu_out = *ptr; 4844 break; 4845 } 4846 case ADDIUPC: { 4847 int64_t se_imm19 = 4848 imm19 | ((imm19 & 0x40000) ? 0xfffffffffff80000 : 0); 4849 alu_out = current_pc + (se_imm19 << 2); 4850 break; 4851 } 4852 default: 4853 UNREACHABLE(); 4854 break; 4855 } 4856 break; 4857 } 4858 } 4859 break; 4860 } 4861 } 4862 SetResult(rs_reg, alu_out); 4863 break; 4864 } 4865 default: 4866 UNREACHABLE(); 4867 } 4868 4869 if (execute_branch_delay_instruction) { 4870 // Execute branch delay slot 4871 // We don't check for end_sim_pc. First it should not be met as the current 4872 // pc is valid. Secondly a jump should always execute its branch delay slot. 4873 Instruction* branch_delay_instr = 4874 reinterpret_cast<Instruction*>(get_pc() + Instruction::kInstrSize); 4875 BranchDelayInstructionDecode(branch_delay_instr); 4876 } 4877 4878 // If needed update pc after the branch delay execution. 4879 if (next_pc != bad_ra) { 4880 set_pc(next_pc); 4881 } 4882} 4883 4884 4885// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). 4886void Simulator::DecodeTypeJump() { 4887 SimInstruction simInstr = instr_; 4888 // Get current pc. 4889 int64_t current_pc = get_pc(); 4890 // Get unchanged bits of pc. 4891 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; 4892 // Next pc. 4893 int64_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2); 4894 4895 // Execute branch delay slot. 4896 // We don't check for end_sim_pc. First it should not be met as the current pc 4897 // is valid. Secondly a jump should always execute its branch delay slot. 4898 Instruction* branch_delay_instr = 4899 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 4900 BranchDelayInstructionDecode(branch_delay_instr); 4901 4902 // Update pc and ra if necessary. 4903 // Do this after the branch delay execution. 4904 if (simInstr.IsLinkingInstruction()) { 4905 set_register(31, current_pc + 2 * Instruction::kInstrSize); 4906 } 4907 set_pc(next_pc); 4908 pc_modified_ = true; 4909} 4910 4911 4912// Executes the current instruction. 4913void Simulator::InstructionDecode(Instruction* instr) { 4914 if (v8::internal::FLAG_check_icache) { 4915 CheckICache(isolate_->simulator_i_cache(), instr); 4916 } 4917 pc_modified_ = false; 4918 4919 v8::internal::EmbeddedVector<char, 256> buffer; 4920 4921 if (::v8::internal::FLAG_trace_sim) { 4922 SNPrintF(trace_buf_, " "); 4923 disasm::NameConverter converter; 4924 disasm::Disassembler dasm(converter); 4925 // Use a reasonably large buffer. 4926 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); 4927 } 4928 4929 instr_ = instr; 4930 switch (instr_.InstructionType()) { 4931 case Instruction::kRegisterType: 4932 DecodeTypeRegister(); 4933 break; 4934 case Instruction::kImmediateType: 4935 DecodeTypeImmediate(); 4936 break; 4937 case Instruction::kJumpType: 4938 DecodeTypeJump(); 4939 break; 4940 default: 4941 UNSUPPORTED(); 4942 } 4943 4944 if (::v8::internal::FLAG_trace_sim) { 4945 PrintF(" 0x%08" PRIxPTR " %-44s %s\n", 4946 reinterpret_cast<intptr_t>(instr), buffer.start(), 4947 trace_buf_.start()); 4948 } 4949 4950 if (!pc_modified_) { 4951 set_register(pc, reinterpret_cast<int64_t>(instr) + 4952 Instruction::kInstrSize); 4953 } 4954} 4955 4956 4957 4958void Simulator::Execute() { 4959 // Get the PC to simulate. Cannot use the accessor here as we need the 4960 // raw PC value and not the one used as input to arithmetic instructions. 4961 int64_t program_counter = get_pc(); 4962 if (::v8::internal::FLAG_stop_sim_at == 0) { 4963 // Fast version of the dispatch loop without checking whether the simulator 4964 // should be stopping at a particular executed instruction. 4965 while (program_counter != end_sim_pc) { 4966 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 4967 icount_++; 4968 InstructionDecode(instr); 4969 program_counter = get_pc(); 4970 } 4971 } else { 4972 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 4973 // we reach the particular instuction count. 4974 while (program_counter != end_sim_pc) { 4975 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 4976 icount_++; 4977 if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) { 4978 MipsDebugger dbg(this); 4979 dbg.Debug(); 4980 } else { 4981 InstructionDecode(instr); 4982 } 4983 program_counter = get_pc(); 4984 } 4985 } 4986} 4987 4988 4989void Simulator::CallInternal(byte* entry) { 4990 // Adjust JS-based stack limit to C-based stack limit. 4991 isolate_->stack_guard()->AdjustStackLimitForSimulator(); 4992 4993 // Prepare to execute the code at entry. 4994 set_register(pc, reinterpret_cast<int64_t>(entry)); 4995 // Put down marker for end of simulation. The simulator will stop simulation 4996 // when the PC reaches this value. By saving the "end simulation" value into 4997 // the LR the simulation stops when returning to this call point. 4998 set_register(ra, end_sim_pc); 4999 5000 // Remember the values of callee-saved registers. 5001 // The code below assumes that r9 is not used as sb (static base) in 5002 // simulator code and therefore is regarded as a callee-saved register. 5003 int64_t s0_val = get_register(s0); 5004 int64_t s1_val = get_register(s1); 5005 int64_t s2_val = get_register(s2); 5006 int64_t s3_val = get_register(s3); 5007 int64_t s4_val = get_register(s4); 5008 int64_t s5_val = get_register(s5); 5009 int64_t s6_val = get_register(s6); 5010 int64_t s7_val = get_register(s7); 5011 int64_t gp_val = get_register(gp); 5012 int64_t sp_val = get_register(sp); 5013 int64_t fp_val = get_register(fp); 5014 5015 // Set up the callee-saved registers with a known value. To be able to check 5016 // that they are preserved properly across JS execution. 5017 int64_t callee_saved_value = icount_; 5018 set_register(s0, callee_saved_value); 5019 set_register(s1, callee_saved_value); 5020 set_register(s2, callee_saved_value); 5021 set_register(s3, callee_saved_value); 5022 set_register(s4, callee_saved_value); 5023 set_register(s5, callee_saved_value); 5024 set_register(s6, callee_saved_value); 5025 set_register(s7, callee_saved_value); 5026 set_register(gp, callee_saved_value); 5027 set_register(fp, callee_saved_value); 5028 5029 // Start the simulation. 5030 Execute(); 5031 5032 // Check that the callee-saved registers have been preserved. 5033 CHECK_EQ(callee_saved_value, get_register(s0)); 5034 CHECK_EQ(callee_saved_value, get_register(s1)); 5035 CHECK_EQ(callee_saved_value, get_register(s2)); 5036 CHECK_EQ(callee_saved_value, get_register(s3)); 5037 CHECK_EQ(callee_saved_value, get_register(s4)); 5038 CHECK_EQ(callee_saved_value, get_register(s5)); 5039 CHECK_EQ(callee_saved_value, get_register(s6)); 5040 CHECK_EQ(callee_saved_value, get_register(s7)); 5041 CHECK_EQ(callee_saved_value, get_register(gp)); 5042 CHECK_EQ(callee_saved_value, get_register(fp)); 5043 5044 // Restore callee-saved registers with the original value. 5045 set_register(s0, s0_val); 5046 set_register(s1, s1_val); 5047 set_register(s2, s2_val); 5048 set_register(s3, s3_val); 5049 set_register(s4, s4_val); 5050 set_register(s5, s5_val); 5051 set_register(s6, s6_val); 5052 set_register(s7, s7_val); 5053 set_register(gp, gp_val); 5054 set_register(sp, sp_val); 5055 set_register(fp, fp_val); 5056} 5057 5058 5059int64_t Simulator::Call(byte* entry, int argument_count, ...) { 5060 const int kRegisterPassedArguments = 8; 5061 va_list parameters; 5062 va_start(parameters, argument_count); 5063 // Set up arguments. 5064 5065 // First four arguments passed in registers in both ABI's. 5066 DCHECK(argument_count >= 4); 5067 set_register(a0, va_arg(parameters, int64_t)); 5068 set_register(a1, va_arg(parameters, int64_t)); 5069 set_register(a2, va_arg(parameters, int64_t)); 5070 set_register(a3, va_arg(parameters, int64_t)); 5071 5072 // Up to eight arguments passed in registers in N64 ABI. 5073 // TODO(plind): N64 ABI calls these regs a4 - a7. Clarify this. 5074 if (argument_count >= 5) set_register(a4, va_arg(parameters, int64_t)); 5075 if (argument_count >= 6) set_register(a5, va_arg(parameters, int64_t)); 5076 if (argument_count >= 7) set_register(a6, va_arg(parameters, int64_t)); 5077 if (argument_count >= 8) set_register(a7, va_arg(parameters, int64_t)); 5078 5079 // Remaining arguments passed on stack. 5080 int64_t original_stack = get_register(sp); 5081 // Compute position of stack on entry to generated code. 5082 int stack_args_count = (argument_count > kRegisterPassedArguments) ? 5083 (argument_count - kRegisterPassedArguments) : 0; 5084 int stack_args_size = stack_args_count * sizeof(int64_t) + kCArgsSlotsSize; 5085 int64_t entry_stack = original_stack - stack_args_size; 5086 5087 if (base::OS::ActivationFrameAlignment() != 0) { 5088 entry_stack &= -base::OS::ActivationFrameAlignment(); 5089 } 5090 // Store remaining arguments on stack, from low to high memory. 5091 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 5092 for (int i = kRegisterPassedArguments; i < argument_count; i++) { 5093 int stack_index = i - kRegisterPassedArguments + kCArgSlotCount; 5094 stack_argument[stack_index] = va_arg(parameters, int64_t); 5095 } 5096 va_end(parameters); 5097 set_register(sp, entry_stack); 5098 5099 CallInternal(entry); 5100 5101 // Pop stack passed arguments. 5102 CHECK_EQ(entry_stack, get_register(sp)); 5103 set_register(sp, original_stack); 5104 5105 int64_t result = get_register(v0); 5106 return result; 5107} 5108 5109 5110double Simulator::CallFP(byte* entry, double d0, double d1) { 5111 if (!IsMipsSoftFloatABI) { 5112 const FPURegister fparg2 = f13; 5113 set_fpu_register_double(f12, d0); 5114 set_fpu_register_double(fparg2, d1); 5115 } else { 5116 int buffer[2]; 5117 DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0)); 5118 memcpy(buffer, &d0, sizeof(d0)); 5119 set_dw_register(a0, buffer); 5120 memcpy(buffer, &d1, sizeof(d1)); 5121 set_dw_register(a2, buffer); 5122 } 5123 CallInternal(entry); 5124 if (!IsMipsSoftFloatABI) { 5125 return get_fpu_register_double(f0); 5126 } else { 5127 return get_double_from_register_pair(v0); 5128 } 5129} 5130 5131 5132uintptr_t Simulator::PushAddress(uintptr_t address) { 5133 int64_t new_sp = get_register(sp) - sizeof(uintptr_t); 5134 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 5135 *stack_slot = address; 5136 set_register(sp, new_sp); 5137 return new_sp; 5138} 5139 5140 5141uintptr_t Simulator::PopAddress() { 5142 int64_t current_sp = get_register(sp); 5143 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 5144 uintptr_t address = *stack_slot; 5145 set_register(sp, current_sp + sizeof(uintptr_t)); 5146 return address; 5147} 5148 5149 5150#undef UNSUPPORTED 5151} // namespace internal 5152} // namespace v8 5153 5154#endif // USE_SIMULATOR 5155 5156#endif // V8_TARGET_ARCH_MIPS64 5157