• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PPCDebugger(Simulator * sim)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 
Stop(Instruction * instr)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 
GetRegisterValue(int regnum)91 intptr_t PPCDebugger::GetRegisterValue(int regnum) {
92   return sim_->get_register(regnum);
93 }
94 
95 
GetRegisterPairDoubleValue(int regnum)96 double PPCDebugger::GetRegisterPairDoubleValue(int regnum) {
97   return sim_->get_double_from_register_pair(regnum);
98 }
99 
100 
GetFPDoubleRegisterValue(int regnum)101 double PPCDebugger::GetFPDoubleRegisterValue(int regnum) {
102   return sim_->get_double_from_d_register(regnum);
103 }
104 
105 
GetValue(const char * desc,intptr_t * value)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 
GetFPDoubleValue(const char * desc,double * value)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 
SetBreakpoint(Instruction * break_pc)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 
DeleteBreakpoint(Instruction * break_pc)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 
UndoBreakpoints()160 void PPCDebugger::UndoBreakpoints() {
161   if (sim_->break_pc_ != nullptr) {
162     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
163   }
164 }
165 
166 
RedoBreakpoints()167 void PPCDebugger::RedoBreakpoints() {
168   if (sim_->break_pc_ != nullptr) {
169     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
170   }
171 }
172 
173 
Debug()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 
ICacheMatch(void * one,void * two)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 
ICacheHash(void * key)647 static uint32_t ICacheHash(void* key) {
648   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
649 }
650 
651 
AllOnOnePage(uintptr_t start,int size)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 
set_last_debugger_input(char * input)659 void Simulator::set_last_debugger_input(char* input) {
660   DeleteArray(last_debugger_input_);
661   last_debugger_input_ = input;
662 }
663 
SetRedirectInstruction(Instruction * instruction)664 void Simulator::SetRedirectInstruction(Instruction* instruction) {
665   instruction->SetInstructionBits(rtCallRedirInstr | kCallRtRedirected);
666 }
667 
FlushICache(base::CustomMatcherHashMap * i_cache,void * start_addr,size_t size)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 
GetCachePage(base::CustomMatcherHashMap * i_cache,void * page)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.
FlushOnePage(base::CustomMatcherHashMap * i_cache,intptr_t start,int 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 
CheckICache(base::CustomMatcherHashMap * i_cache,Instruction * instr)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 
Simulator(Isolate * isolate)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 
~Simulator()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.
current(Isolate * isolate)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.
set_register(int reg,intptr_t value)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.
get_register(int reg) const806 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 
get_double_from_register_pair(int reg)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.
set_pc(intptr_t value)832 void Simulator::set_pc(intptr_t value) {
833   pc_modified_ = true;
834   special_reg_pc_ = value;
835 }
836 
837 
has_bad_pc() const838 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.
get_pc() const844 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.
GetFpArgs(double * x,double * y,intptr_t * z)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.
SetFpResult(const double & result)859 void Simulator::SetFpResult(const double& result) {
860   set_d_register_from_double(1, result);
861 }
862 
863 
TrashCallerSaveRegisters()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 
ReadWU(intptr_t addr,Instruction * instr)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 
ReadExWU(intptr_t addr,Instruction * instr)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 
ReadW(intptr_t addr,Instruction * instr)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 
WriteW(intptr_t addr,uint32_t value,Instruction * instr)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 
WriteExW(intptr_t addr,uint32_t value,Instruction * instr)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 
WriteW(intptr_t addr,int32_t value,Instruction * instr)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 
ReadHU(intptr_t addr,Instruction * instr)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 
ReadExHU(intptr_t addr,Instruction * instr)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 
ReadH(intptr_t addr,Instruction * instr)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 
WriteH(intptr_t addr,uint16_t value,Instruction * instr)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 
WriteH(intptr_t addr,int16_t value,Instruction * instr)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 
WriteExH(intptr_t addr,uint16_t value,Instruction * instr)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 
ReadBU(intptr_t addr)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 
ReadB(intptr_t addr)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 
ReadExBU(intptr_t addr)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 
WriteB(intptr_t addr,uint8_t value)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 
WriteB(intptr_t addr,int8_t value)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 
WriteExB(intptr_t addr,uint8_t value)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 
ReadDW(intptr_t addr)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 
WriteDW(intptr_t addr,int64_t value)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.
StackLimit(uintptr_t c_limit) const1093 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.
Format(Instruction * instr,const char * format)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.
CarryFrom(int32_t left,int32_t right,int32_t carry)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.
BorrowFrom(int32_t left,int32_t right)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.
OverflowFrom(int32_t alu_out,int32_t left,int32_t right,bool addition)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
decodeObjectPair(ObjectPair * pair,intptr_t * x,intptr_t * y)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
decodeObjectPair(ObjectPair * pair,intptr_t * x,intptr_t * y)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.
SoftwareInterrupt(Instruction * instr)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.
isStopInstruction(Instruction * instr)1482 bool Simulator::isStopInstruction(Instruction* instr) {
1483   return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1484 }
1485 
1486 
isWatchedStop(uint32_t code)1487 bool Simulator::isWatchedStop(uint32_t code) {
1488   DCHECK_LE(code, kMaxStopCode);
1489   return code < kNumOfWatchedStops;
1490 }
1491 
1492 
isEnabledStop(uint32_t code)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 
EnableStop(uint32_t code)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 
DisableStop(uint32_t code)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 
IncreaseStopCounter(uint32_t code)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.
PrintStopInfo(uint32_t code)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 
SetCR0(intptr_t result,bool setSO)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 
ExecuteBranchConditional(Instruction * instr,BCType type)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 
ExecuteGeneric(Instruction * instr)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 
Trace(Instruction * instr)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.
ExecuteInstruction(Instruction * instr)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 
Execute()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 
CallInternal(Address entry)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 
CallImpl(Address entry,int argument_count,const intptr_t * arguments)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 
CallFP(Address entry,double d0,double d1)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 
CallFPReturnsInt(Address entry,double d0,double d1)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 
CallFPReturnsDouble(Address entry,double d0,double d1)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 
PushAddress(uintptr_t address)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 
PopAddress()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 
LocalMonitor()4150 Simulator::LocalMonitor::LocalMonitor()
4151     : access_state_(MonitorAccess::Open),
4152       tagged_addr_(0),
4153       size_(TransactionSize::None) {}
4154 
Clear()4155 void Simulator::LocalMonitor::Clear() {
4156   access_state_ = MonitorAccess::Open;
4157   tagged_addr_ = 0;
4158   size_ = TransactionSize::None;
4159 }
4160 
NotifyLoad(int32_t addr)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 
NotifyLoadExcl(int32_t addr,TransactionSize size)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 
NotifyStore(int32_t addr)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 
NotifyStoreExcl(int32_t addr,TransactionSize size)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 
Processor()4202 Simulator::GlobalMonitor::Processor::Processor()
4203     : access_state_(MonitorAccess::Open),
4204       tagged_addr_(0),
4205       next_(nullptr),
4206       prev_(nullptr) {}
4207 
Clear_Locked()4208 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
4209   access_state_ = MonitorAccess::Open;
4210   tagged_addr_ = 0;
4211 }
NotifyLoadExcl_Locked(int32_t addr)4212 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
4213   access_state_ = MonitorAccess::Exclusive;
4214   tagged_addr_ = addr;
4215 }
4216 
NotifyStore_Locked(int32_t addr,bool is_requesting_processor)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 
NotifyStoreExcl_Locked(int32_t addr,bool is_requesting_processor)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 
GlobalMonitor()4243 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
4244 
NotifyLoadExcl_Locked(int32_t addr,Processor * processor)4245 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
4246                                                      Processor* processor) {
4247   processor->NotifyLoadExcl_Locked(addr);
4248   PrependProcessor_Locked(processor);
4249 }
4250 
NotifyStore_Locked(int32_t addr,Processor * processor)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 
NotifyStoreExcl_Locked(int32_t addr,Processor * processor)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 
IsProcessorInLinkedList_Locked(Processor * processor) const4276 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
4277     Processor* processor) const {
4278   return head_ == processor || processor->next_ || processor->prev_;
4279 }
4280 
PrependProcessor_Locked(Processor * processor)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 
RemoveProcessor(Processor * processor)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