v8  3.11.10(node0.8.26)
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.
2072  {
2073  double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2074  int32_t result = static_cast<int32_t>(rounded);
2075  set_fpu_register(fd_reg, result);
2076  if (set_fcsr_round_error(fs, rounded)) {
2077  set_fpu_register(fd_reg, kFPUInvalidResult);
2078  }
2079  }
2080  break;
2081  case TRUNC_W_D: // Truncate double to word (round towards 0).
2082  {
2083  double rounded = trunc(fs);
2084  int32_t result = static_cast<int32_t>(rounded);
2085  set_fpu_register(fd_reg, result);
2086  if (set_fcsr_round_error(fs, rounded)) {
2087  set_fpu_register(fd_reg, kFPUInvalidResult);
2088  }
2089  }
2090  break;
2091  case FLOOR_W_D: // Round double to word towards negative infinity.
2092  {
2093  double rounded = floor(fs);
2094  int32_t result = static_cast<int32_t>(rounded);
2095  set_fpu_register(fd_reg, result);
2096  if (set_fcsr_round_error(fs, rounded)) {
2097  set_fpu_register(fd_reg, kFPUInvalidResult);
2098  }
2099  }
2100  break;
2101  case CEIL_W_D: // Round double to word towards positive infinity.
2102  {
2103  double rounded = ceil(fs);
2104  int32_t result = static_cast<int32_t>(rounded);
2105  set_fpu_register(fd_reg, result);
2106  if (set_fcsr_round_error(fs, rounded)) {
2107  set_fpu_register(fd_reg, kFPUInvalidResult);
2108  }
2109  }
2110  break;
2111  case CVT_S_D: // Convert double to float (single).
2112  set_fpu_register_float(fd_reg, static_cast<float>(fs));
2113  break;
2114  case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
2115  double rounded = trunc(fs);
2116  i64 = static_cast<int64_t>(rounded);
2117  set_fpu_register(fd_reg, i64 & 0xffffffff);
2118  set_fpu_register(fd_reg + 1, i64 >> 32);
2119  break;
2120  }
2121  case TRUNC_L_D: { // Mips32r2 instruction.
2122  double rounded = trunc(fs);
2123  i64 = static_cast<int64_t>(rounded);
2124  set_fpu_register(fd_reg, i64 & 0xffffffff);
2125  set_fpu_register(fd_reg + 1, i64 >> 32);
2126  break;
2127  }
2128  case ROUND_L_D: { // Mips32r2 instruction.
2129  double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2130  i64 = static_cast<int64_t>(rounded);
2131  set_fpu_register(fd_reg, i64 & 0xffffffff);
2132  set_fpu_register(fd_reg + 1, i64 >> 32);
2133  break;
2134  }
2135  case FLOOR_L_D: // Mips32r2 instruction.
2136  i64 = static_cast<int64_t>(floor(fs));
2137  set_fpu_register(fd_reg, i64 & 0xffffffff);
2138  set_fpu_register(fd_reg + 1, i64 >> 32);
2139  break;
2140  case CEIL_L_D: // Mips32r2 instruction.
2141  i64 = static_cast<int64_t>(ceil(fs));
2142  set_fpu_register(fd_reg, i64 & 0xffffffff);
2143  set_fpu_register(fd_reg + 1, i64 >> 32);
2144  break;
2145  case C_F_D:
2147  break;
2148  default:
2149  UNREACHABLE();
2150  }
2151  break;
2152  case W:
2153  switch (instr->FunctionFieldRaw()) {
2154  case CVT_S_W: // Convert word to float (single).
2155  alu_out = get_fpu_register(fs_reg);
2156  set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2157  break;
2158  case CVT_D_W: // Convert word to double.
2159  alu_out = get_fpu_register(fs_reg);
2160  set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2161  break;
2162  default:
2163  UNREACHABLE();
2164  };
2165  break;
2166  case L:
2167  switch (instr->FunctionFieldRaw()) {
2168  case CVT_D_L: // Mips32r2 instruction.
2169  // Watch the signs here, we want 2 32-bit vals
2170  // to make a sign-64.
2171  i64 = (uint32_t) get_fpu_register(fs_reg);
2172  i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
2173  set_fpu_register_double(fd_reg, static_cast<double>(i64));
2174  break;
2175  case CVT_S_L:
2177  break;
2178  default:
2179  UNREACHABLE();
2180  }
2181  break;
2182  case PS:
2183  break;
2184  default:
2185  UNREACHABLE();
2186  };
2187  break;
2188  case SPECIAL:
2189  switch (instr->FunctionFieldRaw()) {
2190  case JR: {
2191  Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2192  current_pc+Instruction::kInstrSize);
2193  BranchDelayInstructionDecode(branch_delay_instr);
2194  set_pc(next_pc);
2195  pc_modified_ = true;
2196  break;
2197  }
2198  case JALR: {
2199  Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2200  current_pc+Instruction::kInstrSize);
2201  BranchDelayInstructionDecode(branch_delay_instr);
2202  set_register(31, current_pc + 2 * Instruction::kInstrSize);
2203  set_pc(next_pc);
2204  pc_modified_ = true;
2205  break;
2206  }
2207  // Instructions using HI and LO registers.
2208  case MULT:
2209  set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2210  set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2211  break;
2212  case MULTU:
2213  set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2214  set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2215  break;
2216  case DIV:
2217  // Divide by zero was not checked in the configuration step - div and
2218  // divu do not raise exceptions. On division by 0, the result will
2219  // be UNPREDICTABLE.
2220  if (rt != 0) {
2221  set_register(LO, rs / rt);
2222  set_register(HI, rs % rt);
2223  }
2224  break;
2225  case DIVU:
2226  if (rt_u != 0) {
2227  set_register(LO, rs_u / rt_u);
2228  set_register(HI, rs_u % rt_u);
2229  }
2230  break;
2231  // Break and trap instructions.
2232  case BREAK:
2233  case TGE:
2234  case TGEU:
2235  case TLT:
2236  case TLTU:
2237  case TEQ:
2238  case TNE:
2239  if (do_interrupt) {
2240  SoftwareInterrupt(instr);
2241  }
2242  break;
2243  // Conditional moves.
2244  case MOVN:
2245  if (rt) set_register(rd_reg, rs);
2246  break;
2247  case MOVCI: {
2248  uint32_t cc = instr->FBccValue();
2249  uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2250  if (instr->Bit(16)) { // Read Tf bit.
2251  if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2252  } else {
2253  if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2254  }
2255  break;
2256  }
2257  case MOVZ:
2258  if (!rt) set_register(rd_reg, rs);
2259  break;
2260  default: // For other special opcodes we do the default operation.
2261  set_register(rd_reg, alu_out);
2262  };
2263  break;
2264  case SPECIAL2:
2265  switch (instr->FunctionFieldRaw()) {
2266  case MUL:
2267  set_register(rd_reg, alu_out);
2268  // HI and LO are UNPREDICTABLE after the operation.
2269  set_register(LO, Unpredictable);
2270  set_register(HI, Unpredictable);
2271  break;
2272  default: // For other special2 opcodes we do the default operation.
2273  set_register(rd_reg, alu_out);
2274  }
2275  break;
2276  case SPECIAL3:
2277  switch (instr->FunctionFieldRaw()) {
2278  case INS:
2279  // Ins instr leaves result in Rt, rather than Rd.
2280  set_register(rt_reg, alu_out);
2281  break;
2282  case EXT:
2283  // Ext instr leaves result in Rt, rather than Rd.
2284  set_register(rt_reg, alu_out);
2285  break;
2286  default:
2287  UNREACHABLE();
2288  };
2289  break;
2290  // Unimplemented opcodes raised an error in the configuration step before,
2291  // so we can use the default here to set the destination register in common
2292  // cases.
2293  default:
2294  set_register(rd_reg, alu_out);
2295  };
2296 }
2297 
2298 
2299 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
2300 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2301  // Instruction fields.
2302  Opcode op = instr->OpcodeFieldRaw();
2303  int32_t rs = get_register(instr->RsValue());
2304  uint32_t rs_u = static_cast<uint32_t>(rs);
2305  int32_t rt_reg = instr->RtValue(); // Destination register.
2306  int32_t rt = get_register(rt_reg);
2307  int16_t imm16 = instr->Imm16Value();
2308 
2309  int32_t ft_reg = instr->FtValue(); // Destination register.
2310 
2311  // Zero extended immediate.
2312  uint32_t oe_imm16 = 0xffff & imm16;
2313  // Sign extended immediate.
2314  int32_t se_imm16 = imm16;
2315 
2316  // Get current pc.
2317  int32_t current_pc = get_pc();
2318  // Next pc.
2319  int32_t next_pc = bad_ra;
2320 
2321  // Used for conditional branch instructions.
2322  bool do_branch = false;
2323  bool execute_branch_delay_instruction = false;
2324 
2325  // Used for arithmetic instructions.
2326  int32_t alu_out = 0;
2327  // Floating point.
2328  double fp_out = 0.0;
2329  uint32_t cc, cc_value, fcsr_cc;
2330 
2331  // Used for memory instructions.
2332  int32_t addr = 0x0;
2333  // Value to be written in memory.
2334  uint32_t mem_value = 0x0;
2335 
2336  // ---------- Configuration (and execution for REGIMM).
2337  switch (op) {
2338  // ------------- COP1. Coprocessor instructions.
2339  case COP1:
2340  switch (instr->RsFieldRaw()) {
2341  case BC1: // Branch on coprocessor condition.
2342  cc = instr->FBccValue();
2343  fcsr_cc = get_fcsr_condition_bit(cc);
2344  cc_value = test_fcsr_bit(fcsr_cc);
2345  do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2346  execute_branch_delay_instruction = true;
2347  // Set next_pc.
2348  if (do_branch) {
2349  next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2350  } else {
2351  next_pc = current_pc + kBranchReturnOffset;
2352  }
2353  break;
2354  default:
2355  UNREACHABLE();
2356  };
2357  break;
2358  // ------------- REGIMM class.
2359  case REGIMM:
2360  switch (instr->RtFieldRaw()) {
2361  case BLTZ:
2362  do_branch = (rs < 0);
2363  break;
2364  case BLTZAL:
2365  do_branch = rs < 0;
2366  break;
2367  case BGEZ:
2368  do_branch = rs >= 0;
2369  break;
2370  case BGEZAL:
2371  do_branch = rs >= 0;
2372  break;
2373  default:
2374  UNREACHABLE();
2375  };
2376  switch (instr->RtFieldRaw()) {
2377  case BLTZ:
2378  case BLTZAL:
2379  case BGEZ:
2380  case BGEZAL:
2381  // Branch instructions common part.
2382  execute_branch_delay_instruction = true;
2383  // Set next_pc.
2384  if (do_branch) {
2385  next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2386  if (instr->IsLinkingInstruction()) {
2387  set_register(31, current_pc + kBranchReturnOffset);
2388  }
2389  } else {
2390  next_pc = current_pc + kBranchReturnOffset;
2391  }
2392  default:
2393  break;
2394  };
2395  break; // case REGIMM.
2396  // ------------- Branch instructions.
2397  // When comparing to zero, the encoding of rt field is always 0, so we don't
2398  // need to replace rt with zero.
2399  case BEQ:
2400  do_branch = (rs == rt);
2401  break;
2402  case BNE:
2403  do_branch = rs != rt;
2404  break;
2405  case BLEZ:
2406  do_branch = rs <= 0;
2407  break;
2408  case BGTZ:
2409  do_branch = rs > 0;
2410  break;
2411  // ------------- Arithmetic instructions.
2412  case ADDI:
2413  if (HaveSameSign(rs, se_imm16)) {
2414  if (rs > 0) {
2415  exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2416  } else if (rs < 0) {
2417  exceptions[kIntegerUnderflow] =
2418  rs < (Registers::kMinValue - se_imm16);
2419  }
2420  }
2421  alu_out = rs + se_imm16;
2422  break;
2423  case ADDIU:
2424  alu_out = rs + se_imm16;
2425  break;
2426  case SLTI:
2427  alu_out = (rs < se_imm16) ? 1 : 0;
2428  break;
2429  case SLTIU:
2430  alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2431  break;
2432  case ANDI:
2433  alu_out = rs & oe_imm16;
2434  break;
2435  case ORI:
2436  alu_out = rs | oe_imm16;
2437  break;
2438  case XORI:
2439  alu_out = rs ^ oe_imm16;
2440  break;
2441  case LUI:
2442  alu_out = (oe_imm16 << 16);
2443  break;
2444  // ------------- Memory instructions.
2445  case LB:
2446  addr = rs + se_imm16;
2447  alu_out = ReadB(addr);
2448  break;
2449  case LH:
2450  addr = rs + se_imm16;
2451  alu_out = ReadH(addr, instr);
2452  break;
2453  case LWL: {
2454  // al_offset is offset of the effective address within an aligned word.
2455  uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2456  uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2457  uint32_t mask = (1 << byte_shift * 8) - 1;
2458  addr = rs + se_imm16 - al_offset;
2459  alu_out = ReadW(addr, instr);
2460  alu_out <<= byte_shift * 8;
2461  alu_out |= rt & mask;
2462  break;
2463  }
2464  case LW:
2465  addr = rs + se_imm16;
2466  alu_out = ReadW(addr, instr);
2467  break;
2468  case LBU:
2469  addr = rs + se_imm16;
2470  alu_out = ReadBU(addr);
2471  break;
2472  case LHU:
2473  addr = rs + se_imm16;
2474  alu_out = ReadHU(addr, instr);
2475  break;
2476  case LWR: {
2477  // al_offset is offset of the effective address within an aligned word.
2478  uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2479  uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2480  uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2481  addr = rs + se_imm16 - al_offset;
2482  alu_out = ReadW(addr, instr);
2483  alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2484  alu_out |= rt & mask;
2485  break;
2486  }
2487  case SB:
2488  addr = rs + se_imm16;
2489  break;
2490  case SH:
2491  addr = rs + se_imm16;
2492  break;
2493  case SWL: {
2494  uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2495  uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2496  uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2497  addr = rs + se_imm16 - al_offset;
2498  mem_value = ReadW(addr, instr) & mask;
2499  mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2500  break;
2501  }
2502  case SW:
2503  addr = rs + se_imm16;
2504  break;
2505  case SWR: {
2506  uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2507  uint32_t mask = (1 << al_offset * 8) - 1;
2508  addr = rs + se_imm16 - al_offset;
2509  mem_value = ReadW(addr, instr);
2510  mem_value = (rt << al_offset * 8) | (mem_value & mask);
2511  break;
2512  }
2513  case LWC1:
2514  addr = rs + se_imm16;
2515  alu_out = ReadW(addr, instr);
2516  break;
2517  case LDC1:
2518  addr = rs + se_imm16;
2519  fp_out = ReadD(addr, instr);
2520  break;
2521  case SWC1:
2522  case SDC1:
2523  addr = rs + se_imm16;
2524  break;
2525  default:
2526  UNREACHABLE();
2527  };
2528 
2529  // ---------- Raise exceptions triggered.
2530  SignalExceptions();
2531 
2532  // ---------- Execution.
2533  switch (op) {
2534  // ------------- Branch instructions.
2535  case BEQ:
2536  case BNE:
2537  case BLEZ:
2538  case BGTZ:
2539  // Branch instructions common part.
2540  execute_branch_delay_instruction = true;
2541  // Set next_pc.
2542  if (do_branch) {
2543  next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2544  if (instr->IsLinkingInstruction()) {
2545  set_register(31, current_pc + 2* Instruction::kInstrSize);
2546  }
2547  } else {
2548  next_pc = current_pc + 2 * Instruction::kInstrSize;
2549  }
2550  break;
2551  // ------------- Arithmetic instructions.
2552  case ADDI:
2553  case ADDIU:
2554  case SLTI:
2555  case SLTIU:
2556  case ANDI:
2557  case ORI:
2558  case XORI:
2559  case LUI:
2560  set_register(rt_reg, alu_out);
2561  break;
2562  // ------------- Memory instructions.
2563  case LB:
2564  case LH:
2565  case LWL:
2566  case LW:
2567  case LBU:
2568  case LHU:
2569  case LWR:
2570  set_register(rt_reg, alu_out);
2571  break;
2572  case SB:
2573  WriteB(addr, static_cast<int8_t>(rt));
2574  break;
2575  case SH:
2576  WriteH(addr, static_cast<uint16_t>(rt), instr);
2577  break;
2578  case SWL:
2579  WriteW(addr, mem_value, instr);
2580  break;
2581  case SW:
2582  WriteW(addr, rt, instr);
2583  break;
2584  case SWR:
2585  WriteW(addr, mem_value, instr);
2586  break;
2587  case LWC1:
2588  set_fpu_register(ft_reg, alu_out);
2589  break;
2590  case LDC1:
2591  set_fpu_register_double(ft_reg, fp_out);
2592  break;
2593  case SWC1:
2594  addr = rs + se_imm16;
2595  WriteW(addr, get_fpu_register(ft_reg), instr);
2596  break;
2597  case SDC1:
2598  addr = rs + se_imm16;
2599  WriteD(addr, get_fpu_register_double(ft_reg), instr);
2600  break;
2601  default:
2602  break;
2603  };
2604 
2605 
2606  if (execute_branch_delay_instruction) {
2607  // Execute branch delay slot
2608  // We don't check for end_sim_pc. First it should not be met as the current
2609  // pc is valid. Secondly a jump should always execute its branch delay slot.
2610  Instruction* branch_delay_instr =
2611  reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2612  BranchDelayInstructionDecode(branch_delay_instr);
2613  }
2614 
2615  // If needed update pc after the branch delay execution.
2616  if (next_pc != bad_ra) {
2617  set_pc(next_pc);
2618  }
2619 }
2620 
2621 
2622 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
2623 void Simulator::DecodeTypeJump(Instruction* instr) {
2624  // Get current pc.
2625  int32_t current_pc = get_pc();
2626  // Get unchanged bits of pc.
2627  int32_t pc_high_bits = current_pc & 0xf0000000;
2628  // Next pc.
2629  int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2630 
2631  // Execute branch delay slot.
2632  // We don't check for end_sim_pc. First it should not be met as the current pc
2633  // is valid. Secondly a jump should always execute its branch delay slot.
2634  Instruction* branch_delay_instr =
2635  reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2636  BranchDelayInstructionDecode(branch_delay_instr);
2637 
2638  // Update pc and ra if necessary.
2639  // Do this after the branch delay execution.
2640  if (instr->IsLinkingInstruction()) {
2641  set_register(31, current_pc + 2 * Instruction::kInstrSize);
2642  }
2643  set_pc(next_pc);
2644  pc_modified_ = true;
2645 }
2646 
2647 
2648 // Executes the current instruction.
2649 void Simulator::InstructionDecode(Instruction* instr) {
2650  if (v8::internal::FLAG_check_icache) {
2651  CheckICache(isolate_->simulator_i_cache(), instr);
2652  }
2653  pc_modified_ = false;
2654  if (::v8::internal::FLAG_trace_sim) {
2655  disasm::NameConverter converter;
2656  disasm::Disassembler dasm(converter);
2657  // Use a reasonably large buffer.
2659  dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2660  PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2661  buffer.start());
2662  }
2663 
2664  switch (instr->InstructionType()) {
2666  DecodeTypeRegister(instr);
2667  break;
2669  DecodeTypeImmediate(instr);
2670  break;
2672  DecodeTypeJump(instr);
2673  break;
2674  default:
2675  UNSUPPORTED();
2676  }
2677  if (!pc_modified_) {
2678  set_register(pc, reinterpret_cast<int32_t>(instr) +
2680  }
2681 }
2682 
2683 
2684 
2685 void Simulator::Execute() {
2686  // Get the PC to simulate. Cannot use the accessor here as we need the
2687  // raw PC value and not the one used as input to arithmetic instructions.
2688  int program_counter = get_pc();
2689  if (::v8::internal::FLAG_stop_sim_at == 0) {
2690  // Fast version of the dispatch loop without checking whether the simulator
2691  // should be stopping at a particular executed instruction.
2692  while (program_counter != end_sim_pc) {
2693  Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2694  icount_++;
2695  InstructionDecode(instr);
2696  program_counter = get_pc();
2697  }
2698  } else {
2699  // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2700  // we reach the particular instuction count.
2701  while (program_counter != end_sim_pc) {
2702  Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2703  icount_++;
2704  if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2705  MipsDebugger dbg(this);
2706  dbg.Debug();
2707  } else {
2708  InstructionDecode(instr);
2709  }
2710  program_counter = get_pc();
2711  }
2712  }
2713 }
2714 
2715 
2716 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2717  va_list parameters;
2718  va_start(parameters, argument_count);
2719  // Set up arguments.
2720 
2721  // First four arguments passed in registers.
2722  ASSERT(argument_count >= 4);
2723  set_register(a0, va_arg(parameters, int32_t));
2724  set_register(a1, va_arg(parameters, int32_t));
2725  set_register(a2, va_arg(parameters, int32_t));
2726  set_register(a3, va_arg(parameters, int32_t));
2727 
2728  // Remaining arguments passed on stack.
2729  int original_stack = get_register(sp);
2730  // Compute position of stack on entry to generated code.
2731  int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
2732  - kCArgsSlotsSize);
2733  if (OS::ActivationFrameAlignment() != 0) {
2734  entry_stack &= -OS::ActivationFrameAlignment();
2735  }
2736  // Store remaining arguments on stack, from low to high memory.
2737  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2738  for (int i = 4; i < argument_count; i++) {
2739  stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t);
2740  }
2741  va_end(parameters);
2742  set_register(sp, entry_stack);
2743 
2744  // Prepare to execute the code at entry.
2745  set_register(pc, reinterpret_cast<int32_t>(entry));
2746  // Put down marker for end of simulation. The simulator will stop simulation
2747  // when the PC reaches this value. By saving the "end simulation" value into
2748  // the LR the simulation stops when returning to this call point.
2749  set_register(ra, end_sim_pc);
2750 
2751  // Remember the values of callee-saved registers.
2752  // The code below assumes that r9 is not used as sb (static base) in
2753  // simulator code and therefore is regarded as a callee-saved register.
2754  int32_t s0_val = get_register(s0);
2755  int32_t s1_val = get_register(s1);
2756  int32_t s2_val = get_register(s2);
2757  int32_t s3_val = get_register(s3);
2758  int32_t s4_val = get_register(s4);
2759  int32_t s5_val = get_register(s5);
2760  int32_t s6_val = get_register(s6);
2761  int32_t s7_val = get_register(s7);
2762  int32_t gp_val = get_register(gp);
2763  int32_t sp_val = get_register(sp);
2764  int32_t fp_val = get_register(fp);
2765 
2766  // Set up the callee-saved registers with a known value. To be able to check
2767  // that they are preserved properly across JS execution.
2768  int32_t callee_saved_value = icount_;
2769  set_register(s0, callee_saved_value);
2770  set_register(s1, callee_saved_value);
2771  set_register(s2, callee_saved_value);
2772  set_register(s3, callee_saved_value);
2773  set_register(s4, callee_saved_value);
2774  set_register(s5, callee_saved_value);
2775  set_register(s6, callee_saved_value);
2776  set_register(s7, callee_saved_value);
2777  set_register(gp, callee_saved_value);
2778  set_register(fp, callee_saved_value);
2779 
2780  // Start the simulation.
2781  Execute();
2782 
2783  // Check that the callee-saved registers have been preserved.
2784  CHECK_EQ(callee_saved_value, get_register(s0));
2785  CHECK_EQ(callee_saved_value, get_register(s1));
2786  CHECK_EQ(callee_saved_value, get_register(s2));
2787  CHECK_EQ(callee_saved_value, get_register(s3));
2788  CHECK_EQ(callee_saved_value, get_register(s4));
2789  CHECK_EQ(callee_saved_value, get_register(s5));
2790  CHECK_EQ(callee_saved_value, get_register(s6));
2791  CHECK_EQ(callee_saved_value, get_register(s7));
2792  CHECK_EQ(callee_saved_value, get_register(gp));
2793  CHECK_EQ(callee_saved_value, get_register(fp));
2794 
2795  // Restore callee-saved registers with the original value.
2796  set_register(s0, s0_val);
2797  set_register(s1, s1_val);
2798  set_register(s2, s2_val);
2799  set_register(s3, s3_val);
2800  set_register(s4, s4_val);
2801  set_register(s5, s5_val);
2802  set_register(s6, s6_val);
2803  set_register(s7, s7_val);
2804  set_register(gp, gp_val);
2805  set_register(sp, sp_val);
2806  set_register(fp, fp_val);
2807 
2808  // Pop stack passed arguments.
2809  CHECK_EQ(entry_stack, get_register(sp));
2810  set_register(sp, original_stack);
2811 
2812  int32_t result = get_register(v0);
2813  return result;
2814 }
2815 
2816 
2817 uintptr_t Simulator::PushAddress(uintptr_t address) {
2818  int new_sp = get_register(sp) - sizeof(uintptr_t);
2819  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2820  *stack_slot = address;
2821  set_register(sp, new_sp);
2822  return new_sp;
2823 }
2824 
2825 
2826 uintptr_t Simulator::PopAddress() {
2827  int current_sp = get_register(sp);
2828  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2829  uintptr_t address = *stack_slot;
2830  set_register(sp, current_sp + sizeof(uintptr_t));
2831  return address;
2832 }
2833 
2834 
2835 #undef UNSUPPORTED
2836 
2837 } } // namespace v8::internal
2838 
2839 #endif // USE_SIMULATOR
2840 
2841 #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:204
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
FlagType type_
Definition: flags.cc:1351
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:61
int isnan(double x)
const SwVfpRegister s6
const int kNumFPURegisters
uint8_t byte
Definition: globals.h:171
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:389
const Instr rtCallRedirInstr
const uint32_t kFPUInvalidResult
static int Number(const char *name)
#define OFFSET_OF(type, field)
Definition: globals.h:287
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:130
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:112
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
const SwVfpRegister s4
static int ActivationFrameAlignment()
const FPURegister f12
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:307
const FPURegister f14
FlagType type() const
Definition: flags.cc:1358
int isfinite(double x)
static const int32_t kMinValue
const FPURegister f13