34 #if V8_TARGET_ARCH_ARM
42 #if defined(USE_SIMULATOR)
52 #define SScanF sscanf // NOLINT
58 explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
61 void Stop(Instruction* instr);
65 static const Instr kBreakpointInstr =
67 static const Instr kNopInstr = (
al | (13*
B21));
71 int32_t GetRegisterValue(
int regnum);
72 double GetRegisterPairDoubleValue(
int regnum);
73 double GetVFPDoubleRegisterValue(
int regnum);
74 bool GetValue(
const char* desc,
int32_t* value);
75 bool GetVFPSingleValue(
const char* desc,
float* value);
76 bool GetVFPDoubleValue(
const char* desc,
double* value);
79 bool SetBreakpoint(Instruction* breakpc);
80 bool DeleteBreakpoint(Instruction* breakpc);
84 void UndoBreakpoints();
85 void RedoBreakpoints();
89 ArmDebugger::~ArmDebugger() {
94 #ifdef GENERATED_CODE_COVERAGE
95 static FILE* coverage_log =
NULL;
98 static void InitializeCoverage() {
99 char* file_name = getenv(
"V8_GENERATED_CODE_COVERAGE_LOG");
100 if (file_name !=
NULL) {
101 coverage_log = fopen(file_name,
"aw+");
106 void ArmDebugger::Stop(Instruction* instr) {
112 char* msg = *msg_address;
116 if (isWatchedStop(code) && !watched_stops_[code].desc) {
117 watched_stops_[
code].desc = msg;
120 if (strlen(msg) > 0) {
121 if (coverage_log !=
NULL) {
122 fprintf(coverage_log,
"%s\n", msg);
123 fflush(coverage_log);
126 instr->SetInstructionBits(kNopInstr);
127 reinterpret_cast<Instruction*
>(msg_address)->SetInstructionBits(kNopInstr);
132 #else // ndef GENERATED_CODE_COVERAGE
134 static void InitializeCoverage() {
138 void ArmDebugger::Stop(Instruction* instr) {
142 char* msg = *
reinterpret_cast<char**
>(sim_->get_pc()
145 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[
code].desc) {
146 sim_->watched_stops_[
code].desc = msg;
150 PrintF(
"Simulator hit stop %u: %s\n", code, msg);
152 PrintF(
"Simulator hit %s\n", msg);
160 int32_t ArmDebugger::GetRegisterValue(
int regnum) {
162 return sim_->get_pc();
164 return sim_->get_register(regnum);
169 double ArmDebugger::GetRegisterPairDoubleValue(
int regnum) {
170 return sim_->get_double_from_register_pair(regnum);
174 double ArmDebugger::GetVFPDoubleRegisterValue(
int regnum) {
175 return sim_->get_double_from_d_register(regnum);
179 bool ArmDebugger::GetValue(
const char* desc,
int32_t* value) {
182 *value = GetRegisterValue(regnum);
185 if (strncmp(desc,
"0x", 2) == 0) {
186 return SScanF(desc + 2,
"%x", reinterpret_cast<uint32_t*>(value)) == 1;
188 return SScanF(desc,
"%u", reinterpret_cast<uint32_t*>(value)) == 1;
195 bool ArmDebugger::GetVFPSingleValue(
const char* desc,
float* value) {
199 *value = sim_->get_float_from_s_register(regnum);
206 bool ArmDebugger::GetVFPDoubleValue(
const char* desc,
double* value) {
210 *value = sim_->get_double_from_d_register(regnum);
217 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
219 if (sim_->break_pc_ !=
NULL) {
224 sim_->break_pc_ = breakpc;
225 sim_->break_instr_ = breakpc->InstructionBits();
232 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
233 if (sim_->break_pc_ !=
NULL) {
234 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
237 sim_->break_pc_ =
NULL;
238 sim_->break_instr_ = 0;
243 void ArmDebugger::UndoBreakpoints() {
244 if (sim_->break_pc_ !=
NULL) {
245 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
250 void ArmDebugger::RedoBreakpoints() {
251 if (sim_->break_pc_ !=
NULL) {
252 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
257 void ArmDebugger::Debug() {
258 intptr_t last_pc = -1;
261 #define COMMAND_SIZE 63
265 #define XSTR(a) STR(a)
267 char cmd[COMMAND_SIZE + 1];
268 char arg1[ARG_SIZE + 1];
269 char arg2[ARG_SIZE + 1];
270 char* argv[3] = { cmd, arg1, arg2 };
273 cmd[COMMAND_SIZE] = 0;
281 while (!done && !sim_->has_bad_pc()) {
282 if (last_pc != sim_->get_pc()) {
287 dasm.InstructionDecode(buffer,
288 reinterpret_cast<byte*>(sim_->get_pc()));
289 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.
start());
290 last_pc = sim_->get_pc();
296 char* last_input = sim_->last_debugger_input();
297 if (strcmp(line,
"\n") == 0 && last_input !=
NULL) {
301 sim_->set_last_debugger_input(line);
305 int argc = SScanF(line,
306 "%" XSTR(COMMAND_SIZE)
"s "
307 "%" XSTR(ARG_SIZE)
"s "
308 "%" XSTR(ARG_SIZE)
"s",
310 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
311 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
312 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
314 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
317 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
318 if (argc == 2 || (argc == 3 && strcmp(arg2,
"fp") == 0)) {
322 if (strcmp(arg1,
"all") == 0) {
324 value = GetRegisterValue(i);
326 if ((argc == 3 && strcmp(arg2,
"fp") == 0) &&
329 dvalue = GetRegisterPairDoubleValue(i);
330 PrintF(
" (%f)\n", dvalue);
336 dvalue = GetVFPDoubleRegisterValue(i);
337 uint64_t as_words = BitCast<uint64_t>(dvalue);
338 PrintF(
"%3s: %f 0x%08x %08x\n",
341 static_cast<uint32_t>(as_words >> 32),
342 static_cast<uint32_t>(as_words & 0xffffffff));
345 if (GetValue(arg1, &value)) {
346 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
347 }
else if (GetVFPSingleValue(arg1, &svalue)) {
348 uint32_t as_word = BitCast<uint32_t>(svalue);
349 PrintF(
"%s: %f 0x%08x\n", arg1, svalue, as_word);
350 }
else if (GetVFPDoubleValue(arg1, &dvalue)) {
351 uint64_t as_words = BitCast<uint64_t>(dvalue);
352 PrintF(
"%s: %f 0x%08x %08x\n",
355 static_cast<uint32_t>(as_words >> 32),
356 static_cast<uint32_t>(as_words & 0xffffffff));
358 PrintF(
"%s unrecognized\n", arg1);
362 PrintF(
"print <register>\n");
364 }
else if ((strcmp(cmd,
"po") == 0)
365 || (strcmp(cmd,
"printobject") == 0)) {
368 if (GetValue(arg1, &value)) {
378 PrintF(
"%s unrecognized\n", arg1);
381 PrintF(
"printobject <value>\n");
383 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
388 if (strcmp(cmd,
"stack") == 0) {
392 if (!GetValue(arg1, &value)) {
393 PrintF(
"%s unrecognized\n", arg1);
396 cur =
reinterpret_cast<int32_t*
>(value);
401 if (argc == next_arg) {
404 if (!GetValue(argv[next_arg], &words)) {
411 PrintF(
" 0x%08x: 0x%08x %10d",
412 reinterpret_cast<intptr_t>(cur), *cur, *cur);
413 HeapObject*
obj =
reinterpret_cast<HeapObject*
>(*cur);
415 Heap* current_heap = v8::internal::Isolate::Current()->heap();
416 if (((value & 1) == 0) || current_heap->Contains(obj)) {
418 if ((value & 1) == 0) {
419 PrintF(
"smi %d", value / 2);
428 }
else if (strcmp(cmd,
"disasm") == 0 || strcmp(cmd,
"di") == 0) {
439 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
441 }
else if (argc == 2) {
443 if (regnum !=
kNoRegister || strncmp(arg1,
"0x", 2) == 0) {
446 if (GetValue(arg1, &value)) {
447 cur =
reinterpret_cast<byte*
>(value);
454 if (GetValue(arg1, &value)) {
455 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
463 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
464 cur =
reinterpret_cast<byte*
>(value1);
471 cur += dasm.InstructionDecode(buffer, cur);
473 reinterpret_cast<intptr_t>(prev), buffer.
start());
475 }
else if (strcmp(cmd,
"gdb") == 0) {
476 PrintF(
"relinquishing control to gdb\n");
478 PrintF(
"regaining control from gdb\n");
479 }
else if (strcmp(cmd,
"break") == 0) {
482 if (GetValue(arg1, &value)) {
483 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
484 PrintF(
"setting breakpoint failed\n");
487 PrintF(
"%s unrecognized\n", arg1);
490 PrintF(
"break <address>\n");
492 }
else if (strcmp(cmd,
"del") == 0) {
493 if (!DeleteBreakpoint(
NULL)) {
494 PrintF(
"deleting breakpoint failed\n");
496 }
else if (strcmp(cmd,
"flags") == 0) {
497 PrintF(
"N flag: %d; ", sim_->n_flag_);
498 PrintF(
"Z flag: %d; ", sim_->z_flag_);
499 PrintF(
"C flag: %d; ", sim_->c_flag_);
500 PrintF(
"V flag: %d\n", sim_->v_flag_);
501 PrintF(
"INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
502 PrintF(
"DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
503 PrintF(
"OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
504 PrintF(
"UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
505 PrintF(
"INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
506 }
else if (strcmp(cmd,
"stop") == 0) {
509 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
510 Instruction* msg_address =
512 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
514 if (sim_->isStopInstruction(stop_instr)) {
515 stop_instr->SetInstructionBits(kNopInstr);
516 msg_address->SetInstructionBits(kNopInstr);
518 PrintF(
"Not at debugger stop.\n");
520 }
else if (argc == 3) {
522 if (strcmp(arg1,
"info") == 0) {
523 if (strcmp(arg2,
"all") == 0) {
524 PrintF(
"Stop information:\n");
525 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
526 sim_->PrintStopInfo(i);
528 }
else if (GetValue(arg2, &value)) {
529 sim_->PrintStopInfo(value);
531 PrintF(
"Unrecognized argument.\n");
533 }
else if (strcmp(arg1,
"enable") == 0) {
535 if (strcmp(arg2,
"all") == 0) {
536 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
539 }
else if (GetValue(arg2, &value)) {
540 sim_->EnableStop(value);
542 PrintF(
"Unrecognized argument.\n");
544 }
else if (strcmp(arg1,
"disable") == 0) {
546 if (strcmp(arg2,
"all") == 0) {
547 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
548 sim_->DisableStop(i);
550 }
else if (GetValue(arg2, &value)) {
551 sim_->DisableStop(value);
553 PrintF(
"Unrecognized argument.\n");
557 PrintF(
"Wrong usage. Use help command for more information.\n");
559 }
else if ((strcmp(cmd,
"t") == 0) || strcmp(cmd,
"trace") == 0) {
560 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
561 PrintF(
"Trace of executed instructions is %s\n",
562 ::v8::internal::FLAG_trace_sim ?
"on" :
"off");
563 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
565 PrintF(
" continue execution (alias 'c')\n");
567 PrintF(
" step one instruction (alias 'si')\n");
568 PrintF(
"print <register>\n");
569 PrintF(
" print register content (alias 'p')\n");
570 PrintF(
" use register name 'all' to print all registers\n");
571 PrintF(
" add argument 'fp' to print register pair double values\n");
572 PrintF(
"printobject <register>\n");
573 PrintF(
" print an object from a register (alias 'po')\n");
576 PrintF(
"stack [<words>]\n");
577 PrintF(
" dump stack content, default dump 10 words)\n");
578 PrintF(
"mem <address> [<words>]\n");
579 PrintF(
" dump memory content, default dump 10 words)\n");
580 PrintF(
"disasm [<instructions>]\n");
581 PrintF(
"disasm [<address/register>]\n");
582 PrintF(
"disasm [[<address/register>] <instructions>]\n");
583 PrintF(
" disassemble code, default is 10 instructions\n");
584 PrintF(
" from pc (alias 'di')\n");
587 PrintF(
"break <address>\n");
588 PrintF(
" set a break point on the address\n");
590 PrintF(
" delete the breakpoint\n");
591 PrintF(
"trace (alias 't')\n");
592 PrintF(
" toogle the tracing of all executed statements\n");
593 PrintF(
"stop feature:\n");
594 PrintF(
" Description:\n");
595 PrintF(
" Stops are debug instructions inserted by\n");
596 PrintF(
" the Assembler::stop() function.\n");
597 PrintF(
" When hitting a stop, the Simulator will\n");
598 PrintF(
" stop and and give control to the ArmDebugger.\n");
599 PrintF(
" The first %d stop codes are watched:\n",
600 Simulator::kNumOfWatchedStops);
601 PrintF(
" - They can be enabled / disabled: the Simulator\n");
602 PrintF(
" will / won't stop when hitting them.\n");
603 PrintF(
" - The Simulator keeps track of how many times they \n");
604 PrintF(
" are met. (See the info command.) Going over a\n");
605 PrintF(
" disabled stop still increases its counter. \n");
607 PrintF(
" stop info all/<code> : print infos about number <code>\n");
608 PrintF(
" or all stop(s).\n");
609 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
610 PrintF(
" all or number <code> stop(s)\n");
612 PrintF(
" ignore the stop instruction at the current location\n");
615 PrintF(
"Unknown command: %s\n", cmd);
632 static bool ICacheMatch(
void* one,
void* two) {
633 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
634 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
639 static uint32_t ICacheHash(
void* key) {
640 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(key)) >> 2;
644 static bool AllOnOnePage(uintptr_t start,
int size) {
645 intptr_t start_page = (start & ~CachePage::kPageMask);
646 intptr_t end_page = ((start +
size) & ~CachePage::kPageMask);
647 return start_page == end_page;
651 void Simulator::set_last_debugger_input(
char* input) {
653 last_debugger_input_ = input;
660 intptr_t start =
reinterpret_cast<intptr_t
>(start_addr);
661 int intra_line = (start & CachePage::kLineMask);
664 size = ((size - 1) | CachePage::kLineMask) + 1;
665 int offset = (start & CachePage::kPageMask);
666 while (!AllOnOnePage(start, size - 1)) {
667 int bytes_to_flush = CachePage::kPageSize - offset;
668 FlushOnePage(i_cache, start, bytes_to_flush);
669 start += bytes_to_flush;
670 size -= bytes_to_flush;
671 ASSERT_EQ(0, start & CachePage::kPageMask);
675 FlushOnePage(i_cache, start, size);
681 v8::internal::HashMap::Entry* entry = i_cache->
Lookup(page,
684 if (entry->value ==
NULL) {
685 CachePage* new_page =
new CachePage();
686 entry->value = new_page;
688 return reinterpret_cast<CachePage*
>(entry->value);
696 ASSERT(size <= CachePage::kPageSize);
697 ASSERT(AllOnOnePage(start, size - 1));
698 ASSERT((start & CachePage::kLineMask) == 0);
699 ASSERT((size & CachePage::kLineMask) == 0);
700 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
701 int offset = (start & CachePage::kPageMask);
702 CachePage* cache_page = GetCachePage(i_cache, page);
703 char* valid_bytemap = cache_page->ValidityByte(offset);
704 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
709 Instruction* instr) {
710 intptr_t address =
reinterpret_cast<intptr_t
>(instr);
711 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
712 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
713 int offset = (address & CachePage::kPageMask);
714 CachePage* cache_page = GetCachePage(i_cache, page);
715 char* cache_valid_byte = cache_page->ValidityByte(offset);
716 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
717 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
720 CHECK(memcmp(reinterpret_cast<void*>(instr),
721 cache_page->CachedData(offset),
725 OS::MemCopy(cached_line, line, CachePage::kLineLength);
726 *cache_valid_byte = CachePage::LINE_VALID;
731 void Simulator::Initialize(Isolate* isolate) {
732 if (isolate->simulator_initialized())
return;
733 isolate->set_simulator_initialized(
true);
734 ::v8::internal::ExternalReference::set_redirector(isolate,
735 &RedirectExternalReference);
739 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
740 i_cache_ = isolate_->simulator_i_cache();
741 if (i_cache_ ==
NULL) {
743 isolate_->set_simulator_i_cache(i_cache_);
748 size_t stack_size = 1 * 1024*1024;
749 stack_ =
reinterpret_cast<char*
>(malloc(stack_size));
750 pc_modified_ =
false;
757 for (
int i = 0; i < num_registers; i++) {
769 for (
int i = 0; i < num_d_registers * 2; i++) {
770 vfp_registers_[i] = 0;
772 n_flag_FPSCR_ =
false;
773 z_flag_FPSCR_ =
false;
774 c_flag_FPSCR_ =
false;
775 v_flag_FPSCR_ =
false;
776 FPSCR_rounding_mode_ =
RZ;
777 FPSCR_default_NaN_mode_ =
true;
779 inv_op_vfp_flag_ =
false;
780 div_zero_vfp_flag_ =
false;
781 overflow_vfp_flag_ =
false;
782 underflow_vfp_flag_ =
false;
783 inexact_vfp_flag_ =
false;
788 registers_[
sp] =
reinterpret_cast<int32_t>(stack_) + stack_size - 64;
791 registers_[
pc] = bad_lr;
792 registers_[
lr] = bad_lr;
793 InitializeCoverage();
795 last_debugger_input_ =
NULL;
799 Simulator::~Simulator() {
813 : external_function_(external_function),
817 Isolate* isolate = Isolate::Current();
818 next_ = isolate->simulator_redirection();
819 Simulator::current(isolate)->
820 FlushICache(isolate->simulator_i_cache(),
821 reinterpret_cast<void*
>(&swi_instruction_),
823 isolate->set_simulator_redirection(
this);
826 void* address_of_swi_instruction() {
827 return reinterpret_cast<void*
>(&swi_instruction_);
830 void* external_function() {
return external_function_; }
833 static Redirection* Get(
void* external_function,
835 Isolate* isolate = Isolate::Current();
836 Redirection* current = isolate->simulator_redirection();
837 for (; current !=
NULL; current = current->next_) {
838 if (current->external_function_ == external_function) {
843 return new Redirection(external_function, type);
846 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
847 char* addr_of_swi =
reinterpret_cast<char*
>(swi_instruction);
848 char* addr_of_redirection =
849 addr_of_swi -
OFFSET_OF(Redirection, swi_instruction_);
850 return reinterpret_cast<Redirection*
>(addr_of_redirection);
853 static void* ReverseRedirection(
int32_t reg) {
854 Redirection* redirection = FromSwiInstruction(
855 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
856 return redirection->external_function();
860 void* external_function_;
861 uint32_t swi_instruction_;
867 void* Simulator::RedirectExternalReference(
void* external_function,
869 Redirection* redirection = Redirection::Get(external_function, type);
870 return redirection->address_of_swi_instruction();
875 Simulator* Simulator::current(Isolate* isolate) {
877 isolate->FindOrAllocatePerThreadDataForThisThread();
880 Simulator* sim = isolate_data->simulator();
883 sim =
new Simulator(isolate);
884 isolate_data->set_simulator(sim);
892 void Simulator::set_register(
int reg,
int32_t value) {
893 ASSERT((reg >= 0) && (reg < num_registers));
897 registers_[reg] = value;
903 int32_t Simulator::get_register(
int reg)
const {
904 ASSERT((reg >= 0) && (reg < num_registers));
907 if (reg >= num_registers)
return 0;
913 double Simulator::get_double_from_register_pair(
int reg) {
914 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
919 char buffer[2 *
sizeof(vfp_registers_[0])];
920 OS::MemCopy(buffer, ®isters_[reg], 2 *
sizeof(registers_[0]));
921 OS::MemCopy(&dm_val, buffer, 2 *
sizeof(registers_[0]));
926 void Simulator::set_register_pair_from_double(
int reg,
double* value) {
927 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
928 memcpy(registers_ + reg, value,
sizeof(*value));
932 void Simulator::set_dw_register(
int dreg,
const int* dbl) {
933 ASSERT((dreg >= 0) && (dreg < num_d_registers));
934 registers_[dreg] = dbl[0];
935 registers_[dreg + 1] = dbl[1];
939 void Simulator::get_d_register(
int dreg, uint64_t* value) {
941 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value));
945 void Simulator::set_d_register(
int dreg,
const uint64_t* value) {
947 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value));
951 void Simulator::get_d_register(
int dreg, uint32_t* value) {
953 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value) * 2);
957 void Simulator::set_d_register(
int dreg,
const uint32_t* value) {
959 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value) * 2);
963 void Simulator::get_q_register(
int qreg, uint64_t* value) {
964 ASSERT((qreg >= 0) && (qreg < num_q_registers));
965 memcpy(value, vfp_registers_ + qreg * 4,
sizeof(*value) * 2);
969 void Simulator::set_q_register(
int qreg,
const uint64_t* value) {
970 ASSERT((qreg >= 0) && (qreg < num_q_registers));
971 memcpy(vfp_registers_ + qreg * 4, value,
sizeof(*value) * 2);
975 void Simulator::get_q_register(
int qreg, uint32_t* value) {
976 ASSERT((qreg >= 0) && (qreg < num_q_registers));
977 memcpy(value, vfp_registers_ + qreg * 4,
sizeof(*value) * 4);
981 void Simulator::set_q_register(
int qreg,
const uint32_t* value) {
982 ASSERT((qreg >= 0) && (qreg < num_q_registers));
983 memcpy(vfp_registers_ + qreg * 4, value,
sizeof(*value) * 4);
988 void Simulator::set_pc(
int32_t value) {
990 registers_[
pc] = value;
994 bool Simulator::has_bad_pc()
const {
995 return ((registers_[
pc] == bad_lr) || (registers_[
pc] == end_sim_pc));
1000 int32_t Simulator::get_pc()
const {
1001 return registers_[
pc];
1006 void Simulator::set_s_register(
int sreg,
unsigned int value) {
1007 ASSERT((sreg >= 0) && (sreg < num_s_registers));
1008 vfp_registers_[sreg] = value;
1012 unsigned int Simulator::get_s_register(
int sreg)
const {
1013 ASSERT((sreg >= 0) && (sreg < num_s_registers));
1014 return vfp_registers_[sreg];
1018 template<
class InputType,
int register_size>
1019 void Simulator::SetVFPRegister(
int reg_index,
const InputType& value) {
1021 if (register_size == 1)
ASSERT(reg_index < num_s_registers);
1024 char buffer[register_size *
sizeof(vfp_registers_[0])];
1025 OS::MemCopy(buffer, &value, register_size *
sizeof(vfp_registers_[0]));
1026 OS::MemCopy(&vfp_registers_[reg_index * register_size], buffer,
1027 register_size *
sizeof(vfp_registers_[0]));
1031 template<
class ReturnType,
int register_size>
1032 ReturnType Simulator::GetFromVFPRegister(
int reg_index) {
1034 if (register_size == 1)
ASSERT(reg_index < num_s_registers);
1037 ReturnType value = 0;
1038 char buffer[register_size *
sizeof(vfp_registers_[0])];
1039 OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index],
1040 register_size *
sizeof(vfp_registers_[0]));
1041 OS::MemCopy(&value, buffer, register_size *
sizeof(vfp_registers_[0]));
1050 void Simulator::GetFpArgs(
double* x,
double* y,
int32_t* z) {
1051 if (use_eabi_hardfloat()) {
1052 *x = get_double_from_d_register(0);
1053 *y = get_double_from_d_register(1);
1054 *z = get_register(0);
1057 *x = get_double_from_register_pair(0);
1059 *y = get_double_from_register_pair(2);
1061 *z = get_register(2);
1067 void Simulator::SetFpResult(
const double& result) {
1068 if (use_eabi_hardfloat()) {
1069 char buffer[2 *
sizeof(vfp_registers_[0])];
1072 OS::MemCopy(vfp_registers_, buffer,
sizeof(buffer));
1074 char buffer[2 *
sizeof(registers_[0])];
1082 void Simulator::TrashCallerSaveRegisters() {
1084 registers_[2] = 0x50Bad4
U;
1085 registers_[3] = 0x50Bad4
U;
1086 registers_[12] = 0x50Bad4
U;
1104 int Simulator::ReadW(
int32_t addr, Instruction* instr) {
1105 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1106 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1111 reinterpret_cast<intptr_t>(instr));
1118 void Simulator::WriteW(
int32_t addr,
int value, Instruction* instr) {
1119 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1120 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1125 reinterpret_cast<intptr_t>(instr));
1132 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1136 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1139 reinterpret_cast<intptr_t>(instr));
1147 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1151 PrintF(
"Unaligned signed halfword read at 0x%08x\n", addr);
1158 void Simulator::WriteH(
int32_t addr,
uint16_t value, Instruction* instr) {
1159 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1163 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1166 reinterpret_cast<intptr_t>(instr));
1172 void Simulator::WriteH(
int32_t addr,
int16_t value, Instruction* instr) {
1173 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1179 reinterpret_cast<intptr_t>(instr));
1185 uint8_t Simulator::ReadBU(
int32_t addr) {
1186 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1191 int8_t Simulator::ReadB(
int32_t addr) {
1192 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1197 void Simulator::WriteB(
int32_t addr, uint8_t value) {
1198 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1203 void Simulator::WriteB(
int32_t addr, int8_t value) {
1204 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1210 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1214 PrintF(
"Unaligned read at 0x%08x\n", addr);
1222 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1227 PrintF(
"Unaligned write at 0x%08x\n", addr);
1234 uintptr_t Simulator::StackLimit()
const {
1237 return reinterpret_cast<uintptr_t
>(stack_) + 1024;
1242 void Simulator::Format(Instruction* instr,
const char* format) {
1243 PrintF(
"Simulator found unsupported instruction:\n 0x%08x: %s\n",
1244 reinterpret_cast<intptr_t>(instr), format);
1251 bool Simulator::ConditionallyExecute(Instruction* instr) {
1252 switch (instr->ConditionField()) {
1253 case eq:
return z_flag_;
1254 case ne:
return !z_flag_;
1255 case cs:
return c_flag_;
1256 case cc:
return !c_flag_;
1257 case mi:
return n_flag_;
1258 case pl:
return !n_flag_;
1259 case vs:
return v_flag_;
1260 case vc:
return !v_flag_;
1261 case hi:
return c_flag_ && !z_flag_;
1262 case ls:
return !c_flag_ || z_flag_;
1263 case ge:
return n_flag_ == v_flag_;
1264 case lt:
return n_flag_ != v_flag_;
1265 case gt:
return !z_flag_ && (n_flag_ == v_flag_);
1266 case le:
return z_flag_ || (n_flag_ != v_flag_);
1267 case al:
return true;
1275 void Simulator::SetNZFlags(
int32_t val) {
1276 n_flag_ = (val < 0);
1277 z_flag_ = (val == 0);
1282 void Simulator::SetCFlag(
bool val) {
1288 void Simulator::SetVFlag(
bool val) {
1295 uint32_t uleft =
static_cast<uint32_t
>(left);
1296 uint32_t uright =
static_cast<uint32_t
>(right);
1297 uint32_t urest = 0xffffffff
U - uleft;
1299 return (uright > urest) ||
1300 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1306 uint32_t uleft =
static_cast<uint32_t
>(left);
1307 uint32_t uright =
static_cast<uint32_t
>(right);
1309 return (uright > uleft);
1314 bool Simulator::OverflowFrom(
int32_t alu_out,
1319 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1321 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1324 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1326 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1333 void Simulator::Compute_FPSCR_Flags(
double val1,
double val2) {
1335 n_flag_FPSCR_ =
false;
1336 z_flag_FPSCR_ =
false;
1337 c_flag_FPSCR_ =
true;
1338 v_flag_FPSCR_ =
true;
1340 }
else if (val1 == val2) {
1341 n_flag_FPSCR_ =
false;
1342 z_flag_FPSCR_ =
true;
1343 c_flag_FPSCR_ =
true;
1344 v_flag_FPSCR_ =
false;
1345 }
else if (val1 < val2) {
1346 n_flag_FPSCR_ =
true;
1347 z_flag_FPSCR_ =
false;
1348 c_flag_FPSCR_ =
false;
1349 v_flag_FPSCR_ =
false;
1352 n_flag_FPSCR_ =
false;
1353 z_flag_FPSCR_ =
false;
1354 c_flag_FPSCR_ =
true;
1355 v_flag_FPSCR_ =
false;
1360 void Simulator::Copy_FPSCR_to_APSR() {
1361 n_flag_ = n_flag_FPSCR_;
1362 z_flag_ = z_flag_FPSCR_;
1363 c_flag_ = c_flag_FPSCR_;
1364 v_flag_ = v_flag_FPSCR_;
1370 int32_t Simulator::GetShiftRm(Instruction* instr,
bool* carry_out) {
1372 int shift_amount = instr->ShiftAmountValue();
1373 int32_t result = get_register(instr->RmValue());
1374 if (instr->Bit(4) == 0) {
1376 if ((shift ==
ROR) && (shift_amount == 0)) {
1379 }
else if (((shift ==
LSR) || (shift ==
ASR)) && (shift_amount == 0)) {
1384 if (shift_amount == 0) {
1386 result = 0xffffffff;
1393 result >>= (shift_amount - 1);
1394 *carry_out = (result & 1) == 1;
1401 if (shift_amount == 0) {
1402 *carry_out = c_flag_;
1404 result <<= (shift_amount - 1);
1405 *carry_out = (result < 0);
1412 if (shift_amount == 0) {
1414 *carry_out = c_flag_;
1416 uint32_t uresult =
static_cast<uint32_t
>(result);
1417 uresult >>= (shift_amount - 1);
1418 *carry_out = (uresult & 1) == 1;
1420 result =
static_cast<int32_t>(uresult);
1426 if (shift_amount == 0) {
1427 *carry_out = c_flag_;
1429 uint32_t left =
static_cast<uint32_t
>(result) >> shift_amount;
1430 uint32_t right =
static_cast<uint32_t
>(result) << (32 - shift_amount);
1431 result = right | left;
1432 *carry_out = (
static_cast<uint32_t
>(result) >> 31) != 0;
1444 int rs = instr->RsValue();
1445 shift_amount = get_register(rs) &0xff;
1448 if (shift_amount == 0) {
1449 *carry_out = c_flag_;
1450 }
else if (shift_amount < 32) {
1451 result >>= (shift_amount - 1);
1452 *carry_out = (result & 1) == 1;
1455 ASSERT(shift_amount >= 32);
1458 result = 0xffffffff;
1468 if (shift_amount == 0) {
1469 *carry_out = c_flag_;
1470 }
else if (shift_amount < 32) {
1471 result <<= (shift_amount - 1);
1472 *carry_out = (result < 0);
1474 }
else if (shift_amount == 32) {
1475 *carry_out = (result & 1) == 1;
1478 ASSERT(shift_amount > 32);
1486 if (shift_amount == 0) {
1487 *carry_out = c_flag_;
1488 }
else if (shift_amount < 32) {
1489 uint32_t uresult =
static_cast<uint32_t
>(result);
1490 uresult >>= (shift_amount - 1);
1491 *carry_out = (uresult & 1) == 1;
1493 result =
static_cast<int32_t>(uresult);
1494 }
else if (shift_amount == 32) {
1495 *carry_out = (result < 0);
1505 if (shift_amount == 0) {
1506 *carry_out = c_flag_;
1508 uint32_t left =
static_cast<uint32_t
>(result) >> shift_amount;
1509 uint32_t right =
static_cast<uint32_t
>(result) << (32 - shift_amount);
1510 result = right | left;
1511 *carry_out = (
static_cast<uint32_t
>(result) >> 31) != 0;
1528 int32_t Simulator::GetImm(Instruction* instr,
bool* carry_out) {
1529 int rotate = instr->RotateValue() * 2;
1530 int immed8 = instr->Immed8Value();
1531 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1532 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1537 static int count_bits(
int bit_vector) {
1539 while (bit_vector != 0) {
1540 if ((bit_vector & 1) != 0) {
1549 int32_t Simulator::ProcessPU(Instruction* instr,
1552 intptr_t* start_address,
1553 intptr_t* end_address) {
1554 int rn = instr->RnValue();
1555 int32_t rn_val = get_register(rn);
1556 switch (instr->PUField()) {
1562 *start_address = rn_val;
1563 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1564 rn_val = rn_val + (num_regs * reg_size);
1568 *start_address = rn_val - (num_regs * reg_size);
1569 *end_address = rn_val - reg_size;
1570 rn_val = *start_address;
1574 *start_address = rn_val + reg_size;
1575 *end_address = rn_val + (num_regs * reg_size);
1576 rn_val = *end_address;
1589 void Simulator::HandleRList(Instruction* instr,
bool load) {
1590 int rlist = instr->RlistValue();
1591 int num_regs = count_bits(rlist);
1593 intptr_t start_address = 0;
1594 intptr_t end_address = 0;
1596 ProcessPU(instr, num_regs,
kPointerSize, &start_address, &end_address);
1598 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1600 ASSERT(start_address > 8191 || start_address < 0);
1602 while (rlist != 0) {
1603 if ((rlist & 1) != 0) {
1605 set_register(reg, *address);
1607 *address = get_register(reg);
1614 ASSERT(end_address == ((intptr_t)address) - 4);
1615 if (instr->HasW()) {
1616 set_register(instr->RnValue(), rn_val);
1622 void Simulator::HandleVList(Instruction* instr) {
1627 bool load = (instr->VLValue() == 0x1);
1631 vd = instr->VFPDRegValue(precision);
1633 num_regs = instr->Immed8Value();
1635 num_regs = instr->Immed8Value() / 2;
1638 intptr_t start_address = 0;
1639 intptr_t end_address = 0;
1641 ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1643 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1644 for (
int reg = vd; reg < vd + num_regs; reg++) {
1647 set_s_register_from_sinteger(
1648 reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1650 WriteW(reinterpret_cast<int32_t>(address),
1651 get_sinteger_from_s_register(reg), instr);
1657 ReadW(reinterpret_cast<int32_t>(address), instr),
1658 ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1662 set_d_register_from_double(reg, d);
1665 double d = get_double_from_d_register(reg);
1667 WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1668 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1673 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1674 if (instr->HasW()) {
1675 set_register(instr->RnValue(), rn_val);
1686 typedef int64_t (*SimulatorRuntimeCall)(
int32_t arg0,
1694 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
1695 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
1696 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
1697 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0,
int32_t arg0);
1701 typedef void (*SimulatorRuntimeDirectApiCall)(
int32_t arg0);
1702 typedef void (*SimulatorRuntimeProfilingApiCall)(
int32_t arg0,
void* arg1);
1705 typedef void (*SimulatorRuntimeDirectGetterCall)(
int32_t arg0,
int32_t arg1);
1706 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1711 void Simulator::SoftwareInterrupt(Instruction* instr) {
1712 int svc = instr->SvcValue();
1717 bool stack_aligned =
1719 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1720 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1726 int32_t arg4 = stack_pointer[0];
1727 int32_t arg5 = stack_pointer[1];
1729 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1730 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1731 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1732 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1737 reinterpret_cast<intptr_t
>(redirection->external_function());
1739 double dval0, dval1;
1741 int64_t iresult = 0;
1743 GetFpArgs(&dval0, &dval1, &ival);
1744 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1745 SimulatorRuntimeCall generic_target =
1746 reinterpret_cast<SimulatorRuntimeCall
>(external);
1747 switch (redirection->type()) {
1748 case ExternalReference::BUILTIN_FP_FP_CALL:
1749 case ExternalReference::BUILTIN_COMPARE_CALL:
1750 PrintF(
"Call to host function at %p with args %f, %f",
1753 case ExternalReference::BUILTIN_FP_CALL:
1754 PrintF(
"Call to host function at %p with arg %f",
1757 case ExternalReference::BUILTIN_FP_INT_CALL:
1758 PrintF(
"Call to host function at %p with args %f, %d",
1765 if (!stack_aligned) {
1766 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1770 CHECK(stack_aligned);
1771 switch (redirection->type()) {
1772 case ExternalReference::BUILTIN_COMPARE_CALL: {
1773 SimulatorRuntimeCompareCall target =
1774 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
1775 iresult = target(dval0, dval1);
1776 set_register(
r0, static_cast<int32_t>(iresult));
1777 set_register(
r1, static_cast<int32_t>(iresult >> 32));
1780 case ExternalReference::BUILTIN_FP_FP_CALL: {
1781 SimulatorRuntimeFPFPCall target =
1782 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
1783 dresult = target(dval0, dval1);
1784 SetFpResult(dresult);
1787 case ExternalReference::BUILTIN_FP_CALL: {
1788 SimulatorRuntimeFPCall target =
1789 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1790 dresult = target(dval0);
1791 SetFpResult(dresult);
1794 case ExternalReference::BUILTIN_FP_INT_CALL: {
1795 SimulatorRuntimeFPIntCall target =
1796 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
1797 dresult = target(dval0, ival);
1798 SetFpResult(dresult);
1805 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1806 switch (redirection->type()) {
1807 case ExternalReference::BUILTIN_COMPARE_CALL:
1808 PrintF(
"Returned %08x\n", static_cast<int32_t>(iresult));
1810 case ExternalReference::BUILTIN_FP_FP_CALL:
1811 case ExternalReference::BUILTIN_FP_CALL:
1812 case ExternalReference::BUILTIN_FP_INT_CALL:
1813 PrintF(
"Returned %f\n", dresult);
1820 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1821 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1822 PrintF(
"Call to host function at %p args %08x",
1823 reinterpret_cast<void*>(external), arg0);
1824 if (!stack_aligned) {
1825 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1829 CHECK(stack_aligned);
1830 SimulatorRuntimeDirectApiCall target =
1831 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1834 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1835 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1836 PrintF(
"Call to host function at %p args %08x %08x",
1837 reinterpret_cast<void*>(external), arg0, arg1);
1838 if (!stack_aligned) {
1839 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1843 CHECK(stack_aligned);
1844 SimulatorRuntimeProfilingApiCall target =
1845 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
1846 target(arg0, Redirection::ReverseRedirection(arg1));
1848 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1849 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1850 PrintF(
"Call to host function at %p args %08x %08x",
1851 reinterpret_cast<void*>(external), arg0, arg1);
1852 if (!stack_aligned) {
1853 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1857 CHECK(stack_aligned);
1858 SimulatorRuntimeDirectGetterCall target =
1859 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1862 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1863 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1864 PrintF(
"Call to host function at %p args %08x %08x %08x",
1865 reinterpret_cast<void*>(external), arg0, arg1, arg2);
1866 if (!stack_aligned) {
1867 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1871 CHECK(stack_aligned);
1872 SimulatorRuntimeProfilingGetterCall target =
1873 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(
1875 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1878 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1879 SimulatorRuntimeCall target =
1880 reinterpret_cast<SimulatorRuntimeCall
>(external);
1881 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1883 "Call to host function at %p "
1884 "args %08x, %08x, %08x, %08x, %08x, %08x",
1892 if (!stack_aligned) {
1893 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1897 CHECK(stack_aligned);
1898 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1901 if (::v8::internal::FLAG_trace_sim) {
1902 PrintF(
"Returned %08x\n", lo_res);
1904 set_register(
r0, lo_res);
1905 set_register(
r1, hi_res);
1907 set_register(
lr, saved_lr);
1908 set_pc(get_register(
lr));
1912 ArmDebugger dbg(
this);
1918 if (svc >= (1 << 23)) {
1920 if (isWatchedStop(code)) {
1921 IncreaseStopCounter(code);
1925 if (isEnabledStop(code)) {
1926 ArmDebugger dbg(
this);
1941 double Simulator::canonicalizeNaN(
double value) {
1942 return (FPSCR_default_NaN_mode_ &&
std::isnan(value)) ?
1948 bool Simulator::isStopInstruction(Instruction* instr) {
1949 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >=
kStopCode);
1953 bool Simulator::isWatchedStop(uint32_t code) {
1955 return code < kNumOfWatchedStops;
1959 bool Simulator::isEnabledStop(uint32_t code) {
1962 return !isWatchedStop(code) ||
1963 !(watched_stops_[
code].count & kStopDisabledBit);
1967 void Simulator::EnableStop(uint32_t code) {
1968 ASSERT(isWatchedStop(code));
1969 if (!isEnabledStop(code)) {
1970 watched_stops_[
code].count &= ~kStopDisabledBit;
1975 void Simulator::DisableStop(uint32_t code) {
1976 ASSERT(isWatchedStop(code));
1977 if (isEnabledStop(code)) {
1978 watched_stops_[
code].count |= kStopDisabledBit;
1983 void Simulator::IncreaseStopCounter(uint32_t code) {
1985 ASSERT(isWatchedStop(code));
1986 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1987 PrintF(
"Stop counter for code %i has overflowed.\n"
1988 "Enabling this code and reseting the counter to 0.\n", code);
1989 watched_stops_[
code].count = 0;
1992 watched_stops_[
code].count++;
1998 void Simulator::PrintStopInfo(uint32_t code) {
2000 if (!isWatchedStop(code)) {
2001 PrintF(
"Stop not watched.");
2003 const char* state = isEnabledStop(code) ?
"Enabled" :
"Disabled";
2004 int32_t count = watched_stops_[
code].count & ~kStopDisabledBit;
2007 if (watched_stops_[code].desc) {
2008 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
2009 code, code, state, count, watched_stops_[code].desc);
2011 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
2012 code, code, state, count);
2023 void Simulator::DecodeType01(Instruction* instr) {
2024 int type = instr->TypeValue();
2025 if ((type == 0) && instr->IsSpecialType0()) {
2027 if (instr->Bits(7, 4) == 9) {
2028 if (instr->Bit(24) == 0) {
2031 int rn = instr->RnValue();
2032 int rm = instr->RmValue();
2033 int rs = instr->RsValue();
2034 int32_t rs_val = get_register(rs);
2035 int32_t rm_val = get_register(rm);
2036 if (instr->Bit(23) == 0) {
2037 if (instr->Bit(21) == 0) {
2043 int32_t alu_out = rm_val * rs_val;
2044 set_register(rd, alu_out);
2045 if (instr->HasS()) {
2046 SetNZFlags(alu_out);
2049 int rd = instr->RdValue();
2050 int32_t acc_value = get_register(rd);
2051 if (instr->Bit(22) == 0) {
2057 int32_t mul_out = rm_val * rs_val;
2058 int32_t result = acc_value + mul_out;
2059 set_register(rn, result);
2062 int32_t mul_out = rm_val * rs_val;
2063 int32_t result = acc_value - mul_out;
2064 set_register(rn, result);
2079 int rd_lo = instr->RdValue();
2082 if (instr->Bit(22) == 1) {
2083 int64_t left_op =
static_cast<int32_t>(rm_val);
2084 int64_t right_op =
static_cast<int32_t>(rs_val);
2085 uint64_t result = left_op * right_op;
2086 hi_res =
static_cast<int32_t>(result >> 32);
2087 lo_res =
static_cast<int32_t>(result & 0xffffffff);
2090 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
2091 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
2092 uint64_t result = left_op * right_op;
2093 hi_res =
static_cast<int32_t>(result >> 32);
2094 lo_res =
static_cast<int32_t>(result & 0xffffffff);
2096 set_register(rd_lo, lo_res);
2097 set_register(rd_hi, hi_res);
2098 if (instr->HasS()) {
2107 int rd = instr->RdValue();
2108 int rn = instr->RnValue();
2109 int32_t rn_val = get_register(rn);
2111 if (instr->Bit(22) == 0) {
2112 int rm = instr->RmValue();
2113 int32_t rm_val = get_register(rm);
2114 switch (instr->PUField()) {
2120 set_register(rn, rn_val);
2128 set_register(rn, rn_val);
2135 if (instr->HasW()) {
2136 set_register(rn, rn_val);
2144 if (instr->HasW()) {
2145 set_register(rn, rn_val);
2156 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2157 switch (instr->PUField()) {
2163 set_register(rn, rn_val);
2171 set_register(rn, rn_val);
2178 if (instr->HasW()) {
2179 set_register(rn, rn_val);
2187 if (instr->HasW()) {
2188 set_register(rn, rn_val);
2199 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2201 if (instr->HasH()) {
2203 int32_t value1 = get_register(rd);
2204 int32_t value2 = get_register(rd+1);
2205 WriteDW(addr, value1, value2);
2208 int* rn_data = ReadDW(addr);
2209 set_dw_register(rd, rn_data);
2211 }
else if (instr->HasH()) {
2212 if (instr->HasSign()) {
2213 if (instr->HasL()) {
2214 int16_t val = ReadH(addr, instr);
2215 set_register(rd, val);
2217 int16_t val = get_register(rd);
2218 WriteH(addr, val, instr);
2221 if (instr->HasL()) {
2222 uint16_t val = ReadHU(addr, instr);
2223 set_register(rd, val);
2226 WriteH(addr, val, instr);
2231 ASSERT(instr->HasSign());
2233 int8_t val = ReadB(addr);
2234 set_register(rd, val);
2238 }
else if ((type == 0) && instr->IsMiscType0()) {
2239 if (instr->Bits(22, 21) == 1) {
2240 int rm = instr->RmValue();
2241 switch (instr->BitField(7, 4)) {
2243 set_pc(get_register(rm));
2246 uint32_t old_pc = get_pc();
2247 set_pc(get_register(rm));
2252 ArmDebugger dbg(
this);
2253 PrintF(
"Simulator hit BKPT.\n");
2260 }
else if (instr->Bits(22, 21) == 3) {
2261 int rm = instr->RmValue();
2262 int rd = instr->RdValue();
2263 switch (instr->BitField(7, 4)) {
2265 uint32_t bits = get_register(rm);
2266 int leading_zeros = 0;
2270 while ((bits & 0x80000000u) == 0) {
2275 set_register(rd, leading_zeros);
2282 PrintF(
"%08x\n", instr->InstructionBits());
2285 }
else if ((type == 1) && instr->IsNopType1()) {
2288 int rd = instr->RdValue();
2289 int rn = instr->RnValue();
2290 int32_t rn_val = get_register(rn);
2292 bool shifter_carry_out = 0;
2294 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2296 ASSERT(instr->TypeValue() == 1);
2297 shifter_operand = GetImm(instr, &shifter_carry_out);
2301 switch (instr->OpcodeField()) {
2305 alu_out = rn_val & shifter_operand;
2306 set_register(rd, alu_out);
2307 if (instr->HasS()) {
2308 SetNZFlags(alu_out);
2309 SetCFlag(shifter_carry_out);
2317 alu_out = rn_val ^ shifter_operand;
2318 set_register(rd, alu_out);
2319 if (instr->HasS()) {
2320 SetNZFlags(alu_out);
2321 SetCFlag(shifter_carry_out);
2329 alu_out = rn_val - shifter_operand;
2330 set_register(rd, alu_out);
2331 if (instr->HasS()) {
2332 SetNZFlags(alu_out);
2333 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2334 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2342 alu_out = shifter_operand - rn_val;
2343 set_register(rd, alu_out);
2344 if (instr->HasS()) {
2345 SetNZFlags(alu_out);
2346 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2347 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val,
false));
2355 alu_out = rn_val + shifter_operand;
2356 set_register(rd, alu_out);
2357 if (instr->HasS()) {
2358 SetNZFlags(alu_out);
2359 SetCFlag(CarryFrom(rn_val, shifter_operand));
2360 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2368 alu_out = rn_val + shifter_operand + GetCarry();
2369 set_register(rd, alu_out);
2370 if (instr->HasS()) {
2371 SetNZFlags(alu_out);
2372 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2373 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2379 Format(instr,
"sbc'cond's 'rd, 'rn, 'shift_rm");
2380 Format(instr,
"sbc'cond's 'rd, 'rn, 'imm");
2385 Format(instr,
"rsc'cond's 'rd, 'rn, 'shift_rm");
2386 Format(instr,
"rsc'cond's 'rd, 'rn, 'imm");
2391 if (instr->HasS()) {
2394 alu_out = rn_val & shifter_operand;
2395 SetNZFlags(alu_out);
2396 SetCFlag(shifter_carry_out);
2399 alu_out = instr->ImmedMovwMovtValue();
2400 set_register(rd, alu_out);
2406 if (instr->HasS()) {
2409 alu_out = rn_val ^ shifter_operand;
2410 SetNZFlags(alu_out);
2411 SetCFlag(shifter_carry_out);
2421 if (instr->HasS()) {
2424 alu_out = rn_val - shifter_operand;
2425 SetNZFlags(alu_out);
2426 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2427 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2430 alu_out = (get_register(rd) & 0xffff) |
2431 (instr->ImmedMovwMovtValue() << 16);
2432 set_register(rd, alu_out);
2438 if (instr->HasS()) {
2441 alu_out = rn_val + shifter_operand;
2442 SetNZFlags(alu_out);
2443 SetCFlag(CarryFrom(rn_val, shifter_operand));
2444 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2456 alu_out = rn_val | shifter_operand;
2457 set_register(rd, alu_out);
2458 if (instr->HasS()) {
2459 SetNZFlags(alu_out);
2460 SetCFlag(shifter_carry_out);
2468 alu_out = shifter_operand;
2469 set_register(rd, alu_out);
2470 if (instr->HasS()) {
2471 SetNZFlags(alu_out);
2472 SetCFlag(shifter_carry_out);
2480 alu_out = rn_val & ~shifter_operand;
2481 set_register(rd, alu_out);
2482 if (instr->HasS()) {
2483 SetNZFlags(alu_out);
2484 SetCFlag(shifter_carry_out);
2492 alu_out = ~shifter_operand;
2493 set_register(rd, alu_out);
2494 if (instr->HasS()) {
2495 SetNZFlags(alu_out);
2496 SetCFlag(shifter_carry_out);
2510 void Simulator::DecodeType2(Instruction* instr) {
2511 int rd = instr->RdValue();
2512 int rn = instr->RnValue();
2513 int32_t rn_val = get_register(rn);
2514 int32_t im_val = instr->Offset12Value();
2516 switch (instr->PUField()) {
2522 set_register(rn, rn_val);
2530 set_register(rn, rn_val);
2537 if (instr->HasW()) {
2538 set_register(rn, rn_val);
2546 if (instr->HasW()) {
2547 set_register(rn, rn_val);
2556 if (instr->HasB()) {
2557 if (instr->HasL()) {
2558 byte val = ReadBU(addr);
2559 set_register(rd, val);
2561 byte val = get_register(rd);
2565 if (instr->HasL()) {
2566 set_register(rd, ReadW(addr, instr));
2568 WriteW(addr, get_register(rd), instr);
2574 void Simulator::DecodeType3(Instruction* instr) {
2575 int rd = instr->RdValue();
2576 int rn = instr->RnValue();
2577 int32_t rn_val = get_register(rn);
2578 bool shifter_carry_out = 0;
2579 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2581 switch (instr->PUField()) {
2584 Format(instr,
"'memop'cond'b 'rd, ['rn], -'shift_rm");
2589 if (instr->Bit(4) == 0) {
2592 if (instr->Bit(5) == 0) {
2593 switch (instr->Bits(22, 21)) {
2595 if (instr->Bit(20) == 0) {
2596 if (instr->Bit(6) == 0) {
2598 uint32_t rn_val = get_register(rn);
2599 uint32_t rm_val = get_register(instr->RmValue());
2600 int32_t shift = instr->Bits(11, 7);
2602 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2605 uint32_t rn_val = get_register(rn);
2606 int32_t rm_val = get_register(instr->RmValue());
2607 int32_t shift = instr->Bits(11, 7);
2612 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2626 int32_t sat_pos = instr->Bits(20, 16);
2627 int32_t sat_val = (1 << sat_pos) - 1;
2628 int32_t shift = instr->Bits(11, 7);
2629 int32_t shift_type = instr->Bit(6);
2630 int32_t rm_val = get_register(instr->RmValue());
2631 if (shift_type == 0) {
2639 if (rm_val > sat_val) {
2641 }
else if (rm_val < 0) {
2644 set_register(rd, rm_val);
2649 switch (instr->Bits(22, 21)) {
2657 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2658 if (instr->Bits(19, 16) == 0xF) {
2660 uint32_t rm_val = get_register(instr->RmValue());
2661 int32_t rotate = instr->Bits(11, 10);
2666 rm_val = (rm_val >> 8) | (rm_val << 24);
2669 rm_val = (rm_val >> 16) | (rm_val << 16);
2672 rm_val = (rm_val >> 24) | (rm_val << 8);
2676 (rm_val & 0xFF) | (rm_val & 0xFF0000));
2685 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2686 if (instr->Bits(19, 16) == 0xF) {
2688 uint32_t rm_val = get_register(instr->RmValue());
2689 int32_t rotate = instr->Bits(11, 10);
2694 rm_val = (rm_val >> 8) | (rm_val << 24);
2697 rm_val = (rm_val >> 16) | (rm_val << 16);
2700 rm_val = (rm_val >> 24) | (rm_val << 8);
2703 set_register(rd, (rm_val & 0xFF));
2706 uint32_t rn_val = get_register(rn);
2707 uint32_t rm_val = get_register(instr->RmValue());
2708 int32_t rotate = instr->Bits(11, 10);
2713 rm_val = (rm_val >> 8) | (rm_val << 24);
2716 rm_val = (rm_val >> 16) | (rm_val << 16);
2719 rm_val = (rm_val >> 24) | (rm_val << 8);
2722 set_register(rd, rn_val + (rm_val & 0xFF));
2735 if (FLAG_enable_sudiv) {
2736 if (!instr->HasW()) {
2737 if (instr->Bits(5, 4) == 0x1) {
2738 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2741 int rm = instr->RmValue();
2742 int32_t rm_val = get_register(rm);
2743 int rs = instr->RsValue();
2744 int32_t rs_val = get_register(rs);
2747 if ((rm_val ==
kMinInt) && (rs_val == -1)) {
2750 ret_val = rm_val / rs_val;
2752 set_register(rn, ret_val);
2759 addr = rn_val - shifter_operand;
2760 if (instr->HasW()) {
2761 set_register(rn, addr);
2766 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2767 uint32_t widthminus1 =
static_cast<uint32_t
>(instr->Bits(20, 16));
2768 uint32_t lsbit =
static_cast<uint32_t
>(instr->Bits(11, 7));
2769 uint32_t msbit = widthminus1 + lsbit;
2771 if (instr->Bit(22)) {
2774 static_cast<uint32_t
>(get_register(instr->RmValue()));
2775 uint32_t extr_val = rm_val << (31 - msbit);
2776 extr_val = extr_val >> (31 - widthminus1);
2777 set_register(instr->RdValue(), extr_val);
2780 int32_t rm_val = get_register(instr->RmValue());
2781 int32_t extr_val = rm_val << (31 - msbit);
2782 extr_val = extr_val >> (31 - widthminus1);
2783 set_register(instr->RdValue(), extr_val);
2789 }
else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2790 uint32_t lsbit =
static_cast<uint32_t
>(instr->Bits(11, 7));
2791 uint32_t msbit =
static_cast<uint32_t
>(instr->Bits(20, 16));
2792 if (msbit >= lsbit) {
2795 static_cast<uint32_t
>(get_register(instr->RdValue()));
2796 uint32_t bitcount = msbit - lsbit + 1;
2797 uint32_t mask = (1 << bitcount) - 1;
2798 rd_val &= ~(mask << lsbit);
2799 if (instr->RmValue() != 15) {
2802 static_cast<uint32_t
>(get_register(instr->RmValue()));
2804 rd_val |= rm_val << lsbit;
2806 set_register(instr->RdValue(), rd_val);
2813 addr = rn_val + shifter_operand;
2814 if (instr->HasW()) {
2815 set_register(rn, addr);
2825 if (instr->HasB()) {
2826 if (instr->HasL()) {
2827 uint8_t
byte = ReadB(addr);
2828 set_register(rd, byte);
2830 uint8_t
byte = get_register(rd);
2834 if (instr->HasL()) {
2835 set_register(rd, ReadW(addr, instr));
2837 WriteW(addr, get_register(rd), instr);
2843 void Simulator::DecodeType4(Instruction* instr) {
2844 ASSERT(instr->Bit(22) == 0);
2845 if (instr->HasL()) {
2847 HandleRList(instr,
true);
2850 HandleRList(instr,
false);
2855 void Simulator::DecodeType5(Instruction* instr) {
2857 int off = (instr->SImmed24Value() << 2);
2858 intptr_t pc_address = get_pc();
2859 if (instr->HasLink()) {
2862 int pc_reg = get_register(
pc);
2863 set_pc(pc_reg + off);
2867 void Simulator::DecodeType6(Instruction* instr) {
2868 DecodeType6CoprocessorIns(instr);
2872 void Simulator::DecodeType7(Instruction* instr) {
2873 if (instr->Bit(24) == 1) {
2874 SoftwareInterrupt(instr);
2876 DecodeTypeVFP(instr);
2897 void Simulator::DecodeTypeVFP(Instruction* instr) {
2898 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2899 ASSERT(instr->Bits(11, 9) == 0x5);
2906 if (instr->Bit(4) == 0) {
2907 if (instr->Opc1Value() == 0x7) {
2909 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2911 if (instr->SzValue() == 0x1) {
2914 set_d_register_from_double(d, get_double_from_d_register(m));
2918 set_s_register_from_float(d, get_float_from_s_register(m));
2920 }
else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2922 double dm_value = get_double_from_d_register(vm);
2923 double dd_value = std::fabs(dm_value);
2924 dd_value = canonicalizeNaN(dd_value);
2925 set_d_register_from_double(vd, dd_value);
2926 }
else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2928 double dm_value = get_double_from_d_register(vm);
2929 double dd_value = -dm_value;
2930 dd_value = canonicalizeNaN(dd_value);
2931 set_d_register_from_double(vd, dd_value);
2932 }
else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2933 DecodeVCVTBetweenDoubleAndSingle(instr);
2934 }
else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2935 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2936 }
else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
2937 (instr->Bit(8) == 1)) {
2939 int fraction_bits = 32 - ((instr->Bit(5) << 4) | instr->Bits(3, 0));
2940 int fixed_value = get_sinteger_from_s_register(vd * 2);
2941 double divide = 1 << fraction_bits;
2942 set_d_register_from_double(vd, fixed_value / divide);
2943 }
else if (((instr->Opc2Value() >> 1) == 0x6) &&
2944 (instr->Opc3Value() & 0x1)) {
2945 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2946 }
else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2947 (instr->Opc3Value() & 0x1)) {
2949 }
else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2951 double dm_value = get_double_from_d_register(vm);
2952 double dd_value = std::sqrt(dm_value);
2953 dd_value = canonicalizeNaN(dd_value);
2954 set_d_register_from_double(vd, dd_value);
2955 }
else if (instr->Opc3Value() == 0x0) {
2957 if (instr->SzValue() == 0x1) {
2958 set_d_register_from_double(vd, instr->DoubleImmedVmov());
2965 }
else if (instr->Opc1Value() == 0x3) {
2966 if (instr->SzValue() != 0x1) {
2970 if (instr->Opc3Value() & 0x1) {
2972 double dn_value = get_double_from_d_register(vn);
2973 double dm_value = get_double_from_d_register(vm);
2974 double dd_value = dn_value - dm_value;
2975 dd_value = canonicalizeNaN(dd_value);
2976 set_d_register_from_double(vd, dd_value);
2979 double dn_value = get_double_from_d_register(vn);
2980 double dm_value = get_double_from_d_register(vm);
2981 double dd_value = dn_value + dm_value;
2982 dd_value = canonicalizeNaN(dd_value);
2983 set_d_register_from_double(vd, dd_value);
2985 }
else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2987 if (instr->SzValue() != 0x1) {
2991 double dn_value = get_double_from_d_register(vn);
2992 double dm_value = get_double_from_d_register(vm);
2993 double dd_value = dn_value * dm_value;
2994 dd_value = canonicalizeNaN(dd_value);
2995 set_d_register_from_double(vd, dd_value);
2996 }
else if ((instr->Opc1Value() == 0x0)) {
2998 const bool is_vmls = (instr->Opc3Value() & 0x1);
3000 if (instr->SzValue() != 0x1) {
3004 const double dd_val = get_double_from_d_register(vd);
3005 const double dn_val = get_double_from_d_register(vn);
3006 const double dm_val = get_double_from_d_register(vm);
3010 set_d_register_from_double(vd, dn_val * dm_val);
3012 set_d_register_from_double(
3014 canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3016 set_d_register_from_double(
3018 canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3020 }
else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3022 if (instr->SzValue() != 0x1) {
3026 double dn_value = get_double_from_d_register(vn);
3027 double dm_value = get_double_from_d_register(vm);
3028 double dd_value = dn_value / dm_value;
3029 div_zero_vfp_flag_ = (dm_value == 0);
3030 dd_value = canonicalizeNaN(dd_value);
3031 set_d_register_from_double(vd, dd_value);
3036 if ((instr->VCValue() == 0x0) &&
3037 (instr->VAValue() == 0x0)) {
3038 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3039 }
else if ((instr->VLValue() == 0x0) &&
3040 (instr->VCValue() == 0x1) &&
3041 (instr->Bit(23) == 0x0)) {
3043 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3044 double dd_value = get_double_from_d_register(vd);
3047 data[instr->Bit(21)] = get_register(instr->RtValue());
3049 set_d_register_from_double(vd, dd_value);
3050 }
else if ((instr->VLValue() == 0x1) &&
3051 (instr->VCValue() == 0x1) &&
3052 (instr->Bit(23) == 0x0)) {
3054 int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3055 double dn_value = get_double_from_d_register(vn);
3058 set_register(instr->RtValue(), data[instr->Bit(21)]);
3059 }
else if ((instr->VLValue() == 0x1) &&
3060 (instr->VCValue() == 0x0) &&
3061 (instr->VAValue() == 0x7) &&
3062 (instr->Bits(19, 16) == 0x1)) {
3064 uint32_t rt = instr->RtValue();
3066 Copy_FPSCR_to_APSR();
3069 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3070 (z_flag_FPSCR_ << 30) |
3071 (c_flag_FPSCR_ << 29) |
3072 (v_flag_FPSCR_ << 28) |
3073 (FPSCR_default_NaN_mode_ << 25) |
3074 (inexact_vfp_flag_ << 4) |
3075 (underflow_vfp_flag_ << 3) |
3076 (overflow_vfp_flag_ << 2) |
3077 (div_zero_vfp_flag_ << 1) |
3078 (inv_op_vfp_flag_ << 0) |
3079 (FPSCR_rounding_mode_);
3080 set_register(rt, fpscr);
3082 }
else if ((instr->VLValue() == 0x0) &&
3083 (instr->VCValue() == 0x0) &&
3084 (instr->VAValue() == 0x7) &&
3085 (instr->Bits(19, 16) == 0x1)) {
3087 uint32_t rt = instr->RtValue();
3091 uint32_t rt_value = get_register(rt);
3092 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3093 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3094 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3095 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3096 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3097 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3098 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3099 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3100 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3101 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3102 FPSCR_rounding_mode_ =
3112 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3113 Instruction* instr) {
3114 ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3115 (instr->VAValue() == 0x0));
3117 int t = instr->RtValue();
3119 bool to_arm_register = (instr->VLValue() == 0x1);
3121 if (to_arm_register) {
3122 int32_t int_value = get_sinteger_from_s_register(n);
3123 set_register(t, int_value);
3125 int32_t rs_val = get_register(t);
3126 set_s_register_from_sinteger(n, rs_val);
3131 void Simulator::DecodeVCMP(Instruction* instr) {
3132 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3133 ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3134 (instr->Opc3Value() & 0x1));
3138 if (instr->SzValue() == 1) {
3142 int d = instr->VFPDRegValue(precision);
3144 if (instr->Opc2Value() == 0x4) {
3145 m = instr->VFPMRegValue(precision);
3149 double dd_value = get_double_from_d_register(d);
3150 double dm_value = 0.0;
3151 if (instr->Opc2Value() == 0x4) {
3152 dm_value = get_double_from_d_register(m);
3156 if (instr->Bit(7) == 1) {
3158 inv_op_vfp_flag_ =
true;
3162 Compute_FPSCR_Flags(dd_value, dm_value);
3169 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3170 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3171 ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3175 if (instr->SzValue() == 1) {
3180 int dst = instr->VFPDRegValue(dst_precision);
3181 int src = instr->VFPMRegValue(src_precision);
3184 double val = get_double_from_d_register(src);
3185 set_s_register_from_float(dst, static_cast<float>(val));
3187 float val = get_float_from_s_register(src);
3188 set_d_register_from_double(dst, static_cast<double>(val));
3196 double max_uint =
static_cast<double>(0xffffffffu);
3197 double max_int =
static_cast<double>(
kMaxInt);
3198 double min_int =
static_cast<double>(
kMinInt);
3209 return unsigned_ ? (val >= (max_uint + 0.5)) ||
3211 : (val >= (max_int + 0.5)) ||
3212 (val < (min_int - 0.5));
3215 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3217 : (val >= (max_int + 1.0)) ||
3221 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3223 : (val >= (max_int + 1.0)) ||
3224 (val <= (min_int - 1.0));
3234 int VFPConversionSaturate(
double val,
bool unsigned_res) {
3239 return (val < 0) ? 0 : 0xffffffffu;
3247 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3248 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3249 (instr->Bits(27, 23) == 0x1D));
3250 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3251 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3254 bool to_integer = (instr->Bit(18) == 1);
3268 int src = instr->VFPMRegValue(src_precision);
3276 bool unsigned_integer = (instr->Bit(16) == 0);
3279 double val = double_precision ? get_double_from_d_register(src)
3280 : get_float_from_s_register(src);
3282 int temp = unsigned_integer ?
static_cast<uint32_t
>(val)
3283 : static_cast<int32_t>(val);
3285 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3288 unsigned_integer ? std::fabs(val - static_cast<uint32_t>(temp))
3289 : std::fabs(val - temp);
3291 inexact_vfp_flag_ = (abs_diff != 0);
3293 if (inv_op_vfp_flag_) {
3294 temp = VFPConversionSaturate(val, unsigned_integer);
3298 int val_sign = (val > 0) ? 1 : -1;
3299 if (abs_diff > 0.5) {
3301 }
else if (abs_diff == 0.5) {
3303 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3309 temp = temp > val ? temp - 1 : temp;
3322 set_s_register_from_sinteger(dst, temp);
3325 bool unsigned_integer = (instr->Bit(7) == 0);
3327 int dst = instr->VFPDRegValue(src_precision);
3330 int val = get_sinteger_from_s_register(src);
3333 if (unsigned_integer) {
3334 set_d_register_from_double(
3335 dst, static_cast<double>(static_cast<uint32_t>(val)));
3337 set_d_register_from_double(dst, static_cast<double>(val));
3340 if (unsigned_integer) {
3341 set_s_register_from_float(
3342 dst, static_cast<float>(static_cast<uint32_t>(val)));
3344 set_s_register_from_float(dst, static_cast<float>(val));
3357 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3358 ASSERT((instr->TypeValue() == 6));
3360 if (instr->CoprocessorValue() == 0xA) {
3361 switch (instr->OpcodeValue()) {
3366 int rn = instr->RnValue();
3368 int offset = instr->Immed8Value();
3369 if (!instr->HasU()) {
3373 int32_t address = get_register(rn) + 4 * offset;
3374 if (instr->HasL()) {
3376 set_s_register_from_sinteger(vd, ReadW(address, instr));
3379 WriteW(address, get_sinteger_from_s_register(vd), instr);
3395 }
else if (instr->CoprocessorValue() == 0xB) {
3396 switch (instr->OpcodeValue()) {
3399 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3402 int rt = instr->RtValue();
3403 int rn = instr->RnValue();
3405 if (instr->HasL()) {
3407 double d = get_double_from_d_register(vm);
3409 set_register(rt, data[0]);
3410 set_register(rn, data[1]);
3412 int32_t data[] = { get_register(rt), get_register(rn) };
3415 set_d_register_from_double(vm, d);
3423 int rn = instr->RnValue();
3425 int offset = instr->Immed8Value();
3426 if (!instr->HasU()) {
3429 int32_t address = get_register(rn) + 4 * offset;
3430 if (instr->HasL()) {
3433 ReadW(address, instr),
3434 ReadW(address + 4, instr)
3438 set_d_register_from_double(vd, val);
3442 double val = get_double_from_d_register(vd);
3444 WriteW(address, data[0], instr);
3445 WriteW(address + 4, data[1], instr);
3467 void Simulator::DecodeSpecialCondition(Instruction* instr) {
3468 switch (instr->SpecialValue()) {
3470 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3471 (instr->Bit(4) == 1)) {
3474 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3475 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3476 int imm3 = instr->Bits(21, 19);
3477 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4))
UNIMPLEMENTED();
3478 int esize = 8 * imm3;
3479 int elements = 64 / esize;
3481 get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3484 while (e < elements) {
3488 set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3494 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3495 (instr->Bit(4) == 1)) {
3498 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3499 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3500 int imm3 = instr->Bits(21, 19);
3501 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4))
UNIMPLEMENTED();
3502 int esize = 8 * imm3;
3503 int elements = 64 / esize;
3505 get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3508 while (e < elements) {
3512 set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3518 if (instr->Bits(21, 20) == 0) {
3520 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3521 int Rn = instr->VnValue();
3522 int type = instr->Bits(11, 8);
3523 int Rm = instr->VmValue();
3524 int32_t address = get_register(Rn);
3546 get_d_register(Vd + r, data);
3547 WriteW(address, data[0], instr);
3548 WriteW(address + 4, data[1], instr);
3554 set_register(Rn, address);
3556 set_register(Rn, get_register(Rn) + get_register(Rm));
3559 }
else if (instr->Bits(21, 20) == 2) {
3561 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3562 int Rn = instr->VnValue();
3563 int type = instr->Bits(11, 8);
3564 int Rm = instr->VmValue();
3565 int32_t address = get_register(Rn);
3587 data[0] = ReadW(address, instr);
3588 data[1] = ReadW(address + 4, instr);
3589 set_d_register(Vd + r, data);
3595 set_register(Rn, address);
3597 set_register(Rn, get_register(Rn) + get_register(Rm));
3606 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
3620 void Simulator::InstructionDecode(Instruction* instr) {
3621 if (v8::internal::FLAG_check_icache) {
3622 CheckICache(isolate_->simulator_i_cache(), instr);
3624 pc_modified_ =
false;
3625 if (::v8::internal::FLAG_trace_sim) {
3630 dasm.InstructionDecode(buffer,
3631 reinterpret_cast<byte*>(instr));
3632 PrintF(
" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.
start());
3635 DecodeSpecialCondition(instr);
3636 }
else if (ConditionallyExecute(instr)) {
3637 switch (instr->TypeValue()) {
3640 DecodeType01(instr);
3674 }
else if (instr->IsStop()) {
3677 if (!pc_modified_) {
3678 set_register(
pc, reinterpret_cast<int32_t>(instr)
3684 void Simulator::Execute() {
3687 int program_counter = get_pc();
3689 if (::v8::internal::FLAG_stop_sim_at == 0) {
3692 while (program_counter != end_sim_pc) {
3693 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3695 InstructionDecode(instr);
3696 program_counter = get_pc();
3701 while (program_counter != end_sim_pc) {
3702 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3704 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3705 ArmDebugger dbg(
this);
3708 InstructionDecode(instr);
3710 program_counter = get_pc();
3716 void Simulator::CallInternal(
byte* entry) {
3718 set_register(
pc, reinterpret_cast<int32_t>(entry));
3722 set_register(
lr, end_sim_pc);
3738 int32_t callee_saved_value = icount_;
3739 set_register(
r4, callee_saved_value);
3740 set_register(
r5, callee_saved_value);
3741 set_register(
r6, callee_saved_value);
3742 set_register(
r7, callee_saved_value);
3743 set_register(
r8, callee_saved_value);
3744 set_register(
r9, callee_saved_value);
3745 set_register(
r10, callee_saved_value);
3746 set_register(
r11, callee_saved_value);
3752 CHECK_EQ(callee_saved_value, get_register(
r4));
3753 CHECK_EQ(callee_saved_value, get_register(
r5));
3754 CHECK_EQ(callee_saved_value, get_register(
r6));
3755 CHECK_EQ(callee_saved_value, get_register(
r7));
3756 CHECK_EQ(callee_saved_value, get_register(
r8));
3757 CHECK_EQ(callee_saved_value, get_register(
r9));
3762 set_register(
r4, r4_val);
3763 set_register(
r5, r5_val);
3764 set_register(
r6, r6_val);
3765 set_register(
r7, r7_val);
3766 set_register(
r8, r8_val);
3767 set_register(
r9, r9_val);
3768 set_register(
r10, r10_val);
3769 set_register(
r11, r11_val);
3773 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
3775 va_start(parameters, argument_count);
3779 ASSERT(argument_count >= 4);
3780 set_register(
r0, va_arg(parameters,
int32_t));
3781 set_register(
r1, va_arg(parameters,
int32_t));
3782 set_register(
r2, va_arg(parameters,
int32_t));
3783 set_register(
r3, va_arg(parameters,
int32_t));
3786 int original_stack = get_register(
sp);
3788 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t));
3793 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
3794 for (
int i = 4; i < argument_count; i++) {
3795 stack_argument[i - 4] = va_arg(parameters,
int32_t);
3798 set_register(
sp, entry_stack);
3800 CallInternal(entry);
3804 set_register(
sp, original_stack);
3811 void Simulator::CallFP(
byte* entry,
double d0,
double d1) {
3812 if (use_eabi_hardfloat()) {
3813 set_d_register_from_double(0, d0);
3814 set_d_register_from_double(1, d1);
3816 set_register_pair_from_double(0, &d0);
3817 set_register_pair_from_double(2, &d1);
3819 CallInternal(entry);
3823 int32_t Simulator::CallFPReturnsInt(
byte* entry,
double d0,
double d1) {
3824 CallFP(entry, d0, d1);
3830 double Simulator::CallFPReturnsDouble(
byte* entry,
double d0,
double d1) {
3831 CallFP(entry, d0, d1);
3832 if (use_eabi_hardfloat()) {
3833 return get_double_from_d_register(0);
3835 return get_double_from_register_pair(0);
3840 uintptr_t Simulator::PushAddress(uintptr_t address) {
3841 int new_sp = get_register(
sp) -
sizeof(uintptr_t);
3842 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
3843 *stack_slot = address;
3844 set_register(
sp, new_sp);
3849 uintptr_t Simulator::PopAddress() {
3850 int current_sp = get_register(
sp);
3851 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
3852 uintptr_t address = *stack_slot;
3853 set_register(
sp, current_sp +
sizeof(uintptr_t));
3859 #endif // USE_SIMULATOR
3861 #endif // V8_TARGET_ARCH_ARM
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
#define CHECK_EQ(expected, value)
void PrintF(const char *format,...)
const LowDwVfpRegister d0
kSerializedDataOffset Object
static const char * Name(int reg, bool is_double)
TypeImpl< ZoneTypeConfig > Type
static int Number(const char *name, bool *is_double)
const uint32_t kMaxStopCode
#define ASSERT(condition)
const uint32_t kStopCodeMask
char * ReadLine(const char *prompt)
static const char * Name(int reg)
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 emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
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
static int Number(const char *name)
#define OFFSET_OF(type, field)
static void MemCopy(void *dest, const void *src, size_t size)
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 shift
static int NumRegisters()
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())
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
#define ASSERT_EQ(v1, v2)
static double canonical_not_the_hole_nan_as_double()
static int ActivationFrameAlignment()
const uint32_t kVFPRoundingModeMask
const LowDwVfpRegister d1
void DeleteArray(T *array)