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