34 #if defined(V8_TARGET_ARCH_MIPS)
45 #if defined(USE_SIMULATOR)
52 return ((a ^ b) >= 0);
56 uint32_t get_fcsr_condition_bit(uint32_t
cc) {
69 #define SScanF sscanf // NOLINT
75 explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
78 void Stop(Instruction* instr);
82 void PrintAllRegsIncludingFPU();
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);
99 bool SetBreakpoint(Instruction* breakpc);
100 bool DeleteBreakpoint(Instruction* breakpc);
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) {
127 uint32_t
code = instr->Bits(25, 6);
130 reinterpret_cast<char**
>(sim_->get_pc() + Instr::kInstrSize);
131 char* msg = *msg_address;
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);
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) {
161 uint32_t code = instr->Bits(25, 6);
163 char* msg = *
reinterpret_cast<char**
>(sim_->get_pc() +
166 if (!sim_->watched_stops[code].desc) {
167 sim_->watched_stops[
code].desc = msg;
169 PrintF(
"Simulator hit %s (%u)\n", msg, code);
173 #endif // GENERATED_CODE_COVERAGE
176 int32_t MipsDebugger::GetRegisterValue(
int regnum) {
178 return sim_->get_pc();
180 return sim_->get_register(regnum);
185 int32_t MipsDebugger::GetFPURegisterValueInt(
int regnum) {
187 return sim_->get_pc();
189 return sim_->get_fpu_register(regnum);
194 int64_t MipsDebugger::GetFPURegisterValueLong(
int regnum) {
196 return sim_->get_pc();
198 return sim_->get_fpu_register_long(regnum);
203 float MipsDebugger::GetFPURegisterValueFloat(
int regnum) {
205 return sim_->get_pc();
207 return sim_->get_fpu_register_float(regnum);
212 double MipsDebugger::GetFPURegisterValueDouble(
int regnum) {
214 return sim_->get_pc();
216 return sim_->get_fpu_register_double(regnum);
221 bool MipsDebugger::GetValue(
const char* desc,
int32_t* value) {
226 *value = GetRegisterValue(regnum);
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) {
242 if (sim_->break_pc_ !=
NULL) {
247 sim_->break_pc_ = breakpc;
248 sim_->break_instr_ = breakpc->InstructionBits();
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)
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 };
367 cmd[COMMAND_SIZE] = 0;
375 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
376 if (last_pc != sim_->get_pc()) {
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();
390 char* last_input = sim_->last_debugger_input();
391 if (strcmp(line,
"\n") == 0 && last_input !=
NULL) {
395 sim_->set_last_debugger_input(line);
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()) ||
408 sim_->InstructionDecode(
409 reinterpret_cast<Instruction*>(sim_->get_pc()));
412 PrintF(
"/!\\ Jumping over generated breakpoint.\n");
415 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
417 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
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();
433 value = GetRegisterValue(regnum);
434 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
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",
453 PrintF(
"%s unrecognized\n", arg1);
458 if (strcmp(arg2,
"single") == 0) {
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)) {
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) {
505 if (!GetValue(arg1, &value)) {
506 PrintF(
"%s unrecognized\n", arg1);
509 cur =
reinterpret_cast<int32_t*
>(value);
514 if (argc == next_arg) {
516 }
else if (argc == next_arg + 1) {
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 (current_heap->Contains(obj) || ((value & 1) == 0)) {
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)) {
554 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
556 }
else if (argc == 2) {
561 if (GetValue(arg1, &value)) {
562 cur =
reinterpret_cast<byte*
>(value);
569 if (GetValue(arg1, &value)) {
570 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
578 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
579 cur =
reinterpret_cast<byte*
>(value1);
585 dasm.InstructionDecode(buffer, cur);
587 reinterpret_cast<intptr_t>(cur), buffer.
start());
590 }
else if (strcmp(cmd,
"gdb") == 0) {
591 PrintF(
"relinquishing control to gdb\n");
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() -
617 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
618 Instruction* msg_address =
619 reinterpret_cast<Instruction*
>(stop_pc +
621 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
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) {
631 if (strcmp(arg1,
"info") == 0) {
632 if (strcmp(arg2,
"all") == 0) {
633 PrintF(
"Stop information:\n");
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) {
646 if (strcmp(arg2,
"all") == 0) {
652 }
else if (GetValue(arg2, &value)) {
653 sim_->EnableStop(value);
655 PrintF(
"Unrecognized argument.\n");
657 }
else if (strcmp(arg1,
"disable") == 0) {
659 if (strcmp(arg2,
"all") == 0) {
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)) {
688 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
690 }
else if (argc == 2) {
692 if (GetValue(arg1, &value)) {
693 cur =
reinterpret_cast<byte*
>(value);
700 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
701 cur =
reinterpret_cast<byte*
>(value1);
707 dasm.InstructionDecode(buffer, cur);
709 reinterpret_cast<intptr_t>(cur), buffer.
start());
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");
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");
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");
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");
757 PrintF(
" ignore the stop instruction at the current location\n");
760 PrintF(
"Unknown command: %s\n", cmd);
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) {
798 last_debugger_input_ = input;
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);
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);
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);
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);
865 CHECK(memcmp(reinterpret_cast<void*>(instr),
866 cache_page->CachedData(offset),
870 memcpy(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) {
888 isolate_->set_simulator_i_cache(i_cache_);
893 stack_ =
reinterpret_cast<char*
>(malloc(stack_size_));
894 pc_modified_ =
false;
906 FPUregisters_[i] = 0;
913 registers_[
sp] =
reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
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;
936 Redirection(
void* external_function, ExternalReference::Type type)
937 : external_function_(external_function),
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_),
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();
990 Simulator* Simulator::current(Isolate* isolate) {
992 isolate->FindOrAllocatePerThreadDataForThisThread();
996 Simulator* sim = isolate_data->simulator();
999 sim =
new Simulator(isolate);
1000 isolate_data->set_simulator(sim);
1008 void Simulator::set_register(
int reg,
int32_t value) {
1009 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1011 pc_modified_ =
true;
1015 registers_[reg] = (reg == 0) ? 0 : value;
1019 void Simulator::set_fpu_register(
int fpureg,
int32_t value) {
1020 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1021 FPUregisters_[fpureg] = value;
1025 void Simulator::set_fpu_register_float(
int fpureg,
float value) {
1026 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1027 *BitCast<float*>(&FPUregisters_[fpureg]) = value;
1031 void Simulator::set_fpu_register_double(
int fpureg,
double value) {
1032 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1033 *BitCast<double*>(&FPUregisters_[fpureg]) = value;
1039 int32_t Simulator::get_register(
int reg)
const {
1040 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1048 int32_t Simulator::get_fpu_register(
int fpureg)
const {
1049 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1050 return FPUregisters_[fpureg];
1054 int64_t Simulator::get_fpu_register_long(
int fpureg)
const {
1055 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1056 return *BitCast<int64_t*>(
1057 const_cast<int32_t*
>(&FPUregisters_[fpureg]));
1061 float Simulator::get_fpu_register_float(
int fpureg)
const {
1062 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1063 return *BitCast<float*>(
1064 const_cast<int32_t*
>(&FPUregisters_[fpureg]));
1068 double Simulator::get_fpu_register_double(
int fpureg)
const {
1069 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1070 return *BitCast<double*>(
const_cast<int32_t*
>(&FPUregisters_[fpureg]));
1076 void Simulator::GetFpArgs(
double* x,
double* y) {
1078 *x = get_fpu_register_double(12);
1079 *y = get_fpu_register_double(14);
1083 char buffer[
sizeof(*x)];
1087 reg_buffer[0] = get_register(a0);
1088 reg_buffer[1] = get_register(a1);
1089 memcpy(x, buffer,
sizeof(buffer));
1092 reg_buffer[0] = get_register(a2);
1093 reg_buffer[1] = get_register(a3);
1094 memcpy(y, buffer,
sizeof(buffer));
1101 void Simulator::GetFpArgs(
double* x) {
1103 *x = get_fpu_register_double(12);
1107 char buffer[
sizeof(*x)];
1110 reg_buffer[0] = get_register(a0);
1111 reg_buffer[1] = get_register(a1);
1112 memcpy(x, buffer,
sizeof(buffer));
1119 void Simulator::GetFpArgs(
double* x,
int32_t* y) {
1121 *x = get_fpu_register_double(12);
1122 *y = get_register(a2);
1126 char buffer[
sizeof(*x)];
1129 reg_buffer[0] = get_register(a0);
1130 reg_buffer[1] = get_register(a1);
1131 memcpy(x, buffer,
sizeof(buffer));
1134 reg_buffer[0] = get_register(a2);
1135 memcpy(y, buffer,
sizeof(*y));
1141 void Simulator::SetFpResult(
const double& result) {
1143 set_fpu_register_double(0, result);
1145 char buffer[2 *
sizeof(registers_[0])];
1147 memcpy(buffer, &result,
sizeof(buffer));
1149 set_register(v0, reg_buffer[0]);
1150 set_register(v1, reg_buffer[1]);
1156 void Simulator::set_fcsr_bit(uint32_t cc,
bool value) {
1160 FCSR_ &= ~(1 <<
cc);
1165 bool Simulator::test_fcsr_bit(uint32_t cc) {
1166 return FCSR_ & (1 <<
cc);
1172 bool Simulator::set_fcsr_round_error(
double original,
double rounded) {
1180 if (original != rounded) {
1184 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1189 if (rounded > INT_MAX || rounded < INT_MIN) {
1201 void Simulator::set_pc(
int32_t value) {
1202 pc_modified_ =
true;
1203 registers_[
pc] = value;
1207 bool Simulator::has_bad_pc()
const {
1208 return ((registers_[
pc] == bad_ra) || (registers_[
pc] == end_sim_pc));
1213 int32_t Simulator::get_pc()
const {
1214 return registers_[
pc];
1226 int Simulator::ReadW(
int32_t addr, Instruction* instr) {
1227 if (addr >=0 && addr < 0x400) {
1229 PrintF(
"Memory read from bad address: 0x%08x, pc=0x%08x\n",
1230 addr, reinterpret_cast<intptr_t>(instr));
1231 MipsDebugger dbg(
this);
1235 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1240 reinterpret_cast<intptr_t>(instr));
1241 MipsDebugger dbg(
this);
1247 void Simulator::WriteW(
int32_t addr,
int value, Instruction* instr) {
1248 if (addr >= 0 && addr < 0x400) {
1250 PrintF(
"Memory write to bad address: 0x%08x, pc=0x%08x\n",
1251 addr, reinterpret_cast<intptr_t>(instr));
1252 MipsDebugger dbg(
this);
1255 if ((addr & kPointerAlignmentMask) == 0) {
1256 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1262 reinterpret_cast<intptr_t>(instr));
1263 MipsDebugger dbg(
this);
1268 double Simulator::ReadD(
int32_t addr, Instruction* instr) {
1270 double* ptr =
reinterpret_cast<double*
>(addr);
1275 reinterpret_cast<intptr_t>(instr));
1281 void Simulator::WriteD(
int32_t addr,
double value, Instruction* instr) {
1282 if ((addr & kDoubleAlignmentMask) == 0) {
1283 double* ptr =
reinterpret_cast<double*
>(addr);
1289 reinterpret_cast<intptr_t>(instr));
1295 if ((addr & 1) == 0) {
1299 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1301 reinterpret_cast<intptr_t>(instr));
1308 if ((addr & 1) == 0) {
1312 PrintF(
"Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1314 reinterpret_cast<intptr_t>(instr));
1320 void Simulator::WriteH(
int32_t addr,
uint16_t value, Instruction* instr) {
1321 if ((addr & 1) == 0) {
1326 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1328 reinterpret_cast<intptr_t>(instr));
1333 void Simulator::WriteH(
int32_t addr,
int16_t value, Instruction* instr) {
1334 if ((addr & 1) == 0) {
1341 reinterpret_cast<intptr_t>(instr));
1346 uint32_t Simulator::ReadBU(
int32_t addr) {
1347 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1353 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1358 void Simulator::WriteB(
int32_t addr, uint8_t value) {
1359 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1364 void Simulator::WriteB(
int32_t addr, int8_t value) {
1365 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1371 uintptr_t Simulator::StackLimit()
const {
1374 return reinterpret_cast<uintptr_t
>(stack_) + 1024;
1379 void Simulator::Format(Instruction* instr,
const char* format) {
1380 PrintF(
"Simulator found unsupported instruction:\n 0x%08x: %s\n",
1381 reinterpret_cast<intptr_t>(instr), format);
1392 typedef int64_t (*SimulatorRuntimeCall)(
int32_t arg0,
1398 typedef double (*SimulatorRuntimeFPCall)(
int32_t arg0,
1413 void Simulator::SoftwareInterrupt(Instruction* instr) {
1417 int32_t func = instr->FunctionFieldRaw();
1418 uint32_t code = (func ==
BREAK) ? instr->Bits(25, 6) : -1;
1422 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1423 int32_t arg0 = get_register(a0);
1424 int32_t arg1 = get_register(a1);
1425 int32_t arg2 = get_register(a2);
1426 int32_t arg3 = get_register(a3);
1430 int32_t arg4 = stack_pointer[4];
1431 int32_t arg5 = stack_pointer[5];
1434 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1435 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1436 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1437 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1444 switch (redirection->type()) {
1445 case ExternalReference::BUILTIN_FP_FP_CALL:
1446 case ExternalReference::BUILTIN_COMPARE_CALL:
1447 arg0 = get_fpu_register(
f12);
1448 arg1 = get_fpu_register(
f13);
1449 arg2 = get_fpu_register(
f14);
1450 arg3 = get_fpu_register(
f15);
1452 case ExternalReference::BUILTIN_FP_CALL:
1453 arg0 = get_fpu_register(
f12);
1454 arg1 = get_fpu_register(
f13);
1456 case ExternalReference::BUILTIN_FP_INT_CALL:
1457 arg0 = get_fpu_register(
f12);
1458 arg1 = get_fpu_register(
f13);
1459 arg2 = get_register(a2);
1468 int32_t saved_ra = get_register(ra);
1471 reinterpret_cast<intptr_t
>(redirection->external_function());
1478 SimulatorRuntimeFPCall target =
1479 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1480 if (::v8::internal::FLAG_trace_sim) {
1481 double dval0, dval1;
1483 switch (redirection->type()) {
1484 case ExternalReference::BUILTIN_FP_FP_CALL:
1485 case ExternalReference::BUILTIN_COMPARE_CALL:
1486 GetFpArgs(&dval0, &dval1);
1487 PrintF(
"Call to host function at %p with args %f, %f",
1490 case ExternalReference::BUILTIN_FP_CALL:
1492 PrintF(
"Call to host function at %p with arg %f",
1495 case ExternalReference::BUILTIN_FP_INT_CALL:
1496 GetFpArgs(&dval0, &ival);
1497 PrintF(
"Call to host function at %p with args %f, %d",
1505 if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
1506 SimulatorRuntimeFPCall target =
1507 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1508 double result = target(arg0, arg1, arg2, arg3);
1509 SetFpResult(result);
1511 SimulatorRuntimeCall target =
1512 reinterpret_cast<SimulatorRuntimeCall
>(external);
1513 uint64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1515 memcpy(&gpreg_pair[0], &result, 2 *
sizeof(
int32_t));
1516 set_register(v0, gpreg_pair[0]);
1517 set_register(v1, gpreg_pair[1]);
1519 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1521 SimulatorRuntimeDirectApiCall target =
1522 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1523 if (::v8::internal::FLAG_trace_sim) {
1524 PrintF(
"Call to host function at %p args %08x\n",
1528 *(
reinterpret_cast<int*
>(arg0)) = (
int32_t) *result;
1529 set_register(v0, arg0);
1530 }
else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1532 SimulatorRuntimeDirectGetterCall target =
1533 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1534 if (::v8::internal::FLAG_trace_sim) {
1535 PrintF(
"Call to host function at %p args %08x %08x\n",
1539 *(
reinterpret_cast<int*
>(arg0)) = (
int32_t) *result;
1540 set_register(v0, arg0);
1542 SimulatorRuntimeCall target =
1543 reinterpret_cast<SimulatorRuntimeCall
>(external);
1544 if (::v8::internal::FLAG_trace_sim) {
1546 "Call to host function at %p "
1547 "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1556 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1557 set_register(v0, static_cast<int32_t>(result));
1558 set_register(v1, static_cast<int32_t>(result >> 32));
1560 if (::v8::internal::FLAG_trace_sim) {
1561 PrintF(
"Returned %08x : %08x\n", get_register(v1), get_register(v0));
1563 set_register(ra, saved_ra);
1564 set_pc(get_register(ra));
1567 if (IsWatchpoint(code)) {
1568 PrintWatchpoint(code);
1570 IncreaseStopCounter(code);
1571 HandleStop(code, instr);
1575 MipsDebugger dbg(
this);
1582 bool Simulator::IsWatchpoint(uint32_t code) {
1587 void Simulator::PrintWatchpoint(uint32_t code) {
1588 MipsDebugger dbg(
this);
1590 PrintF(
"\n---- break %d marker: %3d (instr count: %8d) ----------"
1591 "----------------------------------",
1592 code, break_count_, icount_);
1597 void Simulator::HandleStop(uint32_t code, Instruction* instr) {
1600 if (IsEnabledStop(code)) {
1601 MipsDebugger dbg(
this);
1609 bool Simulator::IsStopInstruction(Instruction* instr) {
1610 int32_t func = instr->FunctionFieldRaw();
1611 uint32_t code =
static_cast<uint32_t
>(instr->Bits(25, 6));
1616 bool Simulator::IsEnabledStop(uint32_t code) {
1619 return !(watched_stops[
code].count & kStopDisabledBit);
1623 void Simulator::EnableStop(uint32_t code) {
1624 if (!IsEnabledStop(code)) {
1625 watched_stops[
code].count &= ~kStopDisabledBit;
1630 void Simulator::DisableStop(uint32_t code) {
1631 if (IsEnabledStop(code)) {
1632 watched_stops[
code].count |= kStopDisabledBit;
1637 void Simulator::IncreaseStopCounter(uint32_t code) {
1639 if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
1640 PrintF(
"Stop counter for code %i has overflowed.\n"
1641 "Enabling this code and reseting the counter to 0.\n", code);
1642 watched_stops[
code].count = 0;
1645 watched_stops[
code].count++;
1651 void Simulator::PrintStopInfo(uint32_t code) {
1653 PrintF(
"That is a watchpoint, not a stop.\n");
1659 const char* state = IsEnabledStop(code) ?
"Enabled" :
"Disabled";
1660 int32_t count = watched_stops[
code].count & ~kStopDisabledBit;
1663 if (watched_stops[code].desc) {
1664 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1665 code, code, state, count, watched_stops[code].desc);
1667 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
1668 code, code, state, count);
1674 void Simulator::SignalExceptions() {
1675 for (
int i = 1; i < kNumExceptions; i++) {
1676 if (exceptions[i] != 0) {
1677 V8_Fatal(__FILE__, __LINE__,
"Error: Exception %i raised.", i);
1685 void Simulator::ConfigureTypeRegister(Instruction* instr,
1690 bool& do_interrupt) {
1696 const Opcode op = instr->OpcodeFieldRaw();
1697 const int32_t rs_reg = instr->RsValue();
1698 const int32_t rs = get_register(rs_reg);
1699 const uint32_t rs_u =
static_cast<uint32_t
>(rs);
1700 const int32_t rt_reg = instr->RtValue();
1701 const int32_t rt = get_register(rt_reg);
1702 const uint32_t rt_u =
static_cast<uint32_t
>(rt);
1703 const int32_t rd_reg = instr->RdValue();
1704 const uint32_t sa = instr->SaValue();
1706 const int32_t fs_reg = instr->FsValue();
1712 switch (instr->RsFieldRaw()) {
1722 alu_out = get_fpu_register(fs_reg);
1744 switch (instr->FunctionFieldRaw()) {
1747 next_pc = get_register(instr->RsValue());
1756 alu_out = rt_u >> sa;
1761 alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1774 alu_out = rt_u >> rs;
1779 alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1786 alu_out = get_register(HI);
1789 alu_out = get_register(LO);
1792 i64hilo =
static_cast<int64_t
>(rs) * static_cast<int64_t>(rt);
1795 u64hilo =
static_cast<uint64_t
>(rs_u) * static_cast<uint64_t>(rt_u);
1798 if (HaveSameSign(rs, rt)) {
1801 }
else if (rs < 0) {
1811 if (!HaveSameSign(rs, rt)) {
1814 }
else if (rs < 0) {
1833 alu_out = ~(rs | rt);
1836 alu_out = rs < rt ? 1 : 0;
1839 alu_out = rs_u < rt_u ? 1 : 0;
1844 do_interrupt =
true;
1847 do_interrupt = rs >= rt;
1850 do_interrupt = rs_u >= rt_u;
1853 do_interrupt = rs < rt;
1856 do_interrupt = rs_u < rt_u;
1859 do_interrupt = rs == rt;
1862 do_interrupt = rs != rt;
1878 switch (instr->FunctionFieldRaw()) {
1880 alu_out = rs_u * rt_u;
1883 alu_out = __builtin_clz(rs_u);
1890 switch (instr->FunctionFieldRaw()) {
1897 uint32_t mask = (1 << size) - 1;
1898 alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1907 uint32_t mask = (1 << size) - 1;
1908 alu_out = (rs_u & (mask << lsb)) >> lsb;
1921 void Simulator::DecodeTypeRegister(Instruction* instr) {
1923 const Opcode op = instr->OpcodeFieldRaw();
1924 const int32_t rs_reg = instr->RsValue();
1925 const int32_t rs = get_register(rs_reg);
1926 const uint32_t rs_u =
static_cast<uint32_t
>(rs);
1927 const int32_t rt_reg = instr->RtValue();
1928 const int32_t rt = get_register(rt_reg);
1929 const uint32_t rt_u =
static_cast<uint32_t
>(rt);
1930 const int32_t rd_reg = instr->RdValue();
1932 const int32_t fs_reg = instr->FsValue();
1933 const int32_t ft_reg = instr->FtValue();
1934 const int32_t fd_reg = instr->FdValue();
1935 int64_t i64hilo = 0;
1936 uint64_t u64hilo = 0;
1944 bool do_interrupt =
false;
1948 int32_t current_pc = get_pc();
1953 ConfigureTypeRegister(instr,
1966 switch (instr->RsFieldRaw()) {
1971 set_register(rt_reg, alu_out);
1973 set_register(rt_reg, alu_out);
1981 FCSR_ = registers_[rt_reg];
1984 FPUregisters_[fs_reg] = registers_[rt_reg];
1991 switch (instr->FunctionFieldRaw()) {
1993 f = get_fpu_register_float(fs_reg);
1994 set_fpu_register_double(fd_reg, static_cast<double>(f));
2015 uint32_t
cc, fcsr_cc;
2017 fs = get_fpu_register_double(fs_reg);
2018 ft = get_fpu_register_double(ft_reg);
2019 cc = instr->FCccValue();
2020 fcsr_cc = get_fcsr_condition_bit(cc);
2021 switch (instr->FunctionFieldRaw()) {
2023 set_fpu_register_double(fd_reg, fs + ft);
2026 set_fpu_register_double(fd_reg, fs - ft);
2029 set_fpu_register_double(fd_reg, fs * ft);
2032 set_fpu_register_double(fd_reg, fs / ft);
2035 set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
2038 set_fpu_register_double(fd_reg, fs);
2041 set_fpu_register_double(fd_reg, -fs);
2044 set_fpu_register_double(fd_reg, sqrt(fs));
2047 set_fcsr_bit(fcsr_cc,
isnan(fs) ||
isnan(ft));
2050 set_fcsr_bit(fcsr_cc, (fs == ft));
2053 set_fcsr_bit(fcsr_cc, (fs == ft) || (
isnan(fs) ||
isnan(ft)));
2056 set_fcsr_bit(fcsr_cc, (fs < ft));
2059 set_fcsr_bit(fcsr_cc, (fs < ft) || (
isnan(fs) ||
isnan(ft)));
2062 set_fcsr_bit(fcsr_cc, (fs <= ft));
2065 set_fcsr_bit(fcsr_cc, (fs <= ft) || (
isnan(fs) ||
isnan(ft)));
2069 ASSERT((FCSR_ & 3) == 0);
2073 double rounded = floor(fs + 0.5);
2075 if ((result & 1) != 0 && result - fs == 0.5) {
2080 set_fpu_register(fd_reg, result);
2081 if (set_fcsr_round_error(fs, rounded)) {
2088 double rounded = trunc(fs);
2090 set_fpu_register(fd_reg, result);
2091 if (set_fcsr_round_error(fs, rounded)) {
2098 double rounded = floor(fs);
2100 set_fpu_register(fd_reg, result);
2101 if (set_fcsr_round_error(fs, rounded)) {
2108 double rounded = ceil(fs);
2110 set_fpu_register(fd_reg, result);
2111 if (set_fcsr_round_error(fs, rounded)) {
2117 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2120 double rounded = trunc(fs);
2121 i64 =
static_cast<int64_t
>(rounded);
2122 set_fpu_register(fd_reg, i64 & 0xffffffff);
2123 set_fpu_register(fd_reg + 1, i64 >> 32);
2127 double rounded = trunc(fs);
2128 i64 =
static_cast<int64_t
>(rounded);
2129 set_fpu_register(fd_reg, i64 & 0xffffffff);
2130 set_fpu_register(fd_reg + 1, i64 >> 32);
2134 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2135 i64 =
static_cast<int64_t
>(rounded);
2136 set_fpu_register(fd_reg, i64 & 0xffffffff);
2137 set_fpu_register(fd_reg + 1, i64 >> 32);
2141 i64 =
static_cast<int64_t
>(floor(fs));
2142 set_fpu_register(fd_reg, i64 & 0xffffffff);
2143 set_fpu_register(fd_reg + 1, i64 >> 32);
2146 i64 =
static_cast<int64_t
>(ceil(fs));
2147 set_fpu_register(fd_reg, i64 & 0xffffffff);
2148 set_fpu_register(fd_reg + 1, i64 >> 32);
2158 switch (instr->FunctionFieldRaw()) {
2160 alu_out = get_fpu_register(fs_reg);
2161 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2164 alu_out = get_fpu_register(fs_reg);
2165 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2172 switch (instr->FunctionFieldRaw()) {
2176 i64 = (uint32_t) get_fpu_register(fs_reg);
2177 i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
2178 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2194 switch (instr->FunctionFieldRaw()) {
2196 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2198 BranchDelayInstructionDecode(branch_delay_instr);
2200 pc_modified_ =
true;
2204 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2206 BranchDelayInstructionDecode(branch_delay_instr);
2209 pc_modified_ =
true;
2214 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2215 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2218 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2219 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2226 set_register(LO, rs / rt);
2227 set_register(HI, rs % rt);
2232 set_register(LO, rs_u / rt_u);
2233 set_register(HI, rs_u % rt_u);
2245 SoftwareInterrupt(instr);
2250 if (rt) set_register(rd_reg, rs);
2253 uint32_t cc = instr->FBccValue();
2254 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2255 if (instr->Bit(16)) {
2256 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2258 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2263 if (!rt) set_register(rd_reg, rs);
2266 set_register(rd_reg, alu_out);
2270 switch (instr->FunctionFieldRaw()) {
2272 set_register(rd_reg, alu_out);
2274 set_register(LO, Unpredictable);
2275 set_register(HI, Unpredictable);
2278 set_register(rd_reg, alu_out);
2282 switch (instr->FunctionFieldRaw()) {
2285 set_register(rt_reg, alu_out);
2289 set_register(rt_reg, alu_out);
2299 set_register(rd_reg, alu_out);
2305 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2307 Opcode op = instr->OpcodeFieldRaw();
2308 int32_t rs = get_register(instr->RsValue());
2309 uint32_t rs_u =
static_cast<uint32_t
>(rs);
2310 int32_t rt_reg = instr->RtValue();
2311 int32_t rt = get_register(rt_reg);
2312 int16_t imm16 = instr->Imm16Value();
2314 int32_t ft_reg = instr->FtValue();
2317 uint32_t oe_imm16 = 0xffff & imm16;
2322 int32_t current_pc = get_pc();
2327 bool do_branch =
false;
2328 bool execute_branch_delay_instruction =
false;
2333 double fp_out = 0.0;
2334 uint32_t
cc, cc_value, fcsr_cc;
2339 uint32_t mem_value = 0x0;
2345 switch (instr->RsFieldRaw()) {
2347 cc = instr->FBccValue();
2348 fcsr_cc = get_fcsr_condition_bit(cc);
2349 cc_value = test_fcsr_bit(fcsr_cc);
2350 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2351 execute_branch_delay_instruction =
true;
2365 switch (instr->RtFieldRaw()) {
2367 do_branch = (rs < 0);
2373 do_branch = rs >= 0;
2376 do_branch = rs >= 0;
2381 switch (instr->RtFieldRaw()) {
2387 execute_branch_delay_instruction =
true;
2391 if (instr->IsLinkingInstruction()) {
2405 do_branch = (rs == rt);
2408 do_branch = rs != rt;
2411 do_branch = rs <= 0;
2418 if (HaveSameSign(rs, se_imm16)) {
2421 }
else if (rs < 0) {
2422 exceptions[kIntegerUnderflow] =
2426 alu_out = rs + se_imm16;
2429 alu_out = rs + se_imm16;
2432 alu_out = (rs < se_imm16) ? 1 : 0;
2435 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2438 alu_out = rs & oe_imm16;
2441 alu_out = rs | oe_imm16;
2444 alu_out = rs ^ oe_imm16;
2447 alu_out = (oe_imm16 << 16);
2451 addr = rs + se_imm16;
2452 alu_out = ReadB(addr);
2455 addr = rs + se_imm16;
2456 alu_out = ReadH(addr, instr);
2460 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2461 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2462 uint32_t mask = (1 << byte_shift * 8) - 1;
2463 addr = rs + se_imm16 - al_offset;
2464 alu_out = ReadW(addr, instr);
2465 alu_out <<= byte_shift * 8;
2466 alu_out |= rt & mask;
2470 addr = rs + se_imm16;
2471 alu_out = ReadW(addr, instr);
2474 addr = rs + se_imm16;
2475 alu_out = ReadBU(addr);
2478 addr = rs + se_imm16;
2479 alu_out = ReadHU(addr, instr);
2483 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2484 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2485 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2486 addr = rs + se_imm16 - al_offset;
2487 alu_out = ReadW(addr, instr);
2488 alu_out =
static_cast<uint32_t
> (alu_out) >> al_offset * 8;
2489 alu_out |= rt & mask;
2493 addr = rs + se_imm16;
2496 addr = rs + se_imm16;
2499 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2500 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2501 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2502 addr = rs + se_imm16 - al_offset;
2503 mem_value = ReadW(addr, instr) & mask;
2504 mem_value |=
static_cast<uint32_t
>(rt) >> byte_shift * 8;
2508 addr = rs + se_imm16;
2511 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2512 uint32_t mask = (1 << al_offset * 8) - 1;
2513 addr = rs + se_imm16 - al_offset;
2514 mem_value = ReadW(addr, instr);
2515 mem_value = (rt << al_offset * 8) | (mem_value & mask);
2519 addr = rs + se_imm16;
2520 alu_out = ReadW(addr, instr);
2523 addr = rs + se_imm16;
2524 fp_out = ReadD(addr, instr);
2528 addr = rs + se_imm16;
2545 execute_branch_delay_instruction =
true;
2549 if (instr->IsLinkingInstruction()) {
2565 set_register(rt_reg, alu_out);
2575 set_register(rt_reg, alu_out);
2578 WriteB(addr, static_cast<int8_t>(rt));
2581 WriteH(addr, static_cast<uint16_t>(rt), instr);
2584 WriteW(addr, mem_value, instr);
2587 WriteW(addr, rt, instr);
2590 WriteW(addr, mem_value, instr);
2593 set_fpu_register(ft_reg, alu_out);
2596 set_fpu_register_double(ft_reg, fp_out);
2599 addr = rs + se_imm16;
2600 WriteW(addr, get_fpu_register(ft_reg), instr);
2603 addr = rs + se_imm16;
2604 WriteD(addr, get_fpu_register_double(ft_reg), instr);
2611 if (execute_branch_delay_instruction) {
2615 Instruction* branch_delay_instr =
2617 BranchDelayInstructionDecode(branch_delay_instr);
2621 if (next_pc != bad_ra) {
2628 void Simulator::DecodeTypeJump(Instruction* instr) {
2630 int32_t current_pc = get_pc();
2632 int32_t pc_high_bits = current_pc & 0xf0000000;
2634 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2639 Instruction* branch_delay_instr =
2641 BranchDelayInstructionDecode(branch_delay_instr);
2645 if (instr->IsLinkingInstruction()) {
2649 pc_modified_ =
true;
2654 void Simulator::InstructionDecode(Instruction* instr) {
2655 if (v8::internal::FLAG_check_icache) {
2656 CheckICache(isolate_->simulator_i_cache(), instr);
2658 pc_modified_ =
false;
2659 if (::v8::internal::FLAG_trace_sim) {
2664 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2665 PrintF(
" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2669 switch (instr->InstructionType()) {
2671 DecodeTypeRegister(instr);
2674 DecodeTypeImmediate(instr);
2677 DecodeTypeJump(instr);
2682 if (!pc_modified_) {
2683 set_register(
pc, reinterpret_cast<int32_t>(instr) +
2690 void Simulator::Execute() {
2693 int program_counter = get_pc();
2694 if (::v8::internal::FLAG_stop_sim_at == 0) {
2697 while (program_counter != end_sim_pc) {
2698 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
2700 InstructionDecode(instr);
2701 program_counter = get_pc();
2706 while (program_counter != end_sim_pc) {
2707 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
2709 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2710 MipsDebugger dbg(
this);
2713 InstructionDecode(instr);
2715 program_counter = get_pc();
2721 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
2723 va_start(parameters, argument_count);
2727 ASSERT(argument_count >= 4);
2728 set_register(a0, va_arg(parameters,
int32_t));
2729 set_register(a1, va_arg(parameters,
int32_t));
2730 set_register(a2, va_arg(parameters,
int32_t));
2731 set_register(a3, va_arg(parameters,
int32_t));
2734 int original_stack = get_register(
sp);
2736 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t)
2742 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
2743 for (
int i = 4; i < argument_count; i++) {
2747 set_register(
sp, entry_stack);
2750 set_register(
pc, reinterpret_cast<int32_t>(entry));
2754 set_register(ra, end_sim_pc);
2767 int32_t gp_val = get_register(gp);
2773 int32_t callee_saved_value = icount_;
2774 set_register(
s0, callee_saved_value);
2775 set_register(
s1, callee_saved_value);
2776 set_register(
s2, callee_saved_value);
2777 set_register(
s3, callee_saved_value);
2778 set_register(
s4, callee_saved_value);
2779 set_register(
s5, callee_saved_value);
2780 set_register(
s6, callee_saved_value);
2781 set_register(
s7, callee_saved_value);
2782 set_register(gp, callee_saved_value);
2783 set_register(
fp, callee_saved_value);
2789 CHECK_EQ(callee_saved_value, get_register(
s0));
2790 CHECK_EQ(callee_saved_value, get_register(
s1));
2791 CHECK_EQ(callee_saved_value, get_register(
s2));
2792 CHECK_EQ(callee_saved_value, get_register(
s3));
2793 CHECK_EQ(callee_saved_value, get_register(
s4));
2794 CHECK_EQ(callee_saved_value, get_register(
s5));
2795 CHECK_EQ(callee_saved_value, get_register(
s6));
2796 CHECK_EQ(callee_saved_value, get_register(
s7));
2797 CHECK_EQ(callee_saved_value, get_register(gp));
2798 CHECK_EQ(callee_saved_value, get_register(
fp));
2801 set_register(
s0, s0_val);
2802 set_register(
s1, s1_val);
2803 set_register(
s2, s2_val);
2804 set_register(
s3, s3_val);
2805 set_register(
s4, s4_val);
2806 set_register(
s5, s5_val);
2807 set_register(
s6, s6_val);
2808 set_register(
s7, s7_val);
2809 set_register(gp, gp_val);
2810 set_register(
sp, sp_val);
2811 set_register(
fp, fp_val);
2815 set_register(
sp, original_stack);
2817 int32_t result = get_register(v0);
2822 uintptr_t Simulator::PushAddress(uintptr_t address) {
2823 int new_sp = get_register(
sp) -
sizeof(uintptr_t);
2824 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
2825 *stack_slot = address;
2826 set_register(
sp, new_sp);
2831 uintptr_t Simulator::PopAddress() {
2832 int current_sp = get_register(
sp);
2833 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
2834 uintptr_t address = *stack_slot;
2835 set_register(
sp, current_sp +
sizeof(uintptr_t));
2844 #endif // USE_SIMULATOR
2846 #endif // V8_TARGET_ARCH_MIPS
const int kCArgsSlotsSize
const uint32_t kFCSRUnderflowFlagBit
#define CHECK_EQ(expected, value)
const intptr_t kDoubleAlignmentMask
const uint32_t kFCSRInexactFlagBit
void PrintF(const char *format,...)
const int kBranchReturnOffset
const int kNumSimuRegisters
const uint32_t kMaxWatchpointCode
const int kInvalidFPURegister
static const int32_t kMaxValue
const uint32_t kMaxStopCode
#define ASSERT(condition)
const int kInvalidRegister
char * ReadLine(const char *prompt)
const int kNumFPURegisters
void V8_Fatal(const char *file, int line, const char *format,...)
const Instr rtCallRedirInstr
const uint32_t kFPUInvalidResult
static int Number(const char *name)
#define OFFSET_OF(type, field)
const bool IsMipsSoftFloatABI
const uint32_t kFCSRInvalidOpFlagBit
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
#define UNIMPLEMENTED_MIPS()
const uint32_t kFCSROverflowFlagBit
static const char * Name(int reg)
const intptr_t kPointerAlignmentMask
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
#define ASSERT_EQ(v1, v2)
static int ActivationFrameAlignment()
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static int Number(const char *name)
void DeleteArray(T *array)
static const int32_t kMinValue