1 // Copyright 2014 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 <stdarg.h> 6 #include <stdlib.h> 7 #include <cmath> 8 9 #if V8_TARGET_ARCH_PPC 10 11 #include "src/assembler.h" 12 #include "src/base/bits.h" 13 #include "src/codegen.h" 14 #include "src/disasm.h" 15 #include "src/macro-assembler.h" 16 #include "src/ostreams.h" 17 #include "src/ppc/constants-ppc.h" 18 #include "src/ppc/frame-constants-ppc.h" 19 #include "src/ppc/simulator-ppc.h" 20 #include "src/runtime/runtime-utils.h" 21 22 #if defined(USE_SIMULATOR) 23 24 // Only build the simulator if not compiling for real PPC hardware. 25 namespace v8 { 26 namespace internal { 27 28 const auto GetRegConfig = RegisterConfiguration::Default; 29 30 // static 31 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ = 32 LAZY_INSTANCE_INITIALIZER; 33 34 // This macro provides a platform independent use of sscanf. The reason for 35 // SScanF not being implemented in a platform independent way through 36 // ::v8::internal::OS in the same way as SNPrintF is that the 37 // Windows C Run-Time Library does not provide vsscanf. 38 #define SScanF sscanf // NOLINT 39 40 // The PPCDebugger class is used by the simulator while debugging simulated 41 // PowerPC code. 42 class PPCDebugger { 43 public: 44 explicit PPCDebugger(Simulator* sim) : sim_(sim) {} 45 46 void Stop(Instruction* instr); 47 void Debug(); 48 49 private: 50 static const Instr kBreakpointInstr = (TWI | 0x1F * B21); 51 static const Instr kNopInstr = (ORI); // ori, 0,0,0 52 53 Simulator* sim_; 54 55 intptr_t GetRegisterValue(int regnum); 56 double GetRegisterPairDoubleValue(int regnum); 57 double GetFPDoubleRegisterValue(int regnum); 58 bool GetValue(const char* desc, intptr_t* value); 59 bool GetFPDoubleValue(const char* desc, double* value); 60 61 // Set or delete a breakpoint. Returns true if successful. 62 bool SetBreakpoint(Instruction* break_pc); 63 bool DeleteBreakpoint(Instruction* break_pc); 64 65 // Undo and redo all breakpoints. This is needed to bracket disassembly and 66 // execution to skip past breakpoints when run from the debugger. 67 void UndoBreakpoints(); 68 void RedoBreakpoints(); 69 }; 70 71 void PPCDebugger::Stop(Instruction* instr) { 72 // Get the stop code. 73 // use of kStopCodeMask not right on PowerPC 74 uint32_t code = instr->SvcValue() & kStopCodeMask; 75 // Retrieve the encoded address, which comes just after this stop. 76 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + kInstrSize); 77 // Update this stop description. 78 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) { 79 sim_->watched_stops_[code].desc = msg; 80 } 81 // Print the stop message and code if it is not the default code. 82 if (code != kMaxStopCode) { 83 PrintF("Simulator hit stop %u: %s\n", code, msg); 84 } else { 85 PrintF("Simulator hit %s\n", msg); 86 } 87 sim_->set_pc(sim_->get_pc() + kInstrSize + kPointerSize); 88 Debug(); 89 } 90 91 intptr_t PPCDebugger::GetRegisterValue(int regnum) { 92 return sim_->get_register(regnum); 93 } 94 95 96 double PPCDebugger::GetRegisterPairDoubleValue(int regnum) { 97 return sim_->get_double_from_register_pair(regnum); 98 } 99 100 101 double PPCDebugger::GetFPDoubleRegisterValue(int regnum) { 102 return sim_->get_double_from_d_register(regnum); 103 } 104 105 106 bool PPCDebugger::GetValue(const char* desc, intptr_t* value) { 107 int regnum = Registers::Number(desc); 108 if (regnum != kNoRegister) { 109 *value = GetRegisterValue(regnum); 110 return true; 111 } else { 112 if (strncmp(desc, "0x", 2) == 0) { 113 return SScanF(desc + 2, "%" V8PRIxPTR, 114 reinterpret_cast<uintptr_t*>(value)) == 1; 115 } else { 116 return SScanF(desc, "%" V8PRIuPTR, reinterpret_cast<uintptr_t*>(value)) == 117 1; 118 } 119 } 120 return false; 121 } 122 123 124 bool PPCDebugger::GetFPDoubleValue(const char* desc, double* value) { 125 int regnum = DoubleRegisters::Number(desc); 126 if (regnum != kNoRegister) { 127 *value = sim_->get_double_from_d_register(regnum); 128 return true; 129 } 130 return false; 131 } 132 133 134 bool PPCDebugger::SetBreakpoint(Instruction* break_pc) { 135 // Check if a breakpoint can be set. If not return without any side-effects. 136 if (sim_->break_pc_ != nullptr) { 137 return false; 138 } 139 140 // Set the breakpoint. 141 sim_->break_pc_ = break_pc; 142 sim_->break_instr_ = break_pc->InstructionBits(); 143 // Not setting the breakpoint instruction in the code itself. It will be set 144 // when the debugger shell continues. 145 return true; 146 } 147 148 149 bool PPCDebugger::DeleteBreakpoint(Instruction* break_pc) { 150 if (sim_->break_pc_ != nullptr) { 151 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 152 } 153 154 sim_->break_pc_ = nullptr; 155 sim_->break_instr_ = 0; 156 return true; 157 } 158 159 160 void PPCDebugger::UndoBreakpoints() { 161 if (sim_->break_pc_ != nullptr) { 162 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 163 } 164 } 165 166 167 void PPCDebugger::RedoBreakpoints() { 168 if (sim_->break_pc_ != nullptr) { 169 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 170 } 171 } 172 173 174 void PPCDebugger::Debug() { 175 intptr_t last_pc = -1; 176 bool done = false; 177 178 #define COMMAND_SIZE 63 179 #define ARG_SIZE 255 180 181 #define STR(a) #a 182 #define XSTR(a) STR(a) 183 184 char cmd[COMMAND_SIZE + 1]; 185 char arg1[ARG_SIZE + 1]; 186 char arg2[ARG_SIZE + 1]; 187 char* argv[3] = {cmd, arg1, arg2}; 188 189 // make sure to have a proper terminating character if reaching the limit 190 cmd[COMMAND_SIZE] = 0; 191 arg1[ARG_SIZE] = 0; 192 arg2[ARG_SIZE] = 0; 193 194 // Undo all set breakpoints while running in the debugger shell. This will 195 // make them invisible to all commands. 196 UndoBreakpoints(); 197 // Disable tracing while simulating 198 bool trace = ::v8::internal::FLAG_trace_sim; 199 ::v8::internal::FLAG_trace_sim = false; 200 201 while (!done && !sim_->has_bad_pc()) { 202 if (last_pc != sim_->get_pc()) { 203 disasm::NameConverter converter; 204 disasm::Disassembler dasm(converter); 205 // use a reasonably large buffer 206 v8::internal::EmbeddedVector<char, 256> buffer; 207 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc())); 208 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(), buffer.start()); 209 last_pc = sim_->get_pc(); 210 } 211 char* line = ReadLine("sim> "); 212 if (line == nullptr) { 213 break; 214 } else { 215 char* last_input = sim_->last_debugger_input(); 216 if (strcmp(line, "\n") == 0 && last_input != nullptr) { 217 line = last_input; 218 } else { 219 // Ownership is transferred to sim_; 220 sim_->set_last_debugger_input(line); 221 } 222 // Use sscanf to parse the individual parts of the command line. At the 223 // moment no command expects more than two parameters. 224 int argc = SScanF(line, 225 "%" XSTR(COMMAND_SIZE) "s " 226 "%" XSTR(ARG_SIZE) "s " 227 "%" XSTR(ARG_SIZE) "s", 228 cmd, arg1, arg2); 229 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 230 intptr_t value; 231 232 // If at a breakpoint, proceed past it. 233 if ((reinterpret_cast<Instruction*>(sim_->get_pc())) 234 ->InstructionBits() == 0x7D821008) { 235 sim_->set_pc(sim_->get_pc() + kInstrSize); 236 } else { 237 sim_->ExecuteInstruction( 238 reinterpret_cast<Instruction*>(sim_->get_pc())); 239 } 240 241 if (argc == 2 && last_pc != sim_->get_pc() && GetValue(arg1, &value)) { 242 for (int i = 1; i < value; i++) { 243 disasm::NameConverter converter; 244 disasm::Disassembler dasm(converter); 245 // use a reasonably large buffer 246 v8::internal::EmbeddedVector<char, 256> buffer; 247 dasm.InstructionDecode(buffer, 248 reinterpret_cast<byte*>(sim_->get_pc())); 249 PrintF(" 0x%08" V8PRIxPTR " %s\n", sim_->get_pc(), 250 buffer.start()); 251 sim_->ExecuteInstruction( 252 reinterpret_cast<Instruction*>(sim_->get_pc())); 253 } 254 } 255 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 256 // If at a breakpoint, proceed past it. 257 if ((reinterpret_cast<Instruction*>(sim_->get_pc())) 258 ->InstructionBits() == 0x7D821008) { 259 sim_->set_pc(sim_->get_pc() + kInstrSize); 260 } else { 261 // Execute the one instruction we broke at with breakpoints disabled. 262 sim_->ExecuteInstruction( 263 reinterpret_cast<Instruction*>(sim_->get_pc())); 264 } 265 // Leave the debugger shell. 266 done = true; 267 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 268 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) { 269 intptr_t value; 270 double dvalue; 271 if (strcmp(arg1, "all") == 0) { 272 for (int i = 0; i < kNumRegisters; i++) { 273 value = GetRegisterValue(i); 274 PrintF(" %3s: %08" V8PRIxPTR, 275 GetRegConfig()->GetGeneralRegisterName(i), value); 276 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 && 277 (i % 2) == 0) { 278 dvalue = GetRegisterPairDoubleValue(i); 279 PrintF(" (%f)\n", dvalue); 280 } else if (i != 0 && !((i + 1) & 3)) { 281 PrintF("\n"); 282 } 283 } 284 PrintF(" pc: %08" V8PRIxPTR " lr: %08" V8PRIxPTR 285 " " 286 "ctr: %08" V8PRIxPTR " xer: %08x cr: %08x\n", 287 sim_->special_reg_pc_, sim_->special_reg_lr_, 288 sim_->special_reg_ctr_, sim_->special_reg_xer_, 289 sim_->condition_reg_); 290 } else if (strcmp(arg1, "alld") == 0) { 291 for (int i = 0; i < kNumRegisters; i++) { 292 value = GetRegisterValue(i); 293 PrintF(" %3s: %08" V8PRIxPTR " %11" V8PRIdPTR, 294 GetRegConfig()->GetGeneralRegisterName(i), value, value); 295 if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 && 296 (i % 2) == 0) { 297 dvalue = GetRegisterPairDoubleValue(i); 298 PrintF(" (%f)\n", dvalue); 299 } else if (!((i + 1) % 2)) { 300 PrintF("\n"); 301 } 302 } 303 PrintF(" pc: %08" V8PRIxPTR " lr: %08" V8PRIxPTR 304 " " 305 "ctr: %08" V8PRIxPTR " xer: %08x cr: %08x\n", 306 sim_->special_reg_pc_, sim_->special_reg_lr_, 307 sim_->special_reg_ctr_, sim_->special_reg_xer_, 308 sim_->condition_reg_); 309 } else if (strcmp(arg1, "allf") == 0) { 310 for (int i = 0; i < DoubleRegister::kNumRegisters; i++) { 311 dvalue = GetFPDoubleRegisterValue(i); 312 uint64_t as_words = bit_cast<uint64_t>(dvalue); 313 PrintF("%3s: %f 0x%08x %08x\n", 314 GetRegConfig()->GetDoubleRegisterName(i), dvalue, 315 static_cast<uint32_t>(as_words >> 32), 316 static_cast<uint32_t>(as_words & 0xFFFFFFFF)); 317 } 318 } else if (arg1[0] == 'r' && 319 (arg1[1] >= '0' && arg1[1] <= '9' && 320 (arg1[2] == '\0' || (arg1[2] >= '0' && arg1[2] <= '9' && 321 arg1[3] == '\0')))) { 322 int regnum = strtoul(&arg1[1], 0, 10); 323 if (regnum != kNoRegister) { 324 value = GetRegisterValue(regnum); 325 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value, 326 value); 327 } else { 328 PrintF("%s unrecognized\n", arg1); 329 } 330 } else { 331 if (GetValue(arg1, &value)) { 332 PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value, 333 value); 334 } else if (GetFPDoubleValue(arg1, &dvalue)) { 335 uint64_t as_words = bit_cast<uint64_t>(dvalue); 336 PrintF("%s: %f 0x%08x %08x\n", arg1, dvalue, 337 static_cast<uint32_t>(as_words >> 32), 338 static_cast<uint32_t>(as_words & 0xFFFFFFFF)); 339 } else { 340 PrintF("%s unrecognized\n", arg1); 341 } 342 } 343 } else { 344 PrintF("print <register>\n"); 345 } 346 } else if ((strcmp(cmd, "po") == 0) || 347 (strcmp(cmd, "printobject") == 0)) { 348 if (argc == 2) { 349 intptr_t value; 350 StdoutStream os; 351 if (GetValue(arg1, &value)) { 352 Object* obj = reinterpret_cast<Object*>(value); 353 os << arg1 << ": \n"; 354 #ifdef DEBUG 355 obj->Print(os); 356 os << "\n"; 357 #else 358 os << Brief(obj) << "\n"; 359 #endif 360 } else { 361 os << arg1 << " unrecognized\n"; 362 } 363 } else { 364 PrintF("printobject <value>\n"); 365 } 366 } else if (strcmp(cmd, "setpc") == 0) { 367 intptr_t value; 368 369 if (!GetValue(arg1, &value)) { 370 PrintF("%s unrecognized\n", arg1); 371 continue; 372 } 373 sim_->set_pc(value); 374 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 375 intptr_t* cur = nullptr; 376 intptr_t* end = nullptr; 377 int next_arg = 1; 378 379 if (strcmp(cmd, "stack") == 0) { 380 cur = reinterpret_cast<intptr_t*>(sim_->get_register(Simulator::sp)); 381 } else { // "mem" 382 intptr_t value; 383 if (!GetValue(arg1, &value)) { 384 PrintF("%s unrecognized\n", arg1); 385 continue; 386 } 387 cur = reinterpret_cast<intptr_t*>(value); 388 next_arg++; 389 } 390 391 intptr_t words; // likely inaccurate variable name for 64bit 392 if (argc == next_arg) { 393 words = 10; 394 } else { 395 if (!GetValue(argv[next_arg], &words)) { 396 words = 10; 397 } 398 } 399 end = cur + words; 400 401 while (cur < end) { 402 PrintF(" 0x%08" V8PRIxPTR ": 0x%08" V8PRIxPTR " %10" V8PRIdPTR, 403 reinterpret_cast<intptr_t>(cur), *cur, *cur); 404 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 405 intptr_t value = *cur; 406 Heap* current_heap = sim_->isolate_->heap(); 407 if (((value & 1) == 0) || 408 current_heap->ContainsSlow(obj->address())) { 409 PrintF(" ("); 410 if ((value & 1) == 0) { 411 PrintF("smi %d", PlatformSmiTagging::SmiToInt(obj)); 412 } else { 413 obj->ShortPrint(); 414 } 415 PrintF(")"); 416 } 417 PrintF("\n"); 418 cur++; 419 } 420 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) { 421 disasm::NameConverter converter; 422 disasm::Disassembler dasm(converter); 423 // use a reasonably large buffer 424 v8::internal::EmbeddedVector<char, 256> buffer; 425 426 byte* prev = nullptr; 427 byte* cur = nullptr; 428 byte* end = nullptr; 429 430 if (argc == 1) { 431 cur = reinterpret_cast<byte*>(sim_->get_pc()); 432 end = cur + (10 * kInstrSize); 433 } else if (argc == 2) { 434 int regnum = Registers::Number(arg1); 435 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) { 436 // The argument is an address or a register name. 437 intptr_t value; 438 if (GetValue(arg1, &value)) { 439 cur = reinterpret_cast<byte*>(value); 440 // Disassemble 10 instructions at <arg1>. 441 end = cur + (10 * kInstrSize); 442 } 443 } else { 444 // The argument is the number of instructions. 445 intptr_t value; 446 if (GetValue(arg1, &value)) { 447 cur = reinterpret_cast<byte*>(sim_->get_pc()); 448 // Disassemble <arg1> instructions. 449 end = cur + (value * kInstrSize); 450 } 451 } 452 } else { 453 intptr_t value1; 454 intptr_t value2; 455 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 456 cur = reinterpret_cast<byte*>(value1); 457 end = cur + (value2 * kInstrSize); 458 } 459 } 460 461 while (cur < end) { 462 prev = cur; 463 cur += dasm.InstructionDecode(buffer, cur); 464 PrintF(" 0x%08" V8PRIxPTR " %s\n", reinterpret_cast<intptr_t>(prev), 465 buffer.start()); 466 } 467 } else if (strcmp(cmd, "gdb") == 0) { 468 PrintF("relinquishing control to gdb\n"); 469 v8::base::OS::DebugBreak(); 470 PrintF("regaining control from gdb\n"); 471 } else if (strcmp(cmd, "break") == 0) { 472 if (argc == 2) { 473 intptr_t value; 474 if (GetValue(arg1, &value)) { 475 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 476 PrintF("setting breakpoint failed\n"); 477 } 478 } else { 479 PrintF("%s unrecognized\n", arg1); 480 } 481 } else { 482 PrintF("break <address>\n"); 483 } 484 } else if (strcmp(cmd, "del") == 0) { 485 if (!DeleteBreakpoint(nullptr)) { 486 PrintF("deleting breakpoint failed\n"); 487 } 488 } else if (strcmp(cmd, "cr") == 0) { 489 PrintF("Condition reg: %08x\n", sim_->condition_reg_); 490 } else if (strcmp(cmd, "lr") == 0) { 491 PrintF("Link reg: %08" V8PRIxPTR "\n", sim_->special_reg_lr_); 492 } else if (strcmp(cmd, "ctr") == 0) { 493 PrintF("Ctr reg: %08" V8PRIxPTR "\n", sim_->special_reg_ctr_); 494 } else if (strcmp(cmd, "xer") == 0) { 495 PrintF("XER: %08x\n", sim_->special_reg_xer_); 496 } else if (strcmp(cmd, "fpscr") == 0) { 497 PrintF("FPSCR: %08x\n", sim_->fp_condition_reg_); 498 } else if (strcmp(cmd, "stop") == 0) { 499 intptr_t value; 500 intptr_t stop_pc = sim_->get_pc() - (kInstrSize + kPointerSize); 501 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); 502 Instruction* msg_address = 503 reinterpret_cast<Instruction*>(stop_pc + kInstrSize); 504 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { 505 // Remove the current stop. 506 if (sim_->isStopInstruction(stop_instr)) { 507 stop_instr->SetInstructionBits(kNopInstr); 508 msg_address->SetInstructionBits(kNopInstr); 509 } else { 510 PrintF("Not at debugger stop.\n"); 511 } 512 } else if (argc == 3) { 513 // Print information about all/the specified breakpoint(s). 514 if (strcmp(arg1, "info") == 0) { 515 if (strcmp(arg2, "all") == 0) { 516 PrintF("Stop information:\n"); 517 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 518 sim_->PrintStopInfo(i); 519 } 520 } else if (GetValue(arg2, &value)) { 521 sim_->PrintStopInfo(value); 522 } else { 523 PrintF("Unrecognized argument.\n"); 524 } 525 } else if (strcmp(arg1, "enable") == 0) { 526 // Enable all/the specified breakpoint(s). 527 if (strcmp(arg2, "all") == 0) { 528 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 529 sim_->EnableStop(i); 530 } 531 } else if (GetValue(arg2, &value)) { 532 sim_->EnableStop(value); 533 } else { 534 PrintF("Unrecognized argument.\n"); 535 } 536 } else if (strcmp(arg1, "disable") == 0) { 537 // Disable all/the specified breakpoint(s). 538 if (strcmp(arg2, "all") == 0) { 539 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) { 540 sim_->DisableStop(i); 541 } 542 } else if (GetValue(arg2, &value)) { 543 sim_->DisableStop(value); 544 } else { 545 PrintF("Unrecognized argument.\n"); 546 } 547 } 548 } else { 549 PrintF("Wrong usage. Use help command for more information.\n"); 550 } 551 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) { 552 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim; 553 PrintF("Trace of executed instructions is %s\n", 554 ::v8::internal::FLAG_trace_sim ? "on" : "off"); 555 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 556 PrintF("cont\n"); 557 PrintF(" continue execution (alias 'c')\n"); 558 PrintF("stepi [num instructions]\n"); 559 PrintF(" step one/num instruction(s) (alias 'si')\n"); 560 PrintF("print <register>\n"); 561 PrintF(" print register content (alias 'p')\n"); 562 PrintF(" use register name 'all' to display all integer registers\n"); 563 PrintF( 564 " use register name 'alld' to display integer registers " 565 "with decimal values\n"); 566 PrintF(" use register name 'rN' to display register number 'N'\n"); 567 PrintF(" add argument 'fp' to print register pair double values\n"); 568 PrintF( 569 " use register name 'allf' to display floating-point " 570 "registers\n"); 571 PrintF("printobject <register>\n"); 572 PrintF(" print an object from a register (alias 'po')\n"); 573 PrintF("cr\n"); 574 PrintF(" print condition register\n"); 575 PrintF("lr\n"); 576 PrintF(" print link register\n"); 577 PrintF("ctr\n"); 578 PrintF(" print ctr register\n"); 579 PrintF("xer\n"); 580 PrintF(" print XER\n"); 581 PrintF("fpscr\n"); 582 PrintF(" print FPSCR\n"); 583 PrintF("stack [<num words>]\n"); 584 PrintF(" dump stack content, default dump 10 words)\n"); 585 PrintF("mem <address> [<num words>]\n"); 586 PrintF(" dump memory content, default dump 10 words)\n"); 587 PrintF("disasm [<instructions>]\n"); 588 PrintF("disasm [<address/register>]\n"); 589 PrintF("disasm [[<address/register>] <instructions>]\n"); 590 PrintF(" disassemble code, default is 10 instructions\n"); 591 PrintF(" from pc (alias 'di')\n"); 592 PrintF("gdb\n"); 593 PrintF(" enter gdb\n"); 594 PrintF("break <address>\n"); 595 PrintF(" set a break point on the address\n"); 596 PrintF("del\n"); 597 PrintF(" delete the breakpoint\n"); 598 PrintF("trace (alias 't')\n"); 599 PrintF(" toogle the tracing of all executed statements\n"); 600 PrintF("stop feature:\n"); 601 PrintF(" Description:\n"); 602 PrintF(" Stops are debug instructions inserted by\n"); 603 PrintF(" the Assembler::stop() function.\n"); 604 PrintF(" When hitting a stop, the Simulator will\n"); 605 PrintF(" stop and give control to the PPCDebugger.\n"); 606 PrintF(" The first %d stop codes are watched:\n", 607 Simulator::kNumOfWatchedStops); 608 PrintF(" - They can be enabled / disabled: the Simulator\n"); 609 PrintF(" will / won't stop when hitting them.\n"); 610 PrintF(" - The Simulator keeps track of how many times they \n"); 611 PrintF(" are met. (See the info command.) Going over a\n"); 612 PrintF(" disabled stop still increases its counter. \n"); 613 PrintF(" Commands:\n"); 614 PrintF(" stop info all/<code> : print infos about number <code>\n"); 615 PrintF(" or all stop(s).\n"); 616 PrintF(" stop enable/disable all/<code> : enables / disables\n"); 617 PrintF(" all or number <code> stop(s)\n"); 618 PrintF(" stop unstop\n"); 619 PrintF(" ignore the stop instruction at the current location\n"); 620 PrintF(" from now on\n"); 621 } else { 622 PrintF("Unknown command: %s\n", cmd); 623 } 624 } 625 } 626 627 // Add all the breakpoints back to stop execution and enter the debugger 628 // shell when hit. 629 RedoBreakpoints(); 630 // Restore tracing 631 ::v8::internal::FLAG_trace_sim = trace; 632 633 #undef COMMAND_SIZE 634 #undef ARG_SIZE 635 636 #undef STR 637 #undef XSTR 638 } 639 640 bool Simulator::ICacheMatch(void* one, void* two) { 641 DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0); 642 DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0); 643 return one == two; 644 } 645 646 647 static uint32_t ICacheHash(void* key) { 648 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; 649 } 650 651 652 static bool AllOnOnePage(uintptr_t start, int size) { 653 intptr_t start_page = (start & ~CachePage::kPageMask); 654 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 655 return start_page == end_page; 656 } 657 658 659 void Simulator::set_last_debugger_input(char* input) { 660 DeleteArray(last_debugger_input_); 661 last_debugger_input_ = input; 662 } 663 664 void Simulator::SetRedirectInstruction(Instruction* instruction) { 665 instruction->SetInstructionBits(rtCallRedirInstr | kCallRtRedirected); 666 } 667 668 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache, 669 void* start_addr, size_t size) { 670 intptr_t start = reinterpret_cast<intptr_t>(start_addr); 671 int intra_line = (start & CachePage::kLineMask); 672 start -= intra_line; 673 size += intra_line; 674 size = ((size - 1) | CachePage::kLineMask) + 1; 675 int offset = (start & CachePage::kPageMask); 676 while (!AllOnOnePage(start, size - 1)) { 677 int bytes_to_flush = CachePage::kPageSize - offset; 678 FlushOnePage(i_cache, start, bytes_to_flush); 679 start += bytes_to_flush; 680 size -= bytes_to_flush; 681 DCHECK_EQ(0, static_cast<int>(start & CachePage::kPageMask)); 682 offset = 0; 683 } 684 if (size != 0) { 685 FlushOnePage(i_cache, start, size); 686 } 687 } 688 689 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache, 690 void* page) { 691 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page)); 692 if (entry->value == nullptr) { 693 CachePage* new_page = new CachePage(); 694 entry->value = new_page; 695 } 696 return reinterpret_cast<CachePage*>(entry->value); 697 } 698 699 700 // Flush from start up to and not including start + size. 701 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache, 702 intptr_t start, int size) { 703 DCHECK_LE(size, CachePage::kPageSize); 704 DCHECK(AllOnOnePage(start, size - 1)); 705 DCHECK_EQ(start & CachePage::kLineMask, 0); 706 DCHECK_EQ(size & CachePage::kLineMask, 0); 707 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 708 int offset = (start & CachePage::kPageMask); 709 CachePage* cache_page = GetCachePage(i_cache, page); 710 char* valid_bytemap = cache_page->ValidityByte(offset); 711 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 712 } 713 714 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache, 715 Instruction* instr) { 716 intptr_t address = reinterpret_cast<intptr_t>(instr); 717 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 718 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 719 int offset = (address & CachePage::kPageMask); 720 CachePage* cache_page = GetCachePage(i_cache, page); 721 char* cache_valid_byte = cache_page->ValidityByte(offset); 722 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 723 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 724 if (cache_hit) { 725 // Check that the data in memory matches the contents of the I-cache. 726 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr), 727 cache_page->CachedData(offset), kInstrSize)); 728 } else { 729 // Cache miss. Load memory into the cache. 730 memcpy(cached_line, line, CachePage::kLineLength); 731 *cache_valid_byte = CachePage::LINE_VALID; 732 } 733 } 734 735 736 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { 737 // Set up simulator support first. Some of this information is needed to 738 // setup the architecture state. 739 #if V8_TARGET_ARCH_PPC64 740 size_t stack_size = FLAG_sim_stack_size * KB; 741 #else 742 size_t stack_size = MB; // allocate 1MB for stack 743 #endif 744 stack_size += 2 * stack_protection_size_; 745 stack_ = reinterpret_cast<char*>(malloc(stack_size)); 746 pc_modified_ = false; 747 icount_ = 0; 748 break_pc_ = nullptr; 749 break_instr_ = 0; 750 751 // Set up architecture state. 752 // All registers are initialized to zero to start with. 753 for (int i = 0; i < kNumGPRs; i++) { 754 registers_[i] = 0; 755 } 756 condition_reg_ = 0; 757 fp_condition_reg_ = 0; 758 special_reg_pc_ = 0; 759 special_reg_lr_ = 0; 760 special_reg_ctr_ = 0; 761 762 // Initializing FP registers. 763 for (int i = 0; i < kNumFPRs; i++) { 764 fp_registers_[i] = 0.0; 765 } 766 767 // The sp is initialized to point to the bottom (high address) of the 768 // allocated stack area. To be safe in potential stack underflows we leave 769 // some buffer below. 770 registers_[sp] = 771 reinterpret_cast<intptr_t>(stack_) + stack_size - stack_protection_size_; 772 773 last_debugger_input_ = nullptr; 774 } 775 776 Simulator::~Simulator() { 777 global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_); 778 free(stack_); 779 } 780 781 782 // Get the active Simulator for the current thread. 783 Simulator* Simulator::current(Isolate* isolate) { 784 v8::internal::Isolate::PerIsolateThreadData* isolate_data = 785 isolate->FindOrAllocatePerThreadDataForThisThread(); 786 DCHECK_NOT_NULL(isolate_data); 787 788 Simulator* sim = isolate_data->simulator(); 789 if (sim == nullptr) { 790 // TODO(146): delete the simulator object when a thread/isolate goes away. 791 sim = new Simulator(isolate); 792 isolate_data->set_simulator(sim); 793 } 794 return sim; 795 } 796 797 798 // Sets the register in the architecture state. 799 void Simulator::set_register(int reg, intptr_t value) { 800 DCHECK((reg >= 0) && (reg < kNumGPRs)); 801 registers_[reg] = value; 802 } 803 804 805 // Get the register from the architecture state. 806 intptr_t Simulator::get_register(int reg) const { 807 DCHECK((reg >= 0) && (reg < kNumGPRs)); 808 // Stupid code added to avoid bug in GCC. 809 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949 810 if (reg >= kNumGPRs) return 0; 811 // End stupid code. 812 return registers_[reg]; 813 } 814 815 816 double Simulator::get_double_from_register_pair(int reg) { 817 DCHECK((reg >= 0) && (reg < kNumGPRs) && ((reg % 2) == 0)); 818 819 double dm_val = 0.0; 820 #if !V8_TARGET_ARCH_PPC64 // doesn't make sense in 64bit mode 821 // Read the bits from the unsigned integer register_[] array 822 // into the double precision floating point value and return it. 823 char buffer[sizeof(fp_registers_[0])]; 824 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); 825 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); 826 #endif 827 return (dm_val); 828 } 829 830 831 // Raw access to the PC register. 832 void Simulator::set_pc(intptr_t value) { 833 pc_modified_ = true; 834 special_reg_pc_ = value; 835 } 836 837 838 bool Simulator::has_bad_pc() const { 839 return ((special_reg_pc_ == bad_lr) || (special_reg_pc_ == end_sim_pc)); 840 } 841 842 843 // Raw access to the PC register without the special adjustment when reading. 844 intptr_t Simulator::get_pc() const { return special_reg_pc_; } 845 846 847 // Runtime FP routines take: 848 // - two double arguments 849 // - one double argument and zero or one integer arguments. 850 // All are consructed here from d1, d2 and r3. 851 void Simulator::GetFpArgs(double* x, double* y, intptr_t* z) { 852 *x = get_double_from_d_register(1); 853 *y = get_double_from_d_register(2); 854 *z = get_register(3); 855 } 856 857 858 // The return value is in d1. 859 void Simulator::SetFpResult(const double& result) { 860 set_d_register_from_double(1, result); 861 } 862 863 864 void Simulator::TrashCallerSaveRegisters() { 865 // We don't trash the registers with the return value. 866 #if 0 // A good idea to trash volatile registers, needs to be done 867 registers_[2] = 0x50BAD4U; 868 registers_[3] = 0x50BAD4U; 869 registers_[12] = 0x50BAD4U; 870 #endif 871 } 872 873 874 uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) { 875 // All supported PPC targets allow unaligned accesses, so we don't need to 876 // check the alignment here. 877 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 878 local_monitor_.NotifyLoad(addr); 879 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 880 return *ptr; 881 } 882 883 uint32_t Simulator::ReadExWU(intptr_t addr, Instruction* instr) { 884 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 885 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word); 886 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr, 887 &global_monitor_processor_); 888 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 889 return *ptr; 890 } 891 892 int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) { 893 // All supported PPC targets allow unaligned accesses, so we don't need to 894 // check the alignment here. 895 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 896 local_monitor_.NotifyLoad(addr); 897 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 898 return *ptr; 899 } 900 901 902 void Simulator::WriteW(intptr_t addr, uint32_t value, Instruction* instr) { 903 // All supported PPC targets allow unaligned accesses, so we don't need to 904 // check the alignment here. 905 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 906 local_monitor_.NotifyStore(addr); 907 global_monitor_.Pointer()->NotifyStore_Locked(addr, 908 &global_monitor_processor_); 909 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 910 *ptr = value; 911 return; 912 } 913 914 int Simulator::WriteExW(intptr_t addr, uint32_t value, Instruction* instr) { 915 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 916 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) && 917 global_monitor_.Pointer()->NotifyStoreExcl_Locked( 918 addr, &global_monitor_processor_)) { 919 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 920 *ptr = value; 921 return 0; 922 } else { 923 return 1; 924 } 925 } 926 927 void Simulator::WriteW(intptr_t addr, int32_t value, Instruction* instr) { 928 // All supported PPC targets allow unaligned accesses, so we don't need to 929 // check the alignment here. 930 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 931 local_monitor_.NotifyStore(addr); 932 global_monitor_.Pointer()->NotifyStore_Locked(addr, 933 &global_monitor_processor_); 934 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 935 *ptr = value; 936 return; 937 } 938 939 uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) { 940 // All supported PPC targets allow unaligned accesses, so we don't need to 941 // check the alignment here. 942 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 943 local_monitor_.NotifyLoad(addr); 944 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 945 return *ptr; 946 } 947 948 uint16_t Simulator::ReadExHU(intptr_t addr, Instruction* instr) { 949 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 950 local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord); 951 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr, 952 &global_monitor_processor_); 953 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 954 return *ptr; 955 } 956 957 int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) { 958 // All supported PPC targets allow unaligned accesses, so we don't need to 959 // check the alignment here. 960 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 961 local_monitor_.NotifyLoad(addr); 962 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 963 return *ptr; 964 } 965 966 967 void Simulator::WriteH(intptr_t addr, uint16_t value, Instruction* instr) { 968 // All supported PPC targets allow unaligned accesses, so we don't need to 969 // check the alignment here. 970 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 971 local_monitor_.NotifyStore(addr); 972 global_monitor_.Pointer()->NotifyStore_Locked(addr, 973 &global_monitor_processor_); 974 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 975 *ptr = value; 976 return; 977 } 978 979 980 void Simulator::WriteH(intptr_t addr, int16_t value, Instruction* instr) { 981 // All supported PPC targets allow unaligned accesses, so we don't need to 982 // check the alignment here. 983 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 984 local_monitor_.NotifyStore(addr); 985 global_monitor_.Pointer()->NotifyStore_Locked(addr, 986 &global_monitor_processor_); 987 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 988 *ptr = value; 989 return; 990 } 991 992 int Simulator::WriteExH(intptr_t addr, uint16_t value, Instruction* instr) { 993 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 994 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) && 995 global_monitor_.Pointer()->NotifyStoreExcl_Locked( 996 addr, &global_monitor_processor_)) { 997 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 998 *ptr = value; 999 return 0; 1000 } else { 1001 return 1; 1002 } 1003 } 1004 1005 uint8_t Simulator::ReadBU(intptr_t addr) { 1006 // All supported PPC targets allow unaligned accesses, so we don't need to 1007 // check the alignment here. 1008 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1009 local_monitor_.NotifyLoad(addr); 1010 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1011 return *ptr; 1012 } 1013 1014 1015 int8_t Simulator::ReadB(intptr_t addr) { 1016 // All supported PPC targets allow unaligned accesses, so we don't need to 1017 // check the alignment here. 1018 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1019 local_monitor_.NotifyLoad(addr); 1020 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1021 return *ptr; 1022 } 1023 1024 uint8_t Simulator::ReadExBU(intptr_t addr) { 1025 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1026 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte); 1027 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr, 1028 &global_monitor_processor_); 1029 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1030 return *ptr; 1031 } 1032 1033 void Simulator::WriteB(intptr_t addr, uint8_t value) { 1034 // All supported PPC targets allow unaligned accesses, so we don't need to 1035 // check the alignment here. 1036 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1037 local_monitor_.NotifyStore(addr); 1038 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1039 &global_monitor_processor_); 1040 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1041 *ptr = value; 1042 } 1043 1044 1045 void Simulator::WriteB(intptr_t addr, int8_t value) { 1046 // All supported PPC targets allow unaligned accesses, so we don't need to 1047 // check the alignment here. 1048 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1049 local_monitor_.NotifyStore(addr); 1050 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1051 &global_monitor_processor_); 1052 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1053 *ptr = value; 1054 } 1055 1056 int Simulator::WriteExB(intptr_t addr, uint8_t value) { 1057 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1058 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) && 1059 global_monitor_.Pointer()->NotifyStoreExcl_Locked( 1060 addr, &global_monitor_processor_)) { 1061 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1062 *ptr = value; 1063 return 0; 1064 } else { 1065 return 1; 1066 } 1067 } 1068 1069 intptr_t* Simulator::ReadDW(intptr_t addr) { 1070 // All supported PPC targets allow unaligned accesses, so we don't need to 1071 // check the alignment here. 1072 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1073 local_monitor_.NotifyLoad(addr); 1074 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1075 return ptr; 1076 } 1077 1078 1079 void Simulator::WriteDW(intptr_t addr, int64_t value) { 1080 // All supported PPC targets allow unaligned accesses, so we don't need to 1081 // check the alignment here. 1082 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex); 1083 local_monitor_.NotifyStore(addr); 1084 global_monitor_.Pointer()->NotifyStore_Locked(addr, 1085 &global_monitor_processor_); 1086 int64_t* ptr = reinterpret_cast<int64_t*>(addr); 1087 *ptr = value; 1088 return; 1089 } 1090 1091 1092 // Returns the limit of the stack area to enable checking for stack overflows. 1093 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const { 1094 // The simulator uses a separate JS stack. If we have exhausted the C stack, 1095 // we also drop down the JS limit to reflect the exhaustion on the JS stack. 1096 if (GetCurrentStackPosition() < c_limit) { 1097 return reinterpret_cast<uintptr_t>(get_sp()); 1098 } 1099 1100 // Otherwise the limit is the JS stack. Leave a safety margin to prevent 1101 // overrunning the stack when pushing values. 1102 return reinterpret_cast<uintptr_t>(stack_) + stack_protection_size_; 1103 } 1104 1105 1106 // Unsupported instructions use Format to print an error and stop execution. 1107 void Simulator::Format(Instruction* instr, const char* format) { 1108 PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n", 1109 reinterpret_cast<intptr_t>(instr), format); 1110 UNIMPLEMENTED(); 1111 } 1112 1113 1114 // Calculate C flag value for additions. 1115 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) { 1116 uint32_t uleft = static_cast<uint32_t>(left); 1117 uint32_t uright = static_cast<uint32_t>(right); 1118 uint32_t urest = 0xFFFFFFFFU - uleft; 1119 1120 return (uright > urest) || 1121 (carry && (((uright + 1) > urest) || (uright > (urest - 1)))); 1122 } 1123 1124 1125 // Calculate C flag value for subtractions. 1126 bool Simulator::BorrowFrom(int32_t left, int32_t right) { 1127 uint32_t uleft = static_cast<uint32_t>(left); 1128 uint32_t uright = static_cast<uint32_t>(right); 1129 1130 return (uright > uleft); 1131 } 1132 1133 1134 // Calculate V flag value for additions and subtractions. 1135 bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right, 1136 bool addition) { 1137 bool overflow; 1138 if (addition) { 1139 // operands have the same sign 1140 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) 1141 // and operands and result have different sign 1142 && 1143 ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 1144 } else { 1145 // operands have different signs 1146 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) 1147 // and first operand and result have different signs 1148 && 1149 ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 1150 } 1151 return overflow; 1152 } 1153 1154 1155 #if V8_TARGET_ARCH_PPC64 1156 static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) { 1157 *x = reinterpret_cast<intptr_t>(pair->x); 1158 *y = reinterpret_cast<intptr_t>(pair->y); 1159 } 1160 #else 1161 static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) { 1162 #if V8_TARGET_BIG_ENDIAN 1163 *x = static_cast<int32_t>(*pair >> 32); 1164 *y = static_cast<int32_t>(*pair); 1165 #else 1166 *x = static_cast<int32_t>(*pair); 1167 *y = static_cast<int32_t>(*pair >> 32); 1168 #endif 1169 } 1170 #endif 1171 1172 // Calls into the V8 runtime. 1173 typedef intptr_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1, 1174 intptr_t arg2, intptr_t arg3, 1175 intptr_t arg4, intptr_t arg5, 1176 intptr_t arg6, intptr_t arg7, 1177 intptr_t arg8); 1178 typedef ObjectPair (*SimulatorRuntimePairCall)(intptr_t arg0, intptr_t arg1, 1179 intptr_t arg2, intptr_t arg3, 1180 intptr_t arg4, intptr_t arg5); 1181 1182 // These prototypes handle the four types of FP calls. 1183 typedef int (*SimulatorRuntimeCompareCall)(double darg0, double darg1); 1184 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1); 1185 typedef double (*SimulatorRuntimeFPCall)(double darg0); 1186 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, intptr_t arg0); 1187 1188 // This signature supports direct call in to API function native callback 1189 // (refer to InvocationCallback in v8.h). 1190 typedef void (*SimulatorRuntimeDirectApiCall)(intptr_t arg0); 1191 typedef void (*SimulatorRuntimeProfilingApiCall)(intptr_t arg0, void* arg1); 1192 1193 // This signature supports direct call to accessor getter callback. 1194 typedef void (*SimulatorRuntimeDirectGetterCall)(intptr_t arg0, intptr_t arg1); 1195 typedef void (*SimulatorRuntimeProfilingGetterCall)(intptr_t arg0, 1196 intptr_t arg1, void* arg2); 1197 1198 // Software interrupt instructions are used by the simulator to call into the 1199 // C-based V8 runtime. 1200 void Simulator::SoftwareInterrupt(Instruction* instr) { 1201 int svc = instr->SvcValue(); 1202 switch (svc) { 1203 case kCallRtRedirected: { 1204 // Check if stack is aligned. Error if not aligned is reported below to 1205 // include information on the function called. 1206 bool stack_aligned = 1207 (get_register(sp) & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 1208 0; 1209 Redirection* redirection = Redirection::FromInstruction(instr); 1210 const int kArgCount = 9; 1211 const int kRegisterArgCount = 8; 1212 int arg0_regnum = 3; 1213 intptr_t result_buffer = 0; 1214 bool uses_result_buffer = 1215 (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR && 1216 !ABI_RETURNS_OBJECT_PAIRS_IN_REGS); 1217 if (uses_result_buffer) { 1218 result_buffer = get_register(r3); 1219 arg0_regnum++; 1220 } 1221 intptr_t arg[kArgCount]; 1222 // First eight arguments in registers r3-r10. 1223 for (int i = 0; i < kRegisterArgCount; i++) { 1224 arg[i] = get_register(arg0_regnum + i); 1225 } 1226 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp)); 1227 // Remaining argument on stack 1228 arg[kRegisterArgCount] = stack_pointer[kStackFrameExtraParamSlot]; 1229 STATIC_ASSERT(kArgCount == kRegisterArgCount + 1); 1230 STATIC_ASSERT(kMaxCParameters == 9); 1231 bool fp_call = 1232 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) || 1233 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) || 1234 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) || 1235 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); 1236 // This is dodgy but it works because the C entry stubs are never moved. 1237 // See comment in codegen-arm.cc and bug 1242173. 1238 intptr_t saved_lr = special_reg_lr_; 1239 intptr_t external = 1240 reinterpret_cast<intptr_t>(redirection->external_function()); 1241 if (fp_call) { 1242 double dval0, dval1; // one or two double parameters 1243 intptr_t ival; // zero or one integer parameters 1244 int iresult = 0; // integer return value 1245 double dresult = 0; // double return value 1246 GetFpArgs(&dval0, &dval1, &ival); 1247 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1248 SimulatorRuntimeCall generic_target = 1249 reinterpret_cast<SimulatorRuntimeCall>(external); 1250 switch (redirection->type()) { 1251 case ExternalReference::BUILTIN_FP_FP_CALL: 1252 case ExternalReference::BUILTIN_COMPARE_CALL: 1253 PrintF("Call to host function at %p with args %f, %f", 1254 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)), 1255 dval0, dval1); 1256 break; 1257 case ExternalReference::BUILTIN_FP_CALL: 1258 PrintF("Call to host function at %p with arg %f", 1259 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)), 1260 dval0); 1261 break; 1262 case ExternalReference::BUILTIN_FP_INT_CALL: 1263 PrintF("Call to host function at %p with args %f, %" V8PRIdPTR, 1264 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)), 1265 dval0, ival); 1266 break; 1267 default: 1268 UNREACHABLE(); 1269 break; 1270 } 1271 if (!stack_aligned) { 1272 PrintF(" with unaligned stack %08" V8PRIxPTR "\n", 1273 get_register(sp)); 1274 } 1275 PrintF("\n"); 1276 } 1277 CHECK(stack_aligned); 1278 switch (redirection->type()) { 1279 case ExternalReference::BUILTIN_COMPARE_CALL: { 1280 SimulatorRuntimeCompareCall target = 1281 reinterpret_cast<SimulatorRuntimeCompareCall>(external); 1282 iresult = target(dval0, dval1); 1283 set_register(r3, iresult); 1284 break; 1285 } 1286 case ExternalReference::BUILTIN_FP_FP_CALL: { 1287 SimulatorRuntimeFPFPCall target = 1288 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 1289 dresult = target(dval0, dval1); 1290 SetFpResult(dresult); 1291 break; 1292 } 1293 case ExternalReference::BUILTIN_FP_CALL: { 1294 SimulatorRuntimeFPCall target = 1295 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1296 dresult = target(dval0); 1297 SetFpResult(dresult); 1298 break; 1299 } 1300 case ExternalReference::BUILTIN_FP_INT_CALL: { 1301 SimulatorRuntimeFPIntCall target = 1302 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 1303 dresult = target(dval0, ival); 1304 SetFpResult(dresult); 1305 break; 1306 } 1307 default: 1308 UNREACHABLE(); 1309 break; 1310 } 1311 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1312 switch (redirection->type()) { 1313 case ExternalReference::BUILTIN_COMPARE_CALL: 1314 PrintF("Returned %08x\n", iresult); 1315 break; 1316 case ExternalReference::BUILTIN_FP_FP_CALL: 1317 case ExternalReference::BUILTIN_FP_CALL: 1318 case ExternalReference::BUILTIN_FP_INT_CALL: 1319 PrintF("Returned %f\n", dresult); 1320 break; 1321 default: 1322 UNREACHABLE(); 1323 break; 1324 } 1325 } 1326 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { 1327 // See callers of MacroAssembler::CallApiFunctionAndReturn for 1328 // explanation of register usage. 1329 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1330 PrintF("Call to host function at %p args %08" V8PRIxPTR, 1331 reinterpret_cast<void*>(external), arg[0]); 1332 if (!stack_aligned) { 1333 PrintF(" with unaligned stack %08" V8PRIxPTR "\n", 1334 get_register(sp)); 1335 } 1336 PrintF("\n"); 1337 } 1338 CHECK(stack_aligned); 1339 SimulatorRuntimeDirectApiCall target = 1340 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 1341 target(arg[0]); 1342 } else if (redirection->type() == ExternalReference::PROFILING_API_CALL) { 1343 // See callers of MacroAssembler::CallApiFunctionAndReturn for 1344 // explanation of register usage. 1345 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1346 PrintF("Call to host function at %p args %08" V8PRIxPTR 1347 " %08" V8PRIxPTR, 1348 reinterpret_cast<void*>(external), arg[0], arg[1]); 1349 if (!stack_aligned) { 1350 PrintF(" with unaligned stack %08" V8PRIxPTR "\n", 1351 get_register(sp)); 1352 } 1353 PrintF("\n"); 1354 } 1355 CHECK(stack_aligned); 1356 SimulatorRuntimeProfilingApiCall target = 1357 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 1358 target(arg[0], Redirection::ReverseRedirection(arg[1])); 1359 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { 1360 // See callers of MacroAssembler::CallApiFunctionAndReturn for 1361 // explanation of register usage. 1362 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1363 PrintF("Call to host function at %p args %08" V8PRIxPTR 1364 " %08" V8PRIxPTR, 1365 reinterpret_cast<void*>(external), arg[0], arg[1]); 1366 if (!stack_aligned) { 1367 PrintF(" with unaligned stack %08" V8PRIxPTR "\n", 1368 get_register(sp)); 1369 } 1370 PrintF("\n"); 1371 } 1372 CHECK(stack_aligned); 1373 SimulatorRuntimeDirectGetterCall target = 1374 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 1375 if (!ABI_PASSES_HANDLES_IN_REGS) { 1376 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0])); 1377 } 1378 target(arg[0], arg[1]); 1379 } else if (redirection->type() == 1380 ExternalReference::PROFILING_GETTER_CALL) { 1381 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1382 PrintF("Call to host function at %p args %08" V8PRIxPTR 1383 " %08" V8PRIxPTR " %08" V8PRIxPTR, 1384 reinterpret_cast<void*>(external), arg[0], arg[1], arg[2]); 1385 if (!stack_aligned) { 1386 PrintF(" with unaligned stack %08" V8PRIxPTR "\n", 1387 get_register(sp)); 1388 } 1389 PrintF("\n"); 1390 } 1391 CHECK(stack_aligned); 1392 SimulatorRuntimeProfilingGetterCall target = 1393 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); 1394 if (!ABI_PASSES_HANDLES_IN_REGS) { 1395 arg[0] = *(reinterpret_cast<intptr_t*>(arg[0])); 1396 } 1397 target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2])); 1398 } else { 1399 // builtin call. 1400 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1401 SimulatorRuntimeCall target = 1402 reinterpret_cast<SimulatorRuntimeCall>(external); 1403 PrintF( 1404 "Call to host function at %p,\n" 1405 "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR 1406 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR 1407 ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR, 1408 reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg[0], arg[1], 1409 arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8]); 1410 if (!stack_aligned) { 1411 PrintF(" with unaligned stack %08" V8PRIxPTR "\n", 1412 get_register(sp)); 1413 } 1414 PrintF("\n"); 1415 } 1416 CHECK(stack_aligned); 1417 if (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR) { 1418 SimulatorRuntimePairCall target = 1419 reinterpret_cast<SimulatorRuntimePairCall>(external); 1420 ObjectPair result = 1421 target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); 1422 intptr_t x; 1423 intptr_t y; 1424 decodeObjectPair(&result, &x, &y); 1425 if (::v8::internal::FLAG_trace_sim) { 1426 PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y); 1427 } 1428 if (ABI_RETURNS_OBJECT_PAIRS_IN_REGS) { 1429 set_register(r3, x); 1430 set_register(r4, y); 1431 } else { 1432 memcpy(reinterpret_cast<void*>(result_buffer), &result, 1433 sizeof(ObjectPair)); 1434 set_register(r3, result_buffer); 1435 } 1436 } else { 1437 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL); 1438 SimulatorRuntimeCall target = 1439 reinterpret_cast<SimulatorRuntimeCall>(external); 1440 intptr_t result = target(arg[0], arg[1], arg[2], arg[3], arg[4], 1441 arg[5], arg[6], arg[7], arg[8]); 1442 if (::v8::internal::FLAG_trace_sim) { 1443 PrintF("Returned %08" V8PRIxPTR "\n", result); 1444 } 1445 set_register(r3, result); 1446 } 1447 } 1448 set_pc(saved_lr); 1449 break; 1450 } 1451 case kBreakpoint: { 1452 PPCDebugger dbg(this); 1453 dbg.Debug(); 1454 break; 1455 } 1456 // stop uses all codes greater than 1 << 23. 1457 default: { 1458 if (svc >= (1 << 23)) { 1459 uint32_t code = svc & kStopCodeMask; 1460 if (isWatchedStop(code)) { 1461 IncreaseStopCounter(code); 1462 } 1463 // Stop if it is enabled, otherwise go on jumping over the stop 1464 // and the message address. 1465 if (isEnabledStop(code)) { 1466 PPCDebugger dbg(this); 1467 dbg.Stop(instr); 1468 } else { 1469 set_pc(get_pc() + kInstrSize + kPointerSize); 1470 } 1471 } else { 1472 // This is not a valid svc code. 1473 UNREACHABLE(); 1474 break; 1475 } 1476 } 1477 } 1478 } 1479 1480 1481 // Stop helper functions. 1482 bool Simulator::isStopInstruction(Instruction* instr) { 1483 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode); 1484 } 1485 1486 1487 bool Simulator::isWatchedStop(uint32_t code) { 1488 DCHECK_LE(code, kMaxStopCode); 1489 return code < kNumOfWatchedStops; 1490 } 1491 1492 1493 bool Simulator::isEnabledStop(uint32_t code) { 1494 DCHECK_LE(code, kMaxStopCode); 1495 // Unwatched stops are always enabled. 1496 return !isWatchedStop(code) || 1497 !(watched_stops_[code].count & kStopDisabledBit); 1498 } 1499 1500 1501 void Simulator::EnableStop(uint32_t code) { 1502 DCHECK(isWatchedStop(code)); 1503 if (!isEnabledStop(code)) { 1504 watched_stops_[code].count &= ~kStopDisabledBit; 1505 } 1506 } 1507 1508 1509 void Simulator::DisableStop(uint32_t code) { 1510 DCHECK(isWatchedStop(code)); 1511 if (isEnabledStop(code)) { 1512 watched_stops_[code].count |= kStopDisabledBit; 1513 } 1514 } 1515 1516 1517 void Simulator::IncreaseStopCounter(uint32_t code) { 1518 DCHECK_LE(code, kMaxStopCode); 1519 DCHECK(isWatchedStop(code)); 1520 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) { 1521 PrintF( 1522 "Stop counter for code %i has overflowed.\n" 1523 "Enabling this code and reseting the counter to 0.\n", 1524 code); 1525 watched_stops_[code].count = 0; 1526 EnableStop(code); 1527 } else { 1528 watched_stops_[code].count++; 1529 } 1530 } 1531 1532 1533 // Print a stop status. 1534 void Simulator::PrintStopInfo(uint32_t code) { 1535 DCHECK_LE(code, kMaxStopCode); 1536 if (!isWatchedStop(code)) { 1537 PrintF("Stop not watched."); 1538 } else { 1539 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled"; 1540 int32_t count = watched_stops_[code].count & ~kStopDisabledBit; 1541 // Don't print the state of unused breakpoints. 1542 if (count != 0) { 1543 if (watched_stops_[code].desc) { 1544 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code, 1545 state, count, watched_stops_[code].desc); 1546 } else { 1547 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state, 1548 count); 1549 } 1550 } 1551 } 1552 } 1553 1554 1555 void Simulator::SetCR0(intptr_t result, bool setSO) { 1556 int bf = 0; 1557 if (result < 0) { 1558 bf |= 0x80000000; 1559 } 1560 if (result > 0) { 1561 bf |= 0x40000000; 1562 } 1563 if (result == 0) { 1564 bf |= 0x20000000; 1565 } 1566 if (setSO) { 1567 bf |= 0x10000000; 1568 } 1569 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf; 1570 } 1571 1572 1573 void Simulator::ExecuteBranchConditional(Instruction* instr, BCType type) { 1574 int bo = instr->Bits(25, 21) << 21; 1575 int condition_bit = instr->Bits(20, 16); 1576 int condition_mask = 0x80000000 >> condition_bit; 1577 switch (bo) { 1578 case DCBNZF: // Decrement CTR; branch if CTR != 0 and condition false 1579 case DCBEZF: // Decrement CTR; branch if CTR == 0 and condition false 1580 UNIMPLEMENTED(); 1581 case BF: { // Branch if condition false 1582 if (condition_reg_ & condition_mask) return; 1583 break; 1584 } 1585 case DCBNZT: // Decrement CTR; branch if CTR != 0 and condition true 1586 case DCBEZT: // Decrement CTR; branch if CTR == 0 and condition true 1587 UNIMPLEMENTED(); 1588 case BT: { // Branch if condition true 1589 if (!(condition_reg_ & condition_mask)) return; 1590 break; 1591 } 1592 case DCBNZ: // Decrement CTR; branch if CTR != 0 1593 case DCBEZ: // Decrement CTR; branch if CTR == 0 1594 special_reg_ctr_ -= 1; 1595 if ((special_reg_ctr_ == 0) != (bo == DCBEZ)) return; 1596 break; 1597 case BA: { // Branch always 1598 break; 1599 } 1600 default: 1601 UNIMPLEMENTED(); // Invalid encoding 1602 } 1603 1604 intptr_t old_pc = get_pc(); 1605 1606 switch (type) { 1607 case BC_OFFSET: { 1608 int offset = (instr->Bits(15, 2) << 18) >> 16; 1609 set_pc(old_pc + offset); 1610 break; 1611 } 1612 case BC_LINK_REG: 1613 set_pc(special_reg_lr_); 1614 break; 1615 case BC_CTR_REG: 1616 set_pc(special_reg_ctr_); 1617 break; 1618 } 1619 1620 if (instr->Bit(0) == 1) { // LK flag set 1621 special_reg_lr_ = old_pc + 4; 1622 } 1623 } 1624 1625 void Simulator::ExecuteGeneric(Instruction* instr) { 1626 uint32_t opcode = instr->OpcodeBase(); 1627 switch (opcode) { 1628 case SUBFIC: { 1629 int rt = instr->RTValue(); 1630 int ra = instr->RAValue(); 1631 intptr_t ra_val = get_register(ra); 1632 int32_t im_val = instr->Bits(15, 0); 1633 im_val = SIGN_EXT_IMM16(im_val); 1634 intptr_t alu_out = im_val - ra_val; 1635 set_register(rt, alu_out); 1636 // todo - handle RC bit 1637 break; 1638 } 1639 case CMPLI: { 1640 int ra = instr->RAValue(); 1641 uint32_t im_val = instr->Bits(15, 0); 1642 int cr = instr->Bits(25, 23); 1643 uint32_t bf = 0; 1644 #if V8_TARGET_ARCH_PPC64 1645 int L = instr->Bit(21); 1646 if (L) { 1647 #endif 1648 uintptr_t ra_val = get_register(ra); 1649 if (ra_val < im_val) { 1650 bf |= 0x80000000; 1651 } 1652 if (ra_val > im_val) { 1653 bf |= 0x40000000; 1654 } 1655 if (ra_val == im_val) { 1656 bf |= 0x20000000; 1657 } 1658 #if V8_TARGET_ARCH_PPC64 1659 } else { 1660 uint32_t ra_val = get_register(ra); 1661 if (ra_val < im_val) { 1662 bf |= 0x80000000; 1663 } 1664 if (ra_val > im_val) { 1665 bf |= 0x40000000; 1666 } 1667 if (ra_val == im_val) { 1668 bf |= 0x20000000; 1669 } 1670 } 1671 #endif 1672 uint32_t condition_mask = 0xF0000000U >> (cr * 4); 1673 uint32_t condition = bf >> (cr * 4); 1674 condition_reg_ = (condition_reg_ & ~condition_mask) | condition; 1675 break; 1676 } 1677 case CMPI: { 1678 int ra = instr->RAValue(); 1679 int32_t im_val = instr->Bits(15, 0); 1680 im_val = SIGN_EXT_IMM16(im_val); 1681 int cr = instr->Bits(25, 23); 1682 uint32_t bf = 0; 1683 #if V8_TARGET_ARCH_PPC64 1684 int L = instr->Bit(21); 1685 if (L) { 1686 #endif 1687 intptr_t ra_val = get_register(ra); 1688 if (ra_val < im_val) { 1689 bf |= 0x80000000; 1690 } 1691 if (ra_val > im_val) { 1692 bf |= 0x40000000; 1693 } 1694 if (ra_val == im_val) { 1695 bf |= 0x20000000; 1696 } 1697 #if V8_TARGET_ARCH_PPC64 1698 } else { 1699 int32_t ra_val = get_register(ra); 1700 if (ra_val < im_val) { 1701 bf |= 0x80000000; 1702 } 1703 if (ra_val > im_val) { 1704 bf |= 0x40000000; 1705 } 1706 if (ra_val == im_val) { 1707 bf |= 0x20000000; 1708 } 1709 } 1710 #endif 1711 uint32_t condition_mask = 0xF0000000U >> (cr * 4); 1712 uint32_t condition = bf >> (cr * 4); 1713 condition_reg_ = (condition_reg_ & ~condition_mask) | condition; 1714 break; 1715 } 1716 case ADDIC: { 1717 int rt = instr->RTValue(); 1718 int ra = instr->RAValue(); 1719 uintptr_t ra_val = get_register(ra); 1720 uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0)); 1721 uintptr_t alu_out = ra_val + im_val; 1722 // Check overflow 1723 if (~ra_val < im_val) { 1724 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000; 1725 } else { 1726 special_reg_xer_ &= ~0xF0000000; 1727 } 1728 set_register(rt, alu_out); 1729 break; 1730 } 1731 case ADDI: { 1732 int rt = instr->RTValue(); 1733 int ra = instr->RAValue(); 1734 int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0)); 1735 intptr_t alu_out; 1736 if (ra == 0) { 1737 alu_out = im_val; 1738 } else { 1739 intptr_t ra_val = get_register(ra); 1740 alu_out = ra_val + im_val; 1741 } 1742 set_register(rt, alu_out); 1743 // todo - handle RC bit 1744 break; 1745 } 1746 case ADDIS: { 1747 int rt = instr->RTValue(); 1748 int ra = instr->RAValue(); 1749 int32_t im_val = (instr->Bits(15, 0) << 16); 1750 intptr_t alu_out; 1751 if (ra == 0) { // treat r0 as zero 1752 alu_out = im_val; 1753 } else { 1754 intptr_t ra_val = get_register(ra); 1755 alu_out = ra_val + im_val; 1756 } 1757 set_register(rt, alu_out); 1758 break; 1759 } 1760 case BCX: { 1761 ExecuteBranchConditional(instr, BC_OFFSET); 1762 break; 1763 } 1764 case BX: { 1765 int offset = (instr->Bits(25, 2) << 8) >> 6; 1766 if (instr->Bit(0) == 1) { // LK flag set 1767 special_reg_lr_ = get_pc() + 4; 1768 } 1769 set_pc(get_pc() + offset); 1770 // todo - AA flag 1771 break; 1772 } 1773 case MCRF: 1774 UNIMPLEMENTED(); // Not used by V8. 1775 case BCLRX: 1776 ExecuteBranchConditional(instr, BC_LINK_REG); 1777 break; 1778 case BCCTRX: 1779 ExecuteBranchConditional(instr, BC_CTR_REG); 1780 break; 1781 case CRNOR: 1782 case RFI: 1783 case CRANDC: 1784 UNIMPLEMENTED(); 1785 case ISYNC: { 1786 // todo - simulate isync 1787 break; 1788 } 1789 case CRXOR: { 1790 int bt = instr->Bits(25, 21); 1791 int ba = instr->Bits(20, 16); 1792 int bb = instr->Bits(15, 11); 1793 int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1; 1794 int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1; 1795 int bt_val = ba_val ^ bb_val; 1796 bt_val = bt_val << (31 - bt); // shift bit to correct destination 1797 condition_reg_ &= ~(0x80000000 >> bt); 1798 condition_reg_ |= bt_val; 1799 break; 1800 } 1801 case CREQV: { 1802 int bt = instr->Bits(25, 21); 1803 int ba = instr->Bits(20, 16); 1804 int bb = instr->Bits(15, 11); 1805 int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1; 1806 int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1; 1807 int bt_val = 1 - (ba_val ^ bb_val); 1808 bt_val = bt_val << (31 - bt); // shift bit to correct destination 1809 condition_reg_ &= ~(0x80000000 >> bt); 1810 condition_reg_ |= bt_val; 1811 break; 1812 } 1813 case CRNAND: 1814 case CRAND: 1815 case CRORC: 1816 case CROR: { 1817 UNIMPLEMENTED(); // Not used by V8. 1818 break; 1819 } 1820 case RLWIMIX: { 1821 int ra = instr->RAValue(); 1822 int rs = instr->RSValue(); 1823 uint32_t rs_val = get_register(rs); 1824 int32_t ra_val = get_register(ra); 1825 int sh = instr->Bits(15, 11); 1826 int mb = instr->Bits(10, 6); 1827 int me = instr->Bits(5, 1); 1828 uint32_t result = base::bits::RotateLeft32(rs_val, sh); 1829 int mask = 0; 1830 if (mb < me + 1) { 1831 int bit = 0x80000000 >> mb; 1832 for (; mb <= me; mb++) { 1833 mask |= bit; 1834 bit >>= 1; 1835 } 1836 } else if (mb == me + 1) { 1837 mask = 0xFFFFFFFF; 1838 } else { // mb > me+1 1839 int bit = 0x80000000 >> (me + 1); // needs to be tested 1840 mask = 0xFFFFFFFF; 1841 for (; me < mb; me++) { 1842 mask ^= bit; 1843 bit >>= 1; 1844 } 1845 } 1846 result &= mask; 1847 ra_val &= ~mask; 1848 result |= ra_val; 1849 set_register(ra, result); 1850 if (instr->Bit(0)) { // RC bit set 1851 SetCR0(result); 1852 } 1853 break; 1854 } 1855 case RLWINMX: 1856 case RLWNMX: { 1857 int ra = instr->RAValue(); 1858 int rs = instr->RSValue(); 1859 uint32_t rs_val = get_register(rs); 1860 int sh = 0; 1861 if (opcode == RLWINMX) { 1862 sh = instr->Bits(15, 11); 1863 } else { 1864 int rb = instr->RBValue(); 1865 uint32_t rb_val = get_register(rb); 1866 sh = (rb_val & 0x1F); 1867 } 1868 int mb = instr->Bits(10, 6); 1869 int me = instr->Bits(5, 1); 1870 uint32_t result = base::bits::RotateLeft32(rs_val, sh); 1871 int mask = 0; 1872 if (mb < me + 1) { 1873 int bit = 0x80000000 >> mb; 1874 for (; mb <= me; mb++) { 1875 mask |= bit; 1876 bit >>= 1; 1877 } 1878 } else if (mb == me + 1) { 1879 mask = 0xFFFFFFFF; 1880 } else { // mb > me+1 1881 int bit = 0x80000000 >> (me + 1); // needs to be tested 1882 mask = 0xFFFFFFFF; 1883 for (; me < mb; me++) { 1884 mask ^= bit; 1885 bit >>= 1; 1886 } 1887 } 1888 result &= mask; 1889 set_register(ra, result); 1890 if (instr->Bit(0)) { // RC bit set 1891 SetCR0(result); 1892 } 1893 break; 1894 } 1895 case ORI: { 1896 int rs = instr->RSValue(); 1897 int ra = instr->RAValue(); 1898 intptr_t rs_val = get_register(rs); 1899 uint32_t im_val = instr->Bits(15, 0); 1900 intptr_t alu_out = rs_val | im_val; 1901 set_register(ra, alu_out); 1902 break; 1903 } 1904 case ORIS: { 1905 int rs = instr->RSValue(); 1906 int ra = instr->RAValue(); 1907 intptr_t rs_val = get_register(rs); 1908 uint32_t im_val = instr->Bits(15, 0); 1909 intptr_t alu_out = rs_val | (im_val << 16); 1910 set_register(ra, alu_out); 1911 break; 1912 } 1913 case XORI: { 1914 int rs = instr->RSValue(); 1915 int ra = instr->RAValue(); 1916 intptr_t rs_val = get_register(rs); 1917 uint32_t im_val = instr->Bits(15, 0); 1918 intptr_t alu_out = rs_val ^ im_val; 1919 set_register(ra, alu_out); 1920 // todo - set condition based SO bit 1921 break; 1922 } 1923 case XORIS: { 1924 int rs = instr->RSValue(); 1925 int ra = instr->RAValue(); 1926 intptr_t rs_val = get_register(rs); 1927 uint32_t im_val = instr->Bits(15, 0); 1928 intptr_t alu_out = rs_val ^ (im_val << 16); 1929 set_register(ra, alu_out); 1930 break; 1931 } 1932 case ANDIx: { 1933 int rs = instr->RSValue(); 1934 int ra = instr->RAValue(); 1935 intptr_t rs_val = get_register(rs); 1936 uint32_t im_val = instr->Bits(15, 0); 1937 intptr_t alu_out = rs_val & im_val; 1938 set_register(ra, alu_out); 1939 SetCR0(alu_out); 1940 break; 1941 } 1942 case ANDISx: { 1943 int rs = instr->RSValue(); 1944 int ra = instr->RAValue(); 1945 intptr_t rs_val = get_register(rs); 1946 uint32_t im_val = instr->Bits(15, 0); 1947 intptr_t alu_out = rs_val & (im_val << 16); 1948 set_register(ra, alu_out); 1949 SetCR0(alu_out); 1950 break; 1951 } 1952 case SRWX: { 1953 int rs = instr->RSValue(); 1954 int ra = instr->RAValue(); 1955 int rb = instr->RBValue(); 1956 uint32_t rs_val = get_register(rs); 1957 uintptr_t rb_val = get_register(rb) & 0x3F; 1958 intptr_t result = (rb_val > 31) ? 0 : rs_val >> rb_val; 1959 set_register(ra, result); 1960 if (instr->Bit(0)) { // RC bit set 1961 SetCR0(result); 1962 } 1963 break; 1964 } 1965 #if V8_TARGET_ARCH_PPC64 1966 case SRDX: { 1967 int rs = instr->RSValue(); 1968 int ra = instr->RAValue(); 1969 int rb = instr->RBValue(); 1970 uintptr_t rs_val = get_register(rs); 1971 uintptr_t rb_val = get_register(rb) & 0x7F; 1972 intptr_t result = (rb_val > 63) ? 0 : rs_val >> rb_val; 1973 set_register(ra, result); 1974 if (instr->Bit(0)) { // RC bit set 1975 SetCR0(result); 1976 } 1977 break; 1978 } 1979 #endif 1980 case MODUW: { 1981 int rt = instr->RTValue(); 1982 int ra = instr->RAValue(); 1983 int rb = instr->RBValue(); 1984 uint32_t ra_val = get_register(ra); 1985 uint32_t rb_val = get_register(rb); 1986 uint32_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val; 1987 set_register(rt, alu_out); 1988 break; 1989 } 1990 #if V8_TARGET_ARCH_PPC64 1991 case MODUD: { 1992 int rt = instr->RTValue(); 1993 int ra = instr->RAValue(); 1994 int rb = instr->RBValue(); 1995 uint64_t ra_val = get_register(ra); 1996 uint64_t rb_val = get_register(rb); 1997 uint64_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val; 1998 set_register(rt, alu_out); 1999 break; 2000 } 2001 #endif 2002 case MODSW: { 2003 int rt = instr->RTValue(); 2004 int ra = instr->RAValue(); 2005 int rb = instr->RBValue(); 2006 int32_t ra_val = get_register(ra); 2007 int32_t rb_val = get_register(rb); 2008 bool overflow = (ra_val == kMinInt && rb_val == -1); 2009 // result is undefined if divisor is zero or if operation 2010 // is 0x80000000 / -1. 2011 int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val % rb_val; 2012 set_register(rt, alu_out); 2013 break; 2014 } 2015 #if V8_TARGET_ARCH_PPC64 2016 case MODSD: { 2017 int rt = instr->RTValue(); 2018 int ra = instr->RAValue(); 2019 int rb = instr->RBValue(); 2020 int64_t ra_val = get_register(ra); 2021 int64_t rb_val = get_register(rb); 2022 int64_t one = 1; // work-around gcc 2023 int64_t kMinLongLong = (one << 63); 2024 // result is undefined if divisor is zero or if operation 2025 // is 0x80000000_00000000 / -1. 2026 int64_t alu_out = 2027 (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1)) 2028 ? -1 2029 : ra_val % rb_val; 2030 set_register(rt, alu_out); 2031 break; 2032 } 2033 #endif 2034 case SRAW: { 2035 int rs = instr->RSValue(); 2036 int ra = instr->RAValue(); 2037 int rb = instr->RBValue(); 2038 int32_t rs_val = get_register(rs); 2039 intptr_t rb_val = get_register(rb) & 0x3F; 2040 intptr_t result = (rb_val > 31) ? rs_val >> 31 : rs_val >> rb_val; 2041 set_register(ra, result); 2042 if (instr->Bit(0)) { // RC bit set 2043 SetCR0(result); 2044 } 2045 break; 2046 } 2047 #if V8_TARGET_ARCH_PPC64 2048 case SRAD: { 2049 int rs = instr->RSValue(); 2050 int ra = instr->RAValue(); 2051 int rb = instr->RBValue(); 2052 intptr_t rs_val = get_register(rs); 2053 intptr_t rb_val = get_register(rb) & 0x7F; 2054 intptr_t result = (rb_val > 63) ? rs_val >> 63 : rs_val >> rb_val; 2055 set_register(ra, result); 2056 if (instr->Bit(0)) { // RC bit set 2057 SetCR0(result); 2058 } 2059 break; 2060 } 2061 #endif 2062 case SRAWIX: { 2063 int ra = instr->RAValue(); 2064 int rs = instr->RSValue(); 2065 int sh = instr->Bits(15, 11); 2066 int32_t rs_val = get_register(rs); 2067 intptr_t result = rs_val >> sh; 2068 set_register(ra, result); 2069 if (instr->Bit(0)) { // RC bit set 2070 SetCR0(result); 2071 } 2072 break; 2073 } 2074 #if V8_TARGET_ARCH_PPC64 2075 case EXTSW: { 2076 const int shift = kBitsPerPointer - 32; 2077 int ra = instr->RAValue(); 2078 int rs = instr->RSValue(); 2079 intptr_t rs_val = get_register(rs); 2080 intptr_t ra_val = (rs_val << shift) >> shift; 2081 set_register(ra, ra_val); 2082 if (instr->Bit(0)) { // RC bit set 2083 SetCR0(ra_val); 2084 } 2085 break; 2086 } 2087 #endif 2088 case EXTSH: { 2089 const int shift = kBitsPerPointer - 16; 2090 int ra = instr->RAValue(); 2091 int rs = instr->RSValue(); 2092 intptr_t rs_val = get_register(rs); 2093 intptr_t ra_val = (rs_val << shift) >> shift; 2094 set_register(ra, ra_val); 2095 if (instr->Bit(0)) { // RC bit set 2096 SetCR0(ra_val); 2097 } 2098 break; 2099 } 2100 case EXTSB: { 2101 const int shift = kBitsPerPointer - 8; 2102 int ra = instr->RAValue(); 2103 int rs = instr->RSValue(); 2104 intptr_t rs_val = get_register(rs); 2105 intptr_t ra_val = (rs_val << shift) >> shift; 2106 set_register(ra, ra_val); 2107 if (instr->Bit(0)) { // RC bit set 2108 SetCR0(ra_val); 2109 } 2110 break; 2111 } 2112 case LFSUX: 2113 case LFSX: { 2114 int frt = instr->RTValue(); 2115 int ra = instr->RAValue(); 2116 int rb = instr->RBValue(); 2117 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2118 intptr_t rb_val = get_register(rb); 2119 int32_t val = ReadW(ra_val + rb_val, instr); 2120 float* fptr = reinterpret_cast<float*>(&val); 2121 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 2122 // Conversion using double changes sNan to qNan on ia32/x64 2123 if ((val & 0x7F800000) == 0x7F800000) { 2124 int64_t dval = static_cast<int64_t>(val); 2125 dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) | 2126 ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) | 0x0; 2127 set_d_register(frt, dval); 2128 } else { 2129 set_d_register_from_double(frt, static_cast<double>(*fptr)); 2130 } 2131 #else 2132 set_d_register_from_double(frt, static_cast<double>(*fptr)); 2133 #endif 2134 if (opcode == LFSUX) { 2135 DCHECK_NE(ra, 0); 2136 set_register(ra, ra_val + rb_val); 2137 } 2138 break; 2139 } 2140 case LFDUX: 2141 case LFDX: { 2142 int frt = instr->RTValue(); 2143 int ra = instr->RAValue(); 2144 int rb = instr->RBValue(); 2145 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2146 intptr_t rb_val = get_register(rb); 2147 int64_t* dptr = reinterpret_cast<int64_t*>(ReadDW(ra_val + rb_val)); 2148 set_d_register(frt, *dptr); 2149 if (opcode == LFDUX) { 2150 DCHECK_NE(ra, 0); 2151 set_register(ra, ra_val + rb_val); 2152 } 2153 break; 2154 } 2155 case STFSUX: V8_FALLTHROUGH; 2156 case STFSX: { 2157 int frs = instr->RSValue(); 2158 int ra = instr->RAValue(); 2159 int rb = instr->RBValue(); 2160 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2161 intptr_t rb_val = get_register(rb); 2162 float frs_val = static_cast<float>(get_double_from_d_register(frs)); 2163 int32_t* p = reinterpret_cast<int32_t*>(&frs_val); 2164 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 2165 // Conversion using double changes sNan to qNan on ia32/x64 2166 int32_t sval = 0; 2167 int64_t dval = get_d_register(frs); 2168 if ((dval & 0x7FF0000000000000) == 0x7FF0000000000000) { 2169 sval = ((dval & 0xC000000000000000) >> 32) | 2170 ((dval & 0x07FFFFFFE0000000) >> 29); 2171 p = &sval; 2172 } else { 2173 p = reinterpret_cast<int32_t*>(&frs_val); 2174 } 2175 #else 2176 p = reinterpret_cast<int32_t*>(&frs_val); 2177 #endif 2178 WriteW(ra_val + rb_val, *p, instr); 2179 if (opcode == STFSUX) { 2180 DCHECK_NE(ra, 0); 2181 set_register(ra, ra_val + rb_val); 2182 } 2183 break; 2184 } 2185 case STFDUX: V8_FALLTHROUGH; 2186 case STFDX: { 2187 int frs = instr->RSValue(); 2188 int ra = instr->RAValue(); 2189 int rb = instr->RBValue(); 2190 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2191 intptr_t rb_val = get_register(rb); 2192 int64_t frs_val = get_d_register(frs); 2193 WriteDW(ra_val + rb_val, frs_val); 2194 if (opcode == STFDUX) { 2195 DCHECK_NE(ra, 0); 2196 set_register(ra, ra_val + rb_val); 2197 } 2198 break; 2199 } 2200 case POPCNTW: { 2201 int rs = instr->RSValue(); 2202 int ra = instr->RAValue(); 2203 uintptr_t rs_val = get_register(rs); 2204 uintptr_t count = 0; 2205 int n = 0; 2206 uintptr_t bit = 0x80000000; 2207 for (; n < 32; n++) { 2208 if (bit & rs_val) count++; 2209 bit >>= 1; 2210 } 2211 set_register(ra, count); 2212 break; 2213 } 2214 #if V8_TARGET_ARCH_PPC64 2215 case POPCNTD: { 2216 int rs = instr->RSValue(); 2217 int ra = instr->RAValue(); 2218 uintptr_t rs_val = get_register(rs); 2219 uintptr_t count = 0; 2220 int n = 0; 2221 uintptr_t bit = 0x8000000000000000UL; 2222 for (; n < 64; n++) { 2223 if (bit & rs_val) count++; 2224 bit >>= 1; 2225 } 2226 set_register(ra, count); 2227 break; 2228 } 2229 #endif 2230 case SYNC: { 2231 // todo - simulate sync 2232 break; 2233 } 2234 case ICBI: { 2235 // todo - simulate icbi 2236 break; 2237 } 2238 2239 case LWZU: 2240 case LWZ: { 2241 int ra = instr->RAValue(); 2242 int rt = instr->RTValue(); 2243 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2244 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 2245 set_register(rt, ReadWU(ra_val + offset, instr)); 2246 if (opcode == LWZU) { 2247 DCHECK_NE(ra, 0); 2248 set_register(ra, ra_val + offset); 2249 } 2250 break; 2251 } 2252 2253 case LBZU: 2254 case LBZ: { 2255 int ra = instr->RAValue(); 2256 int rt = instr->RTValue(); 2257 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2258 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 2259 set_register(rt, ReadB(ra_val + offset) & 0xFF); 2260 if (opcode == LBZU) { 2261 DCHECK_NE(ra, 0); 2262 set_register(ra, ra_val + offset); 2263 } 2264 break; 2265 } 2266 2267 case STWU: 2268 case STW: { 2269 int ra = instr->RAValue(); 2270 int rs = instr->RSValue(); 2271 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2272 int32_t rs_val = get_register(rs); 2273 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 2274 WriteW(ra_val + offset, rs_val, instr); 2275 if (opcode == STWU) { 2276 DCHECK_NE(ra, 0); 2277 set_register(ra, ra_val + offset); 2278 } 2279 break; 2280 } 2281 case SRADIX: { 2282 int ra = instr->RAValue(); 2283 int rs = instr->RSValue(); 2284 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5)); 2285 intptr_t rs_val = get_register(rs); 2286 intptr_t result = rs_val >> sh; 2287 set_register(ra, result); 2288 if (instr->Bit(0)) { // RC bit set 2289 SetCR0(result); 2290 } 2291 break; 2292 } 2293 case STBCX: { 2294 int rs = instr->RSValue(); 2295 int ra = instr->RAValue(); 2296 int rb = instr->RBValue(); 2297 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2298 int8_t rs_val = get_register(rs); 2299 intptr_t rb_val = get_register(rb); 2300 SetCR0(WriteExB(ra_val + rb_val, rs_val)); 2301 break; 2302 } 2303 case STHCX: { 2304 int rs = instr->RSValue(); 2305 int ra = instr->RAValue(); 2306 int rb = instr->RBValue(); 2307 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2308 int16_t rs_val = get_register(rs); 2309 intptr_t rb_val = get_register(rb); 2310 SetCR0(WriteExH(ra_val + rb_val, rs_val, instr)); 2311 break; 2312 } 2313 case STWCX: { 2314 int rs = instr->RSValue(); 2315 int ra = instr->RAValue(); 2316 int rb = instr->RBValue(); 2317 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2318 int32_t rs_val = get_register(rs); 2319 intptr_t rb_val = get_register(rb); 2320 SetCR0(WriteExW(ra_val + rb_val, rs_val, instr)); 2321 break; 2322 } 2323 case TW: { 2324 // used for call redirection in simulation mode 2325 SoftwareInterrupt(instr); 2326 break; 2327 } 2328 case CMP: { 2329 int ra = instr->RAValue(); 2330 int rb = instr->RBValue(); 2331 int cr = instr->Bits(25, 23); 2332 uint32_t bf = 0; 2333 #if V8_TARGET_ARCH_PPC64 2334 int L = instr->Bit(21); 2335 if (L) { 2336 #endif 2337 intptr_t ra_val = get_register(ra); 2338 intptr_t rb_val = get_register(rb); 2339 if (ra_val < rb_val) { 2340 bf |= 0x80000000; 2341 } 2342 if (ra_val > rb_val) { 2343 bf |= 0x40000000; 2344 } 2345 if (ra_val == rb_val) { 2346 bf |= 0x20000000; 2347 } 2348 #if V8_TARGET_ARCH_PPC64 2349 } else { 2350 int32_t ra_val = get_register(ra); 2351 int32_t rb_val = get_register(rb); 2352 if (ra_val < rb_val) { 2353 bf |= 0x80000000; 2354 } 2355 if (ra_val > rb_val) { 2356 bf |= 0x40000000; 2357 } 2358 if (ra_val == rb_val) { 2359 bf |= 0x20000000; 2360 } 2361 } 2362 #endif 2363 uint32_t condition_mask = 0xF0000000U >> (cr * 4); 2364 uint32_t condition = bf >> (cr * 4); 2365 condition_reg_ = (condition_reg_ & ~condition_mask) | condition; 2366 break; 2367 } 2368 case SUBFCX: { 2369 int rt = instr->RTValue(); 2370 int ra = instr->RAValue(); 2371 int rb = instr->RBValue(); 2372 // int oe = instr->Bit(10); 2373 uintptr_t ra_val = get_register(ra); 2374 uintptr_t rb_val = get_register(rb); 2375 uintptr_t alu_out = ~ra_val + rb_val + 1; 2376 // Set carry 2377 if (ra_val <= rb_val) { 2378 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000; 2379 } else { 2380 special_reg_xer_ &= ~0xF0000000; 2381 } 2382 set_register(rt, alu_out); 2383 if (instr->Bit(0)) { // RC bit set 2384 SetCR0(alu_out); 2385 } 2386 // todo - handle OE bit 2387 break; 2388 } 2389 case SUBFEX: { 2390 int rt = instr->RTValue(); 2391 int ra = instr->RAValue(); 2392 int rb = instr->RBValue(); 2393 // int oe = instr->Bit(10); 2394 uintptr_t ra_val = get_register(ra); 2395 uintptr_t rb_val = get_register(rb); 2396 uintptr_t alu_out = ~ra_val + rb_val; 2397 if (special_reg_xer_ & 0x20000000) { 2398 alu_out += 1; 2399 } 2400 set_register(rt, alu_out); 2401 if (instr->Bit(0)) { // RC bit set 2402 SetCR0(static_cast<intptr_t>(alu_out)); 2403 } 2404 // todo - handle OE bit 2405 break; 2406 } 2407 case ADDCX: { 2408 int rt = instr->RTValue(); 2409 int ra = instr->RAValue(); 2410 int rb = instr->RBValue(); 2411 // int oe = instr->Bit(10); 2412 uintptr_t ra_val = get_register(ra); 2413 uintptr_t rb_val = get_register(rb); 2414 uintptr_t alu_out = ra_val + rb_val; 2415 // Set carry 2416 if (~ra_val < rb_val) { 2417 special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000; 2418 } else { 2419 special_reg_xer_ &= ~0xF0000000; 2420 } 2421 set_register(rt, alu_out); 2422 if (instr->Bit(0)) { // RC bit set 2423 SetCR0(static_cast<intptr_t>(alu_out)); 2424 } 2425 // todo - handle OE bit 2426 break; 2427 } 2428 case ADDEX: { 2429 int rt = instr->RTValue(); 2430 int ra = instr->RAValue(); 2431 int rb = instr->RBValue(); 2432 // int oe = instr->Bit(10); 2433 uintptr_t ra_val = get_register(ra); 2434 uintptr_t rb_val = get_register(rb); 2435 uintptr_t alu_out = ra_val + rb_val; 2436 if (special_reg_xer_ & 0x20000000) { 2437 alu_out += 1; 2438 } 2439 set_register(rt, alu_out); 2440 if (instr->Bit(0)) { // RC bit set 2441 SetCR0(static_cast<intptr_t>(alu_out)); 2442 } 2443 // todo - handle OE bit 2444 break; 2445 } 2446 case MULHWX: { 2447 int rt = instr->RTValue(); 2448 int ra = instr->RAValue(); 2449 int rb = instr->RBValue(); 2450 int32_t ra_val = (get_register(ra) & 0xFFFFFFFF); 2451 int32_t rb_val = (get_register(rb) & 0xFFFFFFFF); 2452 int64_t alu_out = (int64_t)ra_val * (int64_t)rb_val; 2453 alu_out >>= 32; 2454 set_register(rt, alu_out); 2455 if (instr->Bit(0)) { // RC bit set 2456 SetCR0(static_cast<intptr_t>(alu_out)); 2457 } 2458 break; 2459 } 2460 case MULHWUX: { 2461 int rt = instr->RTValue(); 2462 int ra = instr->RAValue(); 2463 int rb = instr->RBValue(); 2464 uint32_t ra_val = (get_register(ra) & 0xFFFFFFFF); 2465 uint32_t rb_val = (get_register(rb) & 0xFFFFFFFF); 2466 uint64_t alu_out = (uint64_t)ra_val * (uint64_t)rb_val; 2467 alu_out >>= 32; 2468 set_register(rt, alu_out); 2469 if (instr->Bit(0)) { // RC bit set 2470 SetCR0(static_cast<intptr_t>(alu_out)); 2471 } 2472 break; 2473 } 2474 case NEGX: { 2475 int rt = instr->RTValue(); 2476 int ra = instr->RAValue(); 2477 intptr_t ra_val = get_register(ra); 2478 intptr_t alu_out = 1 + ~ra_val; 2479 #if V8_TARGET_ARCH_PPC64 2480 intptr_t one = 1; // work-around gcc 2481 intptr_t kOverflowVal = (one << 63); 2482 #else 2483 intptr_t kOverflowVal = kMinInt; 2484 #endif 2485 set_register(rt, alu_out); 2486 if (instr->Bit(10)) { // OE bit set 2487 if (ra_val == kOverflowVal) { 2488 special_reg_xer_ |= 0xC0000000; // set SO,OV 2489 } else { 2490 special_reg_xer_ &= ~0x40000000; // clear OV 2491 } 2492 } 2493 if (instr->Bit(0)) { // RC bit set 2494 bool setSO = (special_reg_xer_ & 0x80000000); 2495 SetCR0(alu_out, setSO); 2496 } 2497 break; 2498 } 2499 case SLWX: { 2500 int rs = instr->RSValue(); 2501 int ra = instr->RAValue(); 2502 int rb = instr->RBValue(); 2503 uint32_t rs_val = get_register(rs); 2504 uintptr_t rb_val = get_register(rb) & 0x3F; 2505 uint32_t result = (rb_val > 31) ? 0 : rs_val << rb_val; 2506 set_register(ra, result); 2507 if (instr->Bit(0)) { // RC bit set 2508 SetCR0(result); 2509 } 2510 break; 2511 } 2512 #if V8_TARGET_ARCH_PPC64 2513 case SLDX: { 2514 int rs = instr->RSValue(); 2515 int ra = instr->RAValue(); 2516 int rb = instr->RBValue(); 2517 uintptr_t rs_val = get_register(rs); 2518 uintptr_t rb_val = get_register(rb) & 0x7F; 2519 uintptr_t result = (rb_val > 63) ? 0 : rs_val << rb_val; 2520 set_register(ra, result); 2521 if (instr->Bit(0)) { // RC bit set 2522 SetCR0(result); 2523 } 2524 break; 2525 } 2526 case MFVSRD: { 2527 DCHECK(!instr->Bit(0)); 2528 int frt = instr->RTValue(); 2529 int ra = instr->RAValue(); 2530 int64_t frt_val = get_d_register(frt); 2531 set_register(ra, frt_val); 2532 break; 2533 } 2534 case MFVSRWZ: { 2535 DCHECK(!instr->Bit(0)); 2536 int frt = instr->RTValue(); 2537 int ra = instr->RAValue(); 2538 int64_t frt_val = get_d_register(frt); 2539 set_register(ra, static_cast<uint32_t>(frt_val)); 2540 break; 2541 } 2542 case MTVSRD: { 2543 DCHECK(!instr->Bit(0)); 2544 int frt = instr->RTValue(); 2545 int ra = instr->RAValue(); 2546 int64_t ra_val = get_register(ra); 2547 set_d_register(frt, ra_val); 2548 break; 2549 } 2550 case MTVSRWA: { 2551 DCHECK(!instr->Bit(0)); 2552 int frt = instr->RTValue(); 2553 int ra = instr->RAValue(); 2554 int64_t ra_val = static_cast<int32_t>(get_register(ra)); 2555 set_d_register(frt, ra_val); 2556 break; 2557 } 2558 case MTVSRWZ: { 2559 DCHECK(!instr->Bit(0)); 2560 int frt = instr->RTValue(); 2561 int ra = instr->RAValue(); 2562 uint64_t ra_val = static_cast<uint32_t>(get_register(ra)); 2563 set_d_register(frt, ra_val); 2564 break; 2565 } 2566 #endif 2567 case CNTLZWX: { 2568 int rs = instr->RSValue(); 2569 int ra = instr->RAValue(); 2570 uintptr_t rs_val = get_register(rs); 2571 uintptr_t count = 0; 2572 int n = 0; 2573 uintptr_t bit = 0x80000000; 2574 for (; n < 32; n++) { 2575 if (bit & rs_val) break; 2576 count++; 2577 bit >>= 1; 2578 } 2579 set_register(ra, count); 2580 if (instr->Bit(0)) { // RC Bit set 2581 int bf = 0; 2582 if (count > 0) { 2583 bf |= 0x40000000; 2584 } 2585 if (count == 0) { 2586 bf |= 0x20000000; 2587 } 2588 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf; 2589 } 2590 break; 2591 } 2592 #if V8_TARGET_ARCH_PPC64 2593 case CNTLZDX: { 2594 int rs = instr->RSValue(); 2595 int ra = instr->RAValue(); 2596 uintptr_t rs_val = get_register(rs); 2597 uintptr_t count = 0; 2598 int n = 0; 2599 uintptr_t bit = 0x8000000000000000UL; 2600 for (; n < 64; n++) { 2601 if (bit & rs_val) break; 2602 count++; 2603 bit >>= 1; 2604 } 2605 set_register(ra, count); 2606 if (instr->Bit(0)) { // RC Bit set 2607 int bf = 0; 2608 if (count > 0) { 2609 bf |= 0x40000000; 2610 } 2611 if (count == 0) { 2612 bf |= 0x20000000; 2613 } 2614 condition_reg_ = (condition_reg_ & ~0xF0000000) | bf; 2615 } 2616 break; 2617 } 2618 #endif 2619 case ANDX: { 2620 int rs = instr->RSValue(); 2621 int ra = instr->RAValue(); 2622 int rb = instr->RBValue(); 2623 intptr_t rs_val = get_register(rs); 2624 intptr_t rb_val = get_register(rb); 2625 intptr_t alu_out = rs_val & rb_val; 2626 set_register(ra, alu_out); 2627 if (instr->Bit(0)) { // RC Bit set 2628 SetCR0(alu_out); 2629 } 2630 break; 2631 } 2632 case ANDCX: { 2633 int rs = instr->RSValue(); 2634 int ra = instr->RAValue(); 2635 int rb = instr->RBValue(); 2636 intptr_t rs_val = get_register(rs); 2637 intptr_t rb_val = get_register(rb); 2638 intptr_t alu_out = rs_val & ~rb_val; 2639 set_register(ra, alu_out); 2640 if (instr->Bit(0)) { // RC Bit set 2641 SetCR0(alu_out); 2642 } 2643 break; 2644 } 2645 case CMPL: { 2646 int ra = instr->RAValue(); 2647 int rb = instr->RBValue(); 2648 int cr = instr->Bits(25, 23); 2649 uint32_t bf = 0; 2650 #if V8_TARGET_ARCH_PPC64 2651 int L = instr->Bit(21); 2652 if (L) { 2653 #endif 2654 uintptr_t ra_val = get_register(ra); 2655 uintptr_t rb_val = get_register(rb); 2656 if (ra_val < rb_val) { 2657 bf |= 0x80000000; 2658 } 2659 if (ra_val > rb_val) { 2660 bf |= 0x40000000; 2661 } 2662 if (ra_val == rb_val) { 2663 bf |= 0x20000000; 2664 } 2665 #if V8_TARGET_ARCH_PPC64 2666 } else { 2667 uint32_t ra_val = get_register(ra); 2668 uint32_t rb_val = get_register(rb); 2669 if (ra_val < rb_val) { 2670 bf |= 0x80000000; 2671 } 2672 if (ra_val > rb_val) { 2673 bf |= 0x40000000; 2674 } 2675 if (ra_val == rb_val) { 2676 bf |= 0x20000000; 2677 } 2678 } 2679 #endif 2680 uint32_t condition_mask = 0xF0000000U >> (cr * 4); 2681 uint32_t condition = bf >> (cr * 4); 2682 condition_reg_ = (condition_reg_ & ~condition_mask) | condition; 2683 break; 2684 } 2685 case SUBFX: { 2686 int rt = instr->RTValue(); 2687 int ra = instr->RAValue(); 2688 int rb = instr->RBValue(); 2689 // int oe = instr->Bit(10); 2690 intptr_t ra_val = get_register(ra); 2691 intptr_t rb_val = get_register(rb); 2692 intptr_t alu_out = rb_val - ra_val; 2693 // todo - figure out underflow 2694 set_register(rt, alu_out); 2695 if (instr->Bit(0)) { // RC Bit set 2696 SetCR0(alu_out); 2697 } 2698 // todo - handle OE bit 2699 break; 2700 } 2701 case ADDZEX: { 2702 int rt = instr->RTValue(); 2703 int ra = instr->RAValue(); 2704 intptr_t ra_val = get_register(ra); 2705 if (special_reg_xer_ & 0x20000000) { 2706 ra_val += 1; 2707 } 2708 set_register(rt, ra_val); 2709 if (instr->Bit(0)) { // RC bit set 2710 SetCR0(ra_val); 2711 } 2712 // todo - handle OE bit 2713 break; 2714 } 2715 case NORX: { 2716 int rs = instr->RSValue(); 2717 int ra = instr->RAValue(); 2718 int rb = instr->RBValue(); 2719 intptr_t rs_val = get_register(rs); 2720 intptr_t rb_val = get_register(rb); 2721 intptr_t alu_out = ~(rs_val | rb_val); 2722 set_register(ra, alu_out); 2723 if (instr->Bit(0)) { // RC bit set 2724 SetCR0(alu_out); 2725 } 2726 break; 2727 } 2728 case MULLW: { 2729 int rt = instr->RTValue(); 2730 int ra = instr->RAValue(); 2731 int rb = instr->RBValue(); 2732 int32_t ra_val = (get_register(ra) & 0xFFFFFFFF); 2733 int32_t rb_val = (get_register(rb) & 0xFFFFFFFF); 2734 int32_t alu_out = ra_val * rb_val; 2735 set_register(rt, alu_out); 2736 if (instr->Bit(0)) { // RC bit set 2737 SetCR0(alu_out); 2738 } 2739 // todo - handle OE bit 2740 break; 2741 } 2742 #if V8_TARGET_ARCH_PPC64 2743 case MULLD: { 2744 int rt = instr->RTValue(); 2745 int ra = instr->RAValue(); 2746 int rb = instr->RBValue(); 2747 int64_t ra_val = get_register(ra); 2748 int64_t rb_val = get_register(rb); 2749 int64_t alu_out = ra_val * rb_val; 2750 set_register(rt, alu_out); 2751 if (instr->Bit(0)) { // RC bit set 2752 SetCR0(alu_out); 2753 } 2754 // todo - handle OE bit 2755 break; 2756 } 2757 #endif 2758 case DIVW: { 2759 int rt = instr->RTValue(); 2760 int ra = instr->RAValue(); 2761 int rb = instr->RBValue(); 2762 int32_t ra_val = get_register(ra); 2763 int32_t rb_val = get_register(rb); 2764 bool overflow = (ra_val == kMinInt && rb_val == -1); 2765 // result is undefined if divisor is zero or if operation 2766 // is 0x80000000 / -1. 2767 int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val / rb_val; 2768 set_register(rt, alu_out); 2769 if (instr->Bit(10)) { // OE bit set 2770 if (overflow) { 2771 special_reg_xer_ |= 0xC0000000; // set SO,OV 2772 } else { 2773 special_reg_xer_ &= ~0x40000000; // clear OV 2774 } 2775 } 2776 if (instr->Bit(0)) { // RC bit set 2777 bool setSO = (special_reg_xer_ & 0x80000000); 2778 SetCR0(alu_out, setSO); 2779 } 2780 break; 2781 } 2782 case DIVWU: { 2783 int rt = instr->RTValue(); 2784 int ra = instr->RAValue(); 2785 int rb = instr->RBValue(); 2786 uint32_t ra_val = get_register(ra); 2787 uint32_t rb_val = get_register(rb); 2788 bool overflow = (rb_val == 0); 2789 // result is undefined if divisor is zero 2790 uint32_t alu_out = (overflow) ? -1 : ra_val / rb_val; 2791 set_register(rt, alu_out); 2792 if (instr->Bit(10)) { // OE bit set 2793 if (overflow) { 2794 special_reg_xer_ |= 0xC0000000; // set SO,OV 2795 } else { 2796 special_reg_xer_ &= ~0x40000000; // clear OV 2797 } 2798 } 2799 if (instr->Bit(0)) { // RC bit set 2800 bool setSO = (special_reg_xer_ & 0x80000000); 2801 SetCR0(alu_out, setSO); 2802 } 2803 break; 2804 } 2805 #if V8_TARGET_ARCH_PPC64 2806 case DIVD: { 2807 int rt = instr->RTValue(); 2808 int ra = instr->RAValue(); 2809 int rb = instr->RBValue(); 2810 int64_t ra_val = get_register(ra); 2811 int64_t rb_val = get_register(rb); 2812 int64_t one = 1; // work-around gcc 2813 int64_t kMinLongLong = (one << 63); 2814 // result is undefined if divisor is zero or if operation 2815 // is 0x80000000_00000000 / -1. 2816 int64_t alu_out = 2817 (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1)) 2818 ? -1 2819 : ra_val / rb_val; 2820 set_register(rt, alu_out); 2821 if (instr->Bit(0)) { // RC bit set 2822 SetCR0(alu_out); 2823 } 2824 // todo - handle OE bit 2825 break; 2826 } 2827 case DIVDU: { 2828 int rt = instr->RTValue(); 2829 int ra = instr->RAValue(); 2830 int rb = instr->RBValue(); 2831 uint64_t ra_val = get_register(ra); 2832 uint64_t rb_val = get_register(rb); 2833 // result is undefined if divisor is zero 2834 uint64_t alu_out = (rb_val == 0) ? -1 : ra_val / rb_val; 2835 set_register(rt, alu_out); 2836 if (instr->Bit(0)) { // RC bit set 2837 SetCR0(alu_out); 2838 } 2839 // todo - handle OE bit 2840 break; 2841 } 2842 #endif 2843 case ADDX: { 2844 int rt = instr->RTValue(); 2845 int ra = instr->RAValue(); 2846 int rb = instr->RBValue(); 2847 // int oe = instr->Bit(10); 2848 intptr_t ra_val = get_register(ra); 2849 intptr_t rb_val = get_register(rb); 2850 intptr_t alu_out = ra_val + rb_val; 2851 set_register(rt, alu_out); 2852 if (instr->Bit(0)) { // RC bit set 2853 SetCR0(alu_out); 2854 } 2855 // todo - handle OE bit 2856 break; 2857 } 2858 case XORX: { 2859 int rs = instr->RSValue(); 2860 int ra = instr->RAValue(); 2861 int rb = instr->RBValue(); 2862 intptr_t rs_val = get_register(rs); 2863 intptr_t rb_val = get_register(rb); 2864 intptr_t alu_out = rs_val ^ rb_val; 2865 set_register(ra, alu_out); 2866 if (instr->Bit(0)) { // RC bit set 2867 SetCR0(alu_out); 2868 } 2869 break; 2870 } 2871 case ORX: { 2872 int rs = instr->RSValue(); 2873 int ra = instr->RAValue(); 2874 int rb = instr->RBValue(); 2875 intptr_t rs_val = get_register(rs); 2876 intptr_t rb_val = get_register(rb); 2877 intptr_t alu_out = rs_val | rb_val; 2878 set_register(ra, alu_out); 2879 if (instr->Bit(0)) { // RC bit set 2880 SetCR0(alu_out); 2881 } 2882 break; 2883 } 2884 case ORC: { 2885 int rs = instr->RSValue(); 2886 int ra = instr->RAValue(); 2887 int rb = instr->RBValue(); 2888 intptr_t rs_val = get_register(rs); 2889 intptr_t rb_val = get_register(rb); 2890 intptr_t alu_out = rs_val | ~rb_val; 2891 set_register(ra, alu_out); 2892 if (instr->Bit(0)) { // RC bit set 2893 SetCR0(alu_out); 2894 } 2895 break; 2896 } 2897 case MFSPR: { 2898 int rt = instr->RTValue(); 2899 int spr = instr->Bits(20, 11); 2900 if (spr != 256) { 2901 UNIMPLEMENTED(); // Only LRLR supported 2902 } 2903 set_register(rt, special_reg_lr_); 2904 break; 2905 } 2906 case MTSPR: { 2907 int rt = instr->RTValue(); 2908 intptr_t rt_val = get_register(rt); 2909 int spr = instr->Bits(20, 11); 2910 if (spr == 256) { 2911 special_reg_lr_ = rt_val; 2912 } else if (spr == 288) { 2913 special_reg_ctr_ = rt_val; 2914 } else if (spr == 32) { 2915 special_reg_xer_ = rt_val; 2916 } else { 2917 UNIMPLEMENTED(); // Only LR supported 2918 } 2919 break; 2920 } 2921 case MFCR: { 2922 int rt = instr->RTValue(); 2923 set_register(rt, condition_reg_); 2924 break; 2925 } 2926 case STWUX: 2927 case STWX: { 2928 int rs = instr->RSValue(); 2929 int ra = instr->RAValue(); 2930 int rb = instr->RBValue(); 2931 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2932 int32_t rs_val = get_register(rs); 2933 intptr_t rb_val = get_register(rb); 2934 WriteW(ra_val + rb_val, rs_val, instr); 2935 if (opcode == STWUX) { 2936 DCHECK_NE(ra, 0); 2937 set_register(ra, ra_val + rb_val); 2938 } 2939 break; 2940 } 2941 case STBUX: 2942 case STBX: { 2943 int rs = instr->RSValue(); 2944 int ra = instr->RAValue(); 2945 int rb = instr->RBValue(); 2946 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2947 int8_t rs_val = get_register(rs); 2948 intptr_t rb_val = get_register(rb); 2949 WriteB(ra_val + rb_val, rs_val); 2950 if (opcode == STBUX) { 2951 DCHECK_NE(ra, 0); 2952 set_register(ra, ra_val + rb_val); 2953 } 2954 break; 2955 } 2956 case STHUX: 2957 case STHX: { 2958 int rs = instr->RSValue(); 2959 int ra = instr->RAValue(); 2960 int rb = instr->RBValue(); 2961 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2962 int16_t rs_val = get_register(rs); 2963 intptr_t rb_val = get_register(rb); 2964 WriteH(ra_val + rb_val, rs_val, instr); 2965 if (opcode == STHUX) { 2966 DCHECK_NE(ra, 0); 2967 set_register(ra, ra_val + rb_val); 2968 } 2969 break; 2970 } 2971 case LWZX: 2972 case LWZUX: { 2973 int rt = instr->RTValue(); 2974 int ra = instr->RAValue(); 2975 int rb = instr->RBValue(); 2976 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2977 intptr_t rb_val = get_register(rb); 2978 set_register(rt, ReadWU(ra_val + rb_val, instr)); 2979 if (opcode == LWZUX) { 2980 DCHECK(ra != 0 && ra != rt); 2981 set_register(ra, ra_val + rb_val); 2982 } 2983 break; 2984 } 2985 #if V8_TARGET_ARCH_PPC64 2986 case LWAX: { 2987 int rt = instr->RTValue(); 2988 int ra = instr->RAValue(); 2989 int rb = instr->RBValue(); 2990 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 2991 intptr_t rb_val = get_register(rb); 2992 set_register(rt, ReadW(ra_val + rb_val, instr)); 2993 break; 2994 } 2995 case LDX: 2996 case LDUX: { 2997 int rt = instr->RTValue(); 2998 int ra = instr->RAValue(); 2999 int rb = instr->RBValue(); 3000 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3001 intptr_t rb_val = get_register(rb); 3002 intptr_t* result = ReadDW(ra_val + rb_val); 3003 set_register(rt, *result); 3004 if (opcode == LDUX) { 3005 DCHECK(ra != 0 && ra != rt); 3006 set_register(ra, ra_val + rb_val); 3007 } 3008 break; 3009 } 3010 case STDX: 3011 case STDUX: { 3012 int rs = instr->RSValue(); 3013 int ra = instr->RAValue(); 3014 int rb = instr->RBValue(); 3015 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3016 intptr_t rs_val = get_register(rs); 3017 intptr_t rb_val = get_register(rb); 3018 WriteDW(ra_val + rb_val, rs_val); 3019 if (opcode == STDUX) { 3020 DCHECK_NE(ra, 0); 3021 set_register(ra, ra_val + rb_val); 3022 } 3023 break; 3024 } 3025 #endif 3026 case LBZX: 3027 case LBZUX: { 3028 int rt = instr->RTValue(); 3029 int ra = instr->RAValue(); 3030 int rb = instr->RBValue(); 3031 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3032 intptr_t rb_val = get_register(rb); 3033 set_register(rt, ReadBU(ra_val + rb_val) & 0xFF); 3034 if (opcode == LBZUX) { 3035 DCHECK(ra != 0 && ra != rt); 3036 set_register(ra, ra_val + rb_val); 3037 } 3038 break; 3039 } 3040 case LHZX: 3041 case LHZUX: { 3042 int rt = instr->RTValue(); 3043 int ra = instr->RAValue(); 3044 int rb = instr->RBValue(); 3045 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3046 intptr_t rb_val = get_register(rb); 3047 set_register(rt, ReadHU(ra_val + rb_val, instr) & 0xFFFF); 3048 if (opcode == LHZUX) { 3049 DCHECK(ra != 0 && ra != rt); 3050 set_register(ra, ra_val + rb_val); 3051 } 3052 break; 3053 } 3054 case LHAX: { 3055 int rt = instr->RTValue(); 3056 int ra = instr->RAValue(); 3057 int rb = instr->RBValue(); 3058 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3059 intptr_t rb_val = get_register(rb); 3060 set_register(rt, ReadH(ra_val + rb_val, instr)); 3061 break; 3062 } 3063 case LBARX: { 3064 int rt = instr->RTValue(); 3065 int ra = instr->RAValue(); 3066 int rb = instr->RBValue(); 3067 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3068 intptr_t rb_val = get_register(rb); 3069 set_register(rt, ReadExBU(ra_val + rb_val) & 0xFF); 3070 break; 3071 } 3072 case LHARX: { 3073 int rt = instr->RTValue(); 3074 int ra = instr->RAValue(); 3075 int rb = instr->RBValue(); 3076 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3077 intptr_t rb_val = get_register(rb); 3078 set_register(rt, ReadExHU(ra_val + rb_val, instr)); 3079 break; 3080 } 3081 case LWARX: { 3082 int rt = instr->RTValue(); 3083 int ra = instr->RAValue(); 3084 int rb = instr->RBValue(); 3085 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3086 intptr_t rb_val = get_register(rb); 3087 set_register(rt, ReadExWU(ra_val + rb_val, instr)); 3088 break; 3089 } 3090 case DCBF: { 3091 // todo - simulate dcbf 3092 break; 3093 } 3094 case ISEL: { 3095 int rt = instr->RTValue(); 3096 int ra = instr->RAValue(); 3097 int rb = instr->RBValue(); 3098 int condition_bit = instr->RCValue(); 3099 int condition_mask = 0x80000000 >> condition_bit; 3100 intptr_t ra_val = (ra == 0) ? 0 : get_register(ra); 3101 intptr_t rb_val = get_register(rb); 3102 intptr_t value = (condition_reg_ & condition_mask) ? ra_val : rb_val; 3103 set_register(rt, value); 3104 break; 3105 } 3106 3107 case STBU: 3108 case STB: { 3109 int ra = instr->RAValue(); 3110 int rs = instr->RSValue(); 3111 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3112 int8_t rs_val = get_register(rs); 3113 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3114 WriteB(ra_val + offset, rs_val); 3115 if (opcode == STBU) { 3116 DCHECK_NE(ra, 0); 3117 set_register(ra, ra_val + offset); 3118 } 3119 break; 3120 } 3121 3122 case LHZU: 3123 case LHZ: { 3124 int ra = instr->RAValue(); 3125 int rt = instr->RTValue(); 3126 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3127 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3128 uintptr_t result = ReadHU(ra_val + offset, instr) & 0xFFFF; 3129 set_register(rt, result); 3130 if (opcode == LHZU) { 3131 set_register(ra, ra_val + offset); 3132 } 3133 break; 3134 } 3135 3136 case LHA: 3137 case LHAU: { 3138 int ra = instr->RAValue(); 3139 int rt = instr->RTValue(); 3140 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3141 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3142 intptr_t result = ReadH(ra_val + offset, instr); 3143 set_register(rt, result); 3144 if (opcode == LHAU) { 3145 set_register(ra, ra_val + offset); 3146 } 3147 break; 3148 } 3149 3150 case STHU: 3151 case STH: { 3152 int ra = instr->RAValue(); 3153 int rs = instr->RSValue(); 3154 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3155 int16_t rs_val = get_register(rs); 3156 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3157 WriteH(ra_val + offset, rs_val, instr); 3158 if (opcode == STHU) { 3159 DCHECK_NE(ra, 0); 3160 set_register(ra, ra_val + offset); 3161 } 3162 break; 3163 } 3164 3165 case LMW: 3166 case STMW: { 3167 UNIMPLEMENTED(); 3168 break; 3169 } 3170 3171 case LFSU: 3172 case LFS: { 3173 int frt = instr->RTValue(); 3174 int ra = instr->RAValue(); 3175 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3176 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3177 int32_t val = ReadW(ra_val + offset, instr); 3178 float* fptr = reinterpret_cast<float*>(&val); 3179 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 3180 // Conversion using double changes sNan to qNan on ia32/x64 3181 if ((val & 0x7F800000) == 0x7F800000) { 3182 int64_t dval = static_cast<int64_t>(val); 3183 dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) | 3184 ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) | 0x0; 3185 set_d_register(frt, dval); 3186 } else { 3187 set_d_register_from_double(frt, static_cast<double>(*fptr)); 3188 } 3189 #else 3190 set_d_register_from_double(frt, static_cast<double>(*fptr)); 3191 #endif 3192 if (opcode == LFSU) { 3193 DCHECK_NE(ra, 0); 3194 set_register(ra, ra_val + offset); 3195 } 3196 break; 3197 } 3198 3199 case LFDU: 3200 case LFD: { 3201 int frt = instr->RTValue(); 3202 int ra = instr->RAValue(); 3203 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3204 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3205 int64_t* dptr = reinterpret_cast<int64_t*>(ReadDW(ra_val + offset)); 3206 set_d_register(frt, *dptr); 3207 if (opcode == LFDU) { 3208 DCHECK_NE(ra, 0); 3209 set_register(ra, ra_val + offset); 3210 } 3211 break; 3212 } 3213 3214 case STFSU: V8_FALLTHROUGH; 3215 case STFS: { 3216 int frs = instr->RSValue(); 3217 int ra = instr->RAValue(); 3218 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3219 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3220 float frs_val = static_cast<float>(get_double_from_d_register(frs)); 3221 int32_t* p; 3222 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 3223 // Conversion using double changes sNan to qNan on ia32/x64 3224 int32_t sval = 0; 3225 int64_t dval = get_d_register(frs); 3226 if ((dval & 0x7FF0000000000000) == 0x7FF0000000000000) { 3227 sval = ((dval & 0xC000000000000000) >> 32) | 3228 ((dval & 0x07FFFFFFE0000000) >> 29); 3229 p = &sval; 3230 } else { 3231 p = reinterpret_cast<int32_t*>(&frs_val); 3232 } 3233 #else 3234 p = reinterpret_cast<int32_t*>(&frs_val); 3235 #endif 3236 WriteW(ra_val + offset, *p, instr); 3237 if (opcode == STFSU) { 3238 DCHECK_NE(ra, 0); 3239 set_register(ra, ra_val + offset); 3240 } 3241 break; 3242 } 3243 case STFDU: 3244 case STFD: { 3245 int frs = instr->RSValue(); 3246 int ra = instr->RAValue(); 3247 int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0)); 3248 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3249 int64_t frs_val = get_d_register(frs); 3250 WriteDW(ra_val + offset, frs_val); 3251 if (opcode == STFDU) { 3252 DCHECK_NE(ra, 0); 3253 set_register(ra, ra_val + offset); 3254 } 3255 break; 3256 } 3257 3258 case FCFIDS: { 3259 // fcfids 3260 int frt = instr->RTValue(); 3261 int frb = instr->RBValue(); 3262 int64_t frb_val = get_d_register(frb); 3263 double frt_val = static_cast<float>(frb_val); 3264 set_d_register_from_double(frt, frt_val); 3265 return; 3266 } 3267 case FCFIDUS: { 3268 // fcfidus 3269 int frt = instr->RTValue(); 3270 int frb = instr->RBValue(); 3271 uint64_t frb_val = get_d_register(frb); 3272 double frt_val = static_cast<float>(frb_val); 3273 set_d_register_from_double(frt, frt_val); 3274 return; 3275 } 3276 3277 case FDIV: { 3278 int frt = instr->RTValue(); 3279 int fra = instr->RAValue(); 3280 int frb = instr->RBValue(); 3281 double fra_val = get_double_from_d_register(fra); 3282 double frb_val = get_double_from_d_register(frb); 3283 double frt_val = fra_val / frb_val; 3284 set_d_register_from_double(frt, frt_val); 3285 return; 3286 } 3287 case FSUB: { 3288 int frt = instr->RTValue(); 3289 int fra = instr->RAValue(); 3290 int frb = instr->RBValue(); 3291 double fra_val = get_double_from_d_register(fra); 3292 double frb_val = get_double_from_d_register(frb); 3293 double frt_val = fra_val - frb_val; 3294 set_d_register_from_double(frt, frt_val); 3295 return; 3296 } 3297 case FADD: { 3298 int frt = instr->RTValue(); 3299 int fra = instr->RAValue(); 3300 int frb = instr->RBValue(); 3301 double fra_val = get_double_from_d_register(fra); 3302 double frb_val = get_double_from_d_register(frb); 3303 double frt_val = fra_val + frb_val; 3304 set_d_register_from_double(frt, frt_val); 3305 return; 3306 } 3307 case FSQRT: { 3308 lazily_initialize_fast_sqrt(isolate_); 3309 int frt = instr->RTValue(); 3310 int frb = instr->RBValue(); 3311 double frb_val = get_double_from_d_register(frb); 3312 double frt_val = fast_sqrt(frb_val, isolate_); 3313 set_d_register_from_double(frt, frt_val); 3314 return; 3315 } 3316 case FSEL: { 3317 int frt = instr->RTValue(); 3318 int fra = instr->RAValue(); 3319 int frb = instr->RBValue(); 3320 int frc = instr->RCValue(); 3321 double fra_val = get_double_from_d_register(fra); 3322 double frb_val = get_double_from_d_register(frb); 3323 double frc_val = get_double_from_d_register(frc); 3324 double frt_val = ((fra_val >= 0.0) ? frc_val : frb_val); 3325 set_d_register_from_double(frt, frt_val); 3326 return; 3327 } 3328 case FMUL: { 3329 int frt = instr->RTValue(); 3330 int fra = instr->RAValue(); 3331 int frc = instr->RCValue(); 3332 double fra_val = get_double_from_d_register(fra); 3333 double frc_val = get_double_from_d_register(frc); 3334 double frt_val = fra_val * frc_val; 3335 set_d_register_from_double(frt, frt_val); 3336 return; 3337 } 3338 case FMSUB: { 3339 int frt = instr->RTValue(); 3340 int fra = instr->RAValue(); 3341 int frb = instr->RBValue(); 3342 int frc = instr->RCValue(); 3343 double fra_val = get_double_from_d_register(fra); 3344 double frb_val = get_double_from_d_register(frb); 3345 double frc_val = get_double_from_d_register(frc); 3346 double frt_val = (fra_val * frc_val) - frb_val; 3347 set_d_register_from_double(frt, frt_val); 3348 return; 3349 } 3350 case FMADD: { 3351 int frt = instr->RTValue(); 3352 int fra = instr->RAValue(); 3353 int frb = instr->RBValue(); 3354 int frc = instr->RCValue(); 3355 double fra_val = get_double_from_d_register(fra); 3356 double frb_val = get_double_from_d_register(frb); 3357 double frc_val = get_double_from_d_register(frc); 3358 double frt_val = (fra_val * frc_val) + frb_val; 3359 set_d_register_from_double(frt, frt_val); 3360 return; 3361 } 3362 case FCMPU: { 3363 int fra = instr->RAValue(); 3364 int frb = instr->RBValue(); 3365 double fra_val = get_double_from_d_register(fra); 3366 double frb_val = get_double_from_d_register(frb); 3367 int cr = instr->Bits(25, 23); 3368 int bf = 0; 3369 if (fra_val < frb_val) { 3370 bf |= 0x80000000; 3371 } 3372 if (fra_val > frb_val) { 3373 bf |= 0x40000000; 3374 } 3375 if (fra_val == frb_val) { 3376 bf |= 0x20000000; 3377 } 3378 if (std::isunordered(fra_val, frb_val)) { 3379 bf |= 0x10000000; 3380 } 3381 int condition_mask = 0xF0000000 >> (cr * 4); 3382 int condition = bf >> (cr * 4); 3383 condition_reg_ = (condition_reg_ & ~condition_mask) | condition; 3384 return; 3385 } 3386 case FRIN: { 3387 int frt = instr->RTValue(); 3388 int frb = instr->RBValue(); 3389 double frb_val = get_double_from_d_register(frb); 3390 double frt_val = std::round(frb_val); 3391 set_d_register_from_double(frt, frt_val); 3392 if (instr->Bit(0)) { // RC bit set 3393 // UNIMPLEMENTED(); 3394 } 3395 return; 3396 } 3397 case FRIZ: { 3398 int frt = instr->RTValue(); 3399 int frb = instr->RBValue(); 3400 double frb_val = get_double_from_d_register(frb); 3401 double frt_val = std::trunc(frb_val); 3402 set_d_register_from_double(frt, frt_val); 3403 if (instr->Bit(0)) { // RC bit set 3404 // UNIMPLEMENTED(); 3405 } 3406 return; 3407 } 3408 case FRIP: { 3409 int frt = instr->RTValue(); 3410 int frb = instr->RBValue(); 3411 double frb_val = get_double_from_d_register(frb); 3412 double frt_val = std::ceil(frb_val); 3413 set_d_register_from_double(frt, frt_val); 3414 if (instr->Bit(0)) { // RC bit set 3415 // UNIMPLEMENTED(); 3416 } 3417 return; 3418 } 3419 case FRIM: { 3420 int frt = instr->RTValue(); 3421 int frb = instr->RBValue(); 3422 double frb_val = get_double_from_d_register(frb); 3423 double frt_val = std::floor(frb_val); 3424 set_d_register_from_double(frt, frt_val); 3425 if (instr->Bit(0)) { // RC bit set 3426 // UNIMPLEMENTED(); 3427 } 3428 return; 3429 } 3430 case FRSP: { 3431 int frt = instr->RTValue(); 3432 int frb = instr->RBValue(); 3433 // frsp round 8-byte double-precision value to 3434 // single-precision value 3435 double frb_val = get_double_from_d_register(frb); 3436 double frt_val = static_cast<float>(frb_val); 3437 set_d_register_from_double(frt, frt_val); 3438 if (instr->Bit(0)) { // RC bit set 3439 // UNIMPLEMENTED(); 3440 } 3441 return; 3442 } 3443 case FCFID: { 3444 int frt = instr->RTValue(); 3445 int frb = instr->RBValue(); 3446 int64_t frb_val = get_d_register(frb); 3447 double frt_val = static_cast<double>(frb_val); 3448 set_d_register_from_double(frt, frt_val); 3449 return; 3450 } 3451 case FCFIDU: { 3452 int frt = instr->RTValue(); 3453 int frb = instr->RBValue(); 3454 uint64_t frb_val = get_d_register(frb); 3455 double frt_val = static_cast<double>(frb_val); 3456 set_d_register_from_double(frt, frt_val); 3457 return; 3458 } 3459 case FCTID: 3460 case FCTIDZ: { 3461 int frt = instr->RTValue(); 3462 int frb = instr->RBValue(); 3463 double frb_val = get_double_from_d_register(frb); 3464 int mode = (opcode == FCTIDZ) ? kRoundToZero 3465 : (fp_condition_reg_ & kFPRoundingModeMask); 3466 int64_t frt_val; 3467 int64_t one = 1; // work-around gcc 3468 int64_t kMinVal = (one << 63); 3469 int64_t kMaxVal = kMinVal - 1; 3470 bool invalid_convert = false; 3471 3472 if (std::isnan(frb_val)) { 3473 frt_val = kMinVal; 3474 invalid_convert = true; 3475 } else { 3476 switch (mode) { 3477 case kRoundToZero: 3478 frb_val = std::trunc(frb_val); 3479 break; 3480 case kRoundToPlusInf: 3481 frb_val = std::ceil(frb_val); 3482 break; 3483 case kRoundToMinusInf: 3484 frb_val = std::floor(frb_val); 3485 break; 3486 default: 3487 UNIMPLEMENTED(); // Not used by V8. 3488 break; 3489 } 3490 if (frb_val < static_cast<double>(kMinVal)) { 3491 frt_val = kMinVal; 3492 invalid_convert = true; 3493 } else if (frb_val >= static_cast<double>(kMaxVal)) { 3494 frt_val = kMaxVal; 3495 invalid_convert = true; 3496 } else { 3497 frt_val = (int64_t)frb_val; 3498 } 3499 } 3500 set_d_register(frt, frt_val); 3501 if (invalid_convert) SetFPSCR(VXCVI); 3502 return; 3503 } 3504 case FCTIDU: 3505 case FCTIDUZ: { 3506 int frt = instr->RTValue(); 3507 int frb = instr->RBValue(); 3508 double frb_val = get_double_from_d_register(frb); 3509 int mode = (opcode == FCTIDUZ) 3510 ? kRoundToZero 3511 : (fp_condition_reg_ & kFPRoundingModeMask); 3512 uint64_t frt_val; 3513 uint64_t kMinVal = 0; 3514 uint64_t kMaxVal = kMinVal - 1; 3515 bool invalid_convert = false; 3516 3517 if (std::isnan(frb_val)) { 3518 frt_val = kMinVal; 3519 invalid_convert = true; 3520 } else { 3521 switch (mode) { 3522 case kRoundToZero: 3523 frb_val = std::trunc(frb_val); 3524 break; 3525 case kRoundToPlusInf: 3526 frb_val = std::ceil(frb_val); 3527 break; 3528 case kRoundToMinusInf: 3529 frb_val = std::floor(frb_val); 3530 break; 3531 default: 3532 UNIMPLEMENTED(); // Not used by V8. 3533 break; 3534 } 3535 if (frb_val < static_cast<double>(kMinVal)) { 3536 frt_val = kMinVal; 3537 invalid_convert = true; 3538 } else if (frb_val >= static_cast<double>(kMaxVal)) { 3539 frt_val = kMaxVal; 3540 invalid_convert = true; 3541 } else { 3542 frt_val = (uint64_t)frb_val; 3543 } 3544 } 3545 set_d_register(frt, frt_val); 3546 if (invalid_convert) SetFPSCR(VXCVI); 3547 return; 3548 } 3549 case FCTIW: 3550 case FCTIWZ: { 3551 int frt = instr->RTValue(); 3552 int frb = instr->RBValue(); 3553 double frb_val = get_double_from_d_register(frb); 3554 int mode = (opcode == FCTIWZ) ? kRoundToZero 3555 : (fp_condition_reg_ & kFPRoundingModeMask); 3556 int64_t frt_val; 3557 int64_t kMinVal = kMinInt; 3558 int64_t kMaxVal = kMaxInt; 3559 3560 if (std::isnan(frb_val)) { 3561 frt_val = kMinVal; 3562 } else { 3563 switch (mode) { 3564 case kRoundToZero: 3565 frb_val = std::trunc(frb_val); 3566 break; 3567 case kRoundToPlusInf: 3568 frb_val = std::ceil(frb_val); 3569 break; 3570 case kRoundToMinusInf: 3571 frb_val = std::floor(frb_val); 3572 break; 3573 case kRoundToNearest: { 3574 double orig = frb_val; 3575 frb_val = lround(frb_val); 3576 // Round to even if exactly halfway. (lround rounds up) 3577 if (std::fabs(frb_val - orig) == 0.5 && ((int64_t)frb_val % 2)) { 3578 frb_val += ((frb_val > 0) ? -1.0 : 1.0); 3579 } 3580 break; 3581 } 3582 default: 3583 UNIMPLEMENTED(); // Not used by V8. 3584 break; 3585 } 3586 if (frb_val < kMinVal) { 3587 frt_val = kMinVal; 3588 } else if (frb_val > kMaxVal) { 3589 frt_val = kMaxVal; 3590 } else { 3591 frt_val = (int64_t)frb_val; 3592 } 3593 } 3594 set_d_register(frt, frt_val); 3595 return; 3596 } 3597 case FNEG: { 3598 int frt = instr->RTValue(); 3599 int frb = instr->RBValue(); 3600 double frb_val = get_double_from_d_register(frb); 3601 double frt_val = -frb_val; 3602 set_d_register_from_double(frt, frt_val); 3603 return; 3604 } 3605 case FMR: { 3606 int frt = instr->RTValue(); 3607 int frb = instr->RBValue(); 3608 int64_t frb_val = get_d_register(frb); 3609 set_d_register(frt, frb_val); 3610 return; 3611 } 3612 case MTFSFI: { 3613 int bf = instr->Bits(25, 23); 3614 int imm = instr->Bits(15, 12); 3615 int fp_condition_mask = 0xF0000000 >> (bf * 4); 3616 fp_condition_reg_ &= ~fp_condition_mask; 3617 fp_condition_reg_ |= (imm << (28 - (bf * 4))); 3618 if (instr->Bit(0)) { // RC bit set 3619 condition_reg_ &= 0xF0FFFFFF; 3620 condition_reg_ |= (imm << 23); 3621 } 3622 return; 3623 } 3624 case MTFSF: { 3625 int frb = instr->RBValue(); 3626 int64_t frb_dval = get_d_register(frb); 3627 int32_t frb_ival = static_cast<int32_t>((frb_dval)&0xFFFFFFFF); 3628 int l = instr->Bits(25, 25); 3629 if (l == 1) { 3630 fp_condition_reg_ = frb_ival; 3631 } else { 3632 UNIMPLEMENTED(); 3633 } 3634 if (instr->Bit(0)) { // RC bit set 3635 UNIMPLEMENTED(); 3636 // int w = instr->Bits(16, 16); 3637 // int flm = instr->Bits(24, 17); 3638 } 3639 return; 3640 } 3641 case MFFS: { 3642 int frt = instr->RTValue(); 3643 int64_t lval = static_cast<int64_t>(fp_condition_reg_); 3644 set_d_register(frt, lval); 3645 return; 3646 } 3647 case MCRFS: { 3648 int bf = instr->Bits(25, 23); 3649 int bfa = instr->Bits(20, 18); 3650 int cr_shift = (7 - bf) * CRWIDTH; 3651 int fp_shift = (7 - bfa) * CRWIDTH; 3652 int field_val = (fp_condition_reg_ >> fp_shift) & 0xF; 3653 condition_reg_ &= ~(0x0F << cr_shift); 3654 condition_reg_ |= (field_val << cr_shift); 3655 // Clear copied exception bits 3656 switch (bfa) { 3657 case 5: 3658 ClearFPSCR(VXSOFT); 3659 ClearFPSCR(VXSQRT); 3660 ClearFPSCR(VXCVI); 3661 break; 3662 default: 3663 UNIMPLEMENTED(); 3664 break; 3665 } 3666 return; 3667 } 3668 case MTFSB0: { 3669 int bt = instr->Bits(25, 21); 3670 ClearFPSCR(bt); 3671 if (instr->Bit(0)) { // RC bit set 3672 UNIMPLEMENTED(); 3673 } 3674 return; 3675 } 3676 case MTFSB1: { 3677 int bt = instr->Bits(25, 21); 3678 SetFPSCR(bt); 3679 if (instr->Bit(0)) { // RC bit set 3680 UNIMPLEMENTED(); 3681 } 3682 return; 3683 } 3684 case FABS: { 3685 int frt = instr->RTValue(); 3686 int frb = instr->RBValue(); 3687 double frb_val = get_double_from_d_register(frb); 3688 double frt_val = std::fabs(frb_val); 3689 set_d_register_from_double(frt, frt_val); 3690 return; 3691 } 3692 3693 3694 #if V8_TARGET_ARCH_PPC64 3695 case RLDICL: { 3696 int ra = instr->RAValue(); 3697 int rs = instr->RSValue(); 3698 uintptr_t rs_val = get_register(rs); 3699 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5)); 3700 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5)); 3701 DCHECK(sh >= 0 && sh <= 63); 3702 DCHECK(mb >= 0 && mb <= 63); 3703 uintptr_t result = base::bits::RotateLeft64(rs_val, sh); 3704 uintptr_t mask = 0xFFFFFFFFFFFFFFFF >> mb; 3705 result &= mask; 3706 set_register(ra, result); 3707 if (instr->Bit(0)) { // RC bit set 3708 SetCR0(result); 3709 } 3710 return; 3711 } 3712 case RLDICR: { 3713 int ra = instr->RAValue(); 3714 int rs = instr->RSValue(); 3715 uintptr_t rs_val = get_register(rs); 3716 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5)); 3717 int me = (instr->Bits(10, 6) | (instr->Bit(5) << 5)); 3718 DCHECK(sh >= 0 && sh <= 63); 3719 DCHECK(me >= 0 && me <= 63); 3720 uintptr_t result = base::bits::RotateLeft64(rs_val, sh); 3721 uintptr_t mask = 0xFFFFFFFFFFFFFFFF << (63 - me); 3722 result &= mask; 3723 set_register(ra, result); 3724 if (instr->Bit(0)) { // RC bit set 3725 SetCR0(result); 3726 } 3727 return; 3728 } 3729 case RLDIC: { 3730 int ra = instr->RAValue(); 3731 int rs = instr->RSValue(); 3732 uintptr_t rs_val = get_register(rs); 3733 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5)); 3734 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5)); 3735 DCHECK(sh >= 0 && sh <= 63); 3736 DCHECK(mb >= 0 && mb <= 63); 3737 uintptr_t result = base::bits::RotateLeft64(rs_val, sh); 3738 uintptr_t mask = (0xFFFFFFFFFFFFFFFF >> mb) & (0xFFFFFFFFFFFFFFFF << sh); 3739 result &= mask; 3740 set_register(ra, result); 3741 if (instr->Bit(0)) { // RC bit set 3742 SetCR0(result); 3743 } 3744 return; 3745 } 3746 case RLDIMI: { 3747 int ra = instr->RAValue(); 3748 int rs = instr->RSValue(); 3749 uintptr_t rs_val = get_register(rs); 3750 intptr_t ra_val = get_register(ra); 3751 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5)); 3752 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5)); 3753 int me = 63 - sh; 3754 uintptr_t result = base::bits::RotateLeft64(rs_val, sh); 3755 uintptr_t mask = 0; 3756 if (mb < me + 1) { 3757 uintptr_t bit = 0x8000000000000000 >> mb; 3758 for (; mb <= me; mb++) { 3759 mask |= bit; 3760 bit >>= 1; 3761 } 3762 } else if (mb == me + 1) { 3763 mask = 0xFFFFFFFFFFFFFFFF; 3764 } else { // mb > me+1 3765 uintptr_t bit = 0x8000000000000000 >> (me + 1); // needs to be tested 3766 mask = 0xFFFFFFFFFFFFFFFF; 3767 for (; me < mb; me++) { 3768 mask ^= bit; 3769 bit >>= 1; 3770 } 3771 } 3772 result &= mask; 3773 ra_val &= ~mask; 3774 result |= ra_val; 3775 set_register(ra, result); 3776 if (instr->Bit(0)) { // RC bit set 3777 SetCR0(result); 3778 } 3779 return; 3780 } 3781 case RLDCL: { 3782 int ra = instr->RAValue(); 3783 int rs = instr->RSValue(); 3784 int rb = instr->RBValue(); 3785 uintptr_t rs_val = get_register(rs); 3786 uintptr_t rb_val = get_register(rb); 3787 int sh = (rb_val & 0x3F); 3788 int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5)); 3789 DCHECK(sh >= 0 && sh <= 63); 3790 DCHECK(mb >= 0 && mb <= 63); 3791 uintptr_t result = base::bits::RotateLeft64(rs_val, sh); 3792 uintptr_t mask = 0xFFFFFFFFFFFFFFFF >> mb; 3793 result &= mask; 3794 set_register(ra, result); 3795 if (instr->Bit(0)) { // RC bit set 3796 SetCR0(result); 3797 } 3798 return; 3799 } 3800 3801 case LD: 3802 case LDU: 3803 case LWA: { 3804 int ra = instr->RAValue(); 3805 int rt = instr->RTValue(); 3806 int64_t ra_val = ra == 0 ? 0 : get_register(ra); 3807 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3); 3808 switch (instr->Bits(1, 0)) { 3809 case 0: { // ld 3810 intptr_t* result = ReadDW(ra_val + offset); 3811 set_register(rt, *result); 3812 break; 3813 } 3814 case 1: { // ldu 3815 intptr_t* result = ReadDW(ra_val + offset); 3816 set_register(rt, *result); 3817 DCHECK_NE(ra, 0); 3818 set_register(ra, ra_val + offset); 3819 break; 3820 } 3821 case 2: { // lwa 3822 intptr_t result = ReadW(ra_val + offset, instr); 3823 set_register(rt, result); 3824 break; 3825 } 3826 } 3827 break; 3828 } 3829 3830 case STD: 3831 case STDU: { 3832 int ra = instr->RAValue(); 3833 int rs = instr->RSValue(); 3834 int64_t ra_val = ra == 0 ? 0 : get_register(ra); 3835 int64_t rs_val = get_register(rs); 3836 int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3); 3837 WriteDW(ra_val + offset, rs_val); 3838 if (opcode == STDU) { 3839 DCHECK_NE(ra, 0); 3840 set_register(ra, ra_val + offset); 3841 } 3842 break; 3843 } 3844 #endif 3845 3846 case XSADDDP: { 3847 int frt = instr->RTValue(); 3848 int fra = instr->RAValue(); 3849 int frb = instr->RBValue(); 3850 double fra_val = get_double_from_d_register(fra); 3851 double frb_val = get_double_from_d_register(frb); 3852 double frt_val = fra_val + frb_val; 3853 set_d_register_from_double(frt, frt_val); 3854 return; 3855 } 3856 case XSSUBDP: { 3857 int frt = instr->RTValue(); 3858 int fra = instr->RAValue(); 3859 int frb = instr->RBValue(); 3860 double fra_val = get_double_from_d_register(fra); 3861 double frb_val = get_double_from_d_register(frb); 3862 double frt_val = fra_val - frb_val; 3863 set_d_register_from_double(frt, frt_val); 3864 return; 3865 } 3866 case XSMULDP: { 3867 int frt = instr->RTValue(); 3868 int fra = instr->RAValue(); 3869 int frb = instr->RBValue(); 3870 double fra_val = get_double_from_d_register(fra); 3871 double frb_val = get_double_from_d_register(frb); 3872 double frt_val = fra_val * frb_val; 3873 set_d_register_from_double(frt, frt_val); 3874 return; 3875 } 3876 case XSDIVDP: { 3877 int frt = instr->RTValue(); 3878 int fra = instr->RAValue(); 3879 int frb = instr->RBValue(); 3880 double fra_val = get_double_from_d_register(fra); 3881 double frb_val = get_double_from_d_register(frb); 3882 double frt_val = fra_val / frb_val; 3883 set_d_register_from_double(frt, frt_val); 3884 return; 3885 } 3886 3887 default: { 3888 UNIMPLEMENTED(); 3889 break; 3890 } 3891 } 3892 } // NOLINT 3893 3894 3895 void Simulator::Trace(Instruction* instr) { 3896 disasm::NameConverter converter; 3897 disasm::Disassembler dasm(converter); 3898 // use a reasonably large buffer 3899 v8::internal::EmbeddedVector<char, 256> buffer; 3900 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr)); 3901 PrintF("%05d %08" V8PRIxPTR " %s\n", icount_, 3902 reinterpret_cast<intptr_t>(instr), buffer.start()); 3903 } 3904 3905 3906 // Executes the current instruction. 3907 void Simulator::ExecuteInstruction(Instruction* instr) { 3908 if (v8::internal::FLAG_check_icache) { 3909 CheckICache(i_cache(), instr); 3910 } 3911 pc_modified_ = false; 3912 if (::v8::internal::FLAG_trace_sim) { 3913 Trace(instr); 3914 } 3915 uint32_t opcode = instr->OpcodeField(); 3916 if (opcode == TWI) { 3917 SoftwareInterrupt(instr); 3918 } else { 3919 ExecuteGeneric(instr); 3920 } 3921 if (!pc_modified_) { 3922 set_pc(reinterpret_cast<intptr_t>(instr) + kInstrSize); 3923 } 3924 } 3925 3926 void Simulator::Execute() { 3927 // Get the PC to simulate. Cannot use the accessor here as we need the 3928 // raw PC value and not the one used as input to arithmetic instructions. 3929 intptr_t program_counter = get_pc(); 3930 3931 if (::v8::internal::FLAG_stop_sim_at == 0) { 3932 // Fast version of the dispatch loop without checking whether the simulator 3933 // should be stopping at a particular executed instruction. 3934 while (program_counter != end_sim_pc) { 3935 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3936 icount_++; 3937 ExecuteInstruction(instr); 3938 program_counter = get_pc(); 3939 } 3940 } else { 3941 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 3942 // we reach the particular instruction count. 3943 while (program_counter != end_sim_pc) { 3944 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3945 icount_++; 3946 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 3947 PPCDebugger dbg(this); 3948 dbg.Debug(); 3949 } else { 3950 ExecuteInstruction(instr); 3951 } 3952 program_counter = get_pc(); 3953 } 3954 } 3955 } 3956 3957 void Simulator::CallInternal(Address entry) { 3958 // Adjust JS-based stack limit to C-based stack limit. 3959 isolate_->stack_guard()->AdjustStackLimitForSimulator(); 3960 3961 // Prepare to execute the code at entry 3962 if (ABI_USES_FUNCTION_DESCRIPTORS) { 3963 // entry is the function descriptor 3964 set_pc(*(reinterpret_cast<intptr_t*>(entry))); 3965 } else { 3966 // entry is the instruction address 3967 set_pc(static_cast<intptr_t>(entry)); 3968 } 3969 3970 if (ABI_CALL_VIA_IP) { 3971 // Put target address in ip (for JS prologue). 3972 set_register(r12, get_pc()); 3973 } 3974 3975 // Put down marker for end of simulation. The simulator will stop simulation 3976 // when the PC reaches this value. By saving the "end simulation" value into 3977 // the LR the simulation stops when returning to this call point. 3978 special_reg_lr_ = end_sim_pc; 3979 3980 // Remember the values of non-volatile registers. 3981 intptr_t r2_val = get_register(r2); 3982 intptr_t r13_val = get_register(r13); 3983 intptr_t r14_val = get_register(r14); 3984 intptr_t r15_val = get_register(r15); 3985 intptr_t r16_val = get_register(r16); 3986 intptr_t r17_val = get_register(r17); 3987 intptr_t r18_val = get_register(r18); 3988 intptr_t r19_val = get_register(r19); 3989 intptr_t r20_val = get_register(r20); 3990 intptr_t r21_val = get_register(r21); 3991 intptr_t r22_val = get_register(r22); 3992 intptr_t r23_val = get_register(r23); 3993 intptr_t r24_val = get_register(r24); 3994 intptr_t r25_val = get_register(r25); 3995 intptr_t r26_val = get_register(r26); 3996 intptr_t r27_val = get_register(r27); 3997 intptr_t r28_val = get_register(r28); 3998 intptr_t r29_val = get_register(r29); 3999 intptr_t r30_val = get_register(r30); 4000 intptr_t r31_val = get_register(fp); 4001 4002 // Set up the non-volatile registers with a known value. To be able to check 4003 // that they are preserved properly across JS execution. 4004 intptr_t callee_saved_value = icount_; 4005 set_register(r2, callee_saved_value); 4006 set_register(r13, callee_saved_value); 4007 set_register(r14, callee_saved_value); 4008 set_register(r15, callee_saved_value); 4009 set_register(r16, callee_saved_value); 4010 set_register(r17, callee_saved_value); 4011 set_register(r18, callee_saved_value); 4012 set_register(r19, callee_saved_value); 4013 set_register(r20, callee_saved_value); 4014 set_register(r21, callee_saved_value); 4015 set_register(r22, callee_saved_value); 4016 set_register(r23, callee_saved_value); 4017 set_register(r24, callee_saved_value); 4018 set_register(r25, callee_saved_value); 4019 set_register(r26, callee_saved_value); 4020 set_register(r27, callee_saved_value); 4021 set_register(r28, callee_saved_value); 4022 set_register(r29, callee_saved_value); 4023 set_register(r30, callee_saved_value); 4024 set_register(fp, callee_saved_value); 4025 4026 // Start the simulation 4027 Execute(); 4028 4029 // Check that the non-volatile registers have been preserved. 4030 if (ABI_TOC_REGISTER != 2) { 4031 CHECK_EQ(callee_saved_value, get_register(r2)); 4032 } 4033 if (ABI_TOC_REGISTER != 13) { 4034 CHECK_EQ(callee_saved_value, get_register(r13)); 4035 } 4036 CHECK_EQ(callee_saved_value, get_register(r14)); 4037 CHECK_EQ(callee_saved_value, get_register(r15)); 4038 CHECK_EQ(callee_saved_value, get_register(r16)); 4039 CHECK_EQ(callee_saved_value, get_register(r17)); 4040 CHECK_EQ(callee_saved_value, get_register(r18)); 4041 CHECK_EQ(callee_saved_value, get_register(r19)); 4042 CHECK_EQ(callee_saved_value, get_register(r20)); 4043 CHECK_EQ(callee_saved_value, get_register(r21)); 4044 CHECK_EQ(callee_saved_value, get_register(r22)); 4045 CHECK_EQ(callee_saved_value, get_register(r23)); 4046 CHECK_EQ(callee_saved_value, get_register(r24)); 4047 CHECK_EQ(callee_saved_value, get_register(r25)); 4048 CHECK_EQ(callee_saved_value, get_register(r26)); 4049 CHECK_EQ(callee_saved_value, get_register(r27)); 4050 CHECK_EQ(callee_saved_value, get_register(r28)); 4051 CHECK_EQ(callee_saved_value, get_register(r29)); 4052 CHECK_EQ(callee_saved_value, get_register(r30)); 4053 CHECK_EQ(callee_saved_value, get_register(fp)); 4054 4055 // Restore non-volatile registers with the original value. 4056 set_register(r2, r2_val); 4057 set_register(r13, r13_val); 4058 set_register(r14, r14_val); 4059 set_register(r15, r15_val); 4060 set_register(r16, r16_val); 4061 set_register(r17, r17_val); 4062 set_register(r18, r18_val); 4063 set_register(r19, r19_val); 4064 set_register(r20, r20_val); 4065 set_register(r21, r21_val); 4066 set_register(r22, r22_val); 4067 set_register(r23, r23_val); 4068 set_register(r24, r24_val); 4069 set_register(r25, r25_val); 4070 set_register(r26, r26_val); 4071 set_register(r27, r27_val); 4072 set_register(r28, r28_val); 4073 set_register(r29, r29_val); 4074 set_register(r30, r30_val); 4075 set_register(fp, r31_val); 4076 } 4077 4078 intptr_t Simulator::CallImpl(Address entry, int argument_count, 4079 const intptr_t* arguments) { 4080 // Set up arguments 4081 4082 // First eight arguments passed in registers r3-r10. 4083 int reg_arg_count = std::min(8, argument_count); 4084 int stack_arg_count = argument_count - reg_arg_count; 4085 for (int i = 0; i < reg_arg_count; i++) { 4086 set_register(i + 3, arguments[i]); 4087 } 4088 4089 // Remaining arguments passed on stack. 4090 intptr_t original_stack = get_register(sp); 4091 // Compute position of stack on entry to generated code. 4092 intptr_t entry_stack = 4093 (original_stack - 4094 (kNumRequiredStackFrameSlots + stack_arg_count) * sizeof(intptr_t)); 4095 if (base::OS::ActivationFrameAlignment() != 0) { 4096 entry_stack &= -base::OS::ActivationFrameAlignment(); 4097 } 4098 // Store remaining arguments on stack, from low to high memory. 4099 // +2 is a hack for the LR slot + old SP on PPC 4100 intptr_t* stack_argument = 4101 reinterpret_cast<intptr_t*>(entry_stack) + kStackFrameExtraParamSlot; 4102 memcpy(stack_argument, arguments + reg_arg_count, 4103 stack_arg_count * sizeof(*arguments)); 4104 set_register(sp, entry_stack); 4105 4106 CallInternal(entry); 4107 4108 // Pop stack passed arguments. 4109 CHECK_EQ(entry_stack, get_register(sp)); 4110 set_register(sp, original_stack); 4111 4112 return get_register(r3); 4113 } 4114 4115 void Simulator::CallFP(Address entry, double d0, double d1) { 4116 set_d_register_from_double(1, d0); 4117 set_d_register_from_double(2, d1); 4118 CallInternal(entry); 4119 } 4120 4121 int32_t Simulator::CallFPReturnsInt(Address entry, double d0, double d1) { 4122 CallFP(entry, d0, d1); 4123 int32_t result = get_register(r3); 4124 return result; 4125 } 4126 4127 double Simulator::CallFPReturnsDouble(Address entry, double d0, double d1) { 4128 CallFP(entry, d0, d1); 4129 return get_double_from_d_register(1); 4130 } 4131 4132 4133 uintptr_t Simulator::PushAddress(uintptr_t address) { 4134 uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t); 4135 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 4136 *stack_slot = address; 4137 set_register(sp, new_sp); 4138 return new_sp; 4139 } 4140 4141 4142 uintptr_t Simulator::PopAddress() { 4143 uintptr_t current_sp = get_register(sp); 4144 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 4145 uintptr_t address = *stack_slot; 4146 set_register(sp, current_sp + sizeof(uintptr_t)); 4147 return address; 4148 } 4149 4150 Simulator::LocalMonitor::LocalMonitor() 4151 : access_state_(MonitorAccess::Open), 4152 tagged_addr_(0), 4153 size_(TransactionSize::None) {} 4154 4155 void Simulator::LocalMonitor::Clear() { 4156 access_state_ = MonitorAccess::Open; 4157 tagged_addr_ = 0; 4158 size_ = TransactionSize::None; 4159 } 4160 4161 void Simulator::LocalMonitor::NotifyLoad(int32_t addr) { 4162 if (access_state_ == MonitorAccess::Exclusive) { 4163 // A load could cause a cache eviction which will affect the monitor. As a 4164 // result, it's most strict to unconditionally clear the local monitor on 4165 // load. 4166 Clear(); 4167 } 4168 } 4169 4170 void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr, 4171 TransactionSize size) { 4172 access_state_ = MonitorAccess::Exclusive; 4173 tagged_addr_ = addr; 4174 size_ = size; 4175 } 4176 4177 void Simulator::LocalMonitor::NotifyStore(int32_t addr) { 4178 if (access_state_ == MonitorAccess::Exclusive) { 4179 // A store could cause a cache eviction which will affect the 4180 // monitor. As a result, it's most strict to unconditionally clear the 4181 // local monitor on store. 4182 Clear(); 4183 } 4184 } 4185 4186 bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr, 4187 TransactionSize size) { 4188 if (access_state_ == MonitorAccess::Exclusive) { 4189 if (addr == tagged_addr_ && size_ == size) { 4190 Clear(); 4191 return true; 4192 } else { 4193 Clear(); 4194 return false; 4195 } 4196 } else { 4197 DCHECK(access_state_ == MonitorAccess::Open); 4198 return false; 4199 } 4200 } 4201 4202 Simulator::GlobalMonitor::Processor::Processor() 4203 : access_state_(MonitorAccess::Open), 4204 tagged_addr_(0), 4205 next_(nullptr), 4206 prev_(nullptr) {} 4207 4208 void Simulator::GlobalMonitor::Processor::Clear_Locked() { 4209 access_state_ = MonitorAccess::Open; 4210 tagged_addr_ = 0; 4211 } 4212 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) { 4213 access_state_ = MonitorAccess::Exclusive; 4214 tagged_addr_ = addr; 4215 } 4216 4217 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked( 4218 int32_t addr, bool is_requesting_processor) { 4219 if (access_state_ == MonitorAccess::Exclusive) { 4220 // It is possible that a store caused a cache eviction, 4221 // which can affect the montior, so conservatively, 4222 // we always clear the monitor. 4223 Clear_Locked(); 4224 } 4225 } 4226 4227 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked( 4228 int32_t addr, bool is_requesting_processor) { 4229 if (access_state_ == MonitorAccess::Exclusive) { 4230 if (is_requesting_processor) { 4231 if (addr == tagged_addr_) { 4232 Clear_Locked(); 4233 return true; 4234 } 4235 } else if (addr == tagged_addr_) { 4236 Clear_Locked(); 4237 return false; 4238 } 4239 } 4240 return false; 4241 } 4242 4243 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {} 4244 4245 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr, 4246 Processor* processor) { 4247 processor->NotifyLoadExcl_Locked(addr); 4248 PrependProcessor_Locked(processor); 4249 } 4250 4251 void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr, 4252 Processor* processor) { 4253 // Notify each processor of the store operation. 4254 for (Processor* iter = head_; iter; iter = iter->next_) { 4255 bool is_requesting_processor = iter == processor; 4256 iter->NotifyStore_Locked(addr, is_requesting_processor); 4257 } 4258 } 4259 4260 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr, 4261 Processor* processor) { 4262 DCHECK(IsProcessorInLinkedList_Locked(processor)); 4263 if (processor->NotifyStoreExcl_Locked(addr, true)) { 4264 // Notify the other processors that this StoreExcl succeeded. 4265 for (Processor* iter = head_; iter; iter = iter->next_) { 4266 if (iter != processor) { 4267 iter->NotifyStoreExcl_Locked(addr, false); 4268 } 4269 } 4270 return true; 4271 } else { 4272 return false; 4273 } 4274 } 4275 4276 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked( 4277 Processor* processor) const { 4278 return head_ == processor || processor->next_ || processor->prev_; 4279 } 4280 4281 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) { 4282 if (IsProcessorInLinkedList_Locked(processor)) { 4283 return; 4284 } 4285 4286 if (head_) { 4287 head_->prev_ = processor; 4288 } 4289 processor->prev_ = nullptr; 4290 processor->next_ = head_; 4291 head_ = processor; 4292 } 4293 4294 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) { 4295 base::LockGuard<base::Mutex> lock_guard(&mutex); 4296 if (!IsProcessorInLinkedList_Locked(processor)) { 4297 return; 4298 } 4299 4300 if (processor->prev_) { 4301 processor->prev_->next_ = processor->next_; 4302 } else { 4303 head_ = processor->next_; 4304 } 4305 if (processor->next_) { 4306 processor->next_->prev_ = processor->prev_; 4307 } 4308 processor->prev_ = nullptr; 4309 processor->next_ = nullptr; 4310 } 4311 4312 } // namespace internal 4313 } // namespace v8 4314 4315 #endif // USE_SIMULATOR 4316 #endif // V8_TARGET_ARCH_PPC 4317