1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #if V8_TARGET_ARCH_MIPS
38 #include "assembler.h"
39 #include "globals.h" // Need the BitCast.
40 #include "mips/constants-mips.h"
41 #include "mips/simulator-mips.h"
44 // Only build the simulator if not compiling for real MIPS hardware.
45 #if defined(USE_SIMULATOR)
51 bool HaveSameSign(int32_t a, int32_t b) {
52 return ((a ^ b) >= 0);
56 uint32_t get_fcsr_condition_bit(uint32_t cc) {
65 // This macro provides a platform independent use of sscanf. The reason for
66 // SScanF not being implemented in a platform independent was through
67 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
68 // Library does not provide vsscanf.
69 #define SScanF sscanf // NOLINT
71 // The MipsDebugger class is used by the simulator while debugging simulated
75 explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
78 void Stop(Instruction* instr);
80 // Print all registers with a nice formatting.
82 void PrintAllRegsIncludingFPU();
85 // We set the breakpoint code to 0xfffff to easily recognize it.
86 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
87 static const Instr kNopInstr = 0x0;
91 int32_t GetRegisterValue(int regnum);
92 int32_t GetFPURegisterValueInt(int regnum);
93 int64_t GetFPURegisterValueLong(int regnum);
94 float GetFPURegisterValueFloat(int regnum);
95 double GetFPURegisterValueDouble(int regnum);
96 bool GetValue(const char* desc, int32_t* value);
98 // Set or delete a breakpoint. Returns true if successful.
99 bool SetBreakpoint(Instruction* breakpc);
100 bool DeleteBreakpoint(Instruction* breakpc);
102 // Undo and redo all breakpoints. This is needed to bracket disassembly and
103 // execution to skip past breakpoints when run from the debugger.
104 void UndoBreakpoints();
105 void RedoBreakpoints();
109 MipsDebugger::~MipsDebugger() {
113 #ifdef GENERATED_CODE_COVERAGE
114 static FILE* coverage_log = NULL;
117 static void InitializeCoverage() {
118 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
119 if (file_name != NULL) {
120 coverage_log = fopen(file_name, "aw+");
125 void MipsDebugger::Stop(Instruction* instr) {
126 // Get the stop code.
127 uint32_t code = instr->Bits(25, 6);
128 // Retrieve the encoded address, which comes just after this stop.
130 reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
131 char* msg = *msg_address;
134 // Update this stop description.
135 if (!watched_stops_[code].desc) {
136 watched_stops_[code].desc = msg;
139 if (strlen(msg) > 0) {
140 if (coverage_log != NULL) {
141 fprintf(coverage_log, "%s\n", str);
142 fflush(coverage_log);
144 // Overwrite the instruction and address with nops.
145 instr->SetInstructionBits(kNopInstr);
146 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
148 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize);
152 #else // GENERATED_CODE_COVERAGE
154 #define UNSUPPORTED() printf("Unsupported instruction.\n");
156 static void InitializeCoverage() {}
159 void MipsDebugger::Stop(Instruction* instr) {
160 // Get the stop code.
161 uint32_t code = instr->Bits(25, 6);
162 // Retrieve the encoded address, which comes just after this stop.
163 char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
164 Instruction::kInstrSize);
165 // Update this stop description.
166 if (!sim_->watched_stops_[code].desc) {
167 sim_->watched_stops_[code].desc = msg;
169 PrintF("Simulator hit %s (%u)\n", msg, code);
170 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
173 #endif // GENERATED_CODE_COVERAGE
176 int32_t MipsDebugger::GetRegisterValue(int regnum) {
177 if (regnum == kNumSimuRegisters) {
178 return sim_->get_pc();
180 return sim_->get_register(regnum);
185 int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
186 if (regnum == kNumFPURegisters) {
187 return sim_->get_pc();
189 return sim_->get_fpu_register(regnum);
194 int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
195 if (regnum == kNumFPURegisters) {
196 return sim_->get_pc();
198 return sim_->get_fpu_register_long(regnum);
203 float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
204 if (regnum == kNumFPURegisters) {
205 return sim_->get_pc();
207 return sim_->get_fpu_register_float(regnum);
212 double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
213 if (regnum == kNumFPURegisters) {
214 return sim_->get_pc();
216 return sim_->get_fpu_register_double(regnum);
221 bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
222 int regnum = Registers::Number(desc);
223 int fpuregnum = FPURegisters::Number(desc);
225 if (regnum != kInvalidRegister) {
226 *value = GetRegisterValue(regnum);
228 } else if (fpuregnum != kInvalidFPURegister) {
229 *value = GetFPURegisterValueInt(fpuregnum);
231 } else if (strncmp(desc, "0x", 2) == 0) {
232 return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
234 return SScanF(desc, "%i", value) == 1;
240 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
241 // Check if a breakpoint can be set. If not return without any side-effects.
242 if (sim_->break_pc_ != NULL) {
246 // Set the breakpoint.
247 sim_->break_pc_ = breakpc;
248 sim_->break_instr_ = breakpc->InstructionBits();
249 // Not setting the breakpoint instruction in the code itself. It will be set
250 // when the debugger shell continues.
255 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
256 if (sim_->break_pc_ != NULL) {
257 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
260 sim_->break_pc_ = NULL;
261 sim_->break_instr_ = 0;
266 void MipsDebugger::UndoBreakpoints() {
267 if (sim_->break_pc_ != NULL) {
268 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
273 void MipsDebugger::RedoBreakpoints() {
274 if (sim_->break_pc_ != NULL) {
275 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
280 void MipsDebugger::PrintAllRegs() {
281 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
285 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
286 REG_INFO(1), REG_INFO(2), REG_INFO(4));
288 PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
289 "", REG_INFO(3), REG_INFO(5));
291 PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
293 PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
296 for (int i = 0; i < 8; i++) {
297 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
298 REG_INFO(8+i), REG_INFO(16+i));
302 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
303 REG_INFO(24), REG_INFO(26), REG_INFO(32));
305 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
306 REG_INFO(25), REG_INFO(27), REG_INFO(33));
308 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
309 REG_INFO(29), REG_INFO(30), REG_INFO(28));
311 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
312 REG_INFO(31), REG_INFO(34));
319 void MipsDebugger::PrintAllRegsIncludingFPU() {
320 #define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
321 GetFPURegisterValueInt(n+1), \
322 GetFPURegisterValueInt(n), \
323 GetFPURegisterValueDouble(n)
328 // f0, f1, f2, ... f31.
329 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
330 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
331 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
332 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
333 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
334 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
335 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
336 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
337 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
338 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
339 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
340 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
341 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
342 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
343 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
344 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
351 void MipsDebugger::Debug() {
352 intptr_t last_pc = -1;
355 #define COMMAND_SIZE 63
359 #define XSTR(a) STR(a)
361 char cmd[COMMAND_SIZE + 1];
362 char arg1[ARG_SIZE + 1];
363 char arg2[ARG_SIZE + 1];
364 char* argv[3] = { cmd, arg1, arg2 };
366 // Make sure to have a proper terminating character if reaching the limit.
367 cmd[COMMAND_SIZE] = 0;
371 // Undo all set breakpoints while running in the debugger shell. This will
372 // make them invisible to all commands.
375 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
376 if (last_pc != sim_->get_pc()) {
377 disasm::NameConverter converter;
378 disasm::Disassembler dasm(converter);
379 // Use a reasonably large buffer.
380 v8::internal::EmbeddedVector<char, 256> buffer;
381 dasm.InstructionDecode(buffer,
382 reinterpret_cast<byte*>(sim_->get_pc()));
383 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
384 last_pc = sim_->get_pc();
386 char* line = ReadLine("sim> ");
390 char* last_input = sim_->last_debugger_input();
391 if (strcmp(line, "\n") == 0 && last_input != NULL) {
394 // Ownership is transferred to sim_;
395 sim_->set_last_debugger_input(line);
397 // Use sscanf to parse the individual parts of the command line. At the
398 // moment no command expects more than two parameters.
399 int argc = SScanF(line,
400 "%" XSTR(COMMAND_SIZE) "s "
401 "%" XSTR(ARG_SIZE) "s "
402 "%" XSTR(ARG_SIZE) "s",
404 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
405 Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
406 if (!(instr->IsTrap()) ||
407 instr->InstructionBits() == rtCallRedirInstr) {
408 sim_->InstructionDecode(
409 reinterpret_cast<Instruction*>(sim_->get_pc()));
411 // Allow si to jump over generated breakpoints.
412 PrintF("/!\\ Jumping over generated breakpoint.\n");
413 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
415 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
416 // Execute the one instruction we broke at with breakpoints disabled.
417 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
418 // Leave the debugger shell.
420 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
424 if (strcmp(arg1, "all") == 0) {
426 } else if (strcmp(arg1, "allf") == 0) {
427 PrintAllRegsIncludingFPU();
429 int regnum = Registers::Number(arg1);
430 int fpuregnum = FPURegisters::Number(arg1);
432 if (regnum != kInvalidRegister) {
433 value = GetRegisterValue(regnum);
434 PrintF("%s: 0x%08x %d \n", arg1, value, value);
435 } else if (fpuregnum != kInvalidFPURegister) {
436 if (fpuregnum % 2 == 1) {
437 value = GetFPURegisterValueInt(fpuregnum);
438 fvalue = GetFPURegisterValueFloat(fpuregnum);
439 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
442 int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
443 int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
444 dfvalue = GetFPURegisterValueDouble(fpuregnum);
445 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
446 FPURegisters::Name(fpuregnum+1),
447 FPURegisters::Name(fpuregnum),
453 PrintF("%s unrecognized\n", arg1);
458 if (strcmp(arg2, "single") == 0) {
461 int fpuregnum = FPURegisters::Number(arg1);
463 if (fpuregnum != kInvalidFPURegister) {
464 value = GetFPURegisterValueInt(fpuregnum);
465 fvalue = GetFPURegisterValueFloat(fpuregnum);
466 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
468 PrintF("%s unrecognized\n", arg1);
471 PrintF("print <fpu register> single\n");
474 PrintF("print <register> or print <fpu register> single\n");
477 } else if ((strcmp(cmd, "po") == 0)
478 || (strcmp(cmd, "printobject") == 0)) {
481 if (GetValue(arg1, &value)) {
482 Object* obj = reinterpret_cast<Object*>(value);
483 PrintF("%s: \n", arg1);
491 PrintF("%s unrecognized\n", arg1);
494 PrintF("printobject <value>\n");
496 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
501 if (strcmp(cmd, "stack") == 0) {
502 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
503 } else { // Command "mem".
505 if (!GetValue(arg1, &value)) {
506 PrintF("%s unrecognized\n", arg1);
509 cur = reinterpret_cast<int32_t*>(value);
514 if (argc == next_arg) {
517 if (!GetValue(argv[next_arg], &words)) {
524 PrintF(" 0x%08x: 0x%08x %10d",
525 reinterpret_cast<intptr_t>(cur), *cur, *cur);
526 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
528 Heap* current_heap = v8::internal::Isolate::Current()->heap();
529 if (((value & 1) == 0) || current_heap->Contains(obj)) {
531 if ((value & 1) == 0) {
532 PrintF("smi %d", value / 2);
542 } else if ((strcmp(cmd, "disasm") == 0) ||
543 (strcmp(cmd, "dpc") == 0) ||
544 (strcmp(cmd, "di") == 0)) {
545 disasm::NameConverter converter;
546 disasm::Disassembler dasm(converter);
547 // Use a reasonably large buffer.
548 v8::internal::EmbeddedVector<char, 256> buffer;
554 cur = reinterpret_cast<byte*>(sim_->get_pc());
555 end = cur + (10 * Instruction::kInstrSize);
556 } else if (argc == 2) {
557 int regnum = Registers::Number(arg1);
558 if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
559 // The argument is an address or a register name.
561 if (GetValue(arg1, &value)) {
562 cur = reinterpret_cast<byte*>(value);
563 // Disassemble 10 instructions at <arg1>.
564 end = cur + (10 * Instruction::kInstrSize);
567 // The argument is the number of instructions.
569 if (GetValue(arg1, &value)) {
570 cur = reinterpret_cast<byte*>(sim_->get_pc());
571 // Disassemble <arg1> instructions.
572 end = cur + (value * Instruction::kInstrSize);
578 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
579 cur = reinterpret_cast<byte*>(value1);
580 end = cur + (value2 * Instruction::kInstrSize);
585 dasm.InstructionDecode(buffer, cur);
586 PrintF(" 0x%08x %s\n",
587 reinterpret_cast<intptr_t>(cur), buffer.start());
588 cur += Instruction::kInstrSize;
590 } else if (strcmp(cmd, "gdb") == 0) {
591 PrintF("relinquishing control to gdb\n");
592 v8::internal::OS::DebugBreak();
593 PrintF("regaining control from gdb\n");
594 } else if (strcmp(cmd, "break") == 0) {
597 if (GetValue(arg1, &value)) {
598 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
599 PrintF("setting breakpoint failed\n");
602 PrintF("%s unrecognized\n", arg1);
605 PrintF("break <address>\n");
607 } else if (strcmp(cmd, "del") == 0) {
608 if (!DeleteBreakpoint(NULL)) {
609 PrintF("deleting breakpoint failed\n");
611 } else if (strcmp(cmd, "flags") == 0) {
612 PrintF("No flags on MIPS !\n");
613 } else if (strcmp(cmd, "stop") == 0) {
615 intptr_t stop_pc = sim_->get_pc() -
616 2 * Instruction::kInstrSize;
617 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
618 Instruction* msg_address =
619 reinterpret_cast<Instruction*>(stop_pc +
620 Instruction::kInstrSize);
621 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
622 // Remove the current stop.
623 if (sim_->IsStopInstruction(stop_instr)) {
624 stop_instr->SetInstructionBits(kNopInstr);
625 msg_address->SetInstructionBits(kNopInstr);
627 PrintF("Not at debugger stop.\n");
629 } else if (argc == 3) {
630 // Print information about all/the specified breakpoint(s).
631 if (strcmp(arg1, "info") == 0) {
632 if (strcmp(arg2, "all") == 0) {
633 PrintF("Stop information:\n");
634 for (uint32_t i = kMaxWatchpointCode + 1;
637 sim_->PrintStopInfo(i);
639 } else if (GetValue(arg2, &value)) {
640 sim_->PrintStopInfo(value);
642 PrintF("Unrecognized argument.\n");
644 } else if (strcmp(arg1, "enable") == 0) {
645 // Enable all/the specified breakpoint(s).
646 if (strcmp(arg2, "all") == 0) {
647 for (uint32_t i = kMaxWatchpointCode + 1;
652 } else if (GetValue(arg2, &value)) {
653 sim_->EnableStop(value);
655 PrintF("Unrecognized argument.\n");
657 } else if (strcmp(arg1, "disable") == 0) {
658 // Disable all/the specified breakpoint(s).
659 if (strcmp(arg2, "all") == 0) {
660 for (uint32_t i = kMaxWatchpointCode + 1;
663 sim_->DisableStop(i);
665 } else if (GetValue(arg2, &value)) {
666 sim_->DisableStop(value);
668 PrintF("Unrecognized argument.\n");
672 PrintF("Wrong usage. Use help command for more information.\n");
674 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
675 // Print registers and disassemble.
679 disasm::NameConverter converter;
680 disasm::Disassembler dasm(converter);
681 // Use a reasonably large buffer.
682 v8::internal::EmbeddedVector<char, 256> buffer;
688 cur = reinterpret_cast<byte*>(sim_->get_pc());
689 end = cur + (10 * Instruction::kInstrSize);
690 } else if (argc == 2) {
692 if (GetValue(arg1, &value)) {
693 cur = reinterpret_cast<byte*>(value);
694 // no length parameter passed, assume 10 instructions
695 end = cur + (10 * Instruction::kInstrSize);
700 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
701 cur = reinterpret_cast<byte*>(value1);
702 end = cur + (value2 * Instruction::kInstrSize);
707 dasm.InstructionDecode(buffer, cur);
708 PrintF(" 0x%08x %s\n",
709 reinterpret_cast<intptr_t>(cur), buffer.start());
710 cur += Instruction::kInstrSize;
712 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
714 PrintF(" continue execution (alias 'c')\n");
716 PrintF(" step one instruction (alias 'si')\n");
717 PrintF("print <register>\n");
718 PrintF(" print register content (alias 'p')\n");
719 PrintF(" use register name 'all' to print all registers\n");
720 PrintF("printobject <register>\n");
721 PrintF(" print an object from a register (alias 'po')\n");
722 PrintF("stack [<words>]\n");
723 PrintF(" dump stack content, default dump 10 words)\n");
724 PrintF("mem <address> [<words>]\n");
725 PrintF(" dump memory content, default dump 10 words)\n");
727 PrintF(" print flags\n");
728 PrintF("disasm [<instructions>]\n");
729 PrintF("disasm [<address/register>]\n");
730 PrintF("disasm [[<address/register>] <instructions>]\n");
731 PrintF(" disassemble code, default is 10 instructions\n");
732 PrintF(" from pc (alias 'di')\n");
734 PrintF(" enter gdb\n");
735 PrintF("break <address>\n");
736 PrintF(" set a break point on the address\n");
738 PrintF(" delete the breakpoint\n");
739 PrintF("stop feature:\n");
740 PrintF(" Description:\n");
741 PrintF(" Stops are debug instructions inserted by\n");
742 PrintF(" the Assembler::stop() function.\n");
743 PrintF(" When hitting a stop, the Simulator will\n");
744 PrintF(" stop and and give control to the Debugger.\n");
745 PrintF(" All stop codes are watched:\n");
746 PrintF(" - They can be enabled / disabled: the Simulator\n");
747 PrintF(" will / won't stop when hitting them.\n");
748 PrintF(" - The Simulator keeps track of how many times they \n");
749 PrintF(" are met. (See the info command.) Going over a\n");
750 PrintF(" disabled stop still increases its counter. \n");
751 PrintF(" Commands:\n");
752 PrintF(" stop info all/<code> : print infos about number <code>\n");
753 PrintF(" or all stop(s).\n");
754 PrintF(" stop enable/disable all/<code> : enables / disables\n");
755 PrintF(" all or number <code> stop(s)\n");
756 PrintF(" stop unstop\n");
757 PrintF(" ignore the stop instruction at the current location\n");
758 PrintF(" from now on\n");
760 PrintF("Unknown command: %s\n", cmd);
765 // Add all the breakpoints back to stop execution and enter the debugger
777 static bool ICacheMatch(void* one, void* two) {
778 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
779 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
784 static uint32_t ICacheHash(void* key) {
785 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
789 static bool AllOnOnePage(uintptr_t start, int size) {
790 intptr_t start_page = (start & ~CachePage::kPageMask);
791 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
792 return start_page == end_page;
796 void Simulator::set_last_debugger_input(char* input) {
797 DeleteArray(last_debugger_input_);
798 last_debugger_input_ = input;
802 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
805 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
806 int intra_line = (start & CachePage::kLineMask);
809 size = ((size - 1) | CachePage::kLineMask) + 1;
810 int offset = (start & CachePage::kPageMask);
811 while (!AllOnOnePage(start, size - 1)) {
812 int bytes_to_flush = CachePage::kPageSize - offset;
813 FlushOnePage(i_cache, start, bytes_to_flush);
814 start += bytes_to_flush;
815 size -= bytes_to_flush;
816 ASSERT_EQ(0, start & CachePage::kPageMask);
820 FlushOnePage(i_cache, start, size);
825 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
826 v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
829 if (entry->value == NULL) {
830 CachePage* new_page = new CachePage();
831 entry->value = new_page;
833 return reinterpret_cast<CachePage*>(entry->value);
837 // Flush from start up to and not including start + size.
838 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
841 ASSERT(size <= CachePage::kPageSize);
842 ASSERT(AllOnOnePage(start, size - 1));
843 ASSERT((start & CachePage::kLineMask) == 0);
844 ASSERT((size & CachePage::kLineMask) == 0);
845 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
846 int offset = (start & CachePage::kPageMask);
847 CachePage* cache_page = GetCachePage(i_cache, page);
848 char* valid_bytemap = cache_page->ValidityByte(offset);
849 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
853 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
854 Instruction* instr) {
855 intptr_t address = reinterpret_cast<intptr_t>(instr);
856 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
857 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
858 int offset = (address & CachePage::kPageMask);
859 CachePage* cache_page = GetCachePage(i_cache, page);
860 char* cache_valid_byte = cache_page->ValidityByte(offset);
861 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
862 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
864 // Check that the data in memory matches the contents of the I-cache.
865 CHECK(memcmp(reinterpret_cast<void*>(instr),
866 cache_page->CachedData(offset),
867 Instruction::kInstrSize) == 0);
869 // Cache miss. Load memory into the cache.
870 OS::MemCopy(cached_line, line, CachePage::kLineLength);
871 *cache_valid_byte = CachePage::LINE_VALID;
876 void Simulator::Initialize(Isolate* isolate) {
877 if (isolate->simulator_initialized()) return;
878 isolate->set_simulator_initialized(true);
879 ::v8::internal::ExternalReference::set_redirector(isolate,
880 &RedirectExternalReference);
884 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
885 i_cache_ = isolate_->simulator_i_cache();
886 if (i_cache_ == NULL) {
887 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
888 isolate_->set_simulator_i_cache(i_cache_);
891 // Set up simulator support first. Some of this information is needed to
892 // setup the architecture state.
893 stack_ = reinterpret_cast<char*>(malloc(stack_size_));
894 pc_modified_ = false;
900 // Set up architecture state.
901 // All registers are initialized to zero to start with.
902 for (int i = 0; i < kNumSimuRegisters; i++) {
905 for (int i = 0; i < kNumFPURegisters; i++) {
906 FPUregisters_[i] = 0;
910 // The sp is initialized to point to the bottom (high address) of the
911 // allocated stack area. To be safe in potential stack underflows we leave
912 // some buffer below.
913 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
914 // The ra and pc are initialized to a known bad value that will cause an
915 // access violation if the simulator ever tries to execute it.
916 registers_[pc] = bad_ra;
917 registers_[ra] = bad_ra;
918 InitializeCoverage();
919 for (int i = 0; i < kNumExceptions; i++) {
923 last_debugger_input_ = NULL;
927 // When the generated code calls an external reference we need to catch that in
928 // the simulator. The external reference will be a function compiled for the
929 // host architecture. We need to call that function instead of trying to
930 // execute it with the simulator. We do that by redirecting the external
931 // reference to a swi (software-interrupt) instruction that is handled by
932 // the simulator. We write the original destination of the jump just at a known
933 // offset from the swi instruction so the simulator knows what to call.
936 Redirection(void* external_function, ExternalReference::Type type)
937 : external_function_(external_function),
938 swi_instruction_(rtCallRedirInstr),
941 Isolate* isolate = Isolate::Current();
942 next_ = isolate->simulator_redirection();
943 Simulator::current(isolate)->
944 FlushICache(isolate->simulator_i_cache(),
945 reinterpret_cast<void*>(&swi_instruction_),
946 Instruction::kInstrSize);
947 isolate->set_simulator_redirection(this);
950 void* address_of_swi_instruction() {
951 return reinterpret_cast<void*>(&swi_instruction_);
954 void* external_function() { return external_function_; }
955 ExternalReference::Type type() { return type_; }
957 static Redirection* Get(void* external_function,
958 ExternalReference::Type type) {
959 Isolate* isolate = Isolate::Current();
960 Redirection* current = isolate->simulator_redirection();
961 for (; current != NULL; current = current->next_) {
962 if (current->external_function_ == external_function) return current;
964 return new Redirection(external_function, type);
967 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
968 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
969 char* addr_of_redirection =
970 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
971 return reinterpret_cast<Redirection*>(addr_of_redirection);
975 void* external_function_;
976 uint32_t swi_instruction_;
977 ExternalReference::Type type_;
982 void* Simulator::RedirectExternalReference(void* external_function,
983 ExternalReference::Type type) {
984 Redirection* redirection = Redirection::Get(external_function, type);
985 return redirection->address_of_swi_instruction();
989 // Get the active Simulator for the current thread.
990 Simulator* Simulator::current(Isolate* isolate) {
991 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
992 isolate->FindOrAllocatePerThreadDataForThisThread();
993 ASSERT(isolate_data != NULL);
994 ASSERT(isolate_data != NULL);
996 Simulator* sim = isolate_data->simulator();
998 // TODO(146): delete the simulator object when a thread/isolate goes away.
999 sim = new Simulator(isolate);
1000 isolate_data->set_simulator(sim);
1006 // Sets the register in the architecture state. It will also deal with updating
1007 // Simulator internal state for special registers such as PC.
1008 void Simulator::set_register(int reg, int32_t value) {
1009 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1011 pc_modified_ = true;
1014 // Zero register always holds 0.
1015 registers_[reg] = (reg == 0) ? 0 : value;
1019 void Simulator::set_dw_register(int reg, const int* dbl) {
1020 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1021 registers_[reg] = dbl[0];
1022 registers_[reg + 1] = dbl[1];
1026 void Simulator::set_fpu_register(int fpureg, int32_t value) {
1027 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1028 FPUregisters_[fpureg] = value;
1032 void Simulator::set_fpu_register_float(int fpureg, float value) {
1033 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1034 *BitCast<float*>(&FPUregisters_[fpureg]) = value;
1038 void Simulator::set_fpu_register_double(int fpureg, double value) {
1039 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1040 *BitCast<double*>(&FPUregisters_[fpureg]) = value;
1044 // Get the register from the architecture state. This function does handle
1045 // the special case of accessing the PC register.
1046 int32_t Simulator::get_register(int reg) const {
1047 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1051 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
1055 double Simulator::get_double_from_register_pair(int reg) {
1056 ASSERT((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1058 double dm_val = 0.0;
1059 // Read the bits from the unsigned integer register_[] array
1060 // into the double precision floating point value and return it.
1061 char buffer[2 * sizeof(registers_[0])];
1062 OS::MemCopy(buffer, ®isters_[reg], 2 * sizeof(registers_[0]));
1063 OS::MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0]));
1068 int32_t Simulator::get_fpu_register(int fpureg) const {
1069 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1070 return FPUregisters_[fpureg];
1074 int64_t Simulator::get_fpu_register_long(int fpureg) const {
1075 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1076 return *BitCast<int64_t*>(
1077 const_cast<int32_t*>(&FPUregisters_[fpureg]));
1081 float Simulator::get_fpu_register_float(int fpureg) const {
1082 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1083 return *BitCast<float*>(
1084 const_cast<int32_t*>(&FPUregisters_[fpureg]));
1088 double Simulator::get_fpu_register_double(int fpureg) const {
1089 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1090 return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
1094 // Runtime FP routines take up to two double arguments and zero
1095 // or one integer arguments. All are constructed here,
1096 // from a0-a3 or f12 and f14.
1097 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1098 if (!IsMipsSoftFloatABI) {
1099 *x = get_fpu_register_double(12);
1100 *y = get_fpu_register_double(14);
1101 *z = get_register(a2);
1103 // We use a char buffer to get around the strict-aliasing rules which
1104 // otherwise allow the compiler to optimize away the copy.
1105 char buffer[sizeof(*x)];
1106 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1108 // Registers a0 and a1 -> x.
1109 reg_buffer[0] = get_register(a0);
1110 reg_buffer[1] = get_register(a1);
1111 OS::MemCopy(x, buffer, sizeof(buffer));
1112 // Registers a2 and a3 -> y.
1113 reg_buffer[0] = get_register(a2);
1114 reg_buffer[1] = get_register(a3);
1115 OS::MemCopy(y, buffer, sizeof(buffer));
1117 reg_buffer[0] = get_register(a2);
1118 OS::MemCopy(z, buffer, sizeof(*z));
1123 // The return value is either in v0/v1 or f0.
1124 void Simulator::SetFpResult(const double& result) {
1125 if (!IsMipsSoftFloatABI) {
1126 set_fpu_register_double(0, result);
1128 char buffer[2 * sizeof(registers_[0])];
1129 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1130 OS::MemCopy(buffer, &result, sizeof(buffer));
1131 // Copy result to v0 and v1.
1132 set_register(v0, reg_buffer[0]);
1133 set_register(v1, reg_buffer[1]);
1138 // Helper functions for setting and testing the FCSR register's bits.
1139 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1143 FCSR_ &= ~(1 << cc);
1148 bool Simulator::test_fcsr_bit(uint32_t cc) {
1149 return FCSR_ & (1 << cc);
1153 // Sets the rounding error codes in FCSR based on the result of the rounding.
1154 // Returns true if the operation was invalid.
1155 bool Simulator::set_fcsr_round_error(double original, double rounded) {
1158 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1159 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1163 if (original != rounded) {
1164 set_fcsr_bit(kFCSRInexactFlagBit, true);
1167 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1168 set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1172 if (rounded > INT_MAX || rounded < INT_MIN) {
1173 set_fcsr_bit(kFCSROverflowFlagBit, true);
1174 // The reference is not really clear but it seems this is required:
1175 set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1183 // Raw access to the PC register.
1184 void Simulator::set_pc(int32_t value) {
1185 pc_modified_ = true;
1186 registers_[pc] = value;
1190 bool Simulator::has_bad_pc() const {
1191 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1195 // Raw access to the PC register without the special adjustment when reading.
1196 int32_t Simulator::get_pc() const {
1197 return registers_[pc];
1201 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an
1202 // interrupt is caused. On others it does a funky rotation thing. For now we
1203 // simply disallow unaligned reads, but at some point we may want to move to
1204 // emulating the rotate behaviour. Note that simulator runs have the runtime
1205 // system running directly on the host system and only generated code is
1206 // executed in the simulator. Since the host is typically IA32 we will not
1207 // get the correct MIPS-like behaviour on unaligned accesses.
1209 int Simulator::ReadW(int32_t addr, Instruction* instr) {
1210 if (addr >=0 && addr < 0x400) {
1211 // This has to be a NULL-dereference, drop into debugger.
1212 PrintF("Memory read from bad address: 0x%08x, pc=0x%08x\n",
1213 addr, reinterpret_cast<intptr_t>(instr));
1214 MipsDebugger dbg(this);
1217 if ((addr & kPointerAlignmentMask) == 0) {
1218 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1221 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1223 reinterpret_cast<intptr_t>(instr));
1224 MipsDebugger dbg(this);
1230 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1231 if (addr >= 0 && addr < 0x400) {
1232 // This has to be a NULL-dereference, drop into debugger.
1233 PrintF("Memory write to bad address: 0x%08x, pc=0x%08x\n",
1234 addr, reinterpret_cast<intptr_t>(instr));
1235 MipsDebugger dbg(this);
1238 if ((addr & kPointerAlignmentMask) == 0) {
1239 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1243 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1245 reinterpret_cast<intptr_t>(instr));
1246 MipsDebugger dbg(this);
1251 double Simulator::ReadD(int32_t addr, Instruction* instr) {
1252 if ((addr & kDoubleAlignmentMask) == 0) {
1253 double* ptr = reinterpret_cast<double*>(addr);
1256 PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1258 reinterpret_cast<intptr_t>(instr));
1264 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
1265 if ((addr & kDoubleAlignmentMask) == 0) {
1266 double* ptr = reinterpret_cast<double*>(addr);
1270 PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1272 reinterpret_cast<intptr_t>(instr));
1277 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1278 if ((addr & 1) == 0) {
1279 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1282 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1284 reinterpret_cast<intptr_t>(instr));
1290 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1291 if ((addr & 1) == 0) {
1292 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1295 PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1297 reinterpret_cast<intptr_t>(instr));
1303 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1304 if ((addr & 1) == 0) {
1305 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1309 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1311 reinterpret_cast<intptr_t>(instr));
1316 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1317 if ((addr & 1) == 0) {
1318 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1322 PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1324 reinterpret_cast<intptr_t>(instr));
1329 uint32_t Simulator::ReadBU(int32_t addr) {
1330 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1335 int32_t Simulator::ReadB(int32_t addr) {
1336 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1341 void Simulator::WriteB(int32_t addr, uint8_t value) {
1342 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1347 void Simulator::WriteB(int32_t addr, int8_t value) {
1348 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1353 // Returns the limit of the stack area to enable checking for stack overflows.
1354 uintptr_t Simulator::StackLimit() const {
1355 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1357 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1361 // Unsupported instructions use Format to print an error and stop execution.
1362 void Simulator::Format(Instruction* instr, const char* format) {
1363 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1364 reinterpret_cast<intptr_t>(instr), format);
1365 UNIMPLEMENTED_MIPS();
1369 // Calls into the V8 runtime are based on this very simple interface.
1370 // Note: To be able to return two values from some calls the code in runtime.cc
1371 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1372 // 64-bit value. With the code below we assume that all runtime calls return
1373 // 64 bits of result. If they don't, the v1 result register contains a bogus
1374 // value, which is fine because it is caller-saved.
1375 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1382 // These prototypes handle the four types of FP calls.
1383 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1384 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1385 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1386 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1388 // This signature supports direct call in to API function native callback
1389 // (refer to InvocationCallback in v8.h).
1390 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1391 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, int32_t arg1);
1393 // This signature supports direct call to accessor getter callback.
1394 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1395 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1396 int32_t arg0, int32_t arg1, int32_t arg2);
1398 // Software interrupt instructions are used by the simulator to call into the
1399 // C-based V8 runtime. They are also used for debugging with simulator.
1400 void Simulator::SoftwareInterrupt(Instruction* instr) {
1401 // There are several instructions that could get us here,
1402 // the break_ instruction, or several variants of traps. All
1403 // Are "SPECIAL" class opcode, and are distinuished by function.
1404 int32_t func = instr->FunctionFieldRaw();
1405 uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1407 // We first check if we met a call_rt_redirected.
1408 if (instr->InstructionBits() == rtCallRedirInstr) {
1409 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1410 int32_t arg0 = get_register(a0);
1411 int32_t arg1 = get_register(a1);
1412 int32_t arg2 = get_register(a2);
1413 int32_t arg3 = get_register(a3);
1415 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1416 // Args 4 and 5 are on the stack after the reserved space for args 0..3.
1417 int32_t arg4 = stack_pointer[4];
1418 int32_t arg5 = stack_pointer[5];
1421 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1422 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1423 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1424 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1426 if (!IsMipsSoftFloatABI) {
1427 // With the hard floating point calling convention, double
1428 // arguments are passed in FPU registers. Fetch the arguments
1429 // from there and call the builtin using soft floating point
1431 switch (redirection->type()) {
1432 case ExternalReference::BUILTIN_FP_FP_CALL:
1433 case ExternalReference::BUILTIN_COMPARE_CALL:
1434 arg0 = get_fpu_register(f12);
1435 arg1 = get_fpu_register(f13);
1436 arg2 = get_fpu_register(f14);
1437 arg3 = get_fpu_register(f15);
1439 case ExternalReference::BUILTIN_FP_CALL:
1440 arg0 = get_fpu_register(f12);
1441 arg1 = get_fpu_register(f13);
1443 case ExternalReference::BUILTIN_FP_INT_CALL:
1444 arg0 = get_fpu_register(f12);
1445 arg1 = get_fpu_register(f13);
1446 arg2 = get_register(a2);
1453 // This is dodgy but it works because the C entry stubs are never moved.
1454 // See comment in codegen-arm.cc and bug 1242173.
1455 int32_t saved_ra = get_register(ra);
1458 reinterpret_cast<intptr_t>(redirection->external_function());
1460 // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1461 // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1462 // simulator. Soft-float has additional abstraction of ExternalReference,
1463 // to support serialization.
1465 double dval0, dval1; // one or two double parameters
1466 int32_t ival; // zero or one integer parameters
1467 int64_t iresult = 0; // integer return value
1468 double dresult = 0; // double return value
1469 GetFpArgs(&dval0, &dval1, &ival);
1470 SimulatorRuntimeCall generic_target =
1471 reinterpret_cast<SimulatorRuntimeCall>(external);
1472 if (::v8::internal::FLAG_trace_sim) {
1473 switch (redirection->type()) {
1474 case ExternalReference::BUILTIN_FP_FP_CALL:
1475 case ExternalReference::BUILTIN_COMPARE_CALL:
1476 PrintF("Call to host function at %p with args %f, %f",
1477 FUNCTION_ADDR(generic_target), dval0, dval1);
1479 case ExternalReference::BUILTIN_FP_CALL:
1480 PrintF("Call to host function at %p with arg %f",
1481 FUNCTION_ADDR(generic_target), dval0);
1483 case ExternalReference::BUILTIN_FP_INT_CALL:
1484 PrintF("Call to host function at %p with args %f, %d",
1485 FUNCTION_ADDR(generic_target), dval0, ival);
1492 switch (redirection->type()) {
1493 case ExternalReference::BUILTIN_COMPARE_CALL: {
1494 SimulatorRuntimeCompareCall target =
1495 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1496 iresult = target(dval0, dval1);
1497 set_register(v0, static_cast<int32_t>(iresult));
1498 set_register(v1, static_cast<int32_t>(iresult >> 32));
1501 case ExternalReference::BUILTIN_FP_FP_CALL: {
1502 SimulatorRuntimeFPFPCall target =
1503 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1504 dresult = target(dval0, dval1);
1505 SetFpResult(dresult);
1508 case ExternalReference::BUILTIN_FP_CALL: {
1509 SimulatorRuntimeFPCall target =
1510 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1511 dresult = target(dval0);
1512 SetFpResult(dresult);
1515 case ExternalReference::BUILTIN_FP_INT_CALL: {
1516 SimulatorRuntimeFPIntCall target =
1517 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1518 dresult = target(dval0, ival);
1519 SetFpResult(dresult);
1526 if (::v8::internal::FLAG_trace_sim) {
1527 switch (redirection->type()) {
1528 case ExternalReference::BUILTIN_COMPARE_CALL:
1529 PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1531 case ExternalReference::BUILTIN_FP_FP_CALL:
1532 case ExternalReference::BUILTIN_FP_CALL:
1533 case ExternalReference::BUILTIN_FP_INT_CALL:
1534 PrintF("Returned %f\n", dresult);
1541 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1542 if (::v8::internal::FLAG_trace_sim) {
1543 PrintF("Call to host function at %p args %08x\n",
1544 reinterpret_cast<void*>(external), arg0);
1546 SimulatorRuntimeDirectApiCall target =
1547 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1550 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1551 if (::v8::internal::FLAG_trace_sim) {
1552 PrintF("Call to host function at %p args %08x %08x\n",
1553 reinterpret_cast<void*>(external), arg0, arg1);
1555 SimulatorRuntimeProfilingApiCall target =
1556 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1559 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1560 if (::v8::internal::FLAG_trace_sim) {
1561 PrintF("Call to host function at %p args %08x %08x\n",
1562 reinterpret_cast<void*>(external), arg0, arg1);
1564 SimulatorRuntimeDirectGetterCall target =
1565 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1568 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1569 if (::v8::internal::FLAG_trace_sim) {
1570 PrintF("Call to host function at %p args %08x %08x %08x\n",
1571 reinterpret_cast<void*>(external), arg0, arg1, arg2);
1573 SimulatorRuntimeProfilingGetterCall target =
1574 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1575 target(arg0, arg1, arg2);
1577 SimulatorRuntimeCall target =
1578 reinterpret_cast<SimulatorRuntimeCall>(external);
1579 if (::v8::internal::FLAG_trace_sim) {
1581 "Call to host function at %p "
1582 "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1583 FUNCTION_ADDR(target),
1591 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1592 set_register(v0, static_cast<int32_t>(result));
1593 set_register(v1, static_cast<int32_t>(result >> 32));
1595 if (::v8::internal::FLAG_trace_sim) {
1596 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
1598 set_register(ra, saved_ra);
1599 set_pc(get_register(ra));
1601 } else if (func == BREAK && code <= kMaxStopCode) {
1602 if (IsWatchpoint(code)) {
1603 PrintWatchpoint(code);
1605 IncreaseStopCounter(code);
1606 HandleStop(code, instr);
1609 // All remaining break_ codes, and all traps are handled here.
1610 MipsDebugger dbg(this);
1616 // Stop helper functions.
1617 bool Simulator::IsWatchpoint(uint32_t code) {
1618 return (code <= kMaxWatchpointCode);
1622 void Simulator::PrintWatchpoint(uint32_t code) {
1623 MipsDebugger dbg(this);
1625 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------"
1626 "----------------------------------",
1627 code, break_count_, icount_);
1628 dbg.PrintAllRegs(); // Print registers and continue running.
1632 void Simulator::HandleStop(uint32_t code, Instruction* instr) {
1633 // Stop if it is enabled, otherwise go on jumping over the stop
1634 // and the message address.
1635 if (IsEnabledStop(code)) {
1636 MipsDebugger dbg(this);
1639 set_pc(get_pc() + 2 * Instruction::kInstrSize);
1644 bool Simulator::IsStopInstruction(Instruction* instr) {
1645 int32_t func = instr->FunctionFieldRaw();
1646 uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
1647 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
1651 bool Simulator::IsEnabledStop(uint32_t code) {
1652 ASSERT(code <= kMaxStopCode);
1653 ASSERT(code > kMaxWatchpointCode);
1654 return !(watched_stops_[code].count & kStopDisabledBit);
1658 void Simulator::EnableStop(uint32_t code) {
1659 if (!IsEnabledStop(code)) {
1660 watched_stops_[code].count &= ~kStopDisabledBit;
1665 void Simulator::DisableStop(uint32_t code) {
1666 if (IsEnabledStop(code)) {
1667 watched_stops_[code].count |= kStopDisabledBit;
1672 void Simulator::IncreaseStopCounter(uint32_t code) {
1673 ASSERT(code <= kMaxStopCode);
1674 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1675 PrintF("Stop counter for code %i has overflowed.\n"
1676 "Enabling this code and reseting the counter to 0.\n", code);
1677 watched_stops_[code].count = 0;
1680 watched_stops_[code].count++;
1685 // Print a stop status.
1686 void Simulator::PrintStopInfo(uint32_t code) {
1687 if (code <= kMaxWatchpointCode) {
1688 PrintF("That is a watchpoint, not a stop.\n");
1690 } else if (code > kMaxStopCode) {
1691 PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
1694 const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
1695 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1696 // Don't print the state of unused breakpoints.
1698 if (watched_stops_[code].desc) {
1699 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1700 code, code, state, count, watched_stops_[code].desc);
1702 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
1703 code, code, state, count);
1709 void Simulator::SignalExceptions() {
1710 for (int i = 1; i < kNumExceptions; i++) {
1711 if (exceptions[i] != 0) {
1712 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1718 // Handle execution based on instruction types.
1720 void Simulator::ConfigureTypeRegister(Instruction* instr,
1725 bool& do_interrupt) {
1726 // Every local variable declared here needs to be const.
1727 // This is to make sure that changed values are sent back to
1728 // DecodeTypeRegister correctly.
1730 // Instruction fields.
1731 const Opcode op = instr->OpcodeFieldRaw();
1732 const int32_t rs_reg = instr->RsValue();
1733 const int32_t rs = get_register(rs_reg);
1734 const uint32_t rs_u = static_cast<uint32_t>(rs);
1735 const int32_t rt_reg = instr->RtValue();
1736 const int32_t rt = get_register(rt_reg);
1737 const uint32_t rt_u = static_cast<uint32_t>(rt);
1738 const int32_t rd_reg = instr->RdValue();
1739 const uint32_t sa = instr->SaValue();
1741 const int32_t fs_reg = instr->FsValue();
1744 // ---------- Configuration.
1746 case COP1: // Coprocessor instructions.
1747 switch (instr->RsFieldRaw()) {
1748 case BC1: // Handled in DecodeTypeImmed, should never come here.
1752 // At the moment only FCSR is supported.
1753 ASSERT(fs_reg == kFCSRRegister);
1757 alu_out = get_fpu_register(fs_reg);
1760 UNIMPLEMENTED_MIPS();
1765 // Do the store in the execution step.
1772 // Do everything in the execution step.
1775 UNIMPLEMENTED_MIPS();
1781 switch (instr->FunctionFieldRaw()) {
1784 next_pc = get_register(instr->RsValue());
1791 // Regular logical right shift of a word by a fixed number of
1792 // bits instruction. RS field is always equal to 0.
1793 alu_out = rt_u >> sa;
1795 // Logical right-rotate of a word by a fixed number of bits. This
1796 // is special case of SRL instruction, added in MIPS32 Release 2.
1797 // RS field is equal to 00001.
1798 alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1809 // Regular logical right-shift of a word by a variable number of
1810 // bits instruction. SA field is always equal to 0.
1811 alu_out = rt_u >> rs;
1813 // Logical right-rotate of a word by a variable number of bits.
1814 // This is special case od SRLV instruction, added in MIPS32
1815 // Release 2. SA field is equal to 00001.
1816 alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1823 alu_out = get_register(HI);
1826 alu_out = get_register(LO);
1829 i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1832 u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
1835 if (HaveSameSign(rs, rt)) {
1837 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
1838 } else if (rs < 0) {
1839 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
1848 if (!HaveSameSign(rs, rt)) {
1850 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
1851 } else if (rs < 0) {
1852 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
1870 alu_out = ~(rs | rt);
1873 alu_out = rs < rt ? 1 : 0;
1876 alu_out = rs_u < rt_u ? 1 : 0;
1878 // Break and trap instructions.
1881 do_interrupt = true;
1884 do_interrupt = rs >= rt;
1887 do_interrupt = rs_u >= rt_u;
1890 do_interrupt = rs < rt;
1893 do_interrupt = rs_u < rt_u;
1896 do_interrupt = rs == rt;
1899 do_interrupt = rs != rt;
1904 // No action taken on decode.
1908 // div and divu never raise exceptions.
1915 switch (instr->FunctionFieldRaw()) {
1917 alu_out = rs_u * rt_u; // Only the lower 32 bits are kept.
1920 alu_out = __builtin_clz(rs_u);
1927 switch (instr->FunctionFieldRaw()) {
1928 case INS: { // Mips32r2 instruction.
1929 // Interpret rd field as 5-bit msb of insert.
1930 uint16_t msb = rd_reg;
1931 // Interpret sa field as 5-bit lsb of insert.
1933 uint16_t size = msb - lsb + 1;
1934 uint32_t mask = (1 << size) - 1;
1935 alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1938 case EXT: { // Mips32r2 instruction.
1939 // Interpret rd field as 5-bit msb of extract.
1940 uint16_t msb = rd_reg;
1941 // Interpret sa field as 5-bit lsb of extract.
1943 uint16_t size = msb + 1;
1944 uint32_t mask = (1 << size) - 1;
1945 alu_out = (rs_u & (mask << lsb)) >> lsb;
1958 void Simulator::DecodeTypeRegister(Instruction* instr) {
1959 // Instruction fields.
1960 const Opcode op = instr->OpcodeFieldRaw();
1961 const int32_t rs_reg = instr->RsValue();
1962 const int32_t rs = get_register(rs_reg);
1963 const uint32_t rs_u = static_cast<uint32_t>(rs);
1964 const int32_t rt_reg = instr->RtValue();
1965 const int32_t rt = get_register(rt_reg);
1966 const uint32_t rt_u = static_cast<uint32_t>(rt);
1967 const int32_t rd_reg = instr->RdValue();
1969 const int32_t fr_reg = instr->FrValue();
1970 const int32_t fs_reg = instr->FsValue();
1971 const int32_t ft_reg = instr->FtValue();
1972 const int32_t fd_reg = instr->FdValue();
1973 int64_t i64hilo = 0;
1974 uint64_t u64hilo = 0;
1977 // It should not be used as is. Instructions using it should always
1978 // initialize it first.
1979 int32_t alu_out = 0x12345678;
1981 // For break and trap instructions.
1982 bool do_interrupt = false;
1986 int32_t current_pc = get_pc();
1988 int32_t next_pc = 0;
1990 // Set up the variables if needed before executing the instruction.
1991 ConfigureTypeRegister(instr,
1998 // ---------- Raise exceptions triggered.
2001 // ---------- Execution.
2004 switch (instr->RsFieldRaw()) {
2005 case BC1: // Branch on coprocessor condition.
2009 set_register(rt_reg, alu_out);
2011 set_register(rt_reg, alu_out);
2014 UNIMPLEMENTED_MIPS();
2017 // At the moment only FCSR is supported.
2018 ASSERT(fs_reg == kFCSRRegister);
2019 FCSR_ = registers_[rt_reg];
2022 FPUregisters_[fs_reg] = registers_[rt_reg];
2025 UNIMPLEMENTED_MIPS();
2029 switch (instr->FunctionFieldRaw()) {
2031 f = get_fpu_register_float(fs_reg);
2032 set_fpu_register_double(fd_reg, static_cast<double>(f));
2045 UNIMPLEMENTED_MIPS();
2053 uint32_t cc, fcsr_cc;
2055 fs = get_fpu_register_double(fs_reg);
2056 ft = get_fpu_register_double(ft_reg);
2057 cc = instr->FCccValue();
2058 fcsr_cc = get_fcsr_condition_bit(cc);
2059 switch (instr->FunctionFieldRaw()) {
2061 set_fpu_register_double(fd_reg, fs + ft);
2064 set_fpu_register_double(fd_reg, fs - ft);
2067 set_fpu_register_double(fd_reg, fs * ft);
2070 set_fpu_register_double(fd_reg, fs / ft);
2073 set_fpu_register_double(fd_reg, fabs(fs));
2076 set_fpu_register_double(fd_reg, fs);
2079 set_fpu_register_double(fd_reg, -fs);
2082 set_fpu_register_double(fd_reg, sqrt(fs));
2085 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2088 set_fcsr_bit(fcsr_cc, (fs == ft));
2091 set_fcsr_bit(fcsr_cc,
2092 (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2095 set_fcsr_bit(fcsr_cc, (fs < ft));
2098 set_fcsr_bit(fcsr_cc,
2099 (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2102 set_fcsr_bit(fcsr_cc, (fs <= ft));
2105 set_fcsr_bit(fcsr_cc,
2106 (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2108 case CVT_W_D: // Convert double to word.
2109 // Rounding modes are not yet supported.
2110 ASSERT((FCSR_ & 3) == 0);
2111 // In rounding mode 0 it should behave like ROUND.
2112 case ROUND_W_D: // Round double to word (round half to even).
2114 double rounded = floor(fs + 0.5);
2115 int32_t result = static_cast<int32_t>(rounded);
2116 if ((result & 1) != 0 && result - fs == 0.5) {
2117 // If the number is halfway between two integers,
2118 // round to the even one.
2121 set_fpu_register(fd_reg, result);
2122 if (set_fcsr_round_error(fs, rounded)) {
2123 set_fpu_register(fd_reg, kFPUInvalidResult);
2127 case TRUNC_W_D: // Truncate double to word (round towards 0).
2129 double rounded = trunc(fs);
2130 int32_t result = static_cast<int32_t>(rounded);
2131 set_fpu_register(fd_reg, result);
2132 if (set_fcsr_round_error(fs, rounded)) {
2133 set_fpu_register(fd_reg, kFPUInvalidResult);
2137 case FLOOR_W_D: // Round double to word towards negative infinity.
2139 double rounded = floor(fs);
2140 int32_t result = static_cast<int32_t>(rounded);
2141 set_fpu_register(fd_reg, result);
2142 if (set_fcsr_round_error(fs, rounded)) {
2143 set_fpu_register(fd_reg, kFPUInvalidResult);
2147 case CEIL_W_D: // Round double to word towards positive infinity.
2149 double rounded = ceil(fs);
2150 int32_t result = static_cast<int32_t>(rounded);
2151 set_fpu_register(fd_reg, result);
2152 if (set_fcsr_round_error(fs, rounded)) {
2153 set_fpu_register(fd_reg, kFPUInvalidResult);
2157 case CVT_S_D: // Convert double to float (single).
2158 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2160 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
2161 double rounded = trunc(fs);
2162 i64 = static_cast<int64_t>(rounded);
2163 set_fpu_register(fd_reg, i64 & 0xffffffff);
2164 set_fpu_register(fd_reg + 1, i64 >> 32);
2167 case TRUNC_L_D: { // Mips32r2 instruction.
2168 double rounded = trunc(fs);
2169 i64 = static_cast<int64_t>(rounded);
2170 set_fpu_register(fd_reg, i64 & 0xffffffff);
2171 set_fpu_register(fd_reg + 1, i64 >> 32);
2174 case ROUND_L_D: { // Mips32r2 instruction.
2175 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2176 i64 = static_cast<int64_t>(rounded);
2177 set_fpu_register(fd_reg, i64 & 0xffffffff);
2178 set_fpu_register(fd_reg + 1, i64 >> 32);
2181 case FLOOR_L_D: // Mips32r2 instruction.
2182 i64 = static_cast<int64_t>(floor(fs));
2183 set_fpu_register(fd_reg, i64 & 0xffffffff);
2184 set_fpu_register(fd_reg + 1, i64 >> 32);
2186 case CEIL_L_D: // Mips32r2 instruction.
2187 i64 = static_cast<int64_t>(ceil(fs));
2188 set_fpu_register(fd_reg, i64 & 0xffffffff);
2189 set_fpu_register(fd_reg + 1, i64 >> 32);
2192 UNIMPLEMENTED_MIPS();
2199 switch (instr->FunctionFieldRaw()) {
2200 case CVT_S_W: // Convert word to float (single).
2201 alu_out = get_fpu_register(fs_reg);
2202 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2204 case CVT_D_W: // Convert word to double.
2205 alu_out = get_fpu_register(fs_reg);
2206 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2213 switch (instr->FunctionFieldRaw()) {
2214 case CVT_D_L: // Mips32r2 instruction.
2215 // Watch the signs here, we want 2 32-bit vals
2216 // to make a sign-64.
2217 i64 = static_cast<uint32_t>(get_fpu_register(fs_reg));
2218 i64 |= static_cast<int64_t>(get_fpu_register(fs_reg + 1)) << 32;
2219 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2222 UNIMPLEMENTED_MIPS();
2235 switch (instr->FunctionFieldRaw()) {
2238 fr = get_fpu_register_double(fr_reg);
2239 fs = get_fpu_register_double(fs_reg);
2240 ft = get_fpu_register_double(ft_reg);
2241 set_fpu_register_double(fd_reg, fs * ft + fr);
2248 switch (instr->FunctionFieldRaw()) {
2250 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2251 current_pc+Instruction::kInstrSize);
2252 BranchDelayInstructionDecode(branch_delay_instr);
2254 pc_modified_ = true;
2258 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2259 current_pc+Instruction::kInstrSize);
2260 BranchDelayInstructionDecode(branch_delay_instr);
2261 set_register(31, current_pc + 2 * Instruction::kInstrSize);
2263 pc_modified_ = true;
2266 // Instructions using HI and LO registers.
2268 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2269 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2272 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2273 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2276 // Divide by zero and overflow was not checked in the configuration
2277 // step - div and divu do not raise exceptions. On division by 0
2278 // the result will be UNPREDICTABLE. On overflow (INT_MIN/-1),
2279 // return INT_MIN which is what the hardware does.
2280 if (rs == INT_MIN && rt == -1) {
2281 set_register(LO, INT_MIN);
2282 set_register(HI, 0);
2283 } else if (rt != 0) {
2284 set_register(LO, rs / rt);
2285 set_register(HI, rs % rt);
2290 set_register(LO, rs_u / rt_u);
2291 set_register(HI, rs_u % rt_u);
2294 // Break and trap instructions.
2303 SoftwareInterrupt(instr);
2306 // Conditional moves.
2308 if (rt) set_register(rd_reg, rs);
2311 uint32_t cc = instr->FBccValue();
2312 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2313 if (instr->Bit(16)) { // Read Tf bit.
2314 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2316 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2321 if (!rt) set_register(rd_reg, rs);
2323 default: // For other special opcodes we do the default operation.
2324 set_register(rd_reg, alu_out);
2328 switch (instr->FunctionFieldRaw()) {
2330 set_register(rd_reg, alu_out);
2331 // HI and LO are UNPREDICTABLE after the operation.
2332 set_register(LO, Unpredictable);
2333 set_register(HI, Unpredictable);
2335 default: // For other special2 opcodes we do the default operation.
2336 set_register(rd_reg, alu_out);
2340 switch (instr->FunctionFieldRaw()) {
2342 // Ins instr leaves result in Rt, rather than Rd.
2343 set_register(rt_reg, alu_out);
2346 // Ext instr leaves result in Rt, rather than Rd.
2347 set_register(rt_reg, alu_out);
2353 // Unimplemented opcodes raised an error in the configuration step before,
2354 // so we can use the default here to set the destination register in common
2357 set_register(rd_reg, alu_out);
2362 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
2363 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2364 // Instruction fields.
2365 Opcode op = instr->OpcodeFieldRaw();
2366 int32_t rs = get_register(instr->RsValue());
2367 uint32_t rs_u = static_cast<uint32_t>(rs);
2368 int32_t rt_reg = instr->RtValue(); // Destination register.
2369 int32_t rt = get_register(rt_reg);
2370 int16_t imm16 = instr->Imm16Value();
2372 int32_t ft_reg = instr->FtValue(); // Destination register.
2374 // Zero extended immediate.
2375 uint32_t oe_imm16 = 0xffff & imm16;
2376 // Sign extended immediate.
2377 int32_t se_imm16 = imm16;
2380 int32_t current_pc = get_pc();
2382 int32_t next_pc = bad_ra;
2384 // Used for conditional branch instructions.
2385 bool do_branch = false;
2386 bool execute_branch_delay_instruction = false;
2388 // Used for arithmetic instructions.
2389 int32_t alu_out = 0;
2391 double fp_out = 0.0;
2392 uint32_t cc, cc_value, fcsr_cc;
2394 // Used for memory instructions.
2396 // Value to be written in memory.
2397 uint32_t mem_value = 0x0;
2399 // ---------- Configuration (and execution for REGIMM).
2401 // ------------- COP1. Coprocessor instructions.
2403 switch (instr->RsFieldRaw()) {
2404 case BC1: // Branch on coprocessor condition.
2405 cc = instr->FBccValue();
2406 fcsr_cc = get_fcsr_condition_bit(cc);
2407 cc_value = test_fcsr_bit(fcsr_cc);
2408 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2409 execute_branch_delay_instruction = true;
2412 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2414 next_pc = current_pc + kBranchReturnOffset;
2421 // ------------- REGIMM class.
2423 switch (instr->RtFieldRaw()) {
2425 do_branch = (rs < 0);
2431 do_branch = rs >= 0;
2434 do_branch = rs >= 0;
2439 switch (instr->RtFieldRaw()) {
2444 // Branch instructions common part.
2445 execute_branch_delay_instruction = true;
2448 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2449 if (instr->IsLinkingInstruction()) {
2450 set_register(31, current_pc + kBranchReturnOffset);
2453 next_pc = current_pc + kBranchReturnOffset;
2458 break; // case REGIMM.
2459 // ------------- Branch instructions.
2460 // When comparing to zero, the encoding of rt field is always 0, so we don't
2461 // need to replace rt with zero.
2463 do_branch = (rs == rt);
2466 do_branch = rs != rt;
2469 do_branch = rs <= 0;
2474 // ------------- Arithmetic instructions.
2476 if (HaveSameSign(rs, se_imm16)) {
2478 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2479 } else if (rs < 0) {
2480 exceptions[kIntegerUnderflow] =
2481 rs < (Registers::kMinValue - se_imm16);
2484 alu_out = rs + se_imm16;
2487 alu_out = rs + se_imm16;
2490 alu_out = (rs < se_imm16) ? 1 : 0;
2493 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2496 alu_out = rs & oe_imm16;
2499 alu_out = rs | oe_imm16;
2502 alu_out = rs ^ oe_imm16;
2505 alu_out = (oe_imm16 << 16);
2507 // ------------- Memory instructions.
2509 addr = rs + se_imm16;
2510 alu_out = ReadB(addr);
2513 addr = rs + se_imm16;
2514 alu_out = ReadH(addr, instr);
2517 // al_offset is offset of the effective address within an aligned word.
2518 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2519 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2520 uint32_t mask = (1 << byte_shift * 8) - 1;
2521 addr = rs + se_imm16 - al_offset;
2522 alu_out = ReadW(addr, instr);
2523 alu_out <<= byte_shift * 8;
2524 alu_out |= rt & mask;
2528 addr = rs + se_imm16;
2529 alu_out = ReadW(addr, instr);
2532 addr = rs + se_imm16;
2533 alu_out = ReadBU(addr);
2536 addr = rs + se_imm16;
2537 alu_out = ReadHU(addr, instr);
2540 // al_offset is offset of the effective address within an aligned word.
2541 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2542 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2543 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2544 addr = rs + se_imm16 - al_offset;
2545 alu_out = ReadW(addr, instr);
2546 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2547 alu_out |= rt & mask;
2551 addr = rs + se_imm16;
2554 addr = rs + se_imm16;
2557 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2558 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2559 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2560 addr = rs + se_imm16 - al_offset;
2561 mem_value = ReadW(addr, instr) & mask;
2562 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2566 addr = rs + se_imm16;
2569 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2570 uint32_t mask = (1 << al_offset * 8) - 1;
2571 addr = rs + se_imm16 - al_offset;
2572 mem_value = ReadW(addr, instr);
2573 mem_value = (rt << al_offset * 8) | (mem_value & mask);
2577 addr = rs + se_imm16;
2578 alu_out = ReadW(addr, instr);
2581 addr = rs + se_imm16;
2582 fp_out = ReadD(addr, instr);
2586 addr = rs + se_imm16;
2592 // ---------- Raise exceptions triggered.
2595 // ---------- Execution.
2597 // ------------- Branch instructions.
2602 // Branch instructions common part.
2603 execute_branch_delay_instruction = true;
2606 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2607 if (instr->IsLinkingInstruction()) {
2608 set_register(31, current_pc + 2* Instruction::kInstrSize);
2611 next_pc = current_pc + 2 * Instruction::kInstrSize;
2614 // ------------- Arithmetic instructions.
2623 set_register(rt_reg, alu_out);
2625 // ------------- Memory instructions.
2633 set_register(rt_reg, alu_out);
2636 WriteB(addr, static_cast<int8_t>(rt));
2639 WriteH(addr, static_cast<uint16_t>(rt), instr);
2642 WriteW(addr, mem_value, instr);
2645 WriteW(addr, rt, instr);
2648 WriteW(addr, mem_value, instr);
2651 set_fpu_register(ft_reg, alu_out);
2654 set_fpu_register_double(ft_reg, fp_out);
2657 addr = rs + se_imm16;
2658 WriteW(addr, get_fpu_register(ft_reg), instr);
2661 addr = rs + se_imm16;
2662 WriteD(addr, get_fpu_register_double(ft_reg), instr);
2669 if (execute_branch_delay_instruction) {
2670 // Execute branch delay slot
2671 // We don't check for end_sim_pc. First it should not be met as the current
2672 // pc is valid. Secondly a jump should always execute its branch delay slot.
2673 Instruction* branch_delay_instr =
2674 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2675 BranchDelayInstructionDecode(branch_delay_instr);
2678 // If needed update pc after the branch delay execution.
2679 if (next_pc != bad_ra) {
2685 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
2686 void Simulator::DecodeTypeJump(Instruction* instr) {
2688 int32_t current_pc = get_pc();
2689 // Get unchanged bits of pc.
2690 int32_t pc_high_bits = current_pc & 0xf0000000;
2692 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2694 // Execute branch delay slot.
2695 // We don't check for end_sim_pc. First it should not be met as the current pc
2696 // is valid. Secondly a jump should always execute its branch delay slot.
2697 Instruction* branch_delay_instr =
2698 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2699 BranchDelayInstructionDecode(branch_delay_instr);
2701 // Update pc and ra if necessary.
2702 // Do this after the branch delay execution.
2703 if (instr->IsLinkingInstruction()) {
2704 set_register(31, current_pc + 2 * Instruction::kInstrSize);
2707 pc_modified_ = true;
2711 // Executes the current instruction.
2712 void Simulator::InstructionDecode(Instruction* instr) {
2713 if (v8::internal::FLAG_check_icache) {
2714 CheckICache(isolate_->simulator_i_cache(), instr);
2716 pc_modified_ = false;
2717 if (::v8::internal::FLAG_trace_sim) {
2718 disasm::NameConverter converter;
2719 disasm::Disassembler dasm(converter);
2720 // Use a reasonably large buffer.
2721 v8::internal::EmbeddedVector<char, 256> buffer;
2722 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2723 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2727 switch (instr->InstructionType()) {
2728 case Instruction::kRegisterType:
2729 DecodeTypeRegister(instr);
2731 case Instruction::kImmediateType:
2732 DecodeTypeImmediate(instr);
2734 case Instruction::kJumpType:
2735 DecodeTypeJump(instr);
2740 if (!pc_modified_) {
2741 set_register(pc, reinterpret_cast<int32_t>(instr) +
2742 Instruction::kInstrSize);
2748 void Simulator::Execute() {
2749 // Get the PC to simulate. Cannot use the accessor here as we need the
2750 // raw PC value and not the one used as input to arithmetic instructions.
2751 int program_counter = get_pc();
2752 if (::v8::internal::FLAG_stop_sim_at == 0) {
2753 // Fast version of the dispatch loop without checking whether the simulator
2754 // should be stopping at a particular executed instruction.
2755 while (program_counter != end_sim_pc) {
2756 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2758 InstructionDecode(instr);
2759 program_counter = get_pc();
2762 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2763 // we reach the particular instuction count.
2764 while (program_counter != end_sim_pc) {
2765 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2767 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2768 MipsDebugger dbg(this);
2771 InstructionDecode(instr);
2773 program_counter = get_pc();
2779 void Simulator::CallInternal(byte* entry) {
2780 // Prepare to execute the code at entry.
2781 set_register(pc, reinterpret_cast<int32_t>(entry));
2782 // Put down marker for end of simulation. The simulator will stop simulation
2783 // when the PC reaches this value. By saving the "end simulation" value into
2784 // the LR the simulation stops when returning to this call point.
2785 set_register(ra, end_sim_pc);
2787 // Remember the values of callee-saved registers.
2788 // The code below assumes that r9 is not used as sb (static base) in
2789 // simulator code and therefore is regarded as a callee-saved register.
2790 int32_t s0_val = get_register(s0);
2791 int32_t s1_val = get_register(s1);
2792 int32_t s2_val = get_register(s2);
2793 int32_t s3_val = get_register(s3);
2794 int32_t s4_val = get_register(s4);
2795 int32_t s5_val = get_register(s5);
2796 int32_t s6_val = get_register(s6);
2797 int32_t s7_val = get_register(s7);
2798 int32_t gp_val = get_register(gp);
2799 int32_t sp_val = get_register(sp);
2800 int32_t fp_val = get_register(fp);
2802 // Set up the callee-saved registers with a known value. To be able to check
2803 // that they are preserved properly across JS execution.
2804 int32_t callee_saved_value = icount_;
2805 set_register(s0, callee_saved_value);
2806 set_register(s1, callee_saved_value);
2807 set_register(s2, callee_saved_value);
2808 set_register(s3, callee_saved_value);
2809 set_register(s4, callee_saved_value);
2810 set_register(s5, callee_saved_value);
2811 set_register(s6, callee_saved_value);
2812 set_register(s7, callee_saved_value);
2813 set_register(gp, callee_saved_value);
2814 set_register(fp, callee_saved_value);
2816 // Start the simulation.
2819 // Check that the callee-saved registers have been preserved.
2820 CHECK_EQ(callee_saved_value, get_register(s0));
2821 CHECK_EQ(callee_saved_value, get_register(s1));
2822 CHECK_EQ(callee_saved_value, get_register(s2));
2823 CHECK_EQ(callee_saved_value, get_register(s3));
2824 CHECK_EQ(callee_saved_value, get_register(s4));
2825 CHECK_EQ(callee_saved_value, get_register(s5));
2826 CHECK_EQ(callee_saved_value, get_register(s6));
2827 CHECK_EQ(callee_saved_value, get_register(s7));
2828 CHECK_EQ(callee_saved_value, get_register(gp));
2829 CHECK_EQ(callee_saved_value, get_register(fp));
2831 // Restore callee-saved registers with the original value.
2832 set_register(s0, s0_val);
2833 set_register(s1, s1_val);
2834 set_register(s2, s2_val);
2835 set_register(s3, s3_val);
2836 set_register(s4, s4_val);
2837 set_register(s5, s5_val);
2838 set_register(s6, s6_val);
2839 set_register(s7, s7_val);
2840 set_register(gp, gp_val);
2841 set_register(sp, sp_val);
2842 set_register(fp, fp_val);
2846 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2848 va_start(parameters, argument_count);
2849 // Set up arguments.
2851 // First four arguments passed in registers.
2852 ASSERT(argument_count >= 4);
2853 set_register(a0, va_arg(parameters, int32_t));
2854 set_register(a1, va_arg(parameters, int32_t));
2855 set_register(a2, va_arg(parameters, int32_t));
2856 set_register(a3, va_arg(parameters, int32_t));
2858 // Remaining arguments passed on stack.
2859 int original_stack = get_register(sp);
2860 // Compute position of stack on entry to generated code.
2861 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
2863 if (OS::ActivationFrameAlignment() != 0) {
2864 entry_stack &= -OS::ActivationFrameAlignment();
2866 // Store remaining arguments on stack, from low to high memory.
2867 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2868 for (int i = 4; i < argument_count; i++) {
2869 stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t);
2872 set_register(sp, entry_stack);
2874 CallInternal(entry);
2876 // Pop stack passed arguments.
2877 CHECK_EQ(entry_stack, get_register(sp));
2878 set_register(sp, original_stack);
2880 int32_t result = get_register(v0);
2885 double Simulator::CallFP(byte* entry, double d0, double d1) {
2886 if (!IsMipsSoftFloatABI) {
2887 set_fpu_register_double(f12, d0);
2888 set_fpu_register_double(f14, d1);
2891 ASSERT(sizeof(buffer[0]) * 2 == sizeof(d0));
2892 OS::MemCopy(buffer, &d0, sizeof(d0));
2893 set_dw_register(a0, buffer);
2894 OS::MemCopy(buffer, &d1, sizeof(d1));
2895 set_dw_register(a2, buffer);
2897 CallInternal(entry);
2898 if (!IsMipsSoftFloatABI) {
2899 return get_fpu_register_double(f0);
2901 return get_double_from_register_pair(v0);
2906 uintptr_t Simulator::PushAddress(uintptr_t address) {
2907 int new_sp = get_register(sp) - sizeof(uintptr_t);
2908 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2909 *stack_slot = address;
2910 set_register(sp, new_sp);
2915 uintptr_t Simulator::PopAddress() {
2916 int current_sp = get_register(sp);
2917 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2918 uintptr_t address = *stack_slot;
2919 set_register(sp, current_sp + sizeof(uintptr_t));
2926 } } // namespace v8::internal
2928 #endif // USE_SIMULATOR
2930 #endif // V8_TARGET_ARCH_MIPS