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