• 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 "src/execution/ppc/simulator-ppc.h"
6 
7 #if defined(USE_SIMULATOR)
8 
9 #include <stdarg.h>
10 #include <stdlib.h>
11 
12 #include <cmath>
13 
14 #include "src/base/bits.h"
15 #include "src/base/lazy-instance.h"
16 #include "src/base/overflowing-math.h"
17 #include "src/base/platform/platform.h"
18 #include "src/base/platform/wrappers.h"
19 #include "src/codegen/assembler.h"
20 #include "src/codegen/macro-assembler.h"
21 #include "src/codegen/ppc/constants-ppc.h"
22 #include "src/codegen/register-configuration.h"
23 #include "src/diagnostics/disasm.h"
24 #include "src/execution/ppc/frame-constants-ppc.h"
25 #include "src/heap/combined-heap.h"
26 #include "src/heap/heap-inl.h"  // For CodeSpaceMemoryModificationScope.
27 #include "src/objects/objects-inl.h"
28 #include "src/runtime/runtime-utils.h"
29 #include "src/utils/ostreams.h"
30 
31 // Only build the simulator if not compiling for real PPC hardware.
32 namespace v8 {
33 namespace internal {
34 
35 DEFINE_LAZY_LEAKY_OBJECT_GETTER(Simulator::GlobalMonitor,
36                                 Simulator::GlobalMonitor::Get)
37 
38 // This macro provides a platform independent use of sscanf. The reason for
39 // SScanF not being implemented in a platform independent way through
40 // ::v8::internal::OS in the same way as SNPrintF is that the
41 // Windows C Run-Time Library does not provide vsscanf.
42 #define SScanF sscanf
43 
44 // The PPCDebugger class is used by the simulator while debugging simulated
45 // PowerPC code.
46 class PPCDebugger {
47  public:
PPCDebugger(Simulator * sim)48   explicit PPCDebugger(Simulator* sim) : sim_(sim) {}
49   void Debug();
50 
51  private:
52   static const Instr kBreakpointInstr = (TWI | 0x1F * B21);
53   static const Instr kNopInstr = (ORI);  // ori, 0,0,0
54 
55   Simulator* sim_;
56 
57   intptr_t GetRegisterValue(int regnum);
58   double GetRegisterPairDoubleValue(int regnum);
59   double GetFPDoubleRegisterValue(int regnum);
60   bool GetValue(const char* desc, intptr_t* value);
61   bool GetFPDoubleValue(const char* desc, double* value);
62 
63   // Set or delete breakpoint (there can be only one).
64   bool SetBreakpoint(Instruction* break_pc);
65   void DeleteBreakpoint();
66 
67   // Undo and redo the breakpoint. This is needed to bracket disassembly and
68   // execution to skip past the breakpoint when run from the debugger.
69   void UndoBreakpoint();
70   void RedoBreakpoint();
71 };
72 
DebugAtNextPC()73 void Simulator::DebugAtNextPC() {
74   PrintF("Starting debugger on the next instruction:\n");
75   set_pc(get_pc() + kInstrSize);
76   PPCDebugger(this).Debug();
77 }
78 
GetRegisterValue(int regnum)79 intptr_t PPCDebugger::GetRegisterValue(int regnum) {
80   return sim_->get_register(regnum);
81 }
82 
GetRegisterPairDoubleValue(int regnum)83 double PPCDebugger::GetRegisterPairDoubleValue(int regnum) {
84   return sim_->get_double_from_register_pair(regnum);
85 }
86 
GetFPDoubleRegisterValue(int regnum)87 double PPCDebugger::GetFPDoubleRegisterValue(int regnum) {
88   return sim_->get_double_from_d_register(regnum);
89 }
90 
GetValue(const char * desc,intptr_t * value)91 bool PPCDebugger::GetValue(const char* desc, intptr_t* value) {
92   int regnum = Registers::Number(desc);
93   if (regnum != kNoRegister) {
94     *value = GetRegisterValue(regnum);
95     return true;
96   }
97   if (strncmp(desc, "0x", 2) == 0) {
98     return SScanF(desc + 2, "%" V8PRIxPTR,
99                   reinterpret_cast<uintptr_t*>(value)) == 1;
100   }
101   return SScanF(desc, "%" V8PRIuPTR, reinterpret_cast<uintptr_t*>(value)) == 1;
102 }
103 
GetFPDoubleValue(const char * desc,double * value)104 bool PPCDebugger::GetFPDoubleValue(const char* desc, double* value) {
105   int regnum = DoubleRegisters::Number(desc);
106   if (regnum != kNoRegister) {
107     *value = sim_->get_double_from_d_register(regnum);
108     return true;
109   }
110   return false;
111 }
112 
SetBreakpoint(Instruction * break_pc)113 bool PPCDebugger::SetBreakpoint(Instruction* break_pc) {
114   // Check if a breakpoint can be set. If not return without any side-effects.
115   if (sim_->break_pc_ != nullptr) {
116     return false;
117   }
118 
119   // Set the breakpoint.
120   sim_->break_pc_ = break_pc;
121   sim_->break_instr_ = break_pc->InstructionBits();
122   // Not setting the breakpoint instruction in the code itself. It will be set
123   // when the debugger shell continues.
124   return true;
125 }
126 
127 namespace {
128 // This function is dangerous, but it's only available in non-production
129 // (simulator) builds.
SetInstructionBitsInCodeSpace(Instruction * instr,Instr value,Heap * heap)130 void SetInstructionBitsInCodeSpace(Instruction* instr, Instr value,
131                                    Heap* heap) {
132   CodeSpaceMemoryModificationScope scope(heap);
133   instr->SetInstructionBits(value);
134 }
135 }  // namespace
136 
DeleteBreakpoint()137 void PPCDebugger::DeleteBreakpoint() {
138   UndoBreakpoint();
139   sim_->break_pc_ = nullptr;
140   sim_->break_instr_ = 0;
141 }
142 
UndoBreakpoint()143 void PPCDebugger::UndoBreakpoint() {
144   if (sim_->break_pc_ != nullptr) {
145     SetInstructionBitsInCodeSpace(sim_->break_pc_, sim_->break_instr_,
146                                   sim_->isolate_->heap());
147   }
148 }
149 
RedoBreakpoint()150 void PPCDebugger::RedoBreakpoint() {
151   if (sim_->break_pc_ != nullptr) {
152     SetInstructionBitsInCodeSpace(sim_->break_pc_, kBreakpointInstr,
153                                   sim_->isolate_->heap());
154   }
155 }
156 
Debug()157 void PPCDebugger::Debug() {
158   intptr_t last_pc = -1;
159   bool done = false;
160 
161 #define COMMAND_SIZE 63
162 #define ARG_SIZE 255
163 
164 #define STR(a) #a
165 #define XSTR(a) STR(a)
166 
167   char cmd[COMMAND_SIZE + 1];
168   char arg1[ARG_SIZE + 1];
169   char arg2[ARG_SIZE + 1];
170   char* argv[3] = {cmd, arg1, arg2};
171 
172   // make sure to have a proper terminating character if reaching the limit
173   cmd[COMMAND_SIZE] = 0;
174   arg1[ARG_SIZE] = 0;
175   arg2[ARG_SIZE] = 0;
176 
177   // Unset breakpoint while running in the debugger shell, making it invisible
178   // to all commands.
179   UndoBreakpoint();
180   // Disable tracing while simulating
181   bool trace = ::v8::internal::FLAG_trace_sim;
182   ::v8::internal::FLAG_trace_sim = false;
183 
184   while (!done && !sim_->has_bad_pc()) {
185     if (last_pc != sim_->get_pc()) {
186       disasm::NameConverter converter;
187       disasm::Disassembler dasm(converter);
188       // use a reasonably large buffer
189       v8::base::EmbeddedVector<char, 256> buffer;
190       dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc()));
191       PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(), buffer.begin());
192       last_pc = sim_->get_pc();
193     }
194     char* line = ReadLine("sim> ");
195     if (line == nullptr) {
196       break;
197     } else {
198       char* last_input = sim_->last_debugger_input();
199       if (strcmp(line, "\n") == 0 && last_input != nullptr) {
200         line = last_input;
201       } else {
202         // Ownership is transferred to sim_;
203         sim_->set_last_debugger_input(line);
204       }
205       // Use sscanf to parse the individual parts of the command line. At the
206       // moment no command expects more than two parameters.
207       int argc = SScanF(line,
208                         "%" XSTR(COMMAND_SIZE) "s "
209                         "%" XSTR(ARG_SIZE) "s "
210                         "%" XSTR(ARG_SIZE) "s",
211                         cmd, arg1, arg2);
212       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
213         intptr_t value;
214 
215         // If at a breakpoint, proceed past it.
216         if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
217                 ->InstructionBits() == 0x7D821008) {
218           sim_->set_pc(sim_->get_pc() + kInstrSize);
219         } else {
220           sim_->ExecuteInstruction(
221               reinterpret_cast<Instruction*>(sim_->get_pc()));
222         }
223 
224         if (argc == 2 && last_pc != sim_->get_pc() && GetValue(arg1, &value)) {
225           for (int i = 1; i < value; i++) {
226             disasm::NameConverter converter;
227             disasm::Disassembler dasm(converter);
228             // use a reasonably large buffer
229             v8::base::EmbeddedVector<char, 256> buffer;
230             dasm.InstructionDecode(buffer,
231                                    reinterpret_cast<byte*>(sim_->get_pc()));
232             PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(),
233                    buffer.begin());
234             sim_->ExecuteInstruction(
235                 reinterpret_cast<Instruction*>(sim_->get_pc()));
236           }
237         }
238       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
239         // If at a breakpoint, proceed past it.
240         if ((reinterpret_cast<Instruction*>(sim_->get_pc()))
241                 ->InstructionBits() == 0x7D821008) {
242           sim_->set_pc(sim_->get_pc() + kInstrSize);
243         } else {
244           // Execute the one instruction we broke at with breakpoints disabled.
245           sim_->ExecuteInstruction(
246               reinterpret_cast<Instruction*>(sim_->get_pc()));
247         }
248         // Leave the debugger shell.
249         done = true;
250       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
251         if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
252           intptr_t value;
253           double dvalue;
254           if (strcmp(arg1, "all") == 0) {
255             for (int i = 0; i < kNumRegisters; i++) {
256               value = GetRegisterValue(i);
257               PrintF("    %3s: %08" V8PRIxPTR,
258                      RegisterName(Register::from_code(i)), value);
259               if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
260                   (i % 2) == 0) {
261                 dvalue = GetRegisterPairDoubleValue(i);
262                 PrintF(" (%f)\n", dvalue);
263               } else if (i != 0 && !((i + 1) & 3)) {
264                 PrintF("\n");
265               }
266             }
267             PrintF("  pc: %08" V8PRIxPTR "  lr: %08" V8PRIxPTR
268                    "  "
269                    "ctr: %08" V8PRIxPTR "  xer: %08x  cr: %08x\n",
270                    sim_->special_reg_pc_, sim_->special_reg_lr_,
271                    sim_->special_reg_ctr_, sim_->special_reg_xer_,
272                    sim_->condition_reg_);
273           } else if (strcmp(arg1, "alld") == 0) {
274             for (int i = 0; i < kNumRegisters; i++) {
275               value = GetRegisterValue(i);
276               PrintF("     %3s: %08" V8PRIxPTR " %11" V8PRIdPTR,
277                      RegisterName(Register::from_code(i)), value, value);
278               if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
279                   (i % 2) == 0) {
280                 dvalue = GetRegisterPairDoubleValue(i);
281                 PrintF(" (%f)\n", dvalue);
282               } else if (!((i + 1) % 2)) {
283                 PrintF("\n");
284               }
285             }
286             PrintF("   pc: %08" V8PRIxPTR "  lr: %08" V8PRIxPTR
287                    "  "
288                    "ctr: %08" V8PRIxPTR "  xer: %08x  cr: %08x\n",
289                    sim_->special_reg_pc_, sim_->special_reg_lr_,
290                    sim_->special_reg_ctr_, sim_->special_reg_xer_,
291                    sim_->condition_reg_);
292           } else if (strcmp(arg1, "allf") == 0) {
293             for (int i = 0; i < DoubleRegister::kNumRegisters; i++) {
294               dvalue = GetFPDoubleRegisterValue(i);
295               uint64_t as_words = bit_cast<uint64_t>(dvalue);
296               PrintF("%3s: %f 0x%08x %08x\n",
297                      RegisterName(DoubleRegister::from_code(i)), dvalue,
298                      static_cast<uint32_t>(as_words >> 32),
299                      static_cast<uint32_t>(as_words & 0xFFFFFFFF));
300             }
301           } else if (arg1[0] == 'r' &&
302                      (arg1[1] >= '0' && arg1[1] <= '9' &&
303                       (arg1[2] == '\0' || (arg1[2] >= '0' && arg1[2] <= '9' &&
304                                            arg1[3] == '\0')))) {
305             int regnum = strtoul(&arg1[1], 0, 10);
306             if (regnum != kNoRegister) {
307               value = GetRegisterValue(regnum);
308               PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
309                      value);
310             } else {
311               PrintF("%s unrecognized\n", arg1);
312             }
313           } else {
314             if (GetValue(arg1, &value)) {
315               PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n", arg1, value,
316                      value);
317             } else if (GetFPDoubleValue(arg1, &dvalue)) {
318               uint64_t as_words = bit_cast<uint64_t>(dvalue);
319               PrintF("%s: %f 0x%08x %08x\n", arg1, dvalue,
320                      static_cast<uint32_t>(as_words >> 32),
321                      static_cast<uint32_t>(as_words & 0xFFFFFFFF));
322             } else {
323               PrintF("%s unrecognized\n", arg1);
324             }
325           }
326         } else {
327           PrintF("print <register>\n");
328         }
329       } else if ((strcmp(cmd, "po") == 0) ||
330                  (strcmp(cmd, "printobject") == 0)) {
331         if (argc == 2) {
332           intptr_t value;
333           StdoutStream os;
334           if (GetValue(arg1, &value)) {
335             Object obj(value);
336             os << arg1 << ": \n";
337 #ifdef DEBUG
338             obj.Print(os);
339             os << "\n";
340 #else
341             os << Brief(obj) << "\n";
342 #endif
343           } else {
344             os << arg1 << " unrecognized\n";
345           }
346         } else {
347           PrintF("printobject <value>\n");
348         }
349       } else if (strcmp(cmd, "setpc") == 0) {
350         intptr_t value;
351 
352         if (!GetValue(arg1, &value)) {
353           PrintF("%s unrecognized\n", arg1);
354           continue;
355         }
356         sim_->set_pc(value);
357       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0 ||
358                  strcmp(cmd, "dump") == 0) {
359         intptr_t* cur = nullptr;
360         intptr_t* end = nullptr;
361         int next_arg = 1;
362 
363         if (strcmp(cmd, "stack") == 0) {
364           cur = reinterpret_cast<intptr_t*>(sim_->get_register(Simulator::sp));
365         } else {  // "mem"
366           intptr_t value;
367           if (!GetValue(arg1, &value)) {
368             PrintF("%s unrecognized\n", arg1);
369             continue;
370           }
371           cur = reinterpret_cast<intptr_t*>(value);
372           next_arg++;
373         }
374 
375         intptr_t words;  // likely inaccurate variable name for 64bit
376         if (argc == next_arg) {
377           words = 10;
378         } else {
379           if (!GetValue(argv[next_arg], &words)) {
380             words = 10;
381           }
382         }
383         end = cur + words;
384 
385         bool skip_obj_print = (strcmp(cmd, "dump") == 0);
386         while (cur < end) {
387           PrintF("  0x%08" V8PRIxPTR ":  0x%08" V8PRIxPTR " %10" V8PRIdPTR,
388                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
389           Object obj(*cur);
390           Heap* current_heap = sim_->isolate_->heap();
391           if (!skip_obj_print) {
392             if (obj.IsSmi() ||
393                 IsValidHeapObject(current_heap, HeapObject::cast(obj))) {
394               PrintF(" (");
395               if (obj.IsSmi()) {
396                 PrintF("smi %d", Smi::ToInt(obj));
397               } else {
398                 obj.ShortPrint();
399               }
400               PrintF(")");
401             }
402           }
403           PrintF("\n");
404           cur++;
405         }
406       } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
407         disasm::NameConverter converter;
408         disasm::Disassembler dasm(converter);
409         // use a reasonably large buffer
410         v8::base::EmbeddedVector<char, 256> buffer;
411 
412         byte* prev = nullptr;
413         byte* cur = nullptr;
414         byte* end = nullptr;
415 
416         if (argc == 1) {
417           cur = reinterpret_cast<byte*>(sim_->get_pc());
418           end = cur + (10 * kInstrSize);
419         } else if (argc == 2) {
420           int regnum = Registers::Number(arg1);
421           if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
422             // The argument is an address or a register name.
423             intptr_t value;
424             if (GetValue(arg1, &value)) {
425               cur = reinterpret_cast<byte*>(value);
426               // Disassemble 10 instructions at <arg1>.
427               end = cur + (10 * kInstrSize);
428             }
429           } else {
430             // The argument is the number of instructions.
431             intptr_t value;
432             if (GetValue(arg1, &value)) {
433               cur = reinterpret_cast<byte*>(sim_->get_pc());
434               // Disassemble <arg1> instructions.
435               end = cur + (value * kInstrSize);
436             }
437           }
438         } else {
439           intptr_t value1;
440           intptr_t value2;
441           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
442             cur = reinterpret_cast<byte*>(value1);
443             end = cur + (value2 * kInstrSize);
444           }
445         }
446 
447         while (cur < end) {
448           prev = cur;
449           cur += dasm.InstructionDecode(buffer, cur);
450           PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(prev),
451                  buffer.begin());
452         }
453       } else if (strcmp(cmd, "gdb") == 0) {
454         PrintF("relinquishing control to gdb\n");
455         v8::base::OS::DebugBreak();
456         PrintF("regaining control from gdb\n");
457       } else if (strcmp(cmd, "break") == 0) {
458         if (argc == 2) {
459           intptr_t value;
460           if (GetValue(arg1, &value)) {
461             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
462               PrintF("setting breakpoint failed\n");
463             }
464           } else {
465             PrintF("%s unrecognized\n", arg1);
466           }
467         } else {
468           PrintF("break <address>\n");
469         }
470       } else if (strcmp(cmd, "del") == 0) {
471         DeleteBreakpoint();
472       } else if (strcmp(cmd, "cr") == 0) {
473         PrintF("Condition reg: %08x\n", sim_->condition_reg_);
474       } else if (strcmp(cmd, "lr") == 0) {
475         PrintF("Link reg: %08" V8PRIxPTR "\n", sim_->special_reg_lr_);
476       } else if (strcmp(cmd, "ctr") == 0) {
477         PrintF("Ctr reg: %08" V8PRIxPTR "\n", sim_->special_reg_ctr_);
478       } else if (strcmp(cmd, "xer") == 0) {
479         PrintF("XER: %08x\n", sim_->special_reg_xer_);
480       } else if (strcmp(cmd, "fpscr") == 0) {
481         PrintF("FPSCR: %08x\n", sim_->fp_condition_reg_);
482       } else if (strcmp(cmd, "stop") == 0) {
483         intptr_t value;
484         intptr_t stop_pc = sim_->get_pc() - (kInstrSize + kSystemPointerSize);
485         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
486         Instruction* msg_address =
487             reinterpret_cast<Instruction*>(stop_pc + kInstrSize);
488         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
489           // Remove the current stop.
490           if (sim_->isStopInstruction(stop_instr)) {
491             SetInstructionBitsInCodeSpace(stop_instr, kNopInstr,
492                                           sim_->isolate_->heap());
493             msg_address->SetInstructionBits(kNopInstr);
494           } else {
495             PrintF("Not at debugger stop.\n");
496           }
497         } else if (argc == 3) {
498           // Print information about all/the specified breakpoint(s).
499           if (strcmp(arg1, "info") == 0) {
500             if (strcmp(arg2, "all") == 0) {
501               PrintF("Stop information:\n");
502               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
503                 sim_->PrintStopInfo(i);
504               }
505             } else if (GetValue(arg2, &value)) {
506               sim_->PrintStopInfo(value);
507             } else {
508               PrintF("Unrecognized argument.\n");
509             }
510           } else if (strcmp(arg1, "enable") == 0) {
511             // Enable all/the specified breakpoint(s).
512             if (strcmp(arg2, "all") == 0) {
513               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
514                 sim_->EnableStop(i);
515               }
516             } else if (GetValue(arg2, &value)) {
517               sim_->EnableStop(value);
518             } else {
519               PrintF("Unrecognized argument.\n");
520             }
521           } else if (strcmp(arg1, "disable") == 0) {
522             // Disable all/the specified breakpoint(s).
523             if (strcmp(arg2, "all") == 0) {
524               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
525                 sim_->DisableStop(i);
526               }
527             } else if (GetValue(arg2, &value)) {
528               sim_->DisableStop(value);
529             } else {
530               PrintF("Unrecognized argument.\n");
531             }
532           }
533         } else {
534           PrintF("Wrong usage. Use help command for more information.\n");
535         }
536       } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
537         ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
538         PrintF("Trace of executed instructions is %s\n",
539                ::v8::internal::FLAG_trace_sim ? "on" : "off");
540       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
541         PrintF("cont\n");
542         PrintF("  continue execution (alias 'c')\n");
543         PrintF("stepi [num instructions]\n");
544         PrintF("  step one/num instruction(s) (alias 'si')\n");
545         PrintF("print <register>\n");
546         PrintF("  print register content (alias 'p')\n");
547         PrintF("  use register name 'all' to display all integer registers\n");
548         PrintF(
549             "  use register name 'alld' to display integer registers "
550             "with decimal values\n");
551         PrintF("  use register name 'rN' to display register number 'N'\n");
552         PrintF("  add argument 'fp' to print register pair double values\n");
553         PrintF(
554             "  use register name 'allf' to display floating-point "
555             "registers\n");
556         PrintF("printobject <register>\n");
557         PrintF("  print an object from a register (alias 'po')\n");
558         PrintF("cr\n");
559         PrintF("  print condition register\n");
560         PrintF("lr\n");
561         PrintF("  print link register\n");
562         PrintF("ctr\n");
563         PrintF("  print ctr register\n");
564         PrintF("xer\n");
565         PrintF("  print XER\n");
566         PrintF("fpscr\n");
567         PrintF("  print FPSCR\n");
568         PrintF("stack [<num words>]\n");
569         PrintF("  dump stack content, default dump 10 words)\n");
570         PrintF("mem <address> [<num words>]\n");
571         PrintF("  dump memory content, default dump 10 words)\n");
572         PrintF("dump [<words>]\n");
573         PrintF(
574             "  dump memory content without pretty printing JS objects, default "
575             "dump 10 words)\n");
576         PrintF("disasm [<instructions>]\n");
577         PrintF("disasm [<address/register>]\n");
578         PrintF("disasm [[<address/register>] <instructions>]\n");
579         PrintF("  disassemble code, default is 10 instructions\n");
580         PrintF("  from pc (alias 'di')\n");
581         PrintF("gdb\n");
582         PrintF("  enter gdb\n");
583         PrintF("break <address>\n");
584         PrintF("  set a break point on the address\n");
585         PrintF("del\n");
586         PrintF("  delete the breakpoint\n");
587         PrintF("trace (alias 't')\n");
588         PrintF("  toogle the tracing of all executed statements\n");
589         PrintF("stop feature:\n");
590         PrintF("  Description:\n");
591         PrintF("    Stops are debug instructions inserted by\n");
592         PrintF("    the Assembler::stop() function.\n");
593         PrintF("    When hitting a stop, the Simulator will\n");
594         PrintF("    stop and give control to the PPCDebugger.\n");
595         PrintF("    The first %d stop codes are watched:\n",
596                Simulator::kNumOfWatchedStops);
597         PrintF("    - They can be enabled / disabled: the Simulator\n");
598         PrintF("      will / won't stop when hitting them.\n");
599         PrintF("    - The Simulator keeps track of how many times they \n");
600         PrintF("      are met. (See the info command.) Going over a\n");
601         PrintF("      disabled stop still increases its counter. \n");
602         PrintF("  Commands:\n");
603         PrintF("    stop info all/<code> : print infos about number <code>\n");
604         PrintF("      or all stop(s).\n");
605         PrintF("    stop enable/disable all/<code> : enables / disables\n");
606         PrintF("      all or number <code> stop(s)\n");
607         PrintF("    stop unstop\n");
608         PrintF("      ignore the stop instruction at the current location\n");
609         PrintF("      from now on\n");
610       } else {
611         PrintF("Unknown command: %s\n", cmd);
612       }
613     }
614   }
615 
616   // Reinstall breakpoint to stop execution and enter the debugger shell when
617   // hit.
618   RedoBreakpoint();
619   // Restore tracing
620   ::v8::internal::FLAG_trace_sim = trace;
621 
622 #undef COMMAND_SIZE
623 #undef ARG_SIZE
624 
625 #undef STR
626 #undef XSTR
627 }
628 
ICacheMatch(void * one,void * two)629 bool Simulator::ICacheMatch(void* one, void* two) {
630   DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
631   DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
632   return one == two;
633 }
634 
ICacheHash(void * key)635 static uint32_t ICacheHash(void* key) {
636   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
637 }
638 
AllOnOnePage(uintptr_t start,int size)639 static bool AllOnOnePage(uintptr_t start, int size) {
640   intptr_t start_page = (start & ~CachePage::kPageMask);
641   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
642   return start_page == end_page;
643 }
644 
is_snan(float input)645 static bool is_snan(float input) {
646   uint32_t kQuietNanFPBit = 1 << 22;
647   uint32_t InputAsUint = bit_cast<uint32_t>(input);
648   return isnan(input) && ((InputAsUint & kQuietNanFPBit) == 0);
649 }
650 
is_snan(double input)651 static bool is_snan(double input) {
652   uint64_t kQuietNanDPBit = 1L << 51;
653   uint64_t InputAsUint = bit_cast<uint64_t>(input);
654   return isnan(input) && ((InputAsUint & kQuietNanDPBit) == 0);
655 }
656 
set_last_debugger_input(char * input)657 void Simulator::set_last_debugger_input(char* input) {
658   DeleteArray(last_debugger_input_);
659   last_debugger_input_ = input;
660 }
661 
SetRedirectInstruction(Instruction * instruction)662 void Simulator::SetRedirectInstruction(Instruction* instruction) {
663   instruction->SetInstructionBits(rtCallRedirInstr | kCallRtRedirected);
664 }
665 
FlushICache(base::CustomMatcherHashMap * i_cache,void * start_addr,size_t size)666 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
667                             void* start_addr, size_t size) {
668   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
669   int intra_line = (start & CachePage::kLineMask);
670   start -= intra_line;
671   size += intra_line;
672   size = ((size - 1) | CachePage::kLineMask) + 1;
673   int offset = (start & CachePage::kPageMask);
674   while (!AllOnOnePage(start, size - 1)) {
675     int bytes_to_flush = CachePage::kPageSize - offset;
676     FlushOnePage(i_cache, start, bytes_to_flush);
677     start += bytes_to_flush;
678     size -= bytes_to_flush;
679     DCHECK_EQ(0, static_cast<int>(start & CachePage::kPageMask));
680     offset = 0;
681   }
682   if (size != 0) {
683     FlushOnePage(i_cache, start, size);
684   }
685 }
686 
GetCachePage(base::CustomMatcherHashMap * i_cache,void * page)687 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
688                                    void* page) {
689   base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
690   if (entry->value == nullptr) {
691     CachePage* new_page = new CachePage();
692     entry->value = new_page;
693   }
694   return reinterpret_cast<CachePage*>(entry->value);
695 }
696 
697 // Flush from start up to and not including start + size.
FlushOnePage(base::CustomMatcherHashMap * i_cache,intptr_t start,int size)698 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
699                              intptr_t start, int size) {
700   DCHECK_LE(size, CachePage::kPageSize);
701   DCHECK(AllOnOnePage(start, size - 1));
702   DCHECK_EQ(start & CachePage::kLineMask, 0);
703   DCHECK_EQ(size & CachePage::kLineMask, 0);
704   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
705   int offset = (start & CachePage::kPageMask);
706   CachePage* cache_page = GetCachePage(i_cache, page);
707   char* valid_bytemap = cache_page->ValidityByte(offset);
708   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
709 }
710 
CheckICache(base::CustomMatcherHashMap * i_cache,Instruction * instr)711 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
712                             Instruction* instr) {
713   intptr_t address = reinterpret_cast<intptr_t>(instr);
714   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
715   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
716   int offset = (address & CachePage::kPageMask);
717   CachePage* cache_page = GetCachePage(i_cache, page);
718   char* cache_valid_byte = cache_page->ValidityByte(offset);
719   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
720   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
721   if (cache_hit) {
722     // Check that the data in memory matches the contents of the I-cache.
723     CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
724                        cache_page->CachedData(offset), kInstrSize));
725   } else {
726     // Cache miss.  Load memory into the cache.
727     memcpy(cached_line, line, CachePage::kLineLength);
728     *cache_valid_byte = CachePage::LINE_VALID;
729   }
730 }
731 
Simulator(Isolate * isolate)732 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
733 // Set up simulator support first. Some of this information is needed to
734 // setup the architecture state.
735 #if V8_TARGET_ARCH_PPC64
736   size_t stack_size = FLAG_sim_stack_size * KB;
737 #else
738   size_t stack_size = MB;  // allocate 1MB for stack
739 #endif
740   stack_size += 2 * stack_protection_size_;
741   stack_ = reinterpret_cast<char*>(base::Malloc(stack_size));
742   pc_modified_ = false;
743   icount_ = 0;
744   break_pc_ = nullptr;
745   break_instr_ = 0;
746 
747   // Set up architecture state.
748   // All registers are initialized to zero to start with.
749   for (int i = 0; i < kNumGPRs; i++) {
750     registers_[i] = 0;
751   }
752   condition_reg_ = 0;
753   fp_condition_reg_ = 0;
754   special_reg_pc_ = 0;
755   special_reg_lr_ = 0;
756   special_reg_ctr_ = 0;
757 
758   // Initializing FP registers.
759   for (int i = 0; i < kNumFPRs; i++) {
760     fp_registers_[i] = 0.0;
761   }
762 
763   // The sp is initialized to point to the bottom (high address) of the
764   // allocated stack area. To be safe in potential stack underflows we leave
765   // some buffer below.
766   registers_[sp] =
767       reinterpret_cast<intptr_t>(stack_) + stack_size - stack_protection_size_;
768 
769   last_debugger_input_ = nullptr;
770 }
771 
~Simulator()772 Simulator::~Simulator() { base::Free(stack_); }
773 
774 // Get the active Simulator for the current thread.
current(Isolate * isolate)775 Simulator* Simulator::current(Isolate* isolate) {
776   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
777       isolate->FindOrAllocatePerThreadDataForThisThread();
778   DCHECK_NOT_NULL(isolate_data);
779 
780   Simulator* sim = isolate_data->simulator();
781   if (sim == nullptr) {
782     // TODO(146): delete the simulator object when a thread/isolate goes away.
783     sim = new Simulator(isolate);
784     isolate_data->set_simulator(sim);
785   }
786   return sim;
787 }
788 
789 // Sets the register in the architecture state.
set_register(int reg,intptr_t value)790 void Simulator::set_register(int reg, intptr_t value) {
791   DCHECK((reg >= 0) && (reg < kNumGPRs));
792   registers_[reg] = value;
793 }
794 
795 // Get the register from the architecture state.
get_register(int reg) const796 intptr_t Simulator::get_register(int reg) const {
797   DCHECK((reg >= 0) && (reg < kNumGPRs));
798   // Stupid code added to avoid bug in GCC.
799   // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
800   if (reg >= kNumGPRs) return 0;
801   // End stupid code.
802   return registers_[reg];
803 }
804 
get_double_from_register_pair(int reg)805 double Simulator::get_double_from_register_pair(int reg) {
806   DCHECK((reg >= 0) && (reg < kNumGPRs) && ((reg % 2) == 0));
807 
808   double dm_val = 0.0;
809 #if !V8_TARGET_ARCH_PPC64  // doesn't make sense in 64bit mode
810   // Read the bits from the unsigned integer register_[] array
811   // into the double precision floating point value and return it.
812   char buffer[sizeof(fp_registers_[0])];
813   memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
814   memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
815 #endif
816   return (dm_val);
817 }
818 
819 // Raw access to the PC register.
set_pc(intptr_t value)820 void Simulator::set_pc(intptr_t value) {
821   pc_modified_ = true;
822   special_reg_pc_ = value;
823 }
824 
has_bad_pc() const825 bool Simulator::has_bad_pc() const {
826   return ((special_reg_pc_ == bad_lr) || (special_reg_pc_ == end_sim_pc));
827 }
828 
829 // Raw access to the PC register without the special adjustment when reading.
get_pc() const830 intptr_t Simulator::get_pc() const { return special_reg_pc_; }
831 
832 // Accessor to the internal Link Register
get_lr() const833 intptr_t Simulator::get_lr() const { return special_reg_lr_; }
834 
835 // Runtime FP routines take:
836 // - two double arguments
837 // - one double argument and zero or one integer arguments.
838 // All are consructed here from d1, d2 and r3.
GetFpArgs(double * x,double * y,intptr_t * z)839 void Simulator::GetFpArgs(double* x, double* y, intptr_t* z) {
840   *x = get_double_from_d_register(1);
841   *y = get_double_from_d_register(2);
842   *z = get_register(3);
843 }
844 
845 // The return value is in d1.
SetFpResult(const double & result)846 void Simulator::SetFpResult(const double& result) {
847   set_d_register_from_double(1, result);
848 }
849 
TrashCallerSaveRegisters()850 void Simulator::TrashCallerSaveRegisters() {
851 // We don't trash the registers with the return value.
852 #if 0  // A good idea to trash volatile registers, needs to be done
853   registers_[2] = 0x50BAD4U;
854   registers_[3] = 0x50BAD4U;
855   registers_[12] = 0x50BAD4U;
856 #endif
857 }
858 
859 #define GENERATE_RW_FUNC(size, type)                             \
860   type Simulator::Read##size(uintptr_t addr) {                   \
861     type value;                                                  \
862     Read(addr, &value);                                          \
863     return value;                                                \
864   }                                                              \
865   type Simulator::ReadEx##size(uintptr_t addr) {                 \
866     type value;                                                  \
867     ReadEx(addr, &value);                                        \
868     return value;                                                \
869   }                                                              \
870   void Simulator::Write##size(uintptr_t addr, type value) {      \
871     Write(addr, value);                                          \
872   }                                                              \
873   int32_t Simulator::WriteEx##size(uintptr_t addr, type value) { \
874     return WriteEx(addr, value);                                 \
875   }
876 
RW_VAR_LIST(GENERATE_RW_FUNC)877 RW_VAR_LIST(GENERATE_RW_FUNC)
878 #undef GENERATE_RW_FUNC
879 
880 // Returns the limit of the stack area to enable checking for stack overflows.
881 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
882   // The simulator uses a separate JS stack. If we have exhausted the C stack,
883   // we also drop down the JS limit to reflect the exhaustion on the JS stack.
884   if (base::Stack::GetCurrentStackPosition() < c_limit) {
885     return reinterpret_cast<uintptr_t>(get_sp());
886   }
887 
888   // Otherwise the limit is the JS stack. Leave a safety margin to prevent
889   // overrunning the stack when pushing values.
890   return reinterpret_cast<uintptr_t>(stack_) + stack_protection_size_;
891 }
892 
893 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)894 void Simulator::Format(Instruction* instr, const char* format) {
895   PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
896          reinterpret_cast<intptr_t>(instr), format);
897   UNIMPLEMENTED();
898 }
899 
900 // Calculate C flag value for additions.
CarryFrom(int32_t left,int32_t right,int32_t carry)901 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
902   uint32_t uleft = static_cast<uint32_t>(left);
903   uint32_t uright = static_cast<uint32_t>(right);
904   uint32_t urest = 0xFFFFFFFFU - uleft;
905 
906   return (uright > urest) ||
907          (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
908 }
909 
910 // Calculate C flag value for subtractions.
BorrowFrom(int32_t left,int32_t right)911 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
912   uint32_t uleft = static_cast<uint32_t>(left);
913   uint32_t uright = static_cast<uint32_t>(right);
914 
915   return (uright > uleft);
916 }
917 
918 // Calculate V flag value for additions and subtractions.
OverflowFrom(int32_t alu_out,int32_t left,int32_t right,bool addition)919 bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
920                              bool addition) {
921   bool overflow;
922   if (addition) {
923     // operands have the same sign
924     overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
925                // and operands and result have different sign
926                && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
927   } else {
928     // operands have different signs
929     overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
930                // and first operand and result have different signs
931                && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
932   }
933   return overflow;
934 }
935 
decodeObjectPair(ObjectPair * pair,intptr_t * x,intptr_t * y)936 static void decodeObjectPair(ObjectPair* pair, intptr_t* x, intptr_t* y) {
937   *x = static_cast<intptr_t>(pair->x);
938   *y = static_cast<intptr_t>(pair->y);
939 }
940 
941 // Calls into the V8 runtime.
942 using SimulatorRuntimeCall = intptr_t (*)(
943     intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4,
944     intptr_t arg5, intptr_t arg6, intptr_t arg7, intptr_t arg8, intptr_t arg9,
945     intptr_t arg10, intptr_t arg11, intptr_t arg12, intptr_t arg13,
946     intptr_t arg14, intptr_t arg15, intptr_t arg16, intptr_t arg17,
947     intptr_t arg18, intptr_t arg19);
948 using SimulatorRuntimePairCall = ObjectPair (*)(
949     intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4,
950     intptr_t arg5, intptr_t arg6, intptr_t arg7, intptr_t arg8, intptr_t arg9,
951     intptr_t arg10, intptr_t arg11, intptr_t arg12, intptr_t arg13,
952     intptr_t arg14, intptr_t arg15, intptr_t arg16, intptr_t arg17,
953     intptr_t arg18, intptr_t arg19);
954 
955 // These prototypes handle the four types of FP calls.
956 using SimulatorRuntimeCompareCall = int (*)(double darg0, double darg1);
957 using SimulatorRuntimeFPFPCall = double (*)(double darg0, double darg1);
958 using SimulatorRuntimeFPCall = double (*)(double darg0);
959 using SimulatorRuntimeFPIntCall = double (*)(double darg0, intptr_t arg0);
960 
961 // This signature supports direct call in to API function native callback
962 // (refer to InvocationCallback in v8.h).
963 using SimulatorRuntimeDirectApiCall = void (*)(intptr_t arg0);
964 using SimulatorRuntimeProfilingApiCall = void (*)(intptr_t arg0, void* arg1);
965 
966 // This signature supports direct call to accessor getter callback.
967 using SimulatorRuntimeDirectGetterCall = void (*)(intptr_t arg0, intptr_t arg1);
968 using SimulatorRuntimeProfilingGetterCall = void (*)(intptr_t arg0,
969                                                      intptr_t arg1, void* arg2);
970 
971 // Software interrupt instructions are used by the simulator to call into the
972 // C-based V8 runtime.
SoftwareInterrupt(Instruction * instr)973 void Simulator::SoftwareInterrupt(Instruction* instr) {
974   int svc = instr->SvcValue();
975   switch (svc) {
976     case kCallRtRedirected: {
977       // Check if stack is aligned. Error if not aligned is reported below to
978       // include information on the function called.
979       bool stack_aligned =
980           (get_register(sp) & (::v8::internal::FLAG_sim_stack_alignment - 1)) ==
981           0;
982       Redirection* redirection = Redirection::FromInstruction(instr);
983       const int kArgCount = 20;
984       const int kRegisterArgCount = 8;
985       int arg0_regnum = 3;
986       intptr_t result_buffer = 0;
987       bool uses_result_buffer =
988           (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR &&
989            !ABI_RETURNS_OBJECT_PAIRS_IN_REGS);
990       if (uses_result_buffer) {
991         result_buffer = get_register(r3);
992         arg0_regnum++;
993       }
994       intptr_t arg[kArgCount];
995       // First eight arguments in registers r3-r10.
996       for (int i = 0; i < kRegisterArgCount; i++) {
997         arg[i] = get_register(arg0_regnum + i);
998       }
999       intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
1000       // Remaining argument on stack
1001       for (int i = kRegisterArgCount, j = 0; i < kArgCount; i++, j++) {
1002         arg[i] = stack_pointer[kStackFrameExtraParamSlot + j];
1003       }
1004       STATIC_ASSERT(kArgCount == kRegisterArgCount + 12);
1005       STATIC_ASSERT(kMaxCParameters == kArgCount);
1006       bool fp_call =
1007           (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1008           (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1009           (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1010           (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1011       // This is dodgy but it works because the C entry stubs are never moved.
1012       // See comment in codegen-arm.cc and bug 1242173.
1013       intptr_t saved_lr = special_reg_lr_;
1014       intptr_t external =
1015           reinterpret_cast<intptr_t>(redirection->external_function());
1016       if (fp_call) {
1017         double dval0, dval1;  // one or two double parameters
1018         intptr_t ival;        // zero or one integer parameters
1019         int iresult = 0;      // integer return value
1020         double dresult = 0;   // double return value
1021         GetFpArgs(&dval0, &dval1, &ival);
1022         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1023           SimulatorRuntimeCall generic_target =
1024               reinterpret_cast<SimulatorRuntimeCall>(external);
1025           switch (redirection->type()) {
1026             case ExternalReference::BUILTIN_FP_FP_CALL:
1027             case ExternalReference::BUILTIN_COMPARE_CALL:
1028               PrintF("Call to host function at %p with args %f, %f",
1029                      reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1030                      dval0, dval1);
1031               break;
1032             case ExternalReference::BUILTIN_FP_CALL:
1033               PrintF("Call to host function at %p with arg %f",
1034                      reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1035                      dval0);
1036               break;
1037             case ExternalReference::BUILTIN_FP_INT_CALL:
1038               PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
1039                      reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1040                      dval0, ival);
1041               break;
1042             default:
1043               UNREACHABLE();
1044           }
1045           if (!stack_aligned) {
1046             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1047                    get_register(sp));
1048           }
1049           PrintF("\n");
1050         }
1051         CHECK(stack_aligned);
1052         switch (redirection->type()) {
1053           case ExternalReference::BUILTIN_COMPARE_CALL: {
1054             SimulatorRuntimeCompareCall target =
1055                 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1056             iresult = target(dval0, dval1);
1057             set_register(r3, iresult);
1058             break;
1059           }
1060           case ExternalReference::BUILTIN_FP_FP_CALL: {
1061             SimulatorRuntimeFPFPCall target =
1062                 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1063             dresult = target(dval0, dval1);
1064             SetFpResult(dresult);
1065             break;
1066           }
1067           case ExternalReference::BUILTIN_FP_CALL: {
1068             SimulatorRuntimeFPCall target =
1069                 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1070             dresult = target(dval0);
1071             SetFpResult(dresult);
1072             break;
1073           }
1074           case ExternalReference::BUILTIN_FP_INT_CALL: {
1075             SimulatorRuntimeFPIntCall target =
1076                 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1077             dresult = target(dval0, ival);
1078             SetFpResult(dresult);
1079             break;
1080           }
1081           default:
1082             UNREACHABLE();
1083         }
1084         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1085           switch (redirection->type()) {
1086             case ExternalReference::BUILTIN_COMPARE_CALL:
1087               PrintF("Returned %08x\n", iresult);
1088               break;
1089             case ExternalReference::BUILTIN_FP_FP_CALL:
1090             case ExternalReference::BUILTIN_FP_CALL:
1091             case ExternalReference::BUILTIN_FP_INT_CALL:
1092               PrintF("Returned %f\n", dresult);
1093               break;
1094             default:
1095               UNREACHABLE();
1096           }
1097         }
1098       } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1099         // See callers of MacroAssembler::CallApiFunctionAndReturn for
1100         // explanation of register usage.
1101         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1102           PrintF("Call to host function at %p args %08" V8PRIxPTR,
1103                  reinterpret_cast<void*>(external), arg[0]);
1104           if (!stack_aligned) {
1105             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1106                    get_register(sp));
1107           }
1108           PrintF("\n");
1109         }
1110         CHECK(stack_aligned);
1111         SimulatorRuntimeDirectApiCall target =
1112             reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1113         target(arg[0]);
1114       } else if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
1115         // See callers of MacroAssembler::CallApiFunctionAndReturn for
1116         // explanation of register usage.
1117         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1118           PrintF("Call to host function at %p args %08" V8PRIxPTR
1119                  " %08" V8PRIxPTR,
1120                  reinterpret_cast<void*>(external), arg[0], arg[1]);
1121           if (!stack_aligned) {
1122             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1123                    get_register(sp));
1124           }
1125           PrintF("\n");
1126         }
1127         CHECK(stack_aligned);
1128         SimulatorRuntimeProfilingApiCall target =
1129             reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1130         target(arg[0], Redirection::ReverseRedirection(arg[1]));
1131       } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1132         // See callers of MacroAssembler::CallApiFunctionAndReturn for
1133         // explanation of register usage.
1134         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1135           PrintF("Call to host function at %p args %08" V8PRIxPTR
1136                  " %08" V8PRIxPTR,
1137                  reinterpret_cast<void*>(external), arg[0], arg[1]);
1138           if (!stack_aligned) {
1139             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1140                    get_register(sp));
1141           }
1142           PrintF("\n");
1143         }
1144         CHECK(stack_aligned);
1145         SimulatorRuntimeDirectGetterCall target =
1146             reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1147         if (!ABI_PASSES_HANDLES_IN_REGS) {
1148           arg[0] = bit_cast<intptr_t>(arg[0]);
1149         }
1150         target(arg[0], arg[1]);
1151       } else if (redirection->type() ==
1152                  ExternalReference::PROFILING_GETTER_CALL) {
1153         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1154           PrintF("Call to host function at %p args %08" V8PRIxPTR
1155                  " %08" V8PRIxPTR " %08" V8PRIxPTR,
1156                  reinterpret_cast<void*>(external), arg[0], arg[1], arg[2]);
1157           if (!stack_aligned) {
1158             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1159                    get_register(sp));
1160           }
1161           PrintF("\n");
1162         }
1163         CHECK(stack_aligned);
1164         SimulatorRuntimeProfilingGetterCall target =
1165             reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1166         if (!ABI_PASSES_HANDLES_IN_REGS) {
1167           arg[0] = bit_cast<intptr_t>(arg[0]);
1168         }
1169         target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2]));
1170       } else {
1171         // builtin call.
1172         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1173           SimulatorRuntimeCall target =
1174               reinterpret_cast<SimulatorRuntimeCall>(external);
1175           PrintF(
1176               "Call to host function at %p,\n"
1177               "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1178               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1179               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1180               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1181               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1182               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
1183               ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
1184               reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg[0], arg[1],
1185               arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8], arg[9],
1186               arg[10], arg[11], arg[12], arg[13], arg[14], arg[15], arg[16],
1187               arg[17], arg[18], arg[19]);
1188           if (!stack_aligned) {
1189             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
1190                    get_register(sp));
1191           }
1192           PrintF("\n");
1193         }
1194         CHECK(stack_aligned);
1195         if (redirection->type() == ExternalReference::BUILTIN_CALL_PAIR) {
1196           SimulatorRuntimePairCall target =
1197               reinterpret_cast<SimulatorRuntimePairCall>(external);
1198           ObjectPair result =
1199               target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6],
1200                      arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13],
1201                      arg[14], arg[15], arg[16], arg[17], arg[18], arg[19]);
1202           intptr_t x;
1203           intptr_t y;
1204           decodeObjectPair(&result, &x, &y);
1205           if (::v8::internal::FLAG_trace_sim) {
1206             PrintF("Returned {%08" V8PRIxPTR ", %08" V8PRIxPTR "}\n", x, y);
1207           }
1208           if (ABI_RETURNS_OBJECT_PAIRS_IN_REGS) {
1209             set_register(r3, x);
1210             set_register(r4, y);
1211           } else {
1212             memcpy(reinterpret_cast<void*>(result_buffer), &result,
1213                    sizeof(ObjectPair));
1214             set_register(r3, result_buffer);
1215           }
1216         } else {
1217           // FAST_C_CALL is temporarily handled here as well, because we lack
1218           // proper support for direct C calls with FP params in the simulator.
1219           // The generic BUILTIN_CALL path assumes all parameters are passed in
1220           // the GP registers, thus supporting calling the slow callback without
1221           // crashing. The reason for that is that in the mjsunit tests we check
1222           // the `fast_c_api.supports_fp_params` (which is false on
1223           // non-simulator builds for arm/arm64), thus we expect that the slow
1224           // path will be called. And since the slow path passes the arguments
1225           // as a `const FunctionCallbackInfo<Value>&` (which is a GP argument),
1226           // the call is made correctly.
1227           DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
1228                  redirection->type() == ExternalReference::FAST_C_CALL);
1229           SimulatorRuntimeCall target =
1230               reinterpret_cast<SimulatorRuntimeCall>(external);
1231           intptr_t result =
1232               target(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6],
1233                      arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13],
1234                      arg[14], arg[15], arg[16], arg[17], arg[18], arg[19]);
1235           if (::v8::internal::FLAG_trace_sim) {
1236             PrintF("Returned %08" V8PRIxPTR "\n", result);
1237           }
1238           set_register(r3, result);
1239         }
1240       }
1241       set_pc(saved_lr);
1242       break;
1243     }
1244     case kBreakpoint:
1245       PPCDebugger(this).Debug();
1246       break;
1247     // stop uses all codes greater than 1 << 23.
1248     default:
1249       if (svc >= (1 << 23)) {
1250         uint32_t code = svc & kStopCodeMask;
1251         if (isWatchedStop(code)) {
1252           IncreaseStopCounter(code);
1253         }
1254         // Stop if it is enabled, otherwise go on jumping over the stop
1255         // and the message address.
1256         if (isEnabledStop(code)) {
1257           if (code != kMaxStopCode) {
1258             PrintF("Simulator hit stop %u. ", code);
1259           } else {
1260             PrintF("Simulator hit stop. ");
1261           }
1262           DebugAtNextPC();
1263         } else {
1264           set_pc(get_pc() + kInstrSize + kSystemPointerSize);
1265         }
1266       } else {
1267         // This is not a valid svc code.
1268         UNREACHABLE();
1269       }
1270   }
1271 }
1272 
1273 // Stop helper functions.
isStopInstruction(Instruction * instr)1274 bool Simulator::isStopInstruction(Instruction* instr) {
1275   return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1276 }
1277 
isWatchedStop(uint32_t code)1278 bool Simulator::isWatchedStop(uint32_t code) {
1279   DCHECK_LE(code, kMaxStopCode);
1280   return code < kNumOfWatchedStops;
1281 }
1282 
isEnabledStop(uint32_t code)1283 bool Simulator::isEnabledStop(uint32_t code) {
1284   DCHECK_LE(code, kMaxStopCode);
1285   // Unwatched stops are always enabled.
1286   return !isWatchedStop(code) ||
1287          !(watched_stops_[code].count & kStopDisabledBit);
1288 }
1289 
EnableStop(uint32_t code)1290 void Simulator::EnableStop(uint32_t code) {
1291   DCHECK(isWatchedStop(code));
1292   if (!isEnabledStop(code)) {
1293     watched_stops_[code].count &= ~kStopDisabledBit;
1294   }
1295 }
1296 
DisableStop(uint32_t code)1297 void Simulator::DisableStop(uint32_t code) {
1298   DCHECK(isWatchedStop(code));
1299   if (isEnabledStop(code)) {
1300     watched_stops_[code].count |= kStopDisabledBit;
1301   }
1302 }
1303 
IncreaseStopCounter(uint32_t code)1304 void Simulator::IncreaseStopCounter(uint32_t code) {
1305   DCHECK_LE(code, kMaxStopCode);
1306   DCHECK(isWatchedStop(code));
1307   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
1308     PrintF(
1309         "Stop counter for code %i has overflowed.\n"
1310         "Enabling this code and reseting the counter to 0.\n",
1311         code);
1312     watched_stops_[code].count = 0;
1313     EnableStop(code);
1314   } else {
1315     watched_stops_[code].count++;
1316   }
1317 }
1318 
1319 // Print a stop status.
PrintStopInfo(uint32_t code)1320 void Simulator::PrintStopInfo(uint32_t code) {
1321   DCHECK_LE(code, kMaxStopCode);
1322   if (!isWatchedStop(code)) {
1323     PrintF("Stop not watched.");
1324   } else {
1325     const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1326     int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1327     // Don't print the state of unused breakpoints.
1328     if (count != 0) {
1329       if (watched_stops_[code].desc) {
1330         PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code,
1331                state, count, watched_stops_[code].desc);
1332       } else {
1333         PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state,
1334                count);
1335       }
1336     }
1337   }
1338 }
1339 
SetCR0(intptr_t result,bool setSO)1340 void Simulator::SetCR0(intptr_t result, bool setSO) {
1341   int bf = 0;
1342   if (result < 0) {
1343     bf |= 0x80000000;
1344   }
1345   if (result > 0) {
1346     bf |= 0x40000000;
1347   }
1348   if (result == 0) {
1349     bf |= 0x20000000;
1350   }
1351   if (setSO) {
1352     bf |= 0x10000000;
1353   }
1354   condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
1355 }
1356 
SetCR6(bool true_for_all,bool false_for_all)1357 void Simulator::SetCR6(bool true_for_all, bool false_for_all) {
1358   int32_t clear_cr6_mask = 0xFFFFFF0F;
1359   if (true_for_all) {
1360     condition_reg_ = (condition_reg_ & clear_cr6_mask) | 0x80;
1361   } else if (false_for_all) {
1362     condition_reg_ = (condition_reg_ & clear_cr6_mask) | 0x20;
1363   }
1364 }
1365 
ExecuteBranchConditional(Instruction * instr,BCType type)1366 void Simulator::ExecuteBranchConditional(Instruction* instr, BCType type) {
1367   int bo = instr->Bits(25, 21) << 21;
1368   int condition_bit = instr->Bits(20, 16);
1369   int condition_mask = 0x80000000 >> condition_bit;
1370   switch (bo) {
1371     case DCBNZF:  // Decrement CTR; branch if CTR != 0 and condition false
1372     case DCBEZF:  // Decrement CTR; branch if CTR == 0 and condition false
1373       UNIMPLEMENTED();
1374     case BF: {  // Branch if condition false
1375       if (condition_reg_ & condition_mask) return;
1376       break;
1377     }
1378     case DCBNZT:  // Decrement CTR; branch if CTR != 0 and condition true
1379     case DCBEZT:  // Decrement CTR; branch if CTR == 0 and condition true
1380       UNIMPLEMENTED();
1381     case BT: {  // Branch if condition true
1382       if (!(condition_reg_ & condition_mask)) return;
1383       break;
1384     }
1385     case DCBNZ:  // Decrement CTR; branch if CTR != 0
1386     case DCBEZ:  // Decrement CTR; branch if CTR == 0
1387       special_reg_ctr_ -= 1;
1388       if ((special_reg_ctr_ == 0) != (bo == DCBEZ)) return;
1389       break;
1390     case BA: {  // Branch always
1391       break;
1392     }
1393     default:
1394       UNIMPLEMENTED();  // Invalid encoding
1395   }
1396 
1397   intptr_t old_pc = get_pc();
1398 
1399   switch (type) {
1400     case BC_OFFSET: {
1401       int offset = (instr->Bits(15, 2) << 18) >> 16;
1402       set_pc(old_pc + offset);
1403       break;
1404     }
1405     case BC_LINK_REG:
1406       set_pc(special_reg_lr_);
1407       break;
1408     case BC_CTR_REG:
1409       set_pc(special_reg_ctr_);
1410       break;
1411   }
1412 
1413   if (instr->Bit(0) == 1) {  // LK flag set
1414     special_reg_lr_ = old_pc + 4;
1415   }
1416 }
1417 
1418 // Vector instruction helpers.
1419 #define GET_ADDRESS(a, b, a_val, b_val)          \
1420   intptr_t a_val = a == 0 ? 0 : get_register(a); \
1421   intptr_t b_val = get_register(b);
1422 #define DECODE_VX_INSTRUCTION(d, a, b, source_or_target) \
1423   int d = instr->R##source_or_target##Value();           \
1424   int a = instr->RAValue();                              \
1425   int b = instr->RBValue();
1426 #define FOR_EACH_LANE(i, type) \
1427   for (uint32_t i = 0; i < kSimd128Size / sizeof(type); i++)
1428 template <typename A, typename T, typename Operation>
VectorCompareOp(Simulator * sim,Instruction * instr,bool is_fp,Operation op)1429 void VectorCompareOp(Simulator* sim, Instruction* instr, bool is_fp,
1430                      Operation op) {
1431   DECODE_VX_INSTRUCTION(t, a, b, T)
1432   bool true_for_all = true, false_for_all = true;
1433   FOR_EACH_LANE(i, A) {
1434     A a_val = sim->get_simd_register_by_lane<A>(a, i);
1435     A b_val = sim->get_simd_register_by_lane<A>(b, i);
1436     T t_val = 0;
1437     bool is_not_nan = is_fp ? !isnan(a_val) && !isnan(b_val) : true;
1438     if (is_not_nan && op(a_val, b_val)) {
1439       false_for_all = false;
1440       t_val = -1;  // Set all bits to 1 indicating true.
1441     } else {
1442       true_for_all = false;
1443     }
1444     sim->set_simd_register_by_lane<T>(t, i, t_val);
1445   }
1446   if (instr->Bit(10)) {  // RC bit set.
1447     sim->SetCR6(true_for_all, false_for_all);
1448   }
1449 }
1450 
1451 template <typename S, typename T>
VectorConverFromFPSaturate(Simulator * sim,Instruction * instr,T min_val,T max_val,bool even_lane_result=false)1452 void VectorConverFromFPSaturate(Simulator* sim, Instruction* instr, T min_val,
1453                                 T max_val, bool even_lane_result = false) {
1454   int t = instr->RTValue();
1455   int b = instr->RBValue();
1456   FOR_EACH_LANE(i, S) {
1457     T t_val;
1458     double b_val = static_cast<double>(sim->get_simd_register_by_lane<S>(b, i));
1459     if (isnan(b_val)) {
1460       t_val = min_val;
1461     } else {
1462       // Round Towards Zero.
1463       b_val = std::trunc(b_val);
1464       if (b_val < min_val) {
1465         t_val = min_val;
1466       } else if (b_val > max_val) {
1467         t_val = max_val;
1468       } else {
1469         t_val = static_cast<T>(b_val);
1470       }
1471     }
1472     sim->set_simd_register_by_lane<T>(t, even_lane_result ? 2 * i : i, t_val);
1473   }
1474 }
1475 
1476 template <typename S, typename T>
VectorPackSaturate(Simulator * sim,Instruction * instr,S min_val,S max_val)1477 void VectorPackSaturate(Simulator* sim, Instruction* instr, S min_val,
1478                         S max_val) {
1479   DECODE_VX_INSTRUCTION(t, a, b, T)
1480   int src = a;
1481   int count = 0;
1482   S value = 0;
1483   // Setup a temp array to avoid overwriting dst mid loop.
1484   T temps[kSimd128Size / sizeof(T)] = {0};
1485   for (size_t i = 0; i < kSimd128Size / sizeof(T); i++, count++) {
1486     if (count == kSimd128Size / sizeof(S)) {
1487       src = b;
1488       count = 0;
1489     }
1490     value = sim->get_simd_register_by_lane<S>(src, count);
1491     if (value > max_val) {
1492       value = max_val;
1493     } else if (value < min_val) {
1494       value = min_val;
1495     }
1496     temps[i] = static_cast<T>(value);
1497   }
1498   FOR_EACH_LANE(i, T) { sim->set_simd_register_by_lane<T>(t, i, temps[i]); }
1499 }
1500 
1501 template <typename T>
VSXFPMin(T x,T y)1502 T VSXFPMin(T x, T y) {
1503   // Handle NaN.
1504   // TODO(miladfarca): include the payload of src1.
1505   if (std::isnan(x) && std::isnan(y)) return NAN;
1506   // Handle +0 and -0.
1507   if (std::signbit(x) < std::signbit(y)) return y;
1508   if (std::signbit(y) < std::signbit(x)) return x;
1509   return std::fmin(x, y);
1510 }
1511 
1512 template <typename T>
VSXFPMax(T x,T y)1513 T VSXFPMax(T x, T y) {
1514   // Handle NaN.
1515   // TODO(miladfarca): include the payload of src1.
1516   if (std::isnan(x) && std::isnan(y)) return NAN;
1517   // Handle +0 and -0.
1518   if (std::signbit(x) < std::signbit(y)) return x;
1519   if (std::signbit(y) < std::signbit(x)) return y;
1520   return std::fmax(x, y);
1521 }
1522 
VMXFPMin(float x,float y)1523 float VMXFPMin(float x, float y) {
1524   // Handle NaN.
1525   if (std::isnan(x) || std::isnan(y)) return NAN;
1526   // Handle +0 and -0.
1527   if (std::signbit(x) < std::signbit(y)) return y;
1528   if (std::signbit(y) < std::signbit(x)) return x;
1529   return x < y ? x : y;
1530 }
1531 
VMXFPMax(float x,float y)1532 float VMXFPMax(float x, float y) {
1533   // Handle NaN.
1534   if (std::isnan(x) || std::isnan(y)) return NAN;
1535   // Handle +0 and -0.
1536   if (std::signbit(x) < std::signbit(y)) return x;
1537   if (std::signbit(y) < std::signbit(x)) return y;
1538   return x > y ? x : y;
1539 }
1540 
ExecuteGeneric(Instruction * instr)1541 void Simulator::ExecuteGeneric(Instruction* instr) {
1542   uint32_t opcode = instr->OpcodeBase();
1543   switch (opcode) {
1544       // Prefixed instructions.
1545     case PLOAD_STORE_8LS:
1546     case PLOAD_STORE_MLS: {
1547       // TODO(miladfarca): Simulate PC-relative capability indicated by the R
1548       // bit.
1549       DCHECK_NE(instr->Bit(20), 1);
1550       // Read prefix value.
1551       uint64_t prefix_value = instr->Bits(17, 0);
1552       // Read suffix (next instruction).
1553       Instruction* next_instr = bit_cast<Instruction*>(get_pc() + kInstrSize);
1554       uint16_t suffix_value = next_instr->Bits(15, 0);
1555       int64_t im_val = SIGN_EXT_IMM34((prefix_value << 16) | suffix_value);
1556       switch (next_instr->OpcodeBase()) {
1557           // Prefixed ADDI.
1558         case ADDI: {
1559           int rt = next_instr->RTValue();
1560           int ra = next_instr->RAValue();
1561           intptr_t alu_out;
1562           if (ra == 0) {
1563             alu_out = im_val;
1564           } else {
1565             intptr_t ra_val = get_register(ra);
1566             alu_out = ra_val + im_val;
1567           }
1568           set_register(rt, alu_out);
1569           break;
1570         }
1571           // Prefixed LBZ.
1572         case LBZ: {
1573           int ra = next_instr->RAValue();
1574           int rt = next_instr->RTValue();
1575           intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1576           set_register(rt, ReadB(ra_val + im_val) & 0xFF);
1577           break;
1578         }
1579           // Prefixed LHZ.
1580         case LHZ: {
1581           int ra = next_instr->RAValue();
1582           int rt = next_instr->RTValue();
1583           intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1584           uintptr_t result = ReadHU(ra_val + im_val) & 0xFFFF;
1585           set_register(rt, result);
1586           break;
1587         }
1588           // Prefixed LHA.
1589         case LHA: {
1590           int ra = next_instr->RAValue();
1591           int rt = next_instr->RTValue();
1592           intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1593           intptr_t result = ReadH(ra_val + im_val);
1594           set_register(rt, result);
1595           break;
1596         }
1597           // Prefixed LWZ.
1598         case LWZ: {
1599           int ra = next_instr->RAValue();
1600           int rt = next_instr->RTValue();
1601           intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1602           set_register(rt, ReadWU(ra_val + im_val));
1603           break;
1604         }
1605           // Prefixed LWA.
1606         case PPLWA: {
1607           int ra = next_instr->RAValue();
1608           int rt = next_instr->RTValue();
1609           int64_t ra_val = ra == 0 ? 0 : get_register(ra);
1610           set_register(rt, ReadW(ra_val + im_val));
1611           break;
1612         }
1613           // Prefixed LD.
1614         case PPLD: {
1615           int ra = next_instr->RAValue();
1616           int rt = next_instr->RTValue();
1617           int64_t ra_val = ra == 0 ? 0 : get_register(ra);
1618           set_register(rt, ReadDW(ra_val + im_val));
1619           break;
1620         }
1621           // Prefixed LFS.
1622         case LFS: {
1623           int frt = next_instr->RTValue();
1624           int ra = next_instr->RAValue();
1625           intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1626           int32_t val = ReadW(ra_val + im_val);
1627           float* fptr = reinterpret_cast<float*>(&val);
1628 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
1629           // Conversion using double changes sNan to qNan on ia32/x64
1630           if ((val & 0x7F800000) == 0x7F800000) {
1631             int64_t dval = static_cast<int64_t>(val);
1632             dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
1633                    ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) |
1634                    0x0;
1635             set_d_register(frt, dval);
1636           } else {
1637             set_d_register_from_double(frt, static_cast<double>(*fptr));
1638           }
1639 #else
1640           set_d_register_from_double(frt, static_cast<double>(*fptr));
1641 #endif
1642           break;
1643         }
1644           // Prefixed LFD.
1645         case LFD: {
1646           int frt = next_instr->RTValue();
1647           int ra = next_instr->RAValue();
1648           intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
1649           int64_t dptr = ReadDW(ra_val + im_val);
1650           set_d_register(frt, dptr);
1651           break;
1652         }
1653         default:
1654           UNREACHABLE();
1655       }
1656       // We have now executed instructions at this as well as next pc.
1657       set_pc(get_pc() + (2 * kInstrSize));
1658       break;
1659     }
1660     case SUBFIC: {
1661       int rt = instr->RTValue();
1662       int ra = instr->RAValue();
1663       intptr_t ra_val = get_register(ra);
1664       int32_t im_val = instr->Bits(15, 0);
1665       im_val = SIGN_EXT_IMM16(im_val);
1666       intptr_t alu_out = im_val - ra_val;
1667       set_register(rt, alu_out);
1668       // todo - handle RC bit
1669       break;
1670     }
1671     case CMPLI: {
1672       int ra = instr->RAValue();
1673       uint32_t im_val = instr->Bits(15, 0);
1674       int cr = instr->Bits(25, 23);
1675       uint32_t bf = 0;
1676 #if V8_TARGET_ARCH_PPC64
1677       int L = instr->Bit(21);
1678       if (L) {
1679 #endif
1680         uintptr_t ra_val = get_register(ra);
1681         if (ra_val < im_val) {
1682           bf |= 0x80000000;
1683         }
1684         if (ra_val > im_val) {
1685           bf |= 0x40000000;
1686         }
1687         if (ra_val == im_val) {
1688           bf |= 0x20000000;
1689         }
1690 #if V8_TARGET_ARCH_PPC64
1691       } else {
1692         uint32_t ra_val = get_register(ra);
1693         if (ra_val < im_val) {
1694           bf |= 0x80000000;
1695         }
1696         if (ra_val > im_val) {
1697           bf |= 0x40000000;
1698         }
1699         if (ra_val == im_val) {
1700           bf |= 0x20000000;
1701         }
1702       }
1703 #endif
1704       uint32_t condition_mask = 0xF0000000U >> (cr * 4);
1705       uint32_t condition = bf >> (cr * 4);
1706       condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
1707       break;
1708     }
1709     case CMPI: {
1710       int ra = instr->RAValue();
1711       int32_t im_val = instr->Bits(15, 0);
1712       im_val = SIGN_EXT_IMM16(im_val);
1713       int cr = instr->Bits(25, 23);
1714       uint32_t bf = 0;
1715 #if V8_TARGET_ARCH_PPC64
1716       int L = instr->Bit(21);
1717       if (L) {
1718 #endif
1719         intptr_t ra_val = get_register(ra);
1720         if (ra_val < im_val) {
1721           bf |= 0x80000000;
1722         }
1723         if (ra_val > im_val) {
1724           bf |= 0x40000000;
1725         }
1726         if (ra_val == im_val) {
1727           bf |= 0x20000000;
1728         }
1729 #if V8_TARGET_ARCH_PPC64
1730       } else {
1731         int32_t ra_val = get_register(ra);
1732         if (ra_val < im_val) {
1733           bf |= 0x80000000;
1734         }
1735         if (ra_val > im_val) {
1736           bf |= 0x40000000;
1737         }
1738         if (ra_val == im_val) {
1739           bf |= 0x20000000;
1740         }
1741       }
1742 #endif
1743       uint32_t condition_mask = 0xF0000000U >> (cr * 4);
1744       uint32_t condition = bf >> (cr * 4);
1745       condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
1746       break;
1747     }
1748     case ADDIC: {
1749       int rt = instr->RTValue();
1750       int ra = instr->RAValue();
1751       uintptr_t ra_val = get_register(ra);
1752       uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
1753       uintptr_t alu_out = ra_val + im_val;
1754       // Check overflow
1755       if (~ra_val < im_val) {
1756         special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
1757       } else {
1758         special_reg_xer_ &= ~0xF0000000;
1759       }
1760       set_register(rt, alu_out);
1761       break;
1762     }
1763     case ADDI: {
1764       int rt = instr->RTValue();
1765       int ra = instr->RAValue();
1766       int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
1767       intptr_t alu_out;
1768       if (ra == 0) {
1769         alu_out = im_val;
1770       } else {
1771         intptr_t ra_val = get_register(ra);
1772         alu_out = ra_val + im_val;
1773       }
1774       set_register(rt, alu_out);
1775       // todo - handle RC bit
1776       break;
1777     }
1778     case ADDIS: {
1779       int rt = instr->RTValue();
1780       int ra = instr->RAValue();
1781       int32_t im_val = (instr->Bits(15, 0) << 16);
1782       intptr_t alu_out;
1783       if (ra == 0) {  // treat r0 as zero
1784         alu_out = im_val;
1785       } else {
1786         intptr_t ra_val = get_register(ra);
1787         alu_out = ra_val + im_val;
1788       }
1789       set_register(rt, alu_out);
1790       break;
1791     }
1792     case BCX: {
1793       ExecuteBranchConditional(instr, BC_OFFSET);
1794       break;
1795     }
1796     case BX: {
1797       int offset = (instr->Bits(25, 2) << 8) >> 6;
1798       if (instr->Bit(0) == 1) {  // LK flag set
1799         special_reg_lr_ = get_pc() + 4;
1800       }
1801       set_pc(get_pc() + offset);
1802       // todo - AA flag
1803       break;
1804     }
1805     case MCRF:
1806       UNIMPLEMENTED();  // Not used by V8.
1807     case BCLRX:
1808       ExecuteBranchConditional(instr, BC_LINK_REG);
1809       break;
1810     case BCCTRX:
1811       ExecuteBranchConditional(instr, BC_CTR_REG);
1812       break;
1813     case CRNOR:
1814     case RFI:
1815     case CRANDC:
1816       UNIMPLEMENTED();
1817     case ISYNC: {
1818       // todo - simulate isync
1819       break;
1820     }
1821     case CRXOR: {
1822       int bt = instr->Bits(25, 21);
1823       int ba = instr->Bits(20, 16);
1824       int bb = instr->Bits(15, 11);
1825       int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
1826       int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
1827       int bt_val = ba_val ^ bb_val;
1828       bt_val = bt_val << (31 - bt);  // shift bit to correct destination
1829       condition_reg_ &= ~(0x80000000 >> bt);
1830       condition_reg_ |= bt_val;
1831       break;
1832     }
1833     case CREQV: {
1834       int bt = instr->Bits(25, 21);
1835       int ba = instr->Bits(20, 16);
1836       int bb = instr->Bits(15, 11);
1837       int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
1838       int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
1839       int bt_val = 1 - (ba_val ^ bb_val);
1840       bt_val = bt_val << (31 - bt);  // shift bit to correct destination
1841       condition_reg_ &= ~(0x80000000 >> bt);
1842       condition_reg_ |= bt_val;
1843       break;
1844     }
1845     case CRNAND:
1846     case CRAND:
1847     case CRORC:
1848     case CROR: {
1849       UNIMPLEMENTED();  // Not used by V8.
1850     }
1851     case RLWIMIX: {
1852       int ra = instr->RAValue();
1853       int rs = instr->RSValue();
1854       uint32_t rs_val = get_register(rs);
1855       int32_t ra_val = get_register(ra);
1856       int sh = instr->Bits(15, 11);
1857       int mb = instr->Bits(10, 6);
1858       int me = instr->Bits(5, 1);
1859       uint32_t result = base::bits::RotateLeft32(rs_val, sh);
1860       int mask = 0;
1861       if (mb < me + 1) {
1862         int bit = 0x80000000 >> mb;
1863         for (; mb <= me; mb++) {
1864           mask |= bit;
1865           bit >>= 1;
1866         }
1867       } else if (mb == me + 1) {
1868         mask = 0xFFFFFFFF;
1869       } else {                             // mb > me+1
1870         int bit = 0x80000000 >> (me + 1);  // needs to be tested
1871         mask = 0xFFFFFFFF;
1872         for (; me < mb; me++) {
1873           mask ^= bit;
1874           bit >>= 1;
1875         }
1876       }
1877       result &= mask;
1878       ra_val &= ~mask;
1879       result |= ra_val;
1880       set_register(ra, result);
1881       if (instr->Bit(0)) {  // RC bit set
1882         SetCR0(result);
1883       }
1884       break;
1885     }
1886     case RLWINMX:
1887     case RLWNMX: {
1888       int ra = instr->RAValue();
1889       int rs = instr->RSValue();
1890       uint32_t rs_val = get_register(rs);
1891       int sh = 0;
1892       if (opcode == RLWINMX) {
1893         sh = instr->Bits(15, 11);
1894       } else {
1895         int rb = instr->RBValue();
1896         uint32_t rb_val = get_register(rb);
1897         sh = (rb_val & 0x1F);
1898       }
1899       int mb = instr->Bits(10, 6);
1900       int me = instr->Bits(5, 1);
1901       uint32_t result = base::bits::RotateLeft32(rs_val, sh);
1902       int mask = 0;
1903       if (mb < me + 1) {
1904         int bit = 0x80000000 >> mb;
1905         for (; mb <= me; mb++) {
1906           mask |= bit;
1907           bit >>= 1;
1908         }
1909       } else if (mb == me + 1) {
1910         mask = 0xFFFFFFFF;
1911       } else {                             // mb > me+1
1912         int bit = 0x80000000 >> (me + 1);  // needs to be tested
1913         mask = 0xFFFFFFFF;
1914         for (; me < mb; me++) {
1915           mask ^= bit;
1916           bit >>= 1;
1917         }
1918       }
1919       result &= mask;
1920       set_register(ra, result);
1921       if (instr->Bit(0)) {  // RC bit set
1922         SetCR0(result);
1923       }
1924       break;
1925     }
1926     case ORI: {
1927       int rs = instr->RSValue();
1928       int ra = instr->RAValue();
1929       intptr_t rs_val = get_register(rs);
1930       uint32_t im_val = instr->Bits(15, 0);
1931       intptr_t alu_out = rs_val | im_val;
1932       set_register(ra, alu_out);
1933       break;
1934     }
1935     case ORIS: {
1936       int rs = instr->RSValue();
1937       int ra = instr->RAValue();
1938       intptr_t rs_val = get_register(rs);
1939       uint32_t im_val = instr->Bits(15, 0);
1940       intptr_t alu_out = rs_val | (im_val << 16);
1941       set_register(ra, alu_out);
1942       break;
1943     }
1944     case XORI: {
1945       int rs = instr->RSValue();
1946       int ra = instr->RAValue();
1947       intptr_t rs_val = get_register(rs);
1948       uint32_t im_val = instr->Bits(15, 0);
1949       intptr_t alu_out = rs_val ^ im_val;
1950       set_register(ra, alu_out);
1951       // todo - set condition based SO bit
1952       break;
1953     }
1954     case XORIS: {
1955       int rs = instr->RSValue();
1956       int ra = instr->RAValue();
1957       intptr_t rs_val = get_register(rs);
1958       uint32_t im_val = instr->Bits(15, 0);
1959       intptr_t alu_out = rs_val ^ (im_val << 16);
1960       set_register(ra, alu_out);
1961       break;
1962     }
1963     case ANDIx: {
1964       int rs = instr->RSValue();
1965       int ra = instr->RAValue();
1966       intptr_t rs_val = get_register(rs);
1967       uint32_t im_val = instr->Bits(15, 0);
1968       intptr_t alu_out = rs_val & im_val;
1969       set_register(ra, alu_out);
1970       SetCR0(alu_out);
1971       break;
1972     }
1973     case ANDISx: {
1974       int rs = instr->RSValue();
1975       int ra = instr->RAValue();
1976       intptr_t rs_val = get_register(rs);
1977       uint32_t im_val = instr->Bits(15, 0);
1978       intptr_t alu_out = rs_val & (im_val << 16);
1979       set_register(ra, alu_out);
1980       SetCR0(alu_out);
1981       break;
1982     }
1983     case SRWX: {
1984       int rs = instr->RSValue();
1985       int ra = instr->RAValue();
1986       int rb = instr->RBValue();
1987       uint32_t rs_val = get_register(rs);
1988       uintptr_t rb_val = get_register(rb) & 0x3F;
1989       intptr_t result = (rb_val > 31) ? 0 : rs_val >> rb_val;
1990       set_register(ra, result);
1991       if (instr->Bit(0)) {  // RC bit set
1992         SetCR0(result);
1993       }
1994       break;
1995     }
1996 #if V8_TARGET_ARCH_PPC64
1997     case SRDX: {
1998       int rs = instr->RSValue();
1999       int ra = instr->RAValue();
2000       int rb = instr->RBValue();
2001       uintptr_t rs_val = get_register(rs);
2002       uintptr_t rb_val = get_register(rb) & 0x7F;
2003       intptr_t result = (rb_val > 63) ? 0 : rs_val >> rb_val;
2004       set_register(ra, result);
2005       if (instr->Bit(0)) {  // RC bit set
2006         SetCR0(result);
2007       }
2008       break;
2009     }
2010 #endif
2011     case MODUW: {
2012       int rt = instr->RTValue();
2013       int ra = instr->RAValue();
2014       int rb = instr->RBValue();
2015       uint32_t ra_val = get_register(ra);
2016       uint32_t rb_val = get_register(rb);
2017       uint32_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
2018       set_register(rt, alu_out);
2019       break;
2020     }
2021 #if V8_TARGET_ARCH_PPC64
2022     case MODUD: {
2023       int rt = instr->RTValue();
2024       int ra = instr->RAValue();
2025       int rb = instr->RBValue();
2026       uint64_t ra_val = get_register(ra);
2027       uint64_t rb_val = get_register(rb);
2028       uint64_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
2029       set_register(rt, alu_out);
2030       break;
2031     }
2032 #endif
2033     case MODSW: {
2034       int rt = instr->RTValue();
2035       int ra = instr->RAValue();
2036       int rb = instr->RBValue();
2037       int32_t ra_val = get_register(ra);
2038       int32_t rb_val = get_register(rb);
2039       bool overflow = (ra_val == kMinInt && rb_val == -1);
2040       // result is undefined if divisor is zero or if operation
2041       // is 0x80000000 / -1.
2042       int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val % rb_val;
2043       set_register(rt, alu_out);
2044       break;
2045     }
2046 #if V8_TARGET_ARCH_PPC64
2047     case MODSD: {
2048       int rt = instr->RTValue();
2049       int ra = instr->RAValue();
2050       int rb = instr->RBValue();
2051       int64_t ra_val = get_register(ra);
2052       int64_t rb_val = get_register(rb);
2053       int64_t one = 1;  // work-around gcc
2054       int64_t kMinLongLong = (one << 63);
2055       // result is undefined if divisor is zero or if operation
2056       // is 0x80000000_00000000 / -1.
2057       int64_t alu_out =
2058           (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1))
2059               ? -1
2060               : ra_val % rb_val;
2061       set_register(rt, alu_out);
2062       break;
2063     }
2064 #endif
2065     case SRAW: {
2066       int rs = instr->RSValue();
2067       int ra = instr->RAValue();
2068       int rb = instr->RBValue();
2069       int32_t rs_val = get_register(rs);
2070       intptr_t rb_val = get_register(rb) & 0x3F;
2071       intptr_t result = (rb_val > 31) ? rs_val >> 31 : rs_val >> rb_val;
2072       set_register(ra, result);
2073       if (instr->Bit(0)) {  // RC bit set
2074         SetCR0(result);
2075       }
2076       break;
2077     }
2078 #if V8_TARGET_ARCH_PPC64
2079     case SRAD: {
2080       int rs = instr->RSValue();
2081       int ra = instr->RAValue();
2082       int rb = instr->RBValue();
2083       intptr_t rs_val = get_register(rs);
2084       intptr_t rb_val = get_register(rb) & 0x7F;
2085       intptr_t result = (rb_val > 63) ? rs_val >> 63 : rs_val >> rb_val;
2086       set_register(ra, result);
2087       if (instr->Bit(0)) {  // RC bit set
2088         SetCR0(result);
2089       }
2090       break;
2091     }
2092 #endif
2093     case SRAWIX: {
2094       int ra = instr->RAValue();
2095       int rs = instr->RSValue();
2096       int sh = instr->Bits(15, 11);
2097       int32_t rs_val = get_register(rs);
2098       intptr_t result = rs_val >> sh;
2099       set_register(ra, result);
2100       if (instr->Bit(0)) {  // RC bit set
2101         SetCR0(result);
2102       }
2103       break;
2104     }
2105 #if V8_TARGET_ARCH_PPC64
2106     case EXTSW: {
2107       const int shift = kBitsPerSystemPointer - 32;
2108       int ra = instr->RAValue();
2109       int rs = instr->RSValue();
2110       intptr_t rs_val = get_register(rs);
2111       intptr_t ra_val = (rs_val << shift) >> shift;
2112       set_register(ra, ra_val);
2113       if (instr->Bit(0)) {  // RC bit set
2114         SetCR0(ra_val);
2115       }
2116       break;
2117     }
2118 #endif
2119     case EXTSH: {
2120       const int shift = kBitsPerSystemPointer - 16;
2121       int ra = instr->RAValue();
2122       int rs = instr->RSValue();
2123       intptr_t rs_val = get_register(rs);
2124       intptr_t ra_val = (rs_val << shift) >> shift;
2125       set_register(ra, ra_val);
2126       if (instr->Bit(0)) {  // RC bit set
2127         SetCR0(ra_val);
2128       }
2129       break;
2130     }
2131     case EXTSB: {
2132       const int shift = kBitsPerSystemPointer - 8;
2133       int ra = instr->RAValue();
2134       int rs = instr->RSValue();
2135       intptr_t rs_val = get_register(rs);
2136       intptr_t ra_val = (rs_val << shift) >> shift;
2137       set_register(ra, ra_val);
2138       if (instr->Bit(0)) {  // RC bit set
2139         SetCR0(ra_val);
2140       }
2141       break;
2142     }
2143     case LFSUX:
2144     case LFSX: {
2145       int frt = instr->RTValue();
2146       int ra = instr->RAValue();
2147       int rb = instr->RBValue();
2148       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2149       intptr_t rb_val = get_register(rb);
2150       int32_t val = ReadW(ra_val + rb_val);
2151       float* fptr = reinterpret_cast<float*>(&val);
2152 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
2153       // Conversion using double changes sNan to qNan on ia32/x64
2154       if ((val & 0x7F800000) == 0x7F800000) {
2155         int64_t dval = static_cast<int64_t>(val);
2156         dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
2157                ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) | 0x0;
2158         set_d_register(frt, dval);
2159       } else {
2160         set_d_register_from_double(frt, static_cast<double>(*fptr));
2161       }
2162 #else
2163       set_d_register_from_double(frt, static_cast<double>(*fptr));
2164 #endif
2165       if (opcode == LFSUX) {
2166         DCHECK_NE(ra, 0);
2167         set_register(ra, ra_val + rb_val);
2168       }
2169       break;
2170     }
2171     case LFDUX:
2172     case LFDX: {
2173       int frt = instr->RTValue();
2174       int ra = instr->RAValue();
2175       int rb = instr->RBValue();
2176       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2177       intptr_t rb_val = get_register(rb);
2178       int64_t dptr = ReadDW(ra_val + rb_val);
2179       set_d_register(frt, dptr);
2180       if (opcode == LFDUX) {
2181         DCHECK_NE(ra, 0);
2182         set_register(ra, ra_val + rb_val);
2183       }
2184       break;
2185     }
2186     case STFSUX:
2187       V8_FALLTHROUGH;
2188     case STFSX: {
2189       int frs = instr->RSValue();
2190       int ra = instr->RAValue();
2191       int rb = instr->RBValue();
2192       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2193       intptr_t rb_val = get_register(rb);
2194       float frs_val = static_cast<float>(get_double_from_d_register(frs));
2195       int32_t* p = reinterpret_cast<int32_t*>(&frs_val);
2196 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
2197       // Conversion using double changes sNan to qNan on ia32/x64
2198       int32_t sval = 0;
2199       int64_t dval = get_d_register(frs);
2200       if ((dval & 0x7FF0000000000000) == 0x7FF0000000000000) {
2201         sval = ((dval & 0xC000000000000000) >> 32) |
2202                ((dval & 0x07FFFFFFE0000000) >> 29);
2203         p = &sval;
2204       } else {
2205         p = reinterpret_cast<int32_t*>(&frs_val);
2206       }
2207 #else
2208       p = reinterpret_cast<int32_t*>(&frs_val);
2209 #endif
2210       WriteW(ra_val + rb_val, *p);
2211       if (opcode == STFSUX) {
2212         DCHECK_NE(ra, 0);
2213         set_register(ra, ra_val + rb_val);
2214       }
2215       break;
2216     }
2217     case STFDUX:
2218       V8_FALLTHROUGH;
2219     case STFDX: {
2220       int frs = instr->RSValue();
2221       int ra = instr->RAValue();
2222       int rb = instr->RBValue();
2223       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2224       intptr_t rb_val = get_register(rb);
2225       int64_t frs_val = get_d_register(frs);
2226       WriteDW(ra_val + rb_val, frs_val);
2227       if (opcode == STFDUX) {
2228         DCHECK_NE(ra, 0);
2229         set_register(ra, ra_val + rb_val);
2230       }
2231       break;
2232     }
2233     case POPCNTW: {
2234       int rs = instr->RSValue();
2235       int ra = instr->RAValue();
2236       uintptr_t rs_val = get_register(rs);
2237       uintptr_t count = 0;
2238       int n = 0;
2239       uintptr_t bit = 0x80000000;
2240       for (; n < 32; n++) {
2241         if (bit & rs_val) count++;
2242         bit >>= 1;
2243       }
2244       set_register(ra, count);
2245       break;
2246     }
2247 #if V8_TARGET_ARCH_PPC64
2248     case POPCNTD: {
2249       int rs = instr->RSValue();
2250       int ra = instr->RAValue();
2251       uintptr_t rs_val = get_register(rs);
2252       uintptr_t count = 0;
2253       int n = 0;
2254       uintptr_t bit = 0x8000000000000000UL;
2255       for (; n < 64; n++) {
2256         if (bit & rs_val) count++;
2257         bit >>= 1;
2258       }
2259       set_register(ra, count);
2260       break;
2261     }
2262 #endif
2263     case SYNC: {
2264       // todo - simulate sync
2265       __sync_synchronize();
2266       break;
2267     }
2268     case ICBI: {
2269       // todo - simulate icbi
2270       break;
2271     }
2272 
2273     case LWZU:
2274     case LWZ: {
2275       int ra = instr->RAValue();
2276       int rt = instr->RTValue();
2277       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2278       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
2279       set_register(rt, ReadWU(ra_val + offset));
2280       if (opcode == LWZU) {
2281         DCHECK_NE(ra, 0);
2282         set_register(ra, ra_val + offset);
2283       }
2284       break;
2285     }
2286 
2287     case LBZU:
2288     case LBZ: {
2289       int ra = instr->RAValue();
2290       int rt = instr->RTValue();
2291       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2292       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
2293       set_register(rt, ReadB(ra_val + offset) & 0xFF);
2294       if (opcode == LBZU) {
2295         DCHECK_NE(ra, 0);
2296         set_register(ra, ra_val + offset);
2297       }
2298       break;
2299     }
2300 
2301     case STWU:
2302     case STW: {
2303       int ra = instr->RAValue();
2304       int rs = instr->RSValue();
2305       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2306       int32_t rs_val = get_register(rs);
2307       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
2308       WriteW(ra_val + offset, rs_val);
2309       if (opcode == STWU) {
2310         DCHECK_NE(ra, 0);
2311         set_register(ra, ra_val + offset);
2312       }
2313       break;
2314     }
2315     case SRADIX: {
2316       int ra = instr->RAValue();
2317       int rs = instr->RSValue();
2318       int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2319       intptr_t rs_val = get_register(rs);
2320       intptr_t result = rs_val >> sh;
2321       set_register(ra, result);
2322       if (instr->Bit(0)) {  // RC bit set
2323         SetCR0(result);
2324       }
2325       break;
2326     }
2327     case STBCX: {
2328       int rs = instr->RSValue();
2329       int ra = instr->RAValue();
2330       int rb = instr->RBValue();
2331       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2332       int8_t rs_val = get_register(rs);
2333       intptr_t rb_val = get_register(rb);
2334       SetCR0(WriteExB(ra_val + rb_val, rs_val));
2335       break;
2336     }
2337     case STHCX: {
2338       int rs = instr->RSValue();
2339       int ra = instr->RAValue();
2340       int rb = instr->RBValue();
2341       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2342       int16_t rs_val = get_register(rs);
2343       intptr_t rb_val = get_register(rb);
2344       SetCR0(WriteExH(ra_val + rb_val, rs_val));
2345       break;
2346     }
2347     case STWCX: {
2348       int rs = instr->RSValue();
2349       int ra = instr->RAValue();
2350       int rb = instr->RBValue();
2351       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2352       int32_t rs_val = get_register(rs);
2353       intptr_t rb_val = get_register(rb);
2354       SetCR0(WriteExW(ra_val + rb_val, rs_val));
2355       break;
2356     }
2357     case STDCX: {
2358       int rs = instr->RSValue();
2359       int ra = instr->RAValue();
2360       int rb = instr->RBValue();
2361       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2362       int64_t rs_val = get_register(rs);
2363       intptr_t rb_val = get_register(rb);
2364       SetCR0(WriteExDW(ra_val + rb_val, rs_val));
2365       break;
2366     }
2367     case TW: {
2368       // used for call redirection in simulation mode
2369       SoftwareInterrupt(instr);
2370       break;
2371     }
2372     case CMP: {
2373       int ra = instr->RAValue();
2374       int rb = instr->RBValue();
2375       int cr = instr->Bits(25, 23);
2376       uint32_t bf = 0;
2377 #if V8_TARGET_ARCH_PPC64
2378       int L = instr->Bit(21);
2379       if (L) {
2380 #endif
2381         intptr_t ra_val = get_register(ra);
2382         intptr_t rb_val = get_register(rb);
2383         if (ra_val < rb_val) {
2384           bf |= 0x80000000;
2385         }
2386         if (ra_val > rb_val) {
2387           bf |= 0x40000000;
2388         }
2389         if (ra_val == rb_val) {
2390           bf |= 0x20000000;
2391         }
2392 #if V8_TARGET_ARCH_PPC64
2393       } else {
2394         int32_t ra_val = get_register(ra);
2395         int32_t rb_val = get_register(rb);
2396         if (ra_val < rb_val) {
2397           bf |= 0x80000000;
2398         }
2399         if (ra_val > rb_val) {
2400           bf |= 0x40000000;
2401         }
2402         if (ra_val == rb_val) {
2403           bf |= 0x20000000;
2404         }
2405       }
2406 #endif
2407       uint32_t condition_mask = 0xF0000000U >> (cr * 4);
2408       uint32_t condition = bf >> (cr * 4);
2409       condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
2410       break;
2411     }
2412     case SUBFCX: {
2413       int rt = instr->RTValue();
2414       int ra = instr->RAValue();
2415       int rb = instr->RBValue();
2416       // int oe = instr->Bit(10);
2417       uintptr_t ra_val = get_register(ra);
2418       uintptr_t rb_val = get_register(rb);
2419       uintptr_t alu_out = ~ra_val + rb_val + 1;
2420       // Set carry
2421       if (ra_val <= rb_val) {
2422         special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
2423       } else {
2424         special_reg_xer_ &= ~0xF0000000;
2425       }
2426       set_register(rt, alu_out);
2427       if (instr->Bit(0)) {  // RC bit set
2428         SetCR0(alu_out);
2429       }
2430       // todo - handle OE bit
2431       break;
2432     }
2433     case SUBFEX: {
2434       int rt = instr->RTValue();
2435       int ra = instr->RAValue();
2436       int rb = instr->RBValue();
2437       // int oe = instr->Bit(10);
2438       uintptr_t ra_val = get_register(ra);
2439       uintptr_t rb_val = get_register(rb);
2440       uintptr_t alu_out = ~ra_val + rb_val;
2441       if (special_reg_xer_ & 0x20000000) {
2442         alu_out += 1;
2443       }
2444       set_register(rt, alu_out);
2445       if (instr->Bit(0)) {  // RC bit set
2446         SetCR0(static_cast<intptr_t>(alu_out));
2447       }
2448       // todo - handle OE bit
2449       break;
2450     }
2451     case ADDCX: {
2452       int rt = instr->RTValue();
2453       int ra = instr->RAValue();
2454       int rb = instr->RBValue();
2455       // int oe = instr->Bit(10);
2456       uintptr_t ra_val = get_register(ra);
2457       uintptr_t rb_val = get_register(rb);
2458       uintptr_t alu_out = ra_val + rb_val;
2459       // Set carry
2460       if (~ra_val < rb_val) {
2461         special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
2462       } else {
2463         special_reg_xer_ &= ~0xF0000000;
2464       }
2465       set_register(rt, alu_out);
2466       if (instr->Bit(0)) {  // RC bit set
2467         SetCR0(static_cast<intptr_t>(alu_out));
2468       }
2469       // todo - handle OE bit
2470       break;
2471     }
2472     case ADDEX: {
2473       int rt = instr->RTValue();
2474       int ra = instr->RAValue();
2475       int rb = instr->RBValue();
2476       // int oe = instr->Bit(10);
2477       uintptr_t ra_val = get_register(ra);
2478       uintptr_t rb_val = get_register(rb);
2479       uintptr_t alu_out = ra_val + rb_val;
2480       if (special_reg_xer_ & 0x20000000) {
2481         alu_out += 1;
2482       }
2483       set_register(rt, alu_out);
2484       if (instr->Bit(0)) {  // RC bit set
2485         SetCR0(static_cast<intptr_t>(alu_out));
2486       }
2487       // todo - handle OE bit
2488       break;
2489     }
2490     case MULHWX: {
2491       int rt = instr->RTValue();
2492       int ra = instr->RAValue();
2493       int rb = instr->RBValue();
2494       int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2495       int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2496       int64_t alu_out = (int64_t)ra_val * (int64_t)rb_val;
2497       // High 32 bits of the result is undefined,
2498       // Which is simulated here by adding random bits.
2499       alu_out = (alu_out >> 32) | 0x421000000000000;
2500       set_register(rt, alu_out);
2501       if (instr->Bit(0)) {  // RC bit set
2502         SetCR0(static_cast<intptr_t>(alu_out));
2503       }
2504       break;
2505     }
2506     case MULHWUX: {
2507       int rt = instr->RTValue();
2508       int ra = instr->RAValue();
2509       int rb = instr->RBValue();
2510       uint32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2511       uint32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2512       uint64_t alu_out = (uint64_t)ra_val * (uint64_t)rb_val;
2513       // High 32 bits of the result is undefined,
2514       // Which is simulated here by adding random bits.
2515       alu_out = (alu_out >> 32) | 0x421000000000000;
2516       set_register(rt, alu_out);
2517       if (instr->Bit(0)) {  // RC bit set
2518         SetCR0(static_cast<intptr_t>(alu_out));
2519       }
2520       break;
2521     }
2522     case NEGX: {
2523       int rt = instr->RTValue();
2524       int ra = instr->RAValue();
2525       intptr_t ra_val = get_register(ra);
2526       intptr_t alu_out = 1 + ~ra_val;
2527 #if V8_TARGET_ARCH_PPC64
2528       intptr_t one = 1;  // work-around gcc
2529       intptr_t kOverflowVal = (one << 63);
2530 #else
2531       intptr_t kOverflowVal = kMinInt;
2532 #endif
2533       set_register(rt, alu_out);
2534       if (instr->Bit(10)) {  // OE bit set
2535         if (ra_val == kOverflowVal) {
2536           special_reg_xer_ |= 0xC0000000;  // set SO,OV
2537         } else {
2538           special_reg_xer_ &= ~0x40000000;  // clear OV
2539         }
2540       }
2541       if (instr->Bit(0)) {  // RC bit set
2542         bool setSO = (special_reg_xer_ & 0x80000000);
2543         SetCR0(alu_out, setSO);
2544       }
2545       break;
2546     }
2547     case SLWX: {
2548       int rs = instr->RSValue();
2549       int ra = instr->RAValue();
2550       int rb = instr->RBValue();
2551       uint32_t rs_val = get_register(rs);
2552       uintptr_t rb_val = get_register(rb) & 0x3F;
2553       uint32_t result = (rb_val > 31) ? 0 : rs_val << rb_val;
2554       set_register(ra, result);
2555       if (instr->Bit(0)) {  // RC bit set
2556         SetCR0(result);
2557       }
2558       break;
2559     }
2560 #if V8_TARGET_ARCH_PPC64
2561     case SLDX: {
2562       int rs = instr->RSValue();
2563       int ra = instr->RAValue();
2564       int rb = instr->RBValue();
2565       uintptr_t rs_val = get_register(rs);
2566       uintptr_t rb_val = get_register(rb) & 0x7F;
2567       uintptr_t result = (rb_val > 63) ? 0 : rs_val << rb_val;
2568       set_register(ra, result);
2569       if (instr->Bit(0)) {  // RC bit set
2570         SetCR0(result);
2571       }
2572       break;
2573     }
2574     case MFVSRD: {
2575       int frt = instr->RTValue();
2576       int ra = instr->RAValue();
2577       int64_t frt_val;
2578       if (!instr->Bit(0)) {
2579         // if double reg (TX=0).
2580         frt_val = get_d_register(frt);
2581       } else {
2582         // if simd reg (TX=1).
2583         DCHECK_EQ(instr->Bit(0), 1);
2584         frt_val = get_simd_register_by_lane<int64_t>(frt, 0);
2585       }
2586       set_register(ra, frt_val);
2587       break;
2588     }
2589     case MFVSRWZ: {
2590       DCHECK(!instr->Bit(0));
2591       int frt = instr->RTValue();
2592       int ra = instr->RAValue();
2593       int64_t frt_val = get_d_register(frt);
2594       set_register(ra, static_cast<uint32_t>(frt_val));
2595       break;
2596     }
2597     case MTVSRD: {
2598       int frt = instr->RTValue();
2599       int ra = instr->RAValue();
2600       int64_t ra_val = get_register(ra);
2601       if (!instr->Bit(0)) {
2602         // if double reg (TX=0).
2603         set_d_register(frt, ra_val);
2604       } else {
2605         // if simd reg (TX=1).
2606         DCHECK_EQ(instr->Bit(0), 1);
2607         set_simd_register_by_lane<int64_t>(frt, 0,
2608                                            static_cast<int64_t>(ra_val));
2609         // Low 64 bits of the result is undefined,
2610         // Which is simulated here by adding random bits.
2611         set_simd_register_by_lane<int64_t>(
2612             frt, 1, static_cast<int64_t>(0x123456789ABCD));
2613       }
2614       break;
2615     }
2616     case MTVSRDD: {
2617       int xt = instr->RTValue();
2618       int ra = instr->RAValue();
2619       int rb = instr->RBValue();
2620       set_simd_register_by_lane<int64_t>(
2621           xt, 0, static_cast<int64_t>(get_register(ra)));
2622       set_simd_register_by_lane<int64_t>(
2623           xt, 1, static_cast<int64_t>(get_register(rb)));
2624       break;
2625     }
2626     case MTVSRWA: {
2627       DCHECK(!instr->Bit(0));
2628       int frt = instr->RTValue();
2629       int ra = instr->RAValue();
2630       int64_t ra_val = static_cast<int32_t>(get_register(ra));
2631       set_d_register(frt, ra_val);
2632       break;
2633     }
2634     case MTVSRWZ: {
2635       DCHECK(!instr->Bit(0));
2636       int frt = instr->RTValue();
2637       int ra = instr->RAValue();
2638       uint64_t ra_val = static_cast<uint32_t>(get_register(ra));
2639       set_d_register(frt, ra_val);
2640       break;
2641     }
2642 #endif
2643     case CNTLZWX: {
2644       int rs = instr->RSValue();
2645       int ra = instr->RAValue();
2646       uintptr_t rs_val = get_register(rs);
2647       uintptr_t count = 0;
2648       int n = 0;
2649       uintptr_t bit = 0x80000000;
2650       for (; n < 32; n++) {
2651         if (bit & rs_val) break;
2652         count++;
2653         bit >>= 1;
2654       }
2655       set_register(ra, count);
2656       if (instr->Bit(0)) {  // RC Bit set
2657         int bf = 0;
2658         if (count > 0) {
2659           bf |= 0x40000000;
2660         }
2661         if (count == 0) {
2662           bf |= 0x20000000;
2663         }
2664         condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2665       }
2666       break;
2667     }
2668     case CNTLZDX: {
2669       int rs = instr->RSValue();
2670       int ra = instr->RAValue();
2671       uintptr_t rs_val = get_register(rs);
2672       uintptr_t count = 0;
2673       int n = 0;
2674       uintptr_t bit = 0x8000000000000000UL;
2675       for (; n < 64; n++) {
2676         if (bit & rs_val) break;
2677         count++;
2678         bit >>= 1;
2679       }
2680       set_register(ra, count);
2681       if (instr->Bit(0)) {  // RC Bit set
2682         int bf = 0;
2683         if (count > 0) {
2684           bf |= 0x40000000;
2685         }
2686         if (count == 0) {
2687           bf |= 0x20000000;
2688         }
2689         condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2690       }
2691       break;
2692     }
2693     case CNTTZWX: {
2694       int rs = instr->RSValue();
2695       int ra = instr->RAValue();
2696       uint32_t rs_val = static_cast<uint32_t>(get_register(rs));
2697       uintptr_t count = rs_val == 0 ? 32 : __builtin_ctz(rs_val);
2698       set_register(ra, count);
2699       if (instr->Bit(0)) {  // RC Bit set
2700         int bf = 0;
2701         if (count > 0) {
2702           bf |= 0x40000000;
2703         }
2704         if (count == 0) {
2705           bf |= 0x20000000;
2706         }
2707         condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2708       }
2709       break;
2710     }
2711     case CNTTZDX: {
2712       int rs = instr->RSValue();
2713       int ra = instr->RAValue();
2714       uint64_t rs_val = get_register(rs);
2715       uintptr_t count = rs_val == 0 ? 64 : __builtin_ctzl(rs_val);
2716       set_register(ra, count);
2717       if (instr->Bit(0)) {  // RC Bit set
2718         int bf = 0;
2719         if (count > 0) {
2720           bf |= 0x40000000;
2721         }
2722         if (count == 0) {
2723           bf |= 0x20000000;
2724         }
2725         condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
2726       }
2727       break;
2728     }
2729     case ANDX: {
2730       int rs = instr->RSValue();
2731       int ra = instr->RAValue();
2732       int rb = instr->RBValue();
2733       intptr_t rs_val = get_register(rs);
2734       intptr_t rb_val = get_register(rb);
2735       intptr_t alu_out = rs_val & rb_val;
2736       set_register(ra, alu_out);
2737       if (instr->Bit(0)) {  // RC Bit set
2738         SetCR0(alu_out);
2739       }
2740       break;
2741     }
2742     case ANDCX: {
2743       int rs = instr->RSValue();
2744       int ra = instr->RAValue();
2745       int rb = instr->RBValue();
2746       intptr_t rs_val = get_register(rs);
2747       intptr_t rb_val = get_register(rb);
2748       intptr_t alu_out = rs_val & ~rb_val;
2749       set_register(ra, alu_out);
2750       if (instr->Bit(0)) {  // RC Bit set
2751         SetCR0(alu_out);
2752       }
2753       break;
2754     }
2755     case CMPL: {
2756       int ra = instr->RAValue();
2757       int rb = instr->RBValue();
2758       int cr = instr->Bits(25, 23);
2759       uint32_t bf = 0;
2760 #if V8_TARGET_ARCH_PPC64
2761       int L = instr->Bit(21);
2762       if (L) {
2763 #endif
2764         uintptr_t ra_val = get_register(ra);
2765         uintptr_t rb_val = get_register(rb);
2766         if (ra_val < rb_val) {
2767           bf |= 0x80000000;
2768         }
2769         if (ra_val > rb_val) {
2770           bf |= 0x40000000;
2771         }
2772         if (ra_val == rb_val) {
2773           bf |= 0x20000000;
2774         }
2775 #if V8_TARGET_ARCH_PPC64
2776       } else {
2777         uint32_t ra_val = get_register(ra);
2778         uint32_t rb_val = get_register(rb);
2779         if (ra_val < rb_val) {
2780           bf |= 0x80000000;
2781         }
2782         if (ra_val > rb_val) {
2783           bf |= 0x40000000;
2784         }
2785         if (ra_val == rb_val) {
2786           bf |= 0x20000000;
2787         }
2788       }
2789 #endif
2790       uint32_t condition_mask = 0xF0000000U >> (cr * 4);
2791       uint32_t condition = bf >> (cr * 4);
2792       condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
2793       break;
2794     }
2795     case SUBFX: {
2796       int rt = instr->RTValue();
2797       int ra = instr->RAValue();
2798       int rb = instr->RBValue();
2799       // int oe = instr->Bit(10);
2800       intptr_t ra_val = get_register(ra);
2801       intptr_t rb_val = get_register(rb);
2802       intptr_t alu_out = rb_val - ra_val;
2803       // todo - figure out underflow
2804       set_register(rt, alu_out);
2805       if (instr->Bit(0)) {  // RC Bit set
2806         SetCR0(alu_out);
2807       }
2808       // todo - handle OE bit
2809       break;
2810     }
2811     case ADDZEX: {
2812       int rt = instr->RTValue();
2813       int ra = instr->RAValue();
2814       intptr_t ra_val = get_register(ra);
2815       if (special_reg_xer_ & 0x20000000) {
2816         ra_val += 1;
2817       }
2818       set_register(rt, ra_val);
2819       if (instr->Bit(0)) {  // RC bit set
2820         SetCR0(ra_val);
2821       }
2822       // todo - handle OE bit
2823       break;
2824     }
2825     case NORX: {
2826       int rs = instr->RSValue();
2827       int ra = instr->RAValue();
2828       int rb = instr->RBValue();
2829       intptr_t rs_val = get_register(rs);
2830       intptr_t rb_val = get_register(rb);
2831       intptr_t alu_out = ~(rs_val | rb_val);
2832       set_register(ra, alu_out);
2833       if (instr->Bit(0)) {  // RC bit set
2834         SetCR0(alu_out);
2835       }
2836       break;
2837     }
2838     case MULLW: {
2839       int rt = instr->RTValue();
2840       int ra = instr->RAValue();
2841       int rb = instr->RBValue();
2842       int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
2843       int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
2844       int32_t alu_out = ra_val * rb_val;
2845       set_register(rt, alu_out);
2846       if (instr->Bit(0)) {  // RC bit set
2847         SetCR0(alu_out);
2848       }
2849       // todo - handle OE bit
2850       break;
2851     }
2852 #if V8_TARGET_ARCH_PPC64
2853     case MULLD: {
2854       int rt = instr->RTValue();
2855       int ra = instr->RAValue();
2856       int rb = instr->RBValue();
2857       int64_t ra_val = get_register(ra);
2858       int64_t rb_val = get_register(rb);
2859       int64_t alu_out = ra_val * rb_val;
2860       set_register(rt, alu_out);
2861       if (instr->Bit(0)) {  // RC bit set
2862         SetCR0(alu_out);
2863       }
2864       // todo - handle OE bit
2865       break;
2866     }
2867 #endif
2868     case DIVW: {
2869       int rt = instr->RTValue();
2870       int ra = instr->RAValue();
2871       int rb = instr->RBValue();
2872       int32_t ra_val = get_register(ra);
2873       int32_t rb_val = get_register(rb);
2874       bool overflow = (ra_val == kMinInt && rb_val == -1);
2875       // result is undefined if divisor is zero or if operation
2876       // is 0x80000000 / -1.
2877       int32_t alu_out = (rb_val == 0 || overflow) ? -1 : ra_val / rb_val;
2878       set_register(rt, alu_out);
2879       if (instr->Bit(10)) {  // OE bit set
2880         if (overflow) {
2881           special_reg_xer_ |= 0xC0000000;  // set SO,OV
2882         } else {
2883           special_reg_xer_ &= ~0x40000000;  // clear OV
2884         }
2885       }
2886       if (instr->Bit(0)) {  // RC bit set
2887         bool setSO = (special_reg_xer_ & 0x80000000);
2888         SetCR0(alu_out, setSO);
2889       }
2890       break;
2891     }
2892     case DIVWU: {
2893       int rt = instr->RTValue();
2894       int ra = instr->RAValue();
2895       int rb = instr->RBValue();
2896       uint32_t ra_val = get_register(ra);
2897       uint32_t rb_val = get_register(rb);
2898       bool overflow = (rb_val == 0);
2899       // result is undefined if divisor is zero
2900       uint32_t alu_out = (overflow) ? -1 : ra_val / rb_val;
2901       set_register(rt, alu_out);
2902       if (instr->Bit(10)) {  // OE bit set
2903         if (overflow) {
2904           special_reg_xer_ |= 0xC0000000;  // set SO,OV
2905         } else {
2906           special_reg_xer_ &= ~0x40000000;  // clear OV
2907         }
2908       }
2909       if (instr->Bit(0)) {  // RC bit set
2910         bool setSO = (special_reg_xer_ & 0x80000000);
2911         SetCR0(alu_out, setSO);
2912       }
2913       break;
2914     }
2915 #if V8_TARGET_ARCH_PPC64
2916     case DIVD: {
2917       int rt = instr->RTValue();
2918       int ra = instr->RAValue();
2919       int rb = instr->RBValue();
2920       int64_t ra_val = get_register(ra);
2921       int64_t rb_val = get_register(rb);
2922       int64_t one = 1;  // work-around gcc
2923       int64_t kMinLongLong = (one << 63);
2924       // result is undefined if divisor is zero or if operation
2925       // is 0x80000000_00000000 / -1.
2926       int64_t alu_out =
2927           (rb_val == 0 || (ra_val == kMinLongLong && rb_val == -1))
2928               ? -1
2929               : ra_val / rb_val;
2930       set_register(rt, alu_out);
2931       if (instr->Bit(0)) {  // RC bit set
2932         SetCR0(alu_out);
2933       }
2934       // todo - handle OE bit
2935       break;
2936     }
2937     case DIVDU: {
2938       int rt = instr->RTValue();
2939       int ra = instr->RAValue();
2940       int rb = instr->RBValue();
2941       uint64_t ra_val = get_register(ra);
2942       uint64_t rb_val = get_register(rb);
2943       // result is undefined if divisor is zero
2944       uint64_t alu_out = (rb_val == 0) ? -1 : ra_val / rb_val;
2945       set_register(rt, alu_out);
2946       if (instr->Bit(0)) {  // RC bit set
2947         SetCR0(alu_out);
2948       }
2949       // todo - handle OE bit
2950       break;
2951     }
2952 #endif
2953     case ADDX: {
2954       int rt = instr->RTValue();
2955       int ra = instr->RAValue();
2956       int rb = instr->RBValue();
2957       // int oe = instr->Bit(10);
2958       intptr_t ra_val = get_register(ra);
2959       intptr_t rb_val = get_register(rb);
2960       intptr_t alu_out = ra_val + rb_val;
2961       set_register(rt, alu_out);
2962       if (instr->Bit(0)) {  // RC bit set
2963         SetCR0(alu_out);
2964       }
2965       // todo - handle OE bit
2966       break;
2967     }
2968     case XORX: {
2969       int rs = instr->RSValue();
2970       int ra = instr->RAValue();
2971       int rb = instr->RBValue();
2972       intptr_t rs_val = get_register(rs);
2973       intptr_t rb_val = get_register(rb);
2974       intptr_t alu_out = rs_val ^ rb_val;
2975       set_register(ra, alu_out);
2976       if (instr->Bit(0)) {  // RC bit set
2977         SetCR0(alu_out);
2978       }
2979       break;
2980     }
2981     case ORX: {
2982       int rs = instr->RSValue();
2983       int ra = instr->RAValue();
2984       int rb = instr->RBValue();
2985       intptr_t rs_val = get_register(rs);
2986       intptr_t rb_val = get_register(rb);
2987       intptr_t alu_out = rs_val | rb_val;
2988       set_register(ra, alu_out);
2989       if (instr->Bit(0)) {  // RC bit set
2990         SetCR0(alu_out);
2991       }
2992       break;
2993     }
2994     case ORC: {
2995       int rs = instr->RSValue();
2996       int ra = instr->RAValue();
2997       int rb = instr->RBValue();
2998       intptr_t rs_val = get_register(rs);
2999       intptr_t rb_val = get_register(rb);
3000       intptr_t alu_out = rs_val | ~rb_val;
3001       set_register(ra, alu_out);
3002       if (instr->Bit(0)) {  // RC bit set
3003         SetCR0(alu_out);
3004       }
3005       break;
3006     }
3007     case MFSPR: {
3008       int rt = instr->RTValue();
3009       int spr = instr->Bits(20, 11);
3010       if (spr != 256) {
3011         UNIMPLEMENTED();  // Only LRLR supported
3012       }
3013       set_register(rt, special_reg_lr_);
3014       break;
3015     }
3016     case MTSPR: {
3017       int rt = instr->RTValue();
3018       intptr_t rt_val = get_register(rt);
3019       int spr = instr->Bits(20, 11);
3020       if (spr == 256) {
3021         special_reg_lr_ = rt_val;
3022       } else if (spr == 288) {
3023         special_reg_ctr_ = rt_val;
3024       } else if (spr == 32) {
3025         special_reg_xer_ = rt_val;
3026       } else {
3027         UNIMPLEMENTED();  // Only LR supported
3028       }
3029       break;
3030     }
3031     case MFCR: {
3032       int rt = instr->RTValue();
3033       set_register(rt, condition_reg_);
3034       break;
3035     }
3036     case STWUX:
3037     case STWX: {
3038       int rs = instr->RSValue();
3039       int ra = instr->RAValue();
3040       int rb = instr->RBValue();
3041       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3042       int32_t rs_val = get_register(rs);
3043       intptr_t rb_val = get_register(rb);
3044       WriteW(ra_val + rb_val, rs_val);
3045       if (opcode == STWUX) {
3046         DCHECK_NE(ra, 0);
3047         set_register(ra, ra_val + rb_val);
3048       }
3049       break;
3050     }
3051     case STBUX:
3052     case STBX: {
3053       int rs = instr->RSValue();
3054       int ra = instr->RAValue();
3055       int rb = instr->RBValue();
3056       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3057       int8_t rs_val = get_register(rs);
3058       intptr_t rb_val = get_register(rb);
3059       WriteB(ra_val + rb_val, rs_val);
3060       if (opcode == STBUX) {
3061         DCHECK_NE(ra, 0);
3062         set_register(ra, ra_val + rb_val);
3063       }
3064       break;
3065     }
3066     case STHUX:
3067     case STHX: {
3068       int rs = instr->RSValue();
3069       int ra = instr->RAValue();
3070       int rb = instr->RBValue();
3071       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3072       int16_t rs_val = get_register(rs);
3073       intptr_t rb_val = get_register(rb);
3074       WriteH(ra_val + rb_val, rs_val);
3075       if (opcode == STHUX) {
3076         DCHECK_NE(ra, 0);
3077         set_register(ra, ra_val + rb_val);
3078       }
3079       break;
3080     }
3081     case LWZX:
3082     case LWZUX: {
3083       int rt = instr->RTValue();
3084       int ra = instr->RAValue();
3085       int rb = instr->RBValue();
3086       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3087       intptr_t rb_val = get_register(rb);
3088       set_register(rt, ReadWU(ra_val + rb_val));
3089       if (opcode == LWZUX) {
3090         DCHECK(ra != 0 && ra != rt);
3091         set_register(ra, ra_val + rb_val);
3092       }
3093       break;
3094     }
3095 #if V8_TARGET_ARCH_PPC64
3096     case LWAX: {
3097       int rt = instr->RTValue();
3098       int ra = instr->RAValue();
3099       int rb = instr->RBValue();
3100       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3101       intptr_t rb_val = get_register(rb);
3102       set_register(rt, ReadW(ra_val + rb_val));
3103       break;
3104     }
3105     case LDX:
3106     case LDUX: {
3107       int rt = instr->RTValue();
3108       int ra = instr->RAValue();
3109       int rb = instr->RBValue();
3110       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3111       intptr_t rb_val = get_register(rb);
3112       intptr_t result = ReadDW(ra_val + rb_val);
3113       set_register(rt, result);
3114       if (opcode == LDUX) {
3115         DCHECK(ra != 0 && ra != rt);
3116         set_register(ra, ra_val + rb_val);
3117       }
3118       break;
3119     }
3120     case LDBRX: {
3121       int rt = instr->RTValue();
3122       int ra = instr->RAValue();
3123       int rb = instr->RBValue();
3124       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3125       intptr_t rb_val = get_register(rb);
3126       intptr_t result = __builtin_bswap64(ReadDW(ra_val + rb_val));
3127       set_register(rt, result);
3128       break;
3129     }
3130     case LWBRX: {
3131       int rt = instr->RTValue();
3132       int ra = instr->RAValue();
3133       int rb = instr->RBValue();
3134       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3135       intptr_t rb_val = get_register(rb);
3136       intptr_t result = __builtin_bswap32(ReadW(ra_val + rb_val));
3137       set_register(rt, result);
3138       break;
3139     }
3140     case STDBRX: {
3141       int rs = instr->RSValue();
3142       int ra = instr->RAValue();
3143       int rb = instr->RBValue();
3144       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3145       intptr_t rs_val = get_register(rs);
3146       intptr_t rb_val = get_register(rb);
3147       WriteDW(ra_val + rb_val, __builtin_bswap64(rs_val));
3148       break;
3149     }
3150     case STWBRX: {
3151       int rs = instr->RSValue();
3152       int ra = instr->RAValue();
3153       int rb = instr->RBValue();
3154       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3155       intptr_t rs_val = get_register(rs);
3156       intptr_t rb_val = get_register(rb);
3157       WriteW(ra_val + rb_val, __builtin_bswap32(rs_val));
3158       break;
3159     }
3160     case STHBRX: {
3161       int rs = instr->RSValue();
3162       int ra = instr->RAValue();
3163       int rb = instr->RBValue();
3164       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3165       intptr_t rs_val = get_register(rs);
3166       intptr_t rb_val = get_register(rb);
3167       WriteH(ra_val + rb_val, __builtin_bswap16(rs_val));
3168       break;
3169     }
3170     case STDX:
3171     case STDUX: {
3172       int rs = instr->RSValue();
3173       int ra = instr->RAValue();
3174       int rb = instr->RBValue();
3175       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3176       intptr_t rs_val = get_register(rs);
3177       intptr_t rb_val = get_register(rb);
3178       WriteDW(ra_val + rb_val, rs_val);
3179       if (opcode == STDUX) {
3180         DCHECK_NE(ra, 0);
3181         set_register(ra, ra_val + rb_val);
3182       }
3183       break;
3184     }
3185 #endif
3186     case LBZX:
3187     case LBZUX: {
3188       int rt = instr->RTValue();
3189       int ra = instr->RAValue();
3190       int rb = instr->RBValue();
3191       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3192       intptr_t rb_val = get_register(rb);
3193       set_register(rt, ReadBU(ra_val + rb_val) & 0xFF);
3194       if (opcode == LBZUX) {
3195         DCHECK(ra != 0 && ra != rt);
3196         set_register(ra, ra_val + rb_val);
3197       }
3198       break;
3199     }
3200     case LHZX:
3201     case LHZUX: {
3202       int rt = instr->RTValue();
3203       int ra = instr->RAValue();
3204       int rb = instr->RBValue();
3205       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3206       intptr_t rb_val = get_register(rb);
3207       set_register(rt, ReadHU(ra_val + rb_val) & 0xFFFF);
3208       if (opcode == LHZUX) {
3209         DCHECK(ra != 0 && ra != rt);
3210         set_register(ra, ra_val + rb_val);
3211       }
3212       break;
3213     }
3214     case LHAX: {
3215       int rt = instr->RTValue();
3216       int ra = instr->RAValue();
3217       int rb = instr->RBValue();
3218       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3219       intptr_t rb_val = get_register(rb);
3220       set_register(rt, ReadH(ra_val + rb_val));
3221       break;
3222     }
3223     case LBARX: {
3224       int rt = instr->RTValue();
3225       int ra = instr->RAValue();
3226       int rb = instr->RBValue();
3227       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3228       intptr_t rb_val = get_register(rb);
3229       set_register(rt, ReadExBU(ra_val + rb_val) & 0xFF);
3230       break;
3231     }
3232     case LHARX: {
3233       int rt = instr->RTValue();
3234       int ra = instr->RAValue();
3235       int rb = instr->RBValue();
3236       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3237       intptr_t rb_val = get_register(rb);
3238       set_register(rt, ReadExHU(ra_val + rb_val));
3239       break;
3240     }
3241     case LWARX: {
3242       int rt = instr->RTValue();
3243       int ra = instr->RAValue();
3244       int rb = instr->RBValue();
3245       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3246       intptr_t rb_val = get_register(rb);
3247       set_register(rt, ReadExWU(ra_val + rb_val));
3248       break;
3249     }
3250     case LDARX: {
3251       int rt = instr->RTValue();
3252       int ra = instr->RAValue();
3253       int rb = instr->RBValue();
3254       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3255       intptr_t rb_val = get_register(rb);
3256       set_register(rt, ReadExDWU(ra_val + rb_val));
3257       break;
3258     }
3259     case DCBF: {
3260       // todo - simulate dcbf
3261       break;
3262     }
3263     case ISEL: {
3264       int rt = instr->RTValue();
3265       int ra = instr->RAValue();
3266       int rb = instr->RBValue();
3267       int condition_bit = instr->RCValue();
3268       int condition_mask = 0x80000000 >> condition_bit;
3269       intptr_t ra_val = (ra == 0) ? 0 : get_register(ra);
3270       intptr_t rb_val = get_register(rb);
3271       intptr_t value = (condition_reg_ & condition_mask) ? ra_val : rb_val;
3272       set_register(rt, value);
3273       break;
3274     }
3275 
3276     case STBU:
3277     case STB: {
3278       int ra = instr->RAValue();
3279       int rs = instr->RSValue();
3280       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3281       int8_t rs_val = get_register(rs);
3282       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3283       WriteB(ra_val + offset, rs_val);
3284       if (opcode == STBU) {
3285         DCHECK_NE(ra, 0);
3286         set_register(ra, ra_val + offset);
3287       }
3288       break;
3289     }
3290 
3291     case LHZU:
3292     case LHZ: {
3293       int ra = instr->RAValue();
3294       int rt = instr->RTValue();
3295       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3296       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3297       uintptr_t result = ReadHU(ra_val + offset) & 0xFFFF;
3298       set_register(rt, result);
3299       if (opcode == LHZU) {
3300         set_register(ra, ra_val + offset);
3301       }
3302       break;
3303     }
3304 
3305     case LHA:
3306     case LHAU: {
3307       int ra = instr->RAValue();
3308       int rt = instr->RTValue();
3309       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3310       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3311       intptr_t result = ReadH(ra_val + offset);
3312       set_register(rt, result);
3313       if (opcode == LHAU) {
3314         set_register(ra, ra_val + offset);
3315       }
3316       break;
3317     }
3318 
3319     case STHU:
3320     case STH: {
3321       int ra = instr->RAValue();
3322       int rs = instr->RSValue();
3323       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3324       int16_t rs_val = get_register(rs);
3325       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3326       WriteH(ra_val + offset, rs_val);
3327       if (opcode == STHU) {
3328         DCHECK_NE(ra, 0);
3329         set_register(ra, ra_val + offset);
3330       }
3331       break;
3332     }
3333 
3334     case LMW:
3335     case STMW: {
3336       UNIMPLEMENTED();
3337     }
3338 
3339     case LFSU:
3340     case LFS: {
3341       int frt = instr->RTValue();
3342       int ra = instr->RAValue();
3343       int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3344       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3345       int32_t val = ReadW(ra_val + offset);
3346       float* fptr = reinterpret_cast<float*>(&val);
3347 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
3348       // Conversion using double changes sNan to qNan on ia32/x64
3349       if ((val & 0x7F800000) == 0x7F800000) {
3350         int64_t dval = static_cast<int64_t>(val);
3351         dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
3352                ((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29) | 0x0;
3353         set_d_register(frt, dval);
3354       } else {
3355         set_d_register_from_double(frt, static_cast<double>(*fptr));
3356       }
3357 #else
3358       set_d_register_from_double(frt, static_cast<double>(*fptr));
3359 #endif
3360       if (opcode == LFSU) {
3361         DCHECK_NE(ra, 0);
3362         set_register(ra, ra_val + offset);
3363       }
3364       break;
3365     }
3366 
3367     case LFDU:
3368     case LFD: {
3369       int frt = instr->RTValue();
3370       int ra = instr->RAValue();
3371       int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3372       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3373       int64_t dptr = ReadDW(ra_val + offset);
3374       set_d_register(frt, dptr);
3375       if (opcode == LFDU) {
3376         DCHECK_NE(ra, 0);
3377         set_register(ra, ra_val + offset);
3378       }
3379       break;
3380     }
3381 
3382     case STFSU:
3383       V8_FALLTHROUGH;
3384     case STFS: {
3385       int frs = instr->RSValue();
3386       int ra = instr->RAValue();
3387       int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3388       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3389       float frs_val = static_cast<float>(get_double_from_d_register(frs));
3390       int32_t* p;
3391 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
3392       // Conversion using double changes sNan to qNan on ia32/x64
3393       int32_t sval = 0;
3394       int64_t dval = get_d_register(frs);
3395       if ((dval & 0x7FF0000000000000) == 0x7FF0000000000000) {
3396         sval = ((dval & 0xC000000000000000) >> 32) |
3397                ((dval & 0x07FFFFFFE0000000) >> 29);
3398         p = &sval;
3399       } else {
3400         p = reinterpret_cast<int32_t*>(&frs_val);
3401       }
3402 #else
3403       p = reinterpret_cast<int32_t*>(&frs_val);
3404 #endif
3405       WriteW(ra_val + offset, *p);
3406       if (opcode == STFSU) {
3407         DCHECK_NE(ra, 0);
3408         set_register(ra, ra_val + offset);
3409       }
3410       break;
3411     }
3412     case STFDU:
3413     case STFD: {
3414       int frs = instr->RSValue();
3415       int ra = instr->RAValue();
3416       int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
3417       intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3418       int64_t frs_val = get_d_register(frs);
3419       WriteDW(ra_val + offset, frs_val);
3420       if (opcode == STFDU) {
3421         DCHECK_NE(ra, 0);
3422         set_register(ra, ra_val + offset);
3423       }
3424       break;
3425     }
3426     case BRW: {
3427       constexpr int kBitsPerWord = 32;
3428       int rs = instr->RSValue();
3429       int ra = instr->RAValue();
3430       uint64_t rs_val = get_register(rs);
3431       uint32_t rs_high = rs_val >> kBitsPerWord;
3432       uint32_t rs_low = (rs_val << kBitsPerWord) >> kBitsPerWord;
3433       uint64_t result = __builtin_bswap32(rs_high);
3434       result = (result << kBitsPerWord) | __builtin_bswap32(rs_low);
3435       set_register(ra, result);
3436       break;
3437     }
3438     case BRD: {
3439       int rs = instr->RSValue();
3440       int ra = instr->RAValue();
3441       uint64_t rs_val = get_register(rs);
3442       set_register(ra, __builtin_bswap64(rs_val));
3443       break;
3444     }
3445     case FCFIDS: {
3446       // fcfids
3447       int frt = instr->RTValue();
3448       int frb = instr->RBValue();
3449       int64_t frb_val = get_d_register(frb);
3450       double frt_val = static_cast<float>(frb_val);
3451       set_d_register_from_double(frt, frt_val);
3452       return;
3453     }
3454     case FCFIDUS: {
3455       // fcfidus
3456       int frt = instr->RTValue();
3457       int frb = instr->RBValue();
3458       uint64_t frb_val = get_d_register(frb);
3459       double frt_val = static_cast<float>(frb_val);
3460       set_d_register_from_double(frt, frt_val);
3461       return;
3462     }
3463 
3464     case FDIV: {
3465       int frt = instr->RTValue();
3466       int fra = instr->RAValue();
3467       int frb = instr->RBValue();
3468       double fra_val = get_double_from_d_register(fra);
3469       double frb_val = get_double_from_d_register(frb);
3470       double frt_val = fra_val / frb_val;
3471       set_d_register_from_double(frt, frt_val);
3472       return;
3473     }
3474     case FSUB: {
3475       int frt = instr->RTValue();
3476       int fra = instr->RAValue();
3477       int frb = instr->RBValue();
3478       double fra_val = get_double_from_d_register(fra);
3479       double frb_val = get_double_from_d_register(frb);
3480       double frt_val = fra_val - frb_val;
3481       set_d_register_from_double(frt, frt_val);
3482       return;
3483     }
3484     case FADD: {
3485       int frt = instr->RTValue();
3486       int fra = instr->RAValue();
3487       int frb = instr->RBValue();
3488       double fra_val = get_double_from_d_register(fra);
3489       double frb_val = get_double_from_d_register(frb);
3490       double frt_val = fra_val + frb_val;
3491       set_d_register_from_double(frt, frt_val);
3492       return;
3493     }
3494     case FSQRT: {
3495       int frt = instr->RTValue();
3496       int frb = instr->RBValue();
3497       double frb_val = get_double_from_d_register(frb);
3498       double frt_val = std::sqrt(frb_val);
3499       set_d_register_from_double(frt, frt_val);
3500       return;
3501     }
3502     case FSEL: {
3503       int frt = instr->RTValue();
3504       int fra = instr->RAValue();
3505       int frb = instr->RBValue();
3506       int frc = instr->RCValue();
3507       double fra_val = get_double_from_d_register(fra);
3508       double frb_val = get_double_from_d_register(frb);
3509       double frc_val = get_double_from_d_register(frc);
3510       double frt_val = ((fra_val >= 0.0) ? frc_val : frb_val);
3511       set_d_register_from_double(frt, frt_val);
3512       return;
3513     }
3514     case FMUL: {
3515       int frt = instr->RTValue();
3516       int fra = instr->RAValue();
3517       int frc = instr->RCValue();
3518       double fra_val = get_double_from_d_register(fra);
3519       double frc_val = get_double_from_d_register(frc);
3520       double frt_val = fra_val * frc_val;
3521       set_d_register_from_double(frt, frt_val);
3522       return;
3523     }
3524     case FMSUB: {
3525       int frt = instr->RTValue();
3526       int fra = instr->RAValue();
3527       int frb = instr->RBValue();
3528       int frc = instr->RCValue();
3529       double fra_val = get_double_from_d_register(fra);
3530       double frb_val = get_double_from_d_register(frb);
3531       double frc_val = get_double_from_d_register(frc);
3532       double frt_val = (fra_val * frc_val) - frb_val;
3533       set_d_register_from_double(frt, frt_val);
3534       return;
3535     }
3536     case FMADD: {
3537       int frt = instr->RTValue();
3538       int fra = instr->RAValue();
3539       int frb = instr->RBValue();
3540       int frc = instr->RCValue();
3541       double fra_val = get_double_from_d_register(fra);
3542       double frb_val = get_double_from_d_register(frb);
3543       double frc_val = get_double_from_d_register(frc);
3544       double frt_val = (fra_val * frc_val) + frb_val;
3545       set_d_register_from_double(frt, frt_val);
3546       return;
3547     }
3548     case FCMPU: {
3549       int fra = instr->RAValue();
3550       int frb = instr->RBValue();
3551       double fra_val = get_double_from_d_register(fra);
3552       double frb_val = get_double_from_d_register(frb);
3553       int cr = instr->Bits(25, 23);
3554       int bf = 0;
3555       if (fra_val < frb_val) {
3556         bf |= 0x80000000;
3557       }
3558       if (fra_val > frb_val) {
3559         bf |= 0x40000000;
3560       }
3561       if (fra_val == frb_val) {
3562         bf |= 0x20000000;
3563       }
3564       if (std::isunordered(fra_val, frb_val)) {
3565         bf |= 0x10000000;
3566       }
3567       int condition_mask = 0xF0000000 >> (cr * 4);
3568       int condition = bf >> (cr * 4);
3569       condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
3570       return;
3571     }
3572     case FRIN: {
3573       int frt = instr->RTValue();
3574       int frb = instr->RBValue();
3575       double frb_val = get_double_from_d_register(frb);
3576       double frt_val = std::round(frb_val);
3577       set_d_register_from_double(frt, frt_val);
3578       if (instr->Bit(0)) {  // RC bit set
3579                             //  UNIMPLEMENTED();
3580       }
3581       return;
3582     }
3583     case FRIZ: {
3584       int frt = instr->RTValue();
3585       int frb = instr->RBValue();
3586       double frb_val = get_double_from_d_register(frb);
3587       double frt_val = std::trunc(frb_val);
3588       set_d_register_from_double(frt, frt_val);
3589       if (instr->Bit(0)) {  // RC bit set
3590                             //  UNIMPLEMENTED();
3591       }
3592       return;
3593     }
3594     case FRIP: {
3595       int frt = instr->RTValue();
3596       int frb = instr->RBValue();
3597       double frb_val = get_double_from_d_register(frb);
3598       double frt_val = std::ceil(frb_val);
3599       set_d_register_from_double(frt, frt_val);
3600       if (instr->Bit(0)) {  // RC bit set
3601                             //  UNIMPLEMENTED();
3602       }
3603       return;
3604     }
3605     case FRIM: {
3606       int frt = instr->RTValue();
3607       int frb = instr->RBValue();
3608       double frb_val = get_double_from_d_register(frb);
3609       double frt_val = std::floor(frb_val);
3610       set_d_register_from_double(frt, frt_val);
3611       if (instr->Bit(0)) {  // RC bit set
3612                             //  UNIMPLEMENTED();
3613       }
3614       return;
3615     }
3616     case FRSP: {
3617       int frt = instr->RTValue();
3618       int frb = instr->RBValue();
3619       // frsp round 8-byte double-precision value to
3620       // single-precision value
3621       double frb_val = get_double_from_d_register(frb);
3622       double frt_val = static_cast<float>(frb_val);
3623       set_d_register_from_double(frt, frt_val);
3624       if (instr->Bit(0)) {  // RC bit set
3625                             //  UNIMPLEMENTED();
3626       }
3627       return;
3628     }
3629     case FCFID: {
3630       int frt = instr->RTValue();
3631       int frb = instr->RBValue();
3632       int64_t frb_val = get_d_register(frb);
3633       double frt_val = static_cast<double>(frb_val);
3634       set_d_register_from_double(frt, frt_val);
3635       return;
3636     }
3637     case FCFIDU: {
3638       int frt = instr->RTValue();
3639       int frb = instr->RBValue();
3640       uint64_t frb_val = get_d_register(frb);
3641       double frt_val = static_cast<double>(frb_val);
3642       set_d_register_from_double(frt, frt_val);
3643       return;
3644     }
3645     case FCTID:
3646     case FCTIDZ: {
3647       int frt = instr->RTValue();
3648       int frb = instr->RBValue();
3649       double frb_val = get_double_from_d_register(frb);
3650       int mode = (opcode == FCTIDZ) ? kRoundToZero
3651                                     : (fp_condition_reg_ & kFPRoundingModeMask);
3652       int64_t frt_val;
3653       int64_t one = 1;  // work-around gcc
3654       int64_t kMinVal = (one << 63);
3655       int64_t kMaxVal = kMinVal - 1;
3656       bool invalid_convert = false;
3657 
3658       if (std::isnan(frb_val)) {
3659         frt_val = kMinVal;
3660         invalid_convert = true;
3661       } else {
3662         switch (mode) {
3663           case kRoundToZero:
3664             frb_val = std::trunc(frb_val);
3665             break;
3666           case kRoundToPlusInf:
3667             frb_val = std::ceil(frb_val);
3668             break;
3669           case kRoundToMinusInf:
3670             frb_val = std::floor(frb_val);
3671             break;
3672           default:
3673             UNIMPLEMENTED();  // Not used by V8.
3674         }
3675         if (frb_val < static_cast<double>(kMinVal)) {
3676           frt_val = kMinVal;
3677           invalid_convert = true;
3678         } else if (frb_val >= static_cast<double>(kMaxVal)) {
3679           frt_val = kMaxVal;
3680           invalid_convert = true;
3681         } else {
3682           frt_val = (int64_t)frb_val;
3683         }
3684       }
3685       set_d_register(frt, frt_val);
3686       if (invalid_convert) SetFPSCR(VXCVI);
3687       return;
3688     }
3689     case FCTIDU:
3690     case FCTIDUZ: {
3691       int frt = instr->RTValue();
3692       int frb = instr->RBValue();
3693       double frb_val = get_double_from_d_register(frb);
3694       int mode = (opcode == FCTIDUZ)
3695                      ? kRoundToZero
3696                      : (fp_condition_reg_ & kFPRoundingModeMask);
3697       uint64_t frt_val;
3698       uint64_t kMinVal = 0;
3699       uint64_t kMaxVal = kMinVal - 1;
3700       bool invalid_convert = false;
3701 
3702       if (std::isnan(frb_val)) {
3703         frt_val = kMinVal;
3704         invalid_convert = true;
3705       } else {
3706         switch (mode) {
3707           case kRoundToZero:
3708             frb_val = std::trunc(frb_val);
3709             break;
3710           case kRoundToPlusInf:
3711             frb_val = std::ceil(frb_val);
3712             break;
3713           case kRoundToMinusInf:
3714             frb_val = std::floor(frb_val);
3715             break;
3716           default:
3717             UNIMPLEMENTED();  // Not used by V8.
3718         }
3719         if (frb_val < static_cast<double>(kMinVal)) {
3720           frt_val = kMinVal;
3721           invalid_convert = true;
3722         } else if (frb_val >= static_cast<double>(kMaxVal)) {
3723           frt_val = kMaxVal;
3724           invalid_convert = true;
3725         } else {
3726           frt_val = (uint64_t)frb_val;
3727         }
3728       }
3729       set_d_register(frt, frt_val);
3730       if (invalid_convert) SetFPSCR(VXCVI);
3731       return;
3732     }
3733     case FCTIW:
3734     case FCTIWZ: {
3735       int frt = instr->RTValue();
3736       int frb = instr->RBValue();
3737       double frb_val = get_double_from_d_register(frb);
3738       int mode = (opcode == FCTIWZ) ? kRoundToZero
3739                                     : (fp_condition_reg_ & kFPRoundingModeMask);
3740       int64_t frt_val;
3741       int64_t kMinVal = kMinInt;
3742       int64_t kMaxVal = kMaxInt;
3743       bool invalid_convert = false;
3744 
3745       if (std::isnan(frb_val)) {
3746         frt_val = kMinVal;
3747       } else {
3748         switch (mode) {
3749           case kRoundToZero:
3750             frb_val = std::trunc(frb_val);
3751             break;
3752           case kRoundToPlusInf:
3753             frb_val = std::ceil(frb_val);
3754             break;
3755           case kRoundToMinusInf:
3756             frb_val = std::floor(frb_val);
3757             break;
3758           case kRoundToNearest: {
3759             double orig = frb_val;
3760             frb_val = lround(frb_val);
3761             // Round to even if exactly halfway.  (lround rounds up)
3762             if (std::fabs(frb_val - orig) == 0.5 && ((int64_t)frb_val % 2)) {
3763               frb_val += ((frb_val > 0) ? -1.0 : 1.0);
3764             }
3765             break;
3766           }
3767           default:
3768             UNIMPLEMENTED();  // Not used by V8.
3769         }
3770         if (frb_val < kMinVal) {
3771           frt_val = kMinVal;
3772           invalid_convert = true;
3773         } else if (frb_val > kMaxVal) {
3774           frt_val = kMaxVal;
3775           invalid_convert = true;
3776         } else {
3777           frt_val = (int64_t)frb_val;
3778         }
3779       }
3780       set_d_register(frt, frt_val);
3781       if (invalid_convert) SetFPSCR(VXCVI);
3782       return;
3783     }
3784     case FCTIWU:
3785     case FCTIWUZ: {
3786       int frt = instr->RTValue();
3787       int frb = instr->RBValue();
3788       double frb_val = get_double_from_d_register(frb);
3789       int mode = (opcode == FCTIWUZ)
3790                      ? kRoundToZero
3791                      : (fp_condition_reg_ & kFPRoundingModeMask);
3792       uint64_t frt_val;
3793       uint64_t kMinVal = kMinUInt32;
3794       uint64_t kMaxVal = kMaxUInt32;
3795       bool invalid_convert = false;
3796 
3797       if (std::isnan(frb_val)) {
3798         frt_val = kMinVal;
3799       } else {
3800         switch (mode) {
3801           case kRoundToZero:
3802             frb_val = std::trunc(frb_val);
3803             break;
3804           case kRoundToPlusInf:
3805             frb_val = std::ceil(frb_val);
3806             break;
3807           case kRoundToMinusInf:
3808             frb_val = std::floor(frb_val);
3809             break;
3810           default:
3811             UNIMPLEMENTED();  // Not used by V8.
3812         }
3813         if (frb_val < kMinVal) {
3814           frt_val = kMinVal;
3815           invalid_convert = true;
3816         } else if (frb_val > kMaxVal) {
3817           frt_val = kMaxVal;
3818           invalid_convert = true;
3819         } else {
3820           frt_val = (uint64_t)frb_val;
3821         }
3822       }
3823       set_d_register(frt, frt_val);
3824       if (invalid_convert) SetFPSCR(VXCVI);
3825       return;
3826     }
3827     case FNEG: {
3828       int frt = instr->RTValue();
3829       int frb = instr->RBValue();
3830       double frb_val = get_double_from_d_register(frb);
3831       double frt_val = -frb_val;
3832       set_d_register_from_double(frt, frt_val);
3833       return;
3834     }
3835     case FCPSGN: {
3836       int frt = instr->RTValue();
3837       int frb = instr->RBValue();
3838       int fra = instr->RAValue();
3839       double frb_val = get_double_from_d_register(frb);
3840       double fra_val = get_double_from_d_register(fra);
3841       double frt_val = std::copysign(frb_val, fra_val);
3842       set_d_register_from_double(frt, frt_val);
3843       return;
3844     }
3845     case FMR: {
3846       int frt = instr->RTValue();
3847       int frb = instr->RBValue();
3848       int64_t frb_val = get_d_register(frb);
3849       set_d_register(frt, frb_val);
3850       return;
3851     }
3852     case MTFSFI: {
3853       int bf = instr->Bits(25, 23);
3854       int imm = instr->Bits(15, 12);
3855       int fp_condition_mask = 0xF0000000 >> (bf * 4);
3856       fp_condition_reg_ &= ~fp_condition_mask;
3857       fp_condition_reg_ |= (imm << (28 - (bf * 4)));
3858       if (instr->Bit(0)) {  // RC bit set
3859         condition_reg_ &= 0xF0FFFFFF;
3860         condition_reg_ |= (imm << 23);
3861       }
3862       return;
3863     }
3864     case MTFSF: {
3865       int frb = instr->RBValue();
3866       int64_t frb_dval = get_d_register(frb);
3867       int32_t frb_ival = static_cast<int32_t>((frb_dval)&0xFFFFFFFF);
3868       int l = instr->Bits(25, 25);
3869       if (l == 1) {
3870         fp_condition_reg_ = frb_ival;
3871       } else {
3872         UNIMPLEMENTED();
3873       }
3874       if (instr->Bit(0)) {  // RC bit set
3875         UNIMPLEMENTED();
3876         // int w = instr->Bits(16, 16);
3877         // int flm = instr->Bits(24, 17);
3878       }
3879       return;
3880     }
3881     case MFFS: {
3882       int frt = instr->RTValue();
3883       int64_t lval = static_cast<int64_t>(fp_condition_reg_);
3884       set_d_register(frt, lval);
3885       return;
3886     }
3887     case MCRFS: {
3888       int bf = instr->Bits(25, 23);
3889       int bfa = instr->Bits(20, 18);
3890       int cr_shift = (7 - bf) * CRWIDTH;
3891       int fp_shift = (7 - bfa) * CRWIDTH;
3892       int field_val = (fp_condition_reg_ >> fp_shift) & 0xF;
3893       condition_reg_ &= ~(0x0F << cr_shift);
3894       condition_reg_ |= (field_val << cr_shift);
3895       // Clear copied exception bits
3896       switch (bfa) {
3897         case 5:
3898           ClearFPSCR(VXSOFT);
3899           ClearFPSCR(VXSQRT);
3900           ClearFPSCR(VXCVI);
3901           break;
3902         default:
3903           UNIMPLEMENTED();
3904       }
3905       return;
3906     }
3907     case MTFSB0: {
3908       int bt = instr->Bits(25, 21);
3909       ClearFPSCR(bt);
3910       if (instr->Bit(0)) {  // RC bit set
3911         UNIMPLEMENTED();
3912       }
3913       return;
3914     }
3915     case MTFSB1: {
3916       int bt = instr->Bits(25, 21);
3917       SetFPSCR(bt);
3918       if (instr->Bit(0)) {  // RC bit set
3919         UNIMPLEMENTED();
3920       }
3921       return;
3922     }
3923     case FABS: {
3924       int frt = instr->RTValue();
3925       int frb = instr->RBValue();
3926       double frb_val = get_double_from_d_register(frb);
3927       double frt_val = std::fabs(frb_val);
3928       set_d_register_from_double(frt, frt_val);
3929       return;
3930     }
3931 
3932 #if V8_TARGET_ARCH_PPC64
3933     case RLDICL: {
3934       int ra = instr->RAValue();
3935       int rs = instr->RSValue();
3936       uintptr_t rs_val = get_register(rs);
3937       int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3938       int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3939       DCHECK(sh >= 0 && sh <= 63);
3940       DCHECK(mb >= 0 && mb <= 63);
3941       uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3942       uintptr_t mask = 0xFFFFFFFFFFFFFFFF >> mb;
3943       result &= mask;
3944       set_register(ra, result);
3945       if (instr->Bit(0)) {  // RC bit set
3946         SetCR0(result);
3947       }
3948       return;
3949     }
3950     case RLDICR: {
3951       int ra = instr->RAValue();
3952       int rs = instr->RSValue();
3953       uintptr_t rs_val = get_register(rs);
3954       int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3955       int me = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3956       DCHECK(sh >= 0 && sh <= 63);
3957       DCHECK(me >= 0 && me <= 63);
3958       uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3959       uintptr_t mask = 0xFFFFFFFFFFFFFFFF << (63 - me);
3960       result &= mask;
3961       set_register(ra, result);
3962       if (instr->Bit(0)) {  // RC bit set
3963         SetCR0(result);
3964       }
3965       return;
3966     }
3967     case RLDIC: {
3968       int ra = instr->RAValue();
3969       int rs = instr->RSValue();
3970       uintptr_t rs_val = get_register(rs);
3971       int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3972       int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3973       DCHECK(sh >= 0 && sh <= 63);
3974       DCHECK(mb >= 0 && mb <= 63);
3975       uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3976       uintptr_t mask = (0xFFFFFFFFFFFFFFFF >> mb) & (0xFFFFFFFFFFFFFFFF << sh);
3977       result &= mask;
3978       set_register(ra, result);
3979       if (instr->Bit(0)) {  // RC bit set
3980         SetCR0(result);
3981       }
3982       return;
3983     }
3984     case RLDIMI: {
3985       int ra = instr->RAValue();
3986       int rs = instr->RSValue();
3987       uintptr_t rs_val = get_register(rs);
3988       intptr_t ra_val = get_register(ra);
3989       int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
3990       int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
3991       int me = 63 - sh;
3992       uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
3993       uintptr_t mask = 0;
3994       if (mb < me + 1) {
3995         uintptr_t bit = 0x8000000000000000 >> mb;
3996         for (; mb <= me; mb++) {
3997           mask |= bit;
3998           bit >>= 1;
3999         }
4000       } else if (mb == me + 1) {
4001         mask = 0xFFFFFFFFFFFFFFFF;
4002       } else {                                           // mb > me+1
4003         uintptr_t bit = 0x8000000000000000 >> (me + 1);  // needs to be tested
4004         mask = 0xFFFFFFFFFFFFFFFF;
4005         for (; me < mb; me++) {
4006           mask ^= bit;
4007           bit >>= 1;
4008         }
4009       }
4010       result &= mask;
4011       ra_val &= ~mask;
4012       result |= ra_val;
4013       set_register(ra, result);
4014       if (instr->Bit(0)) {  // RC bit set
4015         SetCR0(result);
4016       }
4017       return;
4018     }
4019     case RLDCL: {
4020       int ra = instr->RAValue();
4021       int rs = instr->RSValue();
4022       int rb = instr->RBValue();
4023       uintptr_t rs_val = get_register(rs);
4024       uintptr_t rb_val = get_register(rb);
4025       int sh = (rb_val & 0x3F);
4026       int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
4027       DCHECK(sh >= 0 && sh <= 63);
4028       DCHECK(mb >= 0 && mb <= 63);
4029       uintptr_t result = base::bits::RotateLeft64(rs_val, sh);
4030       uintptr_t mask = 0xFFFFFFFFFFFFFFFF >> mb;
4031       result &= mask;
4032       set_register(ra, result);
4033       if (instr->Bit(0)) {  // RC bit set
4034         SetCR0(result);
4035       }
4036       return;
4037     }
4038 
4039     case LD:
4040     case LDU:
4041     case LWA: {
4042       int ra = instr->RAValue();
4043       int rt = instr->RTValue();
4044       int64_t ra_val = ra == 0 ? 0 : get_register(ra);
4045       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
4046       switch (instr->Bits(1, 0)) {
4047         case 0: {  // ld
4048           intptr_t result = ReadDW(ra_val + offset);
4049           set_register(rt, result);
4050           break;
4051         }
4052         case 1: {  // ldu
4053           intptr_t result = ReadDW(ra_val + offset);
4054           set_register(rt, result);
4055           DCHECK_NE(ra, 0);
4056           set_register(ra, ra_val + offset);
4057           break;
4058         }
4059         case 2: {  // lwa
4060           intptr_t result = ReadW(ra_val + offset);
4061           set_register(rt, result);
4062           break;
4063         }
4064       }
4065       break;
4066     }
4067 
4068     case STD:
4069     case STDU: {
4070       int ra = instr->RAValue();
4071       int rs = instr->RSValue();
4072       int64_t ra_val = ra == 0 ? 0 : get_register(ra);
4073       int64_t rs_val = get_register(rs);
4074       int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
4075       WriteDW(ra_val + offset, rs_val);
4076       if (opcode == STDU) {
4077         DCHECK_NE(ra, 0);
4078         set_register(ra, ra_val + offset);
4079       }
4080       break;
4081     }
4082 #endif
4083 
4084     case XSADDDP: {
4085       int frt = instr->RTValue();
4086       int fra = instr->RAValue();
4087       int frb = instr->RBValue();
4088       double fra_val = get_double_from_d_register(fra);
4089       double frb_val = get_double_from_d_register(frb);
4090       double frt_val = fra_val + frb_val;
4091       set_d_register_from_double(frt, frt_val);
4092       return;
4093     }
4094     case XSSUBDP: {
4095       int frt = instr->RTValue();
4096       int fra = instr->RAValue();
4097       int frb = instr->RBValue();
4098       double fra_val = get_double_from_d_register(fra);
4099       double frb_val = get_double_from_d_register(frb);
4100       double frt_val = fra_val - frb_val;
4101       set_d_register_from_double(frt, frt_val);
4102       return;
4103     }
4104     case XSMULDP: {
4105       int frt = instr->RTValue();
4106       int fra = instr->RAValue();
4107       int frb = instr->RBValue();
4108       double fra_val = get_double_from_d_register(fra);
4109       double frb_val = get_double_from_d_register(frb);
4110       double frt_val = fra_val * frb_val;
4111       set_d_register_from_double(frt, frt_val);
4112       return;
4113     }
4114     case XSDIVDP: {
4115       int frt = instr->RTValue();
4116       int fra = instr->RAValue();
4117       int frb = instr->RBValue();
4118       double fra_val = get_double_from_d_register(fra);
4119       double frb_val = get_double_from_d_register(frb);
4120       double frt_val = fra_val / frb_val;
4121       set_d_register_from_double(frt, frt_val);
4122       return;
4123     }
4124     case MTCRF: {
4125       int rs = instr->RSValue();
4126       uint32_t rs_val = static_cast<int32_t>(get_register(rs));
4127       uint8_t fxm = instr->Bits(19, 12);
4128       uint8_t bit_mask = 0x80;
4129       const int field_bit_count = 4;
4130       const int max_field_index = 7;
4131       uint32_t result = 0;
4132       for (int i = 0; i <= max_field_index; i++) {
4133         result <<= field_bit_count;
4134         uint32_t source = condition_reg_;
4135         if ((bit_mask & fxm) != 0) {
4136           // take it from rs.
4137           source = rs_val;
4138         }
4139         result |= ((source << i * field_bit_count) >> i * field_bit_count) >>
4140                   (max_field_index - i) * field_bit_count;
4141         bit_mask >>= 1;
4142       }
4143       condition_reg_ = result;
4144       break;
4145     }
4146     // Vector instructions.
4147     case LVX: {
4148       DECODE_VX_INSTRUCTION(vrt, ra, rb, T)
4149       GET_ADDRESS(ra, rb, ra_val, rb_val)
4150       intptr_t addr = (ra_val + rb_val) & 0xFFFFFFFFFFFFFFF0;
4151       simdr_t* ptr = reinterpret_cast<simdr_t*>(addr);
4152       set_simd_register(vrt, *ptr);
4153       break;
4154     }
4155     case STVX: {
4156       DECODE_VX_INSTRUCTION(vrs, ra, rb, S)
4157       GET_ADDRESS(ra, rb, ra_val, rb_val)
4158       __int128 vrs_val = bit_cast<__int128>(get_simd_register(vrs).int8);
4159       WriteQW((ra_val + rb_val) & 0xFFFFFFFFFFFFFFF0, vrs_val);
4160       break;
4161     }
4162     case LXVD: {
4163       DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4164       GET_ADDRESS(ra, rb, ra_val, rb_val)
4165       set_simd_register_by_lane<int64_t>(xt, 0, ReadDW(ra_val + rb_val));
4166       set_simd_register_by_lane<int64_t>(
4167           xt, 1, ReadDW(ra_val + rb_val + kSystemPointerSize));
4168       break;
4169     }
4170     case LXVX: {
4171       DECODE_VX_INSTRUCTION(vrt, ra, rb, T)
4172       GET_ADDRESS(ra, rb, ra_val, rb_val)
4173       intptr_t addr = ra_val + rb_val;
4174       simdr_t* ptr = reinterpret_cast<simdr_t*>(addr);
4175       set_simd_register(vrt, *ptr);
4176       break;
4177     }
4178     case STXVD: {
4179       DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4180       GET_ADDRESS(ra, rb, ra_val, rb_val)
4181       WriteDW(ra_val + rb_val, get_simd_register_by_lane<int64_t>(xs, 0));
4182       WriteDW(ra_val + rb_val + kSystemPointerSize,
4183               get_simd_register_by_lane<int64_t>(xs, 1));
4184       break;
4185     }
4186     case STXVX: {
4187       DECODE_VX_INSTRUCTION(vrs, ra, rb, S)
4188       GET_ADDRESS(ra, rb, ra_val, rb_val)
4189       intptr_t addr = ra_val + rb_val;
4190       __int128 vrs_val = bit_cast<__int128>(get_simd_register(vrs).int8);
4191       WriteQW(addr, vrs_val);
4192       break;
4193     }
4194     case LXSIBZX: {
4195       DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4196       GET_ADDRESS(ra, rb, ra_val, rb_val)
4197       set_simd_register_by_lane<uint64_t>(xt, 0, ReadBU(ra_val + rb_val));
4198       break;
4199     }
4200     case LXSIHZX: {
4201       DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4202       GET_ADDRESS(ra, rb, ra_val, rb_val)
4203       set_simd_register_by_lane<uint64_t>(xt, 0, ReadHU(ra_val + rb_val));
4204       break;
4205     }
4206     case LXSIWZX: {
4207       DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4208       GET_ADDRESS(ra, rb, ra_val, rb_val)
4209       set_simd_register_by_lane<uint64_t>(xt, 0, ReadWU(ra_val + rb_val));
4210       break;
4211     }
4212     case LXSDX: {
4213       DECODE_VX_INSTRUCTION(xt, ra, rb, T)
4214       GET_ADDRESS(ra, rb, ra_val, rb_val)
4215       set_simd_register_by_lane<int64_t>(xt, 0, ReadDW(ra_val + rb_val));
4216       break;
4217     }
4218     case STXSIBX: {
4219       DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4220       GET_ADDRESS(ra, rb, ra_val, rb_val)
4221       WriteB(ra_val + rb_val, get_simd_register_by_lane<int8_t>(xs, 7));
4222       break;
4223     }
4224     case STXSIHX: {
4225       DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4226       GET_ADDRESS(ra, rb, ra_val, rb_val)
4227       WriteH(ra_val + rb_val, get_simd_register_by_lane<int16_t>(xs, 3));
4228       break;
4229     }
4230     case STXSIWX: {
4231       DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4232       GET_ADDRESS(ra, rb, ra_val, rb_val)
4233       WriteW(ra_val + rb_val, get_simd_register_by_lane<int32_t>(xs, 1));
4234       break;
4235     }
4236     case STXSDX: {
4237       DECODE_VX_INSTRUCTION(xs, ra, rb, S)
4238       GET_ADDRESS(ra, rb, ra_val, rb_val)
4239       WriteDW(ra_val + rb_val, get_simd_register_by_lane<int64_t>(xs, 0));
4240       break;
4241     }
4242     case XXBRQ: {
4243       int t = instr->RTValue();
4244       int b = instr->RBValue();
4245       __int128 xb_val = bit_cast<__int128>(get_simd_register(b).int8);
4246       __int128 xb_val_reversed = __builtin_bswap128(xb_val);
4247       simdr_t simdr_xb = bit_cast<simdr_t>(xb_val_reversed);
4248       set_simd_register(t, simdr_xb);
4249       break;
4250     }
4251 #define VSPLT(type)                                       \
4252   uint8_t uim = instr->Bits(19, 16);                      \
4253   int vrt = instr->RTValue();                             \
4254   int vrb = instr->RBValue();                             \
4255   type value = get_simd_register_by_lane<type>(vrb, uim); \
4256   FOR_EACH_LANE(i, type) { set_simd_register_by_lane<type>(vrt, i, value); }
4257     case VSPLTW: {
4258       VSPLT(int32_t)
4259       break;
4260     }
4261     case VSPLTH: {
4262       VSPLT(int16_t)
4263       break;
4264     }
4265     case VSPLTB: {
4266       VSPLT(int8_t)
4267       break;
4268     }
4269     case XXSPLTIB: {
4270       int8_t imm8 = instr->Bits(18, 11);
4271       int t = instr->RTValue();
4272       FOR_EACH_LANE(i, int8_t) {
4273         set_simd_register_by_lane<int8_t>(t, i, imm8);
4274       }
4275       break;
4276     }
4277 #undef VSPLT
4278 #define VSPLTI(type)                                                \
4279   type sim = static_cast<type>(SIGN_EXT_IMM5(instr->Bits(20, 16))); \
4280   int vrt = instr->RTValue();                                       \
4281   FOR_EACH_LANE(i, type) { set_simd_register_by_lane<type>(vrt, i, sim); }
4282     case VSPLTISW: {
4283       VSPLTI(int32_t)
4284       break;
4285     }
4286     case VSPLTISH: {
4287       VSPLTI(int16_t)
4288       break;
4289     }
4290     case VSPLTISB: {
4291       VSPLTI(int8_t)
4292       break;
4293     }
4294 #undef VSPLTI
4295 #define VINSERT(type, element)       \
4296   uint8_t uim = instr->Bits(19, 16); \
4297   int vrt = instr->RTValue();        \
4298   int vrb = instr->RBValue();        \
4299   set_simd_register_bytes<type>(     \
4300       vrt, uim, get_simd_register_by_lane<type>(vrb, element));
4301     case VINSERTD: {
4302       VINSERT(int64_t, 0)
4303       break;
4304     }
4305     case VINSERTW: {
4306       VINSERT(int32_t, 1)
4307       break;
4308     }
4309     case VINSERTH: {
4310       VINSERT(int16_t, 3)
4311       break;
4312     }
4313     case VINSERTB: {
4314       VINSERT(int8_t, 7)
4315       break;
4316     }
4317 #undef VINSERT
4318 #define VINSERT_IMMEDIATE(type)                   \
4319   uint8_t uim = instr->Bits(19, 16);              \
4320   int vrt = instr->RTValue();                     \
4321   int rb = instr->RBValue();                      \
4322   type src = static_cast<type>(get_register(rb)); \
4323   set_simd_register_bytes<type>(vrt, uim, src);
4324     case VINSD: {
4325       VINSERT_IMMEDIATE(int64_t)
4326       break;
4327     }
4328     case VINSW: {
4329       VINSERT_IMMEDIATE(int32_t)
4330       break;
4331     }
4332 #undef VINSERT_IMMEDIATE
4333 #define VEXTRACT(type, element)                       \
4334   uint8_t uim = instr->Bits(19, 16);                  \
4335   int vrt = instr->RTValue();                         \
4336   int vrb = instr->RBValue();                         \
4337   type val = get_simd_register_bytes<type>(vrb, uim); \
4338   set_simd_register_by_lane<uint64_t>(vrt, 0, 0);     \
4339   set_simd_register_by_lane<uint64_t>(vrt, 1, 0);     \
4340   set_simd_register_by_lane<type>(vrt, element, val);
4341     case VEXTRACTD: {
4342       VEXTRACT(uint64_t, 0)
4343       break;
4344     }
4345     case VEXTRACTUW: {
4346       VEXTRACT(uint32_t, 1)
4347       break;
4348     }
4349     case VEXTRACTUH: {
4350       VEXTRACT(uint16_t, 3)
4351       break;
4352     }
4353     case VEXTRACTUB: {
4354       VEXTRACT(uint8_t, 7)
4355       break;
4356     }
4357 #undef VEXTRACT
4358 #define VECTOR_LOGICAL_OP(expr)                               \
4359   DECODE_VX_INSTRUCTION(t, a, b, T)                           \
4360   FOR_EACH_LANE(i, int64_t) {                                 \
4361     int64_t a_val = get_simd_register_by_lane<int64_t>(a, i); \
4362     int64_t b_val = get_simd_register_by_lane<int64_t>(b, i); \
4363     set_simd_register_by_lane<int64_t>(t, i, expr);           \
4364   }
4365     case VAND: {
4366       VECTOR_LOGICAL_OP(a_val & b_val)
4367       break;
4368     }
4369     case VANDC: {
4370       VECTOR_LOGICAL_OP(a_val & (~b_val))
4371       break;
4372     }
4373     case VOR: {
4374       VECTOR_LOGICAL_OP(a_val | b_val)
4375       break;
4376     }
4377     case VNOR: {
4378       VECTOR_LOGICAL_OP(~(a_val | b_val))
4379       break;
4380     }
4381     case VXOR: {
4382       VECTOR_LOGICAL_OP(a_val ^ b_val)
4383       break;
4384     }
4385 #undef VECTOR_LOGICAL_OP
4386 #define VECTOR_ARITHMETIC_OP(type, op)                 \
4387   DECODE_VX_INSTRUCTION(t, a, b, T)                    \
4388   FOR_EACH_LANE(i, type) {                             \
4389     set_simd_register_by_lane<type>(                   \
4390         t, i,                                          \
4391         get_simd_register_by_lane<type>(a, i)          \
4392             op get_simd_register_by_lane<type>(b, i)); \
4393   }
4394     case XVADDDP: {
4395       VECTOR_ARITHMETIC_OP(double, +)
4396       break;
4397     }
4398     case XVSUBDP: {
4399       VECTOR_ARITHMETIC_OP(double, -)
4400       break;
4401     }
4402     case XVMULDP: {
4403       VECTOR_ARITHMETIC_OP(double, *)
4404       break;
4405     }
4406     case XVDIVDP: {
4407       VECTOR_ARITHMETIC_OP(double, /)
4408       break;
4409     }
4410     case VADDFP: {
4411       VECTOR_ARITHMETIC_OP(float, +)
4412       break;
4413     }
4414     case VSUBFP: {
4415       VECTOR_ARITHMETIC_OP(float, -)
4416       break;
4417     }
4418     case XVMULSP: {
4419       VECTOR_ARITHMETIC_OP(float, *)
4420       break;
4421     }
4422     case XVDIVSP: {
4423       VECTOR_ARITHMETIC_OP(float, /)
4424       break;
4425     }
4426     case VADDUDM: {
4427       VECTOR_ARITHMETIC_OP(int64_t, +)
4428       break;
4429     }
4430     case VSUBUDM: {
4431       VECTOR_ARITHMETIC_OP(int64_t, -)
4432       break;
4433     }
4434     case VMULLD: {
4435       VECTOR_ARITHMETIC_OP(int64_t, *)
4436       break;
4437     }
4438     case VADDUWM: {
4439       VECTOR_ARITHMETIC_OP(int32_t, +)
4440       break;
4441     }
4442     case VSUBUWM: {
4443       VECTOR_ARITHMETIC_OP(int32_t, -)
4444       break;
4445     }
4446     case VMULUWM: {
4447       VECTOR_ARITHMETIC_OP(int32_t, *)
4448       break;
4449     }
4450     case VADDUHM: {
4451       VECTOR_ARITHMETIC_OP(int16_t, +)
4452       break;
4453     }
4454     case VSUBUHM: {
4455       VECTOR_ARITHMETIC_OP(int16_t, -)
4456       break;
4457     }
4458     case VADDUBM: {
4459       VECTOR_ARITHMETIC_OP(int8_t, +)
4460       break;
4461     }
4462     case VSUBUBM: {
4463       VECTOR_ARITHMETIC_OP(int8_t, -)
4464       break;
4465     }
4466 #define VECTOR_MULTIPLY_EVEN_ODD(input_type, result_type, is_odd)              \
4467   DECODE_VX_INSTRUCTION(t, a, b, T)                                            \
4468   size_t i = 0, j = 0, k = 0;                                                  \
4469   size_t lane_size = sizeof(input_type);                                       \
4470   if (is_odd) {                                                                \
4471     i = 1;                                                                     \
4472     j = lane_size;                                                             \
4473   }                                                                            \
4474   for (; j < kSimd128Size; i += 2, j += lane_size * 2, k++) {                  \
4475     result_type src0 =                                                         \
4476         static_cast<result_type>(get_simd_register_by_lane<input_type>(a, i)); \
4477     result_type src1 =                                                         \
4478         static_cast<result_type>(get_simd_register_by_lane<input_type>(b, i)); \
4479     set_simd_register_by_lane<result_type>(t, k, src0 * src1);                 \
4480   }
4481     case VMULEUB: {
4482       VECTOR_MULTIPLY_EVEN_ODD(uint8_t, uint16_t, false)
4483       break;
4484     }
4485     case VMULESB: {
4486       VECTOR_MULTIPLY_EVEN_ODD(int8_t, int16_t, false)
4487       break;
4488     }
4489     case VMULOUB: {
4490       VECTOR_MULTIPLY_EVEN_ODD(uint8_t, uint16_t, true)
4491       break;
4492     }
4493     case VMULOSB: {
4494       VECTOR_MULTIPLY_EVEN_ODD(int8_t, int16_t, true)
4495       break;
4496     }
4497     case VMULEUH: {
4498       VECTOR_MULTIPLY_EVEN_ODD(uint16_t, uint32_t, false)
4499       break;
4500     }
4501     case VMULESH: {
4502       VECTOR_MULTIPLY_EVEN_ODD(int16_t, int32_t, false)
4503       break;
4504     }
4505     case VMULOUH: {
4506       VECTOR_MULTIPLY_EVEN_ODD(uint16_t, uint32_t, true)
4507       break;
4508     }
4509     case VMULOSH: {
4510       VECTOR_MULTIPLY_EVEN_ODD(int16_t, int32_t, true)
4511       break;
4512     }
4513     case VMULEUW: {
4514       VECTOR_MULTIPLY_EVEN_ODD(uint32_t, uint64_t, false)
4515       break;
4516     }
4517     case VMULESW: {
4518       VECTOR_MULTIPLY_EVEN_ODD(int32_t, int64_t, false)
4519       break;
4520     }
4521     case VMULOUW: {
4522       VECTOR_MULTIPLY_EVEN_ODD(uint32_t, uint64_t, true)
4523       break;
4524     }
4525     case VMULOSW: {
4526       VECTOR_MULTIPLY_EVEN_ODD(int32_t, int64_t, true)
4527       break;
4528     }
4529 #undef VECTOR_MULTIPLY_EVEN_ODD
4530 #define VECTOR_MERGE(type, is_low_side)                                    \
4531   DECODE_VX_INSTRUCTION(t, a, b, T)                                        \
4532   constexpr size_t index_limit = (kSimd128Size / sizeof(type)) / 2;        \
4533   for (size_t i = 0, source_index = is_low_side ? i + index_limit : i;     \
4534        i < index_limit; i++, source_index++) {                             \
4535     set_simd_register_by_lane<type>(                                       \
4536         t, 2 * i, get_simd_register_by_lane<type>(a, source_index));       \
4537     set_simd_register_by_lane<type>(                                       \
4538         t, (2 * i) + 1, get_simd_register_by_lane<type>(b, source_index)); \
4539   }
4540     case VMRGLW: {
4541       VECTOR_MERGE(int32_t, true)
4542       break;
4543     }
4544     case VMRGHW: {
4545       VECTOR_MERGE(int32_t, false)
4546       break;
4547     }
4548     case VMRGLH: {
4549       VECTOR_MERGE(int16_t, true)
4550       break;
4551     }
4552     case VMRGHH: {
4553       VECTOR_MERGE(int16_t, false)
4554       break;
4555     }
4556 #undef VECTOR_MERGE
4557 #undef VECTOR_ARITHMETIC_OP
4558 #define VECTOR_MIN_MAX_OP(type, op)                                        \
4559   DECODE_VX_INSTRUCTION(t, a, b, T)                                        \
4560   FOR_EACH_LANE(i, type) {                                                 \
4561     type a_val = get_simd_register_by_lane<type>(a, i);                    \
4562     type b_val = get_simd_register_by_lane<type>(b, i);                    \
4563     set_simd_register_by_lane<type>(t, i, a_val op b_val ? a_val : b_val); \
4564   }
4565     case XSMINDP: {
4566       DECODE_VX_INSTRUCTION(t, a, b, T)
4567       double a_val = get_double_from_d_register(a);
4568       double b_val = get_double_from_d_register(b);
4569       set_d_register_from_double(t, VSXFPMin<double>(a_val, b_val));
4570       break;
4571     }
4572     case XSMAXDP: {
4573       DECODE_VX_INSTRUCTION(t, a, b, T)
4574       double a_val = get_double_from_d_register(a);
4575       double b_val = get_double_from_d_register(b);
4576       set_d_register_from_double(t, VSXFPMax<double>(a_val, b_val));
4577       break;
4578     }
4579     case XVMINDP: {
4580       DECODE_VX_INSTRUCTION(t, a, b, T)
4581       FOR_EACH_LANE(i, double) {
4582         double a_val = get_simd_register_by_lane<double>(a, i);
4583         double b_val = get_simd_register_by_lane<double>(b, i);
4584         set_simd_register_by_lane<double>(t, i, VSXFPMin<double>(a_val, b_val));
4585       }
4586       break;
4587     }
4588     case XVMAXDP: {
4589       DECODE_VX_INSTRUCTION(t, a, b, T)
4590       FOR_EACH_LANE(i, double) {
4591         double a_val = get_simd_register_by_lane<double>(a, i);
4592         double b_val = get_simd_register_by_lane<double>(b, i);
4593         set_simd_register_by_lane<double>(t, i, VSXFPMax<double>(a_val, b_val));
4594       }
4595       break;
4596     }
4597     case VMINFP: {
4598       DECODE_VX_INSTRUCTION(t, a, b, T)
4599       FOR_EACH_LANE(i, float) {
4600         float a_val = get_simd_register_by_lane<float>(a, i);
4601         float b_val = get_simd_register_by_lane<float>(b, i);
4602         set_simd_register_by_lane<float>(t, i, VMXFPMin(a_val, b_val));
4603       }
4604       break;
4605     }
4606     case VMAXFP: {
4607       DECODE_VX_INSTRUCTION(t, a, b, T)
4608       FOR_EACH_LANE(i, float) {
4609         float a_val = get_simd_register_by_lane<float>(a, i);
4610         float b_val = get_simd_register_by_lane<float>(b, i);
4611         set_simd_register_by_lane<float>(t, i, VMXFPMax(a_val, b_val));
4612       }
4613       break;
4614     }
4615     case VMINSD: {
4616       VECTOR_MIN_MAX_OP(int64_t, <)
4617       break;
4618     }
4619     case VMINUD: {
4620       VECTOR_MIN_MAX_OP(uint64_t, <)
4621       break;
4622     }
4623     case VMINSW: {
4624       VECTOR_MIN_MAX_OP(int32_t, <)
4625       break;
4626     }
4627     case VMINUW: {
4628       VECTOR_MIN_MAX_OP(uint32_t, <)
4629       break;
4630     }
4631     case VMINSH: {
4632       VECTOR_MIN_MAX_OP(int16_t, <)
4633       break;
4634     }
4635     case VMINUH: {
4636       VECTOR_MIN_MAX_OP(uint16_t, <)
4637       break;
4638     }
4639     case VMINSB: {
4640       VECTOR_MIN_MAX_OP(int8_t, <)
4641       break;
4642     }
4643     case VMINUB: {
4644       VECTOR_MIN_MAX_OP(uint8_t, <)
4645       break;
4646     }
4647     case VMAXSD: {
4648       VECTOR_MIN_MAX_OP(int64_t, >)
4649       break;
4650     }
4651     case VMAXUD: {
4652       VECTOR_MIN_MAX_OP(uint64_t, >)
4653       break;
4654     }
4655     case VMAXSW: {
4656       VECTOR_MIN_MAX_OP(int32_t, >)
4657       break;
4658     }
4659     case VMAXUW: {
4660       VECTOR_MIN_MAX_OP(uint32_t, >)
4661       break;
4662     }
4663     case VMAXSH: {
4664       VECTOR_MIN_MAX_OP(int16_t, >)
4665       break;
4666     }
4667     case VMAXUH: {
4668       VECTOR_MIN_MAX_OP(uint16_t, >)
4669       break;
4670     }
4671     case VMAXSB: {
4672       VECTOR_MIN_MAX_OP(int8_t, >)
4673       break;
4674     }
4675     case VMAXUB: {
4676       VECTOR_MIN_MAX_OP(uint8_t, >)
4677       break;
4678     }
4679 #undef VECTOR_MIN_MAX_OP
4680 #define VECTOR_SHIFT_OP(type, op, mask)                        \
4681   DECODE_VX_INSTRUCTION(t, a, b, T)                            \
4682   FOR_EACH_LANE(i, type) {                                     \
4683     set_simd_register_by_lane<type>(                           \
4684         t, i,                                                  \
4685         get_simd_register_by_lane<type>(a, i)                  \
4686             op(get_simd_register_by_lane<type>(b, i) & mask)); \
4687   }
4688     case VSLD: {
4689       VECTOR_SHIFT_OP(int64_t, <<, 0x3f)
4690       break;
4691     }
4692     case VSRAD: {
4693       VECTOR_SHIFT_OP(int64_t, >>, 0x3f)
4694       break;
4695     }
4696     case VSRD: {
4697       VECTOR_SHIFT_OP(uint64_t, >>, 0x3f)
4698       break;
4699     }
4700     case VSLW: {
4701       VECTOR_SHIFT_OP(int32_t, <<, 0x1f)
4702       break;
4703     }
4704     case VSRAW: {
4705       VECTOR_SHIFT_OP(int32_t, >>, 0x1f)
4706       break;
4707     }
4708     case VSRW: {
4709       VECTOR_SHIFT_OP(uint32_t, >>, 0x1f)
4710       break;
4711     }
4712     case VSLH: {
4713       VECTOR_SHIFT_OP(int16_t, <<, 0xf)
4714       break;
4715     }
4716     case VSRAH: {
4717       VECTOR_SHIFT_OP(int16_t, >>, 0xf)
4718       break;
4719     }
4720     case VSRH: {
4721       VECTOR_SHIFT_OP(uint16_t, >>, 0xf)
4722       break;
4723     }
4724     case VSLB: {
4725       VECTOR_SHIFT_OP(int8_t, <<, 0x7)
4726       break;
4727     }
4728     case VSRAB: {
4729       VECTOR_SHIFT_OP(int8_t, >>, 0x7)
4730       break;
4731     }
4732     case VSRB: {
4733       VECTOR_SHIFT_OP(uint8_t, >>, 0x7)
4734       break;
4735     }
4736 #undef VECTOR_SHIFT_OP
4737 #define VECTOR_COMPARE_OP(type_in, type_out, is_fp, op) \
4738   VectorCompareOp<type_in, type_out>(                   \
4739       this, instr, is_fp, [](type_in a, type_in b) { return a op b; });
4740     case XVCMPEQDP: {
4741       VECTOR_COMPARE_OP(double, int64_t, true, ==)
4742       break;
4743     }
4744     case XVCMPGEDP: {
4745       VECTOR_COMPARE_OP(double, int64_t, true, >=)
4746       break;
4747     }
4748     case XVCMPGTDP: {
4749       VECTOR_COMPARE_OP(double, int64_t, true, >)
4750       break;
4751     }
4752     case XVCMPEQSP: {
4753       VECTOR_COMPARE_OP(float, int32_t, true, ==)
4754       break;
4755     }
4756     case XVCMPGESP: {
4757       VECTOR_COMPARE_OP(float, int32_t, true, >=)
4758       break;
4759     }
4760     case XVCMPGTSP: {
4761       VECTOR_COMPARE_OP(float, int32_t, true, >)
4762       break;
4763     }
4764     case VCMPEQUD: {
4765       VECTOR_COMPARE_OP(uint64_t, int64_t, false, ==)
4766       break;
4767     }
4768     case VCMPGTSD: {
4769       VECTOR_COMPARE_OP(int64_t, int64_t, false, >)
4770       break;
4771     }
4772     case VCMPGTUD: {
4773       VECTOR_COMPARE_OP(uint64_t, int64_t, false, >)
4774       break;
4775     }
4776     case VCMPEQUW: {
4777       VECTOR_COMPARE_OP(uint32_t, int32_t, false, ==)
4778       break;
4779     }
4780     case VCMPGTSW: {
4781       VECTOR_COMPARE_OP(int32_t, int32_t, false, >)
4782       break;
4783     }
4784     case VCMPGTUW: {
4785       VECTOR_COMPARE_OP(uint32_t, int32_t, false, >)
4786       break;
4787     }
4788     case VCMPEQUH: {
4789       VECTOR_COMPARE_OP(uint16_t, int16_t, false, ==)
4790       break;
4791     }
4792     case VCMPGTSH: {
4793       VECTOR_COMPARE_OP(int16_t, int16_t, false, >)
4794       break;
4795     }
4796     case VCMPGTUH: {
4797       VECTOR_COMPARE_OP(uint16_t, int16_t, false, >)
4798       break;
4799     }
4800     case VCMPEQUB: {
4801       VECTOR_COMPARE_OP(uint8_t, int8_t, false, ==)
4802       break;
4803     }
4804     case VCMPGTSB: {
4805       VECTOR_COMPARE_OP(int8_t, int8_t, false, >)
4806       break;
4807     }
4808     case VCMPGTUB: {
4809       VECTOR_COMPARE_OP(uint8_t, int8_t, false, >)
4810       break;
4811     }
4812 #undef VECTOR_COMPARE_OP
4813     case XVCVSPSXWS: {
4814       VectorConverFromFPSaturate<float, int32_t>(this, instr, kMinInt, kMaxInt);
4815       break;
4816     }
4817     case XVCVSPUXWS: {
4818       VectorConverFromFPSaturate<float, uint32_t>(this, instr, 0, kMaxUInt32);
4819       break;
4820     }
4821     case XVCVDPSXWS: {
4822       VectorConverFromFPSaturate<double, int32_t>(this, instr, kMinInt, kMaxInt,
4823                                                   true);
4824       break;
4825     }
4826     case XVCVDPUXWS: {
4827       VectorConverFromFPSaturate<double, uint32_t>(this, instr, 0, kMaxUInt32,
4828                                                    true);
4829       break;
4830     }
4831     case XVCVSXWSP: {
4832       int t = instr->RTValue();
4833       int b = instr->RBValue();
4834       FOR_EACH_LANE(i, int32_t) {
4835         int32_t b_val = get_simd_register_by_lane<int32_t>(b, i);
4836         set_simd_register_by_lane<float>(t, i, static_cast<float>(b_val));
4837       }
4838       break;
4839     }
4840     case XVCVUXWSP: {
4841       int t = instr->RTValue();
4842       int b = instr->RBValue();
4843       FOR_EACH_LANE(i, uint32_t) {
4844         uint32_t b_val = get_simd_register_by_lane<uint32_t>(b, i);
4845         set_simd_register_by_lane<float>(t, i, static_cast<float>(b_val));
4846       }
4847       break;
4848     }
4849     case XVCVSXDDP: {
4850       int t = instr->RTValue();
4851       int b = instr->RBValue();
4852       FOR_EACH_LANE(i, int64_t) {
4853         int64_t b_val = get_simd_register_by_lane<int64_t>(b, i);
4854         set_simd_register_by_lane<double>(t, i, static_cast<double>(b_val));
4855       }
4856       break;
4857     }
4858     case XVCVUXDDP: {
4859       int t = instr->RTValue();
4860       int b = instr->RBValue();
4861       FOR_EACH_LANE(i, uint64_t) {
4862         uint64_t b_val = get_simd_register_by_lane<uint64_t>(b, i);
4863         set_simd_register_by_lane<double>(t, i, static_cast<double>(b_val));
4864       }
4865       break;
4866     }
4867     case XVCVSPDP: {
4868       int t = instr->RTValue();
4869       int b = instr->RBValue();
4870       FOR_EACH_LANE(i, double) {
4871         float b_val = get_simd_register_by_lane<float>(b, 2 * i);
4872         set_simd_register_by_lane<double>(t, i, static_cast<double>(b_val));
4873       }
4874       break;
4875     }
4876     case XVCVDPSP: {
4877       int t = instr->RTValue();
4878       int b = instr->RBValue();
4879       FOR_EACH_LANE(i, double) {
4880         double b_val = get_simd_register_by_lane<double>(b, i);
4881         set_simd_register_by_lane<float>(t, 2 * i, static_cast<float>(b_val));
4882       }
4883       break;
4884     }
4885     case XSCVSPDPN: {
4886       int t = instr->RTValue();
4887       int b = instr->RBValue();
4888       uint64_t double_bits = get_d_register(b);
4889       // Value is at the high 32 bits of the register.
4890       float f =
4891           bit_cast<float, uint32_t>(static_cast<uint32_t>(double_bits >> 32));
4892       double_bits = bit_cast<uint64_t, double>(static_cast<double>(f));
4893       // Preserve snan.
4894       if (is_snan(f)) {
4895         double_bits &= 0xFFF7FFFFFFFFFFFFU;  // Clear bit 51.
4896       }
4897       set_d_register(t, double_bits);
4898       break;
4899     }
4900     case XSCVDPSPN: {
4901       int t = instr->RTValue();
4902       int b = instr->RBValue();
4903       double b_val = get_double_from_d_register(b);
4904       uint64_t float_bits = static_cast<uint64_t>(
4905           bit_cast<uint32_t, float>(static_cast<float>(b_val)));
4906       // Preserve snan.
4907       if (is_snan(b_val)) {
4908         float_bits &= 0xFFBFFFFFU;  // Clear bit 22.
4909       }
4910       // fp result is placed in both 32bit halfs of the dst.
4911       float_bits = (float_bits << 32) | float_bits;
4912       set_d_register(t, float_bits);
4913       break;
4914     }
4915 #define VECTOR_UNPACK(S, D, if_high_side)                           \
4916   int t = instr->RTValue();                                         \
4917   int b = instr->RBValue();                                         \
4918   constexpr size_t kItemCount = kSimd128Size / sizeof(D);           \
4919   D temps[kItemCount] = {0};                                        \
4920   /* Avoid overwriting src if src and dst are the same register. */ \
4921   FOR_EACH_LANE(i, D) {                                             \
4922     temps[i] = get_simd_register_by_lane<S>(b, i, if_high_side);    \
4923   }                                                                 \
4924   FOR_EACH_LANE(i, D) {                                             \
4925     set_simd_register_by_lane<D>(t, i, temps[i], if_high_side);     \
4926   }
4927     case VUPKHSB: {
4928       VECTOR_UNPACK(int8_t, int16_t, true)
4929       break;
4930     }
4931     case VUPKHSH: {
4932       VECTOR_UNPACK(int16_t, int32_t, true)
4933       break;
4934     }
4935     case VUPKHSW: {
4936       VECTOR_UNPACK(int32_t, int64_t, true)
4937       break;
4938     }
4939     case VUPKLSB: {
4940       VECTOR_UNPACK(int8_t, int16_t, false)
4941       break;
4942     }
4943     case VUPKLSH: {
4944       VECTOR_UNPACK(int16_t, int32_t, false)
4945       break;
4946     }
4947     case VUPKLSW: {
4948       VECTOR_UNPACK(int32_t, int64_t, false)
4949       break;
4950     }
4951 #undef VECTOR_UNPACK
4952     case VPKSWSS: {
4953       VectorPackSaturate<int32_t, int16_t>(this, instr, kMinInt16, kMaxInt16);
4954       break;
4955     }
4956     case VPKSWUS: {
4957       VectorPackSaturate<int32_t, uint16_t>(this, instr, 0, kMaxUInt16);
4958       break;
4959     }
4960     case VPKSHSS: {
4961       VectorPackSaturate<int16_t, int8_t>(this, instr, kMinInt8, kMaxInt8);
4962       break;
4963     }
4964     case VPKSHUS: {
4965       VectorPackSaturate<int16_t, uint8_t>(this, instr, 0, kMaxUInt8);
4966       break;
4967     }
4968 #define VECTOR_ADD_SUB_SATURATE(intermediate_type, result_type, op, min_val, \
4969                                 max_val)                                     \
4970   DECODE_VX_INSTRUCTION(t, a, b, T)                                          \
4971   FOR_EACH_LANE(i, result_type) {                                            \
4972     intermediate_type a_val = static_cast<intermediate_type>(                \
4973         get_simd_register_by_lane<result_type>(a, i));                       \
4974     intermediate_type b_val = static_cast<intermediate_type>(                \
4975         get_simd_register_by_lane<result_type>(b, i));                       \
4976     intermediate_type t_val = a_val op b_val;                                \
4977     if (t_val > max_val)                                                     \
4978       t_val = max_val;                                                       \
4979     else if (t_val < min_val)                                                \
4980       t_val = min_val;                                                       \
4981     set_simd_register_by_lane<result_type>(t, i,                             \
4982                                            static_cast<result_type>(t_val)); \
4983   }
4984     case VADDSHS: {
4985       VECTOR_ADD_SUB_SATURATE(int32_t, int16_t, +, kMinInt16, kMaxInt16)
4986       break;
4987     }
4988     case VSUBSHS: {
4989       VECTOR_ADD_SUB_SATURATE(int32_t, int16_t, -, kMinInt16, kMaxInt16)
4990       break;
4991     }
4992     case VADDUHS: {
4993       VECTOR_ADD_SUB_SATURATE(int32_t, uint16_t, +, 0, kMaxUInt16)
4994       break;
4995     }
4996     case VSUBUHS: {
4997       VECTOR_ADD_SUB_SATURATE(int32_t, uint16_t, -, 0, kMaxUInt16)
4998       break;
4999     }
5000     case VADDSBS: {
5001       VECTOR_ADD_SUB_SATURATE(int16_t, int8_t, +, kMinInt8, kMaxInt8)
5002       break;
5003     }
5004     case VSUBSBS: {
5005       VECTOR_ADD_SUB_SATURATE(int16_t, int8_t, -, kMinInt8, kMaxInt8)
5006       break;
5007     }
5008     case VADDUBS: {
5009       VECTOR_ADD_SUB_SATURATE(int16_t, uint8_t, +, 0, kMaxUInt8)
5010       break;
5011     }
5012     case VSUBUBS: {
5013       VECTOR_ADD_SUB_SATURATE(int16_t, uint8_t, -, 0, kMaxUInt8)
5014       break;
5015     }
5016 #undef VECTOR_ADD_SUB_SATURATE
5017 #define VECTOR_FP_ROUNDING(type, op)                       \
5018   int t = instr->RTValue();                                \
5019   int b = instr->RBValue();                                \
5020   FOR_EACH_LANE(i, type) {                                 \
5021     type b_val = get_simd_register_by_lane<type>(b, i);    \
5022     set_simd_register_by_lane<type>(t, i, std::op(b_val)); \
5023   }
5024     case XVRDPIP: {
5025       VECTOR_FP_ROUNDING(double, ceil)
5026       break;
5027     }
5028     case XVRDPIM: {
5029       VECTOR_FP_ROUNDING(double, floor)
5030       break;
5031     }
5032     case XVRDPIZ: {
5033       VECTOR_FP_ROUNDING(double, trunc)
5034       break;
5035     }
5036     case XVRDPI: {
5037       VECTOR_FP_ROUNDING(double, nearbyint)
5038       break;
5039     }
5040     case XVRSPIP: {
5041       VECTOR_FP_ROUNDING(float, ceilf)
5042       break;
5043     }
5044     case XVRSPIM: {
5045       VECTOR_FP_ROUNDING(float, floorf)
5046       break;
5047     }
5048     case XVRSPIZ: {
5049       VECTOR_FP_ROUNDING(float, truncf)
5050       break;
5051     }
5052     case XVRSPI: {
5053       VECTOR_FP_ROUNDING(float, nearbyintf)
5054       break;
5055     }
5056 #undef VECTOR_FP_ROUNDING
5057     case VSEL: {
5058       int vrt = instr->RTValue();
5059       int vra = instr->RAValue();
5060       int vrb = instr->RBValue();
5061       int vrc = instr->RCValue();
5062       unsigned __int128 src_1 = bit_cast<__int128>(get_simd_register(vra).int8);
5063       unsigned __int128 src_2 = bit_cast<__int128>(get_simd_register(vrb).int8);
5064       unsigned __int128 src_3 = bit_cast<__int128>(get_simd_register(vrc).int8);
5065       unsigned __int128 tmp = (src_1 & ~src_3) | (src_2 & src_3);
5066       simdr_t* result = bit_cast<simdr_t*>(&tmp);
5067       set_simd_register(vrt, *result);
5068       break;
5069     }
5070     case VPERM: {
5071       int vrt = instr->RTValue();
5072       int vra = instr->RAValue();
5073       int vrb = instr->RBValue();
5074       int vrc = instr->RCValue();
5075       int8_t temp[kSimd128Size] = {0};
5076       FOR_EACH_LANE(i, int8_t) {
5077         int8_t lane_num = get_simd_register_by_lane<int8_t>(vrc, i);
5078         // Get the five least significant bits.
5079         lane_num = (lane_num << 3) >> 3;
5080         int reg = vra;
5081         if (lane_num >= kSimd128Size) {
5082           lane_num = lane_num - kSimd128Size;
5083           reg = vrb;
5084         }
5085         temp[i] = get_simd_register_by_lane<int8_t>(reg, lane_num);
5086       }
5087       FOR_EACH_LANE(i, int8_t) {
5088         set_simd_register_by_lane<int8_t>(vrt, i, temp[i]);
5089       }
5090       break;
5091     }
5092     case VBPERMQ: {
5093       DECODE_VX_INSTRUCTION(t, a, b, T)
5094       uint16_t result_bits = 0;
5095       unsigned __int128 src_bits =
5096           bit_cast<__int128>(get_simd_register(a).int8);
5097       for (int i = 0; i < kSimd128Size; i++) {
5098         result_bits <<= 1;
5099         uint8_t selected_bit_index = get_simd_register_by_lane<uint8_t>(b, i);
5100         if (selected_bit_index < (kSimd128Size * kBitsPerByte)) {
5101           unsigned __int128 bit_value = (src_bits << selected_bit_index) >>
5102                                         (kSimd128Size * kBitsPerByte - 1);
5103           result_bits |= bit_value;
5104         }
5105       }
5106       set_simd_register_by_lane<uint64_t>(t, 0, 0);
5107       set_simd_register_by_lane<uint64_t>(t, 1, 0);
5108       set_simd_register_by_lane<uint16_t>(t, 3, result_bits);
5109       break;
5110     }
5111 #define VECTOR_FP_QF(type, sign)                             \
5112   DECODE_VX_INSTRUCTION(t, a, b, T)                          \
5113   FOR_EACH_LANE(i, type) {                                   \
5114     type a_val = get_simd_register_by_lane<type>(a, i);      \
5115     type b_val = get_simd_register_by_lane<type>(b, i);      \
5116     type t_val = get_simd_register_by_lane<type>(t, i);      \
5117     type reuslt = sign * ((sign * b_val) + (a_val * t_val)); \
5118     if (isinf(a_val)) reuslt = a_val;                        \
5119     if (isinf(b_val)) reuslt = b_val;                        \
5120     if (isinf(t_val)) reuslt = t_val;                        \
5121     set_simd_register_by_lane<type>(t, i, reuslt);           \
5122   }
5123     case XVMADDMDP: {
5124       VECTOR_FP_QF(double, +1)
5125       break;
5126     }
5127     case XVNMSUBMDP: {
5128       VECTOR_FP_QF(double, -1)
5129       break;
5130     }
5131     case XVMADDMSP: {
5132       VECTOR_FP_QF(float, +1)
5133       break;
5134     }
5135     case XVNMSUBMSP: {
5136       VECTOR_FP_QF(float, -1)
5137       break;
5138     }
5139 #undef VECTOR_FP_QF
5140     case VMHRADDSHS: {
5141       int vrt = instr->RTValue();
5142       int vra = instr->RAValue();
5143       int vrb = instr->RBValue();
5144       int vrc = instr->RCValue();
5145       FOR_EACH_LANE(i, int16_t) {
5146         int16_t vra_val = get_simd_register_by_lane<int16_t>(vra, i);
5147         int16_t vrb_val = get_simd_register_by_lane<int16_t>(vrb, i);
5148         int16_t vrc_val = get_simd_register_by_lane<int16_t>(vrc, i);
5149         int32_t temp = vra_val * vrb_val;
5150         temp = (temp + 0x00004000) >> 15;
5151         temp += vrc_val;
5152         if (temp > kMaxInt16)
5153           temp = kMaxInt16;
5154         else if (temp < kMinInt16)
5155           temp = kMinInt16;
5156         set_simd_register_by_lane<int16_t>(vrt, i, static_cast<int16_t>(temp));
5157       }
5158       break;
5159     }
5160     case VMSUMSHM: {
5161       int vrt = instr->RTValue();
5162       int vra = instr->RAValue();
5163       int vrb = instr->RBValue();
5164       int vrc = instr->RCValue();
5165       FOR_EACH_LANE(i, int32_t) {
5166         int16_t vra_1_val = get_simd_register_by_lane<int16_t>(vra, 2 * i);
5167         int16_t vra_2_val =
5168             get_simd_register_by_lane<int16_t>(vra, (2 * i) + 1);
5169         int16_t vrb_1_val = get_simd_register_by_lane<int16_t>(vrb, 2 * i);
5170         int16_t vrb_2_val =
5171             get_simd_register_by_lane<int16_t>(vrb, (2 * i) + 1);
5172         int32_t vrc_val = get_simd_register_by_lane<int32_t>(vrc, i);
5173         int32_t temp1 = vra_1_val * vrb_1_val, temp2 = vra_2_val * vrb_2_val;
5174         temp1 = temp1 + temp2 + vrc_val;
5175         set_simd_register_by_lane<int32_t>(vrt, i, temp1);
5176       }
5177       break;
5178     }
5179     case VMLADDUHM: {
5180       int vrt = instr->RTValue();
5181       int vra = instr->RAValue();
5182       int vrb = instr->RBValue();
5183       int vrc = instr->RCValue();
5184       FOR_EACH_LANE(i, uint16_t) {
5185         uint16_t vra_val = get_simd_register_by_lane<uint16_t>(vra, i);
5186         uint16_t vrb_val = get_simd_register_by_lane<uint16_t>(vrb, i);
5187         uint16_t vrc_val = get_simd_register_by_lane<uint16_t>(vrc, i);
5188         set_simd_register_by_lane<uint16_t>(vrt, i,
5189                                             (vra_val * vrb_val) + vrc_val);
5190       }
5191       break;
5192     }
5193 #define VECTOR_UNARY_OP(type, op)                         \
5194   int t = instr->RTValue();                               \
5195   int b = instr->RBValue();                               \
5196   FOR_EACH_LANE(i, type) {                                \
5197     set_simd_register_by_lane<type>(                      \
5198         t, i, op(get_simd_register_by_lane<type>(b, i))); \
5199   }
5200     case XVABSDP: {
5201       VECTOR_UNARY_OP(double, std::abs)
5202       break;
5203     }
5204     case XVNEGDP: {
5205       VECTOR_UNARY_OP(double, -)
5206       break;
5207     }
5208     case XVSQRTDP: {
5209       VECTOR_UNARY_OP(double, std::sqrt)
5210       break;
5211     }
5212     case XVABSSP: {
5213       VECTOR_UNARY_OP(float, std::abs)
5214       break;
5215     }
5216     case XVNEGSP: {
5217       VECTOR_UNARY_OP(float, -)
5218       break;
5219     }
5220     case XVSQRTSP: {
5221       VECTOR_UNARY_OP(float, std::sqrt)
5222       break;
5223     }
5224     case XVRESP: {
5225       VECTOR_UNARY_OP(float, base::Recip)
5226       break;
5227     }
5228     case XVRSQRTESP: {
5229       VECTOR_UNARY_OP(float, base::RecipSqrt)
5230       break;
5231     }
5232     case VNEGW: {
5233       VECTOR_UNARY_OP(int32_t, -)
5234       break;
5235     }
5236     case VNEGD: {
5237       VECTOR_UNARY_OP(int64_t, -)
5238       break;
5239     }
5240 #undef VECTOR_UNARY_OP
5241 #define VECTOR_ROUNDING_AVERAGE(intermediate_type, result_type)              \
5242   DECODE_VX_INSTRUCTION(t, a, b, T)                                          \
5243   FOR_EACH_LANE(i, result_type) {                                            \
5244     intermediate_type a_val = static_cast<intermediate_type>(                \
5245         get_simd_register_by_lane<result_type>(a, i));                       \
5246     intermediate_type b_val = static_cast<intermediate_type>(                \
5247         get_simd_register_by_lane<result_type>(b, i));                       \
5248     intermediate_type t_val = ((a_val + b_val) + 1) >> 1;                    \
5249     set_simd_register_by_lane<result_type>(t, i,                             \
5250                                            static_cast<result_type>(t_val)); \
5251   }
5252     case VAVGUH: {
5253       VECTOR_ROUNDING_AVERAGE(uint32_t, uint16_t)
5254       break;
5255     }
5256     case VAVGUB: {
5257       VECTOR_ROUNDING_AVERAGE(uint16_t, uint8_t)
5258       break;
5259     }
5260 #undef VECTOR_ROUNDING_AVERAGE
5261     case VPOPCNTB: {
5262       int t = instr->RTValue();
5263       int b = instr->RBValue();
5264       FOR_EACH_LANE(i, uint8_t) {
5265         set_simd_register_by_lane<uint8_t>(
5266             t, i,
5267             base::bits::CountPopulation(
5268                 get_simd_register_by_lane<uint8_t>(b, i)));
5269       }
5270       break;
5271     }
5272 #define EXTRACT_MASK(type)                                           \
5273   int rt = instr->RTValue();                                         \
5274   int vrb = instr->RBValue();                                        \
5275   uint64_t result = 0;                                               \
5276   FOR_EACH_LANE(i, type) {                                           \
5277     if (i > 0) result <<= 1;                                         \
5278     result |= std::signbit(get_simd_register_by_lane<type>(vrb, i)); \
5279   }                                                                  \
5280   set_register(rt, result);
5281     case VEXTRACTDM: {
5282       EXTRACT_MASK(int64_t)
5283       break;
5284     }
5285     case VEXTRACTWM: {
5286       EXTRACT_MASK(int32_t)
5287       break;
5288     }
5289     case VEXTRACTHM: {
5290       EXTRACT_MASK(int16_t)
5291       break;
5292     }
5293     case VEXTRACTBM: {
5294       EXTRACT_MASK(int8_t)
5295       break;
5296     }
5297 #undef EXTRACT_MASK
5298 #undef FOR_EACH_LANE
5299 #undef DECODE_VX_INSTRUCTION
5300 #undef GET_ADDRESS
5301     default: {
5302       UNIMPLEMENTED();
5303     }
5304   }
5305 }
5306 
Trace(Instruction * instr)5307 void Simulator::Trace(Instruction* instr) {
5308   disasm::NameConverter converter;
5309   disasm::Disassembler dasm(converter);
5310   // use a reasonably large buffer
5311   v8::base::EmbeddedVector<char, 256> buffer;
5312   dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
5313   PrintF("%05d  %08" V8PRIxPTR "  %s\n", icount_,
5314          reinterpret_cast<intptr_t>(instr), buffer.begin());
5315 }
5316 
5317 // Executes the current instruction.
ExecuteInstruction(Instruction * instr)5318 void Simulator::ExecuteInstruction(Instruction* instr) {
5319   if (v8::internal::FLAG_check_icache) {
5320     CheckICache(i_cache(), instr);
5321   }
5322   pc_modified_ = false;
5323   if (::v8::internal::FLAG_trace_sim) {
5324     Trace(instr);
5325   }
5326   uint32_t opcode = instr->OpcodeField();
5327   if (opcode == TWI) {
5328     SoftwareInterrupt(instr);
5329   } else {
5330     ExecuteGeneric(instr);
5331   }
5332   if (!pc_modified_) {
5333     set_pc(reinterpret_cast<intptr_t>(instr) + kInstrSize);
5334   }
5335 }
5336 
Execute()5337 void Simulator::Execute() {
5338   // Get the PC to simulate. Cannot use the accessor here as we need the
5339   // raw PC value and not the one used as input to arithmetic instructions.
5340   intptr_t program_counter = get_pc();
5341 
5342   if (::v8::internal::FLAG_stop_sim_at == 0) {
5343     // Fast version of the dispatch loop without checking whether the simulator
5344     // should be stopping at a particular executed instruction.
5345     while (program_counter != end_sim_pc) {
5346       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5347       icount_++;
5348       ExecuteInstruction(instr);
5349       program_counter = get_pc();
5350     }
5351   } else {
5352     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
5353     // we reach the particular instruction count.
5354     while (program_counter != end_sim_pc) {
5355       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5356       icount_++;
5357       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
5358         PPCDebugger dbg(this);
5359         dbg.Debug();
5360       } else {
5361         ExecuteInstruction(instr);
5362       }
5363       program_counter = get_pc();
5364     }
5365   }
5366 }
5367 
CallInternal(Address entry)5368 void Simulator::CallInternal(Address entry) {
5369   // Adjust JS-based stack limit to C-based stack limit.
5370   isolate_->stack_guard()->AdjustStackLimitForSimulator();
5371 
5372   // Prepare to execute the code at entry
5373   if (ABI_USES_FUNCTION_DESCRIPTORS) {
5374     // entry is the function descriptor
5375     set_pc(*(bit_cast<intptr_t*>(entry)));
5376   } else {
5377     // entry is the instruction address
5378     set_pc(static_cast<intptr_t>(entry));
5379   }
5380 
5381   if (ABI_CALL_VIA_IP) {
5382     // Put target address in ip (for JS prologue).
5383     set_register(r12, get_pc());
5384   }
5385 
5386   // Put down marker for end of simulation. The simulator will stop simulation
5387   // when the PC reaches this value. By saving the "end simulation" value into
5388   // the LR the simulation stops when returning to this call point.
5389   special_reg_lr_ = end_sim_pc;
5390 
5391   // Remember the values of non-volatile registers.
5392   intptr_t r2_val = get_register(r2);
5393   intptr_t r13_val = get_register(r13);
5394   intptr_t r14_val = get_register(r14);
5395   intptr_t r15_val = get_register(r15);
5396   intptr_t r16_val = get_register(r16);
5397   intptr_t r17_val = get_register(r17);
5398   intptr_t r18_val = get_register(r18);
5399   intptr_t r19_val = get_register(r19);
5400   intptr_t r20_val = get_register(r20);
5401   intptr_t r21_val = get_register(r21);
5402   intptr_t r22_val = get_register(r22);
5403   intptr_t r23_val = get_register(r23);
5404   intptr_t r24_val = get_register(r24);
5405   intptr_t r25_val = get_register(r25);
5406   intptr_t r26_val = get_register(r26);
5407   intptr_t r27_val = get_register(r27);
5408   intptr_t r28_val = get_register(r28);
5409   intptr_t r29_val = get_register(r29);
5410   intptr_t r30_val = get_register(r30);
5411   intptr_t r31_val = get_register(fp);
5412 
5413   // Set up the non-volatile registers with a known value. To be able to check
5414   // that they are preserved properly across JS execution.
5415   intptr_t callee_saved_value = icount_;
5416   set_register(r2, callee_saved_value);
5417   set_register(r13, callee_saved_value);
5418   set_register(r14, callee_saved_value);
5419   set_register(r15, callee_saved_value);
5420   set_register(r16, callee_saved_value);
5421   set_register(r17, callee_saved_value);
5422   set_register(r18, callee_saved_value);
5423   set_register(r19, callee_saved_value);
5424   set_register(r20, callee_saved_value);
5425   set_register(r21, callee_saved_value);
5426   set_register(r22, callee_saved_value);
5427   set_register(r23, callee_saved_value);
5428   set_register(r24, callee_saved_value);
5429   set_register(r25, callee_saved_value);
5430   set_register(r26, callee_saved_value);
5431   set_register(r27, callee_saved_value);
5432   set_register(r28, callee_saved_value);
5433   set_register(r29, callee_saved_value);
5434   set_register(r30, callee_saved_value);
5435   set_register(fp, callee_saved_value);
5436 
5437   // Start the simulation
5438   Execute();
5439 
5440   // Check that the non-volatile registers have been preserved.
5441   if (ABI_TOC_REGISTER != 2) {
5442     CHECK_EQ(callee_saved_value, get_register(r2));
5443   }
5444   if (ABI_TOC_REGISTER != 13) {
5445     CHECK_EQ(callee_saved_value, get_register(r13));
5446   }
5447   CHECK_EQ(callee_saved_value, get_register(r14));
5448   CHECK_EQ(callee_saved_value, get_register(r15));
5449   CHECK_EQ(callee_saved_value, get_register(r16));
5450   CHECK_EQ(callee_saved_value, get_register(r17));
5451   CHECK_EQ(callee_saved_value, get_register(r18));
5452   CHECK_EQ(callee_saved_value, get_register(r19));
5453   CHECK_EQ(callee_saved_value, get_register(r20));
5454   CHECK_EQ(callee_saved_value, get_register(r21));
5455   CHECK_EQ(callee_saved_value, get_register(r22));
5456   CHECK_EQ(callee_saved_value, get_register(r23));
5457   CHECK_EQ(callee_saved_value, get_register(r24));
5458   CHECK_EQ(callee_saved_value, get_register(r25));
5459   CHECK_EQ(callee_saved_value, get_register(r26));
5460   CHECK_EQ(callee_saved_value, get_register(r27));
5461   CHECK_EQ(callee_saved_value, get_register(r28));
5462   CHECK_EQ(callee_saved_value, get_register(r29));
5463   CHECK_EQ(callee_saved_value, get_register(r30));
5464   CHECK_EQ(callee_saved_value, get_register(fp));
5465 
5466   // Restore non-volatile registers with the original value.
5467   set_register(r2, r2_val);
5468   set_register(r13, r13_val);
5469   set_register(r14, r14_val);
5470   set_register(r15, r15_val);
5471   set_register(r16, r16_val);
5472   set_register(r17, r17_val);
5473   set_register(r18, r18_val);
5474   set_register(r19, r19_val);
5475   set_register(r20, r20_val);
5476   set_register(r21, r21_val);
5477   set_register(r22, r22_val);
5478   set_register(r23, r23_val);
5479   set_register(r24, r24_val);
5480   set_register(r25, r25_val);
5481   set_register(r26, r26_val);
5482   set_register(r27, r27_val);
5483   set_register(r28, r28_val);
5484   set_register(r29, r29_val);
5485   set_register(r30, r30_val);
5486   set_register(fp, r31_val);
5487 }
5488 
CallImpl(Address entry,int argument_count,const intptr_t * arguments)5489 intptr_t Simulator::CallImpl(Address entry, int argument_count,
5490                              const intptr_t* arguments) {
5491   // Set up arguments
5492 
5493   // First eight arguments passed in registers r3-r10.
5494   int reg_arg_count = std::min(8, argument_count);
5495   int stack_arg_count = argument_count - reg_arg_count;
5496   for (int i = 0; i < reg_arg_count; i++) {
5497     set_register(i + 3, arguments[i]);
5498   }
5499 
5500   // Remaining arguments passed on stack.
5501   intptr_t original_stack = get_register(sp);
5502   // Compute position of stack on entry to generated code.
5503   intptr_t entry_stack =
5504       (original_stack -
5505        (kNumRequiredStackFrameSlots + stack_arg_count) * sizeof(intptr_t));
5506   if (base::OS::ActivationFrameAlignment() != 0) {
5507     entry_stack &= -base::OS::ActivationFrameAlignment();
5508   }
5509   // Store remaining arguments on stack, from low to high memory.
5510   // +2 is a hack for the LR slot + old SP on PPC
5511   intptr_t* stack_argument =
5512       reinterpret_cast<intptr_t*>(entry_stack) + kStackFrameExtraParamSlot;
5513   memcpy(stack_argument, arguments + reg_arg_count,
5514          stack_arg_count * sizeof(*arguments));
5515   set_register(sp, entry_stack);
5516 
5517   CallInternal(entry);
5518 
5519   // Pop stack passed arguments.
5520   CHECK_EQ(entry_stack, get_register(sp));
5521   set_register(sp, original_stack);
5522 
5523   return get_register(r3);
5524 }
5525 
CallFP(Address entry,double d0,double d1)5526 void Simulator::CallFP(Address entry, double d0, double d1) {
5527   set_d_register_from_double(1, d0);
5528   set_d_register_from_double(2, d1);
5529   CallInternal(entry);
5530 }
5531 
CallFPReturnsInt(Address entry,double d0,double d1)5532 int32_t Simulator::CallFPReturnsInt(Address entry, double d0, double d1) {
5533   CallFP(entry, d0, d1);
5534   int32_t result = get_register(r3);
5535   return result;
5536 }
5537 
CallFPReturnsDouble(Address entry,double d0,double d1)5538 double Simulator::CallFPReturnsDouble(Address entry, double d0, double d1) {
5539   CallFP(entry, d0, d1);
5540   return get_double_from_d_register(1);
5541 }
5542 
PushAddress(uintptr_t address)5543 uintptr_t Simulator::PushAddress(uintptr_t address) {
5544   uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t);
5545   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
5546   *stack_slot = address;
5547   set_register(sp, new_sp);
5548   return new_sp;
5549 }
5550 
PopAddress()5551 uintptr_t Simulator::PopAddress() {
5552   uintptr_t current_sp = get_register(sp);
5553   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
5554   uintptr_t address = *stack_slot;
5555   set_register(sp, current_sp + sizeof(uintptr_t));
5556   return address;
5557 }
5558 
Clear()5559 void Simulator::GlobalMonitor::Clear() {
5560   access_state_ = MonitorAccess::Open;
5561   tagged_addr_ = 0;
5562   size_ = TransactionSize::None;
5563   thread_id_ = ThreadId::Invalid();
5564 }
5565 
NotifyLoadExcl(uintptr_t addr,TransactionSize size,ThreadId thread_id)5566 void Simulator::GlobalMonitor::NotifyLoadExcl(uintptr_t addr,
5567                                               TransactionSize size,
5568                                               ThreadId thread_id) {
5569   // TODO(s390): By using Global Monitors, we are effectively limiting one
5570   // active reservation across all processors. This would potentially serialize
5571   // parallel threads executing load&reserve + store conditional on unrelated
5572   // memory. Technically, this implementation would still make the simulator
5573   // adhere to the spec, but seems overly heavy-handed.
5574   access_state_ = MonitorAccess::Exclusive;
5575   tagged_addr_ = addr;
5576   size_ = size;
5577   thread_id_ = thread_id;
5578 }
5579 
NotifyStore(uintptr_t addr,TransactionSize size,ThreadId thread_id)5580 void Simulator::GlobalMonitor::NotifyStore(uintptr_t addr, TransactionSize size,
5581                                            ThreadId thread_id) {
5582   if (access_state_ == MonitorAccess::Exclusive) {
5583     // Calculate if the transaction has been overlapped
5584     uintptr_t transaction_start = addr;
5585     uintptr_t transaction_end = addr + static_cast<uintptr_t>(size);
5586     uintptr_t exclusive_transaction_start = tagged_addr_;
5587     uintptr_t exclusive_transaction_end =
5588         tagged_addr_ + static_cast<uintptr_t>(size_);
5589     bool is_not_overlapped = transaction_end < exclusive_transaction_start ||
5590                              exclusive_transaction_end < transaction_start;
5591     if (!is_not_overlapped && thread_id_ != thread_id) {
5592       Clear();
5593     }
5594   }
5595 }
5596 
NotifyStoreExcl(uintptr_t addr,TransactionSize size,ThreadId thread_id)5597 bool Simulator::GlobalMonitor::NotifyStoreExcl(uintptr_t addr,
5598                                                TransactionSize size,
5599                                                ThreadId thread_id) {
5600   bool permission = access_state_ == MonitorAccess::Exclusive &&
5601                     addr == tagged_addr_ && size_ == size &&
5602                     thread_id_ == thread_id;
5603   // The reservation is cleared if the processor holding the reservation
5604   // executes a store conditional instruction to any address.
5605   Clear();
5606   return permission;
5607 }
5608 
5609 }  // namespace internal
5610 }  // namespace v8
5611 
5612 #undef SScanF
5613 #endif  // USE_SIMULATOR
5614