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