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