35 #if V8_TARGET_ARCH_MIPS
46 #if defined(USE_SIMULATOR)
53 return ((a ^ b) >= 0);
57 uint32_t get_fcsr_condition_bit(uint32_t
cc) {
70 #define SScanF sscanf // NOLINT
76 explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
79 void Stop(Instruction* instr);
83 void PrintAllRegsIncludingFPU();
88 static const Instr kNopInstr = 0x0;
92 int32_t GetRegisterValue(
int regnum);
93 int32_t GetFPURegisterValueInt(
int regnum);
94 int64_t GetFPURegisterValueLong(
int regnum);
95 float GetFPURegisterValueFloat(
int regnum);
96 double GetFPURegisterValueDouble(
int regnum);
97 bool GetValue(
const char* desc,
int32_t* value);
100 bool SetBreakpoint(Instruction* breakpc);
101 bool DeleteBreakpoint(Instruction* breakpc);
105 void UndoBreakpoints();
106 void RedoBreakpoints();
110 MipsDebugger::~MipsDebugger() {
114 #ifdef GENERATED_CODE_COVERAGE
115 static FILE* coverage_log =
NULL;
118 static void InitializeCoverage() {
119 char* file_name = getenv(
"V8_GENERATED_CODE_COVERAGE_LOG");
120 if (file_name !=
NULL) {
121 coverage_log = fopen(file_name,
"aw+");
126 void MipsDebugger::Stop(Instruction* instr) {
128 uint32_t
code = instr->Bits(25, 6);
131 reinterpret_cast<char**
>(sim_->get_pc() + Instr::kInstrSize);
132 char* msg = *msg_address;
136 if (!watched_stops_[code].desc) {
137 watched_stops_[
code].desc = msg;
140 if (strlen(msg) > 0) {
141 if (coverage_log !=
NULL) {
142 fprintf(coverage_log,
"%s\n", str);
143 fflush(coverage_log);
146 instr->SetInstructionBits(kNopInstr);
147 reinterpret_cast<Instr*
>(msg_address)->SetInstructionBits(kNopInstr);
153 #else // GENERATED_CODE_COVERAGE
155 #define UNSUPPORTED() printf("Unsupported instruction.\n");
157 static void InitializeCoverage() {}
160 void MipsDebugger::Stop(Instruction* instr) {
162 uint32_t code = instr->Bits(25, 6);
164 char* msg = *
reinterpret_cast<char**
>(sim_->get_pc() +
167 if (!sim_->watched_stops_[code].desc) {
168 sim_->watched_stops_[
code].desc = msg;
170 PrintF(
"Simulator hit %s (%u)\n", msg, code);
174 #endif // GENERATED_CODE_COVERAGE
177 int32_t MipsDebugger::GetRegisterValue(
int regnum) {
179 return sim_->get_pc();
181 return sim_->get_register(regnum);
186 int32_t MipsDebugger::GetFPURegisterValueInt(
int regnum) {
188 return sim_->get_pc();
190 return sim_->get_fpu_register(regnum);
195 int64_t MipsDebugger::GetFPURegisterValueLong(
int regnum) {
197 return sim_->get_pc();
199 return sim_->get_fpu_register_long(regnum);
204 float MipsDebugger::GetFPURegisterValueFloat(
int regnum) {
206 return sim_->get_pc();
208 return sim_->get_fpu_register_float(regnum);
213 double MipsDebugger::GetFPURegisterValueDouble(
int regnum) {
215 return sim_->get_pc();
217 return sim_->get_fpu_register_double(regnum);
222 bool MipsDebugger::GetValue(
const char* desc,
int32_t* value) {
227 *value = GetRegisterValue(regnum);
230 *value = GetFPURegisterValueInt(fpuregnum);
232 }
else if (strncmp(desc,
"0x", 2) == 0) {
233 return SScanF(desc,
"%x", reinterpret_cast<uint32_t*>(value)) == 1;
235 return SScanF(desc,
"%i", value) == 1;
241 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
243 if (sim_->break_pc_ !=
NULL) {
248 sim_->break_pc_ = breakpc;
249 sim_->break_instr_ = breakpc->InstructionBits();
256 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
257 if (sim_->break_pc_ !=
NULL) {
258 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
261 sim_->break_pc_ =
NULL;
262 sim_->break_instr_ = 0;
267 void MipsDebugger::UndoBreakpoints() {
268 if (sim_->break_pc_ !=
NULL) {
269 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
274 void MipsDebugger::RedoBreakpoints() {
275 if (sim_->break_pc_ !=
NULL) {
276 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
281 void MipsDebugger::PrintAllRegs() {
282 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
286 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
287 REG_INFO(1), REG_INFO(2), REG_INFO(4));
289 PrintF(
"%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
290 "", REG_INFO(3), REG_INFO(5));
292 PrintF(
"%26s\t%26s\t%3s: 0x%08x %10d\n",
"",
"", REG_INFO(6));
294 PrintF(
"%26s\t%26s\t%3s: 0x%08x %10d\n",
"",
"", REG_INFO(7));
297 for (
int i = 0; i < 8; i++) {
298 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
299 REG_INFO(8+i), REG_INFO(16+i));
303 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
304 REG_INFO(24), REG_INFO(26), REG_INFO(32));
306 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
307 REG_INFO(25), REG_INFO(27), REG_INFO(33));
309 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
310 REG_INFO(29), REG_INFO(30), REG_INFO(28));
312 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
313 REG_INFO(31), REG_INFO(34));
320 void MipsDebugger::PrintAllRegsIncludingFPU() {
321 #define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
322 GetFPURegisterValueInt(n+1), \
323 GetFPURegisterValueInt(n), \
324 GetFPURegisterValueDouble(n)
330 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
331 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
332 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
333 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
334 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
335 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
336 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
337 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
338 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
339 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
340 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
341 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
342 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
343 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
344 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
345 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
352 void MipsDebugger::Debug() {
353 intptr_t last_pc = -1;
356 #define COMMAND_SIZE 63
360 #define XSTR(a) STR(a)
362 char cmd[COMMAND_SIZE + 1];
363 char arg1[ARG_SIZE + 1];
364 char arg2[ARG_SIZE + 1];
365 char* argv[3] = { cmd, arg1, arg2 };
368 cmd[COMMAND_SIZE] = 0;
376 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
377 if (last_pc != sim_->get_pc()) {
382 dasm.InstructionDecode(buffer,
383 reinterpret_cast<byte*>(sim_->get_pc()));
384 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.
start());
385 last_pc = sim_->get_pc();
391 char* last_input = sim_->last_debugger_input();
392 if (strcmp(line,
"\n") == 0 && last_input !=
NULL) {
396 sim_->set_last_debugger_input(line);
400 int argc = SScanF(line,
401 "%" XSTR(COMMAND_SIZE)
"s "
402 "%" XSTR(ARG_SIZE)
"s "
403 "%" XSTR(ARG_SIZE)
"s",
405 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
406 Instruction* instr =
reinterpret_cast<Instruction*
>(sim_->get_pc());
407 if (!(instr->IsTrap()) ||
409 sim_->InstructionDecode(
410 reinterpret_cast<Instruction*>(sim_->get_pc()));
413 PrintF(
"/!\\ Jumping over generated breakpoint.\n");
416 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
418 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
421 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
425 if (strcmp(arg1,
"all") == 0) {
427 }
else if (strcmp(arg1,
"allf") == 0) {
428 PrintAllRegsIncludingFPU();
434 value = GetRegisterValue(regnum);
435 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
437 if (fpuregnum % 2 == 1) {
438 value = GetFPURegisterValueInt(fpuregnum);
439 fvalue = GetFPURegisterValueFloat(fpuregnum);
440 PrintF(
"%s: 0x%08x %11.4e\n", arg1, value, fvalue);
443 int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
444 int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
445 dfvalue = GetFPURegisterValueDouble(fpuregnum);
446 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n",
454 PrintF(
"%s unrecognized\n", arg1);
459 if (strcmp(arg2,
"single") == 0) {
465 value = GetFPURegisterValueInt(fpuregnum);
466 fvalue = GetFPURegisterValueFloat(fpuregnum);
467 PrintF(
"%s: 0x%08x %11.4e\n", arg1, value, fvalue);
469 PrintF(
"%s unrecognized\n", arg1);
472 PrintF(
"print <fpu register> single\n");
475 PrintF(
"print <register> or print <fpu register> single\n");
478 }
else if ((strcmp(cmd,
"po") == 0)
479 || (strcmp(cmd,
"printobject") == 0)) {
482 if (GetValue(arg1, &value)) {
492 PrintF(
"%s unrecognized\n", arg1);
495 PrintF(
"printobject <value>\n");
497 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
502 if (strcmp(cmd,
"stack") == 0) {
506 if (!GetValue(arg1, &value)) {
507 PrintF(
"%s unrecognized\n", arg1);
510 cur =
reinterpret_cast<int32_t*
>(value);
515 if (argc == next_arg) {
518 if (!GetValue(argv[next_arg], &words)) {
525 PrintF(
" 0x%08x: 0x%08x %10d",
526 reinterpret_cast<intptr_t>(cur), *cur, *cur);
527 HeapObject*
obj =
reinterpret_cast<HeapObject*
>(*cur);
529 Heap* current_heap = v8::internal::Isolate::Current()->heap();
530 if (((value & 1) == 0) || current_heap->Contains(obj)) {
532 if ((value & 1) == 0) {
533 PrintF(
"smi %d", value / 2);
543 }
else if ((strcmp(cmd,
"disasm") == 0) ||
544 (strcmp(cmd,
"dpc") == 0) ||
545 (strcmp(cmd,
"di") == 0)) {
555 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
557 }
else if (argc == 2) {
562 if (GetValue(arg1, &value)) {
563 cur =
reinterpret_cast<byte*
>(value);
570 if (GetValue(arg1, &value)) {
571 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
579 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
580 cur =
reinterpret_cast<byte*
>(value1);
586 dasm.InstructionDecode(buffer, cur);
588 reinterpret_cast<intptr_t>(cur), buffer.
start());
591 }
else if (strcmp(cmd,
"gdb") == 0) {
592 PrintF(
"relinquishing control to gdb\n");
594 PrintF(
"regaining control from gdb\n");
595 }
else if (strcmp(cmd,
"break") == 0) {
598 if (GetValue(arg1, &value)) {
599 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
600 PrintF(
"setting breakpoint failed\n");
603 PrintF(
"%s unrecognized\n", arg1);
606 PrintF(
"break <address>\n");
608 }
else if (strcmp(cmd,
"del") == 0) {
609 if (!DeleteBreakpoint(
NULL)) {
610 PrintF(
"deleting breakpoint failed\n");
612 }
else if (strcmp(cmd,
"flags") == 0) {
613 PrintF(
"No flags on MIPS !\n");
614 }
else if (strcmp(cmd,
"stop") == 0) {
616 intptr_t stop_pc = sim_->get_pc() -
618 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
619 Instruction* msg_address =
620 reinterpret_cast<Instruction*
>(stop_pc +
622 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
624 if (sim_->IsStopInstruction(stop_instr)) {
625 stop_instr->SetInstructionBits(kNopInstr);
626 msg_address->SetInstructionBits(kNopInstr);
628 PrintF(
"Not at debugger stop.\n");
630 }
else if (argc == 3) {
632 if (strcmp(arg1,
"info") == 0) {
633 if (strcmp(arg2,
"all") == 0) {
634 PrintF(
"Stop information:\n");
638 sim_->PrintStopInfo(i);
640 }
else if (GetValue(arg2, &value)) {
641 sim_->PrintStopInfo(value);
643 PrintF(
"Unrecognized argument.\n");
645 }
else if (strcmp(arg1,
"enable") == 0) {
647 if (strcmp(arg2,
"all") == 0) {
653 }
else if (GetValue(arg2, &value)) {
654 sim_->EnableStop(value);
656 PrintF(
"Unrecognized argument.\n");
658 }
else if (strcmp(arg1,
"disable") == 0) {
660 if (strcmp(arg2,
"all") == 0) {
664 sim_->DisableStop(i);
666 }
else if (GetValue(arg2, &value)) {
667 sim_->DisableStop(value);
669 PrintF(
"Unrecognized argument.\n");
673 PrintF(
"Wrong usage. Use help command for more information.\n");
675 }
else if ((strcmp(cmd,
"stat") == 0) || (strcmp(cmd,
"st") == 0)) {
689 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
691 }
else if (argc == 2) {
693 if (GetValue(arg1, &value)) {
694 cur =
reinterpret_cast<byte*
>(value);
701 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
702 cur =
reinterpret_cast<byte*
>(value1);
708 dasm.InstructionDecode(buffer, cur);
710 reinterpret_cast<intptr_t>(cur), buffer.
start());
713 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
715 PrintF(
" continue execution (alias 'c')\n");
717 PrintF(
" step one instruction (alias 'si')\n");
718 PrintF(
"print <register>\n");
719 PrintF(
" print register content (alias 'p')\n");
720 PrintF(
" use register name 'all' to print all registers\n");
721 PrintF(
"printobject <register>\n");
722 PrintF(
" print an object from a register (alias 'po')\n");
723 PrintF(
"stack [<words>]\n");
724 PrintF(
" dump stack content, default dump 10 words)\n");
725 PrintF(
"mem <address> [<words>]\n");
726 PrintF(
" dump memory content, default dump 10 words)\n");
729 PrintF(
"disasm [<instructions>]\n");
730 PrintF(
"disasm [<address/register>]\n");
731 PrintF(
"disasm [[<address/register>] <instructions>]\n");
732 PrintF(
" disassemble code, default is 10 instructions\n");
733 PrintF(
" from pc (alias 'di')\n");
736 PrintF(
"break <address>\n");
737 PrintF(
" set a break point on the address\n");
739 PrintF(
" delete the breakpoint\n");
740 PrintF(
"stop feature:\n");
741 PrintF(
" Description:\n");
742 PrintF(
" Stops are debug instructions inserted by\n");
743 PrintF(
" the Assembler::stop() function.\n");
744 PrintF(
" When hitting a stop, the Simulator will\n");
745 PrintF(
" stop and and give control to the Debugger.\n");
746 PrintF(
" All stop codes are watched:\n");
747 PrintF(
" - They can be enabled / disabled: the Simulator\n");
748 PrintF(
" will / won't stop when hitting them.\n");
749 PrintF(
" - The Simulator keeps track of how many times they \n");
750 PrintF(
" are met. (See the info command.) Going over a\n");
751 PrintF(
" disabled stop still increases its counter. \n");
753 PrintF(
" stop info all/<code> : print infos about number <code>\n");
754 PrintF(
" or all stop(s).\n");
755 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
756 PrintF(
" all or number <code> stop(s)\n");
758 PrintF(
" ignore the stop instruction at the current location\n");
761 PrintF(
"Unknown command: %s\n", cmd);
778 static bool ICacheMatch(
void* one,
void* two) {
779 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
780 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
785 static uint32_t ICacheHash(
void* key) {
786 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(key)) >> 2;
790 static bool AllOnOnePage(uintptr_t start,
int size) {
791 intptr_t start_page = (start & ~CachePage::kPageMask);
792 intptr_t end_page = ((start +
size) & ~CachePage::kPageMask);
793 return start_page == end_page;
797 void Simulator::set_last_debugger_input(
char* input) {
799 last_debugger_input_ = input;
806 intptr_t start =
reinterpret_cast<intptr_t
>(start_addr);
807 int intra_line = (start & CachePage::kLineMask);
810 size = ((size - 1) | CachePage::kLineMask) + 1;
811 int offset = (start & CachePage::kPageMask);
812 while (!AllOnOnePage(start, size - 1)) {
813 int bytes_to_flush = CachePage::kPageSize - offset;
814 FlushOnePage(i_cache, start, bytes_to_flush);
815 start += bytes_to_flush;
816 size -= bytes_to_flush;
817 ASSERT_EQ(0, start & CachePage::kPageMask);
821 FlushOnePage(i_cache, start, size);
827 v8::internal::HashMap::Entry* entry = i_cache->
Lookup(page,
830 if (entry->value ==
NULL) {
831 CachePage* new_page =
new CachePage();
832 entry->value = new_page;
834 return reinterpret_cast<CachePage*
>(entry->value);
842 ASSERT(size <= CachePage::kPageSize);
843 ASSERT(AllOnOnePage(start, size - 1));
844 ASSERT((start & CachePage::kLineMask) == 0);
845 ASSERT((size & CachePage::kLineMask) == 0);
846 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
847 int offset = (start & CachePage::kPageMask);
848 CachePage* cache_page = GetCachePage(i_cache, page);
849 char* valid_bytemap = cache_page->ValidityByte(offset);
850 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
855 Instruction* instr) {
856 intptr_t address =
reinterpret_cast<intptr_t
>(instr);
857 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
858 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
859 int offset = (address & CachePage::kPageMask);
860 CachePage* cache_page = GetCachePage(i_cache, page);
861 char* cache_valid_byte = cache_page->ValidityByte(offset);
862 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
863 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
866 CHECK(memcmp(reinterpret_cast<void*>(instr),
867 cache_page->CachedData(offset),
871 OS::MemCopy(cached_line, line, CachePage::kLineLength);
872 *cache_valid_byte = CachePage::LINE_VALID;
877 void Simulator::Initialize(Isolate* isolate) {
878 if (isolate->simulator_initialized())
return;
879 isolate->set_simulator_initialized(
true);
880 ::v8::internal::ExternalReference::set_redirector(isolate,
881 &RedirectExternalReference);
885 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
886 i_cache_ = isolate_->simulator_i_cache();
887 if (i_cache_ ==
NULL) {
889 isolate_->set_simulator_i_cache(i_cache_);
894 stack_ =
reinterpret_cast<char*
>(malloc(stack_size_));
895 pc_modified_ =
false;
907 FPUregisters_[i] = 0;
914 registers_[
sp] =
reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
917 registers_[
pc] = bad_ra;
918 registers_[ra] = bad_ra;
919 InitializeCoverage();
920 for (
int i = 0; i < kNumExceptions; i++) {
924 last_debugger_input_ =
NULL;
928 Simulator::~Simulator() {
942 : external_function_(external_function),
946 Isolate* isolate = Isolate::Current();
947 next_ = isolate->simulator_redirection();
948 Simulator::current(isolate)->
949 FlushICache(isolate->simulator_i_cache(),
950 reinterpret_cast<void*
>(&swi_instruction_),
952 isolate->set_simulator_redirection(
this);
955 void* address_of_swi_instruction() {
956 return reinterpret_cast<void*
>(&swi_instruction_);
959 void* external_function() {
return external_function_; }
962 static Redirection* Get(
void* external_function,
964 Isolate* isolate = Isolate::Current();
965 Redirection* current = isolate->simulator_redirection();
966 for (; current !=
NULL; current = current->next_) {
967 if (current->external_function_ == external_function)
return current;
969 return new Redirection(external_function, type);
972 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
973 char* addr_of_swi =
reinterpret_cast<char*
>(swi_instruction);
974 char* addr_of_redirection =
975 addr_of_swi -
OFFSET_OF(Redirection, swi_instruction_);
976 return reinterpret_cast<Redirection*
>(addr_of_redirection);
979 static void* ReverseRedirection(
int32_t reg) {
980 Redirection* redirection = FromSwiInstruction(
981 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
982 return redirection->external_function();
986 void* external_function_;
987 uint32_t swi_instruction_;
993 void* Simulator::RedirectExternalReference(
void* external_function,
995 Redirection* redirection = Redirection::Get(external_function, type);
996 return redirection->address_of_swi_instruction();
1001 Simulator* Simulator::current(Isolate* isolate) {
1003 isolate->FindOrAllocatePerThreadDataForThisThread();
1007 Simulator* sim = isolate_data->simulator();
1010 sim =
new Simulator(isolate);
1011 isolate_data->set_simulator(sim);
1019 void Simulator::set_register(
int reg,
int32_t value) {
1020 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1022 pc_modified_ =
true;
1026 registers_[reg] = (reg == 0) ? 0 : value;
1030 void Simulator::set_dw_register(
int reg,
const int* dbl) {
1031 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1032 registers_[reg] = dbl[0];
1033 registers_[reg + 1] = dbl[1];
1037 void Simulator::set_fpu_register(
int fpureg,
int32_t value) {
1038 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1039 FPUregisters_[fpureg] = value;
1043 void Simulator::set_fpu_register_float(
int fpureg,
float value) {
1044 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1045 *BitCast<float*>(&FPUregisters_[fpureg]) = value;
1049 void Simulator::set_fpu_register_double(
int fpureg,
double value) {
1050 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1051 *BitCast<double*>(&FPUregisters_[fpureg]) = value;
1057 int32_t Simulator::get_register(
int reg)
const {
1058 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1066 double Simulator::get_double_from_register_pair(
int reg) {
1067 ASSERT((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1069 double dm_val = 0.0;
1072 char buffer[2 *
sizeof(registers_[0])];
1073 OS::MemCopy(buffer, ®isters_[reg], 2 *
sizeof(registers_[0]));
1074 OS::MemCopy(&dm_val, buffer, 2 *
sizeof(registers_[0]));
1079 int32_t Simulator::get_fpu_register(
int fpureg)
const {
1080 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1081 return FPUregisters_[fpureg];
1085 int64_t Simulator::get_fpu_register_long(
int fpureg)
const {
1086 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1087 return *BitCast<int64_t*>(
1088 const_cast<int32_t*
>(&FPUregisters_[fpureg]));
1092 float Simulator::get_fpu_register_float(
int fpureg)
const {
1093 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1094 return *BitCast<float*>(
1095 const_cast<int32_t*
>(&FPUregisters_[fpureg]));
1099 double Simulator::get_fpu_register_double(
int fpureg)
const {
1100 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1101 return *BitCast<double*>(
const_cast<int32_t*
>(&FPUregisters_[fpureg]));
1108 void Simulator::GetFpArgs(
double* x,
double* y,
int32_t* z) {
1110 *x = get_fpu_register_double(12);
1111 *y = get_fpu_register_double(14);
1112 *z = get_register(a2);
1116 char buffer[
sizeof(*x)];
1120 reg_buffer[0] = get_register(a0);
1121 reg_buffer[1] = get_register(a1);
1124 reg_buffer[0] = get_register(a2);
1125 reg_buffer[1] = get_register(a3);
1128 reg_buffer[0] = get_register(a2);
1135 void Simulator::SetFpResult(
const double& result) {
1137 set_fpu_register_double(0, result);
1139 char buffer[2 *
sizeof(registers_[0])];
1143 set_register(v0, reg_buffer[0]);
1144 set_register(v1, reg_buffer[1]);
1150 void Simulator::set_fcsr_bit(uint32_t cc,
bool value) {
1154 FCSR_ &= ~(1 <<
cc);
1159 bool Simulator::test_fcsr_bit(uint32_t cc) {
1160 return FCSR_ & (1 <<
cc);
1166 bool Simulator::set_fcsr_round_error(
double original,
double rounded) {
1174 if (original != rounded) {
1178 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1183 if (rounded > INT_MAX || rounded < INT_MIN) {
1195 void Simulator::set_pc(
int32_t value) {
1196 pc_modified_ =
true;
1197 registers_[
pc] = value;
1201 bool Simulator::has_bad_pc()
const {
1202 return ((registers_[
pc] == bad_ra) || (registers_[
pc] == end_sim_pc));
1207 int32_t Simulator::get_pc()
const {
1208 return registers_[
pc];
1220 int Simulator::ReadW(
int32_t addr, Instruction* instr) {
1221 if (addr >=0 && addr < 0x400) {
1223 PrintF(
"Memory read from bad address: 0x%08x, pc=0x%08x\n",
1224 addr, reinterpret_cast<intptr_t>(instr));
1225 MipsDebugger dbg(
this);
1229 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1234 reinterpret_cast<intptr_t>(instr));
1235 MipsDebugger dbg(
this);
1241 void Simulator::WriteW(
int32_t addr,
int value, Instruction* instr) {
1242 if (addr >= 0 && addr < 0x400) {
1244 PrintF(
"Memory write to bad address: 0x%08x, pc=0x%08x\n",
1245 addr, reinterpret_cast<intptr_t>(instr));
1246 MipsDebugger dbg(
this);
1249 if ((addr & kPointerAlignmentMask) == 0) {
1250 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1256 reinterpret_cast<intptr_t>(instr));
1257 MipsDebugger dbg(
this);
1262 double Simulator::ReadD(
int32_t addr, Instruction* instr) {
1264 double* ptr =
reinterpret_cast<double*
>(addr);
1269 reinterpret_cast<intptr_t>(instr));
1275 void Simulator::WriteD(
int32_t addr,
double value, Instruction* instr) {
1276 if ((addr & kDoubleAlignmentMask) == 0) {
1277 double* ptr =
reinterpret_cast<double*
>(addr);
1283 reinterpret_cast<intptr_t>(instr));
1289 if ((addr & 1) == 0) {
1293 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1295 reinterpret_cast<intptr_t>(instr));
1302 if ((addr & 1) == 0) {
1306 PrintF(
"Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1308 reinterpret_cast<intptr_t>(instr));
1314 void Simulator::WriteH(
int32_t addr,
uint16_t value, Instruction* instr) {
1315 if ((addr & 1) == 0) {
1320 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1322 reinterpret_cast<intptr_t>(instr));
1327 void Simulator::WriteH(
int32_t addr,
int16_t value, Instruction* instr) {
1328 if ((addr & 1) == 0) {
1335 reinterpret_cast<intptr_t>(instr));
1340 uint32_t Simulator::ReadBU(
int32_t addr) {
1341 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1347 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1352 void Simulator::WriteB(
int32_t addr, uint8_t value) {
1353 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1358 void Simulator::WriteB(
int32_t addr, int8_t value) {
1359 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1365 uintptr_t Simulator::StackLimit()
const {
1368 return reinterpret_cast<uintptr_t
>(stack_) + 1024;
1373 void Simulator::Format(Instruction* instr,
const char* format) {
1374 PrintF(
"Simulator found unsupported instruction:\n 0x%08x: %s\n",
1375 reinterpret_cast<intptr_t>(instr), format);
1386 typedef int64_t (*SimulatorRuntimeCall)(
int32_t arg0,
1394 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
1395 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
1396 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
1397 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0,
int32_t arg0);
1401 typedef void (*SimulatorRuntimeDirectApiCall)(
int32_t arg0);
1402 typedef void (*SimulatorRuntimeProfilingApiCall)(
int32_t arg0,
void* arg1);
1405 typedef void (*SimulatorRuntimeDirectGetterCall)(
int32_t arg0,
int32_t arg1);
1406 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1411 void Simulator::SoftwareInterrupt(Instruction* instr) {
1415 int32_t func = instr->FunctionFieldRaw();
1416 uint32_t code = (func ==
BREAK) ? instr->Bits(25, 6) : -1;
1420 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1421 int32_t arg0 = get_register(a0);
1422 int32_t arg1 = get_register(a1);
1423 int32_t arg2 = get_register(a2);
1424 int32_t arg3 = get_register(a3);
1428 int32_t arg4 = stack_pointer[4];
1429 int32_t arg5 = stack_pointer[5];
1432 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1433 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1434 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1435 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1442 switch (redirection->type()) {
1443 case ExternalReference::BUILTIN_FP_FP_CALL:
1444 case ExternalReference::BUILTIN_COMPARE_CALL:
1445 arg0 = get_fpu_register(
f12);
1446 arg1 = get_fpu_register(
f13);
1447 arg2 = get_fpu_register(
f14);
1448 arg3 = get_fpu_register(
f15);
1450 case ExternalReference::BUILTIN_FP_CALL:
1451 arg0 = get_fpu_register(
f12);
1452 arg1 = get_fpu_register(
f13);
1454 case ExternalReference::BUILTIN_FP_INT_CALL:
1455 arg0 = get_fpu_register(
f12);
1456 arg1 = get_fpu_register(
f13);
1457 arg2 = get_register(a2);
1466 int32_t saved_ra = get_register(ra);
1469 reinterpret_cast<intptr_t
>(redirection->external_function());
1476 double dval0, dval1;
1478 int64_t iresult = 0;
1480 GetFpArgs(&dval0, &dval1, &ival);
1481 SimulatorRuntimeCall generic_target =
1482 reinterpret_cast<SimulatorRuntimeCall
>(external);
1483 if (::v8::internal::FLAG_trace_sim) {
1484 switch (redirection->type()) {
1485 case ExternalReference::BUILTIN_FP_FP_CALL:
1486 case ExternalReference::BUILTIN_COMPARE_CALL:
1487 PrintF(
"Call to host function at %p with args %f, %f",
1490 case ExternalReference::BUILTIN_FP_CALL:
1491 PrintF(
"Call to host function at %p with arg %f",
1494 case ExternalReference::BUILTIN_FP_INT_CALL:
1495 PrintF(
"Call to host function at %p with args %f, %d",
1503 switch (redirection->type()) {
1504 case ExternalReference::BUILTIN_COMPARE_CALL: {
1505 SimulatorRuntimeCompareCall target =
1506 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
1507 iresult = target(dval0, dval1);
1508 set_register(v0, static_cast<int32_t>(iresult));
1509 set_register(v1, static_cast<int32_t>(iresult >> 32));
1512 case ExternalReference::BUILTIN_FP_FP_CALL: {
1513 SimulatorRuntimeFPFPCall target =
1514 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
1515 dresult = target(dval0, dval1);
1516 SetFpResult(dresult);
1519 case ExternalReference::BUILTIN_FP_CALL: {
1520 SimulatorRuntimeFPCall target =
1521 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1522 dresult = target(dval0);
1523 SetFpResult(dresult);
1526 case ExternalReference::BUILTIN_FP_INT_CALL: {
1527 SimulatorRuntimeFPIntCall target =
1528 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
1529 dresult = target(dval0, ival);
1530 SetFpResult(dresult);
1537 if (::v8::internal::FLAG_trace_sim) {
1538 switch (redirection->type()) {
1539 case ExternalReference::BUILTIN_COMPARE_CALL:
1540 PrintF(
"Returned %08x\n", static_cast<int32_t>(iresult));
1542 case ExternalReference::BUILTIN_FP_FP_CALL:
1543 case ExternalReference::BUILTIN_FP_CALL:
1544 case ExternalReference::BUILTIN_FP_INT_CALL:
1545 PrintF(
"Returned %f\n", dresult);
1552 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1553 if (::v8::internal::FLAG_trace_sim) {
1554 PrintF(
"Call to host function at %p args %08x\n",
1555 reinterpret_cast<void*>(external), arg0);
1557 SimulatorRuntimeDirectApiCall target =
1558 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1561 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1562 if (::v8::internal::FLAG_trace_sim) {
1563 PrintF(
"Call to host function at %p args %08x %08x\n",
1564 reinterpret_cast<void*>(external), arg0, arg1);
1566 SimulatorRuntimeProfilingApiCall target =
1567 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
1568 target(arg0, Redirection::ReverseRedirection(arg1));
1570 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1571 if (::v8::internal::FLAG_trace_sim) {
1572 PrintF(
"Call to host function at %p args %08x %08x\n",
1573 reinterpret_cast<void*>(external), arg0, arg1);
1575 SimulatorRuntimeDirectGetterCall target =
1576 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1579 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1580 if (::v8::internal::FLAG_trace_sim) {
1581 PrintF(
"Call to host function at %p args %08x %08x %08x\n",
1582 reinterpret_cast<void*>(external), arg0, arg1, arg2);
1584 SimulatorRuntimeProfilingGetterCall target =
1585 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(external);
1586 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1588 SimulatorRuntimeCall target =
1589 reinterpret_cast<SimulatorRuntimeCall
>(external);
1590 if (::v8::internal::FLAG_trace_sim) {
1592 "Call to host function at %p "
1593 "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1602 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1603 set_register(v0, static_cast<int32_t>(result));
1604 set_register(v1, static_cast<int32_t>(result >> 32));
1606 if (::v8::internal::FLAG_trace_sim) {
1607 PrintF(
"Returned %08x : %08x\n", get_register(v1), get_register(v0));
1609 set_register(ra, saved_ra);
1610 set_pc(get_register(ra));
1613 if (IsWatchpoint(code)) {
1614 PrintWatchpoint(code);
1616 IncreaseStopCounter(code);
1617 HandleStop(code, instr);
1621 MipsDebugger dbg(
this);
1628 bool Simulator::IsWatchpoint(uint32_t code) {
1633 void Simulator::PrintWatchpoint(uint32_t code) {
1634 MipsDebugger dbg(
this);
1636 PrintF(
"\n---- break %d marker: %3d (instr count: %8d) ----------"
1637 "----------------------------------",
1638 code, break_count_, icount_);
1643 void Simulator::HandleStop(uint32_t code, Instruction* instr) {
1646 if (IsEnabledStop(code)) {
1647 MipsDebugger dbg(
this);
1655 bool Simulator::IsStopInstruction(Instruction* instr) {
1656 int32_t func = instr->FunctionFieldRaw();
1657 uint32_t code =
static_cast<uint32_t
>(instr->Bits(25, 6));
1662 bool Simulator::IsEnabledStop(uint32_t code) {
1665 return !(watched_stops_[
code].count & kStopDisabledBit);
1669 void Simulator::EnableStop(uint32_t code) {
1670 if (!IsEnabledStop(code)) {
1671 watched_stops_[
code].count &= ~kStopDisabledBit;
1676 void Simulator::DisableStop(uint32_t code) {
1677 if (IsEnabledStop(code)) {
1678 watched_stops_[
code].count |= kStopDisabledBit;
1683 void Simulator::IncreaseStopCounter(uint32_t code) {
1685 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1686 PrintF(
"Stop counter for code %i has overflowed.\n"
1687 "Enabling this code and reseting the counter to 0.\n", code);
1688 watched_stops_[
code].count = 0;
1691 watched_stops_[
code].count++;
1697 void Simulator::PrintStopInfo(uint32_t code) {
1699 PrintF(
"That is a watchpoint, not a stop.\n");
1705 const char* state = IsEnabledStop(code) ?
"Enabled" :
"Disabled";
1706 int32_t count = watched_stops_[
code].count & ~kStopDisabledBit;
1709 if (watched_stops_[code].desc) {
1710 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1711 code, code, state, count, watched_stops_[code].desc);
1713 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
1714 code, code, state, count);
1720 void Simulator::SignalExceptions() {
1721 for (
int i = 1; i < kNumExceptions; i++) {
1722 if (exceptions[i] != 0) {
1723 V8_Fatal(__FILE__, __LINE__,
"Error: Exception %i raised.", i);
1731 void Simulator::ConfigureTypeRegister(Instruction* instr,
1737 bool& do_interrupt) {
1743 const Opcode op = instr->OpcodeFieldRaw();
1744 const int32_t rs_reg = instr->RsValue();
1745 const int32_t rs = get_register(rs_reg);
1746 const uint32_t rs_u =
static_cast<uint32_t
>(rs);
1747 const int32_t rt_reg = instr->RtValue();
1748 const int32_t rt = get_register(rt_reg);
1749 const uint32_t rt_u =
static_cast<uint32_t
>(rt);
1750 const int32_t rd_reg = instr->RdValue();
1751 const uint32_t sa = instr->SaValue();
1753 const int32_t fs_reg = instr->FsValue();
1759 switch (instr->RsFieldRaw()) {
1769 alu_out = get_fpu_register(fs_reg);
1793 switch (instr->FunctionFieldRaw()) {
1796 next_pc = get_register(instr->RsValue());
1797 return_addr_reg = instr->RdValue();
1806 alu_out = rt_u >> sa;
1811 alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1824 alu_out = rt_u >> rs;
1829 alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1836 alu_out = get_register(HI);
1839 alu_out = get_register(LO);
1842 i64hilo =
static_cast<int64_t
>(rs) * static_cast<int64_t>(rt);
1845 u64hilo =
static_cast<uint64_t
>(rs_u) * static_cast<uint64_t>(rt_u);
1848 if (HaveSameSign(rs, rt)) {
1851 }
else if (rs < 0) {
1861 if (!HaveSameSign(rs, rt)) {
1864 }
else if (rs < 0) {
1883 alu_out = ~(rs | rt);
1886 alu_out = rs < rt ? 1 : 0;
1889 alu_out = rs_u < rt_u ? 1 : 0;
1894 do_interrupt =
true;
1897 do_interrupt = rs >= rt;
1900 do_interrupt = rs_u >= rt_u;
1903 do_interrupt = rs < rt;
1906 do_interrupt = rs_u < rt_u;
1909 do_interrupt = rs == rt;
1912 do_interrupt = rs != rt;
1928 switch (instr->FunctionFieldRaw()) {
1930 alu_out = rs_u * rt_u;
1944 switch (instr->FunctionFieldRaw()) {
1951 uint32_t mask = (1 <<
size) - 1;
1952 alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1961 uint32_t mask = (1 <<
size) - 1;
1962 alu_out = (rs_u & (mask << lsb)) >> lsb;
1975 void Simulator::DecodeTypeRegister(Instruction* instr) {
1977 const Opcode op = instr->OpcodeFieldRaw();
1978 const int32_t rs_reg = instr->RsValue();
1979 const int32_t rs = get_register(rs_reg);
1980 const uint32_t rs_u =
static_cast<uint32_t
>(rs);
1981 const int32_t rt_reg = instr->RtValue();
1982 const int32_t rt = get_register(rt_reg);
1983 const uint32_t rt_u =
static_cast<uint32_t
>(rt);
1984 const int32_t rd_reg = instr->RdValue();
1986 const int32_t fr_reg = instr->FrValue();
1987 const int32_t fs_reg = instr->FsValue();
1988 const int32_t ft_reg = instr->FtValue();
1989 const int32_t fd_reg = instr->FdValue();
1990 int64_t i64hilo = 0;
1991 uint64_t u64hilo = 0;
1999 bool do_interrupt =
false;
2003 int32_t current_pc = get_pc();
2009 ConfigureTypeRegister(instr,
2023 switch (instr->RsFieldRaw()) {
2028 set_register(rt_reg, alu_out);
2030 set_register(rt_reg, alu_out);
2038 FCSR_ = registers_[rt_reg];
2041 FPUregisters_[fs_reg] = registers_[rt_reg];
2048 switch (instr->FunctionFieldRaw()) {
2050 f = get_fpu_register_float(fs_reg);
2051 set_fpu_register_double(fd_reg, static_cast<double>(f));
2072 uint32_t
cc, fcsr_cc;
2074 fs = get_fpu_register_double(fs_reg);
2075 ft = get_fpu_register_double(ft_reg);
2076 cc = instr->FCccValue();
2077 fcsr_cc = get_fcsr_condition_bit(cc);
2078 switch (instr->FunctionFieldRaw()) {
2080 set_fpu_register_double(fd_reg, fs + ft);
2083 set_fpu_register_double(fd_reg, fs - ft);
2086 set_fpu_register_double(fd_reg, fs * ft);
2089 set_fpu_register_double(fd_reg, fs / ft);
2092 set_fpu_register_double(fd_reg, fabs(fs));
2095 set_fpu_register_double(fd_reg, fs);
2098 set_fpu_register_double(fd_reg, -fs);
2101 set_fpu_register_double(fd_reg, sqrt(fs));
2107 set_fcsr_bit(fcsr_cc, (fs == ft));
2110 set_fcsr_bit(fcsr_cc,
2114 set_fcsr_bit(fcsr_cc, (fs < ft));
2117 set_fcsr_bit(fcsr_cc,
2121 set_fcsr_bit(fcsr_cc, (fs <= ft));
2124 set_fcsr_bit(fcsr_cc,
2129 ASSERT((FCSR_ & 3) == 0);
2133 double rounded = std::floor(fs + 0.5);
2135 if ((result & 1) != 0 && result - fs == 0.5) {
2140 set_fpu_register(fd_reg, result);
2141 if (set_fcsr_round_error(fs, rounded)) {
2148 double rounded = trunc(fs);
2150 set_fpu_register(fd_reg, result);
2151 if (set_fcsr_round_error(fs, rounded)) {
2158 double rounded = std::floor(fs);
2160 set_fpu_register(fd_reg, result);
2161 if (set_fcsr_round_error(fs, rounded)) {
2168 double rounded = std::ceil(fs);
2170 set_fpu_register(fd_reg, result);
2171 if (set_fcsr_round_error(fs, rounded)) {
2177 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2180 double rounded = trunc(fs);
2181 i64 =
static_cast<int64_t
>(rounded);
2182 set_fpu_register(fd_reg, i64 & 0xffffffff);
2183 set_fpu_register(fd_reg + 1, i64 >> 32);
2187 double rounded = trunc(fs);
2188 i64 =
static_cast<int64_t
>(rounded);
2189 set_fpu_register(fd_reg, i64 & 0xffffffff);
2190 set_fpu_register(fd_reg + 1, i64 >> 32);
2195 fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5);
2196 i64 =
static_cast<int64_t
>(rounded);
2197 set_fpu_register(fd_reg, i64 & 0xffffffff);
2198 set_fpu_register(fd_reg + 1, i64 >> 32);
2202 i64 =
static_cast<int64_t
>(std::floor(fs));
2203 set_fpu_register(fd_reg, i64 & 0xffffffff);
2204 set_fpu_register(fd_reg + 1, i64 >> 32);
2207 i64 =
static_cast<int64_t
>(std::ceil(fs));
2208 set_fpu_register(fd_reg, i64 & 0xffffffff);
2209 set_fpu_register(fd_reg + 1, i64 >> 32);
2219 switch (instr->FunctionFieldRaw()) {
2221 alu_out = get_fpu_register(fs_reg);
2222 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2225 alu_out = get_fpu_register(fs_reg);
2226 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2233 switch (instr->FunctionFieldRaw()) {
2237 i64 =
static_cast<uint32_t
>(get_fpu_register(fs_reg));
2238 i64 |=
static_cast<int64_t
>(get_fpu_register(fs_reg + 1)) << 32;
2239 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2255 switch (instr->FunctionFieldRaw()) {
2258 fr = get_fpu_register_double(fr_reg);
2259 fs = get_fpu_register_double(fs_reg);
2260 ft = get_fpu_register_double(ft_reg);
2261 set_fpu_register_double(fd_reg, fs * ft + fr);
2268 switch (instr->FunctionFieldRaw()) {
2270 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2272 BranchDelayInstructionDecode(branch_delay_instr);
2274 pc_modified_ =
true;
2278 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2280 BranchDelayInstructionDecode(branch_delay_instr);
2281 set_register(return_addr_reg,
2284 pc_modified_ =
true;
2289 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2290 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2293 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2294 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2301 if (rs == INT_MIN && rt == -1) {
2302 set_register(LO, INT_MIN);
2303 set_register(HI, 0);
2304 }
else if (rt != 0) {
2305 set_register(LO, rs / rt);
2306 set_register(HI, rs % rt);
2311 set_register(LO, rs_u / rt_u);
2312 set_register(HI, rs_u % rt_u);
2324 SoftwareInterrupt(instr);
2329 if (rt) set_register(rd_reg, rs);
2332 uint32_t cc = instr->FBccValue();
2333 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2334 if (instr->Bit(16)) {
2335 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2337 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2342 if (!rt) set_register(rd_reg, rs);
2345 set_register(rd_reg, alu_out);
2349 switch (instr->FunctionFieldRaw()) {
2351 set_register(rd_reg, alu_out);
2353 set_register(LO, Unpredictable);
2354 set_register(HI, Unpredictable);
2357 set_register(rd_reg, alu_out);
2361 switch (instr->FunctionFieldRaw()) {
2364 set_register(rt_reg, alu_out);
2368 set_register(rt_reg, alu_out);
2378 set_register(rd_reg, alu_out);
2384 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2386 Opcode op = instr->OpcodeFieldRaw();
2387 int32_t rs = get_register(instr->RsValue());
2388 uint32_t rs_u =
static_cast<uint32_t
>(rs);
2389 int32_t rt_reg = instr->RtValue();
2390 int32_t rt = get_register(rt_reg);
2391 int16_t imm16 = instr->Imm16Value();
2393 int32_t ft_reg = instr->FtValue();
2396 uint32_t oe_imm16 = 0xffff & imm16;
2401 int32_t current_pc = get_pc();
2406 bool do_branch =
false;
2407 bool execute_branch_delay_instruction =
false;
2412 double fp_out = 0.0;
2413 uint32_t
cc, cc_value, fcsr_cc;
2418 uint32_t mem_value = 0x0;
2424 switch (instr->RsFieldRaw()) {
2426 cc = instr->FBccValue();
2427 fcsr_cc = get_fcsr_condition_bit(cc);
2428 cc_value = test_fcsr_bit(fcsr_cc);
2429 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2430 execute_branch_delay_instruction =
true;
2444 switch (instr->RtFieldRaw()) {
2446 do_branch = (rs < 0);
2452 do_branch = rs >= 0;
2455 do_branch = rs >= 0;
2460 switch (instr->RtFieldRaw()) {
2466 execute_branch_delay_instruction =
true;
2470 if (instr->IsLinkingInstruction()) {
2484 do_branch = (rs == rt);
2487 do_branch = rs != rt;
2490 do_branch = rs <= 0;
2497 if (HaveSameSign(rs, se_imm16)) {
2500 }
else if (rs < 0) {
2501 exceptions[kIntegerUnderflow] =
2505 alu_out = rs + se_imm16;
2508 alu_out = rs + se_imm16;
2511 alu_out = (rs < se_imm16) ? 1 : 0;
2514 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2517 alu_out = rs & oe_imm16;
2520 alu_out = rs | oe_imm16;
2523 alu_out = rs ^ oe_imm16;
2526 alu_out = (oe_imm16 << 16);
2530 addr = rs + se_imm16;
2531 alu_out = ReadB(addr);
2534 addr = rs + se_imm16;
2535 alu_out = ReadH(addr, instr);
2539 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2540 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2541 uint32_t mask = (1 << byte_shift * 8) - 1;
2542 addr = rs + se_imm16 - al_offset;
2543 alu_out = ReadW(addr, instr);
2544 alu_out <<= byte_shift * 8;
2545 alu_out |= rt & mask;
2549 addr = rs + se_imm16;
2550 alu_out = ReadW(addr, instr);
2553 addr = rs + se_imm16;
2554 alu_out = ReadBU(addr);
2557 addr = rs + se_imm16;
2558 alu_out = ReadHU(addr, instr);
2562 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2563 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2564 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2565 addr = rs + se_imm16 - al_offset;
2566 alu_out = ReadW(addr, instr);
2567 alu_out =
static_cast<uint32_t
> (alu_out) >> al_offset * 8;
2568 alu_out |= rt & mask;
2572 addr = rs + se_imm16;
2575 addr = rs + se_imm16;
2578 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2579 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2580 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2581 addr = rs + se_imm16 - al_offset;
2582 mem_value = ReadW(addr, instr) & mask;
2583 mem_value |=
static_cast<uint32_t
>(rt) >> byte_shift * 8;
2587 addr = rs + se_imm16;
2590 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2591 uint32_t mask = (1 << al_offset * 8) - 1;
2592 addr = rs + se_imm16 - al_offset;
2593 mem_value = ReadW(addr, instr);
2594 mem_value = (rt << al_offset * 8) | (mem_value & mask);
2598 addr = rs + se_imm16;
2599 alu_out = ReadW(addr, instr);
2602 addr = rs + se_imm16;
2603 fp_out = ReadD(addr, instr);
2607 addr = rs + se_imm16;
2624 execute_branch_delay_instruction =
true;
2628 if (instr->IsLinkingInstruction()) {
2644 set_register(rt_reg, alu_out);
2654 set_register(rt_reg, alu_out);
2657 WriteB(addr, static_cast<int8_t>(rt));
2660 WriteH(addr, static_cast<uint16_t>(rt), instr);
2663 WriteW(addr, mem_value, instr);
2666 WriteW(addr, rt, instr);
2669 WriteW(addr, mem_value, instr);
2672 set_fpu_register(ft_reg, alu_out);
2675 set_fpu_register_double(ft_reg, fp_out);
2678 addr = rs + se_imm16;
2679 WriteW(addr, get_fpu_register(ft_reg), instr);
2682 addr = rs + se_imm16;
2683 WriteD(addr, get_fpu_register_double(ft_reg), instr);
2690 if (execute_branch_delay_instruction) {
2694 Instruction* branch_delay_instr =
2696 BranchDelayInstructionDecode(branch_delay_instr);
2700 if (next_pc != bad_ra) {
2707 void Simulator::DecodeTypeJump(Instruction* instr) {
2709 int32_t current_pc = get_pc();
2711 int32_t pc_high_bits = current_pc & 0xf0000000;
2713 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2718 Instruction* branch_delay_instr =
2720 BranchDelayInstructionDecode(branch_delay_instr);
2724 if (instr->IsLinkingInstruction()) {
2728 pc_modified_ =
true;
2733 void Simulator::InstructionDecode(Instruction* instr) {
2734 if (v8::internal::FLAG_check_icache) {
2735 CheckICache(isolate_->simulator_i_cache(), instr);
2737 pc_modified_ =
false;
2738 if (::v8::internal::FLAG_trace_sim) {
2743 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2744 PrintF(
" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2748 switch (instr->InstructionType()) {
2750 DecodeTypeRegister(instr);
2753 DecodeTypeImmediate(instr);
2756 DecodeTypeJump(instr);
2761 if (!pc_modified_) {
2762 set_register(
pc, reinterpret_cast<int32_t>(instr) +
2769 void Simulator::Execute() {
2772 int program_counter = get_pc();
2773 if (::v8::internal::FLAG_stop_sim_at == 0) {
2776 while (program_counter != end_sim_pc) {
2777 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
2779 InstructionDecode(instr);
2780 program_counter = get_pc();
2785 while (program_counter != end_sim_pc) {
2786 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
2788 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2789 MipsDebugger dbg(
this);
2792 InstructionDecode(instr);
2794 program_counter = get_pc();
2800 void Simulator::CallInternal(
byte* entry) {
2802 set_register(
pc, reinterpret_cast<int32_t>(entry));
2806 set_register(ra, end_sim_pc);
2819 int32_t gp_val = get_register(gp);
2825 int32_t callee_saved_value = icount_;
2826 set_register(
s0, callee_saved_value);
2827 set_register(
s1, callee_saved_value);
2828 set_register(
s2, callee_saved_value);
2829 set_register(
s3, callee_saved_value);
2830 set_register(
s4, callee_saved_value);
2831 set_register(
s5, callee_saved_value);
2832 set_register(
s6, callee_saved_value);
2833 set_register(
s7, callee_saved_value);
2834 set_register(gp, callee_saved_value);
2835 set_register(
fp, callee_saved_value);
2841 CHECK_EQ(callee_saved_value, get_register(
s0));
2842 CHECK_EQ(callee_saved_value, get_register(
s1));
2843 CHECK_EQ(callee_saved_value, get_register(
s2));
2844 CHECK_EQ(callee_saved_value, get_register(
s3));
2845 CHECK_EQ(callee_saved_value, get_register(
s4));
2846 CHECK_EQ(callee_saved_value, get_register(
s5));
2847 CHECK_EQ(callee_saved_value, get_register(
s6));
2848 CHECK_EQ(callee_saved_value, get_register(
s7));
2849 CHECK_EQ(callee_saved_value, get_register(gp));
2850 CHECK_EQ(callee_saved_value, get_register(
fp));
2853 set_register(
s0, s0_val);
2854 set_register(
s1, s1_val);
2855 set_register(
s2, s2_val);
2856 set_register(
s3, s3_val);
2857 set_register(
s4, s4_val);
2858 set_register(
s5, s5_val);
2859 set_register(
s6, s6_val);
2860 set_register(
s7, s7_val);
2861 set_register(gp, gp_val);
2862 set_register(
sp, sp_val);
2863 set_register(
fp, fp_val);
2867 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
2869 va_start(parameters, argument_count);
2873 ASSERT(argument_count >= 4);
2874 set_register(a0, va_arg(parameters,
int32_t));
2875 set_register(a1, va_arg(parameters,
int32_t));
2876 set_register(a2, va_arg(parameters,
int32_t));
2877 set_register(a3, va_arg(parameters,
int32_t));
2880 int original_stack = get_register(
sp);
2882 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t)
2888 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
2889 for (
int i = 4; i < argument_count; i++) {
2893 set_register(
sp, entry_stack);
2895 CallInternal(entry);
2899 set_register(
sp, original_stack);
2901 int32_t result = get_register(v0);
2906 double Simulator::CallFP(
byte* entry,
double d0,
double d1) {
2908 set_fpu_register_double(
f12, d0);
2909 set_fpu_register_double(
f14, d1);
2912 ASSERT(
sizeof(buffer[0]) * 2 ==
sizeof(d0));
2914 set_dw_register(a0, buffer);
2916 set_dw_register(a2, buffer);
2918 CallInternal(entry);
2920 return get_fpu_register_double(
f0);
2922 return get_double_from_register_pair(v0);
2927 uintptr_t Simulator::PushAddress(uintptr_t address) {
2928 int new_sp = get_register(
sp) -
sizeof(uintptr_t);
2929 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
2930 *stack_slot = address;
2931 set_register(
sp, new_sp);
2936 uintptr_t Simulator::PopAddress() {
2937 int current_sp = get_register(
sp);
2938 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
2939 uintptr_t address = *stack_slot;
2940 set_register(
sp, current_sp +
sizeof(uintptr_t));
2949 #endif // USE_SIMULATOR
2951 #endif // V8_TARGET_ARCH_MIPS
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
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 LowDwVfpRegister d0
int CountLeadingZeros(uint64_t value, int width)
const int kNumSimuRegisters
kSerializedDataOffset Object
const uint32_t kMaxWatchpointCode
TypeImpl< ZoneTypeConfig > Type
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,...)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
const Instr rtCallRedirInstr
const uint32_t kFPUInvalidResult
static int Number(const char *name)
#define OFFSET_OF(type, field)
static void MemCopy(void *dest, const void *src, size_t size)
const bool IsMipsSoftFloatABI
const uint32_t kFCSRInvalidOpFlagBit
const unsigned kInstructionSize
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
#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()
const LowDwVfpRegister d1
static int Number(const char *name)
void DeleteArray(T *array)
static const int32_t kMinValue