12 #if V8_TARGET_ARCH_MIPS64
22 #if defined(USE_SIMULATOR)
28 bool HaveSameSign(int64_t a, int64_t b) {
29 return ((a ^ b) >= 0);
42 static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
44 int64_t u1, v1, w1, w2, t;
52 t = u1 * v0 + (w0 >> 32);
57 return u1 * v1 + w2 + (w1 >> 32);
71 explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
74 void Stop(Instruction* instr);
78 void PrintAllRegsIncludingFPU();
83 static const Instr kNopInstr = 0x0;
87 int64_t GetRegisterValue(
int regnum);
88 int64_t GetFPURegisterValue(
int regnum);
89 float GetFPURegisterValueFloat(
int regnum);
90 double GetFPURegisterValueDouble(
int regnum);
91 bool GetValue(
const char* desc, int64_t* value);
94 bool SetBreakpoint(Instruction* breakpc);
95 bool DeleteBreakpoint(Instruction* breakpc);
99 void UndoBreakpoints();
100 void RedoBreakpoints();
104 MipsDebugger::~MipsDebugger() {
108 #ifdef GENERATED_CODE_COVERAGE
109 static FILE* coverage_log =
NULL;
112 static void InitializeCoverage() {
113 char* file_name = getenv(
"V8_GENERATED_CODE_COVERAGE_LOG");
114 if (file_name !=
NULL) {
115 coverage_log = fopen(file_name,
"aw+");
120 void MipsDebugger::Stop(Instruction* instr) {
125 reinterpret_cast<char**
>(sim_->get_pc() + Instr::kInstrSize);
126 char* msg = *msg_address;
130 if (!watched_stops_[code].desc) {
131 watched_stops_[code].desc = msg;
134 if (strlen(msg) > 0) {
135 if (coverage_log !=
NULL) {
136 fprintf(coverage_log,
"%s\n", str);
137 fflush(coverage_log);
140 instr->SetInstructionBits(kNopInstr);
141 reinterpret_cast<Instr*
>(msg_address)->SetInstructionBits(kNopInstr);
150 #define UNSUPPORTED() printf("Unsupported instruction.\n");
152 static void InitializeCoverage() {}
155 void MipsDebugger::Stop(Instruction* instr) {
159 char* msg = *
reinterpret_cast<char**
>(sim_->get_pc() +
162 if (!sim_->watched_stops_[code].desc) {
163 sim_->watched_stops_[code].desc = msg;
165 PrintF(
"Simulator hit %s (%u)\n", msg, code);
173 int64_t MipsDebugger::GetRegisterValue(
int regnum) {
175 return sim_->get_pc();
177 return sim_->get_register(regnum);
182 int64_t MipsDebugger::GetFPURegisterValue(
int regnum) {
184 return sim_->get_pc();
186 return sim_->get_fpu_register(regnum);
191 float MipsDebugger::GetFPURegisterValueFloat(
int regnum) {
193 return sim_->get_pc();
195 return sim_->get_fpu_register_float(regnum);
200 double MipsDebugger::GetFPURegisterValueDouble(
int regnum) {
202 return sim_->get_pc();
204 return sim_->get_fpu_register_double(regnum);
209 bool MipsDebugger::GetValue(
const char* desc, int64_t* value) {
214 *value = GetRegisterValue(regnum);
217 *value = GetFPURegisterValue(fpuregnum);
219 }
else if (strncmp(desc,
"0x", 2) == 0) {
220 return SScanF(desc + 2,
"%" SCNx64,
221 reinterpret_cast<uint64_t*
>(value)) == 1;
223 return SScanF(desc,
"%" SCNu64,
reinterpret_cast<uint64_t*
>(value)) == 1;
229 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
231 if (sim_->break_pc_ !=
NULL) {
236 sim_->break_pc_ = breakpc;
237 sim_->break_instr_ = breakpc->InstructionBits();
244 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
245 if (sim_->break_pc_ !=
NULL) {
246 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
249 sim_->break_pc_ =
NULL;
250 sim_->break_instr_ = 0;
255 void MipsDebugger::UndoBreakpoints() {
256 if (sim_->break_pc_ !=
NULL) {
257 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
262 void MipsDebugger::RedoBreakpoints() {
263 if (sim_->break_pc_ !=
NULL) {
264 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
269 void MipsDebugger::PrintAllRegs() {
270 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
274 PrintF(
"%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
275 REG_INFO(1), REG_INFO(2), REG_INFO(4));
277 PrintF(
"%34s\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
278 "", REG_INFO(3), REG_INFO(5));
280 PrintF(
"%34s\t%34s\t%3s: 0x%016lx %14ld\n",
"",
"", REG_INFO(6));
282 PrintF(
"%34s\t%34s\t%3s: 0x%016lx %14ld\n",
"",
"", REG_INFO(7));
285 for (
int i = 0;
i < 8;
i++) {
286 PrintF(
"%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
287 REG_INFO(8+
i), REG_INFO(16+
i));
291 PrintF(
"%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
292 REG_INFO(24), REG_INFO(26), REG_INFO(32));
294 PrintF(
"%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
295 REG_INFO(25), REG_INFO(27), REG_INFO(33));
297 PrintF(
"%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
298 REG_INFO(29), REG_INFO(30), REG_INFO(28));
300 PrintF(
"%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
301 REG_INFO(31), REG_INFO(34));
308 void MipsDebugger::PrintAllRegsIncludingFPU() {
309 #define FPU_REG_INFO(n) FPURegisters::Name(n), \
310 GetFPURegisterValue(n), \
311 GetFPURegisterValueDouble(n)
318 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(0) );
319 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(1) );
320 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(2) );
321 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(3) );
322 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(4) );
323 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(5) );
324 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(6) );
325 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(7) );
326 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(8) );
327 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(9) );
328 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(10));
329 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(11));
330 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(12));
331 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(13));
332 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(14));
333 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(15));
334 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(16));
335 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(17));
336 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(18));
337 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(19));
338 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(20));
339 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(21));
340 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(22));
341 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(23));
342 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(24));
343 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(25));
344 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(26));
345 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(27));
346 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(28));
347 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(29));
348 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(30));
349 PrintF(
"%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(31));
356 void MipsDebugger::Debug() {
357 intptr_t last_pc = -1;
360 #define COMMAND_SIZE 63
364 #define XSTR(a) STR(a)
366 char cmd[COMMAND_SIZE + 1];
367 char arg1[ARG_SIZE + 1];
368 char arg2[ARG_SIZE + 1];
369 char* argv[3] = { cmd, arg1, arg2 };
372 cmd[COMMAND_SIZE] = 0;
380 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
381 if (last_pc != sim_->get_pc()) {
386 dasm.InstructionDecode(buffer,
387 reinterpret_cast<byte*
>(sim_->get_pc()));
388 PrintF(
" 0x%016lx %s\n", sim_->get_pc(), buffer.
start());
389 last_pc = sim_->get_pc();
395 char* last_input = sim_->last_debugger_input();
396 if (strcmp(line,
"\n") == 0 && last_input !=
NULL) {
400 sim_->set_last_debugger_input(line);
404 int argc = SScanF(line,
405 "%" XSTR(COMMAND_SIZE)
"s "
406 "%" XSTR(ARG_SIZE)
"s "
407 "%" XSTR(ARG_SIZE)
"s",
409 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
410 Instruction* instr =
reinterpret_cast<Instruction*
>(sim_->get_pc());
411 if (!(instr->IsTrap()) ||
413 sim_->InstructionDecode(
414 reinterpret_cast<Instruction*
>(sim_->get_pc()));
417 PrintF(
"/!\\ Jumping over generated breakpoint.\n");
420 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
422 sim_->InstructionDecode(
reinterpret_cast<Instruction*
>(sim_->get_pc()));
425 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
429 if (strcmp(arg1,
"all") == 0) {
431 }
else if (strcmp(arg1,
"allf") == 0) {
432 PrintAllRegsIncludingFPU();
438 value = GetRegisterValue(regnum);
439 PrintF(
"%s: 0x%08lx %ld \n", arg1, value, value);
441 value = GetFPURegisterValue(fpuregnum);
442 dvalue = GetFPURegisterValueDouble(fpuregnum);
443 PrintF(
"%3s: 0x%016lx %16.4e\n",
446 PrintF(
"%s unrecognized\n", arg1);
451 if (strcmp(arg2,
"single") == 0) {
457 value = GetFPURegisterValue(fpuregnum);
458 value &= 0xffffffffUL;
459 fvalue = GetFPURegisterValueFloat(fpuregnum);
460 PrintF(
"%s: 0x%08lx %11.4e\n", arg1, value, fvalue);
462 PrintF(
"%s unrecognized\n", arg1);
465 PrintF(
"print <fpu register> single\n");
468 PrintF(
"print <register> or print <fpu register> single\n");
471 }
else if ((strcmp(cmd,
"po") == 0)
472 || (strcmp(cmd,
"printobject") == 0)) {
476 if (GetValue(arg1, &value)) {
478 os << arg1 <<
": \n";
483 os << Brief(obj) <<
"\n";
486 os << arg1 <<
" unrecognized\n";
489 PrintF(
"printobject <value>\n");
491 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
496 if (strcmp(cmd,
"stack") == 0) {
497 cur =
reinterpret_cast<int64_t*
>(sim_->get_register(
Simulator::sp));
500 if (!GetValue(arg1, &value)) {
501 PrintF(
"%s unrecognized\n", arg1);
504 cur =
reinterpret_cast<int64_t*
>(value);
509 if (argc == next_arg) {
512 if (!GetValue(argv[next_arg], &words)) {
519 PrintF(
" 0x%012lx: 0x%016lx %14ld",
520 reinterpret_cast<intptr_t
>(cur), *cur, *cur);
521 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
522 int64_t value = *cur;
523 Heap* current_heap = v8::internal::Isolate::Current()->heap();
524 if (((value & 1) == 0) || current_heap->Contains(obj)) {
526 if ((value & 1) == 0) {
527 PrintF(
"smi %d",
static_cast<int>(value >> 32));
537 }
else if ((strcmp(cmd,
"disasm") == 0) ||
538 (strcmp(cmd,
"dpc") == 0) ||
539 (strcmp(cmd,
"di") == 0)) {
549 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
551 }
else if (argc == 2) {
556 if (GetValue(arg1, &value)) {
557 cur =
reinterpret_cast<byte*
>(value);
564 if (GetValue(arg1, &value)) {
565 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
573 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
574 cur =
reinterpret_cast<byte*
>(value1);
580 dasm.InstructionDecode(buffer, cur);
582 reinterpret_cast<intptr_t
>(cur), buffer.
start());
585 }
else if (strcmp(cmd,
"gdb") == 0) {
586 PrintF(
"relinquishing control to gdb\n");
588 PrintF(
"regaining control from gdb\n");
589 }
else if (strcmp(cmd,
"break") == 0) {
592 if (GetValue(arg1, &value)) {
593 if (!SetBreakpoint(
reinterpret_cast<Instruction*
>(value))) {
594 PrintF(
"setting breakpoint failed\n");
597 PrintF(
"%s unrecognized\n", arg1);
600 PrintF(
"break <address>\n");
602 }
else if (strcmp(cmd,
"del") == 0) {
603 if (!DeleteBreakpoint(
NULL)) {
604 PrintF(
"deleting breakpoint failed\n");
606 }
else if (strcmp(cmd,
"flags") == 0) {
607 PrintF(
"No flags on MIPS !\n");
608 }
else if (strcmp(cmd,
"stop") == 0) {
610 intptr_t stop_pc = sim_->get_pc() -
612 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
613 Instruction* msg_address =
614 reinterpret_cast<Instruction*
>(stop_pc +
616 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
618 if (sim_->IsStopInstruction(stop_instr)) {
619 stop_instr->SetInstructionBits(kNopInstr);
620 msg_address->SetInstructionBits(kNopInstr);
622 PrintF(
"Not at debugger stop.\n");
624 }
else if (argc == 3) {
626 if (strcmp(arg1,
"info") == 0) {
627 if (strcmp(arg2,
"all") == 0) {
628 PrintF(
"Stop information:\n");
632 sim_->PrintStopInfo(
i);
634 }
else if (GetValue(arg2, &value)) {
635 sim_->PrintStopInfo(value);
637 PrintF(
"Unrecognized argument.\n");
639 }
else if (strcmp(arg1,
"enable") == 0) {
641 if (strcmp(arg2,
"all") == 0) {
647 }
else if (GetValue(arg2, &value)) {
648 sim_->EnableStop(value);
650 PrintF(
"Unrecognized argument.\n");
652 }
else if (strcmp(arg1,
"disable") == 0) {
654 if (strcmp(arg2,
"all") == 0) {
658 sim_->DisableStop(
i);
660 }
else if (GetValue(arg2, &value)) {
661 sim_->DisableStop(value);
663 PrintF(
"Unrecognized argument.\n");
667 PrintF(
"Wrong usage. Use help command for more information.\n");
669 }
else if ((strcmp(cmd,
"stat") == 0) || (strcmp(cmd,
"st") == 0)) {
683 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
685 }
else if (argc == 2) {
687 if (GetValue(arg1, &value)) {
688 cur =
reinterpret_cast<byte*
>(value);
695 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
696 cur =
reinterpret_cast<byte*
>(value1);
702 dasm.InstructionDecode(buffer, cur);
704 reinterpret_cast<intptr_t
>(cur), buffer.
start());
707 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
709 PrintF(
" continue execution (alias 'c')\n");
711 PrintF(
" step one instruction (alias 'si')\n");
712 PrintF(
"print <register>\n");
713 PrintF(
" print register content (alias 'p')\n");
714 PrintF(
" use register name 'all' to print all registers\n");
715 PrintF(
"printobject <register>\n");
716 PrintF(
" print an object from a register (alias 'po')\n");
717 PrintF(
"stack [<words>]\n");
718 PrintF(
" dump stack content, default dump 10 words)\n");
719 PrintF(
"mem <address> [<words>]\n");
720 PrintF(
" dump memory content, default dump 10 words)\n");
723 PrintF(
"disasm [<instructions>]\n");
724 PrintF(
"disasm [<address/register>]\n");
725 PrintF(
"disasm [[<address/register>] <instructions>]\n");
726 PrintF(
" disassemble code, default is 10 instructions\n");
727 PrintF(
" from pc (alias 'di')\n");
730 PrintF(
"break <address>\n");
731 PrintF(
" set a break point on the address\n");
733 PrintF(
" delete the breakpoint\n");
734 PrintF(
"stop feature:\n");
735 PrintF(
" Description:\n");
736 PrintF(
" Stops are debug instructions inserted by\n");
737 PrintF(
" the Assembler::stop() function.\n");
738 PrintF(
" When hitting a stop, the Simulator will\n");
739 PrintF(
" stop and and give control to the Debugger.\n");
740 PrintF(
" All stop codes are watched:\n");
741 PrintF(
" - They can be enabled / disabled: the Simulator\n");
742 PrintF(
" will / won't stop when hitting them.\n");
743 PrintF(
" - The Simulator keeps track of how many times they \n");
744 PrintF(
" are met. (See the info command.) Going over a\n");
745 PrintF(
" disabled stop still increases its counter. \n");
747 PrintF(
" stop info all/<code> : print infos about number <code>\n");
748 PrintF(
" or all stop(s).\n");
749 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
750 PrintF(
" all or number <code> stop(s)\n");
752 PrintF(
" ignore the stop instruction at the current location\n");
755 PrintF(
"Unknown command: %s\n", cmd);
772 static bool ICacheMatch(
void* one,
void* two) {
773 DCHECK((
reinterpret_cast<intptr_t
>(one) & CachePage::kPageMask) == 0);
774 DCHECK((
reinterpret_cast<intptr_t
>(two) & CachePage::kPageMask) == 0);
779 static uint32_t ICacheHash(
void* key) {
785 intptr_t start_page = (start & ~CachePage::kPageMask);
786 intptr_t end_page = ((start +
size) & ~CachePage::kPageMask);
787 return start_page == end_page;
791 void Simulator::set_last_debugger_input(
char* input) {
793 last_debugger_input_ = input;
800 int64_t start =
reinterpret_cast<int64_t
>(start_addr);
801 int64_t intra_line = (start & CachePage::kLineMask);
804 size = ((
size - 1) | CachePage::kLineMask) + 1;
805 int offset = (start & CachePage::kPageMask);
806 while (!AllOnOnePage(start,
size - 1)) {
807 int bytes_to_flush = CachePage::kPageSize - offset;
808 FlushOnePage(i_cache, start, bytes_to_flush);
809 start += bytes_to_flush;
810 size -= bytes_to_flush;
811 DCHECK_EQ((uint64_t)0, start & CachePage::kPageMask);
815 FlushOnePage(i_cache, start,
size);
821 v8::internal::HashMap::Entry* entry = i_cache->
Lookup(page,
824 if (entry->value ==
NULL) {
825 CachePage* new_page =
new CachePage();
826 entry->value = new_page;
828 return reinterpret_cast<CachePage*
>(entry->value);
838 DCHECK((start & CachePage::kLineMask) == 0);
840 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
841 int offset = (start & CachePage::kPageMask);
842 CachePage* cache_page = GetCachePage(i_cache, page);
843 char* valid_bytemap = cache_page->ValidityByte(offset);
844 memset(valid_bytemap, CachePage::LINE_INVALID,
size >> CachePage::kLineShift);
849 Instruction* instr) {
850 int64_t address =
reinterpret_cast<int64_t
>(instr);
851 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
852 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
853 int offset = (address & CachePage::kPageMask);
854 CachePage* cache_page = GetCachePage(i_cache, page);
855 char* cache_valid_byte = cache_page->ValidityByte(offset);
856 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
857 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
860 CHECK_EQ(0, memcmp(
reinterpret_cast<void*
>(instr),
861 cache_page->CachedData(offset),
865 memcpy(cached_line, line, CachePage::kLineLength);
866 *cache_valid_byte = CachePage::LINE_VALID;
871 void Simulator::Initialize(Isolate* isolate) {
872 if (isolate->simulator_initialized())
return;
873 isolate->set_simulator_initialized(
true);
874 ::v8::internal::ExternalReference::set_redirector(isolate,
875 &RedirectExternalReference);
879 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
880 i_cache_ = isolate_->simulator_i_cache();
881 if (i_cache_ ==
NULL) {
883 isolate_->set_simulator_i_cache(i_cache_);
888 stack_size_ = FLAG_sim_stack_size *
KB;
889 stack_ =
reinterpret_cast<char*
>(malloc(stack_size_));
890 pc_modified_ =
false;
902 FPUregisters_[
i] = 0;
909 registers_[
sp] =
reinterpret_cast<int64_t
>(stack_) + stack_size_ - 64;
912 registers_[
pc] = bad_ra;
913 registers_[ra] = bad_ra;
914 InitializeCoverage();
915 for (
int i = 0;
i < kNumExceptions;
i++) {
919 last_debugger_input_ =
NULL;
923 Simulator::~Simulator() {
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_),
946 Instruction::kInstrSize);
947 isolate->set_simulator_redirection(
this);
950 void* address_of_swi_instruction() {
951 return reinterpret_cast<void*
>(&swi_instruction_);
954 void* external_function() {
return external_function_; }
957 static Redirection* Get(
void* external_function,
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);
974 static void* ReverseRedirection(int64_t reg) {
975 Redirection* redirection = FromSwiInstruction(
976 reinterpret_cast<Instruction*
>(
reinterpret_cast<void*
>(reg)));
977 return redirection->external_function();
981 void* external_function_;
988 void* Simulator::RedirectExternalReference(
void* external_function,
990 Redirection* redirection = Redirection::Get(external_function, type);
991 return redirection->address_of_swi_instruction();
996 Simulator* Simulator::current(Isolate* isolate) {
998 isolate->FindOrAllocatePerThreadDataForThisThread();
1002 Simulator* sim = isolate_data->simulator();
1005 sim =
new Simulator(isolate);
1006 isolate_data->set_simulator(sim);
1014 void Simulator::set_register(
int reg, int64_t value) {
1017 pc_modified_ =
true;
1021 registers_[reg] = (reg == 0) ? 0 : value;
1025 void Simulator::set_dw_register(
int reg,
const int* dbl) {
1027 registers_[reg] = dbl[1];
1028 registers_[reg] = registers_[reg] << 32;
1029 registers_[reg] += dbl[0];
1033 void Simulator::set_fpu_register(
int fpureg, int64_t value) {
1035 FPUregisters_[fpureg] = value;
1039 void Simulator::set_fpu_register_word(
int fpureg,
int32_t value) {
1043 int32_t *pword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg]);
1048 void Simulator::set_fpu_register_hi_word(
int fpureg,
int32_t value) {
1052 int32_t *phiword = (
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg])) + 1;
1057 void Simulator::set_fpu_register_float(
int fpureg,
float value) {
1059 *bit_cast<float*>(&FPUregisters_[fpureg]) = value;
1063 void Simulator::set_fpu_register_double(
int fpureg,
double value) {
1065 *bit_cast<double*>(&FPUregisters_[fpureg]) = value;
1071 int64_t Simulator::get_register(
int reg)
const {
1076 return registers_[reg] + ((reg ==
pc) ? Instruction::kPCReadOffset : 0);
1080 double Simulator::get_double_from_register_pair(
int reg) {
1084 double dm_val = 0.0;
1087 char buffer[
sizeof(registers_[0])];
1088 memcpy(buffer, ®isters_[reg],
sizeof(registers_[0]));
1089 memcpy(&dm_val, buffer,
sizeof(registers_[0]));
1094 int64_t Simulator::get_fpu_register(
int fpureg)
const {
1096 return FPUregisters_[fpureg];
1100 int32_t Simulator::get_fpu_register_word(
int fpureg)
const {
1102 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1106 int32_t Simulator::get_fpu_register_signed_word(
int fpureg)
const {
1108 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
1112 int32_t Simulator::get_fpu_register_hi_word(
int fpureg)
const {
1114 return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff);
1118 float Simulator::get_fpu_register_float(
int fpureg)
const {
1120 return *bit_cast<float*>(
const_cast<int64_t*
>(&FPUregisters_[fpureg]));
1124 double Simulator::get_fpu_register_double(
int fpureg)
const {
1126 return *bit_cast<double*>(&FPUregisters_[fpureg]);
1133 void Simulator::GetFpArgs(
double* x,
double*
y,
int32_t* z) {
1136 *x = get_fpu_register_double(12);
1137 *
y = get_fpu_register_double(fparg2);
1138 *z = get_register(a2);
1143 char buffer[
sizeof(*x)];
1147 reg_buffer[0] = get_register(a0);
1148 reg_buffer[1] = get_register(a1);
1149 memcpy(x, buffer,
sizeof(buffer));
1151 reg_buffer[0] = get_register(a2);
1152 reg_buffer[1] = get_register(a3);
1153 memcpy(
y, buffer,
sizeof(buffer));
1155 reg_buffer[0] = get_register(a2);
1156 memcpy(z, buffer,
sizeof(*z));
1162 void Simulator::SetFpResult(
const double& result) {
1164 set_fpu_register_double(0, result);
1166 char buffer[2 *
sizeof(registers_[0])];
1167 int64_t* reg_buffer =
reinterpret_cast<int64_t*
>(buffer);
1168 memcpy(buffer, &result,
sizeof(buffer));
1170 set_register(v0, reg_buffer[0]);
1171 set_register(v1, reg_buffer[1]);
1177 void Simulator::set_fcsr_bit(
uint32_t cc,
bool value) {
1181 FCSR_ &= ~(1 <<
cc);
1187 return FCSR_ & (1 <<
cc);
1193 bool Simulator::set_fcsr_round_error(
double original,
double rounded) {
1195 double max_int32 = std::numeric_limits<int32_t>::max();
1198 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1203 if (original != rounded) {
1207 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1212 if (rounded > max_int32 || rounded < min_int32) {
1225 bool Simulator::set_fcsr_round64_error(
double original,
double rounded) {
1227 double max_int64 = std::numeric_limits<int64_t>::max();
1230 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1235 if (original != rounded) {
1239 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1244 if (rounded > max_int64 || rounded < min_int64) {
1256 void Simulator::set_pc(int64_t value) {
1257 pc_modified_ =
true;
1258 registers_[
pc] = value;
1262 bool Simulator::has_bad_pc()
const {
1263 return ((registers_[
pc] == bad_ra) || (registers_[
pc] == end_sim_pc));
1268 int64_t Simulator::get_pc()
const {
1269 return registers_[
pc];
1282 void Simulator::DieOrDebug() {
1284 MipsDebugger dbg(
this);
1292 void Simulator::TraceRegWr(int64_t value) {
1293 if (::v8::internal::FLAG_trace_sim) {
1294 SNPrintF(trace_buf_,
"%016lx", value);
1300 void Simulator::TraceMemRd(int64_t addr, int64_t value) {
1301 if (::v8::internal::FLAG_trace_sim) {
1302 SNPrintF(trace_buf_,
"%016lx <-- [%016lx] (%ld)",
1303 value, addr, icount_);
1308 void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) {
1309 if (::v8::internal::FLAG_trace_sim) {
1312 SNPrintF(trace_buf_,
" %02x --> [%016lx]",
1313 static_cast<int8_t
>(value), addr);
1316 SNPrintF(trace_buf_,
" %04x --> [%016lx]",
1317 static_cast<int16_t>(value), addr);
1320 SNPrintF(trace_buf_,
" %08x --> [%016lx]",
1321 static_cast<int32_t>(value), addr);
1324 SNPrintF(trace_buf_,
"%016lx --> [%016lx] (%ld)",
1325 value, addr, icount_);
1334 int32_t Simulator::ReadW(int64_t addr, Instruction* instr) {
1335 if (addr >=0 && addr < 0x400) {
1337 PrintF(
"Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
1338 addr,
reinterpret_cast<intptr_t
>(instr));
1341 if ((addr & 0x3) == 0) {
1343 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
1348 reinterpret_cast<intptr_t
>(instr));
1354 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) {
1355 if (addr >=0 && addr < 0x400) {
1357 PrintF(
"Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
1358 addr,
reinterpret_cast<intptr_t
>(instr));
1361 if ((addr & 0x3) == 0) {
1363 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
1368 reinterpret_cast<intptr_t
>(instr));
1374 void Simulator::WriteW(int64_t addr,
int value, Instruction* instr) {
1375 if (addr >= 0 && addr < 0x400) {
1377 PrintF(
"Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
1378 addr,
reinterpret_cast<intptr_t
>(instr));
1381 if ((addr & 0x3) == 0) {
1382 TraceMemWr(addr, value, WORD);
1383 int* ptr =
reinterpret_cast<int*
>(addr);
1389 reinterpret_cast<intptr_t
>(instr));
1394 int64_t Simulator::Read2W(int64_t addr, Instruction* instr) {
1395 if (addr >=0 && addr < 0x400) {
1397 PrintF(
"Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
1398 addr,
reinterpret_cast<intptr_t
>(instr));
1402 int64_t* ptr =
reinterpret_cast<int64_t*
>(addr);
1403 TraceMemRd(addr, *ptr);
1408 reinterpret_cast<intptr_t
>(instr));
1414 void Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) {
1415 if (addr >= 0 && addr < 0x400) {
1417 PrintF(
"Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
1418 addr,
reinterpret_cast<intptr_t
>(instr));
1422 TraceMemWr(addr, value,
DWORD);
1423 int64_t* ptr =
reinterpret_cast<int64_t*
>(addr);
1429 reinterpret_cast<intptr_t
>(instr));
1434 double Simulator::ReadD(int64_t addr, Instruction* instr) {
1436 double* ptr =
reinterpret_cast<double*
>(addr);
1441 reinterpret_cast<intptr_t
>(instr));
1447 void Simulator::WriteD(int64_t addr,
double value, Instruction* instr) {
1449 double* ptr =
reinterpret_cast<double*
>(addr);
1453 PrintF(
"Unaligned (double) write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1455 reinterpret_cast<intptr_t
>(instr));
1460 uint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) {
1461 if ((addr & 1) == 0) {
1463 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
1466 PrintF(
"Unaligned unsigned halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1468 reinterpret_cast<intptr_t
>(instr));
1474 int16_t Simulator::ReadH(int64_t addr, Instruction* instr) {
1475 if ((addr & 1) == 0) {
1477 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
1480 PrintF(
"Unaligned signed halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1482 reinterpret_cast<intptr_t
>(instr));
1488 void Simulator::WriteH(int64_t addr,
uint16_t value, Instruction* instr) {
1489 if ((addr & 1) == 0) {
1490 TraceMemWr(addr, value, HALF);
1496 "Unaligned unsigned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1498 reinterpret_cast<intptr_t
>(instr));
1503 void Simulator::WriteH(int64_t addr,
int16_t value, Instruction* instr) {
1504 if ((addr & 1) == 0) {
1505 TraceMemWr(addr, value, HALF);
1510 PrintF(
"Unaligned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
1512 reinterpret_cast<intptr_t
>(instr));
1517 uint32_t Simulator::ReadBU(int64_t addr) {
1518 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1519 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
1524 int32_t Simulator::ReadB(int64_t addr) {
1525 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1526 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
1531 void Simulator::WriteB(int64_t addr, uint8_t value) {
1532 TraceMemWr(addr, value, BYTE);
1533 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1538 void Simulator::WriteB(int64_t addr, int8_t value) {
1539 TraceMemWr(addr, value, BYTE);
1540 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1546 uintptr_t Simulator::StackLimit()
const {
1549 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1554 void Simulator::Format(Instruction* instr,
const char* format) {
1555 PrintF(
"Simulator found unsupported instruction:\n 0x%08lx: %s\n",
1556 reinterpret_cast<intptr_t
>(instr), format);
1573 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
1582 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
1583 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
1584 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
1585 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0,
int32_t arg0);
1589 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
1590 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0,
void* arg1);
1593 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
1594 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1595 int64_t arg0, int64_t arg1,
void* arg2);
1599 void Simulator::SoftwareInterrupt(Instruction* instr) {
1603 int32_t func = instr->FunctionFieldRaw();
1607 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1608 int64_t arg0 = get_register(a0);
1609 int64_t arg1 = get_register(a1);
1610 int64_t arg2 = get_register(a2);
1611 int64_t arg3 = get_register(a3);
1615 arg4 = get_register(a4);
1616 arg5 = get_register(a5);
1618 int64_t* stack_pointer =
reinterpret_cast<int64_t*
>(get_register(
sp));
1620 arg4 = stack_pointer[4];
1621 arg5 = stack_pointer[5];
1624 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1625 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1626 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1627 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1634 switch (redirection->type()) {
1635 case ExternalReference::BUILTIN_FP_FP_CALL:
1636 case ExternalReference::BUILTIN_COMPARE_CALL:
1637 arg0 = get_fpu_register(
f12);
1638 arg1 = get_fpu_register(
f13);
1639 arg2 = get_fpu_register(
f14);
1640 arg3 = get_fpu_register(
f15);
1642 case ExternalReference::BUILTIN_FP_CALL:
1643 arg0 = get_fpu_register(
f12);
1644 arg1 = get_fpu_register(
f13);
1646 case ExternalReference::BUILTIN_FP_INT_CALL:
1647 arg0 = get_fpu_register(
f12);
1648 arg1 = get_fpu_register(
f13);
1649 arg2 = get_register(a2);
1658 int64_t saved_ra = get_register(ra);
1661 reinterpret_cast<intptr_t
>(redirection->external_function());
1668 double dval0, dval1;
1670 int64_t iresult = 0;
1672 GetFpArgs(&dval0, &dval1, &ival);
1673 SimulatorRuntimeCall generic_target =
1674 reinterpret_cast<SimulatorRuntimeCall
>(external);
1675 if (::v8::internal::FLAG_trace_sim) {
1676 switch (redirection->type()) {
1677 case ExternalReference::BUILTIN_FP_FP_CALL:
1678 case ExternalReference::BUILTIN_COMPARE_CALL:
1679 PrintF(
"Call to host function at %p with args %f, %f",
1682 case ExternalReference::BUILTIN_FP_CALL:
1683 PrintF(
"Call to host function at %p with arg %f",
1686 case ExternalReference::BUILTIN_FP_INT_CALL:
1687 PrintF(
"Call to host function at %p with args %f, %d",
1695 switch (redirection->type()) {
1696 case ExternalReference::BUILTIN_COMPARE_CALL: {
1697 SimulatorRuntimeCompareCall target =
1698 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
1699 iresult = target(dval0, dval1);
1700 set_register(v0,
static_cast<int64_t
>(iresult));
1704 case ExternalReference::BUILTIN_FP_FP_CALL: {
1705 SimulatorRuntimeFPFPCall target =
1706 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
1707 dresult = target(dval0, dval1);
1708 SetFpResult(dresult);
1711 case ExternalReference::BUILTIN_FP_CALL: {
1712 SimulatorRuntimeFPCall target =
1713 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1714 dresult = target(dval0);
1715 SetFpResult(dresult);
1718 case ExternalReference::BUILTIN_FP_INT_CALL: {
1719 SimulatorRuntimeFPIntCall target =
1720 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
1721 dresult = target(dval0, ival);
1722 SetFpResult(dresult);
1729 if (::v8::internal::FLAG_trace_sim) {
1730 switch (redirection->type()) {
1731 case ExternalReference::BUILTIN_COMPARE_CALL:
1734 case ExternalReference::BUILTIN_FP_FP_CALL:
1735 case ExternalReference::BUILTIN_FP_CALL:
1736 case ExternalReference::BUILTIN_FP_INT_CALL:
1737 PrintF(
"Returned %f\n", dresult);
1744 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1745 if (::v8::internal::FLAG_trace_sim) {
1746 PrintF(
"Call to host function at %p args %08lx\n",
1747 reinterpret_cast<void*
>(external), arg0);
1749 SimulatorRuntimeDirectApiCall target =
1750 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1753 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1754 if (::v8::internal::FLAG_trace_sim) {
1755 PrintF(
"Call to host function at %p args %08lx %08lx\n",
1756 reinterpret_cast<void*
>(external), arg0, arg1);
1758 SimulatorRuntimeProfilingApiCall target =
1759 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
1760 target(arg0, Redirection::ReverseRedirection(arg1));
1762 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1763 if (::v8::internal::FLAG_trace_sim) {
1764 PrintF(
"Call to host function at %p args %08lx %08lx\n",
1765 reinterpret_cast<void*
>(external), arg0, arg1);
1767 SimulatorRuntimeDirectGetterCall target =
1768 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1771 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1772 if (::v8::internal::FLAG_trace_sim) {
1773 PrintF(
"Call to host function at %p args %08lx %08lx %08lx\n",
1774 reinterpret_cast<void*
>(external), arg0, arg1, arg2);
1776 SimulatorRuntimeProfilingGetterCall target =
1777 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(external);
1778 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1780 SimulatorRuntimeCall target =
1781 reinterpret_cast<SimulatorRuntimeCall
>(external);
1782 if (::v8::internal::FLAG_trace_sim) {
1784 "Call to host function at %p "
1785 "args %08lx, %08lx, %08lx, %08lx, %08lx, %08lx\n",
1797 ObjectPair result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1798 set_register(v0, (int64_t)(result.x));
1799 set_register(v1, (int64_t)(result.y));
1801 if (::v8::internal::FLAG_trace_sim) {
1802 PrintF(
"Returned %08lx : %08lx\n", get_register(v1), get_register(v0));
1804 set_register(ra, saved_ra);
1805 set_pc(get_register(ra));
1808 if (IsWatchpoint(code)) {
1809 PrintWatchpoint(code);
1811 IncreaseStopCounter(code);
1812 HandleStop(code, instr);
1816 MipsDebugger dbg(
this);
1823 bool Simulator::IsWatchpoint(uint64_t code) {
1828 void Simulator::PrintWatchpoint(uint64_t code) {
1829 MipsDebugger dbg(
this);
1831 PrintF(
"\n---- break %ld marker: %3d (instr count: %8ld) ----------"
1832 "----------------------------------",
1833 code, break_count_, icount_);
1838 void Simulator::HandleStop(uint64_t code, Instruction* instr) {
1841 if (IsEnabledStop(code)) {
1842 MipsDebugger dbg(
this);
1845 set_pc(get_pc() + 2 * Instruction::kInstrSize);
1850 bool Simulator::IsStopInstruction(Instruction* instr) {
1851 int32_t func = instr->FunctionFieldRaw();
1857 bool Simulator::IsEnabledStop(uint64_t code) {
1860 return !(watched_stops_[code].count & kStopDisabledBit);
1864 void Simulator::EnableStop(uint64_t code) {
1865 if (!IsEnabledStop(code)) {
1866 watched_stops_[code].count &= ~kStopDisabledBit;
1871 void Simulator::DisableStop(uint64_t code) {
1872 if (IsEnabledStop(code)) {
1873 watched_stops_[code].count |= kStopDisabledBit;
1878 void Simulator::IncreaseStopCounter(uint64_t code) {
1880 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1881 PrintF(
"Stop counter for code %ld has overflowed.\n"
1882 "Enabling this code and reseting the counter to 0.\n", code);
1883 watched_stops_[code].count = 0;
1886 watched_stops_[code].count++;
1892 void Simulator::PrintStopInfo(uint64_t code) {
1894 PrintF(
"That is a watchpoint, not a stop.\n");
1900 const char* state = IsEnabledStop(code) ?
"Enabled" :
"Disabled";
1901 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1904 if (watched_stops_[code].desc) {
1905 PrintF(
"stop %ld - 0x%lx: \t%s, \tcounter = %i, \t%s\n",
1906 code, code, state, count, watched_stops_[code].desc);
1908 PrintF(
"stop %ld - 0x%lx: \t%s, \tcounter = %i\n",
1909 code, code, state, count);
1915 void Simulator::SignalExceptions() {
1916 for (
int i = 1;
i < kNumExceptions;
i++) {
1917 if (exceptions[
i] != 0) {
1918 V8_Fatal(__FILE__, __LINE__,
"Error: Exception %i raised.",
i);
1926 void Simulator::ConfigureTypeRegister(Instruction* instr,
1931 int64_t* return_addr_reg,
1933 int64_t* i128resultH,
1934 int64_t* i128resultL) {
1940 const Opcode op = instr->OpcodeFieldRaw();
1941 const int64_t rs_reg = instr->RsValue();
1942 const int64_t rs = get_register(rs_reg);
1943 const uint64_t rs_u =
static_cast<uint64_t
>(rs);
1944 const int64_t rt_reg = instr->RtValue();
1945 const int64_t rt = get_register(rt_reg);
1946 const uint64_t rt_u =
static_cast<uint64_t
>(rt);
1947 const int64_t rd_reg = instr->RdValue();
1948 const uint64_t sa = instr->SaValue();
1950 const int32_t fs_reg = instr->FsValue();
1956 switch (instr->RsFieldRaw()) {
1963 *alu_out =
static_cast<int64_t
>(get_fpu_register_word(fs_reg));
1966 *alu_out = get_fpu_register(fs_reg);
1969 *alu_out = get_fpu_register_hi_word(fs_reg);
1990 switch (instr->FunctionFieldRaw()) {
1993 *next_pc = get_register(instr->RsValue());
1994 *return_addr_reg = instr->RdValue();
2000 *alu_out = rt << sa;
2003 *alu_out = rt << sa << 32;
2018 *alu_out = rt_u >> sa;
2021 *alu_out = rt_u >> sa >> 32;
2027 *alu_out = rt >> sa;
2030 *alu_out = rt >> sa >> 32;
2036 *alu_out = rt << rs;
2055 *alu_out = rt_u >> rs;
2060 *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
2067 *alu_out = rt >> rs;
2071 DCHECK(instr->SaValue() == 0);
2072 *alu_out = get_register(HI);
2076 DCHECK(instr->SaValue() == 1);
2081 *alu_out = get_register(LO);
2088 *i64hilo =
static_cast<int64_t
>((
int32_t)rs) *
2089 static_cast<int64_t
>((
int32_t)rt);
2092 *u64hilo =
static_cast<uint64_t
>(rs_u) *
static_cast<uint64_t
>(rt_u);
2096 *i128resultH = MultiplyHighSigned(rs, rt);
2097 *i128resultL = rs * rt;
2099 switch (instr->SaValue()) {
2101 *i128resultL = rs * rt;
2104 *i128resultH = MultiplyHighSigned(rs, rt);
2117 if (HaveSameSign(rs, rt)) {
2119 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
2120 }
else if (rs < 0) {
2121 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
2129 *alu_out =
static_cast<int64_t
>(alu32_out);
2137 if (!HaveSameSign(rs, rt)) {
2139 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
2140 }
else if (rs < 0) {
2141 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
2149 *alu_out =
static_cast<int64_t
>(alu32_out);
2165 *alu_out = ~(rs | rt);
2168 *alu_out = rs < rt ? 1 : 0;
2171 *alu_out = rs_u < rt_u ? 1 : 0;
2176 *do_interrupt =
true;
2179 *do_interrupt = rs >= rt;
2182 *do_interrupt = rs_u >= rt_u;
2185 *do_interrupt = rs < rt;
2188 *do_interrupt = rs_u < rt_u;
2191 *do_interrupt = rs == rt;
2194 *do_interrupt = rs != rt;
2212 switch (instr->FunctionFieldRaw()) {
2227 switch (instr->FunctionFieldRaw()) {
2235 *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
2245 *alu_out = (rs_u & (mask << lsb)) >> lsb;
2258 void Simulator::DecodeTypeRegister(Instruction* instr) {
2260 const Opcode op = instr->OpcodeFieldRaw();
2261 const int64_t rs_reg = instr->RsValue();
2262 const int64_t rs = get_register(rs_reg);
2263 const uint64_t rs_u =
static_cast<uint32_t>(rs);
2264 const int64_t rt_reg = instr->RtValue();
2265 const int64_t rt = get_register(rt_reg);
2266 const uint64_t rt_u =
static_cast<uint32_t>(rt);
2267 const int64_t rd_reg = instr->RdValue();
2269 const int32_t fr_reg = instr->FrValue();
2270 const int32_t fs_reg = instr->FsValue();
2271 const int32_t ft_reg = instr->FtValue();
2272 const int64_t fd_reg = instr->FdValue();
2273 int64_t i64hilo = 0;
2274 uint64_t u64hilo = 0;
2279 int64_t alu_out = 0x12345678;
2282 bool do_interrupt =
false;
2286 int64_t current_pc = get_pc();
2288 int64_t next_pc = 0;
2289 int64_t return_addr_reg = 31;
2291 int64_t i128resultH;
2292 int64_t i128resultL;
2295 ConfigureTypeRegister(instr,
2311 switch (instr->RsFieldRaw()) {
2318 set_register(rt_reg, alu_out);
2323 set_register(rt_reg, alu_out);
2328 FCSR_ = registers_[rt_reg];
2332 set_fpu_register_hi_word(fs_reg, 0);
2333 set_fpu_register_word(fs_reg, registers_[rt_reg]);
2336 set_fpu_register(fs_reg, registers_[rt_reg]);
2339 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
2343 switch (instr->FunctionFieldRaw()) {
2345 f = get_fpu_register_float(fs_reg);
2346 set_fpu_register_double(fd_reg,
static_cast<double>(f));
2358 fs = get_fpu_register_double(fs_reg);
2359 ft = get_fpu_register_double(ft_reg);
2360 cc = instr->FCccValue();
2361 fcsr_cc = get_fcsr_condition_bit(
cc);
2362 switch (instr->FunctionFieldRaw()) {
2364 set_fpu_register_double(fd_reg, fs + ft);
2367 set_fpu_register_double(fd_reg, fs - ft);
2370 set_fpu_register_double(fd_reg, fs * ft);
2373 set_fpu_register_double(fd_reg, fs / ft);
2376 set_fpu_register_double(fd_reg, fabs(fs));
2379 set_fpu_register_double(fd_reg, fs);
2382 set_fpu_register_double(fd_reg, -fs);
2385 set_fpu_register_double(fd_reg, sqrt(fs));
2388 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2391 set_fcsr_bit(fcsr_cc, (fs == ft));
2394 set_fcsr_bit(fcsr_cc,
2395 (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2398 set_fcsr_bit(fcsr_cc, (fs < ft));
2401 set_fcsr_bit(fcsr_cc,
2402 (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2405 set_fcsr_bit(fcsr_cc, (fs <= ft));
2408 set_fcsr_bit(fcsr_cc,
2409 (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2413 DCHECK((FCSR_ & 3) == 0);
2418 double rounded = std::floor(fs + 0.5);
2420 if ((result & 1) != 0 && result - fs == 0.5) {
2425 set_fpu_register_word(fd_reg, result);
2426 if (set_fcsr_round_error(fs, rounded)) {
2433 double rounded = trunc(fs);
2435 set_fpu_register_word(fd_reg, result);
2436 if (set_fcsr_round_error(fs, rounded)) {
2443 double rounded = std::floor(fs);
2445 set_fpu_register_word(fd_reg, result);
2446 if (set_fcsr_round_error(fs, rounded)) {
2453 double rounded = std::ceil(fs);
2455 set_fpu_register_word(fd_reg, result);
2456 if (set_fcsr_round_error(fs, rounded)) {
2462 set_fpu_register_float(fd_reg,
static_cast<float>(fs));
2466 DCHECK((FCSR_ & 3) == 0);
2471 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2472 int64_t result =
static_cast<int64_t
>(rounded);
2473 set_fpu_register(fd_reg, result);
2474 if (set_fcsr_round64_error(fs, rounded)) {
2480 double rounded = trunc(fs);
2481 int64_t result =
static_cast<int64_t
>(rounded);
2482 set_fpu_register(fd_reg, result);
2483 if (set_fcsr_round64_error(fs, rounded)) {
2489 double rounded = floor(fs);
2490 int64_t result =
static_cast<int64_t
>(rounded);
2491 set_fpu_register(fd_reg, result);
2492 if (set_fcsr_round64_error(fs, rounded)) {
2498 double rounded = ceil(fs);
2499 int64_t result =
static_cast<int64_t
>(rounded);
2500 set_fpu_register(fd_reg, result);
2501 if (set_fcsr_round64_error(fs, rounded)) {
2514 switch (instr->FunctionFieldRaw()) {
2516 alu_out = get_fpu_register_signed_word(fs_reg);
2517 set_fpu_register_float(fd_reg,
static_cast<float>(alu_out));
2520 alu_out = get_fpu_register_signed_word(fs_reg);
2521 set_fpu_register_double(fd_reg,
static_cast<double>(alu_out));
2528 fs = get_fpu_register_double(fs_reg);
2529 ft = get_fpu_register_double(ft_reg);
2530 switch (instr->FunctionFieldRaw()) {
2532 i64 = get_fpu_register(fs_reg);
2533 set_fpu_register_double(fd_reg,
static_cast<double>(i64));
2542 if (std::isnan(fs) || std::isnan(ft)) {
2543 set_fpu_register(fd_reg, -1);
2545 set_fpu_register(fd_reg, 0);
2550 set_fpu_register(fd_reg, -1);
2552 set_fpu_register(fd_reg, 0);
2556 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2557 set_fpu_register(fd_reg, -1);
2559 set_fpu_register(fd_reg, 0);
2564 set_fpu_register(fd_reg, -1);
2566 set_fpu_register(fd_reg, 0);
2570 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2571 set_fpu_register(fd_reg, -1);
2573 set_fpu_register(fd_reg, 0);
2578 set_fpu_register(fd_reg, -1);
2580 set_fpu_register(fd_reg, 0);
2584 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2585 set_fpu_register(fd_reg, -1);
2587 set_fpu_register(fd_reg, 0);
2599 switch (instr->FunctionFieldRaw()) {
2602 fr = get_fpu_register_double(fr_reg);
2603 fs = get_fpu_register_double(fs_reg);
2604 ft = get_fpu_register_double(ft_reg);
2605 set_fpu_register_double(fd_reg, fs * ft + fr);
2612 switch (instr->FunctionFieldRaw()) {
2614 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2615 current_pc+Instruction::kInstrSize);
2616 BranchDelayInstructionDecode(branch_delay_instr);
2618 pc_modified_ =
true;
2622 Instruction* branch_delay_instr =
reinterpret_cast<Instruction*
>(
2623 current_pc+Instruction::kInstrSize);
2624 BranchDelayInstructionDecode(branch_delay_instr);
2625 set_register(return_addr_reg,
2626 current_pc + 2 * Instruction::kInstrSize);
2628 pc_modified_ =
true;
2634 set_register(LO,
static_cast<int32_t>(i64hilo & 0xffffffff));
2635 set_register(HI,
static_cast<int32_t>(i64hilo >> 32));
2637 switch (instr->SaValue()) {
2639 set_register(rd_reg,
2640 static_cast<int32_t>(i64hilo & 0xffffffff));
2643 set_register(rd_reg,
static_cast<int32_t>(i64hilo >> 32));
2652 set_register(LO,
static_cast<int32_t>(u64hilo & 0xffffffff));
2653 set_register(HI,
static_cast<int32_t>(u64hilo >> 32));
2657 set_register(LO,
static_cast<int64_t
>(i128resultL));
2658 set_register(HI,
static_cast<int64_t
>(i128resultH));
2660 switch (instr->SaValue()) {
2662 set_register(rd_reg,
static_cast<int64_t
>(i128resultL));
2665 set_register(rd_reg,
static_cast<int64_t
>(i128resultH));
2677 set_register(rd_reg, alu_out);
2687 if (rs == INT_MIN && rt == -1) {
2688 set_register(LO, INT_MIN);
2689 set_register(HI, 0);
2690 }
else if (rt != 0) {
2691 set_register(LO, rs / rt);
2692 set_register(HI, rs % rt);
2696 switch (instr->SaValue()) {
2698 if (rs == INT_MIN && rt == -1) {
2699 set_register(rd_reg, INT_MIN);
2700 }
else if (rt != 0) {
2701 set_register(rd_reg, rs / rt);
2705 if (rs == INT_MIN && rt == -1) {
2706 set_register(rd_reg, 0);
2707 }
else if (rt != 0) {
2708 set_register(rd_reg, rs % rt);
2722 set_register(LO, rs_u / rt_u);
2723 set_register(HI, rs_u % rt_u);
2735 SoftwareInterrupt(instr);
2741 set_register(rd_reg, rs);
2747 uint32_t fcsr_cc = get_fcsr_condition_bit(
cc);
2748 if (instr->Bit(16)) {
2749 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2751 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2757 set_register(rd_reg, rs);
2762 set_register(rd_reg, alu_out);
2763 TraceRegWr(alu_out);
2767 switch (instr->FunctionFieldRaw()) {
2769 set_register(rd_reg, alu_out);
2770 TraceRegWr(alu_out);
2772 set_register(LO, Unpredictable);
2773 set_register(HI, Unpredictable);
2776 set_register(rd_reg, alu_out);
2780 switch (instr->FunctionFieldRaw()) {
2783 set_register(rt_reg, alu_out);
2784 TraceRegWr(alu_out);
2788 set_register(rt_reg, alu_out);
2789 TraceRegWr(alu_out);
2799 set_register(rd_reg, alu_out);
2800 TraceRegWr(alu_out);
2806 void Simulator::DecodeTypeImmediate(Instruction* instr) {
2808 Opcode op = instr->OpcodeFieldRaw();
2809 int64_t rs = get_register(instr->RsValue());
2810 uint64_t rs_u =
static_cast<uint64_t
>(rs);
2811 int64_t rt_reg = instr->RtValue();
2812 int64_t rt = get_register(rt_reg);
2813 int16_t imm16 = instr->Imm16Value();
2815 int32_t ft_reg = instr->FtValue();
2816 int64_t ft = get_fpu_register(ft_reg);
2819 uint32_t oe_imm16 = 0xffff & imm16;
2824 int64_t current_pc = get_pc();
2826 int64_t next_pc = bad_ra;
2829 bool do_branch =
false;
2830 bool execute_branch_delay_instruction =
false;
2833 int64_t alu_out = 0;
2835 double fp_out = 0.0;
2841 uint64_t mem_value = 0x0;
2843 const int kInt32AlignmentMask =
sizeof(
uint32_t) - 1;
2849 switch (instr->RsFieldRaw()) {
2851 cc = instr->FBccValue();
2852 fcsr_cc = get_fcsr_condition_bit(
cc);
2853 cc_value = test_fcsr_bit(fcsr_cc);
2854 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2855 execute_branch_delay_instruction =
true;
2858 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2864 do_branch = (ft & 0x1) ?
false :
true;
2865 execute_branch_delay_instruction =
true;
2868 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2874 do_branch = (ft & 0x1) ?
true :
false;
2875 execute_branch_delay_instruction =
true;
2878 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2889 switch (instr->RtFieldRaw()) {
2891 do_branch = (rs < 0);
2897 do_branch = rs >= 0;
2900 do_branch = rs >= 0;
2905 switch (instr->RtFieldRaw()) {
2911 execute_branch_delay_instruction =
true;
2914 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2915 if (instr->IsLinkingInstruction()) {
2929 do_branch = (rs == rt);
2932 do_branch = rs != rt;
2935 do_branch = rs <= 0;
2943 if (HaveSameSign(rs, se_imm16)) {
2945 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2946 }
else if (rs < 0) {
2947 exceptions[kIntegerUnderflow] =
2948 rs < (Registers::kMinValue - se_imm16);
2951 alu_out = rs + se_imm16;
2954 int32_t alu32_out = rs + se_imm16;
2956 alu_out =
static_cast<int64_t
>(alu32_out);
2960 alu_out = rs + se_imm16;
2963 alu_out = (rs < se_imm16) ? 1 : 0;
2966 alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2969 alu_out = rs & oe_imm16;
2972 alu_out = rs | oe_imm16;
2975 alu_out = rs ^ oe_imm16;
2978 int32_t alu32_out = (oe_imm16 << 16);
2980 alu_out =
static_cast<int64_t
>(alu32_out);
2985 addr = rs + se_imm16;
2986 alu_out = ReadB(addr);
2989 addr = rs + se_imm16;
2990 alu_out = ReadH(addr, instr);
2994 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
2995 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
2996 uint32_t mask = (1 << byte_shift * 8) - 1;
2997 addr = rs + se_imm16 - al_offset;
2998 alu_out = ReadW(addr, instr);
2999 alu_out <<= byte_shift * 8;
3000 alu_out |= rt & mask;
3004 addr = rs + se_imm16;
3005 alu_out = ReadW(addr, instr);
3008 addr = rs + se_imm16;
3009 alu_out = ReadWU(addr, instr);
3012 addr = rs + se_imm16;
3013 alu_out = Read2W(addr, instr);
3016 addr = rs + se_imm16;
3017 alu_out = ReadBU(addr);
3020 addr = rs + se_imm16;
3021 alu_out = ReadHU(addr, instr);
3025 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
3026 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
3027 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
3028 addr = rs + se_imm16 - al_offset;
3029 alu_out = ReadW(addr, instr);
3030 alu_out =
static_cast<uint32_t> (alu_out) >> al_offset * 8;
3031 alu_out |= rt & mask;
3035 addr = rs + se_imm16;
3038 addr = rs + se_imm16;
3041 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
3042 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
3043 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
3044 addr = rs + se_imm16 - al_offset;
3045 mem_value = ReadW(addr, instr) & mask;
3046 mem_value |=
static_cast<uint32_t>(rt) >> byte_shift * 8;
3051 addr = rs + se_imm16;
3054 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
3055 uint32_t mask = (1 << al_offset * 8) - 1;
3056 addr = rs + se_imm16 - al_offset;
3057 mem_value = ReadW(addr, instr);
3058 mem_value = (rt << al_offset * 8) | (mem_value & mask);
3062 addr = rs + se_imm16;
3063 alu_out = ReadW(addr, instr);
3066 addr = rs + se_imm16;
3067 fp_out = ReadD(addr, instr);
3071 addr = rs + se_imm16;
3088 execute_branch_delay_instruction =
true;
3091 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
3092 if (instr->IsLinkingInstruction()) {
3093 set_register(31, current_pc + 2* Instruction::kInstrSize);
3096 next_pc = current_pc + 2 * Instruction::kInstrSize;
3110 set_register(rt_reg, alu_out);
3111 TraceRegWr(alu_out);
3123 set_register(rt_reg, alu_out);
3126 WriteB(addr,
static_cast<int8_t
>(rt));
3129 WriteH(addr,
static_cast<uint16_t>(rt), instr);
3132 WriteW(addr, mem_value, instr);
3135 WriteW(addr, rt, instr);
3138 Write2W(addr, rt, instr);
3141 WriteW(addr, mem_value, instr);
3145 set_fpu_register_word(ft_reg,
static_cast<int32_t>(alu_out));
3148 set_fpu_register_double(ft_reg, fp_out);
3151 addr = rs + se_imm16;
3152 WriteW(addr, get_fpu_register(ft_reg), instr);
3155 addr = rs + se_imm16;
3156 WriteD(addr, get_fpu_register_double(ft_reg), instr);
3163 if (execute_branch_delay_instruction) {
3167 Instruction* branch_delay_instr =
3168 reinterpret_cast<Instruction*
>(current_pc+Instruction::kInstrSize);
3169 BranchDelayInstructionDecode(branch_delay_instr);
3173 if (next_pc != bad_ra) {
3180 void Simulator::DecodeTypeJump(Instruction* instr) {
3182 int32_t current_pc = get_pc();
3184 int32_t pc_high_bits = current_pc & 0xf0000000;
3186 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
3191 Instruction* branch_delay_instr =
3192 reinterpret_cast<Instruction*
>(current_pc + Instruction::kInstrSize);
3193 BranchDelayInstructionDecode(branch_delay_instr);
3197 if (instr->IsLinkingInstruction()) {
3198 set_register(31, current_pc + 2 * Instruction::kInstrSize);
3201 pc_modified_ =
true;
3206 void Simulator::InstructionDecode(Instruction* instr) {
3207 if (v8::internal::FLAG_check_icache) {
3208 CheckICache(isolate_->simulator_i_cache(), instr);
3210 pc_modified_ =
false;
3214 if (::v8::internal::FLAG_trace_sim) {
3219 dasm.InstructionDecode(buffer,
reinterpret_cast<byte*
>(instr));
3222 switch (instr->InstructionType()) {
3223 case Instruction::kRegisterType:
3224 DecodeTypeRegister(instr);
3226 case Instruction::kImmediateType:
3227 DecodeTypeImmediate(instr);
3229 case Instruction::kJumpType:
3230 DecodeTypeJump(instr);
3236 if (::v8::internal::FLAG_trace_sim) {
3237 PrintF(
" 0x%08lx %-44s %s\n",
reinterpret_cast<intptr_t
>(instr),
3238 buffer.
start(), trace_buf_.start());
3241 if (!pc_modified_) {
3242 set_register(
pc,
reinterpret_cast<int64_t
>(instr) +
3243 Instruction::kInstrSize);
3249 void Simulator::Execute() {
3252 int64_t program_counter = get_pc();
3253 if (::v8::internal::FLAG_stop_sim_at == 0) {
3256 while (program_counter != end_sim_pc) {
3257 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3259 InstructionDecode(instr);
3260 program_counter = get_pc();
3265 while (program_counter != end_sim_pc) {
3266 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3268 if (icount_ ==
static_cast<int64_t
>(::v8::internal::FLAG_stop_sim_at)) {
3269 MipsDebugger dbg(
this);
3272 InstructionDecode(instr);
3274 program_counter = get_pc();
3280 void Simulator::CallInternal(
byte* entry) {
3282 set_register(
pc,
reinterpret_cast<int64_t
>(entry));
3286 set_register(ra, end_sim_pc);
3291 int64_t s0_val = get_register(
s0);
3292 int64_t s1_val = get_register(
s1);
3293 int64_t s2_val = get_register(
s2);
3294 int64_t s3_val = get_register(
s3);
3295 int64_t s4_val = get_register(
s4);
3296 int64_t s5_val = get_register(
s5);
3297 int64_t s6_val = get_register(
s6);
3298 int64_t s7_val = get_register(
s7);
3299 int64_t gp_val = get_register(gp);
3300 int64_t sp_val = get_register(
sp);
3301 int64_t fp_val = get_register(
fp);
3305 int64_t callee_saved_value = icount_;
3306 set_register(
s0, callee_saved_value);
3307 set_register(
s1, callee_saved_value);
3308 set_register(
s2, callee_saved_value);
3309 set_register(
s3, callee_saved_value);
3310 set_register(
s4, callee_saved_value);
3311 set_register(
s5, callee_saved_value);
3312 set_register(
s6, callee_saved_value);
3313 set_register(
s7, callee_saved_value);
3314 set_register(gp, callee_saved_value);
3315 set_register(
fp, callee_saved_value);
3321 CHECK_EQ(callee_saved_value, get_register(
s0));
3322 CHECK_EQ(callee_saved_value, get_register(
s1));
3323 CHECK_EQ(callee_saved_value, get_register(
s2));
3324 CHECK_EQ(callee_saved_value, get_register(
s3));
3325 CHECK_EQ(callee_saved_value, get_register(
s4));
3326 CHECK_EQ(callee_saved_value, get_register(
s5));
3327 CHECK_EQ(callee_saved_value, get_register(
s6));
3328 CHECK_EQ(callee_saved_value, get_register(
s7));
3329 CHECK_EQ(callee_saved_value, get_register(gp));
3330 CHECK_EQ(callee_saved_value, get_register(
fp));
3333 set_register(
s0, s0_val);
3334 set_register(
s1, s1_val);
3335 set_register(
s2, s2_val);
3336 set_register(
s3, s3_val);
3337 set_register(
s4, s4_val);
3338 set_register(
s5, s5_val);
3339 set_register(
s6, s6_val);
3340 set_register(
s7, s7_val);
3341 set_register(gp, gp_val);
3342 set_register(
sp, sp_val);
3343 set_register(
fp, fp_val);
3347 int64_t Simulator::Call(
byte* entry,
int argument_count, ...) {
3348 const int kRegisterPassedArguments = (
kMipsAbi ==
kN64) ? 8 : 4;
3350 va_start(parameters, argument_count);
3354 DCHECK(argument_count >= 4);
3355 set_register(a0, va_arg(parameters, int64_t));
3356 set_register(a1, va_arg(parameters, int64_t));
3357 set_register(a2, va_arg(parameters, int64_t));
3358 set_register(a3, va_arg(parameters, int64_t));
3363 if (argument_count >= 5) set_register(a4, va_arg(parameters, int64_t));
3364 if (argument_count >= 6) set_register(a5, va_arg(parameters, int64_t));
3365 if (argument_count >= 7) set_register(a6, va_arg(parameters, int64_t));
3366 if (argument_count >= 8) set_register(a7, va_arg(parameters, int64_t));
3370 int64_t original_stack = get_register(
sp);
3372 int stack_args_count = (argument_count > kRegisterPassedArguments) ?
3373 (argument_count - kRegisterPassedArguments) : 0;
3374 int stack_args_size = stack_args_count *
sizeof(int64_t) +
kCArgsSlotsSize;
3375 int64_t entry_stack = original_stack - stack_args_size;
3377 if (base::OS::ActivationFrameAlignment() != 0) {
3378 entry_stack &= -base::OS::ActivationFrameAlignment();
3381 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
3382 for (
int i = kRegisterPassedArguments;
i < argument_count;
i++) {
3384 stack_argument[stack_index] = va_arg(parameters, int64_t);
3387 set_register(
sp, entry_stack);
3389 CallInternal(entry);
3393 set_register(
sp, original_stack);
3395 int64_t result = get_register(v0);
3400 double Simulator::CallFP(
byte* entry,
double d0,
double d1) {
3403 set_fpu_register_double(
f12,
d0);
3404 set_fpu_register_double(fparg2,
d1);
3407 DCHECK(
sizeof(buffer[0]) * 2 ==
sizeof(
d0));
3408 memcpy(buffer, &
d0,
sizeof(
d0));
3409 set_dw_register(a0, buffer);
3410 memcpy(buffer, &
d1,
sizeof(
d1));
3411 set_dw_register(a2, buffer);
3413 CallInternal(entry);
3415 return get_fpu_register_double(
f0);
3417 return get_double_from_register_pair(v0);
3423 int64_t new_sp = get_register(
sp) -
sizeof(
uintptr_t);
3425 *stack_slot = address;
3426 set_register(
sp, new_sp);
3432 int64_t current_sp = get_register(
sp);
static int Number(const char *name)
static const char * Name(int reg)
static int Number(const char *name)
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
static const AbiVariants kMipsAbi
const bool IsMipsSoftFloatABI
#define UNIMPLEMENTED_MIPS()
static const ArchVariants kArchVariant
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
void V8_Fatal(const char *file, int line, const char *format,...)
#define CHECK_EQ(expected, value)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define OFFSET_OF(type, field)
uint32_t CountLeadingZeros32(uint32_t value)
typedef DWORD(__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID)
LinkageHelper< ArmLinkageHelperTraits > LH
void DeleteArray(T *array)
char * ReadLine(const char *prompt)
TypeImpl< ZoneTypeConfig > Type
static int min(int a, int b)
const intptr_t kPointerAlignmentMask
const LowDwVfpRegister d1
const Instr rtCallRedirInstr
const uint32_t kMaxStopCode
const uint32_t kMaxWatchpointCode
const LowDwVfpRegister d0
int SNPrintF(Vector< char > str, const char *format,...)
kSerializedDataOffset Object
const int kNumFPURegisters
const int kInvalidFPURegister
const int kNumSimuRegisters
const int kInvalidRegister
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
void PrintF(const char *format,...)
const int kCArgsSlotsSize
const uint64_t kFPU64InvalidResult
const int kBranchReturnOffset
const uint32_t kFCSRInvalidOpFlagBit
const uint32_t kFPUInvalidResult
const uint32_t kFCSROverflowFlagBit
const unsigned kInstructionSize
const uint32_t kFCSRUnderflowFlagBit
const intptr_t kDoubleAlignmentMask
const uint32_t kFCSRInexactFlagBit
Debugger support for the V8 JavaScript engine.