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 = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2075 set_fpu_register(fd_reg, result);
2076 if (set_fcsr_round_error(fs, rounded)) {
2083 double rounded = trunc(fs);
2085 set_fpu_register(fd_reg, result);
2086 if (set_fcsr_round_error(fs, rounded)) {
2093 double rounded = floor(fs);
2095 set_fpu_register(fd_reg, result);
2096 if (set_fcsr_round_error(fs, rounded)) {
2103 double rounded = ceil(fs);
2105 set_fpu_register(fd_reg, result);
2106 if (set_fcsr_round_error(fs, rounded)) {
2112 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2115 double rounded = trunc(fs);
2116 i64 =
static_cast<int64_t
>(rounded);
2117 set_fpu_register(fd_reg, i64 & 0xffffffff);
2118 set_fpu_register(fd_reg + 1, i64 >> 32);
2122 double rounded = trunc(fs);
2123 i64 =
static_cast<int64_t
>(rounded);
2124 set_fpu_register(fd_reg, i64 & 0xffffffff);
2125 set_fpu_register(fd_reg + 1, i64 >> 32);
2129 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2130 i64 =
static_cast<int64_t
>(rounded);
2131 set_fpu_register(fd_reg, i64 & 0xffffffff);
2132 set_fpu_register(fd_reg + 1, i64 >> 32);
2136 i64 =
static_cast<int64_t
>(floor(fs));
2137 set_fpu_register(fd_reg, i64 & 0xffffffff);
2138 set_fpu_register(fd_reg + 1, i64 >> 32);
2141 i64 =
static_cast<int64_t
>(ceil(fs));
2142 set_fpu_register(fd_reg, i64 & 0xffffffff);
2143 set_fpu_register(fd_reg + 1, i64 >> 32);
2153 switch (instr->FunctionFieldRaw()) {
2155 alu_out = get_fpu_register(fs_reg);
2156 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2159 alu_out = get_fpu_register(fs_reg);
2160 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2167 switch (instr->FunctionFieldRaw()) {
2171 i64 = (uint32_t) get_fpu_register(fs_reg);
2172 i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
2173 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2189 switch (instr->FunctionFieldRaw()) {
2191 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2193 BranchDelayInstructionDecode(branch_delay_instr);
2195 pc_modified_ =
true;
2199 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2201 BranchDelayInstructionDecode(branch_delay_instr);
2204 pc_modified_ =
true;
2209 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2210 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2213 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2214 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2221 set_register(LO, rs / rt);
2222 set_register(HI, rs % rt);
2227 set_register(LO, rs_u / rt_u);
2228 set_register(HI, rs_u % rt_u);
2240 SoftwareInterrupt(instr);
2245 if (rt) set_register(rd_reg, rs);
2248 uint32_t cc = instr->FBccValue();
2249 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2250 if (instr->Bit(16)) {
2251 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2253 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2258 if (!rt) set_register(rd_reg, rs);
2261 set_register(rd_reg, alu_out);
2265 switch (instr->FunctionFieldRaw()) {
2267 set_register(rd_reg, alu_out);
2269 set_register(LO, Unpredictable);
2270 set_register(HI, Unpredictable);
2273 set_register(rd_reg, alu_out);
2277 switch (instr->FunctionFieldRaw()) {
2280 set_register(rt_reg, alu_out);
2284 set_register(rt_reg, alu_out);
2294 set_register(rd_reg, alu_out);
2300 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2302 Opcode op = instr->OpcodeFieldRaw();
2303 int32_t rs = get_register(instr->RsValue());
2304 uint32_t rs_u =
static_cast<uint32_t
>(rs);
2305 int32_t rt_reg = instr->RtValue();
2306 int32_t rt = get_register(rt_reg);
2307 int16_t imm16 = instr->Imm16Value();
2309 int32_t ft_reg = instr->FtValue();
2312 uint32_t oe_imm16 = 0xffff & imm16;
2317 int32_t current_pc = get_pc();
2322 bool do_branch =
false;
2323 bool execute_branch_delay_instruction =
false;
2328 double fp_out = 0.0;
2329 uint32_t
cc, cc_value, fcsr_cc;
2334 uint32_t mem_value = 0x0;
2340 switch (instr->RsFieldRaw()) {
2342 cc = instr->FBccValue();
2343 fcsr_cc = get_fcsr_condition_bit(cc);
2344 cc_value = test_fcsr_bit(fcsr_cc);
2345 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2346 execute_branch_delay_instruction =
true;
2360 switch (instr->RtFieldRaw()) {
2362 do_branch = (rs < 0);
2368 do_branch = rs >= 0;
2371 do_branch = rs >= 0;
2376 switch (instr->RtFieldRaw()) {
2382 execute_branch_delay_instruction =
true;
2386 if (instr->IsLinkingInstruction()) {
2400 do_branch = (rs == rt);
2403 do_branch = rs != rt;
2406 do_branch = rs <= 0;
2413 if (HaveSameSign(rs, se_imm16)) {
2416 }
else if (rs < 0) {
2417 exceptions[kIntegerUnderflow] =
2421 alu_out = rs + se_imm16;
2424 alu_out = rs + se_imm16;
2427 alu_out = (rs < se_imm16) ? 1 : 0;
2430 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2433 alu_out = rs & oe_imm16;
2436 alu_out = rs | oe_imm16;
2439 alu_out = rs ^ oe_imm16;
2442 alu_out = (oe_imm16 << 16);
2446 addr = rs + se_imm16;
2447 alu_out = ReadB(addr);
2450 addr = rs + se_imm16;
2451 alu_out = ReadH(addr, instr);
2455 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2456 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2457 uint32_t mask = (1 << byte_shift * 8) - 1;
2458 addr = rs + se_imm16 - al_offset;
2459 alu_out = ReadW(addr, instr);
2460 alu_out <<= byte_shift * 8;
2461 alu_out |= rt & mask;
2465 addr = rs + se_imm16;
2466 alu_out = ReadW(addr, instr);
2469 addr = rs + se_imm16;
2470 alu_out = ReadBU(addr);
2473 addr = rs + se_imm16;
2474 alu_out = ReadHU(addr, instr);
2478 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2479 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2480 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2481 addr = rs + se_imm16 - al_offset;
2482 alu_out = ReadW(addr, instr);
2483 alu_out =
static_cast<uint32_t
> (alu_out) >> al_offset * 8;
2484 alu_out |= rt & mask;
2488 addr = rs + se_imm16;
2491 addr = rs + se_imm16;
2494 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2495 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2496 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2497 addr = rs + se_imm16 - al_offset;
2498 mem_value = ReadW(addr, instr) & mask;
2499 mem_value |=
static_cast<uint32_t
>(rt) >> byte_shift * 8;
2503 addr = rs + se_imm16;
2506 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2507 uint32_t mask = (1 << al_offset * 8) - 1;
2508 addr = rs + se_imm16 - al_offset;
2509 mem_value = ReadW(addr, instr);
2510 mem_value = (rt << al_offset * 8) | (mem_value & mask);
2514 addr = rs + se_imm16;
2515 alu_out = ReadW(addr, instr);
2518 addr = rs + se_imm16;
2519 fp_out = ReadD(addr, instr);
2523 addr = rs + se_imm16;
2540 execute_branch_delay_instruction =
true;
2544 if (instr->IsLinkingInstruction()) {
2560 set_register(rt_reg, alu_out);
2570 set_register(rt_reg, alu_out);
2573 WriteB(addr, static_cast<int8_t>(rt));
2576 WriteH(addr, static_cast<uint16_t>(rt), instr);
2579 WriteW(addr, mem_value, instr);
2582 WriteW(addr, rt, instr);
2585 WriteW(addr, mem_value, instr);
2588 set_fpu_register(ft_reg, alu_out);
2591 set_fpu_register_double(ft_reg, fp_out);
2594 addr = rs + se_imm16;
2595 WriteW(addr, get_fpu_register(ft_reg), instr);
2598 addr = rs + se_imm16;
2599 WriteD(addr, get_fpu_register_double(ft_reg), instr);
2606 if (execute_branch_delay_instruction) {
2610 Instruction* branch_delay_instr =
2612 BranchDelayInstructionDecode(branch_delay_instr);
2616 if (next_pc != bad_ra) {
2623 void Simulator::DecodeTypeJump(Instruction* instr) {
2625 int32_t current_pc = get_pc();
2627 int32_t pc_high_bits = current_pc & 0xf0000000;
2629 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2634 Instruction* branch_delay_instr =
2636 BranchDelayInstructionDecode(branch_delay_instr);
2640 if (instr->IsLinkingInstruction()) {
2644 pc_modified_ =
true;
2649 void Simulator::InstructionDecode(Instruction* instr) {
2650 if (v8::internal::FLAG_check_icache) {
2651 CheckICache(isolate_->simulator_i_cache(), instr);
2653 pc_modified_ =
false;
2654 if (::v8::internal::FLAG_trace_sim) {
2659 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2660 PrintF(
" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2664 switch (instr->InstructionType()) {
2666 DecodeTypeRegister(instr);
2669 DecodeTypeImmediate(instr);
2672 DecodeTypeJump(instr);
2677 if (!pc_modified_) {
2678 set_register(
pc, reinterpret_cast<int32_t>(instr) +
2685 void Simulator::Execute() {
2688 int program_counter = get_pc();
2689 if (::v8::internal::FLAG_stop_sim_at == 0) {
2692 while (program_counter != end_sim_pc) {
2693 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
2695 InstructionDecode(instr);
2696 program_counter = get_pc();
2701 while (program_counter != end_sim_pc) {
2702 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
2704 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2705 MipsDebugger dbg(
this);
2708 InstructionDecode(instr);
2710 program_counter = get_pc();
2716 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
2718 va_start(parameters, argument_count);
2722 ASSERT(argument_count >= 4);
2723 set_register(a0, va_arg(parameters,
int32_t));
2724 set_register(a1, va_arg(parameters,
int32_t));
2725 set_register(a2, va_arg(parameters,
int32_t));
2726 set_register(a3, va_arg(parameters,
int32_t));
2729 int original_stack = get_register(
sp);
2731 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t)
2737 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
2738 for (
int i = 4; i < argument_count; i++) {
2742 set_register(
sp, entry_stack);
2745 set_register(
pc, reinterpret_cast<int32_t>(entry));
2749 set_register(ra, end_sim_pc);
2762 int32_t gp_val = get_register(gp);
2768 int32_t callee_saved_value = icount_;
2769 set_register(
s0, callee_saved_value);
2770 set_register(
s1, callee_saved_value);
2771 set_register(
s2, callee_saved_value);
2772 set_register(
s3, callee_saved_value);
2773 set_register(
s4, callee_saved_value);
2774 set_register(
s5, callee_saved_value);
2775 set_register(
s6, callee_saved_value);
2776 set_register(
s7, callee_saved_value);
2777 set_register(gp, callee_saved_value);
2778 set_register(
fp, callee_saved_value);
2784 CHECK_EQ(callee_saved_value, get_register(
s0));
2785 CHECK_EQ(callee_saved_value, get_register(
s1));
2786 CHECK_EQ(callee_saved_value, get_register(
s2));
2787 CHECK_EQ(callee_saved_value, get_register(
s3));
2788 CHECK_EQ(callee_saved_value, get_register(
s4));
2789 CHECK_EQ(callee_saved_value, get_register(
s5));
2790 CHECK_EQ(callee_saved_value, get_register(
s6));
2791 CHECK_EQ(callee_saved_value, get_register(
s7));
2792 CHECK_EQ(callee_saved_value, get_register(gp));
2793 CHECK_EQ(callee_saved_value, get_register(
fp));
2796 set_register(
s0, s0_val);
2797 set_register(
s1, s1_val);
2798 set_register(
s2, s2_val);
2799 set_register(
s3, s3_val);
2800 set_register(
s4, s4_val);
2801 set_register(
s5, s5_val);
2802 set_register(
s6, s6_val);
2803 set_register(
s7, s7_val);
2804 set_register(gp, gp_val);
2805 set_register(
sp, sp_val);
2806 set_register(
fp, fp_val);
2810 set_register(
sp, original_stack);
2812 int32_t result = get_register(v0);
2817 uintptr_t Simulator::PushAddress(uintptr_t address) {
2818 int new_sp = get_register(
sp) -
sizeof(uintptr_t);
2819 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
2820 *stack_slot = address;
2821 set_register(
sp, new_sp);
2826 uintptr_t Simulator::PopAddress() {
2827 int current_sp = get_register(
sp);
2828 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
2829 uintptr_t address = *stack_slot;
2830 set_register(
sp, current_sp +
sizeof(uintptr_t));
2839 #endif // USE_SIMULATOR
2841 #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)
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static int ActivationFrameAlignment()
static int Number(const char *name)
void DeleteArray(T *array)
static const int32_t kMinValue