• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdlib.h>
29 #include <math.h>
30 #include <limits.h>
31 #include <cstdarg>
32 #include "v8.h"
33 
34 #if defined(V8_TARGET_ARCH_MIPS)
35 
36 #include "disasm.h"
37 #include "assembler.h"
38 #include "globals.h"    // Need the BitCast
39 #include "mips/constants-mips.h"
40 #include "mips/simulator-mips.h"
41 
42 
43 // Only build the simulator if not compiling for real MIPS hardware.
44 #if defined(USE_SIMULATOR)
45 
46 namespace v8 {
47 namespace internal {
48 
49 // Utils functions
HaveSameSign(int32_t a,int32_t b)50 bool HaveSameSign(int32_t a, int32_t b) {
51   return ((a ^ b) >= 0);
52 }
53 
54 
get_fcsr_condition_bit(uint32_t cc)55 uint32_t get_fcsr_condition_bit(uint32_t cc) {
56   if (cc == 0) {
57     return 23;
58   } else {
59     return 24 + cc;
60   }
61 }
62 
63 
64 // This macro provides a platform independent use of sscanf. The reason for
65 // SScanF not being implemented in a platform independent was through
66 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
67 // Library does not provide vsscanf.
68 #define SScanF sscanf  // NOLINT
69 
70 // The MipsDebugger class is used by the simulator while debugging simulated
71 // code.
72 class MipsDebugger {
73  public:
74   explicit MipsDebugger(Simulator* sim);
75   ~MipsDebugger();
76 
77   void Stop(Instruction* instr);
78   void Debug();
79   // Print all registers with a nice formatting.
80   void PrintAllRegs();
81   void PrintAllRegsIncludingFPU();
82 
83  private:
84   // We set the breakpoint code to 0xfffff to easily recognize it.
85   static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
86   static const Instr kNopInstr =  0x0;
87 
88   Simulator* sim_;
89 
90   int32_t GetRegisterValue(int regnum);
91   int32_t GetFPURegisterValueInt(int regnum);
92   int64_t GetFPURegisterValueLong(int regnum);
93   float GetFPURegisterValueFloat(int regnum);
94   double GetFPURegisterValueDouble(int regnum);
95   bool GetValue(const char* desc, int32_t* value);
96 
97   // Set or delete a breakpoint. Returns true if successful.
98   bool SetBreakpoint(Instruction* breakpc);
99   bool DeleteBreakpoint(Instruction* breakpc);
100 
101   // Undo and redo all breakpoints. This is needed to bracket disassembly and
102   // execution to skip past breakpoints when run from the debugger.
103   void UndoBreakpoints();
104   void RedoBreakpoints();
105 };
106 
MipsDebugger(Simulator * sim)107 MipsDebugger::MipsDebugger(Simulator* sim) {
108   sim_ = sim;
109 }
110 
111 
~MipsDebugger()112 MipsDebugger::~MipsDebugger() {
113 }
114 
115 
116 #ifdef GENERATED_CODE_COVERAGE
117 static FILE* coverage_log = NULL;
118 
119 
InitializeCoverage()120 static void InitializeCoverage() {
121   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
122   if (file_name != NULL) {
123     coverage_log = fopen(file_name, "aw+");
124   }
125 }
126 
127 
Stop(Instruction * instr)128 void MipsDebugger::Stop(Instruction* instr) {
129   UNIMPLEMENTED_MIPS();
130   char* str = reinterpret_cast<char*>(instr->InstructionBits());
131   if (strlen(str) > 0) {
132     if (coverage_log != NULL) {
133       fprintf(coverage_log, "%s\n", str);
134       fflush(coverage_log);
135     }
136     instr->SetInstructionBits(0x0);  // Overwrite with nop.
137   }
138   sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
139 }
140 
141 
142 #else  // ndef GENERATED_CODE_COVERAGE
143 
144 #define UNSUPPORTED() printf("Unsupported instruction.\n");
145 
InitializeCoverage()146 static void InitializeCoverage() {}
147 
148 
Stop(Instruction * instr)149 void MipsDebugger::Stop(Instruction* instr) {
150   const char* str = reinterpret_cast<char*>(instr->InstructionBits());
151   PrintF("Simulator hit %s\n", str);
152   sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
153   Debug();
154 }
155 #endif  // GENERATED_CODE_COVERAGE
156 
157 
GetRegisterValue(int regnum)158 int32_t MipsDebugger::GetRegisterValue(int regnum) {
159   if (regnum == kNumSimuRegisters) {
160     return sim_->get_pc();
161   } else {
162     return sim_->get_register(regnum);
163   }
164 }
165 
166 
GetFPURegisterValueInt(int regnum)167 int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
168   if (regnum == kNumFPURegisters) {
169     return sim_->get_pc();
170   } else {
171     return sim_->get_fpu_register(regnum);
172   }
173 }
174 
175 
GetFPURegisterValueLong(int regnum)176 int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
177   if (regnum == kNumFPURegisters) {
178     return sim_->get_pc();
179   } else {
180     return sim_->get_fpu_register_long(regnum);
181   }
182 }
183 
184 
GetFPURegisterValueFloat(int regnum)185 float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
186   if (regnum == kNumFPURegisters) {
187     return sim_->get_pc();
188   } else {
189     return sim_->get_fpu_register_float(regnum);
190   }
191 }
192 
193 
GetFPURegisterValueDouble(int regnum)194 double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
195   if (regnum == kNumFPURegisters) {
196     return sim_->get_pc();
197   } else {
198     return sim_->get_fpu_register_double(regnum);
199   }
200 }
201 
202 
GetValue(const char * desc,int32_t * value)203 bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
204   int regnum = Registers::Number(desc);
205   int fpuregnum = FPURegisters::Number(desc);
206 
207   if (regnum != kInvalidRegister) {
208     *value = GetRegisterValue(regnum);
209     return true;
210   } else if (fpuregnum != kInvalidFPURegister) {
211     *value = GetFPURegisterValueInt(fpuregnum);
212     return true;
213   } else if (strncmp(desc, "0x", 2) == 0) {
214     return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
215   } else {
216     return SScanF(desc, "%i", value) == 1;
217   }
218   return false;
219 }
220 
221 
SetBreakpoint(Instruction * breakpc)222 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
223   // Check if a breakpoint can be set. If not return without any side-effects.
224   if (sim_->break_pc_ != NULL) {
225     return false;
226   }
227 
228   // Set the breakpoint.
229   sim_->break_pc_ = breakpc;
230   sim_->break_instr_ = breakpc->InstructionBits();
231   // Not setting the breakpoint instruction in the code itself. It will be set
232   // when the debugger shell continues.
233   return true;
234 }
235 
236 
DeleteBreakpoint(Instruction * breakpc)237 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
238   if (sim_->break_pc_ != NULL) {
239     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
240   }
241 
242   sim_->break_pc_ = NULL;
243   sim_->break_instr_ = 0;
244   return true;
245 }
246 
247 
UndoBreakpoints()248 void MipsDebugger::UndoBreakpoints() {
249   if (sim_->break_pc_ != NULL) {
250     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
251   }
252 }
253 
254 
RedoBreakpoints()255 void MipsDebugger::RedoBreakpoints() {
256   if (sim_->break_pc_ != NULL) {
257     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
258   }
259 }
260 
261 
PrintAllRegs()262 void MipsDebugger::PrintAllRegs() {
263 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
264 
265   PrintF("\n");
266   // at, v0, a0
267   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
268          REG_INFO(1), REG_INFO(2), REG_INFO(4));
269   // v1, a1
270   PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
271          "", REG_INFO(3), REG_INFO(5));
272   // a2
273   PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
274   // a3
275   PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
276   PrintF("\n");
277   // t0-t7, s0-s7
278   for (int i = 0; i < 8; i++) {
279     PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
280            REG_INFO(8+i), REG_INFO(16+i));
281   }
282   PrintF("\n");
283   // t8, k0, LO
284   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
285          REG_INFO(24), REG_INFO(26), REG_INFO(32));
286   // t9, k1, HI
287   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
288          REG_INFO(25), REG_INFO(27), REG_INFO(33));
289   // sp, fp, gp
290   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
291          REG_INFO(29), REG_INFO(30), REG_INFO(28));
292   // pc
293   PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
294          REG_INFO(31), REG_INFO(34));
295 
296 #undef REG_INFO
297 #undef FPU_REG_INFO
298 }
299 
300 
PrintAllRegsIncludingFPU()301 void MipsDebugger::PrintAllRegsIncludingFPU() {
302 #define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
303         GetFPURegisterValueInt(n+1), \
304         GetFPURegisterValueInt(n), \
305                         GetFPURegisterValueDouble(n)
306 
307   PrintAllRegs();
308 
309   PrintF("\n\n");
310   // f0, f1, f2, ... f31
311   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
312   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
313   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
314   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
315   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
316   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
317   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
318   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
319   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
320   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
321   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
322   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
323   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
324   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
325   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
326   PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
327 
328 #undef REG_INFO
329 #undef FPU_REG_INFO
330 }
331 
332 
Debug()333 void MipsDebugger::Debug() {
334   intptr_t last_pc = -1;
335   bool done = false;
336 
337 #define COMMAND_SIZE 63
338 #define ARG_SIZE 255
339 
340 #define STR(a) #a
341 #define XSTR(a) STR(a)
342 
343   char cmd[COMMAND_SIZE + 1];
344   char arg1[ARG_SIZE + 1];
345   char arg2[ARG_SIZE + 1];
346   char* argv[3] = { cmd, arg1, arg2 };
347 
348   // make sure to have a proper terminating character if reaching the limit
349   cmd[COMMAND_SIZE] = 0;
350   arg1[ARG_SIZE] = 0;
351   arg2[ARG_SIZE] = 0;
352 
353   // Undo all set breakpoints while running in the debugger shell. This will
354   // make them invisible to all commands.
355   UndoBreakpoints();
356 
357   while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
358     if (last_pc != sim_->get_pc()) {
359       disasm::NameConverter converter;
360       disasm::Disassembler dasm(converter);
361       // use a reasonably large buffer
362       v8::internal::EmbeddedVector<char, 256> buffer;
363       dasm.InstructionDecode(buffer,
364                              reinterpret_cast<byte_*>(sim_->get_pc()));
365       PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
366       last_pc = sim_->get_pc();
367     }
368     char* line = ReadLine("sim> ");
369     if (line == NULL) {
370       break;
371     } else {
372       // Use sscanf to parse the individual parts of the command line. At the
373       // moment no command expects more than two parameters.
374       int argc = SScanF(line,
375                         "%" XSTR(COMMAND_SIZE) "s "
376                         "%" XSTR(ARG_SIZE) "s "
377                         "%" XSTR(ARG_SIZE) "s",
378                         cmd, arg1, arg2);
379       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
380         Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
381         if (!(instr->IsTrap()) ||
382             instr->InstructionBits() == rtCallRedirInstr) {
383           sim_->InstructionDecode(
384               reinterpret_cast<Instruction*>(sim_->get_pc()));
385         } else {
386           // Allow si to jump over generated breakpoints.
387           PrintF("/!\\ Jumping over generated breakpoint.\n");
388           sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
389         }
390       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
391         // Execute the one instruction we broke at with breakpoints disabled.
392         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
393         // Leave the debugger shell.
394         done = true;
395       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
396         if (argc == 2) {
397           int32_t value;
398           float fvalue;
399           if (strcmp(arg1, "all") == 0) {
400             PrintAllRegs();
401           } else if (strcmp(arg1, "allf") == 0) {
402             PrintAllRegsIncludingFPU();
403           } else {
404             int regnum = Registers::Number(arg1);
405             int fpuregnum = FPURegisters::Number(arg1);
406 
407             if (regnum != kInvalidRegister) {
408               value = GetRegisterValue(regnum);
409               PrintF("%s: 0x%08x %d \n", arg1, value, value);
410             } else if (fpuregnum != kInvalidFPURegister) {
411               if (fpuregnum % 2 == 1) {
412                 value = GetFPURegisterValueInt(fpuregnum);
413                 fvalue = GetFPURegisterValueFloat(fpuregnum);
414                 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
415               } else {
416                 double dfvalue;
417                 int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
418                 int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
419                 dfvalue = GetFPURegisterValueDouble(fpuregnum);
420                 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
421                        FPURegisters::Name(fpuregnum+1),
422                        FPURegisters::Name(fpuregnum),
423                        lvalue1,
424                        lvalue2,
425                        dfvalue);
426               }
427             } else {
428               PrintF("%s unrecognized\n", arg1);
429             }
430           }
431         } else {
432           if (argc == 3) {
433             if (strcmp(arg2, "single") == 0) {
434               int32_t value;
435               float fvalue;
436               int fpuregnum = FPURegisters::Number(arg1);
437 
438               if (fpuregnum != kInvalidFPURegister) {
439                 value = GetFPURegisterValueInt(fpuregnum);
440                 fvalue = GetFPURegisterValueFloat(fpuregnum);
441                 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
442               } else {
443                 PrintF("%s unrecognized\n", arg1);
444               }
445             } else {
446               PrintF("print <fpu register> single\n");
447             }
448           } else {
449             PrintF("print <register> or print <fpu register> single\n");
450           }
451         }
452       } else if ((strcmp(cmd, "po") == 0)
453                  || (strcmp(cmd, "printobject") == 0)) {
454         if (argc == 2) {
455           int32_t value;
456           if (GetValue(arg1, &value)) {
457             Object* obj = reinterpret_cast<Object*>(value);
458             PrintF("%s: \n", arg1);
459 #ifdef DEBUG
460             obj->PrintLn();
461 #else
462             obj->ShortPrint();
463             PrintF("\n");
464 #endif
465           } else {
466             PrintF("%s unrecognized\n", arg1);
467           }
468         } else {
469           PrintF("printobject <value>\n");
470         }
471       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
472         int32_t* cur = NULL;
473         int32_t* end = NULL;
474         int next_arg = 1;
475 
476         if (strcmp(cmd, "stack") == 0) {
477           cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
478         } else {  // "mem"
479           int32_t value;
480           if (!GetValue(arg1, &value)) {
481             PrintF("%s unrecognized\n", arg1);
482             continue;
483           }
484           cur = reinterpret_cast<int32_t*>(value);
485           next_arg++;
486         }
487 
488         int32_t words;
489         if (argc == next_arg) {
490           words = 10;
491         } else if (argc == next_arg + 1) {
492           if (!GetValue(argv[next_arg], &words)) {
493             words = 10;
494           }
495         }
496         end = cur + words;
497 
498         while (cur < end) {
499           PrintF("  0x%08x:  0x%08x %10d\n",
500                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
501           cur++;
502         }
503 
504       } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) {
505         disasm::NameConverter converter;
506         disasm::Disassembler dasm(converter);
507         // use a reasonably large buffer
508         v8::internal::EmbeddedVector<char, 256> buffer;
509 
510         byte_* cur = NULL;
511         byte_* end = NULL;
512 
513         if (argc == 1) {
514           cur = reinterpret_cast<byte_*>(sim_->get_pc());
515           end = cur + (10 * Instruction::kInstrSize);
516         } else if (argc == 2) {
517           int32_t value;
518           if (GetValue(arg1, &value)) {
519             cur = reinterpret_cast<byte_*>(value);
520             // no length parameter passed, assume 10 instructions
521             end = cur + (10 * Instruction::kInstrSize);
522           }
523         } else {
524           int32_t value1;
525           int32_t value2;
526           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
527             cur = reinterpret_cast<byte_*>(value1);
528             end = cur + (value2 * Instruction::kInstrSize);
529           }
530         }
531 
532         while (cur < end) {
533           dasm.InstructionDecode(buffer, cur);
534           PrintF("  0x%08x  %s\n",
535               reinterpret_cast<intptr_t>(cur), buffer.start());
536           cur += Instruction::kInstrSize;
537         }
538       } else if (strcmp(cmd, "gdb") == 0) {
539         PrintF("relinquishing control to gdb\n");
540         v8::internal::OS::DebugBreak();
541         PrintF("regaining control from gdb\n");
542       } else if (strcmp(cmd, "break") == 0) {
543         if (argc == 2) {
544           int32_t value;
545           if (GetValue(arg1, &value)) {
546             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
547               PrintF("setting breakpoint failed\n");
548             }
549           } else {
550             PrintF("%s unrecognized\n", arg1);
551           }
552         } else {
553           PrintF("break <address>\n");
554         }
555       } else if (strcmp(cmd, "del") == 0) {
556         if (!DeleteBreakpoint(NULL)) {
557           PrintF("deleting breakpoint failed\n");
558         }
559       } else if (strcmp(cmd, "flags") == 0) {
560         PrintF("No flags on MIPS !\n");
561       } else if (strcmp(cmd, "unstop") == 0) {
562           PrintF("Unstop command not implemented on MIPS.");
563       } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
564         // Print registers and disassemble
565         PrintAllRegs();
566         PrintF("\n");
567 
568         disasm::NameConverter converter;
569         disasm::Disassembler dasm(converter);
570         // use a reasonably large buffer
571         v8::internal::EmbeddedVector<char, 256> buffer;
572 
573         byte_* cur = NULL;
574         byte_* end = NULL;
575 
576         if (argc == 1) {
577           cur = reinterpret_cast<byte_*>(sim_->get_pc());
578           end = cur + (10 * Instruction::kInstrSize);
579         } else if (argc == 2) {
580           int32_t value;
581           if (GetValue(arg1, &value)) {
582             cur = reinterpret_cast<byte_*>(value);
583             // no length parameter passed, assume 10 instructions
584             end = cur + (10 * Instruction::kInstrSize);
585           }
586         } else {
587           int32_t value1;
588           int32_t value2;
589           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
590             cur = reinterpret_cast<byte_*>(value1);
591             end = cur + (value2 * Instruction::kInstrSize);
592           }
593         }
594 
595         while (cur < end) {
596           dasm.InstructionDecode(buffer, cur);
597           PrintF("  0x%08x  %s\n",
598                  reinterpret_cast<intptr_t>(cur), buffer.start());
599           cur += Instruction::kInstrSize;
600         }
601       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
602         PrintF("cont\n");
603         PrintF("  continue execution (alias 'c')\n");
604         PrintF("stepi\n");
605         PrintF("  step one instruction (alias 'si')\n");
606         PrintF("print <register>\n");
607         PrintF("  print register content (alias 'p')\n");
608         PrintF("  use register name 'all' to print all registers\n");
609         PrintF("printobject <register>\n");
610         PrintF("  print an object from a register (alias 'po')\n");
611         PrintF("stack [<words>]\n");
612         PrintF("  dump stack content, default dump 10 words)\n");
613         PrintF("mem <address> [<words>]\n");
614         PrintF("  dump memory content, default dump 10 words)\n");
615         PrintF("flags\n");
616         PrintF("  print flags\n");
617         PrintF("disasm [<instructions>]\n");
618         PrintF("disasm [[<address>] <instructions>]\n");
619         PrintF("  disassemble code, default is 10 instructions from pc\n");
620         PrintF("gdb\n");
621         PrintF("  enter gdb\n");
622         PrintF("break <address>\n");
623         PrintF("  set a break point on the address\n");
624         PrintF("del\n");
625         PrintF("  delete the breakpoint\n");
626         PrintF("unstop\n");
627         PrintF("  ignore the stop instruction at the current location");
628         PrintF(" from now on\n");
629       } else {
630         PrintF("Unknown command: %s\n", cmd);
631       }
632     }
633     DeleteArray(line);
634   }
635 
636   // Add all the breakpoints back to stop execution and enter the debugger
637   // shell when hit.
638   RedoBreakpoints();
639 
640 #undef COMMAND_SIZE
641 #undef ARG_SIZE
642 
643 #undef STR
644 #undef XSTR
645 }
646 
647 
ICacheMatch(void * one,void * two)648 static bool ICacheMatch(void* one, void* two) {
649   ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
650   ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
651   return one == two;
652 }
653 
654 
ICacheHash(void * key)655 static uint32_t ICacheHash(void* key) {
656   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
657 }
658 
659 
AllOnOnePage(uintptr_t start,int size)660 static bool AllOnOnePage(uintptr_t start, int size) {
661   intptr_t start_page = (start & ~CachePage::kPageMask);
662   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
663   return start_page == end_page;
664 }
665 
666 
FlushICache(v8::internal::HashMap * i_cache,void * start_addr,size_t size)667 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
668                             void* start_addr,
669                             size_t size) {
670   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
671   int intra_line = (start & CachePage::kLineMask);
672   start -= intra_line;
673   size += intra_line;
674   size = ((size - 1) | CachePage::kLineMask) + 1;
675   int offset = (start & CachePage::kPageMask);
676   while (!AllOnOnePage(start, size - 1)) {
677     int bytes_to_flush = CachePage::kPageSize - offset;
678     FlushOnePage(i_cache, start, bytes_to_flush);
679     start += bytes_to_flush;
680     size -= bytes_to_flush;
681     ASSERT_EQ(0, start & CachePage::kPageMask);
682     offset = 0;
683   }
684   if (size != 0) {
685     FlushOnePage(i_cache, start, size);
686   }
687 }
688 
689 
GetCachePage(v8::internal::HashMap * i_cache,void * page)690 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
691   v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
692                                                          ICacheHash(page),
693                                                          true);
694   if (entry->value == NULL) {
695     CachePage* new_page = new CachePage();
696     entry->value = new_page;
697   }
698   return reinterpret_cast<CachePage*>(entry->value);
699 }
700 
701 
702 // Flush from start up to and not including start + size.
FlushOnePage(v8::internal::HashMap * i_cache,intptr_t start,int size)703 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
704                              intptr_t start,
705                              int size) {
706   ASSERT(size <= CachePage::kPageSize);
707   ASSERT(AllOnOnePage(start, size - 1));
708   ASSERT((start & CachePage::kLineMask) == 0);
709   ASSERT((size & CachePage::kLineMask) == 0);
710   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
711   int offset = (start & CachePage::kPageMask);
712   CachePage* cache_page = GetCachePage(i_cache, page);
713   char* valid_bytemap = cache_page->ValidityByte(offset);
714   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
715 }
716 
717 
CheckICache(v8::internal::HashMap * i_cache,Instruction * instr)718 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
719                             Instruction* instr) {
720   intptr_t address = reinterpret_cast<intptr_t>(instr);
721   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
722   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
723   int offset = (address & CachePage::kPageMask);
724   CachePage* cache_page = GetCachePage(i_cache, page);
725   char* cache_valid_byte = cache_page->ValidityByte(offset);
726   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
727   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
728   if (cache_hit) {
729     // Check that the data in memory matches the contents of the I-cache.
730     CHECK(memcmp(reinterpret_cast<void*>(instr),
731                  cache_page->CachedData(offset),
732                  Instruction::kInstrSize) == 0);
733   } else {
734     // Cache miss.  Load memory into the cache.
735     memcpy(cached_line, line, CachePage::kLineLength);
736     *cache_valid_byte = CachePage::LINE_VALID;
737   }
738 }
739 
740 
Initialize()741 void Simulator::Initialize() {
742   if (Isolate::Current()->simulator_initialized()) return;
743   Isolate::Current()->set_simulator_initialized(true);
744   ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
745 }
746 
747 
Simulator()748 Simulator::Simulator() : isolate_(Isolate::Current()) {
749   i_cache_ = isolate_->simulator_i_cache();
750   if (i_cache_ == NULL) {
751     i_cache_ = new v8::internal::HashMap(&ICacheMatch);
752     isolate_->set_simulator_i_cache(i_cache_);
753   }
754   Initialize();
755   // Setup simulator support first. Some of this information is needed to
756   // setup the architecture state.
757   stack_size_ = 1 * 1024*1024;  // allocate 1MB for stack
758   stack_ = reinterpret_cast<char*>(malloc(stack_size_));
759   pc_modified_ = false;
760   icount_ = 0;
761   break_count_ = 0;
762   break_pc_ = NULL;
763   break_instr_ = 0;
764 
765   // Setup architecture state.
766   // All registers are initialized to zero to start with.
767   for (int i = 0; i < kNumSimuRegisters; i++) {
768     registers_[i] = 0;
769   }
770   for (int i = 0; i < kNumFPURegisters; i++) {
771     FPUregisters_[i] = 0;
772   }
773   FCSR_ = 0;
774 
775   // The sp is initialized to point to the bottom (high address) of the
776   // allocated stack area. To be safe in potential stack underflows we leave
777   // some buffer below.
778   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
779   // The ra and pc are initialized to a known bad value that will cause an
780   // access violation if the simulator ever tries to execute it.
781   registers_[pc] = bad_ra;
782   registers_[ra] = bad_ra;
783   InitializeCoverage();
784   for (int i = 0; i < kNumExceptions; i++) {
785     exceptions[i] = 0;
786   }
787 }
788 
789 
790 // When the generated code calls an external reference we need to catch that in
791 // the simulator.  The external reference will be a function compiled for the
792 // host architecture.  We need to call that function instead of trying to
793 // execute it with the simulator.  We do that by redirecting the external
794 // reference to a swi (software-interrupt) instruction that is handled by
795 // the simulator.  We write the original destination of the jump just at a known
796 // offset from the swi instruction so the simulator knows what to call.
797 class Redirection {
798  public:
Redirection(void * external_function,ExternalReference::Type type)799   Redirection(void* external_function, ExternalReference::Type type)
800       : external_function_(external_function),
801         swi_instruction_(rtCallRedirInstr),
802         type_(type),
803         next_(NULL) {
804     Isolate* isolate = Isolate::Current();
805     next_ = isolate->simulator_redirection();
806     Simulator::current(isolate)->
807         FlushICache(isolate->simulator_i_cache(),
808                     reinterpret_cast<void*>(&swi_instruction_),
809                     Instruction::kInstrSize);
810     isolate->set_simulator_redirection(this);
811   }
812 
address_of_swi_instruction()813   void* address_of_swi_instruction() {
814     return reinterpret_cast<void*>(&swi_instruction_);
815   }
816 
external_function()817   void* external_function() { return external_function_; }
type()818   ExternalReference::Type type() { return type_; }
819 
Get(void * external_function,ExternalReference::Type type)820   static Redirection* Get(void* external_function,
821                           ExternalReference::Type type) {
822     Isolate* isolate = Isolate::Current();
823     Redirection* current = isolate->simulator_redirection();
824     for (; current != NULL; current = current->next_) {
825       if (current->external_function_ == external_function) return current;
826     }
827     return new Redirection(external_function, type);
828   }
829 
FromSwiInstruction(Instruction * swi_instruction)830   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
831     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
832     char* addr_of_redirection =
833         addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
834     return reinterpret_cast<Redirection*>(addr_of_redirection);
835   }
836 
837  private:
838   void* external_function_;
839   uint32_t swi_instruction_;
840   ExternalReference::Type type_;
841   Redirection* next_;
842 };
843 
844 
RedirectExternalReference(void * external_function,ExternalReference::Type type)845 void* Simulator::RedirectExternalReference(void* external_function,
846                                            ExternalReference::Type type) {
847   Redirection* redirection = Redirection::Get(external_function, type);
848   return redirection->address_of_swi_instruction();
849 }
850 
851 
852 // Get the active Simulator for the current thread.
current(Isolate * isolate)853 Simulator* Simulator::current(Isolate* isolate) {
854   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
855       Isolate::CurrentPerIsolateThreadData();
856   if (isolate_data == NULL) {
857     Isolate::EnterDefaultIsolate();
858     isolate_data = Isolate::CurrentPerIsolateThreadData();
859   }
860   ASSERT(isolate_data != NULL);
861 
862   Simulator* sim = isolate_data->simulator();
863   if (sim == NULL) {
864     // TODO(146): delete the simulator object when a thread/isolate goes away.
865     sim = new Simulator();
866     isolate_data->set_simulator(sim);
867   }
868   return sim;
869 }
870 
871 
872 // Sets the register in the architecture state. It will also deal with updating
873 // Simulator internal state for special registers such as PC.
set_register(int reg,int32_t value)874 void Simulator::set_register(int reg, int32_t value) {
875   ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
876   if (reg == pc) {
877     pc_modified_ = true;
878   }
879 
880   // zero register always hold 0.
881   registers_[reg] = (reg == 0) ? 0 : value;
882 }
883 
884 
set_fpu_register(int fpureg,int32_t value)885 void Simulator::set_fpu_register(int fpureg, int32_t value) {
886   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
887   FPUregisters_[fpureg] = value;
888 }
889 
890 
set_fpu_register_float(int fpureg,float value)891 void Simulator::set_fpu_register_float(int fpureg, float value) {
892   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
893   *BitCast<float*>(&FPUregisters_[fpureg]) = value;
894 }
895 
896 
set_fpu_register_double(int fpureg,double value)897 void Simulator::set_fpu_register_double(int fpureg, double value) {
898   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
899   *BitCast<double*>(&FPUregisters_[fpureg]) = value;
900 }
901 
902 
903 // Get the register from the architecture state. This function does handle
904 // the special case of accessing the PC register.
get_register(int reg) const905 int32_t Simulator::get_register(int reg) const {
906   ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
907   if (reg == 0)
908     return 0;
909   else
910     return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
911 }
912 
913 
get_fpu_register(int fpureg) const914 int32_t Simulator::get_fpu_register(int fpureg) const {
915   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
916   return FPUregisters_[fpureg];
917 }
918 
919 
get_fpu_register_long(int fpureg) const920 int64_t Simulator::get_fpu_register_long(int fpureg) const {
921   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
922   return *BitCast<int64_t*>(
923       const_cast<int32_t*>(&FPUregisters_[fpureg]));
924 }
925 
926 
get_fpu_register_float(int fpureg) const927 float Simulator::get_fpu_register_float(int fpureg) const {
928   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
929   return *BitCast<float*>(
930       const_cast<int32_t*>(&FPUregisters_[fpureg]));
931 }
932 
933 
get_fpu_register_double(int fpureg) const934 double Simulator::get_fpu_register_double(int fpureg) const {
935   ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
936   return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
937 }
938 
939 
940 // Helper functions for setting and testing the FCSR register's bits.
set_fcsr_bit(uint32_t cc,bool value)941 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
942   if (value) {
943     FCSR_ |= (1 << cc);
944   } else {
945     FCSR_ &= ~(1 << cc);
946   }
947 }
948 
949 
test_fcsr_bit(uint32_t cc)950 bool Simulator::test_fcsr_bit(uint32_t cc) {
951   return FCSR_ & (1 << cc);
952 }
953 
954 
955 // Sets the rounding error codes in FCSR based on the result of the rounding.
956 // Returns true if the operation was invalid.
set_fcsr_round_error(double original,double rounded)957 bool Simulator::set_fcsr_round_error(double original, double rounded) {
958   if (!isfinite(original) ||
959       rounded > LONG_MAX ||
960       rounded < LONG_MIN) {
961     set_fcsr_bit(6, true);  // Invalid operation.
962     return true;
963   } else if (original != static_cast<double>(rounded)) {
964     set_fcsr_bit(2, true);  // Inexact.
965   }
966   return false;
967 }
968 
969 
970 // Raw access to the PC register.
set_pc(int32_t value)971 void Simulator::set_pc(int32_t value) {
972   pc_modified_ = true;
973   registers_[pc] = value;
974 }
975 
976 
has_bad_pc() const977 bool Simulator::has_bad_pc() const {
978   return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
979 }
980 
981 
982 // Raw access to the PC register without the special adjustment when reading.
get_pc() const983 int32_t Simulator::get_pc() const {
984   return registers_[pc];
985 }
986 
987 
988 // The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
989 // interrupt is caused.  On others it does a funky rotation thing.  For now we
990 // simply disallow unaligned reads, but at some point we may want to move to
991 // emulating the rotate behaviour.  Note that simulator runs have the runtime
992 // system running directly on the host system and only generated code is
993 // executed in the simulator.  Since the host is typically IA32 we will not
994 // get the correct MIPS-like behaviour on unaligned accesses.
995 
ReadW(int32_t addr,Instruction * instr)996 int Simulator::ReadW(int32_t addr, Instruction* instr) {
997   if (addr >=0 && addr < 0x400) {
998     // this has to be a NULL-dereference
999     MipsDebugger dbg(this);
1000     dbg.Debug();
1001   }
1002   if ((addr & kPointerAlignmentMask) == 0) {
1003     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1004     return *ptr;
1005   }
1006   PrintF("Unaligned read at 0x%08x, pc=%p\n", addr,
1007       reinterpret_cast<void*>(instr));
1008   MipsDebugger dbg(this);
1009   dbg.Debug();
1010   return 0;
1011 }
1012 
1013 
WriteW(int32_t addr,int value,Instruction * instr)1014 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1015   if (addr >= 0 && addr < 0x400) {
1016     // this has to be a NULL-dereference
1017     MipsDebugger dbg(this);
1018     dbg.Debug();
1019   }
1020   if ((addr & kPointerAlignmentMask) == 0) {
1021     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1022     *ptr = value;
1023     return;
1024   }
1025   PrintF("Unaligned write at 0x%08x, pc=%p\n", addr,
1026       reinterpret_cast<void*>(instr));
1027   MipsDebugger dbg(this);
1028   dbg.Debug();
1029 }
1030 
1031 
ReadD(int32_t addr,Instruction * instr)1032 double Simulator::ReadD(int32_t addr, Instruction* instr) {
1033   if ((addr & kDoubleAlignmentMask) == 0) {
1034     double* ptr = reinterpret_cast<double*>(addr);
1035     return *ptr;
1036   }
1037   PrintF("Unaligned (double) read at 0x%08x, pc=%p\n", addr,
1038       reinterpret_cast<void*>(instr));
1039   OS::Abort();
1040   return 0;
1041 }
1042 
1043 
WriteD(int32_t addr,double value,Instruction * instr)1044 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
1045   if ((addr & kDoubleAlignmentMask) == 0) {
1046     double* ptr = reinterpret_cast<double*>(addr);
1047     *ptr = value;
1048     return;
1049   }
1050   PrintF("Unaligned (double) write at 0x%08x, pc=%p\n", addr,
1051       reinterpret_cast<void*>(instr));
1052   OS::Abort();
1053 }
1054 
1055 
ReadHU(int32_t addr,Instruction * instr)1056 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1057   if ((addr & 1) == 0) {
1058     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1059     return *ptr;
1060   }
1061   PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr,
1062       reinterpret_cast<void*>(instr));
1063   OS::Abort();
1064   return 0;
1065 }
1066 
1067 
ReadH(int32_t addr,Instruction * instr)1068 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1069   if ((addr & 1) == 0) {
1070     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1071     return *ptr;
1072   }
1073   PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr,
1074       reinterpret_cast<void*>(instr));
1075   OS::Abort();
1076   return 0;
1077 }
1078 
1079 
WriteH(int32_t addr,uint16_t value,Instruction * instr)1080 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1081   if ((addr & 1) == 0) {
1082     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1083     *ptr = value;
1084     return;
1085   }
1086   PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr,
1087       reinterpret_cast<void*>(instr));
1088   OS::Abort();
1089 }
1090 
1091 
WriteH(int32_t addr,int16_t value,Instruction * instr)1092 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1093   if ((addr & 1) == 0) {
1094     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1095     *ptr = value;
1096     return;
1097   }
1098   PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr,
1099       reinterpret_cast<void*>(instr));
1100   OS::Abort();
1101 }
1102 
1103 
ReadBU(int32_t addr)1104 uint32_t Simulator::ReadBU(int32_t addr) {
1105   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1106   return *ptr & 0xff;
1107 }
1108 
1109 
ReadB(int32_t addr)1110 int32_t Simulator::ReadB(int32_t addr) {
1111   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1112   return *ptr;
1113 }
1114 
1115 
WriteB(int32_t addr,uint8_t value)1116 void Simulator::WriteB(int32_t addr, uint8_t value) {
1117   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1118   *ptr = value;
1119 }
1120 
1121 
WriteB(int32_t addr,int8_t value)1122 void Simulator::WriteB(int32_t addr, int8_t value) {
1123   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1124   *ptr = value;
1125 }
1126 
1127 
1128 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit() const1129 uintptr_t Simulator::StackLimit() const {
1130   // Leave a safety margin of 256 bytes to prevent overrunning the stack when
1131   // pushing values.
1132   return reinterpret_cast<uintptr_t>(stack_) + 256;
1133 }
1134 
1135 
1136 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)1137 void Simulator::Format(Instruction* instr, const char* format) {
1138   PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1139          reinterpret_cast<intptr_t>(instr), format);
1140   UNIMPLEMENTED_MIPS();
1141 }
1142 
1143 
1144 // Calls into the V8 runtime are based on this very simple interface.
1145 // Note: To be able to return two values from some calls the code in runtime.cc
1146 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1147 // 64-bit value. With the code below we assume that all runtime calls return
1148 // 64 bits of result. If they don't, the v1 result register contains a bogus
1149 // value, which is fine because it is caller-saved.
1150 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1151                                         int32_t arg1,
1152                                         int32_t arg2,
1153                                         int32_t arg3,
1154                                         int32_t arg4,
1155                                         int32_t arg5);
1156 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1157                                          int32_t arg1,
1158                                          int32_t arg2,
1159                                          int32_t arg3);
1160 
1161 // Software interrupt instructions are used by the simulator to call into the
1162 // C-based V8 runtime. They are also used for debugging with simulator.
SoftwareInterrupt(Instruction * instr)1163 void Simulator::SoftwareInterrupt(Instruction* instr) {
1164   // There are several instructions that could get us here,
1165   // the break_ instruction, or several variants of traps. All
1166   // Are "SPECIAL" class opcode, and are distinuished by function.
1167   int32_t func = instr->FunctionFieldRaw();
1168   int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1169 
1170   // We first check if we met a call_rt_redirected.
1171   if (instr->InstructionBits() == rtCallRedirInstr) {
1172     // Check if stack is aligned. Error if not aligned is reported below to
1173     // include information on the function called.
1174     bool stack_aligned =
1175         (get_register(sp)
1176          & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1177     Redirection* redirection = Redirection::FromSwiInstruction(instr);
1178     int32_t arg0 = get_register(a0);
1179     int32_t arg1 = get_register(a1);
1180     int32_t arg2 = get_register(a2);
1181     int32_t arg3 = get_register(a3);
1182     int32_t arg4 = 0;
1183     int32_t arg5 = 0;
1184 
1185     // Need to check if sp is valid before assigning arg4, arg5.
1186     // This is a fix for cctest test-api/CatchStackOverflow which causes
1187     // the stack to overflow. For some reason arm doesn't need this
1188     // stack check here.
1189     int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1190     int32_t* stack = reinterpret_cast<int32_t*>(stack_);
1191     if (stack_pointer >= stack && stack_pointer < stack + stack_size_) {
1192       arg4 = stack_pointer[0];
1193       arg5 = stack_pointer[1];
1194     }
1195     // This is dodgy but it works because the C entry stubs are never moved.
1196     // See comment in codegen-arm.cc and bug 1242173.
1197     int32_t saved_ra = get_register(ra);
1198 
1199     intptr_t external =
1200         reinterpret_cast<int32_t>(redirection->external_function());
1201 
1202     // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1203     // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1204     // simulator. Soft-float has additional abstraction of ExternalReference,
1205     // to support serialization. Finally, when simulated on x86 host, the
1206     // x86 softfloat routines are used, and this Redirection infrastructure
1207     // lets simulated-mips make calls into x86 C code.
1208     // When doing that, the 'double' return type must be handled differently
1209     // than the usual int64_t return. The data is returned in different
1210     // registers and cannot be cast from one type to the other. However, the
1211     // calling arguments are passed the same way in both cases.
1212     if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
1213       SimulatorRuntimeFPCall target =
1214           reinterpret_cast<SimulatorRuntimeFPCall>(external);
1215       if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1216         PrintF("Call to host function at %p with args %08x:%08x %08x:%08x",
1217                FUNCTION_ADDR(target), arg0, arg1, arg2, arg3);
1218         if (!stack_aligned) {
1219           PrintF(" with unaligned stack %08x\n", get_register(sp));
1220         }
1221         PrintF("\n");
1222       }
1223       double result = target(arg0, arg1, arg2, arg3);
1224       // fp result -> registers v0 and v1.
1225       int32_t gpreg_pair[2];
1226       memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
1227       set_register(v0, gpreg_pair[0]);
1228       set_register(v1, gpreg_pair[1]);
1229     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1230       PrintF("Mips does not yet support ExternalReference::DIRECT_API_CALL\n");
1231       ASSERT(redirection->type() != ExternalReference::DIRECT_API_CALL);
1232     } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1233       PrintF("Mips does not support ExternalReference::DIRECT_GETTER_CALL\n");
1234       ASSERT(redirection->type() != ExternalReference::DIRECT_GETTER_CALL);
1235     } else {
1236       // Builtin call.
1237       ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1238       SimulatorRuntimeCall target =
1239           reinterpret_cast<SimulatorRuntimeCall>(external);
1240       if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1241         PrintF(
1242             "Call to host function at %p: %08x, %08x, %08x, %08x, %08x, %08x",
1243             FUNCTION_ADDR(target),
1244             arg0,
1245             arg1,
1246             arg2,
1247             arg3,
1248             arg4,
1249             arg5);
1250         if (!stack_aligned) {
1251           PrintF(" with unaligned stack %08x\n", get_register(sp));
1252         }
1253         PrintF("\n");
1254       }
1255 
1256       int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1257       set_register(v0, static_cast<int32_t>(result));
1258       set_register(v1, static_cast<int32_t>(result >> 32));
1259     }
1260     if (::v8::internal::FLAG_trace_sim) {
1261       PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
1262     }
1263     set_register(ra, saved_ra);
1264     set_pc(get_register(ra));
1265 
1266   } else if (func == BREAK && code >= 0 && code < 16) {
1267     // First 16 break_ codes interpreted as debug markers.
1268     MipsDebugger dbg(this);
1269     ++break_count_;
1270     PrintF("\n---- break %d marker: %3d  (instr count: %8d) ----------"
1271            "----------------------------------",
1272            code, break_count_, icount_);
1273     dbg.PrintAllRegs();  // Print registers and continue running.
1274   } else {
1275     // All remaining break_ codes, and all traps are handled here.
1276     MipsDebugger dbg(this);
1277     dbg.Debug();
1278   }
1279 }
1280 
1281 
SignalExceptions()1282 void Simulator::SignalExceptions() {
1283   for (int i = 1; i < kNumExceptions; i++) {
1284     if (exceptions[i] != 0) {
1285       V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1286     }
1287   }
1288 }
1289 
1290 
1291 // Handle execution based on instruction types.
1292 
ConfigureTypeRegister(Instruction * instr,int32_t & alu_out,int64_t & i64hilo,uint64_t & u64hilo,int32_t & next_pc,bool & do_interrupt)1293 void Simulator::ConfigureTypeRegister(Instruction* instr,
1294                                       int32_t& alu_out,
1295                                       int64_t& i64hilo,
1296                                       uint64_t& u64hilo,
1297                                       int32_t& next_pc,
1298                                       bool& do_interrupt) {
1299   // Every local variable declared here needs to be const.
1300   // This is to make sure that changed values are sent back to
1301   // DecodeTypeRegister correctly.
1302 
1303   // Instruction fields.
1304   const Opcode   op     = instr->OpcodeFieldRaw();
1305   const int32_t  rs_reg = instr->RsValue();
1306   const int32_t  rs     = get_register(rs_reg);
1307   const uint32_t rs_u   = static_cast<uint32_t>(rs);
1308   const int32_t  rt_reg = instr->RtValue();
1309   const int32_t  rt     = get_register(rt_reg);
1310   const uint32_t rt_u   = static_cast<uint32_t>(rt);
1311   const int32_t  rd_reg = instr->RdValue();
1312   const uint32_t sa     = instr->SaValue();
1313 
1314   const int32_t  fs_reg = instr->FsValue();
1315 
1316 
1317   // ---------- Configuration
1318   switch (op) {
1319     case COP1:    // Coprocessor instructions
1320       switch (instr->RsFieldRaw()) {
1321         case BC1:   // Handled in DecodeTypeImmed, should never come here.
1322           UNREACHABLE();
1323           break;
1324         case CFC1:
1325           // At the moment only FCSR is supported.
1326           ASSERT(fs_reg == kFCSRRegister);
1327           alu_out = FCSR_;
1328           break;
1329         case MFC1:
1330           alu_out = get_fpu_register(fs_reg);
1331           break;
1332         case MFHC1:
1333           UNIMPLEMENTED_MIPS();
1334           break;
1335         case CTC1:
1336         case MTC1:
1337         case MTHC1:
1338           // Do the store in the execution step.
1339           break;
1340         case S:
1341         case D:
1342         case W:
1343         case L:
1344         case PS:
1345           // Do everything in the execution step.
1346           break;
1347         default:
1348           UNIMPLEMENTED_MIPS();
1349       };
1350       break;
1351     case SPECIAL:
1352       switch (instr->FunctionFieldRaw()) {
1353         case JR:
1354         case JALR:
1355           next_pc = get_register(instr->RsValue());
1356           break;
1357         case SLL:
1358           alu_out = rt << sa;
1359           break;
1360         case SRL:
1361           if (rs_reg == 0) {
1362             // Regular logical right shift of a word by a fixed number of
1363             // bits instruction. RS field is always equal to 0.
1364             alu_out = rt_u >> sa;
1365           } else {
1366             // Logical right-rotate of a word by a fixed number of bits. This
1367             // is special case of SRL instruction, added in MIPS32 Release 2.
1368             // RS field is equal to 00001
1369             alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1370           }
1371           break;
1372         case SRA:
1373           alu_out = rt >> sa;
1374           break;
1375         case SLLV:
1376           alu_out = rt << rs;
1377           break;
1378         case SRLV:
1379           if (sa == 0) {
1380             // Regular logical right-shift of a word by a variable number of
1381             // bits instruction. SA field is always equal to 0.
1382             alu_out = rt_u >> rs;
1383           } else {
1384             // Logical right-rotate of a word by a variable number of bits.
1385             // This is special case od SRLV instruction, added in MIPS32
1386             // Release 2. SA field is equal to 00001
1387             alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1388           }
1389           break;
1390         case SRAV:
1391           alu_out = rt >> rs;
1392           break;
1393         case MFHI:
1394           alu_out = get_register(HI);
1395           break;
1396         case MFLO:
1397           alu_out = get_register(LO);
1398           break;
1399         case MULT:
1400           i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1401           break;
1402         case MULTU:
1403           u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
1404           break;
1405         case DIV:
1406         case DIVU:
1407             exceptions[kDivideByZero] = rt == 0;
1408           break;
1409         case ADD:
1410           if (HaveSameSign(rs, rt)) {
1411             if (rs > 0) {
1412               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
1413             } else if (rs < 0) {
1414               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
1415             }
1416           }
1417           alu_out = rs + rt;
1418           break;
1419         case ADDU:
1420           alu_out = rs + rt;
1421           break;
1422         case SUB:
1423           if (!HaveSameSign(rs, rt)) {
1424             if (rs > 0) {
1425               exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
1426             } else if (rs < 0) {
1427               exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
1428             }
1429           }
1430           alu_out = rs - rt;
1431           break;
1432         case SUBU:
1433           alu_out = rs - rt;
1434           break;
1435         case AND:
1436           alu_out = rs & rt;
1437           break;
1438         case OR:
1439           alu_out = rs | rt;
1440           break;
1441         case XOR:
1442           alu_out = rs ^ rt;
1443           break;
1444         case NOR:
1445           alu_out = ~(rs | rt);
1446           break;
1447         case SLT:
1448           alu_out = rs < rt ? 1 : 0;
1449           break;
1450         case SLTU:
1451           alu_out = rs_u < rt_u ? 1 : 0;
1452           break;
1453         // Break and trap instructions
1454         case BREAK:
1455 
1456           do_interrupt = true;
1457           break;
1458         case TGE:
1459           do_interrupt = rs >= rt;
1460           break;
1461         case TGEU:
1462           do_interrupt = rs_u >= rt_u;
1463           break;
1464         case TLT:
1465           do_interrupt = rs < rt;
1466           break;
1467         case TLTU:
1468           do_interrupt = rs_u < rt_u;
1469           break;
1470         case TEQ:
1471           do_interrupt = rs == rt;
1472           break;
1473         case TNE:
1474           do_interrupt = rs != rt;
1475           break;
1476         case MOVN:
1477         case MOVZ:
1478         case MOVCI:
1479           // No action taken on decode.
1480           break;
1481         default:
1482           UNREACHABLE();
1483       };
1484       break;
1485     case SPECIAL2:
1486       switch (instr->FunctionFieldRaw()) {
1487         case MUL:
1488           alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
1489           break;
1490         case CLZ:
1491           alu_out = __builtin_clz(rs_u);
1492           break;
1493         default:
1494           UNREACHABLE();
1495       };
1496       break;
1497     case SPECIAL3:
1498       switch (instr->FunctionFieldRaw()) {
1499         case INS: {   // Mips32r2 instruction.
1500           // Interpret Rd field as 5-bit msb of insert.
1501           uint16_t msb = rd_reg;
1502           // Interpret sa field as 5-bit lsb of insert.
1503           uint16_t lsb = sa;
1504           uint16_t size = msb - lsb + 1;
1505           uint32_t mask = (1 << size) - 1;
1506           alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1507           break;
1508         }
1509         case EXT: {   // Mips32r2 instruction.
1510           // Interpret Rd field as 5-bit msb of extract.
1511           uint16_t msb = rd_reg;
1512           // Interpret sa field as 5-bit lsb of extract.
1513           uint16_t lsb = sa;
1514           uint16_t size = msb + 1;
1515           uint32_t mask = (1 << size) - 1;
1516           alu_out = (rs_u & (mask << lsb)) >> lsb;
1517           break;
1518         }
1519         default:
1520           UNREACHABLE();
1521       };
1522       break;
1523     default:
1524       UNREACHABLE();
1525   };
1526 }
1527 
1528 
DecodeTypeRegister(Instruction * instr)1529 void Simulator::DecodeTypeRegister(Instruction* instr) {
1530   // Instruction fields.
1531   const Opcode   op     = instr->OpcodeFieldRaw();
1532   const int32_t  rs_reg = instr->RsValue();
1533   const int32_t  rs     = get_register(rs_reg);
1534   const uint32_t rs_u   = static_cast<uint32_t>(rs);
1535   const int32_t  rt_reg = instr->RtValue();
1536   const int32_t  rt     = get_register(rt_reg);
1537   const uint32_t rt_u   = static_cast<uint32_t>(rt);
1538   const int32_t  rd_reg = instr->RdValue();
1539 
1540   const int32_t  fs_reg = instr->FsValue();
1541   const int32_t  ft_reg = instr->FtValue();
1542   const int32_t  fd_reg = instr->FdValue();
1543   int64_t  i64hilo = 0;
1544   uint64_t u64hilo = 0;
1545 
1546   // ALU output
1547   // It should not be used as is. Instructions using it should always
1548   // initialize it first.
1549   int32_t alu_out = 0x12345678;
1550 
1551   // For break and trap instructions.
1552   bool do_interrupt = false;
1553 
1554   // For jr and jalr
1555   // Get current pc.
1556   int32_t current_pc = get_pc();
1557   // Next pc
1558   int32_t next_pc = 0;
1559 
1560   // Setup the variables if needed before executing the instruction.
1561   ConfigureTypeRegister(instr,
1562                         alu_out,
1563                         i64hilo,
1564                         u64hilo,
1565                         next_pc,
1566                         do_interrupt);
1567 
1568   // ---------- Raise exceptions triggered.
1569   SignalExceptions();
1570 
1571   // ---------- Execution
1572   switch (op) {
1573     case COP1:
1574       switch (instr->RsFieldRaw()) {
1575         case BC1:   // branch on coprocessor condition
1576           UNREACHABLE();
1577           break;
1578         case CFC1:
1579           set_register(rt_reg, alu_out);
1580         case MFC1:
1581           set_register(rt_reg, alu_out);
1582           break;
1583         case MFHC1:
1584           UNIMPLEMENTED_MIPS();
1585           break;
1586         case CTC1:
1587           // At the moment only FCSR is supported.
1588           ASSERT(fs_reg == kFCSRRegister);
1589           FCSR_ = registers_[rt_reg];
1590           break;
1591         case MTC1:
1592           FPUregisters_[fs_reg] = registers_[rt_reg];
1593           break;
1594         case MTHC1:
1595           UNIMPLEMENTED_MIPS();
1596           break;
1597         case S:
1598           float f;
1599           switch (instr->FunctionFieldRaw()) {
1600             case CVT_D_S:
1601               f = get_fpu_register_float(fs_reg);
1602               set_fpu_register_double(fd_reg, static_cast<double>(f));
1603               break;
1604             case CVT_W_S:
1605             case CVT_L_S:
1606             case TRUNC_W_S:
1607             case TRUNC_L_S:
1608             case ROUND_W_S:
1609             case ROUND_L_S:
1610             case FLOOR_W_S:
1611             case FLOOR_L_S:
1612             case CEIL_W_S:
1613             case CEIL_L_S:
1614             case CVT_PS_S:
1615               UNIMPLEMENTED_MIPS();
1616               break;
1617             default:
1618               UNREACHABLE();
1619           }
1620           break;
1621         case D:
1622           double ft, fs;
1623           uint32_t cc, fcsr_cc;
1624           int64_t  i64;
1625           fs = get_fpu_register_double(fs_reg);
1626           ft = get_fpu_register_double(ft_reg);
1627           cc = instr->FCccValue();
1628           fcsr_cc = get_fcsr_condition_bit(cc);
1629           switch (instr->FunctionFieldRaw()) {
1630             case ADD_D:
1631               set_fpu_register_double(fd_reg, fs + ft);
1632               break;
1633             case SUB_D:
1634               set_fpu_register_double(fd_reg, fs - ft);
1635               break;
1636             case MUL_D:
1637               set_fpu_register_double(fd_reg, fs * ft);
1638               break;
1639             case DIV_D:
1640               set_fpu_register_double(fd_reg, fs / ft);
1641               break;
1642             case ABS_D:
1643               set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
1644               break;
1645             case MOV_D:
1646               set_fpu_register_double(fd_reg, fs);
1647               break;
1648             case NEG_D:
1649               set_fpu_register_double(fd_reg, -fs);
1650               break;
1651             case SQRT_D:
1652               set_fpu_register_double(fd_reg, sqrt(fs));
1653               break;
1654             case C_UN_D:
1655               set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft));
1656               break;
1657             case C_EQ_D:
1658               set_fcsr_bit(fcsr_cc, (fs == ft));
1659               break;
1660             case C_UEQ_D:
1661               set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft)));
1662               break;
1663             case C_OLT_D:
1664               set_fcsr_bit(fcsr_cc, (fs < ft));
1665               break;
1666             case C_ULT_D:
1667               set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft)));
1668               break;
1669             case C_OLE_D:
1670               set_fcsr_bit(fcsr_cc, (fs <= ft));
1671               break;
1672             case C_ULE_D:
1673               set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft)));
1674               break;
1675             case CVT_W_D:   // Convert double to word.
1676               // Rounding modes are not yet supported.
1677               ASSERT((FCSR_ & 3) == 0);
1678               // In rounding mode 0 it should behave like ROUND.
1679             case ROUND_W_D:  // Round double to word.
1680               {
1681                 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1682                 int32_t result = static_cast<int32_t>(rounded);
1683                 set_fpu_register(fd_reg, result);
1684                 if (set_fcsr_round_error(fs, rounded)) {
1685                   set_fpu_register(fd_reg, kFPUInvalidResult);
1686                 }
1687               }
1688               break;
1689             case TRUNC_W_D:  // Truncate double to word (round towards 0).
1690               {
1691                 int32_t result = static_cast<int32_t>(fs);
1692                 set_fpu_register(fd_reg, result);
1693                 if (set_fcsr_round_error(fs, static_cast<double>(result))) {
1694                   set_fpu_register(fd_reg, kFPUInvalidResult);
1695                 }
1696               }
1697               break;
1698             case FLOOR_W_D:  // Round double to word towards negative infinity.
1699               {
1700                 double rounded = floor(fs);
1701                 int32_t result = static_cast<int32_t>(rounded);
1702                 set_fpu_register(fd_reg, result);
1703                 if (set_fcsr_round_error(fs, rounded)) {
1704                   set_fpu_register(fd_reg, kFPUInvalidResult);
1705                 }
1706               }
1707               break;
1708             case CEIL_W_D:  // Round double to word towards positive infinity.
1709               {
1710                 double rounded = ceil(fs);
1711                 int32_t result = static_cast<int32_t>(rounded);
1712                 set_fpu_register(fd_reg, result);
1713                 if (set_fcsr_round_error(fs, rounded)) {
1714                   set_fpu_register(fd_reg, kFPUInvalidResult);
1715                 }
1716               }
1717               break;
1718             case CVT_S_D:  // Convert double to float (single).
1719               set_fpu_register_float(fd_reg, static_cast<float>(fs));
1720               break;
1721             case CVT_L_D:  // Mips32r2: Truncate double to 64-bit long-word.
1722               i64 = static_cast<int64_t>(fs);
1723               set_fpu_register(fd_reg, i64 & 0xffffffff);
1724               set_fpu_register(fd_reg + 1, i64 >> 32);
1725               break;
1726             case TRUNC_L_D:  // Mips32r2 instruction.
1727               i64 = static_cast<int64_t>(fs);
1728               set_fpu_register(fd_reg, i64 & 0xffffffff);
1729               set_fpu_register(fd_reg + 1, i64 >> 32);
1730               break;
1731             case ROUND_L_D: {  // Mips32r2 instruction.
1732               double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1733               i64 = static_cast<int64_t>(rounded);
1734               set_fpu_register(fd_reg, i64 & 0xffffffff);
1735               set_fpu_register(fd_reg + 1, i64 >> 32);
1736               break;
1737             }
1738             case FLOOR_L_D:  // Mips32r2 instruction.
1739               i64 = static_cast<int64_t>(floor(fs));
1740               set_fpu_register(fd_reg, i64 & 0xffffffff);
1741               set_fpu_register(fd_reg + 1, i64 >> 32);
1742               break;
1743             case CEIL_L_D:  // Mips32r2 instruction.
1744               i64 = static_cast<int64_t>(ceil(fs));
1745               set_fpu_register(fd_reg, i64 & 0xffffffff);
1746               set_fpu_register(fd_reg + 1, i64 >> 32);
1747               break;
1748             case C_F_D:
1749               UNIMPLEMENTED_MIPS();
1750               break;
1751             default:
1752               UNREACHABLE();
1753           }
1754           break;
1755         case W:
1756           switch (instr->FunctionFieldRaw()) {
1757             case CVT_S_W:   // Convert word to float (single).
1758               alu_out = get_fpu_register(fs_reg);
1759               set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
1760               break;
1761             case CVT_D_W:   // Convert word to double.
1762               alu_out = get_fpu_register(fs_reg);
1763               set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
1764               break;
1765             default:
1766               UNREACHABLE();
1767           };
1768           break;
1769         case L:
1770           switch (instr->FunctionFieldRaw()) {
1771           case CVT_D_L:  // Mips32r2 instruction.
1772             // Watch the signs here, we want 2 32-bit vals
1773             // to make a sign-64.
1774             i64 = (uint32_t) get_fpu_register(fs_reg);
1775             i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
1776             set_fpu_register_double(fd_reg, static_cast<double>(i64));
1777             break;
1778             case CVT_S_L:
1779               UNIMPLEMENTED_MIPS();
1780               break;
1781             default:
1782               UNREACHABLE();
1783           }
1784           break;
1785         case PS:
1786           break;
1787         default:
1788           UNREACHABLE();
1789       };
1790       break;
1791     case SPECIAL:
1792       switch (instr->FunctionFieldRaw()) {
1793         case JR: {
1794           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1795               current_pc+Instruction::kInstrSize);
1796           BranchDelayInstructionDecode(branch_delay_instr);
1797           set_pc(next_pc);
1798           pc_modified_ = true;
1799           break;
1800         }
1801         case JALR: {
1802           Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1803               current_pc+Instruction::kInstrSize);
1804           BranchDelayInstructionDecode(branch_delay_instr);
1805           set_register(31, current_pc + 2* Instruction::kInstrSize);
1806           set_pc(next_pc);
1807           pc_modified_ = true;
1808           break;
1809         }
1810         // Instructions using HI and LO registers.
1811         case MULT:
1812           set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
1813           set_register(HI, static_cast<int32_t>(i64hilo >> 32));
1814           break;
1815         case MULTU:
1816           set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
1817           set_register(HI, static_cast<int32_t>(u64hilo >> 32));
1818           break;
1819         case DIV:
1820           // Divide by zero was checked in the configuration step.
1821           set_register(LO, rs / rt);
1822           set_register(HI, rs % rt);
1823           break;
1824         case DIVU:
1825           set_register(LO, rs_u / rt_u);
1826           set_register(HI, rs_u % rt_u);
1827           break;
1828         // Break and trap instructions.
1829         case BREAK:
1830         case TGE:
1831         case TGEU:
1832         case TLT:
1833         case TLTU:
1834         case TEQ:
1835         case TNE:
1836           if (do_interrupt) {
1837             SoftwareInterrupt(instr);
1838           }
1839           break;
1840         // Conditional moves.
1841         case MOVN:
1842           if (rt) set_register(rd_reg, rs);
1843           break;
1844         case MOVCI: {
1845           uint32_t cc = instr->FCccValue();
1846           uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
1847           if (instr->Bit(16)) {  // Read Tf bit
1848             if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
1849           } else {
1850             if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
1851           }
1852           break;
1853         }
1854         case MOVZ:
1855           if (!rt) set_register(rd_reg, rs);
1856           break;
1857         default:  // For other special opcodes we do the default operation.
1858           set_register(rd_reg, alu_out);
1859       };
1860       break;
1861     case SPECIAL2:
1862       switch (instr->FunctionFieldRaw()) {
1863         case MUL:
1864           set_register(rd_reg, alu_out);
1865           // HI and LO are UNPREDICTABLE after the operation.
1866           set_register(LO, Unpredictable);
1867           set_register(HI, Unpredictable);
1868           break;
1869         default:  // For other special2 opcodes we do the default operation.
1870           set_register(rd_reg, alu_out);
1871       }
1872       break;
1873     case SPECIAL3:
1874       switch (instr->FunctionFieldRaw()) {
1875         case INS:
1876           // Ins instr leaves result in Rt, rather than Rd.
1877           set_register(rt_reg, alu_out);
1878           break;
1879         case EXT:
1880           // Ext instr leaves result in Rt, rather than Rd.
1881           set_register(rt_reg, alu_out);
1882           break;
1883         default:
1884           UNREACHABLE();
1885       };
1886       break;
1887     // Unimplemented opcodes raised an error in the configuration step before,
1888     // so we can use the default here to set the destination register in common
1889     // cases.
1890     default:
1891       set_register(rd_reg, alu_out);
1892   };
1893 }
1894 
1895 
1896 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq)
DecodeTypeImmediate(Instruction * instr)1897 void Simulator::DecodeTypeImmediate(Instruction* instr) {
1898   // Instruction fields.
1899   Opcode   op     = instr->OpcodeFieldRaw();
1900   int32_t  rs     = get_register(instr->RsValue());
1901   uint32_t rs_u   = static_cast<uint32_t>(rs);
1902   int32_t  rt_reg = instr->RtValue();  // destination register
1903   int32_t  rt     = get_register(rt_reg);
1904   int16_t  imm16  = instr->Imm16Value();
1905 
1906   int32_t  ft_reg = instr->FtValue();  // destination register
1907 
1908   // Zero extended immediate.
1909   uint32_t  oe_imm16 = 0xffff & imm16;
1910   // Sign extended immediate.
1911   int32_t   se_imm16 = imm16;
1912 
1913   // Get current pc.
1914   int32_t current_pc = get_pc();
1915   // Next pc.
1916   int32_t next_pc = bad_ra;
1917 
1918   // Used for conditional branch instructions.
1919   bool do_branch = false;
1920   bool execute_branch_delay_instruction = false;
1921 
1922   // Used for arithmetic instructions.
1923   int32_t alu_out = 0;
1924   // Floating point.
1925   double fp_out = 0.0;
1926   uint32_t cc, cc_value, fcsr_cc;
1927 
1928   // Used for memory instructions.
1929   int32_t addr = 0x0;
1930   // Value to be written in memory
1931   uint32_t mem_value = 0x0;
1932 
1933   // ---------- Configuration (and execution for REGIMM)
1934   switch (op) {
1935     // ------------- COP1. Coprocessor instructions.
1936     case COP1:
1937       switch (instr->RsFieldRaw()) {
1938         case BC1:   // Branch on coprocessor condition.
1939           cc = instr->FBccValue();
1940           fcsr_cc = get_fcsr_condition_bit(cc);
1941           cc_value = test_fcsr_bit(fcsr_cc);
1942           do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
1943           execute_branch_delay_instruction = true;
1944           // Set next_pc
1945           if (do_branch) {
1946             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
1947           } else {
1948             next_pc = current_pc + kBranchReturnOffset;
1949           }
1950           break;
1951         default:
1952           UNREACHABLE();
1953       };
1954       break;
1955     // ------------- REGIMM class
1956     case REGIMM:
1957       switch (instr->RtFieldRaw()) {
1958         case BLTZ:
1959           do_branch = (rs  < 0);
1960           break;
1961         case BLTZAL:
1962           do_branch = rs  < 0;
1963           break;
1964         case BGEZ:
1965           do_branch = rs >= 0;
1966           break;
1967         case BGEZAL:
1968           do_branch = rs >= 0;
1969           break;
1970         default:
1971           UNREACHABLE();
1972       };
1973       switch (instr->RtFieldRaw()) {
1974         case BLTZ:
1975         case BLTZAL:
1976         case BGEZ:
1977         case BGEZAL:
1978           // Branch instructions common part.
1979           execute_branch_delay_instruction = true;
1980           // Set next_pc
1981           if (do_branch) {
1982             next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
1983             if (instr->IsLinkingInstruction()) {
1984               set_register(31, current_pc + kBranchReturnOffset);
1985             }
1986           } else {
1987             next_pc = current_pc + kBranchReturnOffset;
1988           }
1989         default:
1990           break;
1991         };
1992     break;  // case REGIMM
1993     // ------------- Branch instructions
1994     // When comparing to zero, the encoding of rt field is always 0, so we don't
1995     // need to replace rt with zero.
1996     case BEQ:
1997       do_branch = (rs == rt);
1998       break;
1999     case BNE:
2000       do_branch = rs != rt;
2001       break;
2002     case BLEZ:
2003       do_branch = rs <= 0;
2004       break;
2005     case BGTZ:
2006       do_branch = rs  > 0;
2007       break;
2008     // ------------- Arithmetic instructions
2009     case ADDI:
2010       if (HaveSameSign(rs, se_imm16)) {
2011         if (rs > 0) {
2012           exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2013         } else if (rs < 0) {
2014           exceptions[kIntegerUnderflow] =
2015               rs < (Registers::kMinValue - se_imm16);
2016         }
2017       }
2018       alu_out = rs + se_imm16;
2019       break;
2020     case ADDIU:
2021       alu_out = rs + se_imm16;
2022       break;
2023     case SLTI:
2024       alu_out = (rs < se_imm16) ? 1 : 0;
2025       break;
2026     case SLTIU:
2027       alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2028       break;
2029     case ANDI:
2030         alu_out = rs & oe_imm16;
2031       break;
2032     case ORI:
2033         alu_out = rs | oe_imm16;
2034       break;
2035     case XORI:
2036         alu_out = rs ^ oe_imm16;
2037       break;
2038     case LUI:
2039         alu_out = (oe_imm16 << 16);
2040       break;
2041     // ------------- Memory instructions
2042     case LB:
2043       addr = rs + se_imm16;
2044       alu_out = ReadB(addr);
2045       break;
2046     case LH:
2047       addr = rs + se_imm16;
2048       alu_out = ReadH(addr, instr);
2049       break;
2050     case LWL: {
2051       // al_offset is an offset of the effective address within an aligned word
2052       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2053       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2054       uint32_t mask = (1 << byte_shift * 8) - 1;
2055       addr = rs + se_imm16 - al_offset;
2056       alu_out = ReadW(addr, instr);
2057       alu_out <<= byte_shift * 8;
2058       alu_out |= rt & mask;
2059       break;
2060     }
2061     case LW:
2062       addr = rs + se_imm16;
2063       alu_out = ReadW(addr, instr);
2064       break;
2065     case LBU:
2066       addr = rs + se_imm16;
2067       alu_out = ReadBU(addr);
2068       break;
2069     case LHU:
2070       addr = rs + se_imm16;
2071       alu_out = ReadHU(addr, instr);
2072       break;
2073     case LWR: {
2074       // al_offset is an offset of the effective address within an aligned word
2075       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2076       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2077       uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2078       addr = rs + se_imm16 - al_offset;
2079       alu_out = ReadW(addr, instr);
2080       alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2081       alu_out |= rt & mask;
2082       break;
2083     }
2084     case SB:
2085       addr = rs + se_imm16;
2086       break;
2087     case SH:
2088       addr = rs + se_imm16;
2089       break;
2090     case SWL: {
2091       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2092       uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2093       uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2094       addr = rs + se_imm16 - al_offset;
2095       mem_value = ReadW(addr, instr) & mask;
2096       mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2097       break;
2098     }
2099     case SW:
2100       addr = rs + se_imm16;
2101       break;
2102     case SWR: {
2103       uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2104       uint32_t mask = (1 << al_offset * 8) - 1;
2105       addr = rs + se_imm16 - al_offset;
2106       mem_value = ReadW(addr, instr);
2107       mem_value = (rt << al_offset * 8) | (mem_value & mask);
2108       break;
2109     }
2110     case LWC1:
2111       addr = rs + se_imm16;
2112       alu_out = ReadW(addr, instr);
2113       break;
2114     case LDC1:
2115       addr = rs + se_imm16;
2116       fp_out = ReadD(addr, instr);
2117       break;
2118     case SWC1:
2119     case SDC1:
2120       addr = rs + se_imm16;
2121       break;
2122     default:
2123       UNREACHABLE();
2124   };
2125 
2126   // ---------- Raise exceptions triggered.
2127   SignalExceptions();
2128 
2129   // ---------- Execution
2130   switch (op) {
2131     // ------------- Branch instructions
2132     case BEQ:
2133     case BNE:
2134     case BLEZ:
2135     case BGTZ:
2136       // Branch instructions common part.
2137       execute_branch_delay_instruction = true;
2138       // Set next_pc
2139       if (do_branch) {
2140         next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2141         if (instr->IsLinkingInstruction()) {
2142           set_register(31, current_pc + 2* Instruction::kInstrSize);
2143         }
2144       } else {
2145         next_pc = current_pc + 2 * Instruction::kInstrSize;
2146       }
2147       break;
2148     // ------------- Arithmetic instructions
2149     case ADDI:
2150     case ADDIU:
2151     case SLTI:
2152     case SLTIU:
2153     case ANDI:
2154     case ORI:
2155     case XORI:
2156     case LUI:
2157       set_register(rt_reg, alu_out);
2158       break;
2159     // ------------- Memory instructions
2160     case LB:
2161     case LH:
2162     case LWL:
2163     case LW:
2164     case LBU:
2165     case LHU:
2166     case LWR:
2167       set_register(rt_reg, alu_out);
2168       break;
2169     case SB:
2170       WriteB(addr, static_cast<int8_t>(rt));
2171       break;
2172     case SH:
2173       WriteH(addr, static_cast<uint16_t>(rt), instr);
2174       break;
2175     case SWL:
2176       WriteW(addr, mem_value, instr);
2177       break;
2178     case SW:
2179       WriteW(addr, rt, instr);
2180       break;
2181     case SWR:
2182       WriteW(addr, mem_value, instr);
2183       break;
2184     case LWC1:
2185       set_fpu_register(ft_reg, alu_out);
2186       break;
2187     case LDC1:
2188       set_fpu_register_double(ft_reg, fp_out);
2189       break;
2190     case SWC1:
2191       addr = rs + se_imm16;
2192       WriteW(addr, get_fpu_register(ft_reg), instr);
2193       break;
2194     case SDC1:
2195       addr = rs + se_imm16;
2196       WriteD(addr, get_fpu_register_double(ft_reg), instr);
2197       break;
2198     default:
2199       break;
2200   };
2201 
2202 
2203   if (execute_branch_delay_instruction) {
2204     // Execute branch delay slot
2205     // We don't check for end_sim_pc. First it should not be met as the current
2206     // pc is valid. Secondly a jump should always execute its branch delay slot.
2207     Instruction* branch_delay_instr =
2208       reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2209     BranchDelayInstructionDecode(branch_delay_instr);
2210   }
2211 
2212   // If needed update pc after the branch delay execution.
2213   if (next_pc != bad_ra) {
2214     set_pc(next_pc);
2215   }
2216 }
2217 
2218 
2219 // Type 3: instructions using a 26 bytes immediate. (eg: j, jal)
DecodeTypeJump(Instruction * instr)2220 void Simulator::DecodeTypeJump(Instruction* instr) {
2221   // Get current pc.
2222   int32_t current_pc = get_pc();
2223   // Get unchanged bits of pc.
2224   int32_t pc_high_bits = current_pc & 0xf0000000;
2225   // Next pc
2226   int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2227 
2228   // Execute branch delay slot
2229   // We don't check for end_sim_pc. First it should not be met as the current pc
2230   // is valid. Secondly a jump should always execute its branch delay slot.
2231   Instruction* branch_delay_instr =
2232     reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2233   BranchDelayInstructionDecode(branch_delay_instr);
2234 
2235   // Update pc and ra if necessary.
2236   // Do this after the branch delay execution.
2237   if (instr->IsLinkingInstruction()) {
2238     set_register(31, current_pc + 2* Instruction::kInstrSize);
2239   }
2240   set_pc(next_pc);
2241   pc_modified_ = true;
2242 }
2243 
2244 
2245 // Executes the current instruction.
InstructionDecode(Instruction * instr)2246 void Simulator::InstructionDecode(Instruction* instr) {
2247   if (v8::internal::FLAG_check_icache) {
2248     CheckICache(isolate_->simulator_i_cache(), instr);
2249   }
2250   pc_modified_ = false;
2251   if (::v8::internal::FLAG_trace_sim) {
2252     disasm::NameConverter converter;
2253     disasm::Disassembler dasm(converter);
2254     // use a reasonably large buffer
2255     v8::internal::EmbeddedVector<char, 256> buffer;
2256     dasm.InstructionDecode(buffer, reinterpret_cast<byte_*>(instr));
2257     PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr),
2258            buffer.start());
2259   }
2260 
2261   switch (instr->InstructionType()) {
2262     case Instruction::kRegisterType:
2263       DecodeTypeRegister(instr);
2264       break;
2265     case Instruction::kImmediateType:
2266       DecodeTypeImmediate(instr);
2267       break;
2268     case Instruction::kJumpType:
2269       DecodeTypeJump(instr);
2270       break;
2271     default:
2272       UNSUPPORTED();
2273   }
2274   if (!pc_modified_) {
2275     set_register(pc, reinterpret_cast<int32_t>(instr) +
2276                  Instruction::kInstrSize);
2277   }
2278 }
2279 
2280 
2281 
Execute()2282 void Simulator::Execute() {
2283   // Get the PC to simulate. Cannot use the accessor here as we need the
2284   // raw PC value and not the one used as input to arithmetic instructions.
2285   int program_counter = get_pc();
2286   if (::v8::internal::FLAG_stop_sim_at == 0) {
2287     // Fast version of the dispatch loop without checking whether the simulator
2288     // should be stopping at a particular executed instruction.
2289     while (program_counter != end_sim_pc) {
2290       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2291       icount_++;
2292       InstructionDecode(instr);
2293       program_counter = get_pc();
2294     }
2295   } else {
2296     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2297     // we reach the particular instuction count.
2298     while (program_counter != end_sim_pc) {
2299       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2300       icount_++;
2301       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2302         MipsDebugger dbg(this);
2303         dbg.Debug();
2304       } else {
2305         InstructionDecode(instr);
2306       }
2307       program_counter = get_pc();
2308     }
2309   }
2310 }
2311 
2312 
Call(byte_ * entry,int argument_count,...)2313 int32_t Simulator::Call(byte_* entry, int argument_count, ...) {
2314   va_list parameters;
2315   va_start(parameters, argument_count);
2316   // Setup arguments
2317 
2318   // First four arguments passed in registers.
2319   ASSERT(argument_count >= 4);
2320   set_register(a0, va_arg(parameters, int32_t));
2321   set_register(a1, va_arg(parameters, int32_t));
2322   set_register(a2, va_arg(parameters, int32_t));
2323   set_register(a3, va_arg(parameters, int32_t));
2324 
2325   // Remaining arguments passed on stack.
2326   int original_stack = get_register(sp);
2327   // Compute position of stack on entry to generated code.
2328   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
2329                                     - kCArgsSlotsSize);
2330   if (OS::ActivationFrameAlignment() != 0) {
2331     entry_stack &= -OS::ActivationFrameAlignment();
2332   }
2333   // Store remaining arguments on stack, from low to high memory.
2334   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2335   for (int i = 4; i < argument_count; i++) {
2336     stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
2337   }
2338   va_end(parameters);
2339   set_register(sp, entry_stack);
2340 
2341   // Prepare to execute the code at entry
2342   set_register(pc, reinterpret_cast<int32_t>(entry));
2343   // Put down marker for end of simulation. The simulator will stop simulation
2344   // when the PC reaches this value. By saving the "end simulation" value into
2345   // the LR the simulation stops when returning to this call point.
2346   set_register(ra, end_sim_pc);
2347 
2348   // Remember the values of callee-saved registers.
2349   // The code below assumes that r9 is not used as sb (static base) in
2350   // simulator code and therefore is regarded as a callee-saved register.
2351   int32_t s0_val = get_register(s0);
2352   int32_t s1_val = get_register(s1);
2353   int32_t s2_val = get_register(s2);
2354   int32_t s3_val = get_register(s3);
2355   int32_t s4_val = get_register(s4);
2356   int32_t s5_val = get_register(s5);
2357   int32_t s6_val = get_register(s6);
2358   int32_t s7_val = get_register(s7);
2359   int32_t gp_val = get_register(gp);
2360   int32_t sp_val = get_register(sp);
2361   int32_t fp_val = get_register(fp);
2362 
2363   // Setup the callee-saved registers with a known value. To be able to check
2364   // that they are preserved properly across JS execution.
2365   int32_t callee_saved_value = icount_;
2366   set_register(s0, callee_saved_value);
2367   set_register(s1, callee_saved_value);
2368   set_register(s2, callee_saved_value);
2369   set_register(s3, callee_saved_value);
2370   set_register(s4, callee_saved_value);
2371   set_register(s5, callee_saved_value);
2372   set_register(s6, callee_saved_value);
2373   set_register(s7, callee_saved_value);
2374   set_register(gp, callee_saved_value);
2375   set_register(fp, callee_saved_value);
2376 
2377   // Start the simulation
2378   Execute();
2379 
2380   // Check that the callee-saved registers have been preserved.
2381   CHECK_EQ(callee_saved_value, get_register(s0));
2382   CHECK_EQ(callee_saved_value, get_register(s1));
2383   CHECK_EQ(callee_saved_value, get_register(s2));
2384   CHECK_EQ(callee_saved_value, get_register(s3));
2385   CHECK_EQ(callee_saved_value, get_register(s4));
2386   CHECK_EQ(callee_saved_value, get_register(s5));
2387   CHECK_EQ(callee_saved_value, get_register(s6));
2388   CHECK_EQ(callee_saved_value, get_register(s7));
2389   CHECK_EQ(callee_saved_value, get_register(gp));
2390   CHECK_EQ(callee_saved_value, get_register(fp));
2391 
2392   // Restore callee-saved registers with the original value.
2393   set_register(s0, s0_val);
2394   set_register(s1, s1_val);
2395   set_register(s2, s2_val);
2396   set_register(s3, s3_val);
2397   set_register(s4, s4_val);
2398   set_register(s5, s5_val);
2399   set_register(s6, s6_val);
2400   set_register(s7, s7_val);
2401   set_register(gp, gp_val);
2402   set_register(sp, sp_val);
2403   set_register(fp, fp_val);
2404 
2405   // Pop stack passed arguments.
2406   CHECK_EQ(entry_stack, get_register(sp));
2407   set_register(sp, original_stack);
2408 
2409   int32_t result = get_register(v0);
2410   return result;
2411 }
2412 
2413 
PushAddress(uintptr_t address)2414 uintptr_t Simulator::PushAddress(uintptr_t address) {
2415   int new_sp = get_register(sp) - sizeof(uintptr_t);
2416   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2417   *stack_slot = address;
2418   set_register(sp, new_sp);
2419   return new_sp;
2420 }
2421 
2422 
PopAddress()2423 uintptr_t Simulator::PopAddress() {
2424   int current_sp = get_register(sp);
2425   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2426   uintptr_t address = *stack_slot;
2427   set_register(sp, current_sp + sizeof(uintptr_t));
2428   return address;
2429 }
2430 
2431 
2432 #undef UNSUPPORTED
2433 
2434 } }  // namespace v8::internal
2435 
2436 #endif  // USE_SIMULATOR
2437 
2438 #endif  // V8_TARGET_ARCH_MIPS
2439