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 #include "src/v8.h"
11 
12 #if V8_TARGET_ARCH_MIPS64
13 
14 #include "src/assembler.h"
15 #include "src/base/bits.h"
16 #include "src/disasm.h"
17 #include "src/mips64/constants-mips64.h"
18 #include "src/mips64/simulator-mips64.h"
19 #include "src/ostreams.h"
20 
21 // Only build the simulator if not compiling for real MIPS hardware.
22 #if defined(USE_SIMULATOR)
23 
24 namespace v8 {
25 namespace internal {
26 
27 // Utils functions.
HaveSameSign(int64_t a,int64_t b)28 bool HaveSameSign(int64_t a, int64_t b) {
29   return ((a ^ b) >= 0);
30 }
31 
32 
get_fcsr_condition_bit(uint32_t cc)33 uint32_t get_fcsr_condition_bit(uint32_t cc) {
34   if (cc == 0) {
35     return 23;
36   } else {
37     return 24 + cc;
38   }
39 }
40 
41 
MultiplyHighSigned(int64_t u,int64_t v)42 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
43   uint64_t u0, v0, w0;
44   int64_t u1, v1, w1, w2, t;
45 
46   u0 = u & 0xffffffffL;
47   u1 = u >> 32;
48   v0 = v & 0xffffffffL;
49   v1 = v >> 32;
50 
51   w0 = u0 * v0;
52   t = u1 * v0 + (w0 >> 32);
53   w1 = t & 0xffffffffL;
54   w2 = t >> 32;
55   w1 = u0 * v1 + w1;
56 
57   return u1 * v1 + w2 + (w1 >> 32);
58 }
59 
60 
61 // This macro provides a platform independent use of sscanf. The reason for
62 // SScanF not being implemented in a platform independent was through
63 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
64 // Library does not provide vsscanf.
65 #define SScanF sscanf  // NOLINT
66 
67 // The MipsDebugger class is used by the simulator while debugging simulated
68 // code.
69 class MipsDebugger {
70  public:
MipsDebugger(Simulator * sim)71   explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
72   ~MipsDebugger();
73 
74   void Stop(Instruction* instr);
75   void Debug();
76   // Print all registers with a nice formatting.
77   void PrintAllRegs();
78   void PrintAllRegsIncludingFPU();
79 
80  private:
81   // We set the breakpoint code to 0xfffff to easily recognize it.
82   static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
83   static const Instr kNopInstr =  0x0;
84 
85   Simulator* sim_;
86 
87   int64_t GetRegisterValue(int regnum);
88   int64_t GetFPURegisterValue(int regnum);
89   float GetFPURegisterValueFloat(int regnum);
90   double GetFPURegisterValueDouble(int regnum);
91   bool GetValue(const char* desc, int64_t* value);
92 
93   // Set or delete a breakpoint. Returns true if successful.
94   bool SetBreakpoint(Instruction* breakpc);
95   bool DeleteBreakpoint(Instruction* breakpc);
96 
97   // Undo and redo all breakpoints. This is needed to bracket disassembly and
98   // execution to skip past breakpoints when run from the debugger.
99   void UndoBreakpoints();
100   void RedoBreakpoints();
101 };
102 
103 
~MipsDebugger()104 MipsDebugger::~MipsDebugger() {
105 }
106 
107 
108 #ifdef GENERATED_CODE_COVERAGE
109 static FILE* coverage_log = NULL;
110 
111 
InitializeCoverage()112 static void InitializeCoverage() {
113   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
114   if (file_name != NULL) {
115     coverage_log = fopen(file_name, "aw+");
116   }
117 }
118 
119 
Stop(Instruction * instr)120 void MipsDebugger::Stop(Instruction* instr) {
121   // Get the stop code.
122   uint32_t code = instr->Bits(25, 6);
123   // Retrieve the encoded address, which comes just after this stop.
124   char** msg_address =
125     reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
126   char* msg = *msg_address;
127   DCHECK(msg != NULL);
128 
129   // Update this stop description.
130   if (!watched_stops_[code].desc) {
131     watched_stops_[code].desc = msg;
132   }
133 
134   if (strlen(msg) > 0) {
135     if (coverage_log != NULL) {
136       fprintf(coverage_log, "%s\n", str);
137       fflush(coverage_log);
138     }
139     // Overwrite the instruction and address with nops.
140     instr->SetInstructionBits(kNopInstr);
141     reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
142   }
143   // TODO(yuyin): 2 -> 3?
144   sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstructionSize);
145 }
146 
147 
148 #else  // GENERATED_CODE_COVERAGE
149 
150 #define UNSUPPORTED() printf("Unsupported instruction.\n");
151 
InitializeCoverage()152 static void InitializeCoverage() {}
153 
154 
Stop(Instruction * instr)155 void MipsDebugger::Stop(Instruction* instr) {
156   // Get the stop code.
157   uint32_t code = instr->Bits(25, 6);
158   // Retrieve the encoded address, which comes just after this stop.
159   char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
160       Instruction::kInstrSize);
161   // Update this stop description.
162   if (!sim_->watched_stops_[code].desc) {
163     sim_->watched_stops_[code].desc = msg;
164   }
165   PrintF("Simulator hit %s (%u)\n", msg, code);
166   // TODO(yuyin): 2 -> 3?
167   sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize);
168   Debug();
169 }
170 #endif  // GENERATED_CODE_COVERAGE
171 
172 
GetRegisterValue(int regnum)173 int64_t MipsDebugger::GetRegisterValue(int regnum) {
174   if (regnum == kNumSimuRegisters) {
175     return sim_->get_pc();
176   } else {
177     return sim_->get_register(regnum);
178   }
179 }
180 
181 
GetFPURegisterValue(int regnum)182 int64_t MipsDebugger::GetFPURegisterValue(int regnum) {
183   if (regnum == kNumFPURegisters) {
184     return sim_->get_pc();
185   } else {
186     return sim_->get_fpu_register(regnum);
187   }
188 }
189 
190 
GetFPURegisterValueFloat(int regnum)191 float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
192   if (regnum == kNumFPURegisters) {
193     return sim_->get_pc();
194   } else {
195     return sim_->get_fpu_register_float(regnum);
196   }
197 }
198 
199 
GetFPURegisterValueDouble(int regnum)200 double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
201   if (regnum == kNumFPURegisters) {
202     return sim_->get_pc();
203   } else {
204     return sim_->get_fpu_register_double(regnum);
205   }
206 }
207 
208 
GetValue(const char * desc,int64_t * value)209 bool MipsDebugger::GetValue(const char* desc, int64_t* value) {
210   int regnum = Registers::Number(desc);
211   int fpuregnum = FPURegisters::Number(desc);
212 
213   if (regnum != kInvalidRegister) {
214     *value = GetRegisterValue(regnum);
215     return true;
216   } else if (fpuregnum != kInvalidFPURegister) {
217     *value = GetFPURegisterValue(fpuregnum);
218     return true;
219   } else if (strncmp(desc, "0x", 2) == 0) {
220     return SScanF(desc + 2, "%" SCNx64,
221                   reinterpret_cast<uint64_t*>(value)) == 1;
222   } else {
223     return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
224   }
225   return false;
226 }
227 
228 
SetBreakpoint(Instruction * breakpc)229 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
230   // Check if a breakpoint can be set. If not return without any side-effects.
231   if (sim_->break_pc_ != NULL) {
232     return false;
233   }
234 
235   // Set the breakpoint.
236   sim_->break_pc_ = breakpc;
237   sim_->break_instr_ = breakpc->InstructionBits();
238   // Not setting the breakpoint instruction in the code itself. It will be set
239   // when the debugger shell continues.
240   return true;
241 }
242 
243 
DeleteBreakpoint(Instruction * breakpc)244 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
245   if (sim_->break_pc_ != NULL) {
246     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
247   }
248 
249   sim_->break_pc_ = NULL;
250   sim_->break_instr_ = 0;
251   return true;
252 }
253 
254 
UndoBreakpoints()255 void MipsDebugger::UndoBreakpoints() {
256   if (sim_->break_pc_ != NULL) {
257     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
258   }
259 }
260 
261 
RedoBreakpoints()262 void MipsDebugger::RedoBreakpoints() {
263   if (sim_->break_pc_ != NULL) {
264     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
265   }
266 }
267 
268 
PrintAllRegs()269 void MipsDebugger::PrintAllRegs() {
270 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
271 
272   PrintF("\n");
273   // at, v0, a0.
274   PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
275          REG_INFO(1), REG_INFO(2), REG_INFO(4));
276   // v1, a1.
277   PrintF("%34s\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
278          "", REG_INFO(3), REG_INFO(5));
279   // a2.
280   PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(6));
281   // a3.
282   PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(7));
283   PrintF("\n");
284   // a4-t3, s0-s7
285   for (int i = 0; i < 8; i++) {
286     PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
287            REG_INFO(8+i), REG_INFO(16+i));
288   }
289   PrintF("\n");
290   // t8, k0, LO.
291   PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
292          REG_INFO(24), REG_INFO(26), REG_INFO(32));
293   // t9, k1, HI.
294   PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
295          REG_INFO(25), REG_INFO(27), REG_INFO(33));
296   // sp, fp, gp.
297   PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
298          REG_INFO(29), REG_INFO(30), REG_INFO(28));
299   // pc.
300   PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
301          REG_INFO(31), REG_INFO(34));
302 
303 #undef REG_INFO
304 #undef FPU_REG_INFO
305 }
306 
307 
PrintAllRegsIncludingFPU()308 void MipsDebugger::PrintAllRegsIncludingFPU() {
309 #define FPU_REG_INFO(n) FPURegisters::Name(n), \
310         GetFPURegisterValue(n), \
311         GetFPURegisterValueDouble(n)
312 
313   PrintAllRegs();
314 
315   PrintF("\n\n");
316   // f0, f1, f2, ... f31.
317   // TODO(plind): consider printing 2 columns for space efficiency.
318   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(0) );
319   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(1) );
320   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(2) );
321   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(3) );
322   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(4) );
323   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(5) );
324   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(6) );
325   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(7) );
326   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(8) );
327   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(9) );
328   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(10));
329   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(11));
330   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(12));
331   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(13));
332   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(14));
333   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(15));
334   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(16));
335   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(17));
336   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(18));
337   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(19));
338   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(20));
339   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(21));
340   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(22));
341   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(23));
342   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(24));
343   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(25));
344   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(26));
345   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(27));
346   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(28));
347   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(29));
348   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(30));
349   PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(31));
350 
351 #undef REG_INFO
352 #undef FPU_REG_INFO
353 }
354 
355 
Debug()356 void MipsDebugger::Debug() {
357   intptr_t last_pc = -1;
358   bool done = false;
359 
360 #define COMMAND_SIZE 63
361 #define ARG_SIZE 255
362 
363 #define STR(a) #a
364 #define XSTR(a) STR(a)
365 
366   char cmd[COMMAND_SIZE + 1];
367   char arg1[ARG_SIZE + 1];
368   char arg2[ARG_SIZE + 1];
369   char* argv[3] = { cmd, arg1, arg2 };
370 
371   // Make sure to have a proper terminating character if reaching the limit.
372   cmd[COMMAND_SIZE] = 0;
373   arg1[ARG_SIZE] = 0;
374   arg2[ARG_SIZE] = 0;
375 
376   // Undo all set breakpoints while running in the debugger shell. This will
377   // make them invisible to all commands.
378   UndoBreakpoints();
379 
380   while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
381     if (last_pc != sim_->get_pc()) {
382       disasm::NameConverter converter;
383       disasm::Disassembler dasm(converter);
384       // Use a reasonably large buffer.
385       v8::internal::EmbeddedVector<char, 256> buffer;
386       dasm.InstructionDecode(buffer,
387                              reinterpret_cast<byte*>(sim_->get_pc()));
388       PrintF("  0x%016lx  %s\n", sim_->get_pc(), buffer.start());
389       last_pc = sim_->get_pc();
390     }
391     char* line = ReadLine("sim> ");
392     if (line == NULL) {
393       break;
394     } else {
395       char* last_input = sim_->last_debugger_input();
396       if (strcmp(line, "\n") == 0 && last_input != NULL) {
397         line = last_input;
398       } else {
399         // Ownership is transferred to sim_;
400         sim_->set_last_debugger_input(line);
401       }
402       // Use sscanf to parse the individual parts of the command line. At the
403       // moment no command expects more than two parameters.
404       int argc = SScanF(line,
405                         "%" XSTR(COMMAND_SIZE) "s "
406                         "%" XSTR(ARG_SIZE) "s "
407                         "%" XSTR(ARG_SIZE) "s",
408                         cmd, arg1, arg2);
409       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
410         Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
411         if (!(instr->IsTrap()) ||
412             instr->InstructionBits() == rtCallRedirInstr) {
413           sim_->InstructionDecode(
414               reinterpret_cast<Instruction*>(sim_->get_pc()));
415         } else {
416           // Allow si to jump over generated breakpoints.
417           PrintF("/!\\ Jumping over generated breakpoint.\n");
418           sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
419         }
420       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
421         // Execute the one instruction we broke at with breakpoints disabled.
422         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
423         // Leave the debugger shell.
424         done = true;
425       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
426         if (argc == 2) {
427           int64_t value;
428           double dvalue;
429           if (strcmp(arg1, "all") == 0) {
430             PrintAllRegs();
431           } else if (strcmp(arg1, "allf") == 0) {
432             PrintAllRegsIncludingFPU();
433           } else {
434             int regnum = Registers::Number(arg1);
435             int fpuregnum = FPURegisters::Number(arg1);
436 
437             if (regnum != kInvalidRegister) {
438               value = GetRegisterValue(regnum);
439               PrintF("%s: 0x%08lx %ld \n", arg1, value, value);
440             } else if (fpuregnum != kInvalidFPURegister) {
441               value = GetFPURegisterValue(fpuregnum);
442               dvalue = GetFPURegisterValueDouble(fpuregnum);
443               PrintF("%3s: 0x%016lx %16.4e\n",
444                      FPURegisters::Name(fpuregnum), value, dvalue);
445             } else {
446               PrintF("%s unrecognized\n", arg1);
447             }
448           }
449         } else {
450           if (argc == 3) {
451             if (strcmp(arg2, "single") == 0) {
452               int64_t value;
453               float fvalue;
454               int fpuregnum = FPURegisters::Number(arg1);
455 
456               if (fpuregnum != kInvalidFPURegister) {
457                 value = GetFPURegisterValue(fpuregnum);
458                 value &= 0xffffffffUL;
459                 fvalue = GetFPURegisterValueFloat(fpuregnum);
460                 PrintF("%s: 0x%08lx %11.4e\n", arg1, value, fvalue);
461               } else {
462                 PrintF("%s unrecognized\n", arg1);
463               }
464             } else {
465               PrintF("print <fpu register> single\n");
466             }
467           } else {
468             PrintF("print <register> or print <fpu register> single\n");
469           }
470         }
471       } else if ((strcmp(cmd, "po") == 0)
472                  || (strcmp(cmd, "printobject") == 0)) {
473         if (argc == 2) {
474           int64_t value;
475           OFStream os(stdout);
476           if (GetValue(arg1, &value)) {
477             Object* obj = reinterpret_cast<Object*>(value);
478             os << arg1 << ": \n";
479 #ifdef DEBUG
480             obj->Print(os);
481             os << "\n";
482 #else
483             os << Brief(obj) << "\n";
484 #endif
485           } else {
486             os << arg1 << " unrecognized\n";
487           }
488         } else {
489           PrintF("printobject <value>\n");
490         }
491       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
492         int64_t* cur = NULL;
493         int64_t* end = NULL;
494         int next_arg = 1;
495 
496         if (strcmp(cmd, "stack") == 0) {
497           cur = reinterpret_cast<int64_t*>(sim_->get_register(Simulator::sp));
498         } else {  // Command "mem".
499           int64_t value;
500           if (!GetValue(arg1, &value)) {
501             PrintF("%s unrecognized\n", arg1);
502             continue;
503           }
504           cur = reinterpret_cast<int64_t*>(value);
505           next_arg++;
506         }
507 
508         int64_t words;
509         if (argc == next_arg) {
510           words = 10;
511         } else {
512           if (!GetValue(argv[next_arg], &words)) {
513             words = 10;
514           }
515         }
516         end = cur + words;
517 
518         while (cur < end) {
519           PrintF("  0x%012lx:  0x%016lx %14ld",
520                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
521           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
522           int64_t value = *cur;
523           Heap* current_heap = v8::internal::Isolate::Current()->heap();
524           if (((value & 1) == 0) || current_heap->Contains(obj)) {
525             PrintF(" (");
526             if ((value & 1) == 0) {
527               PrintF("smi %d", static_cast<int>(value >> 32));
528             } else {
529               obj->ShortPrint();
530             }
531             PrintF(")");
532           }
533           PrintF("\n");
534           cur++;
535         }
536 
537       } else if ((strcmp(cmd, "disasm") == 0) ||
538                  (strcmp(cmd, "dpc") == 0) ||
539                  (strcmp(cmd, "di") == 0)) {
540         disasm::NameConverter converter;
541         disasm::Disassembler dasm(converter);
542         // Use a reasonably large buffer.
543         v8::internal::EmbeddedVector<char, 256> buffer;
544 
545         byte* cur = NULL;
546         byte* end = NULL;
547 
548         if (argc == 1) {
549           cur = reinterpret_cast<byte*>(sim_->get_pc());
550           end = cur + (10 * Instruction::kInstrSize);
551         } else if (argc == 2) {
552           int regnum = Registers::Number(arg1);
553           if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
554             // The argument is an address or a register name.
555             int64_t value;
556             if (GetValue(arg1, &value)) {
557               cur = reinterpret_cast<byte*>(value);
558               // Disassemble 10 instructions at <arg1>.
559               end = cur + (10 * Instruction::kInstrSize);
560             }
561           } else {
562             // The argument is the number of instructions.
563             int64_t value;
564             if (GetValue(arg1, &value)) {
565               cur = reinterpret_cast<byte*>(sim_->get_pc());
566               // Disassemble <arg1> instructions.
567               end = cur + (value * Instruction::kInstrSize);
568             }
569           }
570         } else {
571           int64_t value1;
572           int64_t value2;
573           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
574             cur = reinterpret_cast<byte*>(value1);
575             end = cur + (value2 * Instruction::kInstrSize);
576           }
577         }
578 
579         while (cur < end) {
580           dasm.InstructionDecode(buffer, cur);
581           PrintF("  0x%08lx  %s\n",
582               reinterpret_cast<intptr_t>(cur), buffer.start());
583           cur += Instruction::kInstrSize;
584         }
585       } else if (strcmp(cmd, "gdb") == 0) {
586         PrintF("relinquishing control to gdb\n");
587         v8::base::OS::DebugBreak();
588         PrintF("regaining control from gdb\n");
589       } else if (strcmp(cmd, "break") == 0) {
590         if (argc == 2) {
591           int64_t value;
592           if (GetValue(arg1, &value)) {
593             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
594               PrintF("setting breakpoint failed\n");
595             }
596           } else {
597             PrintF("%s unrecognized\n", arg1);
598           }
599         } else {
600           PrintF("break <address>\n");
601         }
602       } else if (strcmp(cmd, "del") == 0) {
603         if (!DeleteBreakpoint(NULL)) {
604           PrintF("deleting breakpoint failed\n");
605         }
606       } else if (strcmp(cmd, "flags") == 0) {
607         PrintF("No flags on MIPS !\n");
608       } else if (strcmp(cmd, "stop") == 0) {
609         int64_t value;
610         intptr_t stop_pc = sim_->get_pc() -
611             2 * Instruction::kInstrSize;
612         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
613         Instruction* msg_address =
614           reinterpret_cast<Instruction*>(stop_pc +
615               Instruction::kInstrSize);
616         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
617           // Remove the current stop.
618           if (sim_->IsStopInstruction(stop_instr)) {
619             stop_instr->SetInstructionBits(kNopInstr);
620             msg_address->SetInstructionBits(kNopInstr);
621           } else {
622             PrintF("Not at debugger stop.\n");
623           }
624         } else if (argc == 3) {
625           // Print information about all/the specified breakpoint(s).
626           if (strcmp(arg1, "info") == 0) {
627             if (strcmp(arg2, "all") == 0) {
628               PrintF("Stop information:\n");
629               for (uint32_t i = kMaxWatchpointCode + 1;
630                    i <= kMaxStopCode;
631                    i++) {
632                 sim_->PrintStopInfo(i);
633               }
634             } else if (GetValue(arg2, &value)) {
635               sim_->PrintStopInfo(value);
636             } else {
637               PrintF("Unrecognized argument.\n");
638             }
639           } else if (strcmp(arg1, "enable") == 0) {
640             // Enable all/the specified breakpoint(s).
641             if (strcmp(arg2, "all") == 0) {
642               for (uint32_t i = kMaxWatchpointCode + 1;
643                    i <= kMaxStopCode;
644                    i++) {
645                 sim_->EnableStop(i);
646               }
647             } else if (GetValue(arg2, &value)) {
648               sim_->EnableStop(value);
649             } else {
650               PrintF("Unrecognized argument.\n");
651             }
652           } else if (strcmp(arg1, "disable") == 0) {
653             // Disable all/the specified breakpoint(s).
654             if (strcmp(arg2, "all") == 0) {
655               for (uint32_t i = kMaxWatchpointCode + 1;
656                    i <= kMaxStopCode;
657                    i++) {
658                 sim_->DisableStop(i);
659               }
660             } else if (GetValue(arg2, &value)) {
661               sim_->DisableStop(value);
662             } else {
663               PrintF("Unrecognized argument.\n");
664             }
665           }
666         } else {
667           PrintF("Wrong usage. Use help command for more information.\n");
668         }
669       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
670         // Print registers and disassemble.
671         PrintAllRegs();
672         PrintF("\n");
673 
674         disasm::NameConverter converter;
675         disasm::Disassembler dasm(converter);
676         // Use a reasonably large buffer.
677         v8::internal::EmbeddedVector<char, 256> buffer;
678 
679         byte* cur = NULL;
680         byte* end = NULL;
681 
682         if (argc == 1) {
683           cur = reinterpret_cast<byte*>(sim_->get_pc());
684           end = cur + (10 * Instruction::kInstrSize);
685         } else if (argc == 2) {
686           int64_t value;
687           if (GetValue(arg1, &value)) {
688             cur = reinterpret_cast<byte*>(value);
689             // no length parameter passed, assume 10 instructions
690             end = cur + (10 * Instruction::kInstrSize);
691           }
692         } else {
693           int64_t value1;
694           int64_t value2;
695           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
696             cur = reinterpret_cast<byte*>(value1);
697             end = cur + (value2 * Instruction::kInstrSize);
698           }
699         }
700 
701         while (cur < end) {
702           dasm.InstructionDecode(buffer, cur);
703           PrintF("  0x%08lx  %s\n",
704                  reinterpret_cast<intptr_t>(cur), buffer.start());
705           cur += Instruction::kInstrSize;
706         }
707       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
708         PrintF("cont\n");
709         PrintF("  continue execution (alias 'c')\n");
710         PrintF("stepi\n");
711         PrintF("  step one instruction (alias 'si')\n");
712         PrintF("print <register>\n");
713         PrintF("  print register content (alias 'p')\n");
714         PrintF("  use register name 'all' to print all registers\n");
715         PrintF("printobject <register>\n");
716         PrintF("  print an object from a register (alias 'po')\n");
717         PrintF("stack [<words>]\n");
718         PrintF("  dump stack content, default dump 10 words)\n");
719         PrintF("mem <address> [<words>]\n");
720         PrintF("  dump memory content, default dump 10 words)\n");
721         PrintF("flags\n");
722         PrintF("  print flags\n");
723         PrintF("disasm [<instructions>]\n");
724         PrintF("disasm [<address/register>]\n");
725         PrintF("disasm [[<address/register>] <instructions>]\n");
726         PrintF("  disassemble code, default is 10 instructions\n");
727         PrintF("  from pc (alias 'di')\n");
728         PrintF("gdb\n");
729         PrintF("  enter gdb\n");
730         PrintF("break <address>\n");
731         PrintF("  set a break point on the address\n");
732         PrintF("del\n");
733         PrintF("  delete the breakpoint\n");
734         PrintF("stop feature:\n");
735         PrintF("  Description:\n");
736         PrintF("    Stops are debug instructions inserted by\n");
737         PrintF("    the Assembler::stop() function.\n");
738         PrintF("    When hitting a stop, the Simulator will\n");
739         PrintF("    stop and and give control to the Debugger.\n");
740         PrintF("    All stop codes are watched:\n");
741         PrintF("    - They can be enabled / disabled: the Simulator\n");
742         PrintF("       will / won't stop when hitting them.\n");
743         PrintF("    - The Simulator keeps track of how many times they \n");
744         PrintF("      are met. (See the info command.) Going over a\n");
745         PrintF("      disabled stop still increases its counter. \n");
746         PrintF("  Commands:\n");
747         PrintF("    stop info all/<code> : print infos about number <code>\n");
748         PrintF("      or all stop(s).\n");
749         PrintF("    stop enable/disable all/<code> : enables / disables\n");
750         PrintF("      all or number <code> stop(s)\n");
751         PrintF("    stop unstop\n");
752         PrintF("      ignore the stop instruction at the current location\n");
753         PrintF("      from now on\n");
754       } else {
755         PrintF("Unknown command: %s\n", cmd);
756       }
757     }
758   }
759 
760   // Add all the breakpoints back to stop execution and enter the debugger
761   // shell when hit.
762   RedoBreakpoints();
763 
764 #undef COMMAND_SIZE
765 #undef ARG_SIZE
766 
767 #undef STR
768 #undef XSTR
769 }
770 
771 
ICacheMatch(void * one,void * two)772 static bool ICacheMatch(void* one, void* two) {
773   DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
774   DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
775   return one == two;
776 }
777 
778 
ICacheHash(void * key)779 static uint32_t ICacheHash(void* key) {
780   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
781 }
782 
783 
AllOnOnePage(uintptr_t start,int size)784 static bool AllOnOnePage(uintptr_t start, int size) {
785   intptr_t start_page = (start & ~CachePage::kPageMask);
786   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
787   return start_page == end_page;
788 }
789 
790 
set_last_debugger_input(char * input)791 void Simulator::set_last_debugger_input(char* input) {
792   DeleteArray(last_debugger_input_);
793   last_debugger_input_ = input;
794 }
795 
796 
FlushICache(v8::internal::HashMap * i_cache,void * start_addr,size_t size)797 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
798                             void* start_addr,
799                             size_t size) {
800   int64_t start = reinterpret_cast<int64_t>(start_addr);
801   int64_t intra_line = (start & CachePage::kLineMask);
802   start -= intra_line;
803   size += intra_line;
804   size = ((size - 1) | CachePage::kLineMask) + 1;
805   int offset = (start & CachePage::kPageMask);
806   while (!AllOnOnePage(start, size - 1)) {
807     int bytes_to_flush = CachePage::kPageSize - offset;
808     FlushOnePage(i_cache, start, bytes_to_flush);
809     start += bytes_to_flush;
810     size -= bytes_to_flush;
811     DCHECK_EQ((uint64_t)0, start & CachePage::kPageMask);
812     offset = 0;
813   }
814   if (size != 0) {
815     FlushOnePage(i_cache, start, size);
816   }
817 }
818 
819 
GetCachePage(v8::internal::HashMap * i_cache,void * page)820 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
821   v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
822                                                         ICacheHash(page),
823                                                         true);
824   if (entry->value == NULL) {
825     CachePage* new_page = new CachePage();
826     entry->value = new_page;
827   }
828   return reinterpret_cast<CachePage*>(entry->value);
829 }
830 
831 
832 // Flush from start up to and not including start + size.
FlushOnePage(v8::internal::HashMap * i_cache,intptr_t start,int size)833 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
834                              intptr_t start,
835                              int size) {
836   DCHECK(size <= CachePage::kPageSize);
837   DCHECK(AllOnOnePage(start, size - 1));
838   DCHECK((start & CachePage::kLineMask) == 0);
839   DCHECK((size & CachePage::kLineMask) == 0);
840   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
841   int offset = (start & CachePage::kPageMask);
842   CachePage* cache_page = GetCachePage(i_cache, page);
843   char* valid_bytemap = cache_page->ValidityByte(offset);
844   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
845 }
846 
847 
CheckICache(v8::internal::HashMap * i_cache,Instruction * instr)848 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
849                             Instruction* instr) {
850   int64_t address = reinterpret_cast<int64_t>(instr);
851   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
852   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
853   int offset = (address & CachePage::kPageMask);
854   CachePage* cache_page = GetCachePage(i_cache, page);
855   char* cache_valid_byte = cache_page->ValidityByte(offset);
856   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
857   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
858   if (cache_hit) {
859     // Check that the data in memory matches the contents of the I-cache.
860     CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
861                        cache_page->CachedData(offset),
862                        Instruction::kInstrSize));
863   } else {
864     // Cache miss.  Load memory into the cache.
865     memcpy(cached_line, line, CachePage::kLineLength);
866     *cache_valid_byte = CachePage::LINE_VALID;
867   }
868 }
869 
870 
Initialize(Isolate * isolate)871 void Simulator::Initialize(Isolate* isolate) {
872   if (isolate->simulator_initialized()) return;
873   isolate->set_simulator_initialized(true);
874   ::v8::internal::ExternalReference::set_redirector(isolate,
875                                                     &RedirectExternalReference);
876 }
877 
878 
Simulator(Isolate * isolate)879 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
880   i_cache_ = isolate_->simulator_i_cache();
881   if (i_cache_ == NULL) {
882     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
883     isolate_->set_simulator_i_cache(i_cache_);
884   }
885   Initialize(isolate);
886   // Set up simulator support first. Some of this information is needed to
887   // setup the architecture state.
888   stack_size_ = FLAG_sim_stack_size * KB;
889   stack_ = reinterpret_cast<char*>(malloc(stack_size_));
890   pc_modified_ = false;
891   icount_ = 0;
892   break_count_ = 0;
893   break_pc_ = NULL;
894   break_instr_ = 0;
895 
896   // Set up architecture state.
897   // All registers are initialized to zero to start with.
898   for (int i = 0; i < kNumSimuRegisters; i++) {
899     registers_[i] = 0;
900   }
901   for (int i = 0; i < kNumFPURegisters; i++) {
902     FPUregisters_[i] = 0;
903   }
904   FCSR_ = 0;
905 
906   // The sp is initialized to point to the bottom (high address) of the
907   // allocated stack area. To be safe in potential stack underflows we leave
908   // some buffer below.
909   registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64;
910   // The ra and pc are initialized to a known bad value that will cause an
911   // access violation if the simulator ever tries to execute it.
912   registers_[pc] = bad_ra;
913   registers_[ra] = bad_ra;
914   InitializeCoverage();
915   for (int i = 0; i < kNumExceptions; i++) {
916     exceptions[i] = 0;
917   }
918 
919   last_debugger_input_ = NULL;
920 }
921 
922 
~Simulator()923 Simulator::~Simulator() {
924 }
925 
926 
927 // When the generated code calls an external reference we need to catch that in
928 // the simulator.  The external reference will be a function compiled for the
929 // host architecture.  We need to call that function instead of trying to
930 // execute it with the simulator.  We do that by redirecting the external
931 // reference to a swi (software-interrupt) instruction that is handled by
932 // the simulator.  We write the original destination of the jump just at a known
933 // offset from the swi instruction so the simulator knows what to call.
934 class Redirection {
935  public:
Redirection(void * external_function,ExternalReference::Type type)936   Redirection(void* external_function, ExternalReference::Type type)
937       : external_function_(external_function),
938         swi_instruction_(rtCallRedirInstr),
939         type_(type),
940         next_(NULL) {
941     Isolate* isolate = Isolate::Current();
942     next_ = isolate->simulator_redirection();
943     Simulator::current(isolate)->
944         FlushICache(isolate->simulator_i_cache(),
945                     reinterpret_cast<void*>(&swi_instruction_),
946                     Instruction::kInstrSize);
947     isolate->set_simulator_redirection(this);
948   }
949 
address_of_swi_instruction()950   void* address_of_swi_instruction() {
951     return reinterpret_cast<void*>(&swi_instruction_);
952   }
953 
external_function()954   void* external_function() { return external_function_; }
type()955   ExternalReference::Type type() { return type_; }
956 
Get(void * external_function,ExternalReference::Type type)957   static Redirection* Get(void* external_function,
958                           ExternalReference::Type type) {
959     Isolate* isolate = Isolate::Current();
960     Redirection* current = isolate->simulator_redirection();
961     for (; current != NULL; current = current->next_) {
962       if (current->external_function_ == external_function) return current;
963     }
964     return new Redirection(external_function, type);
965   }
966 
FromSwiInstruction(Instruction * swi_instruction)967   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
968     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
969     char* addr_of_redirection =
970         addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
971     return reinterpret_cast<Redirection*>(addr_of_redirection);
972   }
973 
ReverseRedirection(int64_t reg)974   static void* ReverseRedirection(int64_t reg) {
975     Redirection* redirection = FromSwiInstruction(
976         reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
977     return redirection->external_function();
978   }
979 
980  private:
981   void* external_function_;
982   uint32_t swi_instruction_;
983   ExternalReference::Type type_;
984   Redirection* next_;
985 };
986 
987 
RedirectExternalReference(void * external_function,ExternalReference::Type type)988 void* Simulator::RedirectExternalReference(void* external_function,
989                                            ExternalReference::Type type) {
990   Redirection* redirection = Redirection::Get(external_function, type);
991   return redirection->address_of_swi_instruction();
992 }
993 
994 
995 // Get the active Simulator for the current thread.
current(Isolate * isolate)996 Simulator* Simulator::current(Isolate* isolate) {
997   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
998        isolate->FindOrAllocatePerThreadDataForThisThread();
999   DCHECK(isolate_data != NULL);
1000   DCHECK(isolate_data != NULL);
1001 
1002   Simulator* sim = isolate_data->simulator();
1003   if (sim == NULL) {
1004     // TODO(146): delete the simulator object when a thread/isolate goes away.
1005     sim = new Simulator(isolate);
1006     isolate_data->set_simulator(sim);
1007   }
1008   return sim;
1009 }
1010 
1011 
1012 // Sets the register in the architecture state. It will also deal with updating
1013 // Simulator internal state for special registers such as PC.
set_register(int reg,int64_t value)1014 void Simulator::set_register(int reg, int64_t value) {
1015   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1016   if (reg == pc) {
1017     pc_modified_ = true;
1018   }
1019 
1020   // Zero register always holds 0.
1021   registers_[reg] = (reg == 0) ? 0 : value;
1022 }
1023 
1024 
set_dw_register(int reg,const int * dbl)1025 void Simulator::set_dw_register(int reg, const int* dbl) {
1026   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1027   registers_[reg] = dbl[1];
1028   registers_[reg] = registers_[reg] << 32;
1029   registers_[reg] += dbl[0];
1030 }
1031 
1032 
set_fpu_register(int fpureg,int64_t value)1033 void Simulator::set_fpu_register(int fpureg, int64_t value) {
1034   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1035   FPUregisters_[fpureg] = value;
1036 }
1037 
1038 
set_fpu_register_word(int fpureg,int32_t value)1039 void Simulator::set_fpu_register_word(int fpureg, int32_t value) {
1040   // Set ONLY lower 32-bits, leaving upper bits untouched.
1041   // TODO(plind): big endian issue.
1042   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1043   int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]);
1044   *pword = value;
1045 }
1046 
1047 
set_fpu_register_hi_word(int fpureg,int32_t value)1048 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
1049   // Set ONLY upper 32-bits, leaving lower bits untouched.
1050   // TODO(plind): big endian issue.
1051   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1052   int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1;
1053   *phiword = value;
1054 }
1055 
1056 
set_fpu_register_float(int fpureg,float value)1057 void Simulator::set_fpu_register_float(int fpureg, float value) {
1058   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1059   *bit_cast<float*>(&FPUregisters_[fpureg]) = value;
1060 }
1061 
1062 
set_fpu_register_double(int fpureg,double value)1063 void Simulator::set_fpu_register_double(int fpureg, double value) {
1064   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1065   *bit_cast<double*>(&FPUregisters_[fpureg]) = value;
1066 }
1067 
1068 
1069 // Get the register from the architecture state. This function does handle
1070 // the special case of accessing the PC register.
get_register(int reg) const1071 int64_t Simulator::get_register(int reg) const {
1072   DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1073   if (reg == 0)
1074     return 0;
1075   else
1076     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
1077 }
1078 
1079 
get_double_from_register_pair(int reg)1080 double Simulator::get_double_from_register_pair(int reg) {
1081   // TODO(plind): bad ABI stuff, refactor or remove.
1082   DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1083 
1084   double dm_val = 0.0;
1085   // Read the bits from the unsigned integer register_[] array
1086   // into the double precision floating point value and return it.
1087   char buffer[sizeof(registers_[0])];
1088   memcpy(buffer, &registers_[reg], sizeof(registers_[0]));
1089   memcpy(&dm_val, buffer, sizeof(registers_[0]));
1090   return(dm_val);
1091 }
1092 
1093 
get_fpu_register(int fpureg) const1094 int64_t Simulator::get_fpu_register(int fpureg) const {
1095   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1096   return FPUregisters_[fpureg];
1097 }
1098 
1099 
get_fpu_register_word(int fpureg) const1100 int32_t Simulator::get_fpu_register_word(int fpureg) const {
1101   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1102   return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1103 }
1104 
1105 
get_fpu_register_signed_word(int fpureg) const1106 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
1107   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1108   return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1109 }
1110 
1111 
get_fpu_register_hi_word(int fpureg) const1112 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
1113   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1114   return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff);
1115 }
1116 
1117 
get_fpu_register_float(int fpureg) const1118 float Simulator::get_fpu_register_float(int fpureg) const {
1119   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1120   return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg]));
1121 }
1122 
1123 
get_fpu_register_double(int fpureg) const1124 double Simulator::get_fpu_register_double(int fpureg) const {
1125   DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1126   return *bit_cast<double*>(&FPUregisters_[fpureg]);
1127 }
1128 
1129 
1130 // Runtime FP routines take up to two double arguments and zero
1131 // or one integer arguments. All are constructed here,
1132 // from a0-a3 or f12 and f13 (n64), or f14 (O32).
GetFpArgs(double * x,double * y,int32_t * z)1133 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1134   if (!IsMipsSoftFloatABI) {
1135     const int fparg2 = (kMipsAbi == kN64) ? 13 : 14;
1136     *x = get_fpu_register_double(12);
1137     *y = get_fpu_register_double(fparg2);
1138     *z = get_register(a2);
1139   } else {
1140   // TODO(plind): bad ABI stuff, refactor or remove.
1141     // We use a char buffer to get around the strict-aliasing rules which
1142     // otherwise allow the compiler to optimize away the copy.
1143     char buffer[sizeof(*x)];
1144     int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1145 
1146     // Registers a0 and a1 -> x.
1147     reg_buffer[0] = get_register(a0);
1148     reg_buffer[1] = get_register(a1);
1149     memcpy(x, buffer, sizeof(buffer));
1150     // Registers a2 and a3 -> y.
1151     reg_buffer[0] = get_register(a2);
1152     reg_buffer[1] = get_register(a3);
1153     memcpy(y, buffer, sizeof(buffer));
1154     // Register 2 -> z.
1155     reg_buffer[0] = get_register(a2);
1156     memcpy(z, buffer, sizeof(*z));
1157   }
1158 }
1159 
1160 
1161 // The return value is either in v0/v1 or f0.
SetFpResult(const double & result)1162 void Simulator::SetFpResult(const double& result) {
1163   if (!IsMipsSoftFloatABI) {
1164     set_fpu_register_double(0, result);
1165   } else {
1166     char buffer[2 * sizeof(registers_[0])];
1167     int64_t* reg_buffer = reinterpret_cast<int64_t*>(buffer);
1168     memcpy(buffer, &result, sizeof(buffer));
1169     // Copy result to v0 and v1.
1170     set_register(v0, reg_buffer[0]);
1171     set_register(v1, reg_buffer[1]);
1172   }
1173 }
1174 
1175 
1176 // Helper functions for setting and testing the FCSR register's bits.
set_fcsr_bit(uint32_t cc,bool value)1177 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1178   if (value) {
1179     FCSR_ |= (1 << cc);
1180   } else {
1181     FCSR_ &= ~(1 << cc);
1182   }
1183 }
1184 
1185 
test_fcsr_bit(uint32_t cc)1186 bool Simulator::test_fcsr_bit(uint32_t cc) {
1187   return FCSR_ & (1 << cc);
1188 }
1189 
1190 
1191 // Sets the rounding error codes in FCSR based on the result of the rounding.
1192 // Returns true if the operation was invalid.
set_fcsr_round_error(double original,double rounded)1193 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1194   bool ret = false;
1195   double max_int32 = std::numeric_limits<int32_t>::max();
1196   double min_int32 = std::numeric_limits<int32_t>::min();
1197 
1198   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1199     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1200     ret = true;
1201   }
1202 
1203   if (original != rounded) {
1204     set_fcsr_bit(kFCSRInexactFlagBit, true);
1205   }
1206 
1207   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1208     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1209     ret = true;
1210   }
1211 
1212   if (rounded > max_int32 || rounded < min_int32) {
1213     set_fcsr_bit(kFCSROverflowFlagBit, true);
1214     // The reference is not really clear but it seems this is required:
1215     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1216     ret = true;
1217   }
1218 
1219   return ret;
1220 }
1221 
1222 
1223 // Sets the rounding error codes in FCSR based on the result of the rounding.
1224 // Returns true if the operation was invalid.
set_fcsr_round64_error(double original,double rounded)1225 bool Simulator::set_fcsr_round64_error(double original, double rounded) {
1226   bool ret = false;
1227   double max_int64 = std::numeric_limits<int64_t>::max();
1228   double min_int64 = std::numeric_limits<int64_t>::min();
1229 
1230   if (!std::isfinite(original) || !std::isfinite(rounded)) {
1231     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1232     ret = true;
1233   }
1234 
1235   if (original != rounded) {
1236     set_fcsr_bit(kFCSRInexactFlagBit, true);
1237   }
1238 
1239   if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1240     set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1241     ret = true;
1242   }
1243 
1244   if (rounded > max_int64 || rounded < min_int64) {
1245     set_fcsr_bit(kFCSROverflowFlagBit, true);
1246     // The reference is not really clear but it seems this is required:
1247     set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1248     ret = true;
1249   }
1250 
1251   return ret;
1252 }
1253 
1254 
1255 // Raw access to the PC register.
set_pc(int64_t value)1256 void Simulator::set_pc(int64_t value) {
1257   pc_modified_ = true;
1258   registers_[pc] = value;
1259 }
1260 
1261 
has_bad_pc() const1262 bool Simulator::has_bad_pc() const {
1263   return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1264 }
1265 
1266 
1267 // Raw access to the PC register without the special adjustment when reading.
get_pc() const1268 int64_t Simulator::get_pc() const {
1269   return registers_[pc];
1270 }
1271 
1272 
1273 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
1274 // interrupt is caused.  On others it does a funky rotation thing.  For now we
1275 // simply disallow unaligned reads, but at some point we may want to move to
1276 // emulating the rotate behaviour.  Note that simulator runs have the runtime
1277 // system running directly on the host system and only generated code is
1278 // executed in the simulator.  Since the host is typically IA32 we will not
1279 // get the correct MIPS-like behaviour on unaligned accesses.
1280 
1281 // TODO(plind): refactor this messy debug code when we do unaligned access.
DieOrDebug()1282 void Simulator::DieOrDebug() {
1283   if (1) {  // Flag for this was removed.
1284     MipsDebugger dbg(this);
1285     dbg.Debug();
1286   } else {
1287     base::OS::Abort();
1288   }
1289 }
1290 
1291 
TraceRegWr(int64_t value)1292 void Simulator::TraceRegWr(int64_t value) {
1293   if (::v8::internal::FLAG_trace_sim) {
1294     SNPrintF(trace_buf_, "%016lx", value);
1295   }
1296 }
1297 
1298 
1299 // TODO(plind): consider making icount_ printing a flag option.
TraceMemRd(int64_t addr,int64_t value)1300 void Simulator::TraceMemRd(int64_t addr, int64_t value) {
1301   if (::v8::internal::FLAG_trace_sim) {
1302     SNPrintF(trace_buf_, "%016lx <-- [%016lx]    (%ld)",
1303              value, addr, icount_);
1304   }
1305 }
1306 
1307 
TraceMemWr(int64_t addr,int64_t value,TraceType t)1308 void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) {
1309   if (::v8::internal::FLAG_trace_sim) {
1310     switch (t) {
1311       case BYTE:
1312         SNPrintF(trace_buf_, "               %02x --> [%016lx]",
1313                  static_cast<int8_t>(value), addr);
1314         break;
1315       case HALF:
1316         SNPrintF(trace_buf_, "            %04x --> [%016lx]",
1317                  static_cast<int16_t>(value), addr);
1318         break;
1319       case WORD:
1320         SNPrintF(trace_buf_, "        %08x --> [%016lx]",
1321                  static_cast<int32_t>(value), addr);
1322         break;
1323       case DWORD:
1324         SNPrintF(trace_buf_, "%016lx --> [%016lx]    (%ld)",
1325                  value, addr, icount_);
1326         break;
1327     }
1328   }
1329 }
1330 
1331 
1332 // TODO(plind): sign-extend and zero-extend not implmented properly
1333 // on all the ReadXX functions, I don't think re-interpret cast does it.
ReadW(int64_t addr,Instruction * instr)1334 int32_t Simulator::ReadW(int64_t addr, Instruction* instr) {
1335   if (addr >=0 && addr < 0x400) {
1336     // This has to be a NULL-dereference, drop into debugger.
1337     PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
1338            addr, reinterpret_cast<intptr_t>(instr));
1339     DieOrDebug();
1340   }
1341   if ((addr & 0x3) == 0) {
1342     int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1343     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1344     return *ptr;
1345   }
1346   PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1347          addr,
1348          reinterpret_cast<intptr_t>(instr));
1349   DieOrDebug();
1350   return 0;
1351 }
1352 
1353 
ReadWU(int64_t addr,Instruction * instr)1354 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) {
1355   if (addr >=0 && addr < 0x400) {
1356     // This has to be a NULL-dereference, drop into debugger.
1357     PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
1358            addr, reinterpret_cast<intptr_t>(instr));
1359     DieOrDebug();
1360   }
1361   if ((addr & 0x3) == 0) {
1362     uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1363     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1364     return *ptr;
1365   }
1366   PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1367          addr,
1368          reinterpret_cast<intptr_t>(instr));
1369   DieOrDebug();
1370   return 0;
1371 }
1372 
1373 
WriteW(int64_t addr,int value,Instruction * instr)1374 void Simulator::WriteW(int64_t addr, int value, Instruction* instr) {
1375   if (addr >= 0 && addr < 0x400) {
1376     // This has to be a NULL-dereference, drop into debugger.
1377     PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
1378            addr, reinterpret_cast<intptr_t>(instr));
1379     DieOrDebug();
1380   }
1381   if ((addr & 0x3) == 0) {
1382     TraceMemWr(addr, value, WORD);
1383     int* ptr = reinterpret_cast<int*>(addr);
1384     *ptr = value;
1385     return;
1386   }
1387   PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1388          addr,
1389          reinterpret_cast<intptr_t>(instr));
1390   DieOrDebug();
1391 }
1392 
1393 
Read2W(int64_t addr,Instruction * instr)1394 int64_t Simulator::Read2W(int64_t addr, Instruction* instr) {
1395   if (addr >=0 && addr < 0x400) {
1396     // This has to be a NULL-dereference, drop into debugger.
1397     PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
1398            addr, reinterpret_cast<intptr_t>(instr));
1399     DieOrDebug();
1400   }
1401   if ((addr & kPointerAlignmentMask) == 0) {
1402     int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1403     TraceMemRd(addr, *ptr);
1404     return *ptr;
1405   }
1406   PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1407          addr,
1408          reinterpret_cast<intptr_t>(instr));
1409   DieOrDebug();
1410   return 0;
1411 }
1412 
1413 
Write2W(int64_t addr,int64_t value,Instruction * instr)1414 void Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) {
1415   if (addr >= 0 && addr < 0x400) {
1416     // This has to be a NULL-dereference, drop into debugger.
1417     PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
1418            addr, reinterpret_cast<intptr_t>(instr));
1419     DieOrDebug();
1420   }
1421   if ((addr & kPointerAlignmentMask) == 0) {
1422     TraceMemWr(addr, value, DWORD);
1423     int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1424     *ptr = value;
1425     return;
1426   }
1427   PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1428          addr,
1429          reinterpret_cast<intptr_t>(instr));
1430   DieOrDebug();
1431 }
1432 
1433 
ReadD(int64_t addr,Instruction * instr)1434 double Simulator::ReadD(int64_t addr, Instruction* instr) {
1435   if ((addr & kDoubleAlignmentMask) == 0) {
1436     double* ptr = reinterpret_cast<double*>(addr);
1437     return *ptr;
1438   }
1439   PrintF("Unaligned (double) read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1440          addr,
1441          reinterpret_cast<intptr_t>(instr));
1442   base::OS::Abort();
1443   return 0;
1444 }
1445 
1446 
WriteD(int64_t addr,double value,Instruction * instr)1447 void Simulator::WriteD(int64_t addr, double value, Instruction* instr) {
1448   if ((addr & kDoubleAlignmentMask) == 0) {
1449     double* ptr = reinterpret_cast<double*>(addr);
1450     *ptr = value;
1451     return;
1452   }
1453   PrintF("Unaligned (double) write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1454          addr,
1455          reinterpret_cast<intptr_t>(instr));
1456   DieOrDebug();
1457 }
1458 
1459 
ReadHU(int64_t addr,Instruction * instr)1460 uint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) {
1461   if ((addr & 1) == 0) {
1462     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1463     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1464     return *ptr;
1465   }
1466   PrintF("Unaligned unsigned halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1467          addr,
1468          reinterpret_cast<intptr_t>(instr));
1469   DieOrDebug();
1470   return 0;
1471 }
1472 
1473 
ReadH(int64_t addr,Instruction * instr)1474 int16_t Simulator::ReadH(int64_t addr, Instruction* instr) {
1475   if ((addr & 1) == 0) {
1476     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1477     TraceMemRd(addr, static_cast<int64_t>(*ptr));
1478     return *ptr;
1479   }
1480   PrintF("Unaligned signed halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1481          addr,
1482          reinterpret_cast<intptr_t>(instr));
1483   DieOrDebug();
1484   return 0;
1485 }
1486 
1487 
WriteH(int64_t addr,uint16_t value,Instruction * instr)1488 void Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) {
1489   if ((addr & 1) == 0) {
1490     TraceMemWr(addr, value, HALF);
1491     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1492     *ptr = value;
1493     return;
1494   }
1495   PrintF(
1496       "Unaligned unsigned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1497       addr,
1498       reinterpret_cast<intptr_t>(instr));
1499   DieOrDebug();
1500 }
1501 
1502 
WriteH(int64_t addr,int16_t value,Instruction * instr)1503 void Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) {
1504   if ((addr & 1) == 0) {
1505     TraceMemWr(addr, value, HALF);
1506     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1507     *ptr = value;
1508     return;
1509   }
1510   PrintF("Unaligned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1511          addr,
1512          reinterpret_cast<intptr_t>(instr));
1513   DieOrDebug();
1514 }
1515 
1516 
ReadBU(int64_t addr)1517 uint32_t Simulator::ReadBU(int64_t addr) {
1518   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1519   TraceMemRd(addr, static_cast<int64_t>(*ptr));
1520   return *ptr & 0xff;
1521 }
1522 
1523 
ReadB(int64_t addr)1524 int32_t Simulator::ReadB(int64_t addr) {
1525   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1526   TraceMemRd(addr, static_cast<int64_t>(*ptr));
1527   return *ptr;
1528 }
1529 
1530 
WriteB(int64_t addr,uint8_t value)1531 void Simulator::WriteB(int64_t addr, uint8_t value) {
1532   TraceMemWr(addr, value, BYTE);
1533   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1534   *ptr = value;
1535 }
1536 
1537 
WriteB(int64_t addr,int8_t value)1538 void Simulator::WriteB(int64_t addr, int8_t value) {
1539   TraceMemWr(addr, value, BYTE);
1540   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1541   *ptr = value;
1542 }
1543 
1544 
1545 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit() const1546 uintptr_t Simulator::StackLimit() const {
1547   // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1548   // pushing values.
1549   return reinterpret_cast<uintptr_t>(stack_) + 1024;
1550 }
1551 
1552 
1553 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)1554 void Simulator::Format(Instruction* instr, const char* format) {
1555   PrintF("Simulator found unsupported instruction:\n 0x%08lx: %s\n",
1556          reinterpret_cast<intptr_t>(instr), format);
1557   UNIMPLEMENTED_MIPS();
1558 }
1559 
1560 
1561 // Calls into the V8 runtime are based on this very simple interface.
1562 // Note: To be able to return two values from some calls the code in runtime.cc
1563 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1564 // 64-bit value. With the code below we assume that all runtime calls return
1565 // 64 bits of result. If they don't, the v1 result register contains a bogus
1566 // value, which is fine because it is caller-saved.
1567 
1568 struct ObjectPair {
1569   Object* x;
1570   Object* y;
1571 };
1572 
1573 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
1574                                         int64_t arg1,
1575                                         int64_t arg2,
1576                                         int64_t arg3,
1577                                         int64_t arg4,
1578                                         int64_t arg5);
1579 
1580 
1581 // These prototypes handle the four types of FP calls.
1582 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1583 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1584 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1585 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1586 
1587 // This signature supports direct call in to API function native callback
1588 // (refer to InvocationCallback in v8.h).
1589 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
1590 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
1591 
1592 // This signature supports direct call to accessor getter callback.
1593 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
1594 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1595     int64_t arg0, int64_t arg1, void* arg2);
1596 
1597 // Software interrupt instructions are used by the simulator to call into the
1598 // C-based V8 runtime. They are also used for debugging with simulator.
SoftwareInterrupt(Instruction * instr)1599 void Simulator::SoftwareInterrupt(Instruction* instr) {
1600   // There are several instructions that could get us here,
1601   // the break_ instruction, or several variants of traps. All
1602   // Are "SPECIAL" class opcode, and are distinuished by function.
1603   int32_t func = instr->FunctionFieldRaw();
1604   uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1605   // We first check if we met a call_rt_redirected.
1606   if (instr->InstructionBits() == rtCallRedirInstr) {
1607     Redirection* redirection = Redirection::FromSwiInstruction(instr);
1608     int64_t arg0 = get_register(a0);
1609     int64_t arg1 = get_register(a1);
1610     int64_t arg2 = get_register(a2);
1611     int64_t arg3 = get_register(a3);
1612     int64_t arg4, arg5;
1613 
1614     if (kMipsAbi == kN64) {
1615       arg4 = get_register(a4);  // Abi n64 register a4.
1616       arg5 = get_register(a5);  // Abi n64 register a5.
1617     } else {  // Abi O32.
1618       int64_t* stack_pointer = reinterpret_cast<int64_t*>(get_register(sp));
1619       // Args 4 and 5 are on the stack after the reserved space for args 0..3.
1620       arg4 = stack_pointer[4];
1621       arg5 = stack_pointer[5];
1622     }
1623     bool fp_call =
1624          (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1625          (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1626          (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1627          (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1628 
1629     if (!IsMipsSoftFloatABI) {
1630       // With the hard floating point calling convention, double
1631       // arguments are passed in FPU registers. Fetch the arguments
1632       // from there and call the builtin using soft floating point
1633       // convention.
1634       switch (redirection->type()) {
1635       case ExternalReference::BUILTIN_FP_FP_CALL:
1636       case ExternalReference::BUILTIN_COMPARE_CALL:
1637         arg0 = get_fpu_register(f12);
1638         arg1 = get_fpu_register(f13);
1639         arg2 = get_fpu_register(f14);
1640         arg3 = get_fpu_register(f15);
1641         break;
1642       case ExternalReference::BUILTIN_FP_CALL:
1643         arg0 = get_fpu_register(f12);
1644         arg1 = get_fpu_register(f13);
1645         break;
1646       case ExternalReference::BUILTIN_FP_INT_CALL:
1647         arg0 = get_fpu_register(f12);
1648         arg1 = get_fpu_register(f13);
1649         arg2 = get_register(a2);
1650         break;
1651       default:
1652         break;
1653       }
1654     }
1655 
1656     // This is dodgy but it works because the C entry stubs are never moved.
1657     // See comment in codegen-arm.cc and bug 1242173.
1658     int64_t saved_ra = get_register(ra);
1659 
1660     intptr_t external =
1661           reinterpret_cast<intptr_t>(redirection->external_function());
1662 
1663     // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1664     // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1665     // simulator. Soft-float has additional abstraction of ExternalReference,
1666     // to support serialization.
1667     if (fp_call) {
1668       double dval0, dval1;  // one or two double parameters
1669       int32_t ival;         // zero or one integer parameters
1670       int64_t iresult = 0;  // integer return value
1671       double dresult = 0;   // double return value
1672       GetFpArgs(&dval0, &dval1, &ival);
1673       SimulatorRuntimeCall generic_target =
1674           reinterpret_cast<SimulatorRuntimeCall>(external);
1675       if (::v8::internal::FLAG_trace_sim) {
1676         switch (redirection->type()) {
1677           case ExternalReference::BUILTIN_FP_FP_CALL:
1678           case ExternalReference::BUILTIN_COMPARE_CALL:
1679             PrintF("Call to host function at %p with args %f, %f",
1680                    FUNCTION_ADDR(generic_target), dval0, dval1);
1681             break;
1682           case ExternalReference::BUILTIN_FP_CALL:
1683             PrintF("Call to host function at %p with arg %f",
1684                 FUNCTION_ADDR(generic_target), dval0);
1685             break;
1686           case ExternalReference::BUILTIN_FP_INT_CALL:
1687             PrintF("Call to host function at %p with args %f, %d",
1688                    FUNCTION_ADDR(generic_target), dval0, ival);
1689             break;
1690           default:
1691             UNREACHABLE();
1692             break;
1693         }
1694       }
1695       switch (redirection->type()) {
1696       case ExternalReference::BUILTIN_COMPARE_CALL: {
1697         SimulatorRuntimeCompareCall target =
1698           reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1699         iresult = target(dval0, dval1);
1700         set_register(v0, static_cast<int64_t>(iresult));
1701       //  set_register(v1, static_cast<int64_t>(iresult >> 32));
1702         break;
1703       }
1704       case ExternalReference::BUILTIN_FP_FP_CALL: {
1705         SimulatorRuntimeFPFPCall target =
1706           reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1707         dresult = target(dval0, dval1);
1708         SetFpResult(dresult);
1709         break;
1710       }
1711       case ExternalReference::BUILTIN_FP_CALL: {
1712         SimulatorRuntimeFPCall target =
1713           reinterpret_cast<SimulatorRuntimeFPCall>(external);
1714         dresult = target(dval0);
1715         SetFpResult(dresult);
1716         break;
1717       }
1718       case ExternalReference::BUILTIN_FP_INT_CALL: {
1719         SimulatorRuntimeFPIntCall target =
1720           reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1721         dresult = target(dval0, ival);
1722         SetFpResult(dresult);
1723         break;
1724       }
1725       default:
1726         UNREACHABLE();
1727         break;
1728       }
1729       if (::v8::internal::FLAG_trace_sim) {
1730         switch (redirection->type()) {
1731         case ExternalReference::BUILTIN_COMPARE_CALL:
1732           PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1733           break;
1734         case ExternalReference::BUILTIN_FP_FP_CALL:
1735         case ExternalReference::BUILTIN_FP_CALL:
1736         case ExternalReference::BUILTIN_FP_INT_CALL:
1737           PrintF("Returned %f\n", dresult);
1738           break;
1739         default:
1740           UNREACHABLE();
1741           break;
1742         }
1743       }
1744     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1745       if (::v8::internal::FLAG_trace_sim) {
1746         PrintF("Call to host function at %p args %08lx\n",
1747             reinterpret_cast<void*>(external), arg0);
1748       }
1749       SimulatorRuntimeDirectApiCall target =
1750           reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1751       target(arg0);
1752     } else if (
1753         redirection->type() == ExternalReference::PROFILING_API_CALL) {
1754       if (::v8::internal::FLAG_trace_sim) {
1755         PrintF("Call to host function at %p args %08lx %08lx\n",
1756             reinterpret_cast<void*>(external), arg0, arg1);
1757       }
1758       SimulatorRuntimeProfilingApiCall target =
1759           reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1760       target(arg0, Redirection::ReverseRedirection(arg1));
1761     } else if (
1762         redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1763       if (::v8::internal::FLAG_trace_sim) {
1764         PrintF("Call to host function at %p args %08lx %08lx\n",
1765             reinterpret_cast<void*>(external), arg0, arg1);
1766       }
1767       SimulatorRuntimeDirectGetterCall target =
1768           reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1769       target(arg0, arg1);
1770     } else if (
1771         redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1772       if (::v8::internal::FLAG_trace_sim) {
1773         PrintF("Call to host function at %p args %08lx %08lx %08lx\n",
1774             reinterpret_cast<void*>(external), arg0, arg1, arg2);
1775       }
1776       SimulatorRuntimeProfilingGetterCall target =
1777           reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1778       target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1779     } else {
1780       SimulatorRuntimeCall target =
1781                   reinterpret_cast<SimulatorRuntimeCall>(external);
1782       if (::v8::internal::FLAG_trace_sim) {
1783         PrintF(
1784             "Call to host function at %p "
1785             "args %08lx, %08lx, %08lx, %08lx, %08lx, %08lx\n",
1786             FUNCTION_ADDR(target),
1787             arg0,
1788             arg1,
1789             arg2,
1790             arg3,
1791             arg4,
1792             arg5);
1793       }
1794       // int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1795       // set_register(v0, static_cast<int32_t>(result));
1796       // set_register(v1, static_cast<int32_t>(result >> 32));
1797       ObjectPair result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1798       set_register(v0, (int64_t)(result.x));
1799       set_register(v1, (int64_t)(result.y));
1800     }
1801      if (::v8::internal::FLAG_trace_sim) {
1802       PrintF("Returned %08lx : %08lx\n", get_register(v1), get_register(v0));
1803     }
1804     set_register(ra, saved_ra);
1805     set_pc(get_register(ra));
1806 
1807   } else if (func == BREAK && code <= kMaxStopCode) {
1808     if (IsWatchpoint(code)) {
1809       PrintWatchpoint(code);
1810     } else {
1811       IncreaseStopCounter(code);
1812       HandleStop(code, instr);
1813     }
1814   } else {
1815     // All remaining break_ codes, and all traps are handled here.
1816     MipsDebugger dbg(this);
1817     dbg.Debug();
1818   }
1819 }
1820 
1821 
1822 // Stop helper functions.
IsWatchpoint(uint64_t code)1823 bool Simulator::IsWatchpoint(uint64_t code) {
1824   return (code <= kMaxWatchpointCode);
1825 }
1826 
1827 
PrintWatchpoint(uint64_t code)1828 void Simulator::PrintWatchpoint(uint64_t code) {
1829   MipsDebugger dbg(this);
1830   ++break_count_;
1831   PrintF("\n---- break %ld marker: %3d  (instr count: %8ld) ----------"
1832          "----------------------------------",
1833          code, break_count_, icount_);
1834   dbg.PrintAllRegs();  // Print registers and continue running.
1835 }
1836 
1837 
HandleStop(uint64_t code,Instruction * instr)1838 void Simulator::HandleStop(uint64_t code, Instruction* instr) {
1839   // Stop if it is enabled, otherwise go on jumping over the stop
1840   // and the message address.
1841   if (IsEnabledStop(code)) {
1842     MipsDebugger dbg(this);
1843     dbg.Stop(instr);
1844   } else {
1845     set_pc(get_pc() + 2 * Instruction::kInstrSize);
1846   }
1847 }
1848 
1849 
IsStopInstruction(Instruction * instr)1850 bool Simulator::IsStopInstruction(Instruction* instr) {
1851   int32_t func = instr->FunctionFieldRaw();
1852   uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
1853   return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
1854 }
1855 
1856 
IsEnabledStop(uint64_t code)1857 bool Simulator::IsEnabledStop(uint64_t code) {
1858   DCHECK(code <= kMaxStopCode);
1859   DCHECK(code > kMaxWatchpointCode);
1860   return !(watched_stops_[code].count & kStopDisabledBit);
1861 }
1862 
1863 
EnableStop(uint64_t code)1864 void Simulator::EnableStop(uint64_t code) {
1865   if (!IsEnabledStop(code)) {
1866     watched_stops_[code].count &= ~kStopDisabledBit;
1867   }
1868 }
1869 
1870 
DisableStop(uint64_t code)1871 void Simulator::DisableStop(uint64_t code) {
1872   if (IsEnabledStop(code)) {
1873     watched_stops_[code].count |= kStopDisabledBit;
1874   }
1875 }
1876 
1877 
IncreaseStopCounter(uint64_t code)1878 void Simulator::IncreaseStopCounter(uint64_t code) {
1879   DCHECK(code <= kMaxStopCode);
1880   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1881     PrintF("Stop counter for code %ld has overflowed.\n"
1882            "Enabling this code and reseting the counter to 0.\n", code);
1883     watched_stops_[code].count = 0;
1884     EnableStop(code);
1885   } else {
1886     watched_stops_[code].count++;
1887   }
1888 }
1889 
1890 
1891 // Print a stop status.
PrintStopInfo(uint64_t code)1892 void Simulator::PrintStopInfo(uint64_t code) {
1893   if (code <= kMaxWatchpointCode) {
1894     PrintF("That is a watchpoint, not a stop.\n");
1895     return;
1896   } else if (code > kMaxStopCode) {
1897     PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
1898     return;
1899   }
1900   const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
1901   int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1902   // Don't print the state of unused breakpoints.
1903   if (count != 0) {
1904     if (watched_stops_[code].desc) {
1905       PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i, \t%s\n",
1906              code, code, state, count, watched_stops_[code].desc);
1907     } else {
1908       PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i\n",
1909              code, code, state, count);
1910     }
1911   }
1912 }
1913 
1914 
SignalExceptions()1915 void Simulator::SignalExceptions() {
1916   for (int i = 1; i < kNumExceptions; i++) {
1917     if (exceptions[i] != 0) {
1918       V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1919     }
1920   }
1921 }
1922 
1923 
1924 // Handle execution based on instruction types.
1925 
ConfigureTypeRegister(Instruction * instr,int64_t * alu_out,int64_t * i64hilo,uint64_t * u64hilo,int64_t * next_pc,int64_t * return_addr_reg,bool * do_interrupt,int64_t * i128resultH,int64_t * i128resultL)1926 void Simulator::ConfigureTypeRegister(Instruction* instr,
1927                                       int64_t* alu_out,
1928                                       int64_t* i64hilo,
1929                                       uint64_t* u64hilo,
1930                                       int64_t* next_pc,
1931                                       int64_t* return_addr_reg,
1932                                       bool* do_interrupt,
1933                                       int64_t* i128resultH,
1934                                       int64_t* i128resultL) {
1935   // Every local variable declared here needs to be const.
1936   // This is to make sure that changed values are sent back to
1937   // DecodeTypeRegister correctly.
1938 
1939   // Instruction fields.
1940   const Opcode   op     = instr->OpcodeFieldRaw();
1941   const int64_t  rs_reg = instr->RsValue();
1942   const int64_t  rs     = get_register(rs_reg);
1943   const uint64_t rs_u   = static_cast<uint64_t>(rs);
1944   const int64_t  rt_reg = instr->RtValue();
1945   const int64_t  rt     = get_register(rt_reg);
1946   const uint64_t rt_u   = static_cast<uint64_t>(rt);
1947   const int64_t  rd_reg = instr->RdValue();
1948   const uint64_t sa     = instr->SaValue();
1949 
1950   const int32_t  fs_reg = instr->FsValue();
1951 
1952 
1953   // ---------- Configuration.
1954   switch (op) {
1955     case COP1:    // Coprocessor instructions.
1956       switch (instr->RsFieldRaw()) {
1957         case CFC1:
1958           // At the moment only FCSR is supported.
1959           DCHECK(fs_reg == kFCSRRegister);
1960           *alu_out = FCSR_;
1961           break;
1962         case MFC1:
1963           *alu_out = static_cast<int64_t>(get_fpu_register_word(fs_reg));
1964           break;
1965         case DMFC1:
1966           *alu_out = get_fpu_register(fs_reg);
1967           break;
1968         case MFHC1:
1969           *alu_out = get_fpu_register_hi_word(fs_reg);
1970           break;
1971         case CTC1:
1972         case MTC1:
1973         case DMTC1:
1974         case MTHC1:
1975         case S:
1976         case D:
1977         case W:
1978         case L:
1979         case PS:
1980           // Do everything in the execution step.
1981           break;
1982         default:
1983         // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
1984            UNREACHABLE();
1985       }
1986       break;
1987     case COP1X:
1988       break;
1989     case SPECIAL:
1990       switch (instr->FunctionFieldRaw()) {
1991         case JR:
1992         case JALR:
1993           *next_pc = get_register(instr->RsValue());
1994           *return_addr_reg = instr->RdValue();
1995           break;
1996         case SLL:
1997           *alu_out = (int32_t)rt << sa;
1998           break;
1999         case DSLL:
2000           *alu_out = rt << sa;
2001           break;
2002         case DSLL32:
2003           *alu_out = rt << sa << 32;
2004           break;
2005         case SRL:
2006           if (rs_reg == 0) {
2007             // Regular logical right shift of a word by a fixed number of
2008             // bits instruction. RS field is always equal to 0.
2009             *alu_out = (uint32_t)rt_u >> sa;
2010           } else {
2011             // Logical right-rotate of a word by a fixed number of bits. This
2012             // is special case of SRL instruction, added in MIPS32 Release 2.
2013             // RS field is equal to 00001.
2014             *alu_out = ((uint32_t)rt_u >> sa) | ((uint32_t)rt_u << (32 - sa));
2015           }
2016           break;
2017         case DSRL:
2018           *alu_out = rt_u >> sa;
2019           break;
2020         case DSRL32:
2021           *alu_out = rt_u >> sa >> 32;
2022           break;
2023         case SRA:
2024           *alu_out = (int32_t)rt >> sa;
2025           break;
2026         case DSRA:
2027           *alu_out = rt >> sa;
2028           break;
2029         case DSRA32:
2030           *alu_out = rt >> sa >> 32;
2031           break;
2032         case SLLV:
2033           *alu_out = (int32_t)rt << rs;
2034           break;
2035         case DSLLV:
2036           *alu_out = rt << rs;
2037           break;
2038         case SRLV:
2039           if (sa == 0) {
2040             // Regular logical right-shift of a word by a variable number of
2041             // bits instruction. SA field is always equal to 0.
2042             *alu_out = (uint32_t)rt_u >> rs;
2043           } else {
2044             // Logical right-rotate of a word by a variable number of bits.
2045             // This is special case od SRLV instruction, added in MIPS32
2046             // Release 2. SA field is equal to 00001.
2047             *alu_out =
2048                 ((uint32_t)rt_u >> rs_u) | ((uint32_t)rt_u << (32 - rs_u));
2049           }
2050           break;
2051         case DSRLV:
2052           if (sa == 0) {
2053             // Regular logical right-shift of a word by a variable number of
2054             // bits instruction. SA field is always equal to 0.
2055             *alu_out = rt_u >> rs;
2056           } else {
2057             // Logical right-rotate of a word by a variable number of bits.
2058             // This is special case od SRLV instruction, added in MIPS32
2059             // Release 2. SA field is equal to 00001.
2060             *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
2061           }
2062           break;
2063         case SRAV:
2064           *alu_out = (int32_t)rt >> rs;
2065           break;
2066         case DSRAV:
2067           *alu_out = rt >> rs;
2068           break;
2069         case MFHI:  // MFHI == CLZ on R6.
2070           if (kArchVariant != kMips64r6) {
2071             DCHECK(instr->SaValue() == 0);
2072             *alu_out = get_register(HI);
2073           } else {
2074             // MIPS spec: If no bits were set in GPR rs, the result written to
2075             // GPR rd is 32.
2076             DCHECK(instr->SaValue() == 1);
2077             *alu_out = base::bits::CountLeadingZeros32(rs_u);
2078           }
2079           break;
2080         case MFLO:
2081           *alu_out = get_register(LO);
2082           break;
2083         case MULT:  // MULT == D_MUL_MUH.
2084           // TODO(plind) - Unify MULT/DMULT with single set of 64-bit HI/Lo
2085           // regs.
2086           // TODO(plind) - make the 32-bit MULT ops conform to spec regarding
2087           //   checking of 32-bit input values, and un-define operations of HW.
2088           *i64hilo = static_cast<int64_t>((int32_t)rs) *
2089               static_cast<int64_t>((int32_t)rt);
2090           break;
2091         case MULTU:
2092           *u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
2093           break;
2094         case DMULT:  // DMULT == D_MUL_MUH.
2095           if (kArchVariant != kMips64r6) {
2096             *i128resultH = MultiplyHighSigned(rs, rt);
2097             *i128resultL = rs * rt;
2098           } else {
2099             switch (instr->SaValue()) {
2100               case MUL_OP:
2101                 *i128resultL = rs * rt;
2102                 break;
2103               case MUH_OP:
2104                 *i128resultH = MultiplyHighSigned(rs, rt);
2105                 break;
2106               default:
2107                 UNIMPLEMENTED_MIPS();
2108                 break;
2109             }
2110           }
2111           break;
2112         case DMULTU:
2113           UNIMPLEMENTED_MIPS();
2114           break;
2115         case ADD:
2116         case DADD:
2117           if (HaveSameSign(rs, rt)) {
2118             if (rs > 0) {
2119               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
2120             } else if (rs < 0) {
2121               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
2122             }
2123           }
2124           *alu_out = rs + rt;
2125           break;
2126         case ADDU: {
2127             int32_t alu32_out = rs + rt;
2128             // Sign-extend result of 32bit operation into 64bit register.
2129             *alu_out = static_cast<int64_t>(alu32_out);
2130           }
2131           break;
2132         case DADDU:
2133           *alu_out = rs + rt;
2134           break;
2135         case SUB:
2136         case DSUB:
2137           if (!HaveSameSign(rs, rt)) {
2138             if (rs > 0) {
2139               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
2140             } else if (rs < 0) {
2141               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
2142             }
2143           }
2144           *alu_out = rs - rt;
2145           break;
2146         case SUBU: {
2147             int32_t alu32_out = rs - rt;
2148             // Sign-extend result of 32bit operation into 64bit register.
2149             *alu_out = static_cast<int64_t>(alu32_out);
2150           }
2151           break;
2152         case DSUBU:
2153           *alu_out = rs - rt;
2154           break;
2155         case AND:
2156           *alu_out = rs & rt;
2157           break;
2158         case OR:
2159           *alu_out = rs | rt;
2160           break;
2161         case XOR:
2162           *alu_out = rs ^ rt;
2163           break;
2164         case NOR:
2165           *alu_out = ~(rs | rt);
2166           break;
2167         case SLT:
2168           *alu_out = rs < rt ? 1 : 0;
2169           break;
2170         case SLTU:
2171           *alu_out = rs_u < rt_u ? 1 : 0;
2172           break;
2173         // Break and trap instructions.
2174         case BREAK:
2175 
2176           *do_interrupt = true;
2177           break;
2178         case TGE:
2179           *do_interrupt = rs >= rt;
2180           break;
2181         case TGEU:
2182           *do_interrupt = rs_u >= rt_u;
2183           break;
2184         case TLT:
2185           *do_interrupt = rs < rt;
2186           break;
2187         case TLTU:
2188           *do_interrupt = rs_u < rt_u;
2189           break;
2190         case TEQ:
2191           *do_interrupt = rs == rt;
2192           break;
2193         case TNE:
2194           *do_interrupt = rs != rt;
2195           break;
2196         case MOVN:
2197         case MOVZ:
2198         case MOVCI:
2199           // No action taken on decode.
2200           break;
2201         case DIV:
2202         case DIVU:
2203         case DDIV:
2204         case DDIVU:
2205           // div and divu never raise exceptions.
2206           break;
2207         default:
2208           UNREACHABLE();
2209       }
2210       break;
2211     case SPECIAL2:
2212       switch (instr->FunctionFieldRaw()) {
2213         case MUL:
2214           // Only the lower 32 bits are kept.
2215           *alu_out = (int32_t)rs_u * (int32_t)rt_u;
2216           break;
2217         case CLZ:
2218           // MIPS32 spec: If no bits were set in GPR rs, the result written to
2219           // GPR rd is 32.
2220           *alu_out = base::bits::CountLeadingZeros32(rs_u);
2221           break;
2222         default:
2223           UNREACHABLE();
2224       }
2225       break;
2226     case SPECIAL3:
2227       switch (instr->FunctionFieldRaw()) {
2228         case INS: {   // Mips32r2 instruction.
2229           // Interpret rd field as 5-bit msb of insert.
2230           uint16_t msb = rd_reg;
2231           // Interpret sa field as 5-bit lsb of insert.
2232           uint16_t lsb = sa;
2233           uint16_t size = msb - lsb + 1;
2234           uint32_t mask = (1 << size) - 1;
2235           *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
2236           break;
2237         }
2238         case EXT: {   // Mips32r2 instruction.
2239           // Interpret rd field as 5-bit msb of extract.
2240           uint16_t msb = rd_reg;
2241           // Interpret sa field as 5-bit lsb of extract.
2242           uint16_t lsb = sa;
2243           uint16_t size = msb + 1;
2244           uint32_t mask = (1 << size) - 1;
2245           *alu_out = (rs_u & (mask << lsb)) >> lsb;
2246           break;
2247         }
2248         default:
2249           UNREACHABLE();
2250       }
2251       break;
2252     default:
2253       UNREACHABLE();
2254   }
2255 }
2256 
2257 
DecodeTypeRegister(Instruction * instr)2258 void Simulator::DecodeTypeRegister(Instruction* instr) {
2259   // Instruction fields.
2260   const Opcode   op     = instr->OpcodeFieldRaw();
2261   const int64_t  rs_reg = instr->RsValue();
2262   const int64_t  rs     = get_register(rs_reg);
2263   const uint64_t rs_u   = static_cast<uint32_t>(rs);
2264   const int64_t  rt_reg = instr->RtValue();
2265   const int64_t  rt     = get_register(rt_reg);
2266   const uint64_t rt_u   = static_cast<uint32_t>(rt);
2267   const int64_t  rd_reg = instr->RdValue();
2268 
2269   const int32_t  fr_reg = instr->FrValue();
2270   const int32_t  fs_reg = instr->FsValue();
2271   const int32_t  ft_reg = instr->FtValue();
2272   const int64_t  fd_reg = instr->FdValue();
2273   int64_t  i64hilo = 0;
2274   uint64_t u64hilo = 0;
2275 
2276   // ALU output.
2277   // It should not be used as is. Instructions using it should always
2278   // initialize it first.
2279   int64_t alu_out = 0x12345678;
2280 
2281   // For break and trap instructions.
2282   bool do_interrupt = false;
2283 
2284   // For jr and jalr.
2285   // Get current pc.
2286   int64_t current_pc = get_pc();
2287   // Next pc
2288   int64_t next_pc = 0;
2289   int64_t return_addr_reg = 31;
2290 
2291   int64_t i128resultH;
2292   int64_t i128resultL;
2293 
2294   // Set up the variables if needed before executing the instruction.
2295   ConfigureTypeRegister(instr,
2296                         &alu_out,
2297                         &i64hilo,
2298                         &u64hilo,
2299                         &next_pc,
2300                         &return_addr_reg,
2301                         &do_interrupt,
2302                         &i128resultH,
2303                         &i128resultL);
2304 
2305   // ---------- Raise exceptions triggered.
2306   SignalExceptions();
2307 
2308   // ---------- Execution.
2309   switch (op) {
2310     case COP1:
2311       switch (instr->RsFieldRaw()) {
2312         case BC1:   // Branch on coprocessor condition.
2313         case BC1EQZ:
2314         case BC1NEZ:
2315           UNREACHABLE();
2316           break;
2317         case CFC1:
2318           set_register(rt_reg, alu_out);
2319           break;
2320         case MFC1:
2321         case DMFC1:
2322         case MFHC1:
2323           set_register(rt_reg, alu_out);
2324           break;
2325         case CTC1:
2326           // At the moment only FCSR is supported.
2327           DCHECK(fs_reg == kFCSRRegister);
2328           FCSR_ = registers_[rt_reg];
2329           break;
2330         case MTC1:
2331           // Hardware writes upper 32-bits to zero on mtc1.
2332           set_fpu_register_hi_word(fs_reg, 0);
2333           set_fpu_register_word(fs_reg, registers_[rt_reg]);
2334           break;
2335         case DMTC1:
2336           set_fpu_register(fs_reg, registers_[rt_reg]);
2337           break;
2338         case MTHC1:
2339           set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
2340           break;
2341         case S:
2342           float f;
2343           switch (instr->FunctionFieldRaw()) {
2344             case CVT_D_S:
2345               f = get_fpu_register_float(fs_reg);
2346               set_fpu_register_double(fd_reg, static_cast<double>(f));
2347               break;
2348             default:
2349             // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2350             // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2351               UNREACHABLE();
2352           }
2353           break;
2354         case D:
2355           double ft, fs;
2356           uint32_t cc, fcsr_cc;
2357           int64_t  i64;
2358           fs = get_fpu_register_double(fs_reg);
2359           ft = get_fpu_register_double(ft_reg);
2360           cc = instr->FCccValue();
2361           fcsr_cc = get_fcsr_condition_bit(cc);
2362           switch (instr->FunctionFieldRaw()) {
2363             case ADD_D:
2364               set_fpu_register_double(fd_reg, fs + ft);
2365               break;
2366             case SUB_D:
2367               set_fpu_register_double(fd_reg, fs - ft);
2368               break;
2369             case MUL_D:
2370               set_fpu_register_double(fd_reg, fs * ft);
2371               break;
2372             case DIV_D:
2373               set_fpu_register_double(fd_reg, fs / ft);
2374               break;
2375             case ABS_D:
2376               set_fpu_register_double(fd_reg, fabs(fs));
2377               break;
2378             case MOV_D:
2379               set_fpu_register_double(fd_reg, fs);
2380               break;
2381             case NEG_D:
2382               set_fpu_register_double(fd_reg, -fs);
2383               break;
2384             case SQRT_D:
2385               set_fpu_register_double(fd_reg, sqrt(fs));
2386               break;
2387             case C_UN_D:
2388               set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2389               break;
2390             case C_EQ_D:
2391               set_fcsr_bit(fcsr_cc, (fs == ft));
2392               break;
2393             case C_UEQ_D:
2394               set_fcsr_bit(fcsr_cc,
2395                            (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2396               break;
2397             case C_OLT_D:
2398               set_fcsr_bit(fcsr_cc, (fs < ft));
2399               break;
2400             case C_ULT_D:
2401               set_fcsr_bit(fcsr_cc,
2402                            (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2403               break;
2404             case C_OLE_D:
2405               set_fcsr_bit(fcsr_cc, (fs <= ft));
2406               break;
2407             case C_ULE_D:
2408               set_fcsr_bit(fcsr_cc,
2409                            (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2410               break;
2411             case CVT_W_D:   // Convert double to word.
2412               // Rounding modes are not yet supported.
2413               DCHECK((FCSR_ & 3) == 0);
2414               // In rounding mode 0 it should behave like ROUND.
2415               // No break.
2416             case ROUND_W_D:  // Round double to word (round half to even).
2417               {
2418                 double rounded = std::floor(fs + 0.5);
2419                 int32_t result = static_cast<int32_t>(rounded);
2420                 if ((result & 1) != 0 && result - fs == 0.5) {
2421                   // If the number is halfway between two integers,
2422                   // round to the even one.
2423                   result--;
2424                 }
2425                 set_fpu_register_word(fd_reg, result);
2426                 if (set_fcsr_round_error(fs, rounded)) {
2427                   set_fpu_register(fd_reg, kFPUInvalidResult);
2428                 }
2429               }
2430               break;
2431             case TRUNC_W_D:  // Truncate double to word (round towards 0).
2432               {
2433                 double rounded = trunc(fs);
2434                 int32_t result = static_cast<int32_t>(rounded);
2435                 set_fpu_register_word(fd_reg, result);
2436                 if (set_fcsr_round_error(fs, rounded)) {
2437                   set_fpu_register(fd_reg, kFPUInvalidResult);
2438                 }
2439               }
2440               break;
2441             case FLOOR_W_D:  // Round double to word towards negative infinity.
2442               {
2443                 double rounded = std::floor(fs);
2444                 int32_t result = static_cast<int32_t>(rounded);
2445                 set_fpu_register_word(fd_reg, result);
2446                 if (set_fcsr_round_error(fs, rounded)) {
2447                   set_fpu_register(fd_reg, kFPUInvalidResult);
2448                 }
2449               }
2450               break;
2451             case CEIL_W_D:  // Round double to word towards positive infinity.
2452               {
2453                 double rounded = std::ceil(fs);
2454                 int32_t result = static_cast<int32_t>(rounded);
2455                 set_fpu_register_word(fd_reg, result);
2456                 if (set_fcsr_round_error(fs, rounded)) {
2457                   set_fpu_register(fd_reg, kFPUInvalidResult);
2458                 }
2459               }
2460               break;
2461             case CVT_S_D:  // Convert double to float (single).
2462               set_fpu_register_float(fd_reg, static_cast<float>(fs));
2463               break;
2464             case CVT_L_D:   // Mips64r2: Truncate double to 64-bit long-word.
2465               // Rounding modes are not yet supported.
2466               DCHECK((FCSR_ & 3) == 0);
2467               // In rounding mode 0 it should behave like ROUND.
2468               // No break.
2469             case ROUND_L_D: {  // Mips64r2 instruction.
2470               // check error cases
2471               double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2472               int64_t result = static_cast<int64_t>(rounded);
2473               set_fpu_register(fd_reg, result);
2474               if (set_fcsr_round64_error(fs, rounded)) {
2475                 set_fpu_register(fd_reg, kFPU64InvalidResult);
2476               }
2477               break;
2478             }
2479             case TRUNC_L_D: {  // Mips64r2 instruction.
2480               double rounded = trunc(fs);
2481               int64_t result = static_cast<int64_t>(rounded);
2482               set_fpu_register(fd_reg, result);
2483               if (set_fcsr_round64_error(fs, rounded)) {
2484                 set_fpu_register(fd_reg, kFPU64InvalidResult);
2485               }
2486               break;
2487             }
2488             case FLOOR_L_D: {  // Mips64r2 instruction.
2489               double rounded = floor(fs);
2490               int64_t result = static_cast<int64_t>(rounded);
2491               set_fpu_register(fd_reg, result);
2492               if (set_fcsr_round64_error(fs, rounded)) {
2493                 set_fpu_register(fd_reg, kFPU64InvalidResult);
2494               }
2495               break;
2496             }
2497             case CEIL_L_D: {  // Mips64r2 instruction.
2498               double rounded = ceil(fs);
2499               int64_t result = static_cast<int64_t>(rounded);
2500               set_fpu_register(fd_reg, result);
2501               if (set_fcsr_round64_error(fs, rounded)) {
2502                 set_fpu_register(fd_reg, kFPU64InvalidResult);
2503               }
2504               break;
2505             }
2506             case C_F_D:
2507               UNIMPLEMENTED_MIPS();
2508               break;
2509             default:
2510               UNREACHABLE();
2511           }
2512           break;
2513         case W:
2514           switch (instr->FunctionFieldRaw()) {
2515             case CVT_S_W:   // Convert word to float (single).
2516               alu_out = get_fpu_register_signed_word(fs_reg);
2517               set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2518               break;
2519             case CVT_D_W:   // Convert word to double.
2520               alu_out = get_fpu_register_signed_word(fs_reg);
2521               set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2522               break;
2523             default:  // Mips64r6 CMP.S instructions unimplemented.
2524               UNREACHABLE();
2525           }
2526           break;
2527         case L:
2528           fs = get_fpu_register_double(fs_reg);
2529           ft = get_fpu_register_double(ft_reg);
2530           switch (instr->FunctionFieldRaw()) {
2531             case CVT_D_L:  // Mips32r2 instruction.
2532               i64 = get_fpu_register(fs_reg);
2533               set_fpu_register_double(fd_reg, static_cast<double>(i64));
2534               break;
2535             case CVT_S_L:
2536               UNIMPLEMENTED_MIPS();
2537               break;
2538             case CMP_AF:  // Mips64r6 CMP.D instructions.
2539               UNIMPLEMENTED_MIPS();
2540               break;
2541             case CMP_UN:
2542               if (std::isnan(fs) || std::isnan(ft)) {
2543                 set_fpu_register(fd_reg, -1);
2544               } else {
2545                 set_fpu_register(fd_reg, 0);
2546               }
2547               break;
2548             case CMP_EQ:
2549               if (fs == ft) {
2550                 set_fpu_register(fd_reg, -1);
2551               } else {
2552                 set_fpu_register(fd_reg, 0);
2553               }
2554               break;
2555             case CMP_UEQ:
2556               if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2557                 set_fpu_register(fd_reg, -1);
2558               } else {
2559                 set_fpu_register(fd_reg, 0);
2560               }
2561               break;
2562             case CMP_LT:
2563               if (fs < ft) {
2564                 set_fpu_register(fd_reg, -1);
2565               } else {
2566                 set_fpu_register(fd_reg, 0);
2567               }
2568               break;
2569             case CMP_ULT:
2570               if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2571                 set_fpu_register(fd_reg, -1);
2572               } else {
2573                 set_fpu_register(fd_reg, 0);
2574               }
2575               break;
2576             case CMP_LE:
2577               if (fs <= ft) {
2578                 set_fpu_register(fd_reg, -1);
2579               } else {
2580                 set_fpu_register(fd_reg, 0);
2581               }
2582               break;
2583             case CMP_ULE:
2584               if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2585                 set_fpu_register(fd_reg, -1);
2586               } else {
2587                 set_fpu_register(fd_reg, 0);
2588               }
2589               break;
2590             default:  // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED
2591               UNREACHABLE();
2592           }
2593           break;
2594         default:
2595           UNREACHABLE();
2596       }
2597       break;
2598     case COP1X:
2599       switch (instr->FunctionFieldRaw()) {
2600         case MADD_D:
2601           double fr, ft, fs;
2602           fr = get_fpu_register_double(fr_reg);
2603           fs = get_fpu_register_double(fs_reg);
2604           ft = get_fpu_register_double(ft_reg);
2605           set_fpu_register_double(fd_reg, fs * ft + fr);
2606           break;
2607         default:
2608           UNREACHABLE();
2609       }
2610       break;
2611     case SPECIAL:
2612       switch (instr->FunctionFieldRaw()) {
2613         case JR: {
2614           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2615               current_pc+Instruction::kInstrSize);
2616           BranchDelayInstructionDecode(branch_delay_instr);
2617           set_pc(next_pc);
2618           pc_modified_ = true;
2619           break;
2620         }
2621         case JALR: {
2622           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2623               current_pc+Instruction::kInstrSize);
2624           BranchDelayInstructionDecode(branch_delay_instr);
2625           set_register(return_addr_reg,
2626                        current_pc + 2 * Instruction::kInstrSize);
2627           set_pc(next_pc);
2628           pc_modified_ = true;
2629           break;
2630         }
2631         // Instructions using HI and LO registers.
2632         case MULT:
2633           if (kArchVariant != kMips64r6) {
2634             set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2635             set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2636           } else {
2637             switch (instr->SaValue()) {
2638               case MUL_OP:
2639                 set_register(rd_reg,
2640                     static_cast<int32_t>(i64hilo & 0xffffffff));
2641                 break;
2642               case MUH_OP:
2643                 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
2644                 break;
2645               default:
2646                 UNIMPLEMENTED_MIPS();
2647                 break;
2648             }
2649           }
2650           break;
2651         case MULTU:
2652           set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2653           set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2654           break;
2655         case DMULT:  // DMULT == D_MUL_MUH.
2656           if (kArchVariant != kMips64r6) {
2657             set_register(LO, static_cast<int64_t>(i128resultL));
2658             set_register(HI, static_cast<int64_t>(i128resultH));
2659           } else {
2660             switch (instr->SaValue()) {
2661               case MUL_OP:
2662                 set_register(rd_reg, static_cast<int64_t>(i128resultL));
2663                 break;
2664               case MUH_OP:
2665                 set_register(rd_reg, static_cast<int64_t>(i128resultH));
2666                 break;
2667               default:
2668                 UNIMPLEMENTED_MIPS();
2669                 break;
2670             }
2671           }
2672           break;
2673         case DMULTU:
2674           UNIMPLEMENTED_MIPS();
2675           break;
2676         case DSLL:
2677           set_register(rd_reg, alu_out);
2678           break;
2679         case DIV:
2680         case DDIV:
2681           switch (kArchVariant) {
2682             case kMips64r2:
2683               // Divide by zero and overflow was not checked in the
2684               // configuration step - div and divu do not raise exceptions. On
2685               // division by 0 the result will be UNPREDICTABLE. On overflow
2686               // (INT_MIN/-1), return INT_MIN which is what the hardware does.
2687               if (rs == INT_MIN && rt == -1) {
2688                 set_register(LO, INT_MIN);
2689                 set_register(HI, 0);
2690               } else if (rt != 0) {
2691                 set_register(LO, rs / rt);
2692                 set_register(HI, rs % rt);
2693               }
2694               break;
2695             case kMips64r6:
2696               switch (instr->SaValue()) {
2697                 case DIV_OP:
2698                   if (rs == INT_MIN && rt == -1) {
2699                     set_register(rd_reg, INT_MIN);
2700                   } else if (rt != 0) {
2701                     set_register(rd_reg, rs / rt);
2702                   }
2703                   break;
2704                 case MOD_OP:
2705                   if (rs == INT_MIN && rt == -1) {
2706                     set_register(rd_reg, 0);
2707                   } else if (rt != 0) {
2708                     set_register(rd_reg, rs % rt);
2709                   }
2710                   break;
2711                 default:
2712                   UNIMPLEMENTED_MIPS();
2713                   break;
2714               }
2715               break;
2716             default:
2717               break;
2718           }
2719           break;
2720         case DIVU:
2721           if (rt_u != 0) {
2722             set_register(LO, rs_u / rt_u);
2723             set_register(HI, rs_u % rt_u);
2724           }
2725           break;
2726         // Break and trap instructions.
2727         case BREAK:
2728         case TGE:
2729         case TGEU:
2730         case TLT:
2731         case TLTU:
2732         case TEQ:
2733         case TNE:
2734           if (do_interrupt) {
2735             SoftwareInterrupt(instr);
2736           }
2737           break;
2738         // Conditional moves.
2739         case MOVN:
2740           if (rt) {
2741             set_register(rd_reg, rs);
2742             TraceRegWr(rs);
2743           }
2744           break;
2745         case MOVCI: {
2746           uint32_t cc = instr->FBccValue();
2747           uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2748           if (instr->Bit(16)) {  // Read Tf bit.
2749             if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2750           } else {
2751             if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2752           }
2753           break;
2754         }
2755         case MOVZ:
2756           if (!rt) {
2757             set_register(rd_reg, rs);
2758             TraceRegWr(rs);
2759           }
2760           break;
2761         default:  // For other special opcodes we do the default operation.
2762           set_register(rd_reg, alu_out);
2763           TraceRegWr(alu_out);
2764       }
2765       break;
2766     case SPECIAL2:
2767       switch (instr->FunctionFieldRaw()) {
2768         case MUL:
2769           set_register(rd_reg, alu_out);
2770           TraceRegWr(alu_out);
2771           // HI and LO are UNPREDICTABLE after the operation.
2772           set_register(LO, Unpredictable);
2773           set_register(HI, Unpredictable);
2774           break;
2775         default:  // For other special2 opcodes we do the default operation.
2776           set_register(rd_reg, alu_out);
2777       }
2778       break;
2779     case SPECIAL3:
2780       switch (instr->FunctionFieldRaw()) {
2781         case INS:
2782           // Ins instr leaves result in Rt, rather than Rd.
2783           set_register(rt_reg, alu_out);
2784           TraceRegWr(alu_out);
2785           break;
2786         case EXT:
2787           // Ext instr leaves result in Rt, rather than Rd.
2788           set_register(rt_reg, alu_out);
2789           TraceRegWr(alu_out);
2790           break;
2791         default:
2792           UNREACHABLE();
2793       }
2794       break;
2795     // Unimplemented opcodes raised an error in the configuration step before,
2796     // so we can use the default here to set the destination register in common
2797     // cases.
2798     default:
2799       set_register(rd_reg, alu_out);
2800       TraceRegWr(alu_out);
2801   }
2802 }
2803 
2804 
2805 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
DecodeTypeImmediate(Instruction * instr)2806 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2807   // Instruction fields.
2808   Opcode   op     = instr->OpcodeFieldRaw();
2809   int64_t  rs     = get_register(instr->RsValue());
2810   uint64_t rs_u   = static_cast<uint64_t>(rs);
2811   int64_t  rt_reg = instr->RtValue();  // Destination register.
2812   int64_t  rt     = get_register(rt_reg);
2813   int16_t  imm16  = instr->Imm16Value();
2814 
2815   int32_t  ft_reg = instr->FtValue();  // Destination register.
2816   int64_t  ft     = get_fpu_register(ft_reg);
2817 
2818   // Zero extended immediate.
2819   uint32_t  oe_imm16 = 0xffff & imm16;
2820   // Sign extended immediate.
2821   int32_t   se_imm16 = imm16;
2822 
2823   // Get current pc.
2824   int64_t current_pc = get_pc();
2825   // Next pc.
2826   int64_t next_pc = bad_ra;
2827 
2828   // Used for conditional branch instructions.
2829   bool do_branch = false;
2830   bool execute_branch_delay_instruction = false;
2831 
2832   // Used for arithmetic instructions.
2833   int64_t alu_out = 0;
2834   // Floating point.
2835   double fp_out = 0.0;
2836   uint32_t cc, cc_value, fcsr_cc;
2837 
2838   // Used for memory instructions.
2839   int64_t addr = 0x0;
2840   // Value to be written in memory.
2841   uint64_t mem_value = 0x0;
2842   // Alignment for 32-bit integers used in LWL, LWR, etc.
2843   const int kInt32AlignmentMask = sizeof(uint32_t) - 1;
2844 
2845   // ---------- Configuration (and execution for REGIMM).
2846   switch (op) {
2847     // ------------- COP1. Coprocessor instructions.
2848     case COP1:
2849       switch (instr->RsFieldRaw()) {
2850         case BC1:   // Branch on coprocessor condition.
2851           cc = instr->FBccValue();
2852           fcsr_cc = get_fcsr_condition_bit(cc);
2853           cc_value = test_fcsr_bit(fcsr_cc);
2854           do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2855           execute_branch_delay_instruction = true;
2856           // Set next_pc.
2857           if (do_branch) {
2858             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2859           } else {
2860             next_pc = current_pc + kBranchReturnOffset;
2861           }
2862           break;
2863         case BC1EQZ:
2864           do_branch = (ft & 0x1) ? false : true;
2865           execute_branch_delay_instruction = true;
2866           // Set next_pc.
2867           if (do_branch) {
2868             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2869           } else {
2870             next_pc = current_pc + kBranchReturnOffset;
2871           }
2872           break;
2873         case BC1NEZ:
2874           do_branch = (ft & 0x1) ? true : false;
2875           execute_branch_delay_instruction = true;
2876           // Set next_pc.
2877           if (do_branch) {
2878             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2879           } else {
2880             next_pc = current_pc + kBranchReturnOffset;
2881           }
2882           break;
2883         default:
2884           UNREACHABLE();
2885       }
2886       break;
2887     // ------------- REGIMM class.
2888     case REGIMM:
2889       switch (instr->RtFieldRaw()) {
2890         case BLTZ:
2891           do_branch = (rs  < 0);
2892           break;
2893         case BLTZAL:
2894           do_branch = rs  < 0;
2895           break;
2896         case BGEZ:
2897           do_branch = rs >= 0;
2898           break;
2899         case BGEZAL:
2900           do_branch = rs >= 0;
2901           break;
2902         default:
2903           UNREACHABLE();
2904       }
2905       switch (instr->RtFieldRaw()) {
2906         case BLTZ:
2907         case BLTZAL:
2908         case BGEZ:
2909         case BGEZAL:
2910           // Branch instructions common part.
2911           execute_branch_delay_instruction = true;
2912           // Set next_pc.
2913           if (do_branch) {
2914             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2915             if (instr->IsLinkingInstruction()) {
2916               set_register(31, current_pc + kBranchReturnOffset);
2917             }
2918           } else {
2919             next_pc = current_pc + kBranchReturnOffset;
2920           }
2921         default:
2922           break;
2923         }
2924     break;  // case REGIMM.
2925     // ------------- Branch instructions.
2926     // When comparing to zero, the encoding of rt field is always 0, so we don't
2927     // need to replace rt with zero.
2928     case BEQ:
2929       do_branch = (rs == rt);
2930       break;
2931     case BNE:
2932       do_branch = rs != rt;
2933       break;
2934     case BLEZ:
2935       do_branch = rs <= 0;
2936       break;
2937     case BGTZ:
2938       do_branch = rs  > 0;
2939       break;
2940     // ------------- Arithmetic instructions.
2941     case ADDI:
2942     case DADDI:
2943       if (HaveSameSign(rs, se_imm16)) {
2944         if (rs > 0) {
2945           exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2946         } else if (rs < 0) {
2947           exceptions[kIntegerUnderflow] =
2948               rs < (Registers::kMinValue - se_imm16);
2949         }
2950       }
2951       alu_out = rs + se_imm16;
2952       break;
2953     case ADDIU: {
2954         int32_t alu32_out = rs + se_imm16;
2955         // Sign-extend result of 32bit operation into 64bit register.
2956         alu_out = static_cast<int64_t>(alu32_out);
2957       }
2958       break;
2959     case DADDIU:
2960       alu_out = rs + se_imm16;
2961       break;
2962     case SLTI:
2963       alu_out = (rs < se_imm16) ? 1 : 0;
2964       break;
2965     case SLTIU:
2966       alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2967       break;
2968     case ANDI:
2969         alu_out = rs & oe_imm16;
2970       break;
2971     case ORI:
2972         alu_out = rs | oe_imm16;
2973       break;
2974     case XORI:
2975         alu_out = rs ^ oe_imm16;
2976       break;
2977     case LUI: {
2978         int32_t alu32_out = (oe_imm16 << 16);
2979         // Sign-extend result of 32bit operation into 64bit register.
2980         alu_out = static_cast<int64_t>(alu32_out);
2981       }
2982       break;
2983     // ------------- Memory instructions.
2984     case LB:
2985       addr = rs + se_imm16;
2986       alu_out = ReadB(addr);
2987       break;
2988     case LH:
2989       addr = rs + se_imm16;
2990       alu_out = ReadH(addr, instr);
2991       break;
2992     case LWL: {
2993       // al_offset is offset of the effective address within an aligned word.
2994       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
2995       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
2996       uint32_t mask = (1 << byte_shift * 8) - 1;
2997       addr = rs + se_imm16 - al_offset;
2998       alu_out = ReadW(addr, instr);
2999       alu_out <<= byte_shift * 8;
3000       alu_out |= rt & mask;
3001       break;
3002     }
3003     case LW:
3004       addr = rs + se_imm16;
3005       alu_out = ReadW(addr, instr);
3006       break;
3007     case LWU:
3008       addr = rs + se_imm16;
3009       alu_out = ReadWU(addr, instr);
3010       break;
3011     case LD:
3012       addr = rs + se_imm16;
3013       alu_out = Read2W(addr, instr);
3014       break;
3015     case LBU:
3016       addr = rs + se_imm16;
3017       alu_out = ReadBU(addr);
3018       break;
3019     case LHU:
3020       addr = rs + se_imm16;
3021       alu_out = ReadHU(addr, instr);
3022       break;
3023     case LWR: {
3024       // al_offset is offset of the effective address within an aligned word.
3025       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
3026       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
3027       uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
3028       addr = rs + se_imm16 - al_offset;
3029       alu_out = ReadW(addr, instr);
3030       alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
3031       alu_out |= rt & mask;
3032       break;
3033     }
3034     case SB:
3035       addr = rs + se_imm16;
3036       break;
3037     case SH:
3038       addr = rs + se_imm16;
3039       break;
3040     case SWL: {
3041       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
3042       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
3043       uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
3044       addr = rs + se_imm16 - al_offset;
3045       mem_value = ReadW(addr, instr) & mask;
3046       mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
3047       break;
3048     }
3049     case SW:
3050     case SD:
3051       addr = rs + se_imm16;
3052       break;
3053     case SWR: {
3054       uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
3055       uint32_t mask = (1 << al_offset * 8) - 1;
3056       addr = rs + se_imm16 - al_offset;
3057       mem_value = ReadW(addr, instr);
3058       mem_value = (rt << al_offset * 8) | (mem_value & mask);
3059       break;
3060     }
3061     case LWC1:
3062       addr = rs + se_imm16;
3063       alu_out = ReadW(addr, instr);
3064       break;
3065     case LDC1:
3066       addr = rs + se_imm16;
3067       fp_out = ReadD(addr, instr);
3068       break;
3069     case SWC1:
3070     case SDC1:
3071       addr = rs + se_imm16;
3072       break;
3073     default:
3074       UNREACHABLE();
3075   }
3076 
3077   // ---------- Raise exceptions triggered.
3078   SignalExceptions();
3079 
3080   // ---------- Execution.
3081   switch (op) {
3082     // ------------- Branch instructions.
3083     case BEQ:
3084     case BNE:
3085     case BLEZ:
3086     case BGTZ:
3087       // Branch instructions common part.
3088       execute_branch_delay_instruction = true;
3089       // Set next_pc.
3090       if (do_branch) {
3091         next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
3092         if (instr->IsLinkingInstruction()) {
3093           set_register(31, current_pc + 2* Instruction::kInstrSize);
3094         }
3095       } else {
3096         next_pc = current_pc + 2 * Instruction::kInstrSize;
3097       }
3098       break;
3099     // ------------- Arithmetic instructions.
3100     case ADDI:
3101     case DADDI:
3102     case ADDIU:
3103     case DADDIU:
3104     case SLTI:
3105     case SLTIU:
3106     case ANDI:
3107     case ORI:
3108     case XORI:
3109     case LUI:
3110       set_register(rt_reg, alu_out);
3111       TraceRegWr(alu_out);
3112       break;
3113     // ------------- Memory instructions.
3114     case LB:
3115     case LH:
3116     case LWL:
3117     case LW:
3118     case LWU:
3119     case LD:
3120     case LBU:
3121     case LHU:
3122     case LWR:
3123       set_register(rt_reg, alu_out);
3124       break;
3125     case SB:
3126       WriteB(addr, static_cast<int8_t>(rt));
3127       break;
3128     case SH:
3129       WriteH(addr, static_cast<uint16_t>(rt), instr);
3130       break;
3131     case SWL:
3132       WriteW(addr, mem_value, instr);
3133       break;
3134     case SW:
3135       WriteW(addr, rt, instr);
3136       break;
3137     case SD:
3138       Write2W(addr, rt, instr);
3139       break;
3140     case SWR:
3141       WriteW(addr, mem_value, instr);
3142       break;
3143     case LWC1:
3144       set_fpu_register(ft_reg, kFPUInvalidResult);  // Trash upper 32 bits.
3145       set_fpu_register_word(ft_reg, static_cast<int32_t>(alu_out));
3146       break;
3147     case LDC1:
3148       set_fpu_register_double(ft_reg, fp_out);
3149       break;
3150     case SWC1:
3151       addr = rs + se_imm16;
3152       WriteW(addr, get_fpu_register(ft_reg), instr);
3153       break;
3154     case SDC1:
3155       addr = rs + se_imm16;
3156       WriteD(addr, get_fpu_register_double(ft_reg), instr);
3157       break;
3158     default:
3159       break;
3160   }
3161 
3162 
3163   if (execute_branch_delay_instruction) {
3164     // Execute branch delay slot
3165     // We don't check for end_sim_pc. First it should not be met as the current
3166     // pc is valid. Secondly a jump should always execute its branch delay slot.
3167     Instruction* branch_delay_instr =
3168       reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
3169     BranchDelayInstructionDecode(branch_delay_instr);
3170   }
3171 
3172   // If needed update pc after the branch delay execution.
3173   if (next_pc != bad_ra) {
3174     set_pc(next_pc);
3175   }
3176 }
3177 
3178 
3179 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
DecodeTypeJump(Instruction * instr)3180 void Simulator::DecodeTypeJump(Instruction* instr) {
3181   // Get current pc.
3182   int32_t current_pc = get_pc();
3183   // Get unchanged bits of pc.
3184   int32_t pc_high_bits = current_pc & 0xf0000000;
3185   // Next pc.
3186   int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
3187 
3188   // Execute branch delay slot.
3189   // We don't check for end_sim_pc. First it should not be met as the current pc
3190   // is valid. Secondly a jump should always execute its branch delay slot.
3191   Instruction* branch_delay_instr =
3192       reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
3193   BranchDelayInstructionDecode(branch_delay_instr);
3194 
3195   // Update pc and ra if necessary.
3196   // Do this after the branch delay execution.
3197   if (instr->IsLinkingInstruction()) {
3198     set_register(31, current_pc + 2 * Instruction::kInstrSize);
3199   }
3200   set_pc(next_pc);
3201   pc_modified_ = true;
3202 }
3203 
3204 
3205 // Executes the current instruction.
InstructionDecode(Instruction * instr)3206 void Simulator::InstructionDecode(Instruction* instr) {
3207   if (v8::internal::FLAG_check_icache) {
3208     CheckICache(isolate_->simulator_i_cache(), instr);
3209   }
3210   pc_modified_ = false;
3211 
3212   v8::internal::EmbeddedVector<char, 256> buffer;
3213 
3214   if (::v8::internal::FLAG_trace_sim) {
3215     SNPrintF(trace_buf_, " ");
3216     disasm::NameConverter converter;
3217     disasm::Disassembler dasm(converter);
3218     // Use a reasonably large buffer.
3219     dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
3220   }
3221 
3222   switch (instr->InstructionType()) {
3223     case Instruction::kRegisterType:
3224       DecodeTypeRegister(instr);
3225       break;
3226     case Instruction::kImmediateType:
3227       DecodeTypeImmediate(instr);
3228       break;
3229     case Instruction::kJumpType:
3230       DecodeTypeJump(instr);
3231       break;
3232     default:
3233       UNSUPPORTED();
3234   }
3235 
3236   if (::v8::internal::FLAG_trace_sim) {
3237     PrintF("  0x%08lx  %-44s   %s\n", reinterpret_cast<intptr_t>(instr),
3238         buffer.start(), trace_buf_.start());
3239   }
3240 
3241   if (!pc_modified_) {
3242     set_register(pc, reinterpret_cast<int64_t>(instr) +
3243                  Instruction::kInstrSize);
3244   }
3245 }
3246 
3247 
3248 
Execute()3249 void Simulator::Execute() {
3250   // Get the PC to simulate. Cannot use the accessor here as we need the
3251   // raw PC value and not the one used as input to arithmetic instructions.
3252   int64_t program_counter = get_pc();
3253   if (::v8::internal::FLAG_stop_sim_at == 0) {
3254     // Fast version of the dispatch loop without checking whether the simulator
3255     // should be stopping at a particular executed instruction.
3256     while (program_counter != end_sim_pc) {
3257       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3258       icount_++;
3259       InstructionDecode(instr);
3260       program_counter = get_pc();
3261     }
3262   } else {
3263     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3264     // we reach the particular instuction count.
3265     while (program_counter != end_sim_pc) {
3266       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3267       icount_++;
3268       if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) {
3269         MipsDebugger dbg(this);
3270         dbg.Debug();
3271       } else {
3272         InstructionDecode(instr);
3273       }
3274       program_counter = get_pc();
3275     }
3276   }
3277 }
3278 
3279 
CallInternal(byte * entry)3280 void Simulator::CallInternal(byte* entry) {
3281   // Prepare to execute the code at entry.
3282   set_register(pc, reinterpret_cast<int64_t>(entry));
3283   // Put down marker for end of simulation. The simulator will stop simulation
3284   // when the PC reaches this value. By saving the "end simulation" value into
3285   // the LR the simulation stops when returning to this call point.
3286   set_register(ra, end_sim_pc);
3287 
3288   // Remember the values of callee-saved registers.
3289   // The code below assumes that r9 is not used as sb (static base) in
3290   // simulator code and therefore is regarded as a callee-saved register.
3291   int64_t s0_val = get_register(s0);
3292   int64_t s1_val = get_register(s1);
3293   int64_t s2_val = get_register(s2);
3294   int64_t s3_val = get_register(s3);
3295   int64_t s4_val = get_register(s4);
3296   int64_t s5_val = get_register(s5);
3297   int64_t s6_val = get_register(s6);
3298   int64_t s7_val = get_register(s7);
3299   int64_t gp_val = get_register(gp);
3300   int64_t sp_val = get_register(sp);
3301   int64_t fp_val = get_register(fp);
3302 
3303   // Set up the callee-saved registers with a known value. To be able to check
3304   // that they are preserved properly across JS execution.
3305   int64_t callee_saved_value = icount_;
3306   set_register(s0, callee_saved_value);
3307   set_register(s1, callee_saved_value);
3308   set_register(s2, callee_saved_value);
3309   set_register(s3, callee_saved_value);
3310   set_register(s4, callee_saved_value);
3311   set_register(s5, callee_saved_value);
3312   set_register(s6, callee_saved_value);
3313   set_register(s7, callee_saved_value);
3314   set_register(gp, callee_saved_value);
3315   set_register(fp, callee_saved_value);
3316 
3317   // Start the simulation.
3318   Execute();
3319 
3320   // Check that the callee-saved registers have been preserved.
3321   CHECK_EQ(callee_saved_value, get_register(s0));
3322   CHECK_EQ(callee_saved_value, get_register(s1));
3323   CHECK_EQ(callee_saved_value, get_register(s2));
3324   CHECK_EQ(callee_saved_value, get_register(s3));
3325   CHECK_EQ(callee_saved_value, get_register(s4));
3326   CHECK_EQ(callee_saved_value, get_register(s5));
3327   CHECK_EQ(callee_saved_value, get_register(s6));
3328   CHECK_EQ(callee_saved_value, get_register(s7));
3329   CHECK_EQ(callee_saved_value, get_register(gp));
3330   CHECK_EQ(callee_saved_value, get_register(fp));
3331 
3332   // Restore callee-saved registers with the original value.
3333   set_register(s0, s0_val);
3334   set_register(s1, s1_val);
3335   set_register(s2, s2_val);
3336   set_register(s3, s3_val);
3337   set_register(s4, s4_val);
3338   set_register(s5, s5_val);
3339   set_register(s6, s6_val);
3340   set_register(s7, s7_val);
3341   set_register(gp, gp_val);
3342   set_register(sp, sp_val);
3343   set_register(fp, fp_val);
3344 }
3345 
3346 
Call(byte * entry,int argument_count,...)3347 int64_t Simulator::Call(byte* entry, int argument_count, ...) {
3348   const int kRegisterPassedArguments = (kMipsAbi == kN64) ? 8 : 4;
3349   va_list parameters;
3350   va_start(parameters, argument_count);
3351   // Set up arguments.
3352 
3353   // First four arguments passed in registers in both ABI's.
3354   DCHECK(argument_count >= 4);
3355   set_register(a0, va_arg(parameters, int64_t));
3356   set_register(a1, va_arg(parameters, int64_t));
3357   set_register(a2, va_arg(parameters, int64_t));
3358   set_register(a3, va_arg(parameters, int64_t));
3359 
3360   if (kMipsAbi == kN64) {
3361     // Up to eight arguments passed in registers in N64 ABI.
3362     // TODO(plind): N64 ABI calls these regs a4 - a7. Clarify this.
3363     if (argument_count >= 5) set_register(a4, va_arg(parameters, int64_t));
3364     if (argument_count >= 6) set_register(a5, va_arg(parameters, int64_t));
3365     if (argument_count >= 7) set_register(a6, va_arg(parameters, int64_t));
3366     if (argument_count >= 8) set_register(a7, va_arg(parameters, int64_t));
3367   }
3368 
3369   // Remaining arguments passed on stack.
3370   int64_t original_stack = get_register(sp);
3371   // Compute position of stack on entry to generated code.
3372   int stack_args_count = (argument_count > kRegisterPassedArguments) ?
3373                          (argument_count - kRegisterPassedArguments) : 0;
3374   int stack_args_size = stack_args_count * sizeof(int64_t) + kCArgsSlotsSize;
3375   int64_t entry_stack = original_stack - stack_args_size;
3376 
3377   if (base::OS::ActivationFrameAlignment() != 0) {
3378     entry_stack &= -base::OS::ActivationFrameAlignment();
3379   }
3380   // Store remaining arguments on stack, from low to high memory.
3381   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3382   for (int i = kRegisterPassedArguments; i < argument_count; i++) {
3383     int stack_index = i - kRegisterPassedArguments + kCArgSlotCount;
3384     stack_argument[stack_index] = va_arg(parameters, int64_t);
3385   }
3386   va_end(parameters);
3387   set_register(sp, entry_stack);
3388 
3389   CallInternal(entry);
3390 
3391   // Pop stack passed arguments.
3392   CHECK_EQ(entry_stack, get_register(sp));
3393   set_register(sp, original_stack);
3394 
3395   int64_t result = get_register(v0);
3396   return result;
3397 }
3398 
3399 
CallFP(byte * entry,double d0,double d1)3400 double Simulator::CallFP(byte* entry, double d0, double d1) {
3401   if (!IsMipsSoftFloatABI) {
3402     const FPURegister fparg2 = (kMipsAbi == kN64) ? f13 : f14;
3403     set_fpu_register_double(f12, d0);
3404     set_fpu_register_double(fparg2, d1);
3405   } else {
3406     int buffer[2];
3407     DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0));
3408     memcpy(buffer, &d0, sizeof(d0));
3409     set_dw_register(a0, buffer);
3410     memcpy(buffer, &d1, sizeof(d1));
3411     set_dw_register(a2, buffer);
3412   }
3413   CallInternal(entry);
3414   if (!IsMipsSoftFloatABI) {
3415     return get_fpu_register_double(f0);
3416   } else {
3417     return get_double_from_register_pair(v0);
3418   }
3419 }
3420 
3421 
PushAddress(uintptr_t address)3422 uintptr_t Simulator::PushAddress(uintptr_t address) {
3423   int64_t new_sp = get_register(sp) - sizeof(uintptr_t);
3424   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3425   *stack_slot = address;
3426   set_register(sp, new_sp);
3427   return new_sp;
3428 }
3429 
3430 
PopAddress()3431 uintptr_t Simulator::PopAddress() {
3432   int64_t current_sp = get_register(sp);
3433   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3434   uintptr_t address = *stack_slot;
3435   set_register(sp, current_sp + sizeof(uintptr_t));
3436   return address;
3437 }
3438 
3439 
3440 #undef UNSUPPORTED
3441 
3442 } }  // namespace v8::internal
3443 
3444 #endif  // USE_SIMULATOR
3445 
3446 #endif  // V8_TARGET_ARCH_MIPS64
3447