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