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