V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
simulator-mips64.cc
1 // Copyright 2011 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 <limits.h>
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <cmath>
9 
10 #if V8_TARGET_ARCH_MIPS64
11 
12 #include "src/assembler-inl.h"
13 #include "src/base/bits.h"
14 #include "src/codegen.h"
15 #include "src/disasm.h"
16 #include "src/macro-assembler.h"
17 #include "src/mips64/constants-mips64.h"
18 #include "src/mips64/simulator-mips64.h"
19 #include "src/ostreams.h"
20 #include "src/runtime/runtime-utils.h"
21 
22 // Only build the simulator if not compiling for real MIPS hardware.
23 #if defined(USE_SIMULATOR)
24 
25 namespace v8 {
26 namespace internal {
27 
28 // Util functions.
29 inline bool HaveSameSign(int64_t a, int64_t b) { return ((a ^ b) >= 0); }
30 
31 uint32_t get_fcsr_condition_bit(uint32_t cc) {
32  if (cc == 0) {
33  return 23;
34  } else {
35  return 24 + cc;
36  }
37 }
38 
39 
40 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
41  uint64_t u0, v0, w0;
42  int64_t u1, v1, w1, w2, t;
43 
44  u0 = u & 0xFFFFFFFFL;
45  u1 = u >> 32;
46  v0 = v & 0xFFFFFFFFL;
47  v1 = v >> 32;
48 
49  w0 = u0 * v0;
50  t = u1 * v0 + (w0 >> 32);
51  w1 = t & 0xFFFFFFFFL;
52  w2 = t >> 32;
53  w1 = u0 * v1 + w1;
54 
55  return u1 * v1 + w2 + (w1 >> 32);
56 }
57 
58 
59 // This macro provides a platform independent use of sscanf. The reason for
60 // SScanF not being implemented in a platform independent was through
61 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
62 // Library does not provide vsscanf.
63 #define SScanF sscanf // NOLINT
64 
65 // The MipsDebugger class is used by the simulator while debugging simulated
66 // code.
67 class MipsDebugger {
68  public:
69  explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
70 
71  void Stop(Instruction* instr);
72  void Debug();
73  // Print all registers with a nice formatting.
74  void PrintAllRegs();
75  void PrintAllRegsIncludingFPU();
76 
77  private:
78  // We set the breakpoint code to 0xFFFFF to easily recognize it.
79  static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xFFFFF << 6;
80  static const Instr kNopInstr = 0x0;
81 
82  Simulator* sim_;
83 
84  int64_t GetRegisterValue(int regnum);
85  int64_t GetFPURegisterValue(int regnum);
86  float GetFPURegisterValueFloat(int regnum);
87  double GetFPURegisterValueDouble(int regnum);
88  bool GetValue(const char* desc, int64_t* value);
89 
90  // Set or delete a breakpoint. Returns true if successful.
91  bool SetBreakpoint(Instruction* breakpc);
92  bool DeleteBreakpoint(Instruction* breakpc);
93 
94  // Undo and redo all breakpoints. This is needed to bracket disassembly and
95  // execution to skip past breakpoints when run from the debugger.
96  void UndoBreakpoints();
97  void RedoBreakpoints();
98 };
99 
100 inline void UNSUPPORTED() { printf("Sim: Unsupported instruction.\n"); }
101 
102 void MipsDebugger::Stop(Instruction* instr) {
103  // Get the stop code.
104  uint32_t code = instr->Bits(25, 6);
105  PrintF("Simulator hit (%u)\n", code);
106  Debug();
107 }
108 
109 int64_t MipsDebugger::GetRegisterValue(int regnum) {
110  if (regnum == kNumSimuRegisters) {
111  return sim_->get_pc();
112  } else {
113  return sim_->get_register(regnum);
114  }
115 }
116 
117 
118 int64_t MipsDebugger::GetFPURegisterValue(int regnum) {
119  if (regnum == kNumFPURegisters) {
120  return sim_->get_pc();
121  } else {
122  return sim_->get_fpu_register(regnum);
123  }
124 }
125 
126 
127 float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
128  if (regnum == kNumFPURegisters) {
129  return sim_->get_pc();
130  } else {
131  return sim_->get_fpu_register_float(regnum);
132  }
133 }
134 
135 
136 double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
137  if (regnum == kNumFPURegisters) {
138  return sim_->get_pc();
139  } else {
140  return sim_->get_fpu_register_double(regnum);
141  }
142 }
143 
144 
145 bool MipsDebugger::GetValue(const char* desc, int64_t* value) {
146  int regnum = Registers::Number(desc);
147  int fpuregnum = FPURegisters::Number(desc);
148 
149  if (regnum != kInvalidRegister) {
150  *value = GetRegisterValue(regnum);
151  return true;
152  } else if (fpuregnum != kInvalidFPURegister) {
153  *value = GetFPURegisterValue(fpuregnum);
154  return true;
155  } else if (strncmp(desc, "0x", 2) == 0) {
156  return SScanF(desc + 2, "%" SCNx64,
157  reinterpret_cast<uint64_t*>(value)) == 1;
158  } else {
159  return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
160  }
161  return false;
162 }
163 
164 
165 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
166  // Check if a breakpoint can be set. If not return without any side-effects.
167  if (sim_->break_pc_ != nullptr) {
168  return false;
169  }
170 
171  // Set the breakpoint.
172  sim_->break_pc_ = breakpc;
173  sim_->break_instr_ = breakpc->InstructionBits();
174  // Not setting the breakpoint instruction in the code itself. It will be set
175  // when the debugger shell continues.
176  return true;
177 }
178 
179 
180 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
181  if (sim_->break_pc_ != nullptr) {
182  sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
183  }
184 
185  sim_->break_pc_ = nullptr;
186  sim_->break_instr_ = 0;
187  return true;
188 }
189 
190 
191 void MipsDebugger::UndoBreakpoints() {
192  if (sim_->break_pc_ != nullptr) {
193  sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
194  }
195 }
196 
197 
198 void MipsDebugger::RedoBreakpoints() {
199  if (sim_->break_pc_ != nullptr) {
200  sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
201  }
202 }
203 
204 
205 void MipsDebugger::PrintAllRegs() {
206 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
207 
208  PrintF("\n");
209  // at, v0, a0.
210  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 "\t%3s: 0x%016" PRIx64 " %14" PRId64
211  "\t%3s: 0x%016" PRIx64 " %14" PRId64 "\n",
212  REG_INFO(1), REG_INFO(2), REG_INFO(4));
213  // v1, a1.
214  PrintF("%34s\t%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64
215  " %14" PRId64 " \n",
216  "", REG_INFO(3), REG_INFO(5));
217  // a2.
218  PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", "", "",
219  REG_INFO(6));
220  // a3.
221  PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 " %14" PRId64 " \n", "", "",
222  REG_INFO(7));
223  PrintF("\n");
224  // a4-t3, s0-s7
225  for (int i = 0; i < 8; i++) {
226  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64
227  " %14" PRId64 " \n",
228  REG_INFO(8 + i), REG_INFO(16 + i));
229  }
230  PrintF("\n");
231  // t8, k0, LO.
232  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64
233  " %14" PRId64 " \t%3s: 0x%016" PRIx64 " %14" PRId64 " \n",
234  REG_INFO(24), REG_INFO(26), REG_INFO(32));
235  // t9, k1, HI.
236  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64
237  " %14" PRId64 " \t%3s: 0x%016" PRIx64 " %14" PRId64 " \n",
238  REG_INFO(25), REG_INFO(27), REG_INFO(33));
239  // sp, fp, gp.
240  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64
241  " %14" PRId64 " \t%3s: 0x%016" PRIx64 " %14" PRId64 " \n",
242  REG_INFO(29), REG_INFO(30), REG_INFO(28));
243  // pc.
244  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 " \t%3s: 0x%016" PRIx64
245  " %14" PRId64 " \n",
246  REG_INFO(31), REG_INFO(34));
247 
248 #undef REG_INFO
249 #undef FPU_REG_INFO
250 }
251 
252 
253 void MipsDebugger::PrintAllRegsIncludingFPU() {
254 #define FPU_REG_INFO(n) FPURegisters::Name(n), \
255  GetFPURegisterValue(n), \
256  GetFPURegisterValueDouble(n)
257 
258  PrintAllRegs();
259 
260  PrintF("\n\n");
261  // f0, f1, f2, ... f31.
262  // TODO(plind): consider printing 2 columns for space efficiency.
263  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(0));
264  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(1));
265  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(2));
266  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(3));
267  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(4));
268  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(5));
269  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(6));
270  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(7));
271  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(8));
272  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(9));
273  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(10));
274  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(11));
275  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(12));
276  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(13));
277  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(14));
278  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(15));
279  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(16));
280  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(17));
281  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(18));
282  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(19));
283  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(20));
284  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(21));
285  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(22));
286  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(23));
287  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(24));
288  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(25));
289  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(26));
290  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(27));
291  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(28));
292  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(29));
293  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(30));
294  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n", FPU_REG_INFO(31));
295 
296 #undef REG_INFO
297 #undef FPU_REG_INFO
298 }
299 
300 
301 void MipsDebugger::Debug() {
302  intptr_t last_pc = -1;
303  bool done = false;
304 
305 #define COMMAND_SIZE 63
306 #define ARG_SIZE 255
307 
308 #define STR(a) #a
309 #define XSTR(a) STR(a)
310 
311  char cmd[COMMAND_SIZE + 1];
312  char arg1[ARG_SIZE + 1];
313  char arg2[ARG_SIZE + 1];
314  char* argv[3] = { cmd, arg1, arg2 };
315 
316  // Make sure to have a proper terminating character if reaching the limit.
317  cmd[COMMAND_SIZE] = 0;
318  arg1[ARG_SIZE] = 0;
319  arg2[ARG_SIZE] = 0;
320 
321  // Undo all set breakpoints while running in the debugger shell. This will
322  // make them invisible to all commands.
323  UndoBreakpoints();
324 
325  while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
326  if (last_pc != sim_->get_pc()) {
327  disasm::NameConverter converter;
328  disasm::Disassembler dasm(converter);
329  // Use a reasonably large buffer.
331  dasm.InstructionDecode(buffer,
332  reinterpret_cast<byte*>(sim_->get_pc()));
333  PrintF(" 0x%016" PRIx64 " %s\n", sim_->get_pc(), buffer.start());
334  last_pc = sim_->get_pc();
335  }
336  char* line = ReadLine("sim> ");
337  if (line == nullptr) {
338  break;
339  } else {
340  char* last_input = sim_->last_debugger_input();
341  if (strcmp(line, "\n") == 0 && last_input != nullptr) {
342  line = last_input;
343  } else {
344  // Ownership is transferred to sim_;
345  sim_->set_last_debugger_input(line);
346  }
347  // Use sscanf to parse the individual parts of the command line. At the
348  // moment no command expects more than two parameters.
349  int argc = SScanF(line,
350  "%" XSTR(COMMAND_SIZE) "s "
351  "%" XSTR(ARG_SIZE) "s "
352  "%" XSTR(ARG_SIZE) "s",
353  cmd, arg1, arg2);
354  if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
355  Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
356  if (!(instr->IsTrap()) ||
357  instr->InstructionBits() == rtCallRedirInstr) {
358  sim_->InstructionDecode(
359  reinterpret_cast<Instruction*>(sim_->get_pc()));
360  } else {
361  // Allow si to jump over generated breakpoints.
362  PrintF("/!\\ Jumping over generated breakpoint.\n");
363  sim_->set_pc(sim_->get_pc() + kInstrSize);
364  }
365  } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
366  // Execute the one instruction we broke at with breakpoints disabled.
367  sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
368  // Leave the debugger shell.
369  done = true;
370  } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
371  if (argc == 2) {
372  int64_t value;
373  double dvalue;
374  if (strcmp(arg1, "all") == 0) {
375  PrintAllRegs();
376  } else if (strcmp(arg1, "allf") == 0) {
377  PrintAllRegsIncludingFPU();
378  } else {
379  int regnum = Registers::Number(arg1);
380  int fpuregnum = FPURegisters::Number(arg1);
381 
382  if (regnum != kInvalidRegister) {
383  value = GetRegisterValue(regnum);
384  PrintF("%s: 0x%08" PRIx64 " %" PRId64 " \n", arg1, value,
385  value);
386  } else if (fpuregnum != kInvalidFPURegister) {
387  value = GetFPURegisterValue(fpuregnum);
388  dvalue = GetFPURegisterValueDouble(fpuregnum);
389  PrintF("%3s: 0x%016" PRIx64 " %16.4e\n",
390  FPURegisters::Name(fpuregnum), value, dvalue);
391  } else {
392  PrintF("%s unrecognized\n", arg1);
393  }
394  }
395  } else {
396  if (argc == 3) {
397  if (strcmp(arg2, "single") == 0) {
398  int64_t value;
399  float fvalue;
400  int fpuregnum = FPURegisters::Number(arg1);
401 
402  if (fpuregnum != kInvalidFPURegister) {
403  value = GetFPURegisterValue(fpuregnum);
404  value &= 0xFFFFFFFFUL;
405  fvalue = GetFPURegisterValueFloat(fpuregnum);
406  PrintF("%s: 0x%08" PRIx64 " %11.4e\n", arg1, value, fvalue);
407  } else {
408  PrintF("%s unrecognized\n", arg1);
409  }
410  } else {
411  PrintF("print <fpu register> single\n");
412  }
413  } else {
414  PrintF("print <register> or print <fpu register> single\n");
415  }
416  }
417  } else if ((strcmp(cmd, "po") == 0)
418  || (strcmp(cmd, "printobject") == 0)) {
419  if (argc == 2) {
420  int64_t value;
421  StdoutStream os;
422  if (GetValue(arg1, &value)) {
423  Object* obj = reinterpret_cast<Object*>(value);
424  os << arg1 << ": \n";
425 #ifdef DEBUG
426  obj->Print(os);
427  os << "\n";
428 #else
429  os << Brief(obj) << "\n";
430 #endif
431  } else {
432  os << arg1 << " unrecognized\n";
433  }
434  } else {
435  PrintF("printobject <value>\n");
436  }
437  } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
438  int64_t* cur = nullptr;
439  int64_t* end = nullptr;
440  int next_arg = 1;
441 
442  if (strcmp(cmd, "stack") == 0) {
443  cur = reinterpret_cast<int64_t*>(sim_->get_register(Simulator::sp));
444  } else { // Command "mem".
445  int64_t value;
446  if (!GetValue(arg1, &value)) {
447  PrintF("%s unrecognized\n", arg1);
448  continue;
449  }
450  cur = reinterpret_cast<int64_t*>(value);
451  next_arg++;
452  }
453 
454  int64_t words;
455  if (argc == next_arg) {
456  words = 10;
457  } else {
458  if (!GetValue(argv[next_arg], &words)) {
459  words = 10;
460  }
461  }
462  end = cur + words;
463 
464  while (cur < end) {
465  PrintF(" 0x%012" PRIxPTR " : 0x%016" PRIx64 " %14" PRId64 " ",
466  reinterpret_cast<intptr_t>(cur), *cur, *cur);
467  HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
468  int64_t value = *cur;
469  Heap* current_heap = sim_->isolate_->heap();
470  if (((value & 1) == 0) || current_heap->Contains(obj)) {
471  PrintF(" (");
472  if ((value & 1) == 0) {
473  PrintF("smi %d", static_cast<int>(value >> 32));
474  } else {
475  obj->ShortPrint();
476  }
477  PrintF(")");
478  }
479  PrintF("\n");
480  cur++;
481  }
482 
483  } else if ((strcmp(cmd, "disasm") == 0) ||
484  (strcmp(cmd, "dpc") == 0) ||
485  (strcmp(cmd, "di") == 0)) {
486  disasm::NameConverter converter;
487  disasm::Disassembler dasm(converter);
488  // Use a reasonably large buffer.
490 
491  byte* cur = nullptr;
492  byte* end = nullptr;
493 
494  if (argc == 1) {
495  cur = reinterpret_cast<byte*>(sim_->get_pc());
496  end = cur + (10 * kInstrSize);
497  } else if (argc == 2) {
498  int regnum = Registers::Number(arg1);
499  if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
500  // The argument is an address or a register name.
501  int64_t value;
502  if (GetValue(arg1, &value)) {
503  cur = reinterpret_cast<byte*>(value);
504  // Disassemble 10 instructions at <arg1>.
505  end = cur + (10 * kInstrSize);
506  }
507  } else {
508  // The argument is the number of instructions.
509  int64_t value;
510  if (GetValue(arg1, &value)) {
511  cur = reinterpret_cast<byte*>(sim_->get_pc());
512  // Disassemble <arg1> instructions.
513  end = cur + (value * kInstrSize);
514  }
515  }
516  } else {
517  int64_t value1;
518  int64_t value2;
519  if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
520  cur = reinterpret_cast<byte*>(value1);
521  end = cur + (value2 * kInstrSize);
522  }
523  }
524 
525  while (cur < end) {
526  dasm.InstructionDecode(buffer, cur);
527  PrintF(" 0x%08" PRIxPTR " %s\n", reinterpret_cast<intptr_t>(cur),
528  buffer.start());
529  cur += kInstrSize;
530  }
531  } else if (strcmp(cmd, "gdb") == 0) {
532  PrintF("relinquishing control to gdb\n");
533  v8::base::OS::DebugBreak();
534  PrintF("regaining control from gdb\n");
535  } else if (strcmp(cmd, "break") == 0) {
536  if (argc == 2) {
537  int64_t value;
538  if (GetValue(arg1, &value)) {
539  if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
540  PrintF("setting breakpoint failed\n");
541  }
542  } else {
543  PrintF("%s unrecognized\n", arg1);
544  }
545  } else {
546  PrintF("break <address>\n");
547  }
548  } else if (strcmp(cmd, "del") == 0) {
549  if (!DeleteBreakpoint(nullptr)) {
550  PrintF("deleting breakpoint failed\n");
551  }
552  } else if (strcmp(cmd, "flags") == 0) {
553  PrintF("No flags on MIPS !\n");
554  } else if (strcmp(cmd, "stop") == 0) {
555  int64_t value;
556  intptr_t stop_pc = sim_->get_pc() - 2 * kInstrSize;
557  Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
558  Instruction* msg_address =
559  reinterpret_cast<Instruction*>(stop_pc + kInstrSize);
560  if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
561  // Remove the current stop.
562  if (sim_->IsStopInstruction(stop_instr)) {
563  stop_instr->SetInstructionBits(kNopInstr);
564  msg_address->SetInstructionBits(kNopInstr);
565  } else {
566  PrintF("Not at debugger stop.\n");
567  }
568  } else if (argc == 3) {
569  // Print information about all/the specified breakpoint(s).
570  if (strcmp(arg1, "info") == 0) {
571  if (strcmp(arg2, "all") == 0) {
572  PrintF("Stop information:\n");
573  for (uint32_t i = kMaxWatchpointCode + 1;
574  i <= kMaxStopCode;
575  i++) {
576  sim_->PrintStopInfo(i);
577  }
578  } else if (GetValue(arg2, &value)) {
579  sim_->PrintStopInfo(value);
580  } else {
581  PrintF("Unrecognized argument.\n");
582  }
583  } else if (strcmp(arg1, "enable") == 0) {
584  // Enable all/the specified breakpoint(s).
585  if (strcmp(arg2, "all") == 0) {
586  for (uint32_t i = kMaxWatchpointCode + 1;
587  i <= kMaxStopCode;
588  i++) {
589  sim_->EnableStop(i);
590  }
591  } else if (GetValue(arg2, &value)) {
592  sim_->EnableStop(value);
593  } else {
594  PrintF("Unrecognized argument.\n");
595  }
596  } else if (strcmp(arg1, "disable") == 0) {
597  // Disable all/the specified breakpoint(s).
598  if (strcmp(arg2, "all") == 0) {
599  for (uint32_t i = kMaxWatchpointCode + 1;
600  i <= kMaxStopCode;
601  i++) {
602  sim_->DisableStop(i);
603  }
604  } else if (GetValue(arg2, &value)) {
605  sim_->DisableStop(value);
606  } else {
607  PrintF("Unrecognized argument.\n");
608  }
609  }
610  } else {
611  PrintF("Wrong usage. Use help command for more information.\n");
612  }
613  } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
614  // Print registers and disassemble.
615  PrintAllRegs();
616  PrintF("\n");
617 
618  disasm::NameConverter converter;
619  disasm::Disassembler dasm(converter);
620  // Use a reasonably large buffer.
622 
623  byte* cur = nullptr;
624  byte* end = nullptr;
625 
626  if (argc == 1) {
627  cur = reinterpret_cast<byte*>(sim_->get_pc());
628  end = cur + (10 * kInstrSize);
629  } else if (argc == 2) {
630  int64_t value;
631  if (GetValue(arg1, &value)) {
632  cur = reinterpret_cast<byte*>(value);
633  // no length parameter passed, assume 10 instructions
634  end = cur + (10 * kInstrSize);
635  }
636  } else {
637  int64_t value1;
638  int64_t value2;
639  if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
640  cur = reinterpret_cast<byte*>(value1);
641  end = cur + (value2 * kInstrSize);
642  }
643  }
644 
645  while (cur < end) {
646  dasm.InstructionDecode(buffer, cur);
647  PrintF(" 0x%08" PRIxPTR " %s\n", reinterpret_cast<intptr_t>(cur),
648  buffer.start());
649  cur += kInstrSize;
650  }
651  } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
652  PrintF("cont\n");
653  PrintF(" continue execution (alias 'c')\n");
654  PrintF("stepi\n");
655  PrintF(" step one instruction (alias 'si')\n");
656  PrintF("print <register>\n");
657  PrintF(" print register content (alias 'p')\n");
658  PrintF(" use register name 'all' to print all registers\n");
659  PrintF("printobject <register>\n");
660  PrintF(" print an object from a register (alias 'po')\n");
661  PrintF("stack [<words>]\n");
662  PrintF(" dump stack content, default dump 10 words)\n");
663  PrintF("mem <address> [<words>]\n");
664  PrintF(" dump memory content, default dump 10 words)\n");
665  PrintF("flags\n");
666  PrintF(" print flags\n");
667  PrintF("disasm [<instructions>]\n");
668  PrintF("disasm [<address/register>]\n");
669  PrintF("disasm [[<address/register>] <instructions>]\n");
670  PrintF(" disassemble code, default is 10 instructions\n");
671  PrintF(" from pc (alias 'di')\n");
672  PrintF("gdb\n");
673  PrintF(" enter gdb\n");
674  PrintF("break <address>\n");
675  PrintF(" set a break point on the address\n");
676  PrintF("del\n");
677  PrintF(" delete the breakpoint\n");
678  PrintF("stop feature:\n");
679  PrintF(" Description:\n");
680  PrintF(" Stops are debug instructions inserted by\n");
681  PrintF(" the Assembler::stop() function.\n");
682  PrintF(" When hitting a stop, the Simulator will\n");
683  PrintF(" stop and give control to the Debugger.\n");
684  PrintF(" All stop codes are watched:\n");
685  PrintF(" - They can be enabled / disabled: the Simulator\n");
686  PrintF(" will / won't stop when hitting them.\n");
687  PrintF(" - The Simulator keeps track of how many times they \n");
688  PrintF(" are met. (See the info command.) Going over a\n");
689  PrintF(" disabled stop still increases its counter. \n");
690  PrintF(" Commands:\n");
691  PrintF(" stop info all/<code> : print infos about number <code>\n");
692  PrintF(" or all stop(s).\n");
693  PrintF(" stop enable/disable all/<code> : enables / disables\n");
694  PrintF(" all or number <code> stop(s)\n");
695  PrintF(" stop unstop\n");
696  PrintF(" ignore the stop instruction at the current location\n");
697  PrintF(" from now on\n");
698  } else {
699  PrintF("Unknown command: %s\n", cmd);
700  }
701  }
702  }
703 
704  // Add all the breakpoints back to stop execution and enter the debugger
705  // shell when hit.
706  RedoBreakpoints();
707 
708 #undef COMMAND_SIZE
709 #undef ARG_SIZE
710 
711 #undef STR
712 #undef XSTR
713 }
714 
715 bool Simulator::ICacheMatch(void* one, void* two) {
716  DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
717  DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
718  return one == two;
719 }
720 
721 
722 static uint32_t ICacheHash(void* key) {
723  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
724 }
725 
726 
727 static bool AllOnOnePage(uintptr_t start, size_t size) {
728  intptr_t start_page = (start & ~CachePage::kPageMask);
729  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
730  return start_page == end_page;
731 }
732 
733 
734 void Simulator::set_last_debugger_input(char* input) {
735  DeleteArray(last_debugger_input_);
736  last_debugger_input_ = input;
737 }
738 
739 void Simulator::SetRedirectInstruction(Instruction* instruction) {
740  instruction->SetInstructionBits(rtCallRedirInstr);
741 }
742 
743 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
744  void* start_addr, size_t size) {
745  int64_t start = reinterpret_cast<int64_t>(start_addr);
746  int64_t intra_line = (start & CachePage::kLineMask);
747  start -= intra_line;
748  size += intra_line;
749  size = ((size - 1) | CachePage::kLineMask) + 1;
750  int offset = (start & CachePage::kPageMask);
751  while (!AllOnOnePage(start, size - 1)) {
752  int bytes_to_flush = CachePage::kPageSize - offset;
753  FlushOnePage(i_cache, start, bytes_to_flush);
754  start += bytes_to_flush;
755  size -= bytes_to_flush;
756  DCHECK_EQ((int64_t)0, start & CachePage::kPageMask);
757  offset = 0;
758  }
759  if (size != 0) {
760  FlushOnePage(i_cache, start, size);
761  }
762 }
763 
764 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
765  void* page) {
766  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
767  if (entry->value == nullptr) {
768  CachePage* new_page = new CachePage();
769  entry->value = new_page;
770  }
771  return reinterpret_cast<CachePage*>(entry->value);
772 }
773 
774 
775 // Flush from start up to and not including start + size.
776 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
777  intptr_t start, size_t size) {
778  DCHECK_LE(size, CachePage::kPageSize);
779  DCHECK(AllOnOnePage(start, size - 1));
780  DCHECK_EQ(start & CachePage::kLineMask, 0);
781  DCHECK_EQ(size & CachePage::kLineMask, 0);
782  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
783  int offset = (start & CachePage::kPageMask);
784  CachePage* cache_page = GetCachePage(i_cache, page);
785  char* valid_bytemap = cache_page->ValidityByte(offset);
786  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
787 }
788 
789 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
790  Instruction* instr) {
791  int64_t address = reinterpret_cast<int64_t>(instr);
792  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
793  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
794  int offset = (address & CachePage::kPageMask);
795  CachePage* cache_page = GetCachePage(i_cache, page);
796  char* cache_valid_byte = cache_page->ValidityByte(offset);
797  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
798  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
799  if (cache_hit) {
800  // Check that the data in memory matches the contents of the I-cache.
801  CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
802  cache_page->CachedData(offset), kInstrSize));
803  } else {
804  // Cache miss. Load memory into the cache.
805  memcpy(cached_line, line, CachePage::kLineLength);
806  *cache_valid_byte = CachePage::LINE_VALID;
807  }
808 }
809 
810 
811 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
812  // Set up simulator support first. Some of this information is needed to
813  // setup the architecture state.
814  stack_size_ = FLAG_sim_stack_size * KB;
815  stack_ = reinterpret_cast<char*>(malloc(stack_size_));
816  pc_modified_ = false;
817  icount_ = 0;
818  break_count_ = 0;
819  break_pc_ = nullptr;
820  break_instr_ = 0;
821 
822  // Set up architecture state.
823  // All registers are initialized to zero to start with.
824  for (int i = 0; i < kNumSimuRegisters; i++) {
825  registers_[i] = 0;
826  }
827  for (int i = 0; i < kNumFPURegisters; i++) {
828  FPUregisters_[2 * i] = 0;
829  FPUregisters_[2 * i + 1] = 0; // upper part for MSA ASE
830  }
831 
832  if (kArchVariant == kMips64r6) {
833  FCSR_ = kFCSRNaN2008FlagMask;
834  MSACSR_ = 0;
835  } else {
836  FCSR_ = 0;
837  }
838 
839  // The sp is initialized to point to the bottom (high address) of the
840  // allocated stack area. To be safe in potential stack underflows we leave
841  // some buffer below.
842  registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64;
843  // The ra and pc are initialized to a known bad value that will cause an
844  // access violation if the simulator ever tries to execute it.
845  registers_[pc] = bad_ra;
846  registers_[ra] = bad_ra;
847 
848  last_debugger_input_ = nullptr;
849 }
850 
851 
852 Simulator::~Simulator() { free(stack_); }
853 
854 
855 // Get the active Simulator for the current thread.
856 Simulator* Simulator::current(Isolate* isolate) {
858  isolate->FindOrAllocatePerThreadDataForThisThread();
859  DCHECK_NOT_NULL(isolate_data);
860 
861  Simulator* sim = isolate_data->simulator();
862  if (sim == nullptr) {
863  // TODO(146): delete the simulator object when a thread/isolate goes away.
864  sim = new Simulator(isolate);
865  isolate_data->set_simulator(sim);
866  }
867  return sim;
868 }
869 
870 
871 // Sets the register in the architecture state. It will also deal with updating
872 // Simulator internal state for special registers such as PC.
873 void Simulator::set_register(int reg, int64_t value) {
874  DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
875  if (reg == pc) {
876  pc_modified_ = true;
877  }
878 
879  // Zero register always holds 0.
880  registers_[reg] = (reg == 0) ? 0 : value;
881 }
882 
883 
884 void Simulator::set_dw_register(int reg, const int* dbl) {
885  DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
886  registers_[reg] = dbl[1];
887  registers_[reg] = registers_[reg] << 32;
888  registers_[reg] += dbl[0];
889 }
890 
891 
892 void Simulator::set_fpu_register(int fpureg, int64_t value) {
893  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
894  FPUregisters_[fpureg * 2] = value;
895 }
896 
897 
898 void Simulator::set_fpu_register_word(int fpureg, int32_t value) {
899  // Set ONLY lower 32-bits, leaving upper bits untouched.
900  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
901  int32_t* pword;
902  if (kArchEndian == kLittle) {
903  pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg * 2]);
904  } else {
905  pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg * 2]) + 1;
906  }
907  *pword = value;
908 }
909 
910 
911 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
912  // Set ONLY upper 32-bits, leaving lower bits untouched.
913  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
914  int32_t* phiword;
915  if (kArchEndian == kLittle) {
916  phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg * 2])) + 1;
917  } else {
918  phiword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg * 2]);
919  }
920  *phiword = value;
921 }
922 
923 
924 void Simulator::set_fpu_register_float(int fpureg, float value) {
925  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
926  *bit_cast<float*>(&FPUregisters_[fpureg * 2]) = value;
927 }
928 
929 
930 void Simulator::set_fpu_register_double(int fpureg, double value) {
931  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
932  *bit_cast<double*>(&FPUregisters_[fpureg * 2]) = value;
933 }
934 
935 
936 // Get the register from the architecture state. This function does handle
937 // the special case of accessing the PC register.
938 int64_t Simulator::get_register(int reg) const {
939  DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
940  if (reg == 0)
941  return 0;
942  else
943  return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
944 }
945 
946 
947 double Simulator::get_double_from_register_pair(int reg) {
948  // TODO(plind): bad ABI stuff, refactor or remove.
949  DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
950 
951  double dm_val = 0.0;
952  // Read the bits from the unsigned integer register_[] array
953  // into the double precision floating point value and return it.
954  char buffer[sizeof(registers_[0])];
955  memcpy(buffer, &registers_[reg], sizeof(registers_[0]));
956  memcpy(&dm_val, buffer, sizeof(registers_[0]));
957  return(dm_val);
958 }
959 
960 
961 int64_t Simulator::get_fpu_register(int fpureg) const {
962  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
963  return FPUregisters_[fpureg * 2];
964 }
965 
966 
967 int32_t Simulator::get_fpu_register_word(int fpureg) const {
968  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
969  return static_cast<int32_t>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
970 }
971 
972 
973 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
974  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
975  return static_cast<int32_t>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
976 }
977 
978 
979 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
980  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
981  return static_cast<int32_t>((FPUregisters_[fpureg * 2] >> 32) & 0xFFFFFFFF);
982 }
983 
984 
985 float Simulator::get_fpu_register_float(int fpureg) const {
986  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
987  return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg * 2]));
988 }
989 
990 
991 double Simulator::get_fpu_register_double(int fpureg) const {
992  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
993  return *bit_cast<double*>(&FPUregisters_[fpureg * 2]);
994 }
995 
996 template <typename T>
997 void Simulator::get_msa_register(int wreg, T* value) {
998  DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
999  memcpy(value, FPUregisters_ + wreg * 2, kSimd128Size);
1000 }
1001 
1002 template <typename T>
1003 void Simulator::set_msa_register(int wreg, const T* value) {
1004  DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
1005  memcpy(FPUregisters_ + wreg * 2, value, kSimd128Size);
1006 }
1007 
1008 // Runtime FP routines take up to two double arguments and zero
1009 // or one integer arguments. All are constructed here,
1010 // from a0-a3 or f12 and f13 (n64), or f14 (O32).
1011 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1012  if (!IsMipsSoftFloatABI) {
1013  const int fparg2 = 13;
1014  *x = get_fpu_register_double(12);
1015  *y = get_fpu_register_double(fparg2);
1016  *z = static_cast<int32_t>(get_register(a2));
1017  } else {
1018  // TODO(plind): bad ABI stuff, refactor or remove.
1019  // We use a char buffer to get around the strict-aliasing rules which
1020  // otherwise allow the compiler to optimize away the copy.
1021  char buffer[sizeof(*x)];
1022  int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1023 
1024  // Registers a0 and a1 -> x.
1025  reg_buffer[0] = get_register(a0);
1026  reg_buffer[1] = get_register(a1);
1027  memcpy(x, buffer, sizeof(buffer));
1028  // Registers a2 and a3 -> y.
1029  reg_buffer[0] = get_register(a2);
1030  reg_buffer[1] = get_register(a3);
1031  memcpy(y, buffer, sizeof(buffer));
1032  // Register 2 -> z.
1033  reg_buffer[0] = get_register(a2);
1034  memcpy(z, buffer, sizeof(*z));
1035  }
1036 }
1037 
1038 
1039 // The return value is either in v0/v1 or f0.
1040 void Simulator::SetFpResult(const double& result) {
1041  if (!IsMipsSoftFloatABI) {
1042  set_fpu_register_double(0, result);
1043  } else {
1044  char buffer[2 * sizeof(registers_[0])];
1045  int64_t* reg_buffer = reinterpret_cast<int64_t*>(buffer);
1046  memcpy(buffer, &result, sizeof(buffer));
1047  // Copy result to v0 and v1.
1048  set_register(v0, reg_buffer[0]);
1049  set_register(v1, reg_buffer[1]);
1050  }
1051 }
1052 
1053 
1054 // Helper functions for setting and testing the FCSR register's bits.
1055 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1056  if (value) {
1057  FCSR_ |= (1 << cc);
1058  } else {
1059  FCSR_ &= ~(1 << cc);
1060  }
1061 }
1062 
1063 
1064 bool Simulator::test_fcsr_bit(uint32_t cc) {
1065  return FCSR_ & (1 << cc);
1066 }
1067 
1068 
1069 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1070  FCSR_ |= mode & kFPURoundingModeMask;
1071 }
1072 
1073 void Simulator::set_msacsr_rounding_mode(FPURoundingMode mode) {
1074  MSACSR_ |= mode & kFPURoundingModeMask;
1075 }
1076 
1077 unsigned int Simulator::get_fcsr_rounding_mode() {
1078  return FCSR_ & kFPURoundingModeMask;
1079 }
1080 
1081 unsigned int Simulator::get_msacsr_rounding_mode() {
1082  return MSACSR_ & kFPURoundingModeMask;
1083 }
1084 
1085 // Sets the rounding error codes in FCSR based on the result of the rounding.
1086 // Returns true if the operation was invalid.
1087 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1088  bool ret = false;
1089  double max_int32 = std::numeric_limits<int32_t>::max();
1090  double min_int32 = std::numeric_limits<int32_t>::min();
1091 
1092  if (!std::isfinite(original) || !std::isfinite(rounded)) {
1093  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1094  ret = true;
1095  }
1096 
1097  if (original != rounded) {
1098  set_fcsr_bit(kFCSRInexactFlagBit, true);
1099  }
1100 
1101  if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1102  set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1103  ret = true;
1104  }
1105 
1106  if (rounded > max_int32 || rounded < min_int32) {
1107  set_fcsr_bit(kFCSROverflowFlagBit, true);
1108  // The reference is not really clear but it seems this is required:
1109  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1110  ret = true;
1111  }
1112 
1113  return ret;
1114 }
1115 
1116 
1117 // Sets the rounding error codes in FCSR based on the result of the rounding.
1118 // Returns true if the operation was invalid.
1119 bool Simulator::set_fcsr_round64_error(double original, double rounded) {
1120  bool ret = false;
1121  // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1122  // loading the most accurate representation into max_int64, which is 2^63.
1123  double max_int64 = std::numeric_limits<int64_t>::max();
1124  double min_int64 = std::numeric_limits<int64_t>::min();
1125 
1126  if (!std::isfinite(original) || !std::isfinite(rounded)) {
1127  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1128  ret = true;
1129  }
1130 
1131  if (original != rounded) {
1132  set_fcsr_bit(kFCSRInexactFlagBit, true);
1133  }
1134 
1135  if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1136  set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1137  ret = true;
1138  }
1139 
1140  if (rounded >= max_int64 || rounded < min_int64) {
1141  set_fcsr_bit(kFCSROverflowFlagBit, true);
1142  // The reference is not really clear but it seems this is required:
1143  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1144  ret = true;
1145  }
1146 
1147  return ret;
1148 }
1149 
1150 
1151 // Sets the rounding error codes in FCSR based on the result of the rounding.
1152 // Returns true if the operation was invalid.
1153 bool Simulator::set_fcsr_round_error(float original, float rounded) {
1154  bool ret = false;
1155  double max_int32 = std::numeric_limits<int32_t>::max();
1156  double min_int32 = std::numeric_limits<int32_t>::min();
1157 
1158  if (!std::isfinite(original) || !std::isfinite(rounded)) {
1159  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1160  ret = true;
1161  }
1162 
1163  if (original != rounded) {
1164  set_fcsr_bit(kFCSRInexactFlagBit, true);
1165  }
1166 
1167  if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1168  set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1169  ret = true;
1170  }
1171 
1172  if (rounded > max_int32 || rounded < min_int32) {
1173  set_fcsr_bit(kFCSROverflowFlagBit, true);
1174  // The reference is not really clear but it seems this is required:
1175  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1176  ret = true;
1177  }
1178 
1179  return ret;
1180 }
1181 
1182 void Simulator::set_fpu_register_word_invalid_result(float original,
1183  float rounded) {
1184  if (FCSR_ & kFCSRNaN2008FlagMask) {
1185  double max_int32 = std::numeric_limits<int32_t>::max();
1186  double min_int32 = std::numeric_limits<int32_t>::min();
1187  if (std::isnan(original)) {
1188  set_fpu_register_word(fd_reg(), 0);
1189  } else if (rounded > max_int32) {
1190  set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1191  } else if (rounded < min_int32) {
1192  set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1193  } else {
1194  UNREACHABLE();
1195  }
1196  } else {
1197  set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1198  }
1199 }
1200 
1201 
1202 void Simulator::set_fpu_register_invalid_result(float original, float rounded) {
1203  if (FCSR_ & kFCSRNaN2008FlagMask) {
1204  double max_int32 = std::numeric_limits<int32_t>::max();
1205  double min_int32 = std::numeric_limits<int32_t>::min();
1206  if (std::isnan(original)) {
1207  set_fpu_register(fd_reg(), 0);
1208  } else if (rounded > max_int32) {
1209  set_fpu_register(fd_reg(), kFPUInvalidResult);
1210  } else if (rounded < min_int32) {
1211  set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1212  } else {
1213  UNREACHABLE();
1214  }
1215  } else {
1216  set_fpu_register(fd_reg(), kFPUInvalidResult);
1217  }
1218 }
1219 
1220 
1221 void Simulator::set_fpu_register_invalid_result64(float original,
1222  float rounded) {
1223  if (FCSR_ & kFCSRNaN2008FlagMask) {
1224  // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1225  // loading the most accurate representation into max_int64, which is 2^63.
1226  double max_int64 = std::numeric_limits<int64_t>::max();
1227  double min_int64 = std::numeric_limits<int64_t>::min();
1228  if (std::isnan(original)) {
1229  set_fpu_register(fd_reg(), 0);
1230  } else if (rounded >= max_int64) {
1231  set_fpu_register(fd_reg(), kFPU64InvalidResult);
1232  } else if (rounded < min_int64) {
1233  set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1234  } else {
1235  UNREACHABLE();
1236  }
1237  } else {
1238  set_fpu_register(fd_reg(), kFPU64InvalidResult);
1239  }
1240 }
1241 
1242 
1243 void Simulator::set_fpu_register_word_invalid_result(double original,
1244  double rounded) {
1245  if (FCSR_ & kFCSRNaN2008FlagMask) {
1246  double max_int32 = std::numeric_limits<int32_t>::max();
1247  double min_int32 = std::numeric_limits<int32_t>::min();
1248  if (std::isnan(original)) {
1249  set_fpu_register_word(fd_reg(), 0);
1250  } else if (rounded > max_int32) {
1251  set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1252  } else if (rounded < min_int32) {
1253  set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1254  } else {
1255  UNREACHABLE();
1256  }
1257  } else {
1258  set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1259  }
1260 }
1261 
1262 
1263 void Simulator::set_fpu_register_invalid_result(double original,
1264  double rounded) {
1265  if (FCSR_ & kFCSRNaN2008FlagMask) {
1266  double max_int32 = std::numeric_limits<int32_t>::max();
1267  double min_int32 = std::numeric_limits<int32_t>::min();
1268  if (std::isnan(original)) {
1269  set_fpu_register(fd_reg(), 0);
1270  } else if (rounded > max_int32) {
1271  set_fpu_register(fd_reg(), kFPUInvalidResult);
1272  } else if (rounded < min_int32) {
1273  set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1274  } else {
1275  UNREACHABLE();
1276  }
1277  } else {
1278  set_fpu_register(fd_reg(), kFPUInvalidResult);
1279  }
1280 }
1281 
1282 
1283 void Simulator::set_fpu_register_invalid_result64(double original,
1284  double rounded) {
1285  if (FCSR_ & kFCSRNaN2008FlagMask) {
1286  // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1287  // loading the most accurate representation into max_int64, which is 2^63.
1288  double max_int64 = std::numeric_limits<int64_t>::max();
1289  double min_int64 = std::numeric_limits<int64_t>::min();
1290  if (std::isnan(original)) {
1291  set_fpu_register(fd_reg(), 0);
1292  } else if (rounded >= max_int64) {
1293  set_fpu_register(fd_reg(), kFPU64InvalidResult);
1294  } else if (rounded < min_int64) {
1295  set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1296  } else {
1297  UNREACHABLE();
1298  }
1299  } else {
1300  set_fpu_register(fd_reg(), kFPU64InvalidResult);
1301  }
1302 }
1303 
1304 
1305 // Sets the rounding error codes in FCSR based on the result of the rounding.
1306 // Returns true if the operation was invalid.
1307 bool Simulator::set_fcsr_round64_error(float original, float rounded) {
1308  bool ret = false;
1309  // The value of INT64_MAX (2^63-1) can't be represented as double exactly,
1310  // loading the most accurate representation into max_int64, which is 2^63.
1311  double max_int64 = std::numeric_limits<int64_t>::max();
1312  double min_int64 = std::numeric_limits<int64_t>::min();
1313 
1314  if (!std::isfinite(original) || !std::isfinite(rounded)) {
1315  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1316  ret = true;
1317  }
1318 
1319  if (original != rounded) {
1320  set_fcsr_bit(kFCSRInexactFlagBit, true);
1321  }
1322 
1323  if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1324  set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1325  ret = true;
1326  }
1327 
1328  if (rounded >= max_int64 || rounded < min_int64) {
1329  set_fcsr_bit(kFCSROverflowFlagBit, true);
1330  // The reference is not really clear but it seems this is required:
1331  set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1332  ret = true;
1333  }
1334 
1335  return ret;
1336 }
1337 
1338 
1339 // For cvt instructions only
1340 void Simulator::round_according_to_fcsr(double toRound, double& rounded,
1341  int32_t& rounded_int, double fs) {
1342  // 0 RN (round to nearest): Round a result to the nearest
1343  // representable value; if the result is exactly halfway between
1344  // two representable values, round to zero. Behave like round_w_d.
1345 
1346  // 1 RZ (round toward zero): Round a result to the closest
1347  // representable value whose absolute value is less than or
1348  // equal to the infinitely accurate result. Behave like trunc_w_d.
1349 
1350  // 2 RP (round up, or toward +infinity): Round a result to the
1351  // next representable value up. Behave like ceil_w_d.
1352 
1353  // 3 RN (round down, or toward −infinity): Round a result to
1354  // the next representable value down. Behave like floor_w_d.
1355  switch (FCSR_ & 3) {
1356  case kRoundToNearest:
1357  rounded = std::floor(fs + 0.5);
1358  rounded_int = static_cast<int32_t>(rounded);
1359  if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1360  // If the number is halfway between two integers,
1361  // round to the even one.
1362  rounded_int--;
1363  rounded -= 1.;
1364  }
1365  break;
1366  case kRoundToZero:
1367  rounded = trunc(fs);
1368  rounded_int = static_cast<int32_t>(rounded);
1369  break;
1370  case kRoundToPlusInf:
1371  rounded = std::ceil(fs);
1372  rounded_int = static_cast<int32_t>(rounded);
1373  break;
1374  case kRoundToMinusInf:
1375  rounded = std::floor(fs);
1376  rounded_int = static_cast<int32_t>(rounded);
1377  break;
1378  }
1379 }
1380 
1381 
1382 void Simulator::round64_according_to_fcsr(double toRound, double& rounded,
1383  int64_t& rounded_int, double fs) {
1384  // 0 RN (round to nearest): Round a result to the nearest
1385  // representable value; if the result is exactly halfway between
1386  // two representable values, round to zero. Behave like round_w_d.
1387 
1388  // 1 RZ (round toward zero): Round a result to the closest
1389  // representable value whose absolute value is less than or.
1390  // equal to the infinitely accurate result. Behave like trunc_w_d.
1391 
1392  // 2 RP (round up, or toward +infinity): Round a result to the
1393  // next representable value up. Behave like ceil_w_d.
1394 
1395  // 3 RN (round down, or toward −infinity): Round a result to
1396  // the next representable value down. Behave like floor_w_d.
1397  switch (FCSR_ & 3) {
1398  case kRoundToNearest:
1399  rounded = std::floor(fs + 0.5);
1400  rounded_int = static_cast<int64_t>(rounded);
1401  if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1402  // If the number is halfway between two integers,
1403  // round to the even one.
1404  rounded_int--;
1405  rounded -= 1.;
1406  }
1407  break;
1408  case kRoundToZero:
1409  rounded = trunc(fs);
1410  rounded_int = static_cast<int64_t>(rounded);
1411  break;
1412  case kRoundToPlusInf:
1413  rounded = std::ceil(fs);
1414  rounded_int = static_cast<int64_t>(rounded);
1415  break;
1416  case kRoundToMinusInf:
1417  rounded = std::floor(fs);
1418  rounded_int = static_cast<int64_t>(rounded);
1419  break;
1420  }
1421 }
1422 
1423 
1424 // for cvt instructions only
1425 void Simulator::round_according_to_fcsr(float toRound, float& rounded,
1426  int32_t& rounded_int, float fs) {
1427  // 0 RN (round to nearest): Round a result to the nearest
1428  // representable value; if the result is exactly halfway between
1429  // two representable values, round to zero. Behave like round_w_d.
1430 
1431  // 1 RZ (round toward zero): Round a result to the closest
1432  // representable value whose absolute value is less than or
1433  // equal to the infinitely accurate result. Behave like trunc_w_d.
1434 
1435  // 2 RP (round up, or toward +infinity): Round a result to the
1436  // next representable value up. Behave like ceil_w_d.
1437 
1438  // 3 RN (round down, or toward −infinity): Round a result to
1439  // the next representable value down. Behave like floor_w_d.
1440  switch (FCSR_ & 3) {
1441  case kRoundToNearest:
1442  rounded = std::floor(fs + 0.5);
1443  rounded_int = static_cast<int32_t>(rounded);
1444  if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1445  // If the number is halfway between two integers,
1446  // round to the even one.
1447  rounded_int--;
1448  rounded -= 1.f;
1449  }
1450  break;
1451  case kRoundToZero:
1452  rounded = trunc(fs);
1453  rounded_int = static_cast<int32_t>(rounded);
1454  break;
1455  case kRoundToPlusInf:
1456  rounded = std::ceil(fs);
1457  rounded_int = static_cast<int32_t>(rounded);
1458  break;
1459  case kRoundToMinusInf:
1460  rounded = std::floor(fs);
1461  rounded_int = static_cast<int32_t>(rounded);
1462  break;
1463  }
1464 }
1465 
1466 
1467 void Simulator::round64_according_to_fcsr(float toRound, float& rounded,
1468  int64_t& rounded_int, float fs) {
1469  // 0 RN (round to nearest): Round a result to the nearest
1470  // representable value; if the result is exactly halfway between
1471  // two representable values, round to zero. Behave like round_w_d.
1472 
1473  // 1 RZ (round toward zero): Round a result to the closest
1474  // representable value whose absolute value is less than or.
1475  // equal to the infinitely accurate result. Behave like trunc_w_d.
1476 
1477  // 2 RP (round up, or toward +infinity): Round a result to the
1478  // next representable value up. Behave like ceil_w_d.
1479 
1480  // 3 RN (round down, or toward −infinity): Round a result to
1481  // the next representable value down. Behave like floor_w_d.
1482  switch (FCSR_ & 3) {
1483  case kRoundToNearest:
1484  rounded = std::floor(fs + 0.5);
1485  rounded_int = static_cast<int64_t>(rounded);
1486  if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1487  // If the number is halfway between two integers,
1488  // round to the even one.
1489  rounded_int--;
1490  rounded -= 1.f;
1491  }
1492  break;
1493  case kRoundToZero:
1494  rounded = trunc(fs);
1495  rounded_int = static_cast<int64_t>(rounded);
1496  break;
1497  case kRoundToPlusInf:
1498  rounded = std::ceil(fs);
1499  rounded_int = static_cast<int64_t>(rounded);
1500  break;
1501  case kRoundToMinusInf:
1502  rounded = std::floor(fs);
1503  rounded_int = static_cast<int64_t>(rounded);
1504  break;
1505  }
1506 }
1507 
1508 template <typename T_fp, typename T_int>
1509 void Simulator::round_according_to_msacsr(T_fp toRound, T_fp& rounded,
1510  T_int& rounded_int) {
1511  // 0 RN (round to nearest): Round a result to the nearest
1512  // representable value; if the result is exactly halfway between
1513  // two representable values, round to zero. Behave like round_w_d.
1514 
1515  // 1 RZ (round toward zero): Round a result to the closest
1516  // representable value whose absolute value is less than or
1517  // equal to the infinitely accurate result. Behave like trunc_w_d.
1518 
1519  // 2 RP (round up, or toward +infinity): Round a result to the
1520  // next representable value up. Behave like ceil_w_d.
1521 
1522  // 3 RN (round down, or toward −infinity): Round a result to
1523  // the next representable value down. Behave like floor_w_d.
1524  switch (get_msacsr_rounding_mode()) {
1525  case kRoundToNearest:
1526  rounded = std::floor(toRound + 0.5);
1527  rounded_int = static_cast<T_int>(rounded);
1528  if ((rounded_int & 1) != 0 && rounded_int - toRound == 0.5) {
1529  // If the number is halfway between two integers,
1530  // round to the even one.
1531  rounded_int--;
1532  rounded -= 1.;
1533  }
1534  break;
1535  case kRoundToZero:
1536  rounded = trunc(toRound);
1537  rounded_int = static_cast<T_int>(rounded);
1538  break;
1539  case kRoundToPlusInf:
1540  rounded = std::ceil(toRound);
1541  rounded_int = static_cast<T_int>(rounded);
1542  break;
1543  case kRoundToMinusInf:
1544  rounded = std::floor(toRound);
1545  rounded_int = static_cast<T_int>(rounded);
1546  break;
1547  }
1548 }
1549 
1550 // Raw access to the PC register.
1551 void Simulator::set_pc(int64_t value) {
1552  pc_modified_ = true;
1553  registers_[pc] = value;
1554 }
1555 
1556 
1557 bool Simulator::has_bad_pc() const {
1558  return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1559 }
1560 
1561 
1562 // Raw access to the PC register without the special adjustment when reading.
1563 int64_t Simulator::get_pc() const {
1564  return registers_[pc];
1565 }
1566 
1567 
1568 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an
1569 // interrupt is caused. On others it does a funky rotation thing. For now we
1570 // simply disallow unaligned reads, but at some point we may want to move to
1571 // emulating the rotate behaviour. Note that simulator runs have the runtime
1572 // system running directly on the host system and only generated code is
1573 // executed in the simulator. Since the host is typically IA32 we will not
1574 // get the correct MIPS-like behaviour on unaligned accesses.
1575 
1576 // TODO(plind): refactor this messy debug code when we do unaligned access.
1577 void Simulator::DieOrDebug() {
1578  if ((1)) { // Flag for this was removed.
1579  MipsDebugger dbg(this);
1580  dbg.Debug();
1581  } else {
1582  base::OS::Abort();
1583  }
1584 }
1585 
1586 void Simulator::TraceRegWr(int64_t value, TraceType t) {
1587  if (::v8::internal::FLAG_trace_sim) {
1588  union {
1589  int64_t fmt_int64;
1590  int32_t fmt_int32[2];
1591  float fmt_float[2];
1592  double fmt_double;
1593  } v;
1594  v.fmt_int64 = value;
1595 
1596  switch (t) {
1597  case WORD:
1598  SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") int32:%" PRId32
1599  " uint32:%" PRIu32,
1600  v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0]);
1601  break;
1602  case DWORD:
1603  SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") int64:%" PRId64
1604  " uint64:%" PRIu64,
1605  value, icount_, value, value);
1606  break;
1607  case FLOAT:
1608  SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") flt:%e",
1609  v.fmt_int64, icount_, v.fmt_float[0]);
1610  break;
1611  case DOUBLE:
1612  SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") dbl:%e",
1613  v.fmt_int64, icount_, v.fmt_double);
1614  break;
1615  case FLOAT_DOUBLE:
1616  SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") flt:%e dbl:%e",
1617  v.fmt_int64, icount_, v.fmt_float[0], v.fmt_double);
1618  break;
1619  case WORD_DWORD:
1620  SNPrintF(trace_buf_,
1621  "%016" PRIx64 " (%" PRId64 ") int32:%" PRId32
1622  " uint32:%" PRIu32 " int64:%" PRId64 " uint64:%" PRIu64,
1623  v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0],
1624  v.fmt_int64, v.fmt_int64);
1625  break;
1626  default:
1627  UNREACHABLE();
1628  }
1629  }
1630 }
1631 
1632 template <typename T>
1633 void Simulator::TraceMSARegWr(T* value, TraceType t) {
1634  if (::v8::internal::FLAG_trace_sim) {
1635  union {
1636  uint8_t b[16];
1637  uint16_t h[8];
1638  uint32_t w[4];
1639  uint64_t d[2];
1640  float f[4];
1641  double df[2];
1642  } v;
1643  memcpy(v.b, value, kSimd128Size);
1644  switch (t) {
1645  case BYTE:
1646  SNPrintF(trace_buf_,
1647  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64 ")",
1648  v.d[0], v.d[1], icount_);
1649  break;
1650  case HALF:
1651  SNPrintF(trace_buf_,
1652  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64 ")",
1653  v.d[0], v.d[1], icount_);
1654  break;
1655  case WORD:
1656  SNPrintF(trace_buf_,
1657  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
1658  ") int32[0..3]:%" PRId32 " %" PRId32 " %" PRId32
1659  " %" PRId32,
1660  v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1661  break;
1662  case DWORD:
1663  SNPrintF(trace_buf_,
1664  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64 ")",
1665  v.d[0], v.d[1], icount_);
1666  break;
1667  case FLOAT:
1668  SNPrintF(trace_buf_,
1669  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
1670  ") flt[0..3]:%e %e %e %e",
1671  v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1672  break;
1673  case DOUBLE:
1674  SNPrintF(trace_buf_,
1675  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
1676  ") dbl[0..1]:%e %e",
1677  v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1678  break;
1679  default:
1680  UNREACHABLE();
1681  }
1682  }
1683 }
1684 
1685 template <typename T>
1686 void Simulator::TraceMSARegWr(T* value) {
1687  if (::v8::internal::FLAG_trace_sim) {
1688  union {
1689  uint8_t b[kMSALanesByte];
1690  uint16_t h[kMSALanesHalf];
1691  uint32_t w[kMSALanesWord];
1692  uint64_t d[kMSALanesDword];
1693  float f[kMSALanesWord];
1694  double df[kMSALanesDword];
1695  } v;
1696  memcpy(v.b, value, kMSALanesByte);
1697 
1698  if (std::is_same<T, int32_t>::value) {
1699  SNPrintF(trace_buf_,
1700  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
1701  ") int32[0..3]:%" PRId32 " %" PRId32 " %" PRId32
1702  " %" PRId32,
1703  v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1704  } else if (std::is_same<T, float>::value) {
1705  SNPrintF(trace_buf_,
1706  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
1707  ") flt[0..3]:%e %e %e %e",
1708  v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1709  } else if (std::is_same<T, double>::value) {
1710  SNPrintF(trace_buf_,
1711  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
1712  ") dbl[0..1]:%e %e",
1713  v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1714  } else {
1715  SNPrintF(trace_buf_,
1716  "LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64 ")",
1717  v.d[0], v.d[1], icount_);
1718  }
1719  }
1720 }
1721 
1722 // TODO(plind): consider making icount_ printing a flag option.
1723 void Simulator::TraceMemRd(int64_t addr, int64_t value, TraceType t) {
1724  if (::v8::internal::FLAG_trace_sim) {
1725  union {
1726  int64_t fmt_int64;
1727  int32_t fmt_int32[2];
1728  float fmt_float[2];
1729  double fmt_double;
1730  } v;
1731  v.fmt_int64 = value;
1732 
1733  switch (t) {
1734  case WORD:
1735  SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64
1736  ") int32:%" PRId32 " uint32:%" PRIu32,
1737  v.fmt_int64, addr, icount_, v.fmt_int32[0], v.fmt_int32[0]);
1738  break;
1739  case DWORD:
1740  SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64
1741  ") int64:%" PRId64 " uint64:%" PRIu64,
1742  value, addr, icount_, value, value);
1743  break;
1744  case FLOAT:
1745  SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64
1746  ") flt:%e",
1747  v.fmt_int64, addr, icount_, v.fmt_float[0]);
1748  break;
1749  case DOUBLE:
1750  SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64
1751  ") dbl:%e",
1752  v.fmt_int64, addr, icount_, v.fmt_double);
1753  break;
1754  case FLOAT_DOUBLE:
1755  SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64
1756  ") flt:%e dbl:%e",
1757  v.fmt_int64, addr, icount_, v.fmt_float[0], v.fmt_double);
1758  break;
1759  default:
1760  UNREACHABLE();
1761  }
1762  }
1763 }
1764 
1765 
1766 void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) {
1767  if (::v8::internal::FLAG_trace_sim) {
1768  switch (t) {
1769  case BYTE:
1770  SNPrintF(trace_buf_, " %02" PRIx8 " --> [%016" PRIx64
1771  "] (%" PRId64 ")",
1772  static_cast<uint8_t>(value), addr, icount_);
1773  break;
1774  case HALF:
1775  SNPrintF(trace_buf_, " %04" PRIx16 " --> [%016" PRIx64
1776  "] (%" PRId64 ")",
1777  static_cast<uint16_t>(value), addr, icount_);
1778  break;
1779  case WORD:
1780  SNPrintF(trace_buf_,
1781  " %08" PRIx32 " --> [%016" PRIx64 "] (%" PRId64 ")",
1782  static_cast<uint32_t>(value), addr, icount_);
1783  break;
1784  case DWORD:
1785  SNPrintF(trace_buf_,
1786  "%016" PRIx64 " --> [%016" PRIx64 "] (%" PRId64 " )",
1787  value, addr, icount_);
1788  break;
1789  default:
1790  UNREACHABLE();
1791  }
1792  }
1793 }
1794 
1795 template <typename T>
1796 void Simulator::TraceMemRd(int64_t addr, T value) {
1797  if (::v8::internal::FLAG_trace_sim) {
1798  switch (sizeof(T)) {
1799  case 1:
1800  SNPrintF(trace_buf_,
1801  "%08" PRIx8 " <-- [%08" PRIx64 "] (%" PRIu64
1802  ") int8:%" PRId8 " uint8:%" PRIu8,
1803  static_cast<uint8_t>(value), addr, icount_,
1804  static_cast<int8_t>(value), static_cast<uint8_t>(value));
1805  break;
1806  case 2:
1807  SNPrintF(trace_buf_,
1808  "%08" PRIx16 " <-- [%08" PRIx64 "] (%" PRIu64
1809  ") int16:%" PRId16 " uint16:%" PRIu16,
1810  static_cast<uint16_t>(value), addr, icount_,
1811  static_cast<int16_t>(value), static_cast<uint16_t>(value));
1812  break;
1813  case 4:
1814  SNPrintF(trace_buf_,
1815  "%08" PRIx32 " <-- [%08" PRIx64 "] (%" PRIu64
1816  ") int32:%" PRId32 " uint32:%" PRIu32,
1817  static_cast<uint32_t>(value), addr, icount_,
1818  static_cast<int32_t>(value), static_cast<uint32_t>(value));
1819  break;
1820  case 8:
1821  SNPrintF(trace_buf_,
1822  "%08" PRIx64 " <-- [%08" PRIx64 "] (%" PRIu64
1823  ") int64:%" PRId64 " uint64:%" PRIu64,
1824  static_cast<uint64_t>(value), addr, icount_,
1825  static_cast<int64_t>(value), static_cast<uint64_t>(value));
1826  break;
1827  default:
1828  UNREACHABLE();
1829  }
1830  }
1831 }
1832 
1833 template <typename T>
1834 void Simulator::TraceMemWr(int64_t addr, T value) {
1835  if (::v8::internal::FLAG_trace_sim) {
1836  switch (sizeof(T)) {
1837  case 1:
1838  SNPrintF(trace_buf_,
1839  " %02" PRIx8 " --> [%08" PRIx64 "] (%" PRIu64 ")",
1840  static_cast<uint8_t>(value), addr, icount_);
1841  break;
1842  case 2:
1843  SNPrintF(trace_buf_,
1844  " %04" PRIx16 " --> [%08" PRIx64 "] (%" PRIu64 ")",
1845  static_cast<uint16_t>(value), addr, icount_);
1846  break;
1847  case 4:
1848  SNPrintF(trace_buf_,
1849  "%08" PRIx32 " --> [%08" PRIx64 "] (%" PRIu64 ")",
1850  static_cast<uint32_t>(value), addr, icount_);
1851  break;
1852  case 8:
1853  SNPrintF(trace_buf_,
1854  "%16" PRIx64 " --> [%08" PRIx64 "] (%" PRIu64 ")",
1855  static_cast<uint64_t>(value), addr, icount_);
1856  break;
1857  default:
1858  UNREACHABLE();
1859  }
1860  }
1861 }
1862 
1863 // TODO(plind): sign-extend and zero-extend not implmented properly
1864 // on all the ReadXX functions, I don't think re-interpret cast does it.
1865 int32_t Simulator::ReadW(int64_t addr, Instruction* instr, TraceType t) {
1866  if (addr >=0 && addr < 0x400) {
1867  // This has to be a nullptr-dereference, drop into debugger.
1868  PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1869  " \n",
1870  addr, reinterpret_cast<intptr_t>(instr));
1871  DieOrDebug();
1872  }
1873  if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1874  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1875  TraceMemRd(addr, static_cast<int64_t>(*ptr), t);
1876  return *ptr;
1877  }
1878  PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1879  reinterpret_cast<intptr_t>(instr));
1880  DieOrDebug();
1881  return 0;
1882 }
1883 
1884 
1885 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) {
1886  if (addr >=0 && addr < 0x400) {
1887  // This has to be a nullptr-dereference, drop into debugger.
1888  PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1889  " \n",
1890  addr, reinterpret_cast<intptr_t>(instr));
1891  DieOrDebug();
1892  }
1893  if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1894  uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1895  TraceMemRd(addr, static_cast<int64_t>(*ptr), WORD);
1896  return *ptr;
1897  }
1898  PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1899  reinterpret_cast<intptr_t>(instr));
1900  DieOrDebug();
1901  return 0;
1902 }
1903 
1904 
1905 void Simulator::WriteW(int64_t addr, int32_t value, Instruction* instr) {
1906  if (addr >= 0 && addr < 0x400) {
1907  // This has to be a nullptr-dereference, drop into debugger.
1908  PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1909  " \n",
1910  addr, reinterpret_cast<intptr_t>(instr));
1911  DieOrDebug();
1912  }
1913  if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1914  TraceMemWr(addr, value, WORD);
1915  int* ptr = reinterpret_cast<int*>(addr);
1916  *ptr = value;
1917  return;
1918  }
1919  PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1920  reinterpret_cast<intptr_t>(instr));
1921  DieOrDebug();
1922 }
1923 
1924 
1925 int64_t Simulator::Read2W(int64_t addr, Instruction* instr) {
1926  if (addr >=0 && addr < 0x400) {
1927  // This has to be a nullptr-dereference, drop into debugger.
1928  PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1929  " \n",
1930  addr, reinterpret_cast<intptr_t>(instr));
1931  DieOrDebug();
1932  }
1933  if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1934  int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1935  TraceMemRd(addr, *ptr);
1936  return *ptr;
1937  }
1938  PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1939  reinterpret_cast<intptr_t>(instr));
1940  DieOrDebug();
1941  return 0;
1942 }
1943 
1944 
1945 void Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) {
1946  if (addr >= 0 && addr < 0x400) {
1947  // This has to be a nullptr-dereference, drop into debugger.
1948  PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
1949  "\n",
1950  addr, reinterpret_cast<intptr_t>(instr));
1951  DieOrDebug();
1952  }
1953  if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1954  TraceMemWr(addr, value, DWORD);
1955  int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1956  *ptr = value;
1957  return;
1958  }
1959  PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
1960  reinterpret_cast<intptr_t>(instr));
1961  DieOrDebug();
1962 }
1963 
1964 
1965 double Simulator::ReadD(int64_t addr, Instruction* instr) {
1966  if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1967  double* ptr = reinterpret_cast<double*>(addr);
1968  return *ptr;
1969  }
1970  PrintF("Unaligned (double) read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n",
1971  addr, reinterpret_cast<intptr_t>(instr));
1972  base::OS::Abort();
1973  return 0;
1974 }
1975 
1976 
1977 void Simulator::WriteD(int64_t addr, double value, Instruction* instr) {
1978  if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1979  double* ptr = reinterpret_cast<double*>(addr);
1980  *ptr = value;
1981  return;
1982  }
1983  PrintF("Unaligned (double) write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR
1984  "\n",
1985  addr, reinterpret_cast<intptr_t>(instr));
1986  DieOrDebug();
1987 }
1988 
1989 
1990 uint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) {
1991  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
1992  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1993  TraceMemRd(addr, static_cast<int64_t>(*ptr));
1994  return *ptr;
1995  }
1996  PrintF("Unaligned unsigned halfword read at 0x%08" PRIx64
1997  " , pc=0x%08" V8PRIxPTR "\n",
1998  addr, reinterpret_cast<intptr_t>(instr));
1999  DieOrDebug();
2000  return 0;
2001 }
2002 
2003 
2004 int16_t Simulator::ReadH(int64_t addr, Instruction* instr) {
2005  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
2006  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
2007  TraceMemRd(addr, static_cast<int64_t>(*ptr));
2008  return *ptr;
2009  }
2010  PrintF("Unaligned signed halfword read at 0x%08" PRIx64
2011  " , pc=0x%08" V8PRIxPTR "\n",
2012  addr, reinterpret_cast<intptr_t>(instr));
2013  DieOrDebug();
2014  return 0;
2015 }
2016 
2017 
2018 void Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) {
2019  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
2020  TraceMemWr(addr, value, HALF);
2021  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
2022  *ptr = value;
2023  return;
2024  }
2025  PrintF("Unaligned unsigned halfword write at 0x%08" PRIx64
2026  " , pc=0x%08" V8PRIxPTR "\n",
2027  addr, reinterpret_cast<intptr_t>(instr));
2028  DieOrDebug();
2029 }
2030 
2031 
2032 void Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) {
2033  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
2034  TraceMemWr(addr, value, HALF);
2035  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
2036  *ptr = value;
2037  return;
2038  }
2039  PrintF("Unaligned halfword write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR
2040  "\n",
2041  addr, reinterpret_cast<intptr_t>(instr));
2042  DieOrDebug();
2043 }
2044 
2045 
2046 uint32_t Simulator::ReadBU(int64_t addr) {
2047  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
2048  TraceMemRd(addr, static_cast<int64_t>(*ptr));
2049  return *ptr & 0xFF;
2050 }
2051 
2052 
2053 int32_t Simulator::ReadB(int64_t addr) {
2054  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
2055  TraceMemRd(addr, static_cast<int64_t>(*ptr));
2056  return *ptr;
2057 }
2058 
2059 
2060 void Simulator::WriteB(int64_t addr, uint8_t value) {
2061  TraceMemWr(addr, value, BYTE);
2062  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
2063  *ptr = value;
2064 }
2065 
2066 
2067 void Simulator::WriteB(int64_t addr, int8_t value) {
2068  TraceMemWr(addr, value, BYTE);
2069  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
2070  *ptr = value;
2071 }
2072 
2073 template <typename T>
2074 T Simulator::ReadMem(int64_t addr, Instruction* instr) {
2075  int alignment_mask = (1 << sizeof(T)) - 1;
2076  if ((addr & alignment_mask) == 0 || kArchVariant == kMips64r6) {
2077  T* ptr = reinterpret_cast<T*>(addr);
2078  TraceMemRd(addr, *ptr);
2079  return *ptr;
2080  }
2081  PrintF("Unaligned read of type sizeof(%ld) at 0x%08lx, pc=0x%08" V8PRIxPTR
2082  "\n",
2083  sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
2084  base::OS::Abort();
2085  return 0;
2086 }
2087 
2088 template <typename T>
2089 void Simulator::WriteMem(int64_t addr, T value, Instruction* instr) {
2090  int alignment_mask = (1 << sizeof(T)) - 1;
2091  if ((addr & alignment_mask) == 0 || kArchVariant == kMips64r6) {
2092  T* ptr = reinterpret_cast<T*>(addr);
2093  *ptr = value;
2094  TraceMemWr(addr, value);
2095  return;
2096  }
2097  PrintF("Unaligned write of type sizeof(%ld) at 0x%08lx, pc=0x%08" V8PRIxPTR
2098  "\n",
2099  sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
2100  base::OS::Abort();
2101 }
2102 
2103 // Returns the limit of the stack area to enable checking for stack overflows.
2104 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
2105  // The simulator uses a separate JS stack. If we have exhausted the C stack,
2106  // we also drop down the JS limit to reflect the exhaustion on the JS stack.
2107  if (GetCurrentStackPosition() < c_limit) {
2108  return reinterpret_cast<uintptr_t>(get_sp());
2109  }
2110 
2111  // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
2112  // to prevent overrunning the stack when pushing values.
2113  return reinterpret_cast<uintptr_t>(stack_) + 1024;
2114 }
2115 
2116 
2117 // Unsupported instructions use Format to print an error and stop execution.
2118 void Simulator::Format(Instruction* instr, const char* format) {
2119  PrintF("Simulator found unsupported instruction:\n 0x%08" PRIxPTR " : %s\n",
2120  reinterpret_cast<intptr_t>(instr), format);
2121  UNIMPLEMENTED_MIPS();
2122 }
2123 
2124 
2125 // Calls into the V8 runtime are based on this very simple interface.
2126 // Note: To be able to return two values from some calls the code in runtime.cc
2127 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
2128 // 64-bit value. With the code below we assume that all runtime calls return
2129 // 64 bits of result. If they don't, the v1 result register contains a bogus
2130 // value, which is fine because it is caller-saved.
2131 
2132 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, int64_t arg1,
2133  int64_t arg2, int64_t arg3,
2134  int64_t arg4, int64_t arg5,
2135  int64_t arg6, int64_t arg7,
2136  int64_t arg8);
2137 
2138 // These prototypes handle the four types of FP calls.
2139 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
2140 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
2141 typedef double (*SimulatorRuntimeFPCall)(double darg0);
2142 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
2143 
2144 // This signature supports direct call in to API function native callback
2145 // (refer to InvocationCallback in v8.h).
2146 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
2147 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
2148 
2149 // This signature supports direct call to accessor getter callback.
2150 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
2151 typedef void (*SimulatorRuntimeProfilingGetterCall)(
2152  int64_t arg0, int64_t arg1, void* arg2);
2153 
2154 // Software interrupt instructions are used by the simulator to call into the
2155 // C-based V8 runtime. They are also used for debugging with simulator.
2156 void Simulator::SoftwareInterrupt() {
2157  // There are several instructions that could get us here,
2158  // the break_ instruction, or several variants of traps. All
2159  // Are "SPECIAL" class opcode, and are distinuished by function.
2160  int32_t func = instr_.FunctionFieldRaw();
2161  uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1;
2162  // We first check if we met a call_rt_redirected.
2163  if (instr_.InstructionBits() == rtCallRedirInstr) {
2164  Redirection* redirection = Redirection::FromInstruction(instr_.instr());
2165 
2166  int64_t* stack_pointer = reinterpret_cast<int64_t*>(get_register(sp));
2167 
2168  int64_t arg0 = get_register(a0);
2169  int64_t arg1 = get_register(a1);
2170  int64_t arg2 = get_register(a2);
2171  int64_t arg3 = get_register(a3);
2172  int64_t arg4 = get_register(a4);
2173  int64_t arg5 = get_register(a5);
2174  int64_t arg6 = get_register(a6);
2175  int64_t arg7 = get_register(a7);
2176  int64_t arg8 = stack_pointer[0];
2177  STATIC_ASSERT(kMaxCParameters == 9);
2178 
2179  bool fp_call =
2180  (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
2181  (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
2182  (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
2183  (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
2184 
2185  if (!IsMipsSoftFloatABI) {
2186  // With the hard floating point calling convention, double
2187  // arguments are passed in FPU registers. Fetch the arguments
2188  // from there and call the builtin using soft floating point
2189  // convention.
2190  switch (redirection->type()) {
2191  case ExternalReference::BUILTIN_FP_FP_CALL:
2192  case ExternalReference::BUILTIN_COMPARE_CALL:
2193  arg0 = get_fpu_register(f12);
2194  arg1 = get_fpu_register(f13);
2195  arg2 = get_fpu_register(f14);
2196  arg3 = get_fpu_register(f15);
2197  break;
2198  case ExternalReference::BUILTIN_FP_CALL:
2199  arg0 = get_fpu_register(f12);
2200  arg1 = get_fpu_register(f13);
2201  break;
2202  case ExternalReference::BUILTIN_FP_INT_CALL:
2203  arg0 = get_fpu_register(f12);
2204  arg1 = get_fpu_register(f13);
2205  arg2 = get_register(a2);
2206  break;
2207  default:
2208  break;
2209  }
2210  }
2211 
2212  // This is dodgy but it works because the C entry stubs are never moved.
2213  // See comment in codegen-arm.cc and bug 1242173.
2214  int64_t saved_ra = get_register(ra);
2215 
2216  intptr_t external =
2217  reinterpret_cast<intptr_t>(redirection->external_function());
2218 
2219  // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
2220  // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
2221  // simulator. Soft-float has additional abstraction of ExternalReference,
2222  // to support serialization.
2223  if (fp_call) {
2224  double dval0, dval1; // one or two double parameters
2225  int32_t ival; // zero or one integer parameters
2226  int64_t iresult = 0; // integer return value
2227  double dresult = 0; // double return value
2228  GetFpArgs(&dval0, &dval1, &ival);
2229  SimulatorRuntimeCall generic_target =
2230  reinterpret_cast<SimulatorRuntimeCall>(external);
2231  if (::v8::internal::FLAG_trace_sim) {
2232  switch (redirection->type()) {
2233  case ExternalReference::BUILTIN_FP_FP_CALL:
2234  case ExternalReference::BUILTIN_COMPARE_CALL:
2235  PrintF("Call to host function at %p with args %f, %f",
2236  reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2237  dval0, dval1);
2238  break;
2239  case ExternalReference::BUILTIN_FP_CALL:
2240  PrintF("Call to host function at %p with arg %f",
2241  reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2242  dval0);
2243  break;
2244  case ExternalReference::BUILTIN_FP_INT_CALL:
2245  PrintF("Call to host function at %p with args %f, %d",
2246  reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2247  dval0, ival);
2248  break;
2249  default:
2250  UNREACHABLE();
2251  break;
2252  }
2253  }
2254  switch (redirection->type()) {
2255  case ExternalReference::BUILTIN_COMPARE_CALL: {
2256  SimulatorRuntimeCompareCall target =
2257  reinterpret_cast<SimulatorRuntimeCompareCall>(external);
2258  iresult = target(dval0, dval1);
2259  set_register(v0, static_cast<int64_t>(iresult));
2260  // set_register(v1, static_cast<int64_t>(iresult >> 32));
2261  break;
2262  }
2263  case ExternalReference::BUILTIN_FP_FP_CALL: {
2264  SimulatorRuntimeFPFPCall target =
2265  reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
2266  dresult = target(dval0, dval1);
2267  SetFpResult(dresult);
2268  break;
2269  }
2270  case ExternalReference::BUILTIN_FP_CALL: {
2271  SimulatorRuntimeFPCall target =
2272  reinterpret_cast<SimulatorRuntimeFPCall>(external);
2273  dresult = target(dval0);
2274  SetFpResult(dresult);
2275  break;
2276  }
2277  case ExternalReference::BUILTIN_FP_INT_CALL: {
2278  SimulatorRuntimeFPIntCall target =
2279  reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
2280  dresult = target(dval0, ival);
2281  SetFpResult(dresult);
2282  break;
2283  }
2284  default:
2285  UNREACHABLE();
2286  break;
2287  }
2288  if (::v8::internal::FLAG_trace_sim) {
2289  switch (redirection->type()) {
2290  case ExternalReference::BUILTIN_COMPARE_CALL:
2291  PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
2292  break;
2293  case ExternalReference::BUILTIN_FP_FP_CALL:
2294  case ExternalReference::BUILTIN_FP_CALL:
2295  case ExternalReference::BUILTIN_FP_INT_CALL:
2296  PrintF("Returned %f\n", dresult);
2297  break;
2298  default:
2299  UNREACHABLE();
2300  break;
2301  }
2302  }
2303  } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
2304  if (::v8::internal::FLAG_trace_sim) {
2305  PrintF("Call to host function at %p args %08" PRIx64 " \n",
2306  reinterpret_cast<void*>(external), arg0);
2307  }
2308  SimulatorRuntimeDirectApiCall target =
2309  reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
2310  target(arg0);
2311  } else if (
2312  redirection->type() == ExternalReference::PROFILING_API_CALL) {
2313  if (::v8::internal::FLAG_trace_sim) {
2314  PrintF("Call to host function at %p args %08" PRIx64 " %08" PRIx64
2315  " \n",
2316  reinterpret_cast<void*>(external), arg0, arg1);
2317  }
2318  SimulatorRuntimeProfilingApiCall target =
2319  reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
2320  target(arg0, Redirection::ReverseRedirection(arg1));
2321  } else if (
2322  redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
2323  if (::v8::internal::FLAG_trace_sim) {
2324  PrintF("Call to host function at %p args %08" PRIx64 " %08" PRIx64
2325  " \n",
2326  reinterpret_cast<void*>(external), arg0, arg1);
2327  }
2328  SimulatorRuntimeDirectGetterCall target =
2329  reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
2330  target(arg0, arg1);
2331  } else if (
2332  redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
2333  if (::v8::internal::FLAG_trace_sim) {
2334  PrintF("Call to host function at %p args %08" PRIx64 " %08" PRIx64
2335  " %08" PRIx64 " \n",
2336  reinterpret_cast<void*>(external), arg0, arg1, arg2);
2337  }
2338  SimulatorRuntimeProfilingGetterCall target =
2339  reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
2340  target(arg0, arg1, Redirection::ReverseRedirection(arg2));
2341  } else {
2342  DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
2343  redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
2344  SimulatorRuntimeCall target =
2345  reinterpret_cast<SimulatorRuntimeCall>(external);
2346  if (::v8::internal::FLAG_trace_sim) {
2347  PrintF(
2348  "Call to host function at %p "
2349  "args %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64
2350  " , %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64
2351  " , %08" PRIx64 " \n",
2352  reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2,
2353  arg3, arg4, arg5, arg6, arg7, arg8);
2354  }
2355  ObjectPair result =
2356  target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
2357  set_register(v0, (int64_t)(result.x));
2358  set_register(v1, (int64_t)(result.y));
2359  }
2360  if (::v8::internal::FLAG_trace_sim) {
2361  PrintF("Returned %08" PRIx64 " : %08" PRIx64 " \n", get_register(v1),
2362  get_register(v0));
2363  }
2364  set_register(ra, saved_ra);
2365  set_pc(get_register(ra));
2366 
2367  } else if (func == BREAK && code <= kMaxStopCode) {
2368  if (IsWatchpoint(code)) {
2369  PrintWatchpoint(code);
2370  } else {
2371  IncreaseStopCounter(code);
2372  HandleStop(code, instr_.instr());
2373  }
2374  } else {
2375  // All remaining break_ codes, and all traps are handled here.
2376  MipsDebugger dbg(this);
2377  dbg.Debug();
2378  }
2379 }
2380 
2381 
2382 // Stop helper functions.
2383 bool Simulator::IsWatchpoint(uint64_t code) {
2384  return (code <= kMaxWatchpointCode);
2385 }
2386 
2387 
2388 void Simulator::PrintWatchpoint(uint64_t code) {
2389  MipsDebugger dbg(this);
2390  ++break_count_;
2391  PrintF("\n---- break %" PRId64 " marker: %3d (instr count: %8" PRId64
2392  " ) ----------"
2393  "----------------------------------",
2394  code, break_count_, icount_);
2395  dbg.PrintAllRegs(); // Print registers and continue running.
2396 }
2397 
2398 
2399 void Simulator::HandleStop(uint64_t code, Instruction* instr) {
2400  // Stop if it is enabled, otherwise go on jumping over the stop
2401  // and the message address.
2402  if (IsEnabledStop(code)) {
2403  MipsDebugger dbg(this);
2404  dbg.Stop(instr);
2405  }
2406 }
2407 
2408 
2409 bool Simulator::IsStopInstruction(Instruction* instr) {
2410  int32_t func = instr->FunctionFieldRaw();
2411  uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
2412  return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
2413 }
2414 
2415 
2416 bool Simulator::IsEnabledStop(uint64_t code) {
2417  DCHECK_LE(code, kMaxStopCode);
2418  DCHECK_GT(code, kMaxWatchpointCode);
2419  return !(watched_stops_[code].count & kStopDisabledBit);
2420 }
2421 
2422 
2423 void Simulator::EnableStop(uint64_t code) {
2424  if (!IsEnabledStop(code)) {
2425  watched_stops_[code].count &= ~kStopDisabledBit;
2426  }
2427 }
2428 
2429 
2430 void Simulator::DisableStop(uint64_t code) {
2431  if (IsEnabledStop(code)) {
2432  watched_stops_[code].count |= kStopDisabledBit;
2433  }
2434 }
2435 
2436 
2437 void Simulator::IncreaseStopCounter(uint64_t code) {
2438  DCHECK_LE(code, kMaxStopCode);
2439  if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
2440  PrintF("Stop counter for code %" PRId64
2441  " has overflowed.\n"
2442  "Enabling this code and reseting the counter to 0.\n",
2443  code);
2444  watched_stops_[code].count = 0;
2445  EnableStop(code);
2446  } else {
2447  watched_stops_[code].count++;
2448  }
2449 }
2450 
2451 
2452 // Print a stop status.
2453 void Simulator::PrintStopInfo(uint64_t code) {
2454  if (code <= kMaxWatchpointCode) {
2455  PrintF("That is a watchpoint, not a stop.\n");
2456  return;
2457  } else if (code > kMaxStopCode) {
2458  PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
2459  return;
2460  }
2461  const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
2462  int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2463  // Don't print the state of unused breakpoints.
2464  if (count != 0) {
2465  if (watched_stops_[code].desc) {
2466  PrintF("stop %" PRId64 " - 0x%" PRIx64 " : \t%s, \tcounter = %i, \t%s\n",
2467  code, code, state, count, watched_stops_[code].desc);
2468  } else {
2469  PrintF("stop %" PRId64 " - 0x%" PRIx64 " : \t%s, \tcounter = %i\n", code,
2470  code, state, count);
2471  }
2472  }
2473 }
2474 
2475 
2476 void Simulator::SignalException(Exception e) {
2477  FATAL("Error: Exception %i raised.", static_cast<int>(e));
2478 }
2479 
2480 // Min/Max template functions for Double and Single arguments.
2481 
2482 template <typename T>
2483 static T FPAbs(T a);
2484 
2485 template <>
2486 double FPAbs<double>(double a) {
2487  return fabs(a);
2488 }
2489 
2490 template <>
2491 float FPAbs<float>(float a) {
2492  return fabsf(a);
2493 }
2494 
2495 template <typename T>
2496 static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind kind, T& result) {
2497  if (std::isnan(a) && std::isnan(b)) {
2498  result = a;
2499  } else if (std::isnan(a)) {
2500  result = b;
2501  } else if (std::isnan(b)) {
2502  result = a;
2503  } else if (b == a) {
2504  // Handle -0.0 == 0.0 case.
2505  // std::signbit() returns int 0 or 1 so subtracting MaxMinKind::kMax
2506  // negates the result.
2507  result = std::signbit(b) - static_cast<int>(kind) ? b : a;
2508  } else {
2509  return false;
2510  }
2511  return true;
2512 }
2513 
2514 template <typename T>
2515 static T FPUMin(T a, T b) {
2516  T result;
2517  if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2518  return result;
2519  } else {
2520  return b < a ? b : a;
2521  }
2522 }
2523 
2524 template <typename T>
2525 static T FPUMax(T a, T b) {
2526  T result;
2527  if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, result)) {
2528  return result;
2529  } else {
2530  return b > a ? b : a;
2531  }
2532 }
2533 
2534 template <typename T>
2535 static T FPUMinA(T a, T b) {
2536  T result;
2537  if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2538  if (FPAbs(a) < FPAbs(b)) {
2539  result = a;
2540  } else if (FPAbs(b) < FPAbs(a)) {
2541  result = b;
2542  } else {
2543  result = a < b ? a : b;
2544  }
2545  }
2546  return result;
2547 }
2548 
2549 template <typename T>
2550 static T FPUMaxA(T a, T b) {
2551  T result;
2552  if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2553  if (FPAbs(a) > FPAbs(b)) {
2554  result = a;
2555  } else if (FPAbs(b) > FPAbs(a)) {
2556  result = b;
2557  } else {
2558  result = a > b ? a : b;
2559  }
2560  }
2561  return result;
2562 }
2563 
2564 enum class KeepSign : bool { no = false, yes };
2565 
2566 template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
2567  int>::type = 0>
2568 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) {
2569  DCHECK(std::isnan(arg));
2570  T qNaN = std::numeric_limits<T>::quiet_NaN();
2571  if (keepSign == KeepSign::yes) {
2572  return std::copysign(qNaN, result);
2573  }
2574  return qNaN;
2575 }
2576 
2577 template <typename T>
2578 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
2579  if (std::isnan(first)) {
2580  return FPUCanonalizeNaNArg(result, first, keepSign);
2581  }
2582  return result;
2583 }
2584 
2585 template <typename T, typename... Args>
2586 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
2587  if (std::isnan(first)) {
2588  return FPUCanonalizeNaNArg(result, first, keepSign);
2589  }
2590  return FPUCanonalizeNaNArgs(result, keepSign, args...);
2591 }
2592 
2593 template <typename Func, typename T, typename... Args>
2594 T FPUCanonalizeOperation(Func f, T first, Args... args) {
2595  return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
2596 }
2597 
2598 template <typename Func, typename T, typename... Args>
2599 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
2600  T result = f(first, args...);
2601  if (std::isnan(result)) {
2602  result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
2603  }
2604  return result;
2605 }
2606 
2607 // Handle execution based on instruction types.
2608 
2609 void Simulator::DecodeTypeRegisterSRsType() {
2610  float fs, ft, fd;
2611  fs = get_fpu_register_float(fs_reg());
2612  ft = get_fpu_register_float(ft_reg());
2613  fd = get_fpu_register_float(fd_reg());
2614  int32_t ft_int = bit_cast<int32_t>(ft);
2615  int32_t fd_int = bit_cast<int32_t>(fd);
2616  uint32_t cc, fcsr_cc;
2617  cc = instr_.FCccValue();
2618  fcsr_cc = get_fcsr_condition_bit(cc);
2619  switch (instr_.FunctionFieldRaw()) {
2620  case RINT: {
2621  DCHECK_EQ(kArchVariant, kMips64r6);
2622  float result, temp_result;
2623  double temp;
2624  float upper = std::ceil(fs);
2625  float lower = std::floor(fs);
2626  switch (get_fcsr_rounding_mode()) {
2627  case kRoundToNearest:
2628  if (upper - fs < fs - lower) {
2629  result = upper;
2630  } else if (upper - fs > fs - lower) {
2631  result = lower;
2632  } else {
2633  temp_result = upper / 2;
2634  float reminder = modf(temp_result, &temp);
2635  if (reminder == 0) {
2636  result = upper;
2637  } else {
2638  result = lower;
2639  }
2640  }
2641  break;
2642  case kRoundToZero:
2643  result = (fs > 0 ? lower : upper);
2644  break;
2645  case kRoundToPlusInf:
2646  result = upper;
2647  break;
2648  case kRoundToMinusInf:
2649  result = lower;
2650  break;
2651  }
2652  SetFPUFloatResult(fd_reg(), result);
2653  if (result != fs) {
2654  set_fcsr_bit(kFCSRInexactFlagBit, true);
2655  }
2656  break;
2657  }
2658  case ADD_S:
2659  SetFPUFloatResult(
2660  fd_reg(),
2661  FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; },
2662  fs, ft));
2663  break;
2664  case SUB_S:
2665  SetFPUFloatResult(
2666  fd_reg(),
2667  FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; },
2668  fs, ft));
2669  break;
2670  case MADDF_S:
2671  DCHECK_EQ(kArchVariant, kMips64r6);
2672  SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd));
2673  break;
2674  case MSUBF_S:
2675  DCHECK_EQ(kArchVariant, kMips64r6);
2676  SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd));
2677  break;
2678  case MUL_S:
2679  SetFPUFloatResult(
2680  fd_reg(),
2681  FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; },
2682  fs, ft));
2683  break;
2684  case DIV_S:
2685  SetFPUFloatResult(
2686  fd_reg(),
2687  FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; },
2688  fs, ft));
2689  break;
2690  case ABS_S:
2691  SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
2692  [](float fs) { return FPAbs(fs); }, fs));
2693  break;
2694  case MOV_S:
2695  SetFPUFloatResult(fd_reg(), fs);
2696  break;
2697  case NEG_S:
2698  SetFPUFloatResult(fd_reg(),
2699  FPUCanonalizeOperation([](float src) { return -src; },
2700  KeepSign::yes, fs));
2701  break;
2702  case SQRT_S:
2703  SetFPUFloatResult(
2704  fd_reg(),
2705  FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs));
2706  break;
2707  case RSQRT_S:
2708  SetFPUFloatResult(
2709  fd_reg(), FPUCanonalizeOperation(
2710  [](float src) { return 1.0 / std::sqrt(src); }, fs));
2711  break;
2712  case RECIP_S:
2713  SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
2714  [](float src) { return 1.0 / src; }, fs));
2715  break;
2716  case C_F_D:
2717  set_fcsr_bit(fcsr_cc, false);
2718  TraceRegWr(test_fcsr_bit(fcsr_cc));
2719  break;
2720  case C_UN_D:
2721  set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2722  TraceRegWr(test_fcsr_bit(fcsr_cc));
2723  break;
2724  case C_EQ_D:
2725  set_fcsr_bit(fcsr_cc, (fs == ft));
2726  TraceRegWr(test_fcsr_bit(fcsr_cc));
2727  break;
2728  case C_UEQ_D:
2729  set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2730  TraceRegWr(test_fcsr_bit(fcsr_cc));
2731  break;
2732  case C_OLT_D:
2733  set_fcsr_bit(fcsr_cc, (fs < ft));
2734  TraceRegWr(test_fcsr_bit(fcsr_cc));
2735  break;
2736  case C_ULT_D:
2737  set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2738  TraceRegWr(test_fcsr_bit(fcsr_cc));
2739  break;
2740  case C_OLE_D:
2741  set_fcsr_bit(fcsr_cc, (fs <= ft));
2742  TraceRegWr(test_fcsr_bit(fcsr_cc));
2743  break;
2744  case C_ULE_D:
2745  set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2746  TraceRegWr(test_fcsr_bit(fcsr_cc));
2747  break;
2748  case CVT_D_S:
2749  SetFPUDoubleResult(fd_reg(), static_cast<double>(fs));
2750  break;
2751  case CLASS_S: { // Mips64r6 instruction
2752  // Convert float input to uint32_t for easier bit manipulation
2753  uint32_t classed = bit_cast<uint32_t>(fs);
2754 
2755  // Extracting sign, exponent and mantissa from the input float
2756  uint32_t sign = (classed >> 31) & 1;
2757  uint32_t exponent = (classed >> 23) & 0x000000FF;
2758  uint32_t mantissa = classed & 0x007FFFFF;
2759  uint32_t result;
2760  float fResult;
2761 
2762  // Setting flags if input float is negative infinity,
2763  // positive infinity, negative zero or positive zero
2764  bool negInf = (classed == 0xFF800000);
2765  bool posInf = (classed == 0x7F800000);
2766  bool negZero = (classed == 0x80000000);
2767  bool posZero = (classed == 0x00000000);
2768 
2769  bool signalingNan;
2770  bool quietNan;
2771  bool negSubnorm;
2772  bool posSubnorm;
2773  bool negNorm;
2774  bool posNorm;
2775 
2776  // Setting flags if float is NaN
2777  signalingNan = false;
2778  quietNan = false;
2779  if (!negInf && !posInf && (exponent == 0xFF)) {
2780  quietNan = ((mantissa & 0x00200000) == 0) &&
2781  ((mantissa & (0x00200000 - 1)) == 0);
2782  signalingNan = !quietNan;
2783  }
2784 
2785  // Setting flags if float is subnormal number
2786  posSubnorm = false;
2787  negSubnorm = false;
2788  if ((exponent == 0) && (mantissa != 0)) {
2789  DCHECK(sign == 0 || sign == 1);
2790  posSubnorm = (sign == 0);
2791  negSubnorm = (sign == 1);
2792  }
2793 
2794  // Setting flags if float is normal number
2795  posNorm = false;
2796  negNorm = false;
2797  if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
2798  !quietNan && !negZero && !posZero) {
2799  DCHECK(sign == 0 || sign == 1);
2800  posNorm = (sign == 0);
2801  negNorm = (sign == 1);
2802  }
2803 
2804  // Calculating result according to description of CLASS.S instruction
2805  result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
2806  (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
2807  (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
2808 
2809  DCHECK_NE(result, 0);
2810 
2811  fResult = bit_cast<float>(result);
2812  SetFPUFloatResult(fd_reg(), fResult);
2813  break;
2814  }
2815  case CVT_L_S: {
2816  float rounded;
2817  int64_t result;
2818  round64_according_to_fcsr(fs, rounded, result, fs);
2819  SetFPUResult(fd_reg(), result);
2820  if (set_fcsr_round64_error(fs, rounded)) {
2821  set_fpu_register_invalid_result64(fs, rounded);
2822  }
2823  break;
2824  }
2825  case CVT_W_S: {
2826  float rounded;
2827  int32_t result;
2828  round_according_to_fcsr(fs, rounded, result, fs);
2829  SetFPUWordResult(fd_reg(), result);
2830  if (set_fcsr_round_error(fs, rounded)) {
2831  set_fpu_register_word_invalid_result(fs, rounded);
2832  }
2833  break;
2834  }
2835  case TRUNC_W_S: { // Truncate single to word (round towards 0).
2836  float rounded = trunc(fs);
2837  int32_t result = static_cast<int32_t>(rounded);
2838  SetFPUWordResult(fd_reg(), result);
2839  if (set_fcsr_round_error(fs, rounded)) {
2840  set_fpu_register_word_invalid_result(fs, rounded);
2841  }
2842  } break;
2843  case TRUNC_L_S: { // Mips64r2 instruction.
2844  float rounded = trunc(fs);
2845  int64_t result = static_cast<int64_t>(rounded);
2846  SetFPUResult(fd_reg(), result);
2847  if (set_fcsr_round64_error(fs, rounded)) {
2848  set_fpu_register_invalid_result64(fs, rounded);
2849  }
2850  break;
2851  }
2852  case ROUND_W_S: {
2853  float rounded = std::floor(fs + 0.5);
2854  int32_t result = static_cast<int32_t>(rounded);
2855  if ((result & 1) != 0 && result - fs == 0.5) {
2856  // If the number is halfway between two integers,
2857  // round to the even one.
2858  result--;
2859  }
2860  SetFPUWordResult(fd_reg(), result);
2861  if (set_fcsr_round_error(fs, rounded)) {
2862  set_fpu_register_word_invalid_result(fs, rounded);
2863  }
2864  break;
2865  }
2866  case ROUND_L_S: { // Mips64r2 instruction.
2867  float rounded = std::floor(fs + 0.5);
2868  int64_t result = static_cast<int64_t>(rounded);
2869  if ((result & 1) != 0 && result - fs == 0.5) {
2870  // If the number is halfway between two integers,
2871  // round to the even one.
2872  result--;
2873  }
2874  int64_t i64 = static_cast<int64_t>(result);
2875  SetFPUResult(fd_reg(), i64);
2876  if (set_fcsr_round64_error(fs, rounded)) {
2877  set_fpu_register_invalid_result64(fs, rounded);
2878  }
2879  break;
2880  }
2881  case FLOOR_L_S: { // Mips64r2 instruction.
2882  float rounded = floor(fs);
2883  int64_t result = static_cast<int64_t>(rounded);
2884  SetFPUResult(fd_reg(), result);
2885  if (set_fcsr_round64_error(fs, rounded)) {
2886  set_fpu_register_invalid_result64(fs, rounded);
2887  }
2888  break;
2889  }
2890  case FLOOR_W_S: // Round double to word towards negative infinity.
2891  {
2892  float rounded = std::floor(fs);
2893  int32_t result = static_cast<int32_t>(rounded);
2894  SetFPUWordResult(fd_reg(), result);
2895  if (set_fcsr_round_error(fs, rounded)) {
2896  set_fpu_register_word_invalid_result(fs, rounded);
2897  }
2898  } break;
2899  case CEIL_W_S: // Round double to word towards positive infinity.
2900  {
2901  float rounded = std::ceil(fs);
2902  int32_t result = static_cast<int32_t>(rounded);
2903  SetFPUWordResult(fd_reg(), result);
2904  if (set_fcsr_round_error(fs, rounded)) {
2905  set_fpu_register_invalid_result(fs, rounded);
2906  }
2907  } break;
2908  case CEIL_L_S: { // Mips64r2 instruction.
2909  float rounded = ceil(fs);
2910  int64_t result = static_cast<int64_t>(rounded);
2911  SetFPUResult(fd_reg(), result);
2912  if (set_fcsr_round64_error(fs, rounded)) {
2913  set_fpu_register_invalid_result64(fs, rounded);
2914  }
2915  break;
2916  }
2917  case MINA:
2918  DCHECK_EQ(kArchVariant, kMips64r6);
2919  SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs));
2920  break;
2921  case MAXA:
2922  DCHECK_EQ(kArchVariant, kMips64r6);
2923  SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs));
2924  break;
2925  case MIN:
2926  DCHECK_EQ(kArchVariant, kMips64r6);
2927  SetFPUFloatResult(fd_reg(), FPUMin(ft, fs));
2928  break;
2929  case MAX:
2930  DCHECK_EQ(kArchVariant, kMips64r6);
2931  SetFPUFloatResult(fd_reg(), FPUMax(ft, fs));
2932  break;
2933  case SEL:
2934  DCHECK_EQ(kArchVariant, kMips64r6);
2935  SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
2936  break;
2937  case SELEQZ_C:
2938  DCHECK_EQ(kArchVariant, kMips64r6);
2939  SetFPUFloatResult(
2940  fd_reg(),
2941  (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0);
2942  break;
2943  case SELNEZ_C:
2944  DCHECK_EQ(kArchVariant, kMips64r6);
2945  SetFPUFloatResult(
2946  fd_reg(),
2947  (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0);
2948  break;
2949  case MOVZ_C: {
2950  DCHECK_EQ(kArchVariant, kMips64r2);
2951  if (rt() == 0) {
2952  SetFPUFloatResult(fd_reg(), fs);
2953  }
2954  break;
2955  }
2956  case MOVN_C: {
2957  DCHECK_EQ(kArchVariant, kMips64r2);
2958  if (rt() != 0) {
2959  SetFPUFloatResult(fd_reg(), fs);
2960  }
2961  break;
2962  }
2963  case MOVF: {
2964  // Same function field for MOVT.D and MOVF.D
2965  uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
2966  ft_cc = get_fcsr_condition_bit(ft_cc);
2967 
2968  if (instr_.Bit(16)) { // Read Tf bit.
2969  // MOVT.D
2970  if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
2971  } else {
2972  // MOVF.D
2973  if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
2974  }
2975  break;
2976  }
2977  default:
2978  // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2979  // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2980  UNREACHABLE();
2981  }
2982 }
2983 
2984 
2985 void Simulator::DecodeTypeRegisterDRsType() {
2986  double ft, fs, fd;
2987  uint32_t cc, fcsr_cc;
2988  fs = get_fpu_register_double(fs_reg());
2989  ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg())
2990  : 0.0;
2991  fd = get_fpu_register_double(fd_reg());
2992  cc = instr_.FCccValue();
2993  fcsr_cc = get_fcsr_condition_bit(cc);
2994  int64_t ft_int = bit_cast<int64_t>(ft);
2995  int64_t fd_int = bit_cast<int64_t>(fd);
2996  switch (instr_.FunctionFieldRaw()) {
2997  case RINT: {
2998  DCHECK_EQ(kArchVariant, kMips64r6);
2999  double result, temp, temp_result;
3000  double upper = std::ceil(fs);
3001  double lower = std::floor(fs);
3002  switch (get_fcsr_rounding_mode()) {
3003  case kRoundToNearest:
3004  if (upper - fs < fs - lower) {
3005  result = upper;
3006  } else if (upper - fs > fs - lower) {
3007  result = lower;
3008  } else {
3009  temp_result = upper / 2;
3010  double reminder = modf(temp_result, &temp);
3011  if (reminder == 0) {
3012  result = upper;
3013  } else {
3014  result = lower;
3015  }
3016  }
3017  break;
3018  case kRoundToZero:
3019  result = (fs > 0 ? lower : upper);
3020  break;
3021  case kRoundToPlusInf:
3022  result = upper;
3023  break;
3024  case kRoundToMinusInf:
3025  result = lower;
3026  break;
3027  }
3028  SetFPUDoubleResult(fd_reg(), result);
3029  if (result != fs) {
3030  set_fcsr_bit(kFCSRInexactFlagBit, true);
3031  }
3032  break;
3033  }
3034  case SEL:
3035  DCHECK_EQ(kArchVariant, kMips64r6);
3036  SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
3037  break;
3038  case SELEQZ_C:
3039  DCHECK_EQ(kArchVariant, kMips64r6);
3040  SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
3041  break;
3042  case SELNEZ_C:
3043  DCHECK_EQ(kArchVariant, kMips64r6);
3044  SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
3045  break;
3046  case MOVZ_C: {
3047  DCHECK_EQ(kArchVariant, kMips64r2);
3048  if (rt() == 0) {
3049  SetFPUDoubleResult(fd_reg(), fs);
3050  }
3051  break;
3052  }
3053  case MOVN_C: {
3054  DCHECK_EQ(kArchVariant, kMips64r2);
3055  if (rt() != 0) {
3056  SetFPUDoubleResult(fd_reg(), fs);
3057  }
3058  break;
3059  }
3060  case MOVF: {
3061  // Same function field for MOVT.D and MOVF.D
3062  uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
3063  ft_cc = get_fcsr_condition_bit(ft_cc);
3064  if (instr_.Bit(16)) { // Read Tf bit.
3065  // MOVT.D
3066  if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
3067  } else {
3068  // MOVF.D
3069  if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
3070  }
3071  break;
3072  }
3073  case MINA:
3074  DCHECK_EQ(kArchVariant, kMips64r6);
3075  SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs));
3076  break;
3077  case MAXA:
3078  DCHECK_EQ(kArchVariant, kMips64r6);
3079  SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs));
3080  break;
3081  case MIN:
3082  DCHECK_EQ(kArchVariant, kMips64r6);
3083  SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs));
3084  break;
3085  case MAX:
3086  DCHECK_EQ(kArchVariant, kMips64r6);
3087  SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs));
3088  break;
3089  case ADD_D:
3090  SetFPUDoubleResult(
3091  fd_reg(),
3092  FPUCanonalizeOperation(
3093  [](double lhs, double rhs) { return lhs + rhs; }, fs, ft));
3094  break;
3095  case SUB_D:
3096  SetFPUDoubleResult(
3097  fd_reg(),
3098  FPUCanonalizeOperation(
3099  [](double lhs, double rhs) { return lhs - rhs; }, fs, ft));
3100  break;
3101  case MADDF_D:
3102  DCHECK_EQ(kArchVariant, kMips64r6);
3103  SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd));
3104  break;
3105  case MSUBF_D:
3106  DCHECK_EQ(kArchVariant, kMips64r6);
3107  SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd));
3108  break;
3109  case MUL_D:
3110  SetFPUDoubleResult(
3111  fd_reg(),
3112  FPUCanonalizeOperation(
3113  [](double lhs, double rhs) { return lhs * rhs; }, fs, ft));
3114  break;
3115  case DIV_D:
3116  SetFPUDoubleResult(
3117  fd_reg(),
3118  FPUCanonalizeOperation(
3119  [](double lhs, double rhs) { return lhs / rhs; }, fs, ft));
3120  break;
3121  case ABS_D:
3122  SetFPUDoubleResult(
3123  fd_reg(),
3124  FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs));
3125  break;
3126  case MOV_D:
3127  SetFPUDoubleResult(fd_reg(), fs);
3128  break;
3129  case NEG_D:
3130  SetFPUDoubleResult(fd_reg(),
3131  FPUCanonalizeOperation([](double src) { return -src; },
3132  KeepSign::yes, fs));
3133  break;
3134  case SQRT_D:
3135  SetFPUDoubleResult(
3136  fd_reg(),
3137  FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs));
3138  break;
3139  case RSQRT_D:
3140  SetFPUDoubleResult(
3141  fd_reg(), FPUCanonalizeOperation(
3142  [](double fs) { return 1.0 / std::sqrt(fs); }, fs));
3143  break;
3144  case RECIP_D:
3145  SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation(
3146  [](double fs) { return 1.0 / fs; }, fs));
3147  break;
3148  case C_UN_D:
3149  set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
3150  TraceRegWr(test_fcsr_bit(fcsr_cc));
3151  break;
3152  case C_EQ_D:
3153  set_fcsr_bit(fcsr_cc, (fs == ft));
3154  TraceRegWr(test_fcsr_bit(fcsr_cc));
3155  break;
3156  case C_UEQ_D:
3157  set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
3158  TraceRegWr(test_fcsr_bit(fcsr_cc));
3159  break;
3160  case C_OLT_D:
3161  set_fcsr_bit(fcsr_cc, (fs < ft));
3162  TraceRegWr(test_fcsr_bit(fcsr_cc));
3163  break;
3164  case C_ULT_D:
3165  set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
3166  TraceRegWr(test_fcsr_bit(fcsr_cc));
3167  break;
3168  case C_OLE_D:
3169  set_fcsr_bit(fcsr_cc, (fs <= ft));
3170  TraceRegWr(test_fcsr_bit(fcsr_cc));
3171  break;
3172  case C_ULE_D:
3173  set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
3174  TraceRegWr(test_fcsr_bit(fcsr_cc));
3175  break;
3176  case CVT_W_D: { // Convert double to word.
3177  double rounded;
3178  int32_t result;
3179  round_according_to_fcsr(fs, rounded, result, fs);
3180  SetFPUWordResult(fd_reg(), result);
3181  if (set_fcsr_round_error(fs, rounded)) {
3182  set_fpu_register_word_invalid_result(fs, rounded);
3183  }
3184  break;
3185  }
3186  case ROUND_W_D: // Round double to word (round half to even).
3187  {
3188  double rounded = std::floor(fs + 0.5);
3189  int32_t result = static_cast<int32_t>(rounded);
3190  if ((result & 1) != 0 && result - fs == 0.5) {
3191  // If the number is halfway between two integers,
3192  // round to the even one.
3193  result--;
3194  }
3195  SetFPUWordResult(fd_reg(), result);
3196  if (set_fcsr_round_error(fs, rounded)) {
3197  set_fpu_register_invalid_result(fs, rounded);
3198  }
3199  } break;
3200  case TRUNC_W_D: // Truncate double to word (round towards 0).
3201  {
3202  double rounded = trunc(fs);
3203  int32_t result = static_cast<int32_t>(rounded);
3204  SetFPUWordResult(fd_reg(), result);
3205  if (set_fcsr_round_error(fs, rounded)) {
3206  set_fpu_register_invalid_result(fs, rounded);
3207  }
3208  } break;
3209  case FLOOR_W_D: // Round double to word towards negative infinity.
3210  {
3211  double rounded = std::floor(fs);
3212  int32_t result = static_cast<int32_t>(rounded);
3213  SetFPUWordResult(fd_reg(), result);
3214  if (set_fcsr_round_error(fs, rounded)) {
3215  set_fpu_register_invalid_result(fs, rounded);
3216  }
3217  } break;
3218  case CEIL_W_D: // Round double to word towards positive infinity.
3219  {
3220  double rounded = std::ceil(fs);
3221  int32_t result = static_cast<int32_t>(rounded);
3222  SetFPUWordResult2(fd_reg(), result);
3223  if (set_fcsr_round_error(fs, rounded)) {
3224  set_fpu_register_invalid_result(fs, rounded);
3225  }
3226  } break;
3227  case CVT_S_D: // Convert double to float (single).
3228  SetFPUFloatResult(fd_reg(), static_cast<float>(fs));
3229  break;
3230  case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word.
3231  double rounded;
3232  int64_t result;
3233  round64_according_to_fcsr(fs, rounded, result, fs);
3234  SetFPUResult(fd_reg(), result);
3235  if (set_fcsr_round64_error(fs, rounded)) {
3236  set_fpu_register_invalid_result64(fs, rounded);
3237  }
3238  break;
3239  }
3240  case ROUND_L_D: { // Mips64r2 instruction.
3241  double rounded = std::floor(fs + 0.5);
3242  int64_t result = static_cast<int64_t>(rounded);
3243  if ((result & 1) != 0 && result - fs == 0.5) {
3244  // If the number is halfway between two integers,
3245  // round to the even one.
3246  result--;
3247  }
3248  int64_t i64 = static_cast<int64_t>(result);
3249  SetFPUResult(fd_reg(), i64);
3250  if (set_fcsr_round64_error(fs, rounded)) {
3251  set_fpu_register_invalid_result64(fs, rounded);
3252  }
3253  break;
3254  }
3255  case TRUNC_L_D: { // Mips64r2 instruction.
3256  double rounded = trunc(fs);
3257  int64_t result = static_cast<int64_t>(rounded);
3258  SetFPUResult(fd_reg(), result);
3259  if (set_fcsr_round64_error(fs, rounded)) {
3260  set_fpu_register_invalid_result64(fs, rounded);
3261  }
3262  break;
3263  }
3264  case FLOOR_L_D: { // Mips64r2 instruction.
3265  double rounded = floor(fs);
3266  int64_t result = static_cast<int64_t>(rounded);
3267  SetFPUResult(fd_reg(), result);
3268  if (set_fcsr_round64_error(fs, rounded)) {
3269  set_fpu_register_invalid_result64(fs, rounded);
3270  }
3271  break;
3272  }
3273  case CEIL_L_D: { // Mips64r2 instruction.
3274  double rounded = ceil(fs);
3275  int64_t result = static_cast<int64_t>(rounded);
3276  SetFPUResult(fd_reg(), result);
3277  if (set_fcsr_round64_error(fs, rounded)) {
3278  set_fpu_register_invalid_result64(fs, rounded);
3279  }
3280  break;
3281  }
3282  case CLASS_D: { // Mips64r6 instruction
3283  // Convert double input to uint64_t for easier bit manipulation
3284  uint64_t classed = bit_cast<uint64_t>(fs);
3285 
3286  // Extracting sign, exponent and mantissa from the input double
3287  uint32_t sign = (classed >> 63) & 1;
3288  uint32_t exponent = (classed >> 52) & 0x00000000000007FF;
3289  uint64_t mantissa = classed & 0x000FFFFFFFFFFFFF;
3290  uint64_t result;
3291  double dResult;
3292 
3293  // Setting flags if input double is negative infinity,
3294  // positive infinity, negative zero or positive zero
3295  bool negInf = (classed == 0xFFF0000000000000);
3296  bool posInf = (classed == 0x7FF0000000000000);
3297  bool negZero = (classed == 0x8000000000000000);
3298  bool posZero = (classed == 0x0000000000000000);
3299 
3300  bool signalingNan;
3301  bool quietNan;
3302  bool negSubnorm;
3303  bool posSubnorm;
3304  bool negNorm;
3305  bool posNorm;
3306 
3307  // Setting flags if double is NaN
3308  signalingNan = false;
3309  quietNan = false;
3310  if (!negInf && !posInf && exponent == 0x7FF) {
3311  quietNan = ((mantissa & 0x0008000000000000) != 0) &&
3312  ((mantissa & (0x0008000000000000 - 1)) == 0);
3313  signalingNan = !quietNan;
3314  }
3315 
3316  // Setting flags if double is subnormal number
3317  posSubnorm = false;
3318  negSubnorm = false;
3319  if ((exponent == 0) && (mantissa != 0)) {
3320  DCHECK(sign == 0 || sign == 1);
3321  posSubnorm = (sign == 0);
3322  negSubnorm = (sign == 1);
3323  }
3324 
3325  // Setting flags if double is normal number
3326  posNorm = false;
3327  negNorm = false;
3328  if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3329  !quietNan && !negZero && !posZero) {
3330  DCHECK(sign == 0 || sign == 1);
3331  posNorm = (sign == 0);
3332  negNorm = (sign == 1);
3333  }
3334 
3335  // Calculating result according to description of CLASS.D instruction
3336  result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3337  (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3338  (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3339 
3340  DCHECK_NE(result, 0);
3341 
3342  dResult = bit_cast<double>(result);
3343  SetFPUDoubleResult(fd_reg(), dResult);
3344  break;
3345  }
3346  case C_F_D: {
3347  set_fcsr_bit(fcsr_cc, false);
3348  TraceRegWr(test_fcsr_bit(fcsr_cc));
3349  break;
3350  }
3351  default:
3352  UNREACHABLE();
3353  }
3354 }
3355 
3356 
3357 void Simulator::DecodeTypeRegisterWRsType() {
3358  float fs = get_fpu_register_float(fs_reg());
3359  float ft = get_fpu_register_float(ft_reg());
3360  int64_t alu_out = 0x12345678;
3361  switch (instr_.FunctionFieldRaw()) {
3362  case CVT_S_W: // Convert word to float (single).
3363  alu_out = get_fpu_register_signed_word(fs_reg());
3364  SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out));
3365  break;
3366  case CVT_D_W: // Convert word to double.
3367  alu_out = get_fpu_register_signed_word(fs_reg());
3368  SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out));
3369  break;
3370  case CMP_AF:
3371  SetFPUWordResult2(fd_reg(), 0);
3372  break;
3373  case CMP_UN:
3374  if (std::isnan(fs) || std::isnan(ft)) {
3375  SetFPUWordResult2(fd_reg(), -1);
3376  } else {
3377  SetFPUWordResult2(fd_reg(), 0);
3378  }
3379  break;
3380  case CMP_EQ:
3381  if (fs == ft) {
3382  SetFPUWordResult2(fd_reg(), -1);
3383  } else {
3384  SetFPUWordResult2(fd_reg(), 0);
3385  }
3386  break;
3387  case CMP_UEQ:
3388  if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3389  SetFPUWordResult2(fd_reg(), -1);
3390  } else {
3391  SetFPUWordResult2(fd_reg(), 0);
3392  }
3393  break;
3394  case CMP_LT:
3395  if (fs < ft) {
3396  SetFPUWordResult2(fd_reg(), -1);
3397  } else {
3398  SetFPUWordResult2(fd_reg(), 0);
3399  }
3400  break;
3401  case CMP_ULT:
3402  if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3403  SetFPUWordResult2(fd_reg(), -1);
3404  } else {
3405  SetFPUWordResult2(fd_reg(), 0);
3406  }
3407  break;
3408  case CMP_LE:
3409  if (fs <= ft) {
3410  SetFPUWordResult2(fd_reg(), -1);
3411  } else {
3412  SetFPUWordResult2(fd_reg(), 0);
3413  }
3414  break;
3415  case CMP_ULE:
3416  if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3417  SetFPUWordResult2(fd_reg(), -1);
3418  } else {
3419  SetFPUWordResult2(fd_reg(), 0);
3420  }
3421  break;
3422  case CMP_OR:
3423  if (!std::isnan(fs) && !std::isnan(ft)) {
3424  SetFPUWordResult2(fd_reg(), -1);
3425  } else {
3426  SetFPUWordResult2(fd_reg(), 0);
3427  }
3428  break;
3429  case CMP_UNE:
3430  if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3431  SetFPUWordResult2(fd_reg(), -1);
3432  } else {
3433  SetFPUWordResult2(fd_reg(), 0);
3434  }
3435  break;
3436  case CMP_NE:
3437  if (fs != ft) {
3438  SetFPUWordResult2(fd_reg(), -1);
3439  } else {
3440  SetFPUWordResult2(fd_reg(), 0);
3441  }
3442  break;
3443  default:
3444  UNREACHABLE();
3445  }
3446 }
3447 
3448 
3449 void Simulator::DecodeTypeRegisterLRsType() {
3450  double fs = get_fpu_register_double(fs_reg());
3451  double ft = get_fpu_register_double(ft_reg());
3452  int64_t i64;
3453  switch (instr_.FunctionFieldRaw()) {
3454  case CVT_D_L: // Mips32r2 instruction.
3455  i64 = get_fpu_register(fs_reg());
3456  SetFPUDoubleResult(fd_reg(), static_cast<double>(i64));
3457  break;
3458  case CVT_S_L:
3459  i64 = get_fpu_register(fs_reg());
3460  SetFPUFloatResult(fd_reg(), static_cast<float>(i64));
3461  break;
3462  case CMP_AF:
3463  SetFPUResult(fd_reg(), 0);
3464  break;
3465  case CMP_UN:
3466  if (std::isnan(fs) || std::isnan(ft)) {
3467  SetFPUResult(fd_reg(), -1);
3468  } else {
3469  SetFPUResult(fd_reg(), 0);
3470  }
3471  break;
3472  case CMP_EQ:
3473  if (fs == ft) {
3474  SetFPUResult(fd_reg(), -1);
3475  } else {
3476  SetFPUResult(fd_reg(), 0);
3477  }
3478  break;
3479  case CMP_UEQ:
3480  if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3481  SetFPUResult(fd_reg(), -1);
3482  } else {
3483  SetFPUResult(fd_reg(), 0);
3484  }
3485  break;
3486  case CMP_LT:
3487  if (fs < ft) {
3488  SetFPUResult(fd_reg(), -1);
3489  } else {
3490  SetFPUResult(fd_reg(), 0);
3491  }
3492  break;
3493  case CMP_ULT:
3494  if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3495  SetFPUResult(fd_reg(), -1);
3496  } else {
3497  SetFPUResult(fd_reg(), 0);
3498  }
3499  break;
3500  case CMP_LE:
3501  if (fs <= ft) {
3502  SetFPUResult(fd_reg(), -1);
3503  } else {
3504  SetFPUResult(fd_reg(), 0);
3505  }
3506  break;
3507  case CMP_ULE:
3508  if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3509  SetFPUResult(fd_reg(), -1);
3510  } else {
3511  SetFPUResult(fd_reg(), 0);
3512  }
3513  break;
3514  case CMP_OR:
3515  if (!std::isnan(fs) && !std::isnan(ft)) {
3516  SetFPUResult(fd_reg(), -1);
3517  } else {
3518  SetFPUResult(fd_reg(), 0);
3519  }
3520  break;
3521  case CMP_UNE:
3522  if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3523  SetFPUResult(fd_reg(), -1);
3524  } else {
3525  SetFPUResult(fd_reg(), 0);
3526  }
3527  break;
3528  case CMP_NE:
3529  if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3530  SetFPUResult(fd_reg(), -1);
3531  } else {
3532  SetFPUResult(fd_reg(), 0);
3533  }
3534  break;
3535  default:
3536  UNREACHABLE();
3537  }
3538 }
3539 
3540 
3541 void Simulator::DecodeTypeRegisterCOP1() {
3542  switch (instr_.RsFieldRaw()) {
3543  case BC1: // Branch on coprocessor condition.
3544  case BC1EQZ:
3545  case BC1NEZ:
3546  UNREACHABLE();
3547  break;
3548  case CFC1:
3549  // At the moment only FCSR is supported.
3550  DCHECK_EQ(fs_reg(), kFCSRRegister);
3551  SetResult(rt_reg(), FCSR_);
3552  break;
3553  case MFC1:
3554  set_register(rt_reg(),
3555  static_cast<int64_t>(get_fpu_register_word(fs_reg())));
3556  TraceRegWr(get_register(rt_reg()), WORD_DWORD);
3557  break;
3558  case DMFC1:
3559  SetResult(rt_reg(), get_fpu_register(fs_reg()));
3560  break;
3561  case MFHC1:
3562  SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg()));
3563  break;
3564  case CTC1: {
3565  // At the moment only FCSR is supported.
3566  DCHECK_EQ(fs_reg(), kFCSRRegister);
3567  uint32_t reg = static_cast<uint32_t>(rt());
3568  if (kArchVariant == kMips64r6) {
3569  FCSR_ = reg | kFCSRNaN2008FlagMask;
3570  } else {
3571  DCHECK_EQ(kArchVariant, kMips64r2);
3572  FCSR_ = reg & ~kFCSRNaN2008FlagMask;
3573  }
3574  TraceRegWr(FCSR_);
3575  break;
3576  }
3577  case MTC1:
3578  // Hardware writes upper 32-bits to zero on mtc1.
3579  set_fpu_register_hi_word(fs_reg(), 0);
3580  set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt()));
3581  TraceRegWr(get_fpu_register(fs_reg()), FLOAT_DOUBLE);
3582  break;
3583  case DMTC1:
3584  SetFPUResult2(fs_reg(), rt());
3585  break;
3586  case MTHC1:
3587  set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt()));
3588  TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
3589  break;
3590  case S:
3591  DecodeTypeRegisterSRsType();
3592  break;
3593  case D:
3594  DecodeTypeRegisterDRsType();
3595  break;
3596  case W:
3597  DecodeTypeRegisterWRsType();
3598  break;
3599  case L:
3600  DecodeTypeRegisterLRsType();
3601  break;
3602  default:
3603  UNREACHABLE();
3604  }
3605 }
3606 
3607 
3608 void Simulator::DecodeTypeRegisterCOP1X() {
3609  switch (instr_.FunctionFieldRaw()) {
3610  case MADD_S: {
3611  DCHECK_EQ(kArchVariant, kMips64r2);
3612  float fr, ft, fs;
3613  fr = get_fpu_register_float(fr_reg());
3614  fs = get_fpu_register_float(fs_reg());
3615  ft = get_fpu_register_float(ft_reg());
3616  SetFPUFloatResult(fd_reg(), fs * ft + fr);
3617  break;
3618  }
3619  case MSUB_S: {
3620  DCHECK_EQ(kArchVariant, kMips64r2);
3621  float fr, ft, fs;
3622  fr = get_fpu_register_float(fr_reg());
3623  fs = get_fpu_register_float(fs_reg());
3624  ft = get_fpu_register_float(ft_reg());
3625  SetFPUFloatResult(fd_reg(), fs * ft - fr);
3626  break;
3627  }
3628  case MADD_D: {
3629  DCHECK_EQ(kArchVariant, kMips64r2);
3630  double fr, ft, fs;
3631  fr = get_fpu_register_double(fr_reg());
3632  fs = get_fpu_register_double(fs_reg());
3633  ft = get_fpu_register_double(ft_reg());
3634  SetFPUDoubleResult(fd_reg(), fs * ft + fr);
3635  break;
3636  }
3637  case MSUB_D: {
3638  DCHECK_EQ(kArchVariant, kMips64r2);
3639  double fr, ft, fs;
3640  fr = get_fpu_register_double(fr_reg());
3641  fs = get_fpu_register_double(fs_reg());
3642  ft = get_fpu_register_double(ft_reg());
3643  SetFPUDoubleResult(fd_reg(), fs * ft - fr);
3644  break;
3645  }
3646  default:
3647  UNREACHABLE();
3648  }
3649 }
3650 
3651 
3652 void Simulator::DecodeTypeRegisterSPECIAL() {
3653  int64_t i64hilo;
3654  uint64_t u64hilo;
3655  int64_t alu_out;
3656  bool do_interrupt = false;
3657 
3658  switch (instr_.FunctionFieldRaw()) {
3659  case SELEQZ_S:
3660  DCHECK_EQ(kArchVariant, kMips64r6);
3661  SetResult(rd_reg(), rt() == 0 ? rs() : 0);
3662  break;
3663  case SELNEZ_S:
3664  DCHECK_EQ(kArchVariant, kMips64r6);
3665  SetResult(rd_reg(), rt() != 0 ? rs() : 0);
3666  break;
3667  case JR: {
3668  int64_t next_pc = rs();
3669  int64_t current_pc = get_pc();
3670  Instruction* branch_delay_instr =
3671  reinterpret_cast<Instruction*>(current_pc + kInstrSize);
3672  BranchDelayInstructionDecode(branch_delay_instr);
3673  set_pc(next_pc);
3674  pc_modified_ = true;
3675  break;
3676  }
3677  case JALR: {
3678  int64_t next_pc = rs();
3679  int64_t current_pc = get_pc();
3680  int32_t return_addr_reg = rd_reg();
3681  Instruction* branch_delay_instr =
3682  reinterpret_cast<Instruction*>(current_pc + kInstrSize);
3683  BranchDelayInstructionDecode(branch_delay_instr);
3684  set_register(return_addr_reg, current_pc + 2 * kInstrSize);
3685  set_pc(next_pc);
3686  pc_modified_ = true;
3687  break;
3688  }
3689  case SLL:
3690  SetResult(rd_reg(), static_cast<int32_t>(rt()) << sa());
3691  break;
3692  case DSLL:
3693  SetResult(rd_reg(), rt() << sa());
3694  break;
3695  case DSLL32:
3696  SetResult(rd_reg(), rt() << sa() << 32);
3697  break;
3698  case SRL:
3699  if (rs_reg() == 0) {
3700  // Regular logical right shift of a word by a fixed number of
3701  // bits instruction. RS field is always equal to 0.
3702  // Sign-extend the 32-bit result.
3703  alu_out = static_cast<int32_t>(static_cast<uint32_t>(rt_u()) >> sa());
3704  } else if (rs_reg() == 1) {
3705  // Logical right-rotate of a word by a fixed number of bits. This
3706  // is special case of SRL instruction, added in MIPS32 Release 2.
3707  // RS field is equal to 00001.
3708  alu_out = static_cast<int32_t>(
3709  base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
3710  static_cast<const uint32_t>(sa())));
3711  } else {
3712  UNREACHABLE();
3713  }
3714  SetResult(rd_reg(), alu_out);
3715  break;
3716  case DSRL:
3717  if (rs_reg() == 0) {
3718  // Regular logical right shift of a word by a fixed number of
3719  // bits instruction. RS field is always equal to 0.
3720  // Sign-extend the 64-bit result.
3721  alu_out = static_cast<int64_t>(rt_u() >> sa());
3722  } else if (rs_reg() == 1) {
3723  // Logical right-rotate of a word by a fixed number of bits. This
3724  // is special case of SRL instruction, added in MIPS32 Release 2.
3725  // RS field is equal to 00001.
3726  alu_out = static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa()));
3727  } else {
3728  UNREACHABLE();
3729  }
3730  SetResult(rd_reg(), alu_out);
3731  break;
3732  case DSRL32:
3733  if (rs_reg() == 0) {
3734  // Regular logical right shift of a word by a fixed number of
3735  // bits instruction. RS field is always equal to 0.
3736  // Sign-extend the 64-bit result.
3737  alu_out = static_cast<int64_t>(rt_u() >> sa() >> 32);
3738  } else if (rs_reg() == 1) {
3739  // Logical right-rotate of a word by a fixed number of bits. This
3740  // is special case of SRL instruction, added in MIPS32 Release 2.
3741  // RS field is equal to 00001.
3742  alu_out =
3743  static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa() + 32));
3744  } else {
3745  UNREACHABLE();
3746  }
3747  SetResult(rd_reg(), alu_out);
3748  break;
3749  case SRA:
3750  SetResult(rd_reg(), (int32_t)rt() >> sa());
3751  break;
3752  case DSRA:
3753  SetResult(rd_reg(), rt() >> sa());
3754  break;
3755  case DSRA32:
3756  SetResult(rd_reg(), rt() >> sa() >> 32);
3757  break;
3758  case SLLV:
3759  SetResult(rd_reg(), (int32_t)rt() << rs());
3760  break;
3761  case DSLLV:
3762  SetResult(rd_reg(), rt() << rs());
3763  break;
3764  case SRLV:
3765  if (sa() == 0) {
3766  // Regular logical right-shift of a word by a variable number of
3767  // bits instruction. SA field is always equal to 0.
3768  alu_out = static_cast<int32_t>((uint32_t)rt_u() >> rs());
3769  } else {
3770  // Logical right-rotate of a word by a variable number of bits.
3771  // This is special case od SRLV instruction, added in MIPS32
3772  // Release 2. SA field is equal to 00001.
3773  alu_out = static_cast<int32_t>(
3774  base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
3775  static_cast<const uint32_t>(rs_u())));
3776  }
3777  SetResult(rd_reg(), alu_out);
3778  break;
3779  case DSRLV:
3780  if (sa() == 0) {
3781  // Regular logical right-shift of a word by a variable number of
3782  // bits instruction. SA field is always equal to 0.
3783  alu_out = static_cast<int64_t>(rt_u() >> rs());
3784  } else {
3785  // Logical right-rotate of a word by a variable number of bits.
3786  // This is special case od SRLV instruction, added in MIPS32
3787  // Release 2. SA field is equal to 00001.
3788  alu_out =
3789  static_cast<int64_t>(base::bits::RotateRight64(rt_u(), rs_u()));
3790  }
3791  SetResult(rd_reg(), alu_out);
3792  break;
3793  case SRAV:
3794  SetResult(rd_reg(), (int32_t)rt() >> rs());
3795  break;
3796  case DSRAV:
3797  SetResult(rd_reg(), rt() >> rs());
3798  break;
3799  case LSA: {
3800  DCHECK_EQ(kArchVariant, kMips64r6);
3801  int8_t sa = lsa_sa() + 1;
3802  int32_t _rt = static_cast<int32_t>(rt());
3803  int32_t _rs = static_cast<int32_t>(rs());
3804  int32_t res = _rs << sa;
3805  res += _rt;
3806  SetResult(rd_reg(), static_cast<int64_t>(res));
3807  break;
3808  }
3809  case DLSA:
3810  DCHECK_EQ(kArchVariant, kMips64r6);
3811  SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt());
3812  break;
3813  case MFHI: // MFHI == CLZ on R6.
3814  if (kArchVariant != kMips64r6) {
3815  DCHECK_EQ(sa(), 0);
3816  alu_out = get_register(HI);
3817  } else {
3818  // MIPS spec: If no bits were set in GPR rs(), the result written to
3819  // GPR rd() is 32.
3820  DCHECK_EQ(sa(), 1);
3821  alu_out = base::bits::CountLeadingZeros32(static_cast<int32_t>(rs_u()));
3822  }
3823  SetResult(rd_reg(), alu_out);
3824  break;
3825  case MFLO: // MFLO == DCLZ on R6.
3826  if (kArchVariant != kMips64r6) {
3827  DCHECK_EQ(sa(), 0);
3828  alu_out = get_register(LO);
3829  } else {
3830  // MIPS spec: If no bits were set in GPR rs(), the result written to
3831  // GPR rd() is 64.
3832  DCHECK_EQ(sa(), 1);
3833  alu_out = base::bits::CountLeadingZeros64(static_cast<int64_t>(rs_u()));
3834  }
3835  SetResult(rd_reg(), alu_out);
3836  break;
3837  // Instructions using HI and LO registers.
3838  case MULT: { // MULT == D_MUL_MUH.
3839  int32_t rs_lo = static_cast<int32_t>(rs());
3840  int32_t rt_lo = static_cast<int32_t>(rt());
3841  i64hilo = static_cast<int64_t>(rs_lo) * static_cast<int64_t>(rt_lo);
3842  if (kArchVariant != kMips64r6) {
3843  set_register(LO, static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
3844  set_register(HI, static_cast<int32_t>(i64hilo >> 32));
3845  } else {
3846  switch (sa()) {
3847  case MUL_OP:
3848  SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
3849  break;
3850  case MUH_OP:
3851  SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
3852  break;
3853  default:
3854  UNIMPLEMENTED_MIPS();
3855  break;
3856  }
3857  }
3858  break;
3859  }
3860  case MULTU:
3861  u64hilo = static_cast<uint64_t>(rs_u() & 0xFFFFFFFF) *
3862  static_cast<uint64_t>(rt_u() & 0xFFFFFFFF);
3863  if (kArchVariant != kMips64r6) {
3864  set_register(LO, static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
3865  set_register(HI, static_cast<int32_t>(u64hilo >> 32));
3866  } else {
3867  switch (sa()) {
3868  case MUL_OP:
3869  SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
3870  break;
3871  case MUH_OP:
3872  SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
3873  break;
3874  default:
3875  UNIMPLEMENTED_MIPS();
3876  break;
3877  }
3878  }
3879  break;
3880  case DMULT: // DMULT == D_MUL_MUH.
3881  if (kArchVariant != kMips64r6) {
3882  set_register(LO, rs() * rt());
3883  set_register(HI, MultiplyHighSigned(rs(), rt()));
3884  } else {
3885  switch (sa()) {
3886  case MUL_OP:
3887  SetResult(rd_reg(), rs() * rt());
3888  break;
3889  case MUH_OP:
3890  SetResult(rd_reg(), MultiplyHighSigned(rs(), rt()));
3891  break;
3892  default:
3893  UNIMPLEMENTED_MIPS();
3894  break;
3895  }
3896  }
3897  break;
3898  case DMULTU:
3899  UNIMPLEMENTED_MIPS();
3900  break;
3901  case DIV:
3902  case DDIV: {
3903  const int64_t int_min_value =
3904  instr_.FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN;
3905  switch (kArchVariant) {
3906  case kMips64r2:
3907  // Divide by zero and overflow was not checked in the
3908  // configuration step - div and divu do not raise exceptions. On
3909  // division by 0 the result will be UNPREDICTABLE. On overflow
3910  // (INT_MIN/-1), return INT_MIN which is what the hardware does.
3911  if (rs() == int_min_value && rt() == -1) {
3912  set_register(LO, int_min_value);
3913  set_register(HI, 0);
3914  } else if (rt() != 0) {
3915  set_register(LO, rs() / rt());
3916  set_register(HI, rs() % rt());
3917  }
3918  break;
3919  case kMips64r6:
3920  switch (sa()) {
3921  case DIV_OP:
3922  if (rs() == int_min_value && rt() == -1) {
3923  SetResult(rd_reg(), int_min_value);
3924  } else if (rt() != 0) {
3925  SetResult(rd_reg(), rs() / rt());
3926  }
3927  break;
3928  case MOD_OP:
3929  if (rs() == int_min_value && rt() == -1) {
3930  SetResult(rd_reg(), 0);
3931  } else if (rt() != 0) {
3932  SetResult(rd_reg(), rs() % rt());
3933  }
3934  break;
3935  default:
3936  UNIMPLEMENTED_MIPS();
3937  break;
3938  }
3939  break;
3940  default:
3941  break;
3942  }
3943  break;
3944  }
3945  case DIVU:
3946  switch (kArchVariant) {
3947  case kMips64r6: {
3948  uint32_t rt_u_32 = static_cast<uint32_t>(rt_u());
3949  uint32_t rs_u_32 = static_cast<uint32_t>(rs_u());
3950  switch (sa()) {
3951  case DIV_OP:
3952  if (rt_u_32 != 0) {
3953  SetResult(rd_reg(), rs_u_32 / rt_u_32);
3954  }
3955  break;
3956  case MOD_OP:
3957  if (rt_u() != 0) {
3958  SetResult(rd_reg(), rs_u_32 % rt_u_32);
3959  }
3960  break;
3961  default:
3962  UNIMPLEMENTED_MIPS();
3963  break;
3964  }
3965  } break;
3966  default: {
3967  if (rt_u() != 0) {
3968  uint32_t rt_u_32 = static_cast<uint32_t>(rt_u());
3969  uint32_t rs_u_32 = static_cast<uint32_t>(rs_u());
3970  set_register(LO, rs_u_32 / rt_u_32);
3971  set_register(HI, rs_u_32 % rt_u_32);
3972  }
3973  }
3974  }
3975  break;
3976  case DDIVU:
3977  switch (kArchVariant) {
3978  case kMips64r6: {
3979  switch (instr_.SaValue()) {
3980  case DIV_OP:
3981  if (rt_u() != 0) {
3982  SetResult(rd_reg(), rs_u() / rt_u());
3983  }
3984  break;
3985  case MOD_OP:
3986  if (rt_u() != 0) {
3987  SetResult(rd_reg(), rs_u() % rt_u());
3988  }
3989  break;
3990  default:
3991  UNIMPLEMENTED_MIPS();
3992  break;
3993  }
3994  } break;
3995  default: {
3996  if (rt_u() != 0) {
3997  set_register(LO, rs_u() / rt_u());
3998  set_register(HI, rs_u() % rt_u());
3999  }
4000  }
4001  }
4002  break;
4003  case ADD:
4004  case DADD:
4005  if (HaveSameSign(rs(), rt())) {
4006  if (rs() > 0) {
4007  if (rs() > (Registers::kMaxValue - rt())) {
4008  SignalException(kIntegerOverflow);
4009  }
4010  } else if (rs() < 0) {
4011  if (rs() < (Registers::kMinValue - rt())) {
4012  SignalException(kIntegerUnderflow);
4013  }
4014  }
4015  }
4016  SetResult(rd_reg(), rs() + rt());
4017  break;
4018  case ADDU: {
4019  int32_t alu32_out = static_cast<int32_t>(rs() + rt());
4020  // Sign-extend result of 32bit operation into 64bit register.
4021  SetResult(rd_reg(), static_cast<int64_t>(alu32_out));
4022  break;
4023  }
4024  case DADDU:
4025  SetResult(rd_reg(), rs() + rt());
4026  break;
4027  case SUB:
4028  case DSUB:
4029  if (!HaveSameSign(rs(), rt())) {
4030  if (rs() > 0) {
4031  if (rs() > (Registers::kMaxValue + rt())) {
4032  SignalException(kIntegerOverflow);
4033  }
4034  } else if (rs() < 0) {
4035  if (rs() < (Registers::kMinValue + rt())) {
4036  SignalException(kIntegerUnderflow);
4037  }
4038  }
4039  }
4040  SetResult(rd_reg(), rs() - rt());
4041  break;
4042  case SUBU: {
4043  int32_t alu32_out = static_cast<int32_t>(rs() - rt());
4044  // Sign-extend result of 32bit operation into 64bit register.
4045  SetResult(rd_reg(), static_cast<int64_t>(alu32_out));
4046  break;
4047  }
4048  case DSUBU:
4049  SetResult(rd_reg(), rs() - rt());
4050  break;
4051  case AND:
4052  SetResult(rd_reg(), rs() & rt());
4053  break;
4054  case OR:
4055  SetResult(rd_reg(), rs() | rt());
4056  break;
4057  case XOR:
4058  SetResult(rd_reg(), rs() ^ rt());
4059  break;
4060  case NOR:
4061  SetResult(rd_reg(), ~(rs() | rt()));
4062  break;
4063  case SLT:
4064  SetResult(rd_reg(), rs() < rt() ? 1 : 0);
4065  break;
4066  case SLTU:
4067  SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
4068  break;
4069  // Break and trap instructions.
4070  case BREAK:
4071  do_interrupt = true;
4072  break;
4073  case TGE:
4074  do_interrupt = rs() >= rt();
4075  break;
4076  case TGEU:
4077  do_interrupt = rs_u() >= rt_u();
4078  break;
4079  case TLT:
4080  do_interrupt = rs() < rt();
4081  break;
4082  case TLTU:
4083  do_interrupt = rs_u() < rt_u();
4084  break;
4085  case TEQ:
4086  do_interrupt = rs() == rt();
4087  break;
4088  case TNE:
4089  do_interrupt = rs() != rt();
4090  break;
4091  case SYNC:
4092  // TODO(palfia): Ignore sync instruction for now.
4093  break;
4094  // Conditional moves.
4095  case MOVN:
4096  if (rt()) {
4097  SetResult(rd_reg(), rs());
4098  }
4099  break;
4100  case MOVCI: {
4101  uint32_t cc = instr_.FBccValue();
4102  uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
4103  if (instr_.Bit(16)) { // Read Tf bit.
4104  if (test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs());
4105  } else {
4106  if (!test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs());
4107  }
4108  break;
4109  }
4110  case MOVZ:
4111  if (!rt()) {
4112  SetResult(rd_reg(), rs());
4113  }
4114  break;
4115  default:
4116  UNREACHABLE();
4117  }
4118  if (do_interrupt) {
4119  SoftwareInterrupt();
4120  }
4121 }
4122 
4123 
4124 void Simulator::DecodeTypeRegisterSPECIAL2() {
4125  int64_t alu_out;
4126  switch (instr_.FunctionFieldRaw()) {
4127  case MUL:
4128  alu_out = static_cast<int32_t>(rs_u()) * static_cast<int32_t>(rt_u());
4129  SetResult(rd_reg(), alu_out);
4130  // HI and LO are UNPREDICTABLE after the operation.
4131  set_register(LO, Unpredictable);
4132  set_register(HI, Unpredictable);
4133  break;
4134  case CLZ:
4135  // MIPS32 spec: If no bits were set in GPR rs(), the result written to
4136  // GPR rd is 32.
4137  alu_out = base::bits::CountLeadingZeros32(static_cast<uint32_t>(rs_u()));
4138  SetResult(rd_reg(), alu_out);
4139  break;
4140  case DCLZ:
4141  // MIPS64 spec: If no bits were set in GPR rs(), the result written to
4142  // GPR rd is 64.
4143  alu_out = base::bits::CountLeadingZeros64(static_cast<uint64_t>(rs_u()));
4144  SetResult(rd_reg(), alu_out);
4145  break;
4146  default:
4147  alu_out = 0x12345678;
4148  UNREACHABLE();
4149  }
4150 }
4151 
4152 
4153 void Simulator::DecodeTypeRegisterSPECIAL3() {
4154  int64_t alu_out;
4155  switch (instr_.FunctionFieldRaw()) {
4156  case EXT: { // Mips32r2 instruction.
4157  // Interpret rd field as 5-bit msbd of extract.
4158  uint16_t msbd = rd_reg();
4159  // Interpret sa field as 5-bit lsb of extract.
4160  uint16_t lsb = sa();
4161  uint16_t size = msbd + 1;
4162  uint64_t mask = (1ULL << size) - 1;
4163  alu_out = static_cast<int32_t>((rs_u() & (mask << lsb)) >> lsb);
4164  SetResult(rt_reg(), alu_out);
4165  break;
4166  }
4167  case DEXT: { // Mips64r2 instruction.
4168  // Interpret rd field as 5-bit msbd of extract.
4169  uint16_t msbd = rd_reg();
4170  // Interpret sa field as 5-bit lsb of extract.
4171  uint16_t lsb = sa();
4172  uint16_t size = msbd + 1;
4173  uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4174  alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
4175  SetResult(rt_reg(), alu_out);
4176  break;
4177  }
4178  case DEXTM: {
4179  // Interpret rd field as 5-bit msbdminus32 of extract.
4180  uint16_t msbdminus32 = rd_reg();
4181  // Interpret sa field as 5-bit lsb of extract.
4182  uint16_t lsb = sa();
4183  uint16_t size = msbdminus32 + 1 + 32;
4184  uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4185  alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
4186  SetResult(rt_reg(), alu_out);
4187  break;
4188  }
4189  case DEXTU: {
4190  // Interpret rd field as 5-bit msbd of extract.
4191  uint16_t msbd = rd_reg();
4192  // Interpret sa field as 5-bit lsbminus32 of extract and add 32 to get
4193  // lsb.
4194  uint16_t lsb = sa() + 32;
4195  uint16_t size = msbd + 1;
4196  uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4197  alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
4198  SetResult(rt_reg(), alu_out);
4199  break;
4200  }
4201  case INS: { // Mips32r2 instruction.
4202  // Interpret rd field as 5-bit msb of insert.
4203  uint16_t msb = rd_reg();
4204  // Interpret sa field as 5-bit lsb of insert.
4205  uint16_t lsb = sa();
4206  uint16_t size = msb - lsb + 1;
4207  uint64_t mask = (1ULL << size) - 1;
4208  alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) |
4209  ((rs_u() & mask) << lsb));
4210  SetResult(rt_reg(), alu_out);
4211  break;
4212  }
4213  case DINS: { // Mips64r2 instruction.
4214  // Interpret rd field as 5-bit msb of insert.
4215  uint16_t msb = rd_reg();
4216  // Interpret sa field as 5-bit lsb of insert.
4217  uint16_t lsb = sa();
4218  uint16_t size = msb - lsb + 1;
4219  uint64_t mask = (1ULL << size) - 1;
4220  alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4221  SetResult(rt_reg(), alu_out);
4222  break;
4223  }
4224  case DINSM: { // Mips64r2 instruction.
4225  // Interpret rd field as 5-bit msbminus32 of insert.
4226  uint16_t msbminus32 = rd_reg();
4227  // Interpret sa field as 5-bit lsb of insert.
4228  uint16_t lsb = sa();
4229  uint16_t size = msbminus32 + 32 - lsb + 1;
4230  uint64_t mask;
4231  if (size < 64)
4232  mask = (1ULL << size) - 1;
4233  else
4234  mask = std::numeric_limits<uint64_t>::max();
4235  alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4236  SetResult(rt_reg(), alu_out);
4237  break;
4238  }
4239  case DINSU: { // Mips64r2 instruction.
4240  // Interpret rd field as 5-bit msbminus32 of insert.
4241  uint16_t msbminus32 = rd_reg();
4242  // Interpret rd field as 5-bit lsbminus32 of insert.
4243  uint16_t lsbminus32 = sa();
4244  uint16_t lsb = lsbminus32 + 32;
4245  uint16_t size = msbminus32 + 32 - lsb + 1;
4246  uint64_t mask = (1ULL << size) - 1;
4247  alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4248  SetResult(rt_reg(), alu_out);
4249  break;
4250  }
4251  case BSHFL: {
4252  int32_t sa = instr_.SaFieldRaw() >> kSaShift;
4253  switch (sa) {
4254  case BITSWAP: {
4255  uint32_t input = static_cast<uint32_t>(rt());
4256  uint32_t output = 0;
4257  uint8_t i_byte, o_byte;
4258 
4259  // Reverse the bit in byte for each individual byte
4260  for (int i = 0; i < 4; i++) {
4261  output = output >> 8;
4262  i_byte = input & 0xFF;
4263 
4264  // Fast way to reverse bits in byte
4265  // Devised by Sean Anderson, July 13, 2001
4266  o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
4267  (i_byte * 0x8020LU & 0x88440LU)) *
4268  0x10101LU >>
4269  16);
4270 
4271  output = output | (static_cast<uint32_t>(o_byte << 24));
4272  input = input >> 8;
4273  }
4274 
4275  alu_out = static_cast<int64_t>(static_cast<int32_t>(output));
4276  break;
4277  }
4278  case SEB: {
4279  uint8_t input = static_cast<uint8_t>(rt());
4280  uint32_t output = input;
4281  uint32_t mask = 0x00000080;
4282 
4283  // Extending sign
4284  if (mask & input) {
4285  output |= 0xFFFFFF00;
4286  }
4287 
4288  alu_out = static_cast<int32_t>(output);
4289  break;
4290  }
4291  case SEH: {
4292  uint16_t input = static_cast<uint16_t>(rt());
4293  uint32_t output = input;
4294  uint32_t mask = 0x00008000;
4295 
4296  // Extending sign
4297  if (mask & input) {
4298  output |= 0xFFFF0000;
4299  }
4300 
4301  alu_out = static_cast<int32_t>(output);
4302  break;
4303  }
4304  case WSBH: {
4305  uint32_t input = static_cast<uint32_t>(rt());
4306  uint64_t output = 0;
4307 
4308  uint32_t mask = 0xFF000000;
4309  for (int i = 0; i < 4; i++) {
4310  uint32_t tmp = mask & input;
4311  if (i % 2 == 0) {
4312  tmp = tmp >> 8;
4313  } else {
4314  tmp = tmp << 8;
4315  }
4316  output = output | tmp;
4317  mask = mask >> 8;
4318  }
4319  mask = 0x80000000;
4320 
4321  // Extending sign
4322  if (mask & output) {
4323  output |= 0xFFFFFFFF00000000;
4324  }
4325 
4326  alu_out = static_cast<int64_t>(output);
4327  break;
4328  }
4329  default: {
4330  const uint8_t bp2 = instr_.Bp2Value();
4331  sa >>= kBp2Bits;
4332  switch (sa) {
4333  case ALIGN: {
4334  if (bp2 == 0) {
4335  alu_out = static_cast<int32_t>(rt());
4336  } else {
4337  uint64_t rt_hi = rt() << (8 * bp2);
4338  uint64_t rs_lo = rs() >> (8 * (4 - bp2));
4339  alu_out = static_cast<int32_t>(rt_hi | rs_lo);
4340  }
4341  break;
4342  }
4343  default:
4344  alu_out = 0x12345678;
4345  UNREACHABLE();
4346  break;
4347  }
4348  break;
4349  }
4350  }
4351  SetResult(rd_reg(), alu_out);
4352  break;
4353  }
4354  case DBSHFL: {
4355  int32_t sa = instr_.SaFieldRaw() >> kSaShift;
4356  switch (sa) {
4357  case DBITSWAP: {
4358  switch (sa) {
4359  case DBITSWAP_SA: { // Mips64r6
4360  uint64_t input = static_cast<uint64_t>(rt());
4361  uint64_t output = 0;
4362  uint8_t i_byte, o_byte;
4363 
4364  // Reverse the bit in byte for each individual byte
4365  for (int i = 0; i < 8; i++) {
4366  output = output >> 8;
4367  i_byte = input & 0xFF;
4368 
4369  // Fast way to reverse bits in byte
4370  // Devised by Sean Anderson, July 13, 2001
4371  o_byte =
4372  static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) |
4373  (i_byte * 0x8020LU & 0x88440LU)) *
4374  0x10101LU >>
4375  16);
4376 
4377  output = output | ((static_cast<uint64_t>(o_byte) << 56));
4378  input = input >> 8;
4379  }
4380 
4381  alu_out = static_cast<int64_t>(output);
4382  break;
4383  }
4384  }
4385  break;
4386  }
4387  case DSBH: {
4388  uint64_t input = static_cast<uint64_t>(rt());
4389  uint64_t output = 0;
4390 
4391  uint64_t mask = 0xFF00000000000000;
4392  for (int i = 0; i < 8; i++) {
4393  uint64_t tmp = mask & input;
4394  if (i % 2 == 0)
4395  tmp = tmp >> 8;
4396  else
4397  tmp = tmp << 8;
4398 
4399  output = output | tmp;
4400  mask = mask >> 8;
4401  }
4402 
4403  alu_out = static_cast<int64_t>(output);
4404  break;
4405  }
4406  case DSHD: {
4407  uint64_t input = static_cast<uint64_t>(rt());
4408  uint64_t output = 0;
4409 
4410  uint64_t mask = 0xFFFF000000000000;
4411  for (int i = 0; i < 4; i++) {
4412  uint64_t tmp = mask & input;
4413  if (i == 0)
4414  tmp = tmp >> 48;
4415  else if (i == 1)
4416  tmp = tmp >> 16;
4417  else if (i == 2)
4418  tmp = tmp << 16;
4419  else
4420  tmp = tmp << 48;
4421  output = output | tmp;
4422  mask = mask >> 16;
4423  }
4424 
4425  alu_out = static_cast<int64_t>(output);
4426  break;
4427  }
4428  default: {
4429  const uint8_t bp3 = instr_.Bp3Value();
4430  sa >>= kBp3Bits;
4431  switch (sa) {
4432  case DALIGN: {
4433  if (bp3 == 0) {
4434  alu_out = static_cast<int64_t>(rt());
4435  } else {
4436  uint64_t rt_hi = rt() << (8 * bp3);
4437  uint64_t rs_lo = rs() >> (8 * (8 - bp3));
4438  alu_out = static_cast<int64_t>(rt_hi | rs_lo);
4439  }
4440  break;
4441  }
4442  default:
4443  alu_out = 0x12345678;
4444  UNREACHABLE();
4445  break;
4446  }
4447  break;
4448  }
4449  }
4450  SetResult(rd_reg(), alu_out);
4451  break;
4452  }
4453  default:
4454  UNREACHABLE();
4455  }
4456 }
4457 
4458 int Simulator::DecodeMsaDataFormat() {
4459  int df = -1;
4460  if (instr_.IsMSABranchInstr()) {
4461  switch (instr_.RsFieldRaw()) {
4462  case BZ_V:
4463  case BNZ_V:
4464  df = MSA_VECT;
4465  break;
4466  case BZ_B:
4467  case BNZ_B:
4468  df = MSA_BYTE;
4469  break;
4470  case BZ_H:
4471  case BNZ_H:
4472  df = MSA_HALF;
4473  break;
4474  case BZ_W:
4475  case BNZ_W:
4476  df = MSA_WORD;
4477  break;
4478  case BZ_D:
4479  case BNZ_D:
4480  df = MSA_DWORD;
4481  break;
4482  default:
4483  UNREACHABLE();
4484  break;
4485  }
4486  } else {
4487  int DF[] = {MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD};
4488  switch (instr_.MSAMinorOpcodeField()) {
4489  case kMsaMinorI5:
4490  case kMsaMinorI10:
4491  case kMsaMinor3R:
4492  df = DF[instr_.Bits(22, 21)];
4493  break;
4494  case kMsaMinorMI10:
4495  df = DF[instr_.Bits(1, 0)];
4496  break;
4497  case kMsaMinorBIT:
4498  df = DF[instr_.MsaBitDf()];
4499  break;
4500  case kMsaMinorELM:
4501  df = DF[instr_.MsaElmDf()];
4502  break;
4503  case kMsaMinor3RF: {
4504  uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
4505  switch (opcode) {
4506  case FEXDO:
4507  case FTQ:
4508  case MUL_Q:
4509  case MADD_Q:
4510  case MSUB_Q:
4511  case MULR_Q:
4512  case MADDR_Q:
4513  case MSUBR_Q:
4514  df = DF[1 + instr_.Bit(21)];
4515  break;
4516  default:
4517  df = DF[2 + instr_.Bit(21)];
4518  break;
4519  }
4520  } break;
4521  case kMsaMinor2R:
4522  df = DF[instr_.Bits(17, 16)];
4523  break;
4524  case kMsaMinor2RF:
4525  df = DF[2 + instr_.Bit(16)];
4526  break;
4527  default:
4528  UNREACHABLE();
4529  break;
4530  }
4531  }
4532  return df;
4533 }
4534 
4535 void Simulator::DecodeTypeMsaI8() {
4536  DCHECK_EQ(kArchVariant, kMips64r6);
4537  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4538  uint32_t opcode = instr_.InstructionBits() & kMsaI8Mask;
4539  int8_t i8 = instr_.MsaImm8Value();
4540  msa_reg_t ws, wd;
4541 
4542  switch (opcode) {
4543  case ANDI_B:
4544  get_msa_register(instr_.WsValue(), ws.b);
4545  for (int i = 0; i < kMSALanesByte; i++) {
4546  wd.b[i] = ws.b[i] & i8;
4547  }
4548  set_msa_register(instr_.WdValue(), wd.b);
4549  TraceMSARegWr(wd.b);
4550  break;
4551  case ORI_B:
4552  get_msa_register(instr_.WsValue(), ws.b);
4553  for (int i = 0; i < kMSALanesByte; i++) {
4554  wd.b[i] = ws.b[i] | i8;
4555  }
4556  set_msa_register(instr_.WdValue(), wd.b);
4557  TraceMSARegWr(wd.b);
4558  break;
4559  case NORI_B:
4560  get_msa_register(instr_.WsValue(), ws.b);
4561  for (int i = 0; i < kMSALanesByte; i++) {
4562  wd.b[i] = ~(ws.b[i] | i8);
4563  }
4564  set_msa_register(instr_.WdValue(), wd.b);
4565  TraceMSARegWr(wd.b);
4566  break;
4567  case XORI_B:
4568  get_msa_register(instr_.WsValue(), ws.b);
4569  for (int i = 0; i < kMSALanesByte; i++) {
4570  wd.b[i] = ws.b[i] ^ i8;
4571  }
4572  set_msa_register(instr_.WdValue(), wd.b);
4573  TraceMSARegWr(wd.b);
4574  break;
4575  case BMNZI_B:
4576  get_msa_register(instr_.WsValue(), ws.b);
4577  get_msa_register(instr_.WdValue(), wd.b);
4578  for (int i = 0; i < kMSALanesByte; i++) {
4579  wd.b[i] = (ws.b[i] & i8) | (wd.b[i] & ~i8);
4580  }
4581  set_msa_register(instr_.WdValue(), wd.b);
4582  TraceMSARegWr(wd.b);
4583  break;
4584  case BMZI_B:
4585  get_msa_register(instr_.WsValue(), ws.b);
4586  get_msa_register(instr_.WdValue(), wd.b);
4587  for (int i = 0; i < kMSALanesByte; i++) {
4588  wd.b[i] = (ws.b[i] & ~i8) | (wd.b[i] & i8);
4589  }
4590  set_msa_register(instr_.WdValue(), wd.b);
4591  TraceMSARegWr(wd.b);
4592  break;
4593  case BSELI_B:
4594  get_msa_register(instr_.WsValue(), ws.b);
4595  get_msa_register(instr_.WdValue(), wd.b);
4596  for (int i = 0; i < kMSALanesByte; i++) {
4597  wd.b[i] = (ws.b[i] & ~wd.b[i]) | (wd.b[i] & i8);
4598  }
4599  set_msa_register(instr_.WdValue(), wd.b);
4600  TraceMSARegWr(wd.b);
4601  break;
4602  case SHF_B:
4603  get_msa_register(instr_.WsValue(), ws.b);
4604  for (int i = 0; i < kMSALanesByte; i++) {
4605  int j = i % 4;
4606  int k = (i8 >> (2 * j)) & 0x3;
4607  wd.b[i] = ws.b[i - j + k];
4608  }
4609  set_msa_register(instr_.WdValue(), wd.b);
4610  TraceMSARegWr(wd.b);
4611  break;
4612  case SHF_H:
4613  get_msa_register(instr_.WsValue(), ws.h);
4614  for (int i = 0; i < kMSALanesHalf; i++) {
4615  int j = i % 4;
4616  int k = (i8 >> (2 * j)) & 0x3;
4617  wd.h[i] = ws.h[i - j + k];
4618  }
4619  set_msa_register(instr_.WdValue(), wd.h);
4620  TraceMSARegWr(wd.h);
4621  break;
4622  case SHF_W:
4623  get_msa_register(instr_.WsValue(), ws.w);
4624  for (int i = 0; i < kMSALanesWord; i++) {
4625  int j = (i8 >> (2 * i)) & 0x3;
4626  wd.w[i] = ws.w[j];
4627  }
4628  set_msa_register(instr_.WdValue(), wd.w);
4629  TraceMSARegWr(wd.w);
4630  break;
4631  default:
4632  UNREACHABLE();
4633  }
4634 }
4635 
4636 template <typename T>
4637 T Simulator::MsaI5InstrHelper(uint32_t opcode, T ws, int32_t i5) {
4638  T res;
4639  uint32_t ui5 = i5 & 0x1Fu;
4640  uint64_t ws_u64 = static_cast<uint64_t>(ws);
4641  uint64_t ui5_u64 = static_cast<uint64_t>(ui5);
4642 
4643  switch (opcode) {
4644  case ADDVI:
4645  res = static_cast<T>(ws + ui5);
4646  break;
4647  case SUBVI:
4648  res = static_cast<T>(ws - ui5);
4649  break;
4650  case MAXI_S:
4651  res = static_cast<T>(Max(ws, static_cast<T>(i5)));
4652  break;
4653  case MINI_S:
4654  res = static_cast<T>(Min(ws, static_cast<T>(i5)));
4655  break;
4656  case MAXI_U:
4657  res = static_cast<T>(Max(ws_u64, ui5_u64));
4658  break;
4659  case MINI_U:
4660  res = static_cast<T>(Min(ws_u64, ui5_u64));
4661  break;
4662  case CEQI:
4663  res = static_cast<T>(!Compare(ws, static_cast<T>(i5)) ? -1ull : 0ull);
4664  break;
4665  case CLTI_S:
4666  res = static_cast<T>((Compare(ws, static_cast<T>(i5)) == -1) ? -1ull
4667  : 0ull);
4668  break;
4669  case CLTI_U:
4670  res = static_cast<T>((Compare(ws_u64, ui5_u64) == -1) ? -1ull : 0ull);
4671  break;
4672  case CLEI_S:
4673  res =
4674  static_cast<T>((Compare(ws, static_cast<T>(i5)) != 1) ? -1ull : 0ull);
4675  break;
4676  case CLEI_U:
4677  res = static_cast<T>((Compare(ws_u64, ui5_u64) != 1) ? -1ull : 0ull);
4678  break;
4679  default:
4680  UNREACHABLE();
4681  }
4682  return res;
4683 }
4684 
4685 void Simulator::DecodeTypeMsaI5() {
4686  DCHECK_EQ(kArchVariant, kMips64r6);
4687  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4688  uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
4689  msa_reg_t ws, wd;
4690 
4691  // sign extend 5bit value to int32_t
4692  int32_t i5 = static_cast<int32_t>(instr_.MsaImm5Value() << 27) >> 27;
4693 
4694 #define MSA_I5_DF(elem, num_of_lanes) \
4695  get_msa_register(instr_.WsValue(), ws.elem); \
4696  for (int i = 0; i < num_of_lanes; i++) { \
4697  wd.elem[i] = MsaI5InstrHelper(opcode, ws.elem[i], i5); \
4698  } \
4699  set_msa_register(instr_.WdValue(), wd.elem); \
4700  TraceMSARegWr(wd.elem)
4701 
4702  switch (DecodeMsaDataFormat()) {
4703  case MSA_BYTE:
4704  MSA_I5_DF(b, kMSALanesByte);
4705  break;
4706  case MSA_HALF:
4707  MSA_I5_DF(h, kMSALanesHalf);
4708  break;
4709  case MSA_WORD:
4710  MSA_I5_DF(w, kMSALanesWord);
4711  break;
4712  case MSA_DWORD:
4713  MSA_I5_DF(d, kMSALanesDword);
4714  break;
4715  default:
4716  UNREACHABLE();
4717  }
4718 #undef MSA_I5_DF
4719 }
4720 
4721 void Simulator::DecodeTypeMsaI10() {
4722  DCHECK_EQ(kArchVariant, kMips64r6);
4723  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4724  uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
4725  int64_t s10 = (static_cast<int64_t>(instr_.MsaImm10Value()) << 54) >> 54;
4726  msa_reg_t wd;
4727 
4728 #define MSA_I10_DF(elem, num_of_lanes, T) \
4729  for (int i = 0; i < num_of_lanes; ++i) { \
4730  wd.elem[i] = static_cast<T>(s10); \
4731  } \
4732  set_msa_register(instr_.WdValue(), wd.elem); \
4733  TraceMSARegWr(wd.elem)
4734 
4735  if (opcode == LDI) {
4736  switch (DecodeMsaDataFormat()) {
4737  case MSA_BYTE:
4738  MSA_I10_DF(b, kMSALanesByte, int8_t);
4739  break;
4740  case MSA_HALF:
4741  MSA_I10_DF(h, kMSALanesHalf, int16_t);
4742  break;
4743  case MSA_WORD:
4744  MSA_I10_DF(w, kMSALanesWord, int32_t);
4745  break;
4746  case MSA_DWORD:
4747  MSA_I10_DF(d, kMSALanesDword, int64_t);
4748  break;
4749  default:
4750  UNREACHABLE();
4751  }
4752  } else {
4753  UNREACHABLE();
4754  }
4755 #undef MSA_I10_DF
4756 }
4757 
4758 void Simulator::DecodeTypeMsaELM() {
4759  DCHECK_EQ(kArchVariant, kMips64r6);
4760  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4761  uint32_t opcode = instr_.InstructionBits() & kMsaLongerELMMask;
4762  int32_t n = instr_.MsaElmNValue();
4763  int64_t alu_out;
4764  switch (opcode) {
4765  case CTCMSA:
4766  DCHECK_EQ(sa(), kMSACSRRegister);
4767  MSACSR_ = bit_cast<uint32_t>(
4768  static_cast<int32_t>(registers_[rd_reg()] & kMaxUInt32));
4769  TraceRegWr(static_cast<int32_t>(MSACSR_));
4770  break;
4771  case CFCMSA:
4772  DCHECK_EQ(rd_reg(), kMSACSRRegister);
4773  SetResult(sa(), static_cast<int64_t>(bit_cast<int32_t>(MSACSR_)));
4774  break;
4775  case MOVE_V: {
4776  msa_reg_t ws;
4777  get_msa_register(ws_reg(), &ws);
4778  set_msa_register(wd_reg(), &ws);
4779  TraceMSARegWr(&ws);
4780  } break;
4781  default:
4782  opcode &= kMsaELMMask;
4783  switch (opcode) {
4784  case COPY_S:
4785  case COPY_U: {
4786  msa_reg_t ws;
4787  switch (DecodeMsaDataFormat()) {
4788  case MSA_BYTE:
4789  DCHECK_LT(n, kMSALanesByte);
4790  get_msa_register(instr_.WsValue(), ws.b);
4791  alu_out = static_cast<int32_t>(ws.b[n]);
4792  SetResult(wd_reg(),
4793  (opcode == COPY_U) ? alu_out & 0xFFu : alu_out);
4794  break;
4795  case MSA_HALF:
4796  DCHECK_LT(n, kMSALanesHalf);
4797  get_msa_register(instr_.WsValue(), ws.h);
4798  alu_out = static_cast<int32_t>(ws.h[n]);
4799  SetResult(wd_reg(),
4800  (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out);
4801  break;
4802  case MSA_WORD:
4803  DCHECK_LT(n, kMSALanesWord);
4804  get_msa_register(instr_.WsValue(), ws.w);
4805  alu_out = static_cast<int32_t>(ws.w[n]);
4806  SetResult(wd_reg(),
4807  (opcode == COPY_U) ? alu_out & 0xFFFFFFFFu : alu_out);
4808  break;
4809  case MSA_DWORD:
4810  DCHECK_LT(n, kMSALanesDword);
4811  get_msa_register(instr_.WsValue(), ws.d);
4812  alu_out = static_cast<int64_t>(ws.d[n]);
4813  SetResult(wd_reg(), alu_out);
4814  break;
4815  default:
4816  UNREACHABLE();
4817  }
4818  } break;
4819  case INSERT: {
4820  msa_reg_t wd;
4821  switch (DecodeMsaDataFormat()) {
4822  case MSA_BYTE: {
4823  DCHECK_LT(n, kMSALanesByte);
4824  int64_t rs = get_register(instr_.WsValue());
4825  get_msa_register(instr_.WdValue(), wd.b);
4826  wd.b[n] = rs & 0xFFu;
4827  set_msa_register(instr_.WdValue(), wd.b);
4828  TraceMSARegWr(wd.b);
4829  break;
4830  }
4831  case MSA_HALF: {
4832  DCHECK_LT(n, kMSALanesHalf);
4833  int64_t rs = get_register(instr_.WsValue());
4834  get_msa_register(instr_.WdValue(), wd.h);
4835  wd.h[n] = rs & 0xFFFFu;
4836  set_msa_register(instr_.WdValue(), wd.h);
4837  TraceMSARegWr(wd.h);
4838  break;
4839  }
4840  case MSA_WORD: {
4841  DCHECK_LT(n, kMSALanesWord);
4842  int64_t rs = get_register(instr_.WsValue());
4843  get_msa_register(instr_.WdValue(), wd.w);
4844  wd.w[n] = rs & 0xFFFFFFFFu;
4845  set_msa_register(instr_.WdValue(), wd.w);
4846  TraceMSARegWr(wd.w);
4847  break;
4848  }
4849  case MSA_DWORD: {
4850  DCHECK_LT(n, kMSALanesDword);
4851  int64_t rs = get_register(instr_.WsValue());
4852  get_msa_register(instr_.WdValue(), wd.d);
4853  wd.d[n] = rs;
4854  set_msa_register(instr_.WdValue(), wd.d);
4855  TraceMSARegWr(wd.d);
4856  break;
4857  }
4858  default:
4859  UNREACHABLE();
4860  }
4861  } break;
4862  case SLDI: {
4863  uint8_t v[32];
4864  msa_reg_t ws;
4865  msa_reg_t wd;
4866  get_msa_register(ws_reg(), &ws);
4867  get_msa_register(wd_reg(), &wd);
4868 #define SLDI_DF(s, k) \
4869  for (unsigned i = 0; i < s; i++) { \
4870  v[i] = ws.b[s * k + i]; \
4871  v[i + s] = wd.b[s * k + i]; \
4872  } \
4873  for (unsigned i = 0; i < s; i++) { \
4874  wd.b[s * k + i] = v[i + n]; \
4875  }
4876  switch (DecodeMsaDataFormat()) {
4877  case MSA_BYTE:
4878  DCHECK(n < kMSALanesByte);
4879  SLDI_DF(kMSARegSize / sizeof(int8_t) / kBitsPerByte, 0)
4880  break;
4881  case MSA_HALF:
4882  DCHECK(n < kMSALanesHalf);
4883  for (int k = 0; k < 2; ++k) {
4884  SLDI_DF(kMSARegSize / sizeof(int16_t) / kBitsPerByte, k)
4885  }
4886  break;
4887  case MSA_WORD:
4888  DCHECK(n < kMSALanesWord);
4889  for (int k = 0; k < 4; ++k) {
4890  SLDI_DF(kMSARegSize / sizeof(int32_t) / kBitsPerByte, k)
4891  }
4892  break;
4893  case MSA_DWORD:
4894  DCHECK(n < kMSALanesDword);
4895  for (int k = 0; k < 8; ++k) {
4896  SLDI_DF(kMSARegSize / sizeof(int64_t) / kBitsPerByte, k)
4897  }
4898  break;
4899  default:
4900  UNREACHABLE();
4901  }
4902  set_msa_register(wd_reg(), &wd);
4903  TraceMSARegWr(&wd);
4904  } break;
4905 #undef SLDI_DF
4906  case SPLATI:
4907  case INSVE:
4908  UNIMPLEMENTED();
4909  break;
4910  default:
4911  UNREACHABLE();
4912  }
4913  break;
4914  }
4915 }
4916 
4917 template <typename T>
4918 T Simulator::MsaBitInstrHelper(uint32_t opcode, T wd, T ws, int32_t m) {
4919  typedef typename std::make_unsigned<T>::type uT;
4920  T res;
4921  switch (opcode) {
4922  case SLLI:
4923  res = static_cast<T>(ws << m);
4924  break;
4925  case SRAI:
4926  res = static_cast<T>(ArithmeticShiftRight(ws, m));
4927  break;
4928  case SRLI:
4929  res = static_cast<T>(static_cast<uT>(ws) >> m);
4930  break;
4931  case BCLRI:
4932  res = static_cast<T>(static_cast<T>(~(1ull << m)) & ws);
4933  break;
4934  case BSETI:
4935  res = static_cast<T>(static_cast<T>(1ull << m) | ws);
4936  break;
4937  case BNEGI:
4938  res = static_cast<T>(static_cast<T>(1ull << m) ^ ws);
4939  break;
4940  case BINSLI: {
4941  int elem_size = 8 * sizeof(T);
4942  int bits = m + 1;
4943  if (bits == elem_size) {
4944  res = static_cast<T>(ws);
4945  } else {
4946  uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
4947  res = static_cast<T>((static_cast<T>(mask) & ws) |
4948  (static_cast<T>(~mask) & wd));
4949  }
4950  } break;
4951  case BINSRI: {
4952  int elem_size = 8 * sizeof(T);
4953  int bits = m + 1;
4954  if (bits == elem_size) {
4955  res = static_cast<T>(ws);
4956  } else {
4957  uint64_t mask = (1ull << bits) - 1;
4958  res = static_cast<T>((static_cast<T>(mask) & ws) |
4959  (static_cast<T>(~mask) & wd));
4960  }
4961  } break;
4962  case SAT_S: {
4963 #define M_MAX_INT(x) static_cast<int64_t>((1LL << ((x)-1)) - 1)
4964 #define M_MIN_INT(x) static_cast<int64_t>(-(1LL << ((x)-1)))
4965  int shift = 64 - 8 * sizeof(T);
4966  int64_t ws_i64 = (static_cast<int64_t>(ws) << shift) >> shift;
4967  res = static_cast<T>(ws_i64 < M_MIN_INT(m + 1)
4968  ? M_MIN_INT(m + 1)
4969  : ws_i64 > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1)
4970  : ws_i64);
4971 #undef M_MAX_INT
4972 #undef M_MIN_INT
4973  } break;
4974  case SAT_U: {
4975 #define M_MAX_UINT(x) static_cast<uint64_t>(-1ULL >> (64 - (x)))
4976  uint64_t mask = static_cast<uint64_t>(-1ULL >> (64 - 8 * sizeof(T)));
4977  uint64_t ws_u64 = static_cast<uint64_t>(ws) & mask;
4978  res = static_cast<T>(ws_u64 < M_MAX_UINT(m + 1) ? ws_u64
4979  : M_MAX_UINT(m + 1));
4980 #undef M_MAX_UINT
4981  } break;
4982  case SRARI:
4983  if (!m) {
4984  res = static_cast<T>(ws);
4985  } else {
4986  res = static_cast<T>(ArithmeticShiftRight(ws, m)) +
4987  static_cast<T>((ws >> (m - 1)) & 0x1);
4988  }
4989  break;
4990  case SRLRI:
4991  if (!m) {
4992  res = static_cast<T>(ws);
4993  } else {
4994  res = static_cast<T>(static_cast<uT>(ws) >> m) +
4995  static_cast<T>((ws >> (m - 1)) & 0x1);
4996  }
4997  break;
4998  default:
4999  UNREACHABLE();
5000  }
5001  return res;
5002 }
5003 
5004 void Simulator::DecodeTypeMsaBIT() {
5005  DCHECK_EQ(kArchVariant, kMips64r6);
5006  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5007  uint32_t opcode = instr_.InstructionBits() & kMsaBITMask;
5008  int32_t m = instr_.MsaBitMValue();
5009  msa_reg_t wd, ws;
5010 
5011 #define MSA_BIT_DF(elem, num_of_lanes) \
5012  get_msa_register(instr_.WsValue(), ws.elem); \
5013  if (opcode == BINSLI || opcode == BINSRI) { \
5014  get_msa_register(instr_.WdValue(), wd.elem); \
5015  } \
5016  for (int i = 0; i < num_of_lanes; i++) { \
5017  wd.elem[i] = MsaBitInstrHelper(opcode, wd.elem[i], ws.elem[i], m); \
5018  } \
5019  set_msa_register(instr_.WdValue(), wd.elem); \
5020  TraceMSARegWr(wd.elem)
5021 
5022  switch (DecodeMsaDataFormat()) {
5023  case MSA_BYTE:
5024  DCHECK(m < kMSARegSize / kMSALanesByte);
5025  MSA_BIT_DF(b, kMSALanesByte);
5026  break;
5027  case MSA_HALF:
5028  DCHECK(m < kMSARegSize / kMSALanesHalf);
5029  MSA_BIT_DF(h, kMSALanesHalf);
5030  break;
5031  case MSA_WORD:
5032  DCHECK(m < kMSARegSize / kMSALanesWord);
5033  MSA_BIT_DF(w, kMSALanesWord);
5034  break;
5035  case MSA_DWORD:
5036  DCHECK(m < kMSARegSize / kMSALanesDword);
5037  MSA_BIT_DF(d, kMSALanesDword);
5038  break;
5039  default:
5040  UNREACHABLE();
5041  }
5042 #undef MSA_BIT_DF
5043 }
5044 
5045 void Simulator::DecodeTypeMsaMI10() {
5046  DCHECK_EQ(kArchVariant, kMips64r6);
5047  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5048  uint32_t opcode = instr_.InstructionBits() & kMsaMI10Mask;
5049  int64_t s10 = (static_cast<int64_t>(instr_.MsaImmMI10Value()) << 54) >> 54;
5050  int64_t rs = get_register(instr_.WsValue());
5051  int64_t addr;
5052  msa_reg_t wd;
5053 
5054 #define MSA_MI10_LOAD(elem, num_of_lanes, T) \
5055  for (int i = 0; i < num_of_lanes; ++i) { \
5056  addr = rs + (s10 + i) * sizeof(T); \
5057  wd.elem[i] = ReadMem<T>(addr, instr_.instr()); \
5058  } \
5059  set_msa_register(instr_.WdValue(), wd.elem);
5060 
5061 #define MSA_MI10_STORE(elem, num_of_lanes, T) \
5062  get_msa_register(instr_.WdValue(), wd.elem); \
5063  for (int i = 0; i < num_of_lanes; ++i) { \
5064  addr = rs + (s10 + i) * sizeof(T); \
5065  WriteMem<T>(addr, wd.elem[i], instr_.instr()); \
5066  }
5067 
5068  if (opcode == MSA_LD) {
5069  switch (DecodeMsaDataFormat()) {
5070  case MSA_BYTE:
5071  MSA_MI10_LOAD(b, kMSALanesByte, int8_t);
5072  break;
5073  case MSA_HALF:
5074  MSA_MI10_LOAD(h, kMSALanesHalf, int16_t);
5075  break;
5076  case MSA_WORD:
5077  MSA_MI10_LOAD(w, kMSALanesWord, int32_t);
5078  break;
5079  case MSA_DWORD:
5080  MSA_MI10_LOAD(d, kMSALanesDword, int64_t);
5081  break;
5082  default:
5083  UNREACHABLE();
5084  }
5085  } else if (opcode == MSA_ST) {
5086  switch (DecodeMsaDataFormat()) {
5087  case MSA_BYTE:
5088  MSA_MI10_STORE(b, kMSALanesByte, int8_t);
5089  break;
5090  case MSA_HALF:
5091  MSA_MI10_STORE(h, kMSALanesHalf, int16_t);
5092  break;
5093  case MSA_WORD:
5094  MSA_MI10_STORE(w, kMSALanesWord, int32_t);
5095  break;
5096  case MSA_DWORD:
5097  MSA_MI10_STORE(d, kMSALanesDword, int64_t);
5098  break;
5099  default:
5100  UNREACHABLE();
5101  }
5102  } else {
5103  UNREACHABLE();
5104  }
5105 
5106 #undef MSA_MI10_LOAD
5107 #undef MSA_MI10_STORE
5108 }
5109 
5110 template <typename T>
5111 T Simulator::Msa3RInstrHelper(uint32_t opcode, T wd, T ws, T wt) {
5112  typedef typename std::make_unsigned<T>::type uT;
5113  T res;
5114  int wt_modulo = wt % (sizeof(T) * 8);
5115  switch (opcode) {
5116  case SLL_MSA:
5117  res = static_cast<T>(ws << wt_modulo);
5118  break;
5119  case SRA_MSA:
5120  res = static_cast<T>(ArithmeticShiftRight(ws, wt_modulo));
5121  break;
5122  case SRL_MSA:
5123  res = static_cast<T>(static_cast<uT>(ws) >> wt_modulo);
5124  break;
5125  case BCLR:
5126  res = static_cast<T>(static_cast<T>(~(1ull << wt_modulo)) & ws);
5127  break;
5128  case BSET:
5129  res = static_cast<T>(static_cast<T>(1ull << wt_modulo) | ws);
5130  break;
5131  case BNEG:
5132  res = static_cast<T>(static_cast<T>(1ull << wt_modulo) ^ ws);
5133  break;
5134  case BINSL: {
5135  int elem_size = 8 * sizeof(T);
5136  int bits = wt_modulo + 1;
5137  if (bits == elem_size) {
5138  res = static_cast<T>(ws);
5139  } else {
5140  uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
5141  res = static_cast<T>((static_cast<T>(mask) & ws) |
5142  (static_cast<T>(~mask) & wd));
5143  }
5144  } break;
5145  case BINSR: {
5146  int elem_size = 8 * sizeof(T);
5147  int bits = wt_modulo + 1;
5148  if (bits == elem_size) {
5149  res = static_cast<T>(ws);
5150  } else {
5151  uint64_t mask = (1ull << bits) - 1;
5152  res = static_cast<T>((static_cast<T>(mask) & ws) |
5153  (static_cast<T>(~mask) & wd));
5154  }
5155  } break;
5156  case ADDV:
5157  res = ws + wt;
5158  break;
5159  case SUBV:
5160  res = ws - wt;
5161  break;
5162  case MAX_S:
5163  res = Max(ws, wt);
5164  break;
5165  case MAX_U:
5166  res = static_cast<T>(Max(static_cast<uT>(ws), static_cast<uT>(wt)));
5167  break;
5168  case MIN_S:
5169  res = Min(ws, wt);
5170  break;
5171  case MIN_U:
5172  res = static_cast<T>(Min(static_cast<uT>(ws), static_cast<uT>(wt)));
5173  break;
5174  case MAX_A:
5175  // We use negative abs in order to avoid problems
5176  // with corner case for MIN_INT
5177  res = Nabs(ws) < Nabs(wt) ? ws : wt;
5178  break;
5179  case MIN_A:
5180  // We use negative abs in order to avoid problems
5181  // with corner case for MIN_INT
5182  res = Nabs(ws) > Nabs(wt) ? ws : wt;
5183  break;
5184  case CEQ:
5185  res = static_cast<T>(!Compare(ws, wt) ? -1ull : 0ull);
5186  break;
5187  case CLT_S:
5188  res = static_cast<T>((Compare(ws, wt) == -1) ? -1ull : 0ull);
5189  break;
5190  case CLT_U:
5191  res = static_cast<T>(
5192  (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) == -1) ? -1ull
5193  : 0ull);
5194  break;
5195  case CLE_S:
5196  res = static_cast<T>((Compare(ws, wt) != 1) ? -1ull : 0ull);
5197  break;
5198  case CLE_U:
5199  res = static_cast<T>(
5200  (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) != 1) ? -1ull
5201  : 0ull);
5202  break;
5203  case ADD_A:
5204  res = static_cast<T>(Abs(ws) + Abs(wt));
5205  break;
5206  case ADDS_A: {
5207  T ws_nabs = Nabs(ws);
5208  T wt_nabs = Nabs(wt);
5209  if (ws_nabs < -std::numeric_limits<T>::max() - wt_nabs) {
5210  res = std::numeric_limits<T>::max();
5211  } else {
5212  res = -(ws_nabs + wt_nabs);
5213  }
5214  } break;
5215  case ADDS_S:
5216  res = SaturateAdd(ws, wt);
5217  break;
5218  case ADDS_U: {
5219  uT ws_u = static_cast<uT>(ws);
5220  uT wt_u = static_cast<uT>(wt);
5221  res = static_cast<T>(SaturateAdd(ws_u, wt_u));
5222  } break;
5223  case AVE_S:
5224  res = static_cast<T>((wt & ws) + ((wt ^ ws) >> 1));
5225  break;
5226  case AVE_U: {
5227  uT ws_u = static_cast<uT>(ws);
5228  uT wt_u = static_cast<uT>(wt);
5229  res = static_cast<T>((wt_u & ws_u) + ((wt_u ^ ws_u) >> 1));
5230  } break;
5231  case AVER_S:
5232  res = static_cast<T>((wt | ws) - ((wt ^ ws) >> 1));
5233  break;
5234  case AVER_U: {
5235  uT ws_u = static_cast<uT>(ws);
5236  uT wt_u = static_cast<uT>(wt);
5237  res = static_cast<T>((wt_u | ws_u) - ((wt_u ^ ws_u) >> 1));
5238  } break;
5239  case SUBS_S:
5240  res = SaturateSub(ws, wt);
5241  break;
5242  case SUBS_U: {
5243  uT ws_u = static_cast<uT>(ws);
5244  uT wt_u = static_cast<uT>(wt);
5245  res = static_cast<T>(SaturateSub(ws_u, wt_u));
5246  } break;
5247  case SUBSUS_U: {
5248  uT wsu = static_cast<uT>(ws);
5249  if (wt > 0) {
5250  uT wtu = static_cast<uT>(wt);
5251  if (wtu > wsu) {
5252  res = 0;
5253  } else {
5254  res = static_cast<T>(wsu - wtu);
5255  }
5256  } else {
5257  if (wsu > std::numeric_limits<uT>::max() + wt) {
5258  res = static_cast<T>(std::numeric_limits<uT>::max());
5259  } else {
5260  res = static_cast<T>(wsu - wt);
5261  }
5262  }
5263  } break;
5264  case SUBSUU_S: {
5265  uT wsu = static_cast<uT>(ws);
5266  uT wtu = static_cast<uT>(wt);
5267  uT wdu;
5268  if (wsu > wtu) {
5269  wdu = wsu - wtu;
5270  if (wdu > std::numeric_limits<T>::max()) {
5271  res = std::numeric_limits<T>::max();
5272  } else {
5273  res = static_cast<T>(wdu);
5274  }
5275  } else {
5276  wdu = wtu - wsu;
5277  CHECK(-std::numeric_limits<T>::max() ==
5278  std::numeric_limits<T>::min() + 1);
5279  if (wdu <= std::numeric_limits<T>::max()) {
5280  res = -static_cast<T>(wdu);
5281  } else {
5282  res = std::numeric_limits<T>::min();
5283  }
5284  }
5285  } break;
5286  case ASUB_S:
5287  res = static_cast<T>(Abs(ws - wt));
5288  break;
5289  case ASUB_U: {
5290  uT wsu = static_cast<uT>(ws);
5291  uT wtu = static_cast<uT>(wt);
5292  res = static_cast<T>(wsu > wtu ? wsu - wtu : wtu - wsu);
5293  } break;
5294  case MULV:
5295  res = ws * wt;
5296  break;
5297  case MADDV:
5298  res = wd + ws * wt;
5299  break;
5300  case MSUBV:
5301  res = wd - ws * wt;
5302  break;
5303  case DIV_S_MSA:
5304  res = wt != 0 ? ws / wt : static_cast<T>(Unpredictable);
5305  break;
5306  case DIV_U:
5307  res = wt != 0 ? static_cast<T>(static_cast<uT>(ws) / static_cast<uT>(wt))
5308  : static_cast<T>(Unpredictable);
5309  break;
5310  case MOD_S:
5311  res = wt != 0 ? ws % wt : static_cast<T>(Unpredictable);
5312  break;
5313  case MOD_U:
5314  res = wt != 0 ? static_cast<T>(static_cast<uT>(ws) % static_cast<uT>(wt))
5315  : static_cast<T>(Unpredictable);
5316  break;
5317  case DOTP_S:
5318  case DOTP_U:
5319  case DPADD_S:
5320  case DPADD_U:
5321  case DPSUB_S:
5322  case DPSUB_U:
5323  case SLD:
5324  case SPLAT:
5325  UNIMPLEMENTED();
5326  break;
5327  case SRAR: {
5328  int bit = wt_modulo == 0 ? 0 : (ws >> (wt_modulo - 1)) & 1;
5329  res = static_cast<T>(ArithmeticShiftRight(ws, wt_modulo) + bit);
5330  } break;
5331  case SRLR: {
5332  uT wsu = static_cast<uT>(ws);
5333  int bit = wt_modulo == 0 ? 0 : (wsu >> (wt_modulo - 1)) & 1;
5334  res = static_cast<T>((wsu >> wt_modulo) + bit);
5335  } break;
5336  default:
5337  UNREACHABLE();
5338  }
5339  return res;
5340 }
5341 template <typename T_int, typename T_reg>
5342 void Msa3RInstrHelper_shuffle(const uint32_t opcode, T_reg ws, T_reg wt,
5343  T_reg wd, const int i, const int num_of_lanes) {
5344  T_int *ws_p, *wt_p, *wd_p;
5345  ws_p = reinterpret_cast<T_int*>(ws);
5346  wt_p = reinterpret_cast<T_int*>(wt);
5347  wd_p = reinterpret_cast<T_int*>(wd);
5348  switch (opcode) {
5349  case PCKEV:
5350  wd_p[i] = wt_p[2 * i];
5351  wd_p[i + num_of_lanes / 2] = ws_p[2 * i];
5352  break;
5353  case PCKOD:
5354  wd_p[i] = wt_p[2 * i + 1];
5355  wd_p[i + num_of_lanes / 2] = ws_p[2 * i + 1];
5356  break;
5357  case ILVL:
5358  wd_p[2 * i] = wt_p[i + num_of_lanes / 2];
5359  wd_p[2 * i + 1] = ws_p[i + num_of_lanes / 2];
5360  break;
5361  case ILVR:
5362  wd_p[2 * i] = wt_p[i];
5363  wd_p[2 * i + 1] = ws_p[i];
5364  break;
5365  case ILVEV:
5366  wd_p[2 * i] = wt_p[2 * i];
5367  wd_p[2 * i + 1] = ws_p[2 * i];
5368  break;
5369  case ILVOD:
5370  wd_p[2 * i] = wt_p[2 * i + 1];
5371  wd_p[2 * i + 1] = ws_p[2 * i + 1];
5372  break;
5373  case VSHF: {
5374  const int mask_not_valid = 0xC0;
5375  const int mask_6_bits = 0x3F;
5376  if ((wd_p[i] & mask_not_valid)) {
5377  wd_p[i] = 0;
5378  } else {
5379  int k = (wd_p[i] & mask_6_bits) % (num_of_lanes * 2);
5380  wd_p[i] = k >= num_of_lanes ? ws_p[k - num_of_lanes] : wt_p[k];
5381  }
5382  } break;
5383  default:
5384  UNREACHABLE();
5385  }
5386 }
5387 
5388 template <typename T_int, typename T_smaller_int, typename T_reg>
5389 void Msa3RInstrHelper_horizontal(const uint32_t opcode, T_reg ws, T_reg wt,
5390  T_reg wd, const int i,
5391  const int num_of_lanes) {
5392  typedef typename std::make_unsigned<T_int>::type T_uint;
5393  typedef typename std::make_unsigned<T_smaller_int>::type T_smaller_uint;
5394  T_int* wd_p;
5395  T_smaller_int *ws_p, *wt_p;
5396  ws_p = reinterpret_cast<T_smaller_int*>(ws);
5397  wt_p = reinterpret_cast<T_smaller_int*>(wt);
5398  wd_p = reinterpret_cast<T_int*>(wd);
5399  T_uint* wd_pu;
5400  T_smaller_uint *ws_pu, *wt_pu;
5401  ws_pu = reinterpret_cast<T_smaller_uint*>(ws);
5402  wt_pu = reinterpret_cast<T_smaller_uint*>(wt);
5403  wd_pu = reinterpret_cast<T_uint*>(wd);
5404  switch (opcode) {
5405  case HADD_S:
5406  wd_p[i] =
5407  static_cast<T_int>(ws_p[2 * i + 1]) + static_cast<T_int>(wt_p[2 * i]);
5408  break;
5409  case HADD_U:
5410  wd_pu[i] = static_cast<T_uint>(ws_pu[2 * i + 1]) +
5411  static_cast<T_uint>(wt_pu[2 * i]);
5412  break;
5413  case HSUB_S:
5414  wd_p[i] =
5415  static_cast<T_int>(ws_p[2 * i + 1]) - static_cast<T_int>(wt_p[2 * i]);
5416  break;
5417  case HSUB_U:
5418  wd_pu[i] = static_cast<T_uint>(ws_pu[2 * i + 1]) -
5419  static_cast<T_uint>(wt_pu[2 * i]);
5420  break;
5421  default:
5422  UNREACHABLE();
5423  }
5424 }
5425 
5426 void Simulator::DecodeTypeMsa3R() {
5427  DCHECK_EQ(kArchVariant, kMips64r6);
5428  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5429  uint32_t opcode = instr_.InstructionBits() & kMsa3RMask;
5430  msa_reg_t ws, wd, wt;
5431  get_msa_register(ws_reg(), &ws);
5432  get_msa_register(wt_reg(), &wt);
5433  get_msa_register(wd_reg(), &wd);
5434  switch (opcode) {
5435  case HADD_S:
5436  case HADD_U:
5437  case HSUB_S:
5438  case HSUB_U:
5439 #define HORIZONTAL_ARITHMETIC_DF(num_of_lanes, int_type, lesser_int_type) \
5440  for (int i = 0; i < num_of_lanes; ++i) { \
5441  Msa3RInstrHelper_horizontal<int_type, lesser_int_type>( \
5442  opcode, &ws, &wt, &wd, i, num_of_lanes); \
5443  }
5444  switch (DecodeMsaDataFormat()) {
5445  case MSA_HALF:
5446  HORIZONTAL_ARITHMETIC_DF(kMSALanesHalf, int16_t, int8_t);
5447  break;
5448  case MSA_WORD:
5449  HORIZONTAL_ARITHMETIC_DF(kMSALanesWord, int32_t, int16_t);
5450  break;
5451  case MSA_DWORD:
5452  HORIZONTAL_ARITHMETIC_DF(kMSALanesDword, int64_t, int32_t);
5453  break;
5454  default:
5455  UNREACHABLE();
5456  }
5457  break;
5458 #undef HORIZONTAL_ARITHMETIC_DF
5459  case VSHF:
5460 #define VSHF_DF(num_of_lanes, int_type) \
5461  for (int i = 0; i < num_of_lanes; ++i) { \
5462  Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \
5463  num_of_lanes); \
5464  }
5465  switch (DecodeMsaDataFormat()) {
5466  case MSA_BYTE:
5467  VSHF_DF(kMSALanesByte, int8_t);
5468  break;
5469  case MSA_HALF:
5470  VSHF_DF(kMSALanesHalf, int16_t);
5471  break;
5472  case MSA_WORD:
5473  VSHF_DF(kMSALanesWord, int32_t);
5474  break;
5475  case MSA_DWORD:
5476  VSHF_DF(kMSALanesDword, int64_t);
5477  break;
5478  default:
5479  UNREACHABLE();
5480  }
5481 #undef VSHF_DF
5482  break;
5483  case PCKEV:
5484  case PCKOD:
5485  case ILVL:
5486  case ILVR:
5487  case ILVEV:
5488  case ILVOD:
5489 #define INTERLEAVE_PACK_DF(num_of_lanes, int_type) \
5490  for (int i = 0; i < num_of_lanes / 2; ++i) { \
5491  Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \
5492  num_of_lanes); \
5493  }
5494  switch (DecodeMsaDataFormat()) {
5495  case MSA_BYTE:
5496  INTERLEAVE_PACK_DF(kMSALanesByte, int8_t);
5497  break;
5498  case MSA_HALF:
5499  INTERLEAVE_PACK_DF(kMSALanesHalf, int16_t);
5500  break;
5501  case MSA_WORD:
5502  INTERLEAVE_PACK_DF(kMSALanesWord, int32_t);
5503  break;
5504  case MSA_DWORD:
5505  INTERLEAVE_PACK_DF(kMSALanesDword, int64_t);
5506  break;
5507  default:
5508  UNREACHABLE();
5509  }
5510  break;
5511 #undef INTERLEAVE_PACK_DF
5512  default:
5513 #define MSA_3R_DF(elem, num_of_lanes) \
5514  for (int i = 0; i < num_of_lanes; i++) { \
5515  wd.elem[i] = Msa3RInstrHelper(opcode, wd.elem[i], ws.elem[i], wt.elem[i]); \
5516  }
5517 
5518  switch (DecodeMsaDataFormat()) {
5519  case MSA_BYTE:
5520  MSA_3R_DF(b, kMSALanesByte);
5521  break;
5522  case MSA_HALF:
5523  MSA_3R_DF(h, kMSALanesHalf);
5524  break;
5525  case MSA_WORD:
5526  MSA_3R_DF(w, kMSALanesWord);
5527  break;
5528  case MSA_DWORD:
5529  MSA_3R_DF(d, kMSALanesDword);
5530  break;
5531  default:
5532  UNREACHABLE();
5533  }
5534 #undef MSA_3R_DF
5535  break;
5536  }
5537  set_msa_register(wd_reg(), &wd);
5538  TraceMSARegWr(&wd);
5539 }
5540 
5541 template <typename T_int, typename T_fp, typename T_reg>
5542 void Msa3RFInstrHelper(uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
5543  const T_int all_ones = static_cast<T_int>(-1);
5544  const T_fp s_element = *reinterpret_cast<T_fp*>(&ws);
5545  const T_fp t_element = *reinterpret_cast<T_fp*>(&wt);
5546  switch (opcode) {
5547  case FCUN: {
5548  if (std::isnan(s_element) || std::isnan(t_element)) {
5549  wd = all_ones;
5550  } else {
5551  wd = 0;
5552  }
5553  } break;
5554  case FCEQ: {
5555  if (s_element != t_element || std::isnan(s_element) ||
5556  std::isnan(t_element)) {
5557  wd = 0;
5558  } else {
5559  wd = all_ones;
5560  }
5561  } break;
5562  case FCUEQ: {
5563  if (s_element == t_element || std::isnan(s_element) ||
5564  std::isnan(t_element)) {
5565  wd = all_ones;
5566  } else {
5567  wd = 0;
5568  }
5569  } break;
5570  case FCLT: {
5571  if (s_element >= t_element || std::isnan(s_element) ||
5572  std::isnan(t_element)) {
5573  wd = 0;
5574  } else {
5575  wd = all_ones;
5576  }
5577  } break;
5578  case FCULT: {
5579  if (s_element < t_element || std::isnan(s_element) ||
5580  std::isnan(t_element)) {
5581  wd = all_ones;
5582  } else {
5583  wd = 0;
5584  }
5585  } break;
5586  case FCLE: {
5587  if (s_element > t_element || std::isnan(s_element) ||
5588  std::isnan(t_element)) {
5589  wd = 0;
5590  } else {
5591  wd = all_ones;
5592  }
5593  } break;
5594  case FCULE: {
5595  if (s_element <= t_element || std::isnan(s_element) ||
5596  std::isnan(t_element)) {
5597  wd = all_ones;
5598  } else {
5599  wd = 0;
5600  }
5601  } break;
5602  case FCOR: {
5603  if (std::isnan(s_element) || std::isnan(t_element)) {
5604  wd = 0;
5605  } else {
5606  wd = all_ones;
5607  }
5608  } break;
5609  case FCUNE: {
5610  if (s_element != t_element || std::isnan(s_element) ||
5611  std::isnan(t_element)) {
5612  wd = all_ones;
5613  } else {
5614  wd = 0;
5615  }
5616  } break;
5617  case FCNE: {
5618  if (s_element == t_element || std::isnan(s_element) ||
5619  std::isnan(t_element)) {
5620  wd = 0;
5621  } else {
5622  wd = all_ones;
5623  }
5624  } break;
5625  case FADD:
5626  wd = bit_cast<T_int>(s_element + t_element);
5627  break;
5628  case FSUB:
5629  wd = bit_cast<T_int>(s_element - t_element);
5630  break;
5631  case FMUL:
5632  wd = bit_cast<T_int>(s_element * t_element);
5633  break;
5634  case FDIV: {
5635  if (t_element == 0) {
5636  wd = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
5637  } else {
5638  wd = bit_cast<T_int>(s_element / t_element);
5639  }
5640  } break;
5641  case FMADD:
5642  wd = bit_cast<T_int>(
5643  std::fma(s_element, t_element, *reinterpret_cast<T_fp*>(&wd)));
5644  break;
5645  case FMSUB:
5646  wd = bit_cast<T_int>(
5647  std::fma(-s_element, t_element, *reinterpret_cast<T_fp*>(&wd)));
5648  break;
5649  case FEXP2:
5650  wd = bit_cast<T_int>(std::ldexp(s_element, static_cast<int>(wt)));
5651  break;
5652  case FMIN:
5653  wd = bit_cast<T_int>(std::min(s_element, t_element));
5654  break;
5655  case FMAX:
5656  wd = bit_cast<T_int>(std::max(s_element, t_element));
5657  break;
5658  case FMIN_A: {
5659  wd = bit_cast<T_int>(
5660  std::fabs(s_element) < std::fabs(t_element) ? s_element : t_element);
5661  } break;
5662  case FMAX_A: {
5663  wd = bit_cast<T_int>(
5664  std::fabs(s_element) > std::fabs(t_element) ? s_element : t_element);
5665  } break;
5666  case FSOR:
5667  case FSUNE:
5668  case FSNE:
5669  case FSAF:
5670  case FSUN:
5671  case FSEQ:
5672  case FSUEQ:
5673  case FSLT:
5674  case FSULT:
5675  case FSLE:
5676  case FSULE:
5677  UNIMPLEMENTED();
5678  break;
5679  default:
5680  UNREACHABLE();
5681  }
5682 }
5683 
5684 template <typename T_int, typename T_int_dbl, typename T_reg>
5685 void Msa3RFInstrHelper2(uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
5686  // typedef typename std::make_unsigned<T_int>::type T_uint;
5687  typedef typename std::make_unsigned<T_int_dbl>::type T_uint_dbl;
5688  const T_int max_int = std::numeric_limits<T_int>::max();
5689  const T_int min_int = std::numeric_limits<T_int>::min();
5690  const int shift = kBitsPerByte * sizeof(T_int) - 1;
5691  const T_int_dbl reg_s = ws;
5692  const T_int_dbl reg_t = wt;
5693  T_int_dbl product, result;
5694  product = reg_s * reg_t;
5695  switch (opcode) {
5696  case MUL_Q: {
5697  const T_int_dbl min_fix_dbl =
5698  bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
5699  const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5700  if (product == min_fix_dbl) {
5701  product = max_fix_dbl;
5702  }
5703  wd = static_cast<T_int>(product >> shift);
5704  } break;
5705  case MADD_Q: {
5706  result = (product + (static_cast<T_int_dbl>(wd) << shift)) >> shift;
5707  wd = static_cast<T_int>(
5708  result > max_int ? max_int : result < min_int ? min_int : result);
5709  } break;
5710  case MSUB_Q: {
5711  result = (-product + (static_cast<T_int_dbl>(wd) << shift)) >> shift;
5712  wd = static_cast<T_int>(
5713  result > max_int ? max_int : result < min_int ? min_int : result);
5714  } break;
5715  case MULR_Q: {
5716  const T_int_dbl min_fix_dbl =
5717  bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
5718  const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5719  if (product == min_fix_dbl) {
5720  wd = static_cast<T_int>(max_fix_dbl >> shift);
5721  break;
5722  }
5723  wd = static_cast<T_int>((product + (1 << (shift - 1))) >> shift);
5724  } break;
5725  case MADDR_Q: {
5726  result = (product + (static_cast<T_int_dbl>(wd) << shift) +
5727  (1 << (shift - 1))) >>
5728  shift;
5729  wd = static_cast<T_int>(
5730  result > max_int ? max_int : result < min_int ? min_int : result);
5731  } break;
5732  case MSUBR_Q: {
5733  result = (-product + (static_cast<T_int_dbl>(wd) << shift) +
5734  (1 << (shift - 1))) >>
5735  shift;
5736  wd = static_cast<T_int>(
5737  result > max_int ? max_int : result < min_int ? min_int : result);
5738  } break;
5739  default:
5740  UNREACHABLE();
5741  }
5742 }
5743 
5744 void Simulator::DecodeTypeMsa3RF() {
5745  DCHECK_EQ(kArchVariant, kMips64r6);
5746  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5747  uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
5748  msa_reg_t wd, ws, wt;
5749  if (opcode != FCAF) {
5750  get_msa_register(ws_reg(), &ws);
5751  get_msa_register(wt_reg(), &wt);
5752  }
5753  switch (opcode) {
5754  case FCAF:
5755  wd.d[0] = 0;
5756  wd.d[1] = 0;
5757  break;
5758  case FEXDO:
5759 #define PACK_FLOAT16(sign, exp, frac) \
5760  static_cast<uint16_t>(((sign) << 15) + ((exp) << 10) + (frac))
5761 #define FEXDO_DF(source, dst) \
5762  do { \
5763  element = source; \
5764  aSign = element >> 31; \
5765  aExp = element >> 23 & 0xFF; \
5766  aFrac = element & 0x007FFFFF; \
5767  if (aExp == 0xFF) { \
5768  if (aFrac) { \
5769  /* Input is a NaN */ \
5770  dst = 0x7DFFU; \
5771  break; \
5772  } \
5773  /* Infinity */ \
5774  dst = PACK_FLOAT16(aSign, 0x1F, 0); \
5775  break; \
5776  } else if (aExp == 0 && aFrac == 0) { \
5777  dst = PACK_FLOAT16(aSign, 0, 0); \
5778  break; \
5779  } else { \
5780  int maxexp = 29; \
5781  uint32_t mask; \
5782  uint32_t increment; \
5783  bool rounding_bumps_exp; \
5784  aFrac |= 0x00800000; \
5785  aExp -= 0x71; \
5786  if (aExp < 1) { \
5787  /* Will be denormal in halfprec */ \
5788  mask = 0x00FFFFFF; \
5789  if (aExp >= -11) { \
5790  mask >>= 11 + aExp; \
5791  } \
5792  } else { \
5793  /* Normal number in halfprec */ \
5794  mask = 0x00001FFF; \
5795  } \
5796  switch (MSACSR_ & 3) { \
5797  case kRoundToNearest: \
5798  increment = (mask + 1) >> 1; \
5799  if ((aFrac & mask) == increment) { \
5800  increment = aFrac & (increment << 1); \
5801  } \
5802  break; \
5803  case kRoundToPlusInf: \
5804  increment = aSign ? 0 : mask; \
5805  break; \
5806  case kRoundToMinusInf: \
5807  increment = aSign ? mask : 0; \
5808  break; \
5809  case kRoundToZero: \
5810  increment = 0; \
5811  break; \
5812  } \
5813  rounding_bumps_exp = (aFrac + increment >= 0x01000000); \
5814  if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) { \
5815  dst = PACK_FLOAT16(aSign, 0x1F, 0); \
5816  break; \
5817  } \
5818  aFrac += increment; \
5819  if (rounding_bumps_exp) { \
5820  aFrac >>= 1; \
5821  aExp++; \
5822  } \
5823  if (aExp < -10) { \
5824  dst = PACK_FLOAT16(aSign, 0, 0); \
5825  break; \
5826  } \
5827  if (aExp < 0) { \
5828  aFrac >>= -aExp; \
5829  aExp = 0; \
5830  } \
5831  dst = PACK_FLOAT16(aSign, aExp, aFrac >> 13); \
5832  } \
5833  } while (0);
5834  switch (DecodeMsaDataFormat()) {
5835  case MSA_HALF:
5836  for (int i = 0; i < kMSALanesWord; i++) {
5837  uint_fast32_t element;
5838  uint_fast32_t aSign, aFrac;
5839  int_fast32_t aExp;
5840  FEXDO_DF(ws.uw[i], wd.uh[i + kMSALanesHalf / 2])
5841  FEXDO_DF(wt.uw[i], wd.uh[i])
5842  }
5843  break;
5844  case MSA_WORD:
5845  for (int i = 0; i < kMSALanesDword; i++) {
5846  wd.w[i + kMSALanesWord / 2] = bit_cast<int32_t>(
5847  static_cast<float>(bit_cast<double>(ws.d[i])));
5848  wd.w[i] = bit_cast<int32_t>(
5849  static_cast<float>(bit_cast<double>(wt.d[i])));
5850  }
5851  break;
5852  default:
5853  UNREACHABLE();
5854  }
5855  break;
5856 #undef PACK_FLOAT16
5857 #undef FEXDO_DF
5858  case FTQ:
5859 #define FTQ_DF(source, dst, fp_type, int_type) \
5860  element = bit_cast<fp_type>(source) * \
5861  (1U << (sizeof(int_type) * kBitsPerByte - 1)); \
5862  if (element > std::numeric_limits<int_type>::max()) { \
5863  dst = std::numeric_limits<int_type>::max(); \
5864  } else if (element < std::numeric_limits<int_type>::min()) { \
5865  dst = std::numeric_limits<int_type>::min(); \
5866  } else if (std::isnan(element)) { \
5867  dst = 0; \
5868  } else { \
5869  int_type fixed_point; \
5870  round_according_to_msacsr(element, element, fixed_point); \
5871  dst = fixed_point; \
5872  }
5873 
5874  switch (DecodeMsaDataFormat()) {
5875  case MSA_HALF:
5876  for (int i = 0; i < kMSALanesWord; i++) {
5877  float element;
5878  FTQ_DF(ws.w[i], wd.h[i + kMSALanesHalf / 2], float, int16_t)
5879  FTQ_DF(wt.w[i], wd.h[i], float, int16_t)
5880  }
5881  break;
5882  case MSA_WORD:
5883  double element;
5884  for (int i = 0; i < kMSALanesDword; i++) {
5885  FTQ_DF(ws.d[i], wd.w[i + kMSALanesWord / 2], double, int32_t)
5886  FTQ_DF(wt.d[i], wd.w[i], double, int32_t)
5887  }
5888  break;
5889  default:
5890  UNREACHABLE();
5891  }
5892  break;
5893 #undef FTQ_DF
5894 #define MSA_3RF_DF(T1, T2, Lanes, ws, wt, wd) \
5895  for (int i = 0; i < Lanes; i++) { \
5896  Msa3RFInstrHelper<T1, T2>(opcode, ws, wt, wd); \
5897  }
5898 #define MSA_3RF_DF2(T1, T2, Lanes, ws, wt, wd) \
5899  for (int i = 0; i < Lanes; i++) { \
5900  Msa3RFInstrHelper2<T1, T2>(opcode, ws, wt, wd); \
5901  }
5902  case MADD_Q:
5903  case MSUB_Q:
5904  case MADDR_Q:
5905  case MSUBR_Q:
5906  get_msa_register(wd_reg(), &wd);
5907  V8_FALLTHROUGH;
5908  case MUL_Q:
5909  case MULR_Q:
5910  switch (DecodeMsaDataFormat()) {
5911  case MSA_HALF:
5912  MSA_3RF_DF2(int16_t, int32_t, kMSALanesHalf, ws.h[i], wt.h[i],
5913  wd.h[i])
5914  break;
5915  case MSA_WORD:
5916  MSA_3RF_DF2(int32_t, int64_t, kMSALanesWord, ws.w[i], wt.w[i],
5917  wd.w[i])
5918  break;
5919  default:
5920  UNREACHABLE();
5921  }
5922  break;
5923  default:
5924  if (opcode == FMADD || opcode == FMSUB) {
5925  get_msa_register(wd_reg(), &wd);
5926  }
5927  switch (DecodeMsaDataFormat()) {
5928  case MSA_WORD:
5929  MSA_3RF_DF(int32_t, float, kMSALanesWord, ws.w[i], wt.w[i], wd.w[i])
5930  break;
5931  case MSA_DWORD:
5932  MSA_3RF_DF(int64_t, double, kMSALanesDword, ws.d[i], wt.d[i], wd.d[i])
5933  break;
5934  default:
5935  UNREACHABLE();
5936  }
5937  break;
5938 #undef MSA_3RF_DF
5939 #undef MSA_3RF_DF2
5940  }
5941  set_msa_register(wd_reg(), &wd);
5942  TraceMSARegWr(&wd);
5943 }
5944 
5945 void Simulator::DecodeTypeMsaVec() {
5946  DCHECK_EQ(kArchVariant, kMips64r6);
5947  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5948  uint32_t opcode = instr_.InstructionBits() & kMsaVECMask;
5949  msa_reg_t wd, ws, wt;
5950 
5951  get_msa_register(instr_.WsValue(), ws.d);
5952  get_msa_register(instr_.WtValue(), wt.d);
5953  if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
5954  get_msa_register(instr_.WdValue(), wd.d);
5955  }
5956 
5957  for (int i = 0; i < kMSALanesDword; i++) {
5958  switch (opcode) {
5959  case AND_V:
5960  wd.d[i] = ws.d[i] & wt.d[i];
5961  break;
5962  case OR_V:
5963  wd.d[i] = ws.d[i] | wt.d[i];
5964  break;
5965  case NOR_V:
5966  wd.d[i] = ~(ws.d[i] | wt.d[i]);
5967  break;
5968  case XOR_V:
5969  wd.d[i] = ws.d[i] ^ wt.d[i];
5970  break;
5971  case BMNZ_V:
5972  wd.d[i] = (wt.d[i] & ws.d[i]) | (~wt.d[i] & wd.d[i]);
5973  break;
5974  case BMZ_V:
5975  wd.d[i] = (~wt.d[i] & ws.d[i]) | (wt.d[i] & wd.d[i]);
5976  break;
5977  case BSEL_V:
5978  wd.d[i] = (~wd.d[i] & ws.d[i]) | (wd.d[i] & wt.d[i]);
5979  break;
5980  default:
5981  UNREACHABLE();
5982  }
5983  }
5984  set_msa_register(instr_.WdValue(), wd.d);
5985  TraceMSARegWr(wd.d);
5986 }
5987 
5988 void Simulator::DecodeTypeMsa2R() {
5989  DCHECK_EQ(kArchVariant, kMips64r6);
5990  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5991  uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
5992  msa_reg_t wd, ws;
5993  switch (opcode) {
5994  case FILL:
5995  switch (DecodeMsaDataFormat()) {
5996  case MSA_BYTE: {
5997  int64_t rs = get_register(instr_.WsValue());
5998  for (int i = 0; i < kMSALanesByte; i++) {
5999  wd.b[i] = rs & 0xFFu;
6000  }
6001  set_msa_register(instr_.WdValue(), wd.b);
6002  TraceMSARegWr(wd.b);
6003  break;
6004  }
6005  case MSA_HALF: {
6006  int64_t rs = get_register(instr_.WsValue());
6007  for (int i = 0; i < kMSALanesHalf; i++) {
6008  wd.h[i] = rs & 0xFFFFu;
6009  }
6010  set_msa_register(instr_.WdValue(), wd.h);
6011  TraceMSARegWr(wd.h);
6012  break;
6013  }
6014  case MSA_WORD: {
6015  int64_t rs = get_register(instr_.WsValue());
6016  for (int i = 0; i < kMSALanesWord; i++) {
6017  wd.w[i] = rs & 0xFFFFFFFFu;
6018  }
6019  set_msa_register(instr_.WdValue(), wd.w);
6020  TraceMSARegWr(wd.w);
6021  break;
6022  }
6023  case MSA_DWORD: {
6024  int64_t rs = get_register(instr_.WsValue());
6025  wd.d[0] = wd.d[1] = rs;
6026  set_msa_register(instr_.WdValue(), wd.d);
6027  TraceMSARegWr(wd.d);
6028  break;
6029  }
6030  default:
6031  UNREACHABLE();
6032  }
6033  break;
6034  case PCNT:
6035 #define PCNT_DF(elem, num_of_lanes) \
6036  get_msa_register(instr_.WsValue(), ws.elem); \
6037  for (int i = 0; i < num_of_lanes; i++) { \
6038  uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
6039  wd.elem[i] = base::bits::CountPopulation(u64elem); \
6040  } \
6041  set_msa_register(instr_.WdValue(), wd.elem); \
6042  TraceMSARegWr(wd.elem)
6043 
6044  switch (DecodeMsaDataFormat()) {
6045  case MSA_BYTE:
6046  PCNT_DF(ub, kMSALanesByte);
6047  break;
6048  case MSA_HALF:
6049  PCNT_DF(uh, kMSALanesHalf);
6050  break;
6051  case MSA_WORD:
6052  PCNT_DF(uw, kMSALanesWord);
6053  break;
6054  case MSA_DWORD:
6055  PCNT_DF(ud, kMSALanesDword);
6056  break;
6057  default:
6058  UNREACHABLE();
6059  }
6060 #undef PCNT_DF
6061  break;
6062  case NLOC:
6063 #define NLOC_DF(elem, num_of_lanes) \
6064  get_msa_register(instr_.WsValue(), ws.elem); \
6065  for (int i = 0; i < num_of_lanes; i++) { \
6066  const uint64_t mask = (num_of_lanes == kMSALanesDword) \
6067  ? UINT64_MAX \
6068  : (1ULL << (kMSARegSize / num_of_lanes)) - 1; \
6069  uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask; \
6070  wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
6071  (64 - kMSARegSize / num_of_lanes); \
6072  } \
6073  set_msa_register(instr_.WdValue(), wd.elem); \
6074  TraceMSARegWr(wd.elem)
6075 
6076  switch (DecodeMsaDataFormat()) {
6077  case MSA_BYTE:
6078  NLOC_DF(ub, kMSALanesByte);
6079  break;
6080  case MSA_HALF:
6081  NLOC_DF(uh, kMSALanesHalf);
6082  break;
6083  case MSA_WORD:
6084  NLOC_DF(uw, kMSALanesWord);
6085  break;
6086  case MSA_DWORD:
6087  NLOC_DF(ud, kMSALanesDword);
6088  break;
6089  default:
6090  UNREACHABLE();
6091  }
6092 #undef NLOC_DF
6093  break;
6094  case NLZC:
6095 #define NLZC_DF(elem, num_of_lanes) \
6096  get_msa_register(instr_.WsValue(), ws.elem); \
6097  for (int i = 0; i < num_of_lanes; i++) { \
6098  uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
6099  wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
6100  (64 - kMSARegSize / num_of_lanes); \
6101  } \
6102  set_msa_register(instr_.WdValue(), wd.elem); \
6103  TraceMSARegWr(wd.elem)
6104 
6105  switch (DecodeMsaDataFormat()) {
6106  case MSA_BYTE:
6107  NLZC_DF(ub, kMSALanesByte);
6108  break;
6109  case MSA_HALF:
6110  NLZC_DF(uh, kMSALanesHalf);
6111  break;
6112  case MSA_WORD:
6113  NLZC_DF(uw, kMSALanesWord);
6114  break;
6115  case MSA_DWORD:
6116  NLZC_DF(ud, kMSALanesDword);
6117  break;
6118  default:
6119  UNREACHABLE();
6120  }
6121 #undef NLZC_DF
6122  break;
6123  default:
6124  UNREACHABLE();
6125  }
6126 }
6127 
6128 #define BIT(n) (0x1LL << n)
6129 #define QUIET_BIT_S(nan) (bit_cast<int32_t>(nan) & BIT(22))
6130 #define QUIET_BIT_D(nan) (bit_cast<int64_t>(nan) & BIT(51))
6131 static inline bool isSnan(float fp) { return !QUIET_BIT_S(fp); }
6132 static inline bool isSnan(double fp) { return !QUIET_BIT_D(fp); }
6133 #undef QUIET_BIT_S
6134 #undef QUIET_BIT_D
6135 
6136 template <typename T_int, typename T_fp, typename T_src, typename T_dst>
6137 T_int Msa2RFInstrHelper(uint32_t opcode, T_src src, T_dst& dst,
6138  Simulator* sim) {
6139  typedef typename std::make_unsigned<T_int>::type T_uint;
6140  switch (opcode) {
6141  case FCLASS: {
6142 #define SNAN_BIT BIT(0)
6143 #define QNAN_BIT BIT(1)
6144 #define NEG_INFINITY_BIT BIT(2)
6145 #define NEG_NORMAL_BIT BIT(3)
6146 #define NEG_SUBNORMAL_BIT BIT(4)
6147 #define NEG_ZERO_BIT BIT(5)
6148 #define POS_INFINITY_BIT BIT(6)
6149 #define POS_NORMAL_BIT BIT(7)
6150 #define POS_SUBNORMAL_BIT BIT(8)
6151 #define POS_ZERO_BIT BIT(9)
6152  T_fp element = *reinterpret_cast<T_fp*>(&src);
6153  switch (std::fpclassify(element)) {
6154  case FP_INFINITE:
6155  if (std::signbit(element)) {
6156  dst = NEG_INFINITY_BIT;
6157  } else {
6158  dst = POS_INFINITY_BIT;
6159  }
6160  break;
6161  case FP_NAN:
6162  if (isSnan(element)) {
6163  dst = SNAN_BIT;
6164  } else {
6165  dst = QNAN_BIT;
6166  }
6167  break;
6168  case FP_NORMAL:
6169  if (std::signbit(element)) {
6170  dst = NEG_NORMAL_BIT;
6171  } else {
6172  dst = POS_NORMAL_BIT;
6173  }
6174  break;
6175  case FP_SUBNORMAL:
6176  if (std::signbit(element)) {
6177  dst = NEG_SUBNORMAL_BIT;
6178  } else {
6179  dst = POS_SUBNORMAL_BIT;
6180  }
6181  break;
6182  case FP_ZERO:
6183  if (std::signbit(element)) {
6184  dst = NEG_ZERO_BIT;
6185  } else {
6186  dst = POS_ZERO_BIT;
6187  }
6188  break;
6189  default:
6190  UNREACHABLE();
6191  }
6192  break;
6193  }
6194 #undef BIT
6195 #undef SNAN_BIT
6196 #undef QNAN_BIT
6197 #undef NEG_INFINITY_BIT
6198 #undef NEG_NORMAL_BIT
6199 #undef NEG_SUBNORMAL_BIT
6200 #undef NEG_ZERO_BIT
6201 #undef POS_INFINITY_BIT
6202 #undef POS_NORMAL_BIT
6203 #undef POS_SUBNORMAL_BIT
6204 #undef POS_ZERO_BIT
6205  case FTRUNC_S: {
6206  T_fp element = bit_cast<T_fp>(src);
6207  const T_int max_int = std::numeric_limits<T_int>::max();
6208  const T_int min_int = std::numeric_limits<T_int>::min();
6209  if (std::isnan(element)) {
6210  dst = 0;
6211  } else if (element >= max_int || element <= min_int) {
6212  dst = element >= max_int ? max_int : min_int;
6213  } else {
6214  dst = static_cast<T_int>(std::trunc(element));
6215  }
6216  break;
6217  }
6218  case FTRUNC_U: {
6219  T_fp element = bit_cast<T_fp>(src);
6220  const T_uint max_int = std::numeric_limits<T_uint>::max();
6221  if (std::isnan(element)) {
6222  dst = 0;
6223  } else if (element >= max_int || element <= 0) {
6224  dst = element >= max_int ? max_int : 0;
6225  } else {
6226  dst = static_cast<T_uint>(std::trunc(element));
6227  }
6228  break;
6229  }
6230  case FSQRT: {
6231  T_fp element = bit_cast<T_fp>(src);
6232  if (element < 0 || std::isnan(element)) {
6233  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6234  } else {
6235  dst = bit_cast<T_int>(std::sqrt(element));
6236  }
6237  break;
6238  }
6239  case FRSQRT: {
6240  T_fp element = bit_cast<T_fp>(src);
6241  if (element < 0 || std::isnan(element)) {
6242  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6243  } else {
6244  dst = bit_cast<T_int>(1 / std::sqrt(element));
6245  }
6246  break;
6247  }
6248  case FRCP: {
6249  T_fp element = bit_cast<T_fp>(src);
6250  if (std::isnan(element)) {
6251  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6252  } else {
6253  dst = bit_cast<T_int>(1 / element);
6254  }
6255  break;
6256  }
6257  case FRINT: {
6258  T_fp element = bit_cast<T_fp>(src);
6259  if (std::isnan(element)) {
6260  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6261  } else {
6262  T_int dummy;
6263  sim->round_according_to_msacsr<T_fp, T_int>(element, element, dummy);
6264  dst = bit_cast<T_int>(element);
6265  }
6266  break;
6267  }
6268  case FLOG2: {
6269  T_fp element = bit_cast<T_fp>(src);
6270  switch (std::fpclassify(element)) {
6271  case FP_NORMAL:
6272  case FP_SUBNORMAL:
6273  dst = bit_cast<T_int>(std::logb(element));
6274  break;
6275  case FP_ZERO:
6276  dst = bit_cast<T_int>(-std::numeric_limits<T_fp>::infinity());
6277  break;
6278  case FP_NAN:
6279  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6280  break;
6281  case FP_INFINITE:
6282  if (element < 0) {
6283  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6284  } else {
6285  dst = bit_cast<T_int>(std::numeric_limits<T_fp>::infinity());
6286  }
6287  break;
6288  default:
6289  UNREACHABLE();
6290  }
6291  break;
6292  }
6293  case FTINT_S: {
6294  T_fp element = bit_cast<T_fp>(src);
6295  const T_int max_int = std::numeric_limits<T_int>::max();
6296  const T_int min_int = std::numeric_limits<T_int>::min();
6297  if (std::isnan(element)) {
6298  dst = 0;
6299  } else if (element < min_int || element > max_int) {
6300  dst = element > max_int ? max_int : min_int;
6301  } else {
6302  sim->round_according_to_msacsr<T_fp, T_int>(element, element, dst);
6303  }
6304  break;
6305  }
6306  case FTINT_U: {
6307  T_fp element = bit_cast<T_fp>(src);
6308  const T_uint max_uint = std::numeric_limits<T_uint>::max();
6309  if (std::isnan(element)) {
6310  dst = 0;
6311  } else if (element < 0 || element > max_uint) {
6312  dst = element > max_uint ? max_uint : 0;
6313  } else {
6314  T_uint res;
6315  sim->round_according_to_msacsr<T_fp, T_uint>(element, element, res);
6316  dst = *reinterpret_cast<T_int*>(&res);
6317  }
6318  break;
6319  }
6320  case FFINT_S:
6321  dst = bit_cast<T_int>(static_cast<T_fp>(src));
6322  break;
6323  case FFINT_U:
6324  typedef typename std::make_unsigned<T_src>::type uT_src;
6325  dst = bit_cast<T_int>(static_cast<T_fp>(bit_cast<uT_src>(src)));
6326  break;
6327  default:
6328  UNREACHABLE();
6329  }
6330  return 0;
6331 }
6332 
6333 template <typename T_int, typename T_fp, typename T_reg>
6334 T_int Msa2RFInstrHelper2(uint32_t opcode, T_reg ws, int i) {
6335  switch (opcode) {
6336 #define EXTRACT_FLOAT16_SIGN(fp16) (fp16 >> 15)
6337 #define EXTRACT_FLOAT16_EXP(fp16) (fp16 >> 10 & 0x1F)
6338 #define EXTRACT_FLOAT16_FRAC(fp16) (fp16 & 0x3FF)
6339 #define PACK_FLOAT32(sign, exp, frac) \
6340  static_cast<uint32_t>(((sign) << 31) + ((exp) << 23) + (frac))
6341 #define FEXUP_DF(src_index) \
6342  uint_fast16_t element = ws.uh[src_index]; \
6343  uint_fast32_t aSign, aFrac; \
6344  int_fast32_t aExp; \
6345  aSign = EXTRACT_FLOAT16_SIGN(element); \
6346  aExp = EXTRACT_FLOAT16_EXP(element); \
6347  aFrac = EXTRACT_FLOAT16_FRAC(element); \
6348  if (V8_LIKELY(aExp && aExp != 0x1F)) { \
6349  return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \
6350  } else if (aExp == 0x1F) { \
6351  if (aFrac) { \
6352  return bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN()); \
6353  } else { \
6354  return bit_cast<uint32_t>(std::numeric_limits<float>::infinity()) | \
6355  static_cast<uint32_t>(aSign) << 31; \
6356  } \
6357  } else { \
6358  if (aFrac == 0) { \
6359  return PACK_FLOAT32(aSign, 0, 0); \
6360  } else { \
6361  int_fast16_t shiftCount = \
6362  base::bits::CountLeadingZeros32(static_cast<uint32_t>(aFrac)) - 21; \
6363  aFrac <<= shiftCount; \
6364  aExp = -shiftCount; \
6365  return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \
6366  } \
6367  }
6368  case FEXUPL:
6369  if (std::is_same<int32_t, T_int>::value) {
6370  FEXUP_DF(i + kMSALanesWord)
6371  } else {
6372  return bit_cast<int64_t>(
6373  static_cast<double>(bit_cast<float>(ws.w[i + kMSALanesDword])));
6374  }
6375  case FEXUPR:
6376  if (std::is_same<int32_t, T_int>::value) {
6377  FEXUP_DF(i)
6378  } else {
6379  return bit_cast<int64_t>(static_cast<double>(bit_cast<float>(ws.w[i])));
6380  }
6381  case FFQL: {
6382  if (std::is_same<int32_t, T_int>::value) {
6383  return bit_cast<int32_t>(static_cast<float>(ws.h[i + kMSALanesWord]) /
6384  (1U << 15));
6385  } else {
6386  return bit_cast<int64_t>(static_cast<double>(ws.w[i + kMSALanesDword]) /
6387  (1U << 31));
6388  }
6389  break;
6390  }
6391  case FFQR: {
6392  if (std::is_same<int32_t, T_int>::value) {
6393  return bit_cast<int32_t>(static_cast<float>(ws.h[i]) / (1U << 15));
6394  } else {
6395  return bit_cast<int64_t>(static_cast<double>(ws.w[i]) / (1U << 31));
6396  }
6397  break;
6398  default:
6399  UNREACHABLE();
6400  }
6401  }
6402 #undef EXTRACT_FLOAT16_SIGN
6403 #undef EXTRACT_FLOAT16_EXP
6404 #undef EXTRACT_FLOAT16_FRAC
6405 #undef PACK_FLOAT32
6406 #undef FEXUP_DF
6407 }
6408 
6409 void Simulator::DecodeTypeMsa2RF() {
6410  DCHECK_EQ(kArchVariant, kMips64r6);
6411  DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
6412  uint32_t opcode = instr_.InstructionBits() & kMsa2RFMask;
6413  msa_reg_t wd, ws;
6414  get_msa_register(ws_reg(), &ws);
6415  if (opcode == FEXUPL || opcode == FEXUPR || opcode == FFQL ||
6416  opcode == FFQR) {
6417  switch (DecodeMsaDataFormat()) {
6418  case MSA_WORD:
6419  for (int i = 0; i < kMSALanesWord; i++) {
6420  wd.w[i] = Msa2RFInstrHelper2<int32_t, float>(opcode, ws, i);
6421  }
6422  break;
6423  case MSA_DWORD:
6424  for (int i = 0; i < kMSALanesDword; i++) {
6425  wd.d[i] = Msa2RFInstrHelper2<int64_t, double>(opcode, ws, i);
6426  }
6427  break;
6428  default:
6429  UNREACHABLE();
6430  }
6431  } else {
6432  switch (DecodeMsaDataFormat()) {
6433  case MSA_WORD:
6434  for (int i = 0; i < kMSALanesWord; i++) {
6435  Msa2RFInstrHelper<int32_t, float>(opcode, ws.w[i], wd.w[i], this);
6436  }
6437  break;
6438  case MSA_DWORD:
6439  for (int i = 0; i < kMSALanesDword; i++) {
6440  Msa2RFInstrHelper<int64_t, double>(opcode, ws.d[i], wd.d[i], this);
6441  }
6442  break;
6443  default:
6444  UNREACHABLE();
6445  }
6446  }
6447  set_msa_register(wd_reg(), &wd);
6448  TraceMSARegWr(&wd);
6449 }
6450 
6451 void Simulator::DecodeTypeRegister() {
6452  // ---------- Execution.
6453  switch (instr_.OpcodeFieldRaw()) {
6454  case COP1:
6455  DecodeTypeRegisterCOP1();
6456  break;
6457  case COP1X:
6458  DecodeTypeRegisterCOP1X();
6459  break;
6460  case SPECIAL:
6461  DecodeTypeRegisterSPECIAL();
6462  break;
6463  case SPECIAL2:
6464  DecodeTypeRegisterSPECIAL2();
6465  break;
6466  case SPECIAL3:
6467  DecodeTypeRegisterSPECIAL3();
6468  break;
6469  case MSA:
6470  switch (instr_.MSAMinorOpcodeField()) {
6471  case kMsaMinor3R:
6472  DecodeTypeMsa3R();
6473  break;
6474  case kMsaMinor3RF:
6475  DecodeTypeMsa3RF();
6476  break;
6477  case kMsaMinorVEC:
6478  DecodeTypeMsaVec();
6479  break;
6480  case kMsaMinor2R:
6481  DecodeTypeMsa2R();
6482  break;
6483  case kMsaMinor2RF:
6484  DecodeTypeMsa2RF();
6485  break;
6486  case kMsaMinorELM:
6487  DecodeTypeMsaELM();
6488  break;
6489  default:
6490  UNREACHABLE();
6491  }
6492  break;
6493  // Unimplemented opcodes raised an error in the configuration step before,
6494  // so we can use the default here to set the destination register in common
6495  // cases.
6496  default:
6497  UNREACHABLE();
6498  }
6499 }
6500 
6501 
6502 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc).
6503 void Simulator::DecodeTypeImmediate() {
6504  // Instruction fields.
6505  Opcode op = instr_.OpcodeFieldRaw();
6506  int32_t rs_reg = instr_.RsValue();
6507  int64_t rs = get_register(instr_.RsValue());
6508  uint64_t rs_u = static_cast<uint64_t>(rs);
6509  int32_t rt_reg = instr_.RtValue(); // Destination register.
6510  int64_t rt = get_register(rt_reg);
6511  int16_t imm16 = instr_.Imm16Value();
6512  int32_t imm18 = instr_.Imm18Value();
6513 
6514  int32_t ft_reg = instr_.FtValue(); // Destination register.
6515 
6516  // Zero extended immediate.
6517  uint64_t oe_imm16 = 0xFFFF & imm16;
6518  // Sign extended immediate.
6519  int64_t se_imm16 = imm16;
6520  int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xFFFFFFFFFFFC0000 : 0);
6521 
6522  // Next pc.
6523  int64_t next_pc = bad_ra;
6524 
6525  // Used for conditional branch instructions.
6526  bool execute_branch_delay_instruction = false;
6527 
6528  // Used for arithmetic instructions.
6529  int64_t alu_out = 0;
6530 
6531  // Used for memory instructions.
6532  int64_t addr = 0x0;
6533  // Alignment for 32-bit integers used in LWL, LWR, etc.
6534  const int kInt32AlignmentMask = sizeof(uint32_t) - 1;
6535  // Alignment for 64-bit integers used in LDL, LDR, etc.
6536  const int kInt64AlignmentMask = sizeof(uint64_t) - 1;
6537 
6538  // Branch instructions common part.
6539  auto BranchAndLinkHelper =
6540  [this, &next_pc, &execute_branch_delay_instruction](bool do_branch) {
6541  execute_branch_delay_instruction = true;
6542  int64_t current_pc = get_pc();
6543  set_register(31, current_pc + 2 * kInstrSize);
6544  if (do_branch) {
6545  int16_t imm16 = instr_.Imm16Value();
6546  next_pc = current_pc + (imm16 << 2) + kInstrSize;
6547  } else {
6548  next_pc = current_pc + 2 * kInstrSize;
6549  }
6550  };
6551 
6552  auto BranchHelper = [this, &next_pc,
6553  &execute_branch_delay_instruction](bool do_branch) {
6554  execute_branch_delay_instruction = true;
6555  int64_t current_pc = get_pc();
6556  if (do_branch) {
6557  int16_t imm16 = instr_.Imm16Value();
6558  next_pc = current_pc + (imm16 << 2) + kInstrSize;
6559  } else {
6560  next_pc = current_pc + 2 * kInstrSize;
6561  }
6562  };
6563 
6564  auto BranchHelper_MSA = [this, &next_pc, imm16,
6565  &execute_branch_delay_instruction](bool do_branch) {
6566  execute_branch_delay_instruction = true;
6567  int64_t current_pc = get_pc();
6568  const int32_t bitsIn16Int = sizeof(int16_t) * kBitsPerByte;
6569  if (do_branch) {
6570  if (FLAG_debug_code) {
6571  int16_t bits = imm16 & 0xFC;
6572  if (imm16 >= 0) {
6573  CHECK_EQ(bits, 0);
6574  } else {
6575  CHECK_EQ(bits ^ 0xFC, 0);
6576  }
6577  }
6578  // jump range :[pc + kInstrSize - 512 * kInstrSize,
6579  // pc + kInstrSize + 511 * kInstrSize]
6580  int16_t offset = static_cast<int16_t>(imm16 << (bitsIn16Int - 10)) >>
6581  (bitsIn16Int - 12);
6582  next_pc = current_pc + offset + kInstrSize;
6583  } else {
6584  next_pc = current_pc + 2 * kInstrSize;
6585  }
6586  };
6587 
6588  auto BranchAndLinkCompactHelper = [this, &next_pc](bool do_branch, int bits) {
6589  int64_t current_pc = get_pc();
6590  CheckForbiddenSlot(current_pc);
6591  if (do_branch) {
6592  int32_t imm = instr_.ImmValue(bits);
6593  imm <<= 32 - bits;
6594  imm >>= 32 - bits;
6595  next_pc = current_pc + (imm << 2) + kInstrSize;
6596  set_register(31, current_pc + kInstrSize);
6597  }
6598  };
6599 
6600  auto BranchCompactHelper = [this, &next_pc](bool do_branch, int bits) {
6601  int64_t current_pc = get_pc();
6602  CheckForbiddenSlot(current_pc);
6603  if (do_branch) {
6604  int32_t imm = instr_.ImmValue(bits);
6605  imm <<= 32 - bits;
6606  imm >>= 32 - bits;
6607  next_pc = get_pc() + (imm << 2) + kInstrSize;
6608  }
6609  };
6610 
6611  switch (op) {
6612  // ------------- COP1. Coprocessor instructions.
6613  case COP1:
6614  switch (instr_.RsFieldRaw()) {
6615  case BC1: { // Branch on coprocessor condition.
6616  uint32_t cc = instr_.FBccValue();
6617  uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
6618  uint32_t cc_value = test_fcsr_bit(fcsr_cc);
6619  bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value;
6620  BranchHelper(do_branch);
6621  break;
6622  }
6623  case BC1EQZ:
6624  BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
6625  break;
6626  case BC1NEZ:
6627  BranchHelper(get_fpu_register(ft_reg) & 0x1);
6628  break;
6629  case BZ_V: {
6630  msa_reg_t wt;
6631  get_msa_register(wt_reg(), &wt);
6632  BranchHelper_MSA(wt.d[0] == 0 && wt.d[1] == 0);
6633  } break;
6634 #define BZ_DF(witdh, lanes) \
6635  { \
6636  msa_reg_t wt; \
6637  get_msa_register(wt_reg(), &wt); \
6638  int i; \
6639  for (i = 0; i < lanes; ++i) { \
6640  if (wt.witdh[i] == 0) { \
6641  break; \
6642  } \
6643  } \
6644  BranchHelper_MSA(i != lanes); \
6645  }
6646  case BZ_B:
6647  BZ_DF(b, kMSALanesByte)
6648  break;
6649  case BZ_H:
6650  BZ_DF(h, kMSALanesHalf)
6651  break;
6652  case BZ_W:
6653  BZ_DF(w, kMSALanesWord)
6654  break;
6655  case BZ_D:
6656  BZ_DF(d, kMSALanesDword)
6657  break;
6658 #undef BZ_DF
6659  case BNZ_V: {
6660  msa_reg_t wt;
6661  get_msa_register(wt_reg(), &wt);
6662  BranchHelper_MSA(wt.d[0] != 0 || wt.d[1] != 0);
6663  } break;
6664 #define BNZ_DF(witdh, lanes) \
6665  { \
6666  msa_reg_t wt; \
6667  get_msa_register(wt_reg(), &wt); \
6668  int i; \
6669  for (i = 0; i < lanes; ++i) { \
6670  if (wt.witdh[i] == 0) { \
6671  break; \
6672  } \
6673  } \
6674  BranchHelper_MSA(i == lanes); \
6675  }
6676  case BNZ_B:
6677  BNZ_DF(b, kMSALanesByte)
6678  break;
6679  case BNZ_H:
6680  BNZ_DF(h, kMSALanesHalf)
6681  break;
6682  case BNZ_W:
6683  BNZ_DF(w, kMSALanesWord)
6684  break;
6685  case BNZ_D:
6686  BNZ_DF(d, kMSALanesDword)
6687  break;
6688 #undef BNZ_DF
6689  default:
6690  UNREACHABLE();
6691  }
6692  break;
6693  // ------------- REGIMM class.
6694  case REGIMM:
6695  switch (instr_.RtFieldRaw()) {
6696  case BLTZ:
6697  BranchHelper(rs < 0);
6698  break;
6699  case BGEZ:
6700  BranchHelper(rs >= 0);
6701  break;
6702  case BLTZAL:
6703  BranchAndLinkHelper(rs < 0);
6704  break;
6705  case BGEZAL:
6706  BranchAndLinkHelper(rs >= 0);
6707  break;
6708  case DAHI:
6709  SetResult(rs_reg, rs + (se_imm16 << 32));
6710  break;
6711  case DATI:
6712  SetResult(rs_reg, rs + (se_imm16 << 48));
6713  break;
6714  default:
6715  UNREACHABLE();
6716  }
6717  break; // case REGIMM.
6718  // ------------- Branch instructions.
6719  // When comparing to zero, the encoding of rt field is always 0, so we don't
6720  // need to replace rt with zero.
6721  case BEQ:
6722  BranchHelper(rs == rt);
6723  break;
6724  case BNE:
6725  BranchHelper(rs != rt);
6726  break;
6727  case POP06: // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6)
6728  if (kArchVariant == kMips64r6) {
6729  if (rt_reg != 0) {
6730  if (rs_reg == 0) { // BLEZALC
6731  BranchAndLinkCompactHelper(rt <= 0, 16);
6732  } else {
6733  if (rs_reg == rt_reg) { // BGEZALC
6734  BranchAndLinkCompactHelper(rt >= 0, 16);
6735  } else { // BGEUC
6736  BranchCompactHelper(
6737  static_cast<uint64_t>(rs) >= static_cast<uint64_t>(rt), 16);
6738  }
6739  }
6740  } else { // BLEZ
6741  BranchHelper(rs <= 0);
6742  }
6743  } else { // BLEZ
6744  BranchHelper(rs <= 0);
6745  }
6746  break;
6747  case POP07: // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6)
6748  if (kArchVariant == kMips64r6) {
6749  if (rt_reg != 0) {
6750  if (rs_reg == 0) { // BGTZALC
6751  BranchAndLinkCompactHelper(rt > 0, 16);
6752  } else {
6753  if (rt_reg == rs_reg) { // BLTZALC
6754  BranchAndLinkCompactHelper(rt < 0, 16);
6755  } else { // BLTUC
6756  BranchCompactHelper(
6757  static_cast<uint64_t>(rs) < static_cast<uint64_t>(rt), 16);
6758  }
6759  }
6760  } else { // BGTZ
6761  BranchHelper(rs > 0);
6762  }
6763  } else { // BGTZ
6764  BranchHelper(rs > 0);
6765  }
6766  break;
6767  case POP26: // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6)
6768  if (kArchVariant == kMips64r6) {
6769  if (rt_reg != 0) {
6770  if (rs_reg == 0) { // BLEZC
6771  BranchCompactHelper(rt <= 0, 16);
6772  } else {
6773  if (rs_reg == rt_reg) { // BGEZC
6774  BranchCompactHelper(rt >= 0, 16);
6775  } else { // BGEC/BLEC
6776  BranchCompactHelper(rs >= rt, 16);
6777  }
6778  }
6779  }
6780  } else { // BLEZL
6781  BranchAndLinkHelper(rs <= 0);
6782  }
6783  break;
6784  case POP27: // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6)
6785  if (kArchVariant == kMips64r6) {
6786  if (rt_reg != 0) {
6787  if (rs_reg == 0) { // BGTZC
6788  BranchCompactHelper(rt > 0, 16);
6789  } else {
6790  if (rs_reg == rt_reg) { // BLTZC
6791  BranchCompactHelper(rt < 0, 16);
6792  } else { // BLTC/BGTC
6793  BranchCompactHelper(rs < rt, 16);
6794  }
6795  }
6796  }
6797  } else { // BGTZL
6798  BranchAndLinkHelper(rs > 0);
6799  }
6800  break;
6801  case POP66: // BEQZC, JIC
6802  if (rs_reg != 0) { // BEQZC
6803  BranchCompactHelper(rs == 0, 21);
6804  } else { // JIC
6805  next_pc = rt + imm16;
6806  }
6807  break;
6808  case POP76: // BNEZC, JIALC
6809  if (rs_reg != 0) { // BNEZC
6810  BranchCompactHelper(rs != 0, 21);
6811  } else { // JIALC
6812  int64_t current_pc = get_pc();
6813  set_register(31, current_pc + kInstrSize);
6814  next_pc = rt + imm16;
6815  }
6816  break;
6817  case BC:
6818  BranchCompactHelper(true, 26);
6819  break;
6820  case BALC:
6821  BranchAndLinkCompactHelper(true, 26);
6822  break;
6823  case POP10: // BOVC, BEQZALC, BEQC / ADDI (pre-r6)
6824  if (kArchVariant == kMips64r6) {
6825  if (rs_reg >= rt_reg) { // BOVC
6826  bool condition = !is_int32(rs) || !is_int32(rt) || !is_int32(rs + rt);
6827  BranchCompactHelper(condition, 16);
6828  } else {
6829  if (rs_reg == 0) { // BEQZALC
6830  BranchAndLinkCompactHelper(rt == 0, 16);
6831  } else { // BEQC
6832  BranchCompactHelper(rt == rs, 16);
6833  }
6834  }
6835  } else { // ADDI
6836  if (HaveSameSign(rs, se_imm16)) {
6837  if (rs > 0) {
6838  if (rs <= Registers::kMaxValue - se_imm16) {
6839  SignalException(kIntegerOverflow);
6840  }
6841  } else if (rs < 0) {
6842  if (rs >= Registers::kMinValue - se_imm16) {
6843  SignalException(kIntegerUnderflow);
6844  }
6845  }
6846  }
6847  SetResult(rt_reg, rs + se_imm16);
6848  }
6849  break;
6850  case POP30: // BNVC, BNEZALC, BNEC / DADDI (pre-r6)
6851  if (kArchVariant == kMips64r6) {
6852  if (rs_reg >= rt_reg) { // BNVC
6853  bool condition = is_int32(rs) && is_int32(rt) && is_int32(rs + rt);
6854  BranchCompactHelper(condition, 16);
6855  } else {
6856  if (rs_reg == 0) { // BNEZALC
6857  BranchAndLinkCompactHelper(rt != 0, 16);
6858  } else { // BNEC
6859  BranchCompactHelper(rt != rs, 16);
6860  }
6861  }
6862  }
6863  break;
6864  // ------------- Arithmetic instructions.
6865  case ADDIU: {
6866  int32_t alu32_out = static_cast<int32_t>(rs + se_imm16);
6867  // Sign-extend result of 32bit operation into 64bit register.
6868  SetResult(rt_reg, static_cast<int64_t>(alu32_out));
6869  break;
6870  }
6871  case DADDIU:
6872  SetResult(rt_reg, rs + se_imm16);
6873  break;
6874  case SLTI:
6875  SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
6876  break;
6877  case SLTIU:
6878  SetResult(rt_reg, rs_u < static_cast<uint64_t>(se_imm16) ? 1 : 0);
6879  break;
6880  case ANDI:
6881  SetResult(rt_reg, rs & oe_imm16);
6882  break;
6883  case ORI:
6884  SetResult(rt_reg, rs | oe_imm16);
6885  break;
6886  case XORI:
6887  SetResult(rt_reg, rs ^ oe_imm16);
6888  break;
6889  case LUI:
6890  if (rs_reg != 0) {
6891  // AUI instruction.
6892  DCHECK_EQ(kArchVariant, kMips64r6);
6893  int32_t alu32_out = static_cast<int32_t>(rs + (se_imm16 << 16));
6894  SetResult(rt_reg, static_cast<int64_t>(alu32_out));
6895  } else {
6896  // LUI instruction.
6897  int32_t alu32_out = static_cast<int32_t>(oe_imm16 << 16);
6898  // Sign-extend result of 32bit operation into 64bit register.
6899  SetResult(rt_reg, static_cast<int64_t>(alu32_out));
6900  }
6901  break;
6902  case DAUI:
6903  DCHECK_EQ(kArchVariant, kMips64r6);
6904  DCHECK_NE(rs_reg, 0);
6905  SetResult(rt_reg, rs + (se_imm16 << 16));
6906  break;
6907  // ------------- Memory instructions.
6908  case LB:
6909  set_register(rt_reg, ReadB(rs + se_imm16));
6910  break;
6911  case LH:
6912  set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr()));
6913  break;
6914  case LWL: {
6915  // al_offset is offset of the effective address within an aligned word.
6916  uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
6917  uint8_t byte_shift = kInt32AlignmentMask - al_offset;
6918  uint32_t mask = (1 << byte_shift * 8) - 1;
6919  addr = rs + se_imm16 - al_offset;
6920  int32_t val = ReadW(addr, instr_.instr());
6921  val <<= byte_shift * 8;
6922  val |= rt & mask;
6923  set_register(rt_reg, static_cast<int64_t>(val));
6924  break;
6925  }
6926  case LW:
6927  set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
6928  break;
6929  case LWU:
6930  set_register(rt_reg, ReadWU(rs + se_imm16, instr_.instr()));
6931  break;
6932  case LD:
6933  set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr()));
6934  break;
6935  case LBU:
6936  set_register(rt_reg, ReadBU(rs + se_imm16));
6937  break;
6938  case LHU:
6939  set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr()));
6940  break;
6941  case LWR: {
6942  // al_offset is offset of the effective address within an aligned word.
6943  uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
6944  uint8_t byte_shift = kInt32AlignmentMask - al_offset;
6945  uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
6946  addr = rs + se_imm16 - al_offset;
6947  alu_out = ReadW(addr, instr_.instr());
6948  alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
6949  alu_out |= rt & mask;
6950  set_register(rt_reg, alu_out);
6951  break;
6952  }
6953  case LDL: {
6954  // al_offset is offset of the effective address within an aligned word.
6955  uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
6956  uint8_t byte_shift = kInt64AlignmentMask - al_offset;
6957  uint64_t mask = (1UL << byte_shift * 8) - 1;
6958  addr = rs + se_imm16 - al_offset;
6959  alu_out = Read2W(addr, instr_.instr());
6960  alu_out <<= byte_shift * 8;
6961  alu_out |= rt & mask;
6962  set_register(rt_reg, alu_out);
6963  break;
6964  }
6965  case LDR: {
6966  // al_offset is offset of the effective address within an aligned word.
6967  uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
6968  uint8_t byte_shift = kInt64AlignmentMask - al_offset;
6969  uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL;
6970  addr = rs + se_imm16 - al_offset;
6971  alu_out = Read2W(addr, instr_.instr());
6972  alu_out = alu_out >> al_offset * 8;
6973  alu_out |= rt & mask;
6974  set_register(rt_reg, alu_out);
6975  break;
6976  }
6977  case SB:
6978  WriteB(rs + se_imm16, static_cast<int8_t>(rt));
6979  break;
6980  case SH:
6981  WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr());
6982  break;
6983  case SWL: {
6984  uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
6985  uint8_t byte_shift = kInt32AlignmentMask - al_offset;
6986  uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
6987  addr = rs + se_imm16 - al_offset;
6988  uint64_t mem_value = ReadW(addr, instr_.instr()) & mask;
6989  mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
6990  WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr());
6991  break;
6992  }
6993  case SW:
6994  WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr_.instr());
6995  break;
6996  case SD:
6997  Write2W(rs + se_imm16, rt, instr_.instr());
6998  break;
6999  case SWR: {
7000  uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
7001  uint32_t mask = (1 << al_offset * 8) - 1;
7002  addr = rs + se_imm16 - al_offset;
7003  uint64_t mem_value = ReadW(addr, instr_.instr());
7004  mem_value = (rt << al_offset * 8) | (mem_value & mask);
7005  WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr());
7006  break;
7007  }
7008  case SDL: {
7009  uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7010  uint8_t byte_shift = kInt64AlignmentMask - al_offset;
7011  uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0;
7012  addr = rs + se_imm16 - al_offset;
7013  uint64_t mem_value = Read2W(addr, instr_.instr()) & mask;
7014  mem_value |= static_cast<uint64_t>(rt) >> byte_shift * 8;
7015  Write2W(addr, mem_value, instr_.instr());
7016  break;
7017  }
7018  case SDR: {
7019  uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7020  uint64_t mask = (1UL << al_offset * 8) - 1;
7021  addr = rs + se_imm16 - al_offset;
7022  uint64_t mem_value = Read2W(addr, instr_.instr());
7023  mem_value = (rt << al_offset * 8) | (mem_value & mask);
7024  Write2W(addr, mem_value, instr_.instr());
7025  break;
7026  }
7027  case LL: {
7028  // LL/SC sequence cannot be simulated properly
7029  DCHECK_EQ(kArchVariant, kMips64r2);
7030  set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
7031  break;
7032  }
7033  case SC: {
7034  // LL/SC sequence cannot be simulated properly
7035  DCHECK_EQ(kArchVariant, kMips64r2);
7036  WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr_.instr());
7037  set_register(rt_reg, 1);
7038  break;
7039  }
7040  case LLD: {
7041  // LL/SC sequence cannot be simulated properly
7042  DCHECK_EQ(kArchVariant, kMips64r2);
7043  set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr()));
7044  break;
7045  }
7046  case SCD: {
7047  // LL/SC sequence cannot be simulated properly
7048  DCHECK_EQ(kArchVariant, kMips64r2);
7049  Write2W(rs + se_imm16, rt, instr_.instr());
7050  set_register(rt_reg, 1);
7051  break;
7052  }
7053  case LWC1:
7054  set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits.
7055  set_fpu_register_word(ft_reg,
7056  ReadW(rs + se_imm16, instr_.instr(), FLOAT_DOUBLE));
7057  break;
7058  case LDC1:
7059  set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr()));
7060  TraceMemRd(addr, get_fpu_register(ft_reg), DOUBLE);
7061  break;
7062  case SWC1: {
7063  int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg));
7064  WriteW(rs + se_imm16, alu_out_32, instr_.instr());
7065  break;
7066  }
7067  case SDC1:
7068  WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr());
7069  TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg), DWORD);
7070  break;
7071  // ------------- PC-Relative instructions.
7072  case PCREL: {
7073  // rt field: checking 5-bits.
7074  int32_t imm21 = instr_.Imm21Value();
7075  int64_t current_pc = get_pc();
7076  uint8_t rt = (imm21 >> kImm16Bits);
7077  switch (rt) {
7078  case ALUIPC:
7079  addr = current_pc + (se_imm16 << 16);
7080  alu_out = static_cast<int64_t>(~0x0FFFF) & addr;
7081  break;
7082  case AUIPC:
7083  alu_out = current_pc + (se_imm16 << 16);
7084  break;
7085  default: {
7086  int32_t imm19 = instr_.Imm19Value();
7087  // rt field: checking the most significant 3-bits.
7088  rt = (imm21 >> kImm18Bits);
7089  switch (rt) {
7090  case LDPC:
7091  addr =
7092  (current_pc & static_cast<int64_t>(~0x7)) + (se_imm18 << 3);
7093  alu_out = Read2W(addr, instr_.instr());
7094  break;
7095  default: {
7096  // rt field: checking the most significant 2-bits.
7097  rt = (imm21 >> kImm19Bits);
7098  switch (rt) {
7099  case LWUPC: {
7100  // Set sign.
7101  imm19 <<= (kOpcodeBits + kRsBits + 2);
7102  imm19 >>= (kOpcodeBits + kRsBits + 2);
7103  addr = current_pc + (imm19 << 2);
7104  uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
7105  alu_out = *ptr;
7106  break;
7107  }
7108  case LWPC: {
7109  // Set sign.
7110  imm19 <<= (kOpcodeBits + kRsBits + 2);
7111  imm19 >>= (kOpcodeBits + kRsBits + 2);
7112  addr = current_pc + (imm19 << 2);
7113  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
7114  alu_out = *ptr;
7115  break;
7116  }
7117  case ADDIUPC: {
7118  int64_t se_imm19 =
7119  imm19 | ((imm19 & 0x40000) ? 0xFFFFFFFFFFF80000 : 0);
7120  alu_out = current_pc + (se_imm19 << 2);
7121  break;
7122  }
7123  default:
7124  UNREACHABLE();
7125  break;
7126  }
7127  break;
7128  }
7129  }
7130  break;
7131  }
7132  }
7133  SetResult(rs_reg, alu_out);
7134  break;
7135  }
7136  case SPECIAL3: {
7137  switch (instr_.FunctionFieldRaw()) {
7138  case LL_R6: {
7139  // LL/SC sequence cannot be simulated properly
7140  DCHECK_EQ(kArchVariant, kMips64r6);
7141  int64_t base = get_register(instr_.BaseValue());
7142  int32_t offset9 = instr_.Imm9Value();
7143  set_register(rt_reg, ReadW(base + offset9, instr_.instr()));
7144  break;
7145  }
7146  case LLD_R6: {
7147  // LL/SC sequence cannot be simulated properly
7148  DCHECK_EQ(kArchVariant, kMips64r6);
7149  int64_t base = get_register(instr_.BaseValue());
7150  int32_t offset9 = instr_.Imm9Value();
7151  set_register(rt_reg, Read2W(base + offset9, instr_.instr()));
7152  break;
7153  }
7154  case SC_R6: {
7155  // LL/SC sequence cannot be simulated properly
7156  DCHECK_EQ(kArchVariant, kMips64r6);
7157  int64_t base = get_register(instr_.BaseValue());
7158  int32_t offset9 = instr_.Imm9Value();
7159  WriteW(base + offset9, static_cast<int32_t>(rt), instr_.instr());
7160  set_register(rt_reg, 1);
7161  break;
7162  }
7163  case SCD_R6: {
7164  // LL/SC sequence cannot be simulated properly
7165  DCHECK_EQ(kArchVariant, kMips64r6);
7166  int64_t base = get_register(instr_.BaseValue());
7167  int32_t offset9 = instr_.Imm9Value();
7168  Write2W(base + offset9, rt, instr_.instr());
7169  set_register(rt_reg, 1);
7170  break;
7171  }
7172  default:
7173  UNREACHABLE();
7174  }
7175  break;
7176  }
7177 
7178  case MSA:
7179  switch (instr_.MSAMinorOpcodeField()) {
7180  case kMsaMinorI8:
7181  DecodeTypeMsaI8();
7182  break;
7183  case kMsaMinorI5:
7184  DecodeTypeMsaI5();
7185  break;
7186  case kMsaMinorI10:
7187  DecodeTypeMsaI10();
7188  break;
7189  case kMsaMinorELM:
7190  DecodeTypeMsaELM();
7191  break;
7192  case kMsaMinorBIT:
7193  DecodeTypeMsaBIT();
7194  break;
7195  case kMsaMinorMI10:
7196  DecodeTypeMsaMI10();
7197  break;
7198  default:
7199  UNREACHABLE();
7200  break;
7201  }
7202  break;
7203  default:
7204  UNREACHABLE();
7205  }
7206 
7207  if (execute_branch_delay_instruction) {
7208  // Execute branch delay slot
7209  // We don't check for end_sim_pc. First it should not be met as the current
7210  // pc is valid. Secondly a jump should always execute its branch delay slot.
7211  Instruction* branch_delay_instr =
7212  reinterpret_cast<Instruction*>(get_pc() + kInstrSize);
7213  BranchDelayInstructionDecode(branch_delay_instr);
7214  }
7215 
7216  // If needed update pc after the branch delay execution.
7217  if (next_pc != bad_ra) {
7218  set_pc(next_pc);
7219  }
7220 }
7221 
7222 
7223 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
7224 void Simulator::DecodeTypeJump() {
7225  SimInstruction simInstr = instr_;
7226  // Get current pc.
7227  int64_t current_pc = get_pc();
7228  // Get unchanged bits of pc.
7229  int64_t pc_high_bits = current_pc & 0xFFFFFFFFF0000000;
7230  // Next pc.
7231  int64_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2);
7232 
7233  // Execute branch delay slot.
7234  // We don't check for end_sim_pc. First it should not be met as the current pc
7235  // is valid. Secondly a jump should always execute its branch delay slot.
7236  Instruction* branch_delay_instr =
7237  reinterpret_cast<Instruction*>(current_pc + kInstrSize);
7238  BranchDelayInstructionDecode(branch_delay_instr);
7239 
7240  // Update pc and ra if necessary.
7241  // Do this after the branch delay execution.
7242  if (simInstr.IsLinkingInstruction()) {
7243  set_register(31, current_pc + 2 * kInstrSize);
7244  }
7245  set_pc(next_pc);
7246  pc_modified_ = true;
7247 }
7248 
7249 
7250 // Executes the current instruction.
7251 void Simulator::InstructionDecode(Instruction* instr) {
7252  if (v8::internal::FLAG_check_icache) {
7253  CheckICache(i_cache(), instr);
7254  }
7255  pc_modified_ = false;
7256 
7258 
7259  if (::v8::internal::FLAG_trace_sim) {
7260  SNPrintF(trace_buf_, " ");
7261  disasm::NameConverter converter;
7262  disasm::Disassembler dasm(converter);
7263  // Use a reasonably large buffer.
7264  dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
7265  }
7266 
7267  instr_ = instr;
7268  switch (instr_.InstructionType()) {
7269  case Instruction::kRegisterType:
7270  DecodeTypeRegister();
7271  break;
7272  case Instruction::kImmediateType:
7273  DecodeTypeImmediate();
7274  break;
7275  case Instruction::kJumpType:
7276  DecodeTypeJump();
7277  break;
7278  default:
7279  UNSUPPORTED();
7280  }
7281 
7282  if (::v8::internal::FLAG_trace_sim) {
7283  PrintF(" 0x%08" PRIxPTR " %-44s %s\n",
7284  reinterpret_cast<intptr_t>(instr), buffer.start(),
7285  trace_buf_.start());
7286  }
7287 
7288  if (!pc_modified_) {
7289  set_register(pc, reinterpret_cast<int64_t>(instr) + kInstrSize);
7290  }
7291 }
7292 
7293 
7294 
7295 void Simulator::Execute() {
7296  // Get the PC to simulate. Cannot use the accessor here as we need the
7297  // raw PC value and not the one used as input to arithmetic instructions.
7298  int64_t program_counter = get_pc();
7299  if (::v8::internal::FLAG_stop_sim_at == 0) {
7300  // Fast version of the dispatch loop without checking whether the simulator
7301  // should be stopping at a particular executed instruction.
7302  while (program_counter != end_sim_pc) {
7303  Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
7304  icount_++;
7305  InstructionDecode(instr);
7306  program_counter = get_pc();
7307  }
7308  } else {
7309  // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
7310  // we reach the particular instruction count.
7311  while (program_counter != end_sim_pc) {
7312  Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
7313  icount_++;
7314  if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) {
7315  MipsDebugger dbg(this);
7316  dbg.Debug();
7317  } else {
7318  InstructionDecode(instr);
7319  }
7320  program_counter = get_pc();
7321  }
7322  }
7323 }
7324 
7325 void Simulator::CallInternal(Address entry) {
7326  // Adjust JS-based stack limit to C-based stack limit.
7327  isolate_->stack_guard()->AdjustStackLimitForSimulator();
7328 
7329  // Prepare to execute the code at entry.
7330  set_register(pc, static_cast<int64_t>(entry));
7331  // Put down marker for end of simulation. The simulator will stop simulation
7332  // when the PC reaches this value. By saving the "end simulation" value into
7333  // the LR the simulation stops when returning to this call point.
7334  set_register(ra, end_sim_pc);
7335 
7336  // Remember the values of callee-saved registers.
7337  // The code below assumes that r9 is not used as sb (static base) in
7338  // simulator code and therefore is regarded as a callee-saved register.
7339  int64_t s0_val = get_register(s0);
7340  int64_t s1_val = get_register(s1);
7341  int64_t s2_val = get_register(s2);
7342  int64_t s3_val = get_register(s3);
7343  int64_t s4_val = get_register(s4);
7344  int64_t s5_val = get_register(s5);
7345  int64_t s6_val = get_register(s6);
7346  int64_t s7_val = get_register(s7);
7347  int64_t gp_val = get_register(gp);
7348  int64_t sp_val = get_register(sp);
7349  int64_t fp_val = get_register(fp);
7350 
7351  // Set up the callee-saved registers with a known value. To be able to check
7352  // that they are preserved properly across JS execution.
7353  int64_t callee_saved_value = icount_;
7354  set_register(s0, callee_saved_value);
7355  set_register(s1, callee_saved_value);
7356  set_register(s2, callee_saved_value);
7357  set_register(s3, callee_saved_value);
7358  set_register(s4, callee_saved_value);
7359  set_register(s5, callee_saved_value);
7360  set_register(s6, callee_saved_value);
7361  set_register(s7, callee_saved_value);
7362  set_register(gp, callee_saved_value);
7363  set_register(fp, callee_saved_value);
7364 
7365  // Start the simulation.
7366  Execute();
7367 
7368  // Check that the callee-saved registers have been preserved.
7369  CHECK_EQ(callee_saved_value, get_register(s0));
7370  CHECK_EQ(callee_saved_value, get_register(s1));
7371  CHECK_EQ(callee_saved_value, get_register(s2));
7372  CHECK_EQ(callee_saved_value, get_register(s3));
7373  CHECK_EQ(callee_saved_value, get_register(s4));
7374  CHECK_EQ(callee_saved_value, get_register(s5));
7375  CHECK_EQ(callee_saved_value, get_register(s6));
7376  CHECK_EQ(callee_saved_value, get_register(s7));
7377  CHECK_EQ(callee_saved_value, get_register(gp));
7378  CHECK_EQ(callee_saved_value, get_register(fp));
7379 
7380  // Restore callee-saved registers with the original value.
7381  set_register(s0, s0_val);
7382  set_register(s1, s1_val);
7383  set_register(s2, s2_val);
7384  set_register(s3, s3_val);
7385  set_register(s4, s4_val);
7386  set_register(s5, s5_val);
7387  set_register(s6, s6_val);
7388  set_register(s7, s7_val);
7389  set_register(gp, gp_val);
7390  set_register(sp, sp_val);
7391  set_register(fp, fp_val);
7392 }
7393 
7394 intptr_t Simulator::CallImpl(Address entry, int argument_count,
7395  const intptr_t* arguments) {
7396  constexpr int kRegisterPassedArguments = 8;
7397  // Set up arguments.
7398 
7399  // First four arguments passed in registers in both ABI's.
7400  int reg_arg_count = std::min(kRegisterPassedArguments, argument_count);
7401  if (reg_arg_count > 0) set_register(a0, arguments[0]);
7402  if (reg_arg_count > 1) set_register(a1, arguments[1]);
7403  if (reg_arg_count > 2) set_register(a2, arguments[2]);
7404  if (reg_arg_count > 2) set_register(a3, arguments[3]);
7405 
7406  // Up to eight arguments passed in registers in N64 ABI.
7407  // TODO(plind): N64 ABI calls these regs a4 - a7. Clarify this.
7408  if (reg_arg_count > 4) set_register(a4, arguments[4]);
7409  if (reg_arg_count > 5) set_register(a5, arguments[5]);
7410  if (reg_arg_count > 6) set_register(a6, arguments[6]);
7411  if (reg_arg_count > 7) set_register(a7, arguments[7]);
7412 
7413  // Remaining arguments passed on stack.
7414  int64_t original_stack = get_register(sp);
7415  // Compute position of stack on entry to generated code.
7416  int stack_args_count = argument_count - reg_arg_count;
7417  int stack_args_size = stack_args_count * sizeof(*arguments) + kCArgsSlotsSize;
7418  int64_t entry_stack = original_stack - stack_args_size;
7419 
7420  if (base::OS::ActivationFrameAlignment() != 0) {
7421  entry_stack &= -base::OS::ActivationFrameAlignment();
7422  }
7423  // Store remaining arguments on stack, from low to high memory.
7424  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
7425  memcpy(stack_argument + kCArgSlotCount, arguments + reg_arg_count,
7426  stack_args_count * sizeof(*arguments));
7427  set_register(sp, entry_stack);
7428 
7429  CallInternal(entry);
7430 
7431  // Pop stack passed arguments.
7432  CHECK_EQ(entry_stack, get_register(sp));
7433  set_register(sp, original_stack);
7434 
7435  return get_register(v0);
7436 }
7437 
7438 double Simulator::CallFP(Address entry, double d0, double d1) {
7439  if (!IsMipsSoftFloatABI) {
7440  const FPURegister fparg2 = f13;
7441  set_fpu_register_double(f12, d0);
7442  set_fpu_register_double(fparg2, d1);
7443  } else {
7444  int buffer[2];
7445  DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0));
7446  memcpy(buffer, &d0, sizeof(d0));
7447  set_dw_register(a0, buffer);
7448  memcpy(buffer, &d1, sizeof(d1));
7449  set_dw_register(a2, buffer);
7450  }
7451  CallInternal(entry);
7452  if (!IsMipsSoftFloatABI) {
7453  return get_fpu_register_double(f0);
7454  } else {
7455  return get_double_from_register_pair(v0);
7456  }
7457 }
7458 
7459 
7460 uintptr_t Simulator::PushAddress(uintptr_t address) {
7461  int64_t new_sp = get_register(sp) - sizeof(uintptr_t);
7462  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
7463  *stack_slot = address;
7464  set_register(sp, new_sp);
7465  return new_sp;
7466 }
7467 
7468 
7469 uintptr_t Simulator::PopAddress() {
7470  int64_t current_sp = get_register(sp);
7471  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
7472  uintptr_t address = *stack_slot;
7473  set_register(sp, current_sp + sizeof(uintptr_t));
7474  return address;
7475 }
7476 
7477 
7478 #undef UNSUPPORTED
7479 } // namespace internal
7480 } // namespace v8
7481 
7482 #endif // USE_SIMULATOR
7483 
7484 #endif // V8_TARGET_ARCH_MIPS64
Definition: libplatform.h:13