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