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