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