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