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