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