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