11 #if V8_TARGET_ARCH_ARM
19 #if defined(USE_SIMULATOR)
35 explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
38 void Stop(Instruction* instr);
42 static const Instr kBreakpointInstr =
44 static const Instr kNopInstr = (
al | (13*
B21));
48 int32_t GetRegisterValue(
int regnum);
49 double GetRegisterPairDoubleValue(
int regnum);
50 double GetVFPDoubleRegisterValue(
int regnum);
51 bool GetValue(
const char* desc,
int32_t* value);
52 bool GetVFPSingleValue(
const char* desc,
float* value);
53 bool GetVFPDoubleValue(
const char* desc,
double* value);
56 bool SetBreakpoint(Instruction* breakpc);
57 bool DeleteBreakpoint(Instruction* breakpc);
61 void UndoBreakpoints();
62 void RedoBreakpoints();
66 ArmDebugger::~ArmDebugger() {
71 #ifdef GENERATED_CODE_COVERAGE
72 static FILE* coverage_log =
NULL;
75 static void InitializeCoverage() {
76 char* file_name = getenv(
"V8_GENERATED_CODE_COVERAGE_LOG");
77 if (file_name !=
NULL) {
78 coverage_log = fopen(file_name,
"aw+");
83 void ArmDebugger::Stop(Instruction* instr) {
89 char* msg = *msg_address;
93 if (isWatchedStop(code) && !watched_stops_[code].desc) {
94 watched_stops_[code].desc = msg;
97 if (strlen(msg) > 0) {
98 if (coverage_log !=
NULL) {
99 fprintf(coverage_log,
"%s\n", msg);
100 fflush(coverage_log);
103 instr->SetInstructionBits(kNopInstr);
104 reinterpret_cast<Instruction*
>(msg_address)->SetInstructionBits(kNopInstr);
111 static void InitializeCoverage() {
115 void ArmDebugger::Stop(Instruction* instr) {
119 char* msg = *
reinterpret_cast<char**
>(sim_->get_pc()
122 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
123 sim_->watched_stops_[code].desc = msg;
127 PrintF(
"Simulator hit stop %u: %s\n", code, msg);
129 PrintF(
"Simulator hit %s\n", msg);
137 int32_t ArmDebugger::GetRegisterValue(
int regnum) {
139 return sim_->get_pc();
141 return sim_->get_register(regnum);
146 double ArmDebugger::GetRegisterPairDoubleValue(
int regnum) {
147 return sim_->get_double_from_register_pair(regnum);
151 double ArmDebugger::GetVFPDoubleRegisterValue(
int regnum) {
152 return sim_->get_double_from_d_register(regnum);
156 bool ArmDebugger::GetValue(
const char* desc,
int32_t* value) {
159 *value = GetRegisterValue(regnum);
162 if (strncmp(desc,
"0x", 2) == 0) {
163 return SScanF(desc + 2,
"%x",
reinterpret_cast<uint32_t*
>(value)) == 1;
165 return SScanF(desc,
"%u",
reinterpret_cast<uint32_t*
>(value)) == 1;
172 bool ArmDebugger::GetVFPSingleValue(
const char* desc,
float* value) {
176 *value = sim_->get_float_from_s_register(regnum);
183 bool ArmDebugger::GetVFPDoubleValue(
const char* desc,
double* value) {
187 *value = sim_->get_double_from_d_register(regnum);
194 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
196 if (sim_->break_pc_ !=
NULL) {
201 sim_->break_pc_ = breakpc;
202 sim_->break_instr_ = breakpc->InstructionBits();
209 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
210 if (sim_->break_pc_ !=
NULL) {
211 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
214 sim_->break_pc_ =
NULL;
215 sim_->break_instr_ = 0;
220 void ArmDebugger::UndoBreakpoints() {
221 if (sim_->break_pc_ !=
NULL) {
222 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
227 void ArmDebugger::RedoBreakpoints() {
228 if (sim_->break_pc_ !=
NULL) {
229 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
234 void ArmDebugger::Debug() {
235 intptr_t last_pc = -1;
238 #define COMMAND_SIZE 63
242 #define XSTR(a) STR(a)
244 char cmd[COMMAND_SIZE + 1];
245 char arg1[ARG_SIZE + 1];
246 char arg2[ARG_SIZE + 1];
247 char* argv[3] = { cmd, arg1, arg2 };
250 cmd[COMMAND_SIZE] = 0;
258 while (!done && !sim_->has_bad_pc()) {
259 if (last_pc != sim_->get_pc()) {
264 dasm.InstructionDecode(buffer,
265 reinterpret_cast<byte*
>(sim_->get_pc()));
266 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.
start());
267 last_pc = sim_->get_pc();
273 char* last_input = sim_->last_debugger_input();
274 if (strcmp(line,
"\n") == 0 && last_input !=
NULL) {
278 sim_->set_last_debugger_input(line);
282 int argc = SScanF(line,
283 "%" XSTR(COMMAND_SIZE)
"s "
284 "%" XSTR(ARG_SIZE)
"s "
285 "%" XSTR(ARG_SIZE)
"s",
287 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
288 sim_->InstructionDecode(
reinterpret_cast<Instruction*
>(sim_->get_pc()));
289 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
291 sim_->InstructionDecode(
reinterpret_cast<Instruction*
>(sim_->get_pc()));
294 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
295 if (argc == 2 || (argc == 3 && strcmp(arg2,
"fp") == 0)) {
299 if (strcmp(arg1,
"all") == 0) {
301 value = GetRegisterValue(
i);
303 if ((argc == 3 && strcmp(arg2,
"fp") == 0) &&
306 dvalue = GetRegisterPairDoubleValue(
i);
307 PrintF(
" (%f)\n", dvalue);
313 dvalue = GetVFPDoubleRegisterValue(
i);
314 uint64_t as_words = bit_cast<uint64_t>(dvalue);
315 PrintF(
"%3s: %f 0x%08x %08x\n",
318 static_cast<uint32_t>(as_words >> 32),
319 static_cast<uint32_t>(as_words & 0xffffffff));
322 if (GetValue(arg1, &value)) {
323 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
324 }
else if (GetVFPSingleValue(arg1, &svalue)) {
325 uint32_t as_word = bit_cast<uint32_t>(svalue);
326 PrintF(
"%s: %f 0x%08x\n", arg1, svalue, as_word);
327 }
else if (GetVFPDoubleValue(arg1, &dvalue)) {
328 uint64_t as_words = bit_cast<uint64_t>(dvalue);
329 PrintF(
"%s: %f 0x%08x %08x\n",
332 static_cast<uint32_t>(as_words >> 32),
333 static_cast<uint32_t>(as_words & 0xffffffff));
335 PrintF(
"%s unrecognized\n", arg1);
339 PrintF(
"print <register>\n");
341 }
else if ((strcmp(cmd,
"po") == 0)
342 || (strcmp(cmd,
"printobject") == 0)) {
346 if (GetValue(arg1, &value)) {
348 os << arg1 <<
": \n";
353 os << Brief(obj) <<
"\n";
356 os << arg1 <<
" unrecognized\n";
359 PrintF(
"printobject <value>\n");
361 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
366 if (strcmp(cmd,
"stack") == 0) {
370 if (!GetValue(arg1, &value)) {
371 PrintF(
"%s unrecognized\n", arg1);
374 cur =
reinterpret_cast<int32_t*
>(value);
379 if (argc == next_arg) {
382 if (!GetValue(argv[next_arg], &words)) {
389 PrintF(
" 0x%08x: 0x%08x %10d",
390 reinterpret_cast<intptr_t
>(cur), *cur, *cur);
391 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
393 Heap* current_heap = v8::internal::Isolate::Current()->heap();
394 if (((value & 1) == 0) || current_heap->Contains(obj)) {
396 if ((value & 1) == 0) {
397 PrintF(
"smi %d", value / 2);
406 }
else if (strcmp(cmd,
"disasm") == 0 || strcmp(cmd,
"di") == 0) {
417 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
419 }
else if (argc == 2) {
421 if (regnum !=
kNoRegister || strncmp(arg1,
"0x", 2) == 0) {
424 if (GetValue(arg1, &value)) {
425 cur =
reinterpret_cast<byte*
>(value);
432 if (GetValue(arg1, &value)) {
433 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
441 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
442 cur =
reinterpret_cast<byte*
>(value1);
449 cur += dasm.InstructionDecode(buffer, cur);
451 reinterpret_cast<intptr_t
>(prev), buffer.
start());
453 }
else if (strcmp(cmd,
"gdb") == 0) {
454 PrintF(
"relinquishing control to gdb\n");
456 PrintF(
"regaining control from gdb\n");
457 }
else if (strcmp(cmd,
"break") == 0) {
460 if (GetValue(arg1, &value)) {
461 if (!SetBreakpoint(
reinterpret_cast<Instruction*
>(value))) {
462 PrintF(
"setting breakpoint failed\n");
465 PrintF(
"%s unrecognized\n", arg1);
468 PrintF(
"break <address>\n");
470 }
else if (strcmp(cmd,
"del") == 0) {
471 if (!DeleteBreakpoint(
NULL)) {
472 PrintF(
"deleting breakpoint failed\n");
474 }
else if (strcmp(cmd,
"flags") == 0) {
475 PrintF(
"N flag: %d; ", sim_->n_flag_);
476 PrintF(
"Z flag: %d; ", sim_->z_flag_);
477 PrintF(
"C flag: %d; ", sim_->c_flag_);
478 PrintF(
"V flag: %d\n", sim_->v_flag_);
479 PrintF(
"INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
480 PrintF(
"DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
481 PrintF(
"OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
482 PrintF(
"UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
483 PrintF(
"INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
484 }
else if (strcmp(cmd,
"stop") == 0) {
487 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
488 Instruction* msg_address =
490 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
492 if (sim_->isStopInstruction(stop_instr)) {
493 stop_instr->SetInstructionBits(kNopInstr);
494 msg_address->SetInstructionBits(kNopInstr);
496 PrintF(
"Not at debugger stop.\n");
498 }
else if (argc == 3) {
500 if (strcmp(arg1,
"info") == 0) {
501 if (strcmp(arg2,
"all") == 0) {
502 PrintF(
"Stop information:\n");
503 for (
uint32_t i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
504 sim_->PrintStopInfo(
i);
506 }
else if (GetValue(arg2, &value)) {
507 sim_->PrintStopInfo(value);
509 PrintF(
"Unrecognized argument.\n");
511 }
else if (strcmp(arg1,
"enable") == 0) {
513 if (strcmp(arg2,
"all") == 0) {
514 for (
uint32_t i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
517 }
else if (GetValue(arg2, &value)) {
518 sim_->EnableStop(value);
520 PrintF(
"Unrecognized argument.\n");
522 }
else if (strcmp(arg1,
"disable") == 0) {
524 if (strcmp(arg2,
"all") == 0) {
525 for (
uint32_t i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
526 sim_->DisableStop(
i);
528 }
else if (GetValue(arg2, &value)) {
529 sim_->DisableStop(value);
531 PrintF(
"Unrecognized argument.\n");
535 PrintF(
"Wrong usage. Use help command for more information.\n");
537 }
else if ((strcmp(cmd,
"t") == 0) || strcmp(cmd,
"trace") == 0) {
538 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
539 PrintF(
"Trace of executed instructions is %s\n",
540 ::v8::internal::FLAG_trace_sim ?
"on" :
"off");
541 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
543 PrintF(
" continue execution (alias 'c')\n");
545 PrintF(
" step one instruction (alias 'si')\n");
546 PrintF(
"print <register>\n");
547 PrintF(
" print register content (alias 'p')\n");
548 PrintF(
" use register name 'all' to print all registers\n");
549 PrintF(
" add argument 'fp' to print register pair double values\n");
550 PrintF(
"printobject <register>\n");
551 PrintF(
" print an object from a register (alias 'po')\n");
554 PrintF(
"stack [<words>]\n");
555 PrintF(
" dump stack content, default dump 10 words)\n");
556 PrintF(
"mem <address> [<words>]\n");
557 PrintF(
" dump memory content, default dump 10 words)\n");
558 PrintF(
"disasm [<instructions>]\n");
559 PrintF(
"disasm [<address/register>]\n");
560 PrintF(
"disasm [[<address/register>] <instructions>]\n");
561 PrintF(
" disassemble code, default is 10 instructions\n");
562 PrintF(
" from pc (alias 'di')\n");
565 PrintF(
"break <address>\n");
566 PrintF(
" set a break point on the address\n");
568 PrintF(
" delete the breakpoint\n");
569 PrintF(
"trace (alias 't')\n");
570 PrintF(
" toogle the tracing of all executed statements\n");
571 PrintF(
"stop feature:\n");
572 PrintF(
" Description:\n");
573 PrintF(
" Stops are debug instructions inserted by\n");
574 PrintF(
" the Assembler::stop() function.\n");
575 PrintF(
" When hitting a stop, the Simulator will\n");
576 PrintF(
" stop and and give control to the ArmDebugger.\n");
577 PrintF(
" The first %d stop codes are watched:\n",
578 Simulator::kNumOfWatchedStops);
579 PrintF(
" - They can be enabled / disabled: the Simulator\n");
580 PrintF(
" will / won't stop when hitting them.\n");
581 PrintF(
" - The Simulator keeps track of how many times they \n");
582 PrintF(
" are met. (See the info command.) Going over a\n");
583 PrintF(
" disabled stop still increases its counter. \n");
585 PrintF(
" stop info all/<code> : print infos about number <code>\n");
586 PrintF(
" or all stop(s).\n");
587 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
588 PrintF(
" all or number <code> stop(s)\n");
590 PrintF(
" ignore the stop instruction at the current location\n");
593 PrintF(
"Unknown command: %s\n", cmd);
610 static bool ICacheMatch(
void* one,
void* two) {
611 DCHECK((
reinterpret_cast<intptr_t
>(one) & CachePage::kPageMask) == 0);
612 DCHECK((
reinterpret_cast<intptr_t
>(two) & CachePage::kPageMask) == 0);
617 static uint32_t ICacheHash(
void* key) {
623 intptr_t start_page = (start & ~CachePage::kPageMask);
624 intptr_t end_page = ((start +
size) & ~CachePage::kPageMask);
625 return start_page == end_page;
629 void Simulator::set_last_debugger_input(
char* input) {
631 last_debugger_input_ = input;
638 intptr_t start =
reinterpret_cast<intptr_t
>(start_addr);
639 int intra_line = (start & CachePage::kLineMask);
642 size = ((
size - 1) | CachePage::kLineMask) + 1;
643 int offset = (start & CachePage::kPageMask);
644 while (!AllOnOnePage(start,
size - 1)) {
645 int bytes_to_flush = CachePage::kPageSize - offset;
646 FlushOnePage(i_cache, start, bytes_to_flush);
647 start += bytes_to_flush;
648 size -= bytes_to_flush;
649 DCHECK_EQ(0, start & CachePage::kPageMask);
653 FlushOnePage(i_cache, start,
size);
659 v8::internal::HashMap::Entry* entry = i_cache->
Lookup(page,
662 if (entry->value ==
NULL) {
663 CachePage* new_page =
new CachePage();
664 entry->value = new_page;
666 return reinterpret_cast<CachePage*
>(entry->value);
676 DCHECK((start & CachePage::kLineMask) == 0);
678 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
679 int offset = (start & CachePage::kPageMask);
680 CachePage* cache_page = GetCachePage(i_cache, page);
681 char* valid_bytemap = cache_page->ValidityByte(offset);
682 memset(valid_bytemap, CachePage::LINE_INVALID,
size >> CachePage::kLineShift);
687 Instruction* instr) {
688 intptr_t address =
reinterpret_cast<intptr_t
>(instr);
689 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
690 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
691 int offset = (address & CachePage::kPageMask);
692 CachePage* cache_page = GetCachePage(i_cache, page);
693 char* cache_valid_byte = cache_page->ValidityByte(offset);
694 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
695 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
699 memcmp(
reinterpret_cast<void*
>(instr),
703 memcpy(cached_line, line, CachePage::kLineLength);
704 *cache_valid_byte = CachePage::LINE_VALID;
709 void Simulator::Initialize(Isolate* isolate) {
710 if (isolate->simulator_initialized())
return;
711 isolate->set_simulator_initialized(
true);
712 ::v8::internal::ExternalReference::set_redirector(isolate,
713 &RedirectExternalReference);
717 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
718 i_cache_ = isolate_->simulator_i_cache();
719 if (i_cache_ ==
NULL) {
721 isolate_->set_simulator_i_cache(i_cache_);
726 size_t stack_size = 1 * 1024*1024;
727 stack_ =
reinterpret_cast<char*
>(malloc(stack_size));
728 pc_modified_ =
false;
735 for (
int i = 0;
i < num_registers;
i++) {
747 for (
int i = 0;
i < num_d_registers * 2;
i++) {
748 vfp_registers_[
i] = 0;
750 n_flag_FPSCR_ =
false;
751 z_flag_FPSCR_ =
false;
752 c_flag_FPSCR_ =
false;
753 v_flag_FPSCR_ =
false;
754 FPSCR_rounding_mode_ =
RN;
755 FPSCR_default_NaN_mode_ =
false;
757 inv_op_vfp_flag_ =
false;
758 div_zero_vfp_flag_ =
false;
759 overflow_vfp_flag_ =
false;
760 underflow_vfp_flag_ =
false;
761 inexact_vfp_flag_ =
false;
766 registers_[
sp] =
reinterpret_cast<int32_t>(stack_) + stack_size - 64;
769 registers_[
pc] = bad_lr;
770 registers_[
lr] = bad_lr;
771 InitializeCoverage();
773 last_debugger_input_ =
NULL;
777 Simulator::~Simulator() {
791 : external_function_(external_function),
795 Isolate* isolate = Isolate::Current();
796 next_ = isolate->simulator_redirection();
797 Simulator::current(isolate)->
798 FlushICache(isolate->simulator_i_cache(),
799 reinterpret_cast<void*
>(&swi_instruction_),
800 Instruction::kInstrSize);
801 isolate->set_simulator_redirection(
this);
804 void* address_of_swi_instruction() {
805 return reinterpret_cast<void*
>(&swi_instruction_);
808 void* external_function() {
return external_function_; }
811 static Redirection* Get(
void* external_function,
813 Isolate* isolate = Isolate::Current();
814 Redirection* current = isolate->simulator_redirection();
815 for (; current !=
NULL; current = current->next_) {
816 if (current->external_function_ == external_function) {
821 return new Redirection(external_function, type);
824 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
825 char* addr_of_swi =
reinterpret_cast<char*
>(swi_instruction);
826 char* addr_of_redirection =
827 addr_of_swi -
OFFSET_OF(Redirection, swi_instruction_);
828 return reinterpret_cast<Redirection*
>(addr_of_redirection);
831 static void* ReverseRedirection(
int32_t reg) {
832 Redirection* redirection = FromSwiInstruction(
833 reinterpret_cast<Instruction*
>(
reinterpret_cast<void*
>(reg)));
834 return redirection->external_function();
838 void* external_function_;
845 void* Simulator::RedirectExternalReference(
void* external_function,
847 Redirection* redirection = Redirection::Get(external_function, type);
848 return redirection->address_of_swi_instruction();
853 Simulator* Simulator::current(Isolate* isolate) {
855 isolate->FindOrAllocatePerThreadDataForThisThread();
858 Simulator* sim = isolate_data->simulator();
861 sim =
new Simulator(isolate);
862 isolate_data->set_simulator(sim);
870 void Simulator::set_register(
int reg,
int32_t value) {
871 DCHECK((reg >= 0) && (reg < num_registers));
875 registers_[reg] = value;
881 int32_t Simulator::get_register(
int reg)
const {
882 DCHECK((reg >= 0) && (reg < num_registers));
885 if (reg >= num_registers)
return 0;
887 return registers_[reg] + ((reg ==
pc) ? Instruction::kPCReadOffset : 0);
891 double Simulator::get_double_from_register_pair(
int reg) {
892 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
897 char buffer[2 *
sizeof(vfp_registers_[0])];
898 memcpy(buffer, ®isters_[reg], 2 *
sizeof(registers_[0]));
899 memcpy(&dm_val, buffer, 2 *
sizeof(registers_[0]));
904 void Simulator::set_register_pair_from_double(
int reg,
double* value) {
905 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
906 memcpy(registers_ + reg, value,
sizeof(*value));
910 void Simulator::set_dw_register(
int dreg,
const int* dbl) {
911 DCHECK((dreg >= 0) && (dreg < num_d_registers));
912 registers_[dreg] = dbl[0];
913 registers_[dreg + 1] = dbl[1];
917 void Simulator::get_d_register(
int dreg, uint64_t* value) {
918 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
919 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value));
923 void Simulator::set_d_register(
int dreg,
const uint64_t* value) {
924 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
925 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value));
929 void Simulator::get_d_register(
int dreg,
uint32_t* value) {
930 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
931 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value) * 2);
935 void Simulator::set_d_register(
int dreg,
const uint32_t* value) {
936 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
937 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value) * 2);
941 void Simulator::get_q_register(
int qreg, uint64_t* value) {
942 DCHECK((qreg >= 0) && (qreg < num_q_registers));
943 memcpy(value, vfp_registers_ + qreg * 4,
sizeof(*value) * 2);
947 void Simulator::set_q_register(
int qreg,
const uint64_t* value) {
948 DCHECK((qreg >= 0) && (qreg < num_q_registers));
949 memcpy(vfp_registers_ + qreg * 4, value,
sizeof(*value) * 2);
953 void Simulator::get_q_register(
int qreg,
uint32_t* value) {
954 DCHECK((qreg >= 0) && (qreg < num_q_registers));
955 memcpy(value, vfp_registers_ + qreg * 4,
sizeof(*value) * 4);
959 void Simulator::set_q_register(
int qreg,
const uint32_t* value) {
960 DCHECK((qreg >= 0) && (qreg < num_q_registers));
961 memcpy(vfp_registers_ + qreg * 4, value,
sizeof(*value) * 4);
966 void Simulator::set_pc(
int32_t value) {
968 registers_[
pc] = value;
972 bool Simulator::has_bad_pc()
const {
973 return ((registers_[
pc] == bad_lr) || (registers_[
pc] == end_sim_pc));
978 int32_t Simulator::get_pc()
const {
979 return registers_[
pc];
984 void Simulator::set_s_register(
int sreg,
unsigned int value) {
985 DCHECK((sreg >= 0) && (sreg < num_s_registers));
986 vfp_registers_[sreg] = value;
990 unsigned int Simulator::get_s_register(
int sreg)
const {
991 DCHECK((sreg >= 0) && (sreg < num_s_registers));
992 return vfp_registers_[sreg];
996 template<
class InputType,
int register_size>
997 void Simulator::SetVFPRegister(
int reg_index,
const InputType& value) {
999 if (register_size == 1)
DCHECK(reg_index < num_s_registers);
1000 if (register_size == 2)
DCHECK(reg_index < DwVfpRegister::NumRegisters());
1002 char buffer[register_size *
sizeof(vfp_registers_[0])];
1003 memcpy(buffer, &value, register_size *
sizeof(vfp_registers_[0]));
1004 memcpy(&vfp_registers_[reg_index * register_size], buffer,
1005 register_size *
sizeof(vfp_registers_[0]));
1009 template<
class ReturnType,
int register_size>
1010 ReturnType Simulator::GetFromVFPRegister(
int reg_index) {
1012 if (register_size == 1)
DCHECK(reg_index < num_s_registers);
1013 if (register_size == 2)
DCHECK(reg_index < DwVfpRegister::NumRegisters());
1015 ReturnType value = 0;
1016 char buffer[register_size *
sizeof(vfp_registers_[0])];
1017 memcpy(buffer, &vfp_registers_[register_size * reg_index],
1018 register_size *
sizeof(vfp_registers_[0]));
1019 memcpy(&value, buffer, register_size *
sizeof(vfp_registers_[0]));
1028 void Simulator::GetFpArgs(
double* x,
double*
y,
int32_t* z) {
1029 if (use_eabi_hardfloat()) {
1030 *x = get_double_from_d_register(0);
1031 *
y = get_double_from_d_register(1);
1032 *z = get_register(0);
1035 *x = get_double_from_register_pair(0);
1037 *
y = get_double_from_register_pair(2);
1039 *z = get_register(2);
1045 void Simulator::SetFpResult(
const double& result) {
1046 if (use_eabi_hardfloat()) {
1047 char buffer[2 *
sizeof(vfp_registers_[0])];
1048 memcpy(buffer, &result,
sizeof(buffer));
1050 memcpy(vfp_registers_, buffer,
sizeof(buffer));
1052 char buffer[2 *
sizeof(registers_[0])];
1053 memcpy(buffer, &result,
sizeof(buffer));
1055 memcpy(registers_, buffer,
sizeof(buffer));
1060 void Simulator::TrashCallerSaveRegisters() {
1062 registers_[2] = 0x50Bad4U;
1063 registers_[3] = 0x50Bad4U;
1064 registers_[12] = 0x50Bad4U;
1082 int Simulator::ReadW(
int32_t addr, Instruction* instr) {
1083 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1084 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1089 reinterpret_cast<intptr_t
>(instr));
1096 void Simulator::WriteW(
int32_t addr,
int value, Instruction* instr) {
1097 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1098 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1103 reinterpret_cast<intptr_t
>(instr));
1110 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1114 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1117 reinterpret_cast<intptr_t
>(instr));
1125 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1129 PrintF(
"Unaligned signed halfword read at 0x%08x\n", addr);
1136 void Simulator::WriteH(
int32_t addr,
uint16_t value, Instruction* instr) {
1137 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1141 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1144 reinterpret_cast<intptr_t
>(instr));
1150 void Simulator::WriteH(
int32_t addr,
int16_t value, Instruction* instr) {
1151 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1157 reinterpret_cast<intptr_t
>(instr));
1163 uint8_t Simulator::ReadBU(
int32_t addr) {
1164 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1169 int8_t Simulator::ReadB(
int32_t addr) {
1170 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1175 void Simulator::WriteB(
int32_t addr, uint8_t value) {
1176 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1181 void Simulator::WriteB(
int32_t addr, int8_t value) {
1182 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1188 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1192 PrintF(
"Unaligned read at 0x%08x\n", addr);
1200 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1205 PrintF(
"Unaligned write at 0x%08x\n", addr);
1212 uintptr_t Simulator::StackLimit()
const {
1215 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1220 void Simulator::Format(Instruction* instr,
const char* format) {
1221 PrintF(
"Simulator found unsupported instruction:\n 0x%08x: %s\n",
1222 reinterpret_cast<intptr_t
>(instr), format);
1229 bool Simulator::ConditionallyExecute(Instruction* instr) {
1230 switch (instr->ConditionField()) {
1231 case eq:
return z_flag_;
1232 case ne:
return !z_flag_;
1233 case cs:
return c_flag_;
1234 case cc:
return !c_flag_;
1235 case mi:
return n_flag_;
1236 case pl:
return !n_flag_;
1237 case vs:
return v_flag_;
1238 case vc:
return !v_flag_;
1239 case hi:
return c_flag_ && !z_flag_;
1240 case ls:
return !c_flag_ || z_flag_;
1241 case ge:
return n_flag_ == v_flag_;
1242 case lt:
return n_flag_ != v_flag_;
1243 case gt:
return !z_flag_ && (n_flag_ == v_flag_);
1244 case le:
return z_flag_ || (n_flag_ != v_flag_);
1245 case al:
return true;
1253 void Simulator::SetNZFlags(
int32_t val) {
1254 n_flag_ = (val < 0);
1255 z_flag_ = (val == 0);
1260 void Simulator::SetCFlag(
bool val) {
1266 void Simulator::SetVFlag(
bool val) {
1275 uint32_t urest = 0xffffffffU - uleft;
1277 return (uright > urest) ||
1278 (
carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1287 return (uright > uleft);
1292 bool Simulator::OverflowFrom(
int32_t alu_out,
1297 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1299 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1302 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1304 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1311 void Simulator::Compute_FPSCR_Flags(
double val1,
double val2) {
1312 if (std::isnan(val1) || std::isnan(val2)) {
1313 n_flag_FPSCR_ =
false;
1314 z_flag_FPSCR_ =
false;
1315 c_flag_FPSCR_ =
true;
1316 v_flag_FPSCR_ =
true;
1318 }
else if (val1 == val2) {
1319 n_flag_FPSCR_ =
false;
1320 z_flag_FPSCR_ =
true;
1321 c_flag_FPSCR_ =
true;
1322 v_flag_FPSCR_ =
false;
1323 }
else if (val1 < val2) {
1324 n_flag_FPSCR_ =
true;
1325 z_flag_FPSCR_ =
false;
1326 c_flag_FPSCR_ =
false;
1327 v_flag_FPSCR_ =
false;
1330 n_flag_FPSCR_ =
false;
1331 z_flag_FPSCR_ =
false;
1332 c_flag_FPSCR_ =
true;
1333 v_flag_FPSCR_ =
false;
1338 void Simulator::Copy_FPSCR_to_APSR() {
1339 n_flag_ = n_flag_FPSCR_;
1340 z_flag_ = z_flag_FPSCR_;
1341 c_flag_ = c_flag_FPSCR_;
1342 v_flag_ = v_flag_FPSCR_;
1348 int32_t Simulator::GetShiftRm(Instruction* instr,
bool* carry_out) {
1350 int shift_amount = instr->ShiftAmountValue();
1351 int32_t result = get_register(instr->RmValue());
1352 if (instr->Bit(4) == 0) {
1354 if ((
shift ==
ROR) && (shift_amount == 0)) {
1362 if (shift_amount == 0) {
1364 result = 0xffffffff;
1371 result >>= (shift_amount - 1);
1372 *carry_out = (result & 1) == 1;
1379 if (shift_amount == 0) {
1380 *carry_out = c_flag_;
1382 result <<= (shift_amount - 1);
1383 *carry_out = (result < 0);
1390 if (shift_amount == 0) {
1392 *carry_out = c_flag_;
1395 uresult >>= (shift_amount - 1);
1396 *carry_out = (uresult & 1) == 1;
1398 result =
static_cast<int32_t>(uresult);
1404 if (shift_amount == 0) {
1405 *carry_out = c_flag_;
1409 result = right | left;
1410 *carry_out = (
static_cast<uint32_t>(result) >> 31) != 0;
1422 int rs = instr->RsValue();
1423 shift_amount = get_register(rs) &0xff;
1426 if (shift_amount == 0) {
1427 *carry_out = c_flag_;
1428 }
else if (shift_amount < 32) {
1429 result >>= (shift_amount - 1);
1430 *carry_out = (result & 1) == 1;
1433 DCHECK(shift_amount >= 32);
1436 result = 0xffffffff;
1446 if (shift_amount == 0) {
1447 *carry_out = c_flag_;
1448 }
else if (shift_amount < 32) {
1449 result <<= (shift_amount - 1);
1450 *carry_out = (result < 0);
1452 }
else if (shift_amount == 32) {
1453 *carry_out = (result & 1) == 1;
1456 DCHECK(shift_amount > 32);
1464 if (shift_amount == 0) {
1465 *carry_out = c_flag_;
1466 }
else if (shift_amount < 32) {
1468 uresult >>= (shift_amount - 1);
1469 *carry_out = (uresult & 1) == 1;
1471 result =
static_cast<int32_t>(uresult);
1472 }
else if (shift_amount == 32) {
1473 *carry_out = (result < 0);
1483 if (shift_amount == 0) {
1484 *carry_out = c_flag_;
1488 result = right | left;
1489 *carry_out = (
static_cast<uint32_t>(result) >> 31) != 0;
1506 int32_t Simulator::GetImm(Instruction* instr,
bool* carry_out) {
1507 int rotate = instr->RotateValue() * 2;
1508 int immed8 = instr->Immed8Value();
1509 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1510 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1515 static int count_bits(
int bit_vector) {
1517 while (bit_vector != 0) {
1518 if ((bit_vector & 1) != 0) {
1527 int32_t Simulator::ProcessPU(Instruction* instr,
1530 intptr_t* start_address,
1531 intptr_t* end_address) {
1532 int rn = instr->RnValue();
1533 int32_t rn_val = get_register(rn);
1534 switch (instr->PUField()) {
1540 *start_address = rn_val;
1541 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1542 rn_val = rn_val + (num_regs * reg_size);
1546 *start_address = rn_val - (num_regs * reg_size);
1547 *end_address = rn_val - reg_size;
1548 rn_val = *start_address;
1552 *start_address = rn_val + reg_size;
1553 *end_address = rn_val + (num_regs * reg_size);
1554 rn_val = *end_address;
1567 void Simulator::HandleRList(Instruction* instr,
bool load) {
1568 int rlist = instr->RlistValue();
1569 int num_regs = count_bits(rlist);
1571 intptr_t start_address = 0;
1572 intptr_t end_address = 0;
1574 ProcessPU(instr, num_regs,
kPointerSize, &start_address, &end_address);
1576 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1578 DCHECK(start_address > 8191 || start_address < 0);
1580 while (rlist != 0) {
1581 if ((rlist & 1) != 0) {
1583 set_register(reg, *address);
1585 *address = get_register(reg);
1592 DCHECK(end_address == ((intptr_t)address) - 4);
1593 if (instr->HasW()) {
1594 set_register(instr->RnValue(), rn_val);
1600 void Simulator::HandleVList(Instruction* instr) {
1605 bool load = (instr->VLValue() == 0x1);
1609 vd = instr->VFPDRegValue(precision);
1611 num_regs = instr->Immed8Value();
1613 num_regs = instr->Immed8Value() / 2;
1616 intptr_t start_address = 0;
1617 intptr_t end_address = 0;
1619 ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1621 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1622 for (
int reg = vd; reg < vd + num_regs; reg++) {
1625 set_s_register_from_sinteger(
1626 reg, ReadW(
reinterpret_cast<int32_t>(address), instr));
1628 WriteW(
reinterpret_cast<int32_t>(address),
1629 get_sinteger_from_s_register(reg), instr);
1635 ReadW(
reinterpret_cast<int32_t>(address), instr),
1636 ReadW(
reinterpret_cast<int32_t>(address + 1), instr)
1639 memcpy(&d, data, 8);
1640 set_d_register_from_double(reg, d);
1643 double d = get_double_from_d_register(reg);
1644 memcpy(data, &d, 8);
1645 WriteW(
reinterpret_cast<int32_t>(address), data[0], instr);
1646 WriteW(
reinterpret_cast<int32_t>(address + 1), data[1], instr);
1651 DCHECK(
reinterpret_cast<intptr_t
>(address) - operand_size == end_address);
1652 if (instr->HasW()) {
1653 set_register(instr->RnValue(), rn_val);
1664 typedef int64_t (*SimulatorRuntimeCall)(
int32_t arg0,
1672 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
1673 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
1674 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
1675 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0,
int32_t arg0);
1679 typedef void (*SimulatorRuntimeDirectApiCall)(
int32_t arg0);
1680 typedef void (*SimulatorRuntimeProfilingApiCall)(
int32_t arg0,
void* arg1);
1683 typedef void (*SimulatorRuntimeDirectGetterCall)(
int32_t arg0,
int32_t arg1);
1684 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1689 void Simulator::SoftwareInterrupt(Instruction* instr) {
1690 int svc = instr->SvcValue();
1695 bool stack_aligned =
1697 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1698 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1704 int32_t arg4 = stack_pointer[0];
1705 int32_t arg5 = stack_pointer[1];
1707 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1708 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1709 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1710 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1715 reinterpret_cast<intptr_t
>(redirection->external_function());
1717 double dval0, dval1;
1719 int64_t iresult = 0;
1721 GetFpArgs(&dval0, &dval1, &ival);
1722 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1723 SimulatorRuntimeCall generic_target =
1724 reinterpret_cast<SimulatorRuntimeCall
>(external);
1725 switch (redirection->type()) {
1726 case ExternalReference::BUILTIN_FP_FP_CALL:
1727 case ExternalReference::BUILTIN_COMPARE_CALL:
1728 PrintF(
"Call to host function at %p with args %f, %f",
1731 case ExternalReference::BUILTIN_FP_CALL:
1732 PrintF(
"Call to host function at %p with arg %f",
1735 case ExternalReference::BUILTIN_FP_INT_CALL:
1736 PrintF(
"Call to host function at %p with args %f, %d",
1743 if (!stack_aligned) {
1744 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1748 CHECK(stack_aligned);
1749 switch (redirection->type()) {
1750 case ExternalReference::BUILTIN_COMPARE_CALL: {
1751 SimulatorRuntimeCompareCall target =
1752 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
1753 iresult = target(dval0, dval1);
1754 set_register(
r0,
static_cast<int32_t>(iresult));
1755 set_register(
r1,
static_cast<int32_t>(iresult >> 32));
1758 case ExternalReference::BUILTIN_FP_FP_CALL: {
1759 SimulatorRuntimeFPFPCall target =
1760 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
1761 dresult = target(dval0, dval1);
1762 SetFpResult(dresult);
1765 case ExternalReference::BUILTIN_FP_CALL: {
1766 SimulatorRuntimeFPCall target =
1767 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1768 dresult = target(dval0);
1769 SetFpResult(dresult);
1772 case ExternalReference::BUILTIN_FP_INT_CALL: {
1773 SimulatorRuntimeFPIntCall target =
1774 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
1775 dresult = target(dval0, ival);
1776 SetFpResult(dresult);
1783 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1784 switch (redirection->type()) {
1785 case ExternalReference::BUILTIN_COMPARE_CALL:
1788 case ExternalReference::BUILTIN_FP_FP_CALL:
1789 case ExternalReference::BUILTIN_FP_CALL:
1790 case ExternalReference::BUILTIN_FP_INT_CALL:
1791 PrintF(
"Returned %f\n", dresult);
1798 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1799 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1800 PrintF(
"Call to host function at %p args %08x",
1801 reinterpret_cast<void*
>(external), arg0);
1802 if (!stack_aligned) {
1803 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1807 CHECK(stack_aligned);
1808 SimulatorRuntimeDirectApiCall target =
1809 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1812 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1813 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1814 PrintF(
"Call to host function at %p args %08x %08x",
1815 reinterpret_cast<void*
>(external), arg0, arg1);
1816 if (!stack_aligned) {
1817 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1821 CHECK(stack_aligned);
1822 SimulatorRuntimeProfilingApiCall target =
1823 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
1824 target(arg0, Redirection::ReverseRedirection(arg1));
1826 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1827 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1828 PrintF(
"Call to host function at %p args %08x %08x",
1829 reinterpret_cast<void*
>(external), arg0, arg1);
1830 if (!stack_aligned) {
1831 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1835 CHECK(stack_aligned);
1836 SimulatorRuntimeDirectGetterCall target =
1837 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1840 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1841 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1842 PrintF(
"Call to host function at %p args %08x %08x %08x",
1843 reinterpret_cast<void*
>(external), arg0, arg1, arg2);
1844 if (!stack_aligned) {
1845 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1849 CHECK(stack_aligned);
1850 SimulatorRuntimeProfilingGetterCall target =
1851 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(
1853 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1856 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
1857 SimulatorRuntimeCall target =
1858 reinterpret_cast<SimulatorRuntimeCall
>(external);
1859 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1861 "Call to host function at %p "
1862 "args %08x, %08x, %08x, %08x, %08x, %08x",
1870 if (!stack_aligned) {
1871 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1875 CHECK(stack_aligned);
1876 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1879 if (::v8::internal::FLAG_trace_sim) {
1880 PrintF(
"Returned %08x\n", lo_res);
1882 set_register(
r0, lo_res);
1883 set_register(
r1, hi_res);
1885 set_register(
lr, saved_lr);
1886 set_pc(get_register(
lr));
1890 ArmDebugger dbg(
this);
1896 if (svc >= (1 << 23)) {
1898 if (isWatchedStop(code)) {
1899 IncreaseStopCounter(code);
1903 if (isEnabledStop(code)) {
1904 ArmDebugger dbg(
this);
1907 set_pc(get_pc() + 2 * Instruction::kInstrSize);
1919 double Simulator::canonicalizeNaN(
double value) {
1920 return (FPSCR_default_NaN_mode_ && std::isnan(value)) ?
1921 FixedDoubleArray::canonical_not_the_hole_nan_as_double() : value;
1926 bool Simulator::isStopInstruction(Instruction* instr) {
1927 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >=
kStopCode);
1931 bool Simulator::isWatchedStop(
uint32_t code) {
1933 return code < kNumOfWatchedStops;
1937 bool Simulator::isEnabledStop(
uint32_t code) {
1940 return !isWatchedStop(code) ||
1941 !(watched_stops_[code].count & kStopDisabledBit);
1945 void Simulator::EnableStop(
uint32_t code) {
1946 DCHECK(isWatchedStop(code));
1947 if (!isEnabledStop(code)) {
1948 watched_stops_[code].count &= ~kStopDisabledBit;
1953 void Simulator::DisableStop(
uint32_t code) {
1954 DCHECK(isWatchedStop(code));
1955 if (isEnabledStop(code)) {
1956 watched_stops_[code].count |= kStopDisabledBit;
1961 void Simulator::IncreaseStopCounter(
uint32_t code) {
1963 DCHECK(isWatchedStop(code));
1964 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1965 PrintF(
"Stop counter for code %i has overflowed.\n"
1966 "Enabling this code and reseting the counter to 0.\n", code);
1967 watched_stops_[code].count = 0;
1970 watched_stops_[code].count++;
1976 void Simulator::PrintStopInfo(
uint32_t code) {
1978 if (!isWatchedStop(code)) {
1979 PrintF(
"Stop not watched.");
1981 const char* state = isEnabledStop(code) ?
"Enabled" :
"Disabled";
1982 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1985 if (watched_stops_[code].desc) {
1986 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1987 code, code, state, count, watched_stops_[code].desc);
1989 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
1990 code, code, state, count);
2001 void Simulator::DecodeType01(Instruction* instr) {
2002 int type = instr->TypeValue();
2003 if ((type == 0) && instr->IsSpecialType0()) {
2005 if (instr->Bits(7, 4) == 9) {
2006 if (instr->Bit(24) == 0) {
2009 int rn = instr->RnValue();
2010 int rm = instr->RmValue();
2011 int rs = instr->RsValue();
2012 int32_t rs_val = get_register(rs);
2013 int32_t rm_val = get_register(rm);
2014 if (instr->Bit(23) == 0) {
2015 if (instr->Bit(21) == 0) {
2021 int32_t alu_out = rm_val * rs_val;
2022 set_register(rd, alu_out);
2023 if (instr->HasS()) {
2024 SetNZFlags(alu_out);
2027 int rd = instr->RdValue();
2028 int32_t acc_value = get_register(rd);
2029 if (instr->Bit(22) == 0) {
2035 int32_t mul_out = rm_val * rs_val;
2036 int32_t result = acc_value + mul_out;
2037 set_register(rn, result);
2040 int32_t mul_out = rm_val * rs_val;
2041 int32_t result = acc_value - mul_out;
2042 set_register(rn, result);
2057 int rd_lo = instr->RdValue();
2060 if (instr->Bit(22) == 1) {
2061 int64_t left_op =
static_cast<int32_t>(rm_val);
2062 int64_t right_op =
static_cast<int32_t>(rs_val);
2063 uint64_t result = left_op * right_op;
2064 hi_res =
static_cast<int32_t>(result >> 32);
2065 lo_res =
static_cast<int32_t>(result & 0xffffffff);
2068 uint64_t left_op =
static_cast<uint32_t>(rm_val);
2069 uint64_t right_op =
static_cast<uint32_t>(rs_val);
2070 uint64_t result = left_op * right_op;
2071 hi_res =
static_cast<int32_t>(result >> 32);
2072 lo_res =
static_cast<int32_t>(result & 0xffffffff);
2074 set_register(rd_lo, lo_res);
2075 set_register(rd_hi, hi_res);
2076 if (instr->HasS()) {
2085 int rd = instr->RdValue();
2086 int rn = instr->RnValue();
2087 int32_t rn_val = get_register(rn);
2089 if (instr->Bit(22) == 0) {
2090 int rm = instr->RmValue();
2091 int32_t rm_val = get_register(rm);
2092 switch (instr->PUField()) {
2098 set_register(rn, rn_val);
2106 set_register(rn, rn_val);
2113 if (instr->HasW()) {
2114 set_register(rn, rn_val);
2122 if (instr->HasW()) {
2123 set_register(rn, rn_val);
2134 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2135 switch (instr->PUField()) {
2141 set_register(rn, rn_val);
2149 set_register(rn, rn_val);
2156 if (instr->HasW()) {
2157 set_register(rn, rn_val);
2165 if (instr->HasW()) {
2166 set_register(rn, rn_val);
2177 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2179 if (instr->HasH()) {
2181 int32_t value1 = get_register(rd);
2182 int32_t value2 = get_register(rd+1);
2183 WriteDW(addr, value1, value2);
2186 int* rn_data = ReadDW(addr);
2187 set_dw_register(rd, rn_data);
2189 }
else if (instr->HasH()) {
2190 if (instr->HasSign()) {
2191 if (instr->HasL()) {
2192 int16_t val = ReadH(addr, instr);
2193 set_register(rd, val);
2195 int16_t val = get_register(rd);
2196 WriteH(addr, val, instr);
2199 if (instr->HasL()) {
2200 uint16_t val = ReadHU(addr, instr);
2201 set_register(rd, val);
2204 WriteH(addr, val, instr);
2209 DCHECK(instr->HasSign());
2211 int8_t val = ReadB(addr);
2212 set_register(rd, val);
2216 }
else if ((type == 0) && instr->IsMiscType0()) {
2217 if (instr->Bits(22, 21) == 1) {
2218 int rm = instr->RmValue();
2219 switch (instr->BitField(7, 4)) {
2221 set_pc(get_register(rm));
2225 set_pc(get_register(rm));
2226 set_register(
lr, old_pc + Instruction::kInstrSize);
2230 ArmDebugger dbg(
this);
2231 PrintF(
"Simulator hit BKPT.\n");
2238 }
else if (instr->Bits(22, 21) == 3) {
2239 int rm = instr->RmValue();
2240 int rd = instr->RdValue();
2241 switch (instr->BitField(7, 4)) {
2244 int leading_zeros = 0;
2248 while ((bits & 0x80000000u) == 0) {
2253 set_register(rd, leading_zeros);
2260 PrintF(
"%08x\n", instr->InstructionBits());
2263 }
else if ((type == 1) && instr->IsNopType1()) {
2266 int rd = instr->RdValue();
2267 int rn = instr->RnValue();
2268 int32_t rn_val = get_register(rn);
2270 bool shifter_carry_out = 0;
2272 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2274 DCHECK(instr->TypeValue() == 1);
2275 shifter_operand = GetImm(instr, &shifter_carry_out);
2279 switch (instr->OpcodeField()) {
2283 alu_out = rn_val & shifter_operand;
2284 set_register(rd, alu_out);
2285 if (instr->HasS()) {
2286 SetNZFlags(alu_out);
2287 SetCFlag(shifter_carry_out);
2295 alu_out = rn_val ^ shifter_operand;
2296 set_register(rd, alu_out);
2297 if (instr->HasS()) {
2298 SetNZFlags(alu_out);
2299 SetCFlag(shifter_carry_out);
2307 alu_out = rn_val - shifter_operand;
2308 set_register(rd, alu_out);
2309 if (instr->HasS()) {
2310 SetNZFlags(alu_out);
2311 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2312 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2320 alu_out = shifter_operand - rn_val;
2321 set_register(rd, alu_out);
2322 if (instr->HasS()) {
2323 SetNZFlags(alu_out);
2324 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2325 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val,
false));
2333 alu_out = rn_val + shifter_operand;
2334 set_register(rd, alu_out);
2335 if (instr->HasS()) {
2336 SetNZFlags(alu_out);
2337 SetCFlag(CarryFrom(rn_val, shifter_operand));
2338 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2346 alu_out = rn_val + shifter_operand + GetCarry();
2347 set_register(rd, alu_out);
2348 if (instr->HasS()) {
2349 SetNZFlags(alu_out);
2350 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2351 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2357 Format(instr,
"sbc'cond's 'rd, 'rn, 'shift_rm");
2358 Format(instr,
"sbc'cond's 'rd, 'rn, 'imm");
2363 Format(instr,
"rsc'cond's 'rd, 'rn, 'shift_rm");
2364 Format(instr,
"rsc'cond's 'rd, 'rn, 'imm");
2369 if (instr->HasS()) {
2372 alu_out = rn_val & shifter_operand;
2373 SetNZFlags(alu_out);
2374 SetCFlag(shifter_carry_out);
2377 alu_out = instr->ImmedMovwMovtValue();
2378 set_register(rd, alu_out);
2384 if (instr->HasS()) {
2387 alu_out = rn_val ^ shifter_operand;
2388 SetNZFlags(alu_out);
2389 SetCFlag(shifter_carry_out);
2399 if (instr->HasS()) {
2402 alu_out = rn_val - shifter_operand;
2403 SetNZFlags(alu_out);
2404 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2405 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2408 alu_out = (get_register(rd) & 0xffff) |
2409 (instr->ImmedMovwMovtValue() << 16);
2410 set_register(rd, alu_out);
2416 if (instr->HasS()) {
2419 alu_out = rn_val + shifter_operand;
2420 SetNZFlags(alu_out);
2421 SetCFlag(CarryFrom(rn_val, shifter_operand));
2422 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2434 alu_out = rn_val | shifter_operand;
2435 set_register(rd, alu_out);
2436 if (instr->HasS()) {
2437 SetNZFlags(alu_out);
2438 SetCFlag(shifter_carry_out);
2446 alu_out = shifter_operand;
2447 set_register(rd, alu_out);
2448 if (instr->HasS()) {
2449 SetNZFlags(alu_out);
2450 SetCFlag(shifter_carry_out);
2458 alu_out = rn_val & ~shifter_operand;
2459 set_register(rd, alu_out);
2460 if (instr->HasS()) {
2461 SetNZFlags(alu_out);
2462 SetCFlag(shifter_carry_out);
2470 alu_out = ~shifter_operand;
2471 set_register(rd, alu_out);
2472 if (instr->HasS()) {
2473 SetNZFlags(alu_out);
2474 SetCFlag(shifter_carry_out);
2488 void Simulator::DecodeType2(Instruction* instr) {
2489 int rd = instr->RdValue();
2490 int rn = instr->RnValue();
2491 int32_t rn_val = get_register(rn);
2492 int32_t im_val = instr->Offset12Value();
2494 switch (instr->PUField()) {
2500 set_register(rn, rn_val);
2508 set_register(rn, rn_val);
2515 if (instr->HasW()) {
2516 set_register(rn, rn_val);
2524 if (instr->HasW()) {
2525 set_register(rn, rn_val);
2534 if (instr->HasB()) {
2535 if (instr->HasL()) {
2536 byte val = ReadBU(addr);
2537 set_register(rd, val);
2539 byte val = get_register(rd);
2543 if (instr->HasL()) {
2544 set_register(rd, ReadW(addr, instr));
2546 WriteW(addr, get_register(rd), instr);
2552 void Simulator::DecodeType3(Instruction* instr) {
2553 int rd = instr->RdValue();
2554 int rn = instr->RnValue();
2555 int32_t rn_val = get_register(rn);
2556 bool shifter_carry_out = 0;
2557 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2559 switch (instr->PUField()) {
2562 Format(instr,
"'memop'cond'b 'rd, ['rn], -'shift_rm");
2567 if (instr->Bit(4) == 0) {
2570 if (instr->Bit(5) == 0) {
2571 switch (instr->Bits(22, 21)) {
2573 if (instr->Bit(20) == 0) {
2574 if (instr->Bit(6) == 0) {
2576 uint32_t rn_val = get_register(rn);
2577 uint32_t rm_val = get_register(instr->RmValue());
2580 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2583 uint32_t rn_val = get_register(rn);
2584 int32_t rm_val = get_register(instr->RmValue());
2590 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2604 int32_t sat_pos = instr->Bits(20, 16);
2605 int32_t sat_val = (1 << sat_pos) - 1;
2607 int32_t shift_type = instr->Bit(6);
2608 int32_t rm_val = get_register(instr->RmValue());
2609 if (shift_type == 0) {
2617 if (rm_val > sat_val) {
2619 }
else if (rm_val < 0) {
2622 set_register(rd, rm_val);
2627 switch (instr->Bits(22, 21)) {
2635 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2636 if (instr->Bits(19, 16) == 0xF) {
2638 uint32_t rm_val = get_register(instr->RmValue());
2639 int32_t rotate = instr->Bits(11, 10);
2644 rm_val = (rm_val >> 8) | (rm_val << 24);
2647 rm_val = (rm_val >> 16) | (rm_val << 16);
2650 rm_val = (rm_val >> 24) | (rm_val << 8);
2654 (rm_val & 0xFF) | (rm_val & 0xFF0000));
2663 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2664 if (instr->Bits(19, 16) == 0xF) {
2666 uint32_t rm_val = get_register(instr->RmValue());
2667 int32_t rotate = instr->Bits(11, 10);
2672 rm_val = (rm_val >> 8) | (rm_val << 24);
2675 rm_val = (rm_val >> 16) | (rm_val << 16);
2678 rm_val = (rm_val >> 24) | (rm_val << 8);
2681 set_register(rd, (rm_val & 0xFF));
2684 uint32_t rn_val = get_register(rn);
2685 uint32_t rm_val = get_register(instr->RmValue());
2686 int32_t rotate = instr->Bits(11, 10);
2691 rm_val = (rm_val >> 8) | (rm_val << 24);
2694 rm_val = (rm_val >> 16) | (rm_val << 16);
2697 rm_val = (rm_val >> 24) | (rm_val << 8);
2700 set_register(rd, rn_val + (rm_val & 0xFF));
2713 if (FLAG_enable_sudiv) {
2714 if (instr->Bits(5, 4) == 0x1) {
2715 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2718 int rm = instr->RmValue();
2719 int32_t rm_val = get_register(rm);
2720 int rs = instr->RsValue();
2721 int32_t rs_val = get_register(rs);
2725 if (instr->Bit(21) == 0x1) {
2728 }
else if ((rm_val ==
kMinInt) && (rs_val == -1)) {
2731 ret_val = rm_val / rs_val;
2733 set_register(rn, ret_val);
2739 addr = rn_val - shifter_operand;
2740 if (instr->HasW()) {
2741 set_register(rn, addr);
2746 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2749 uint32_t msbit = widthminus1 + lsbit;
2751 if (instr->Bit(22)) {
2754 static_cast<uint32_t>(get_register(instr->RmValue()));
2755 uint32_t extr_val = rm_val << (31 - msbit);
2756 extr_val = extr_val >> (31 - widthminus1);
2757 set_register(instr->RdValue(), extr_val);
2760 int32_t rm_val = get_register(instr->RmValue());
2761 int32_t extr_val = rm_val << (31 - msbit);
2762 extr_val = extr_val >> (31 - widthminus1);
2763 set_register(instr->RdValue(), extr_val);
2769 }
else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2772 if (msbit >= lsbit) {
2775 static_cast<uint32_t>(get_register(instr->RdValue()));
2776 uint32_t bitcount = msbit - lsbit + 1;
2777 uint32_t mask = 0xffffffffu >> (32 - bitcount);
2778 rd_val &= ~(mask << lsbit);
2779 if (instr->RmValue() != 15) {
2782 static_cast<uint32_t>(get_register(instr->RmValue()));
2784 rd_val |= rm_val << lsbit;
2786 set_register(instr->RdValue(), rd_val);
2793 addr = rn_val + shifter_operand;
2794 if (instr->HasW()) {
2795 set_register(rn, addr);
2805 if (instr->HasB()) {
2806 if (instr->HasL()) {
2807 uint8_t
byte = ReadB(addr);
2808 set_register(rd,
byte);
2810 uint8_t
byte = get_register(rd);
2814 if (instr->HasL()) {
2815 set_register(rd, ReadW(addr, instr));
2817 WriteW(addr, get_register(rd), instr);
2823 void Simulator::DecodeType4(Instruction* instr) {
2824 DCHECK(instr->Bit(22) == 0);
2825 if (instr->HasL()) {
2827 HandleRList(instr,
true);
2830 HandleRList(instr,
false);
2835 void Simulator::DecodeType5(Instruction* instr) {
2837 int off = (instr->SImmed24Value() << 2);
2838 intptr_t pc_address = get_pc();
2839 if (instr->HasLink()) {
2840 set_register(
lr, pc_address + Instruction::kInstrSize);
2842 int pc_reg = get_register(
pc);
2843 set_pc(pc_reg + off);
2847 void Simulator::DecodeType6(Instruction* instr) {
2848 DecodeType6CoprocessorIns(instr);
2852 void Simulator::DecodeType7(Instruction* instr) {
2853 if (instr->Bit(24) == 1) {
2854 SoftwareInterrupt(instr);
2856 DecodeTypeVFP(instr);
2877 void Simulator::DecodeTypeVFP(Instruction* instr) {
2878 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2879 DCHECK(instr->Bits(11, 9) == 0x5);
2886 if (instr->Bit(4) == 0) {
2887 if (instr->Opc1Value() == 0x7) {
2889 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2891 if (instr->SzValue() == 0x1) {
2894 set_d_register_from_double(d, get_double_from_d_register(m));
2898 set_s_register_from_float(d, get_float_from_s_register(m));
2900 }
else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2902 double dm_value = get_double_from_d_register(vm);
2903 double dd_value = std::fabs(dm_value);
2904 dd_value = canonicalizeNaN(dd_value);
2905 set_d_register_from_double(vd, dd_value);
2906 }
else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2908 double dm_value = get_double_from_d_register(vm);
2909 double dd_value = -dm_value;
2910 dd_value = canonicalizeNaN(dd_value);
2911 set_d_register_from_double(vd, dd_value);
2912 }
else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2913 DecodeVCVTBetweenDoubleAndSingle(instr);
2914 }
else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2915 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2916 }
else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
2917 (instr->Bit(8) == 1)) {
2919 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
2920 int fixed_value = get_sinteger_from_s_register(vd * 2);
2921 double divide = 1 << fraction_bits;
2922 set_d_register_from_double(vd, fixed_value / divide);
2923 }
else if (((instr->Opc2Value() >> 1) == 0x6) &&
2924 (instr->Opc3Value() & 0x1)) {
2925 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2926 }
else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2927 (instr->Opc3Value() & 0x1)) {
2929 }
else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2931 double dm_value = get_double_from_d_register(vm);
2932 double dd_value = std::sqrt(dm_value);
2933 dd_value = canonicalizeNaN(dd_value);
2934 set_d_register_from_double(vd, dd_value);
2935 }
else if (instr->Opc3Value() == 0x0) {
2937 if (instr->SzValue() == 0x1) {
2938 set_d_register_from_double(vd, instr->DoubleImmedVmov());
2945 }
else if (instr->Opc1Value() == 0x3) {
2946 if (instr->SzValue() != 0x1) {
2950 if (instr->Opc3Value() & 0x1) {
2952 double dn_value = get_double_from_d_register(vn);
2953 double dm_value = get_double_from_d_register(vm);
2954 double dd_value = dn_value - dm_value;
2955 dd_value = canonicalizeNaN(dd_value);
2956 set_d_register_from_double(vd, dd_value);
2959 double dn_value = get_double_from_d_register(vn);
2960 double dm_value = get_double_from_d_register(vm);
2961 double dd_value = dn_value + dm_value;
2962 dd_value = canonicalizeNaN(dd_value);
2963 set_d_register_from_double(vd, dd_value);
2965 }
else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2967 if (instr->SzValue() != 0x1) {
2971 double dn_value = get_double_from_d_register(vn);
2972 double dm_value = get_double_from_d_register(vm);
2973 double dd_value = dn_value * dm_value;
2974 dd_value = canonicalizeNaN(dd_value);
2975 set_d_register_from_double(vd, dd_value);
2976 }
else if ((instr->Opc1Value() == 0x0)) {
2978 const bool is_vmls = (instr->Opc3Value() & 0x1);
2980 if (instr->SzValue() != 0x1) {
2984 const double dd_val = get_double_from_d_register(vd);
2985 const double dn_val = get_double_from_d_register(vn);
2986 const double dm_val = get_double_from_d_register(vm);
2990 set_d_register_from_double(vd, dn_val * dm_val);
2992 set_d_register_from_double(
2994 canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
2996 set_d_register_from_double(
2998 canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3000 }
else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3002 if (instr->SzValue() != 0x1) {
3006 double dn_value = get_double_from_d_register(vn);
3007 double dm_value = get_double_from_d_register(vm);
3008 double dd_value = dn_value / dm_value;
3009 div_zero_vfp_flag_ = (dm_value == 0);
3010 dd_value = canonicalizeNaN(dd_value);
3011 set_d_register_from_double(vd, dd_value);
3016 if ((instr->VCValue() == 0x0) &&
3017 (instr->VAValue() == 0x0)) {
3018 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3019 }
else if ((instr->VLValue() == 0x0) &&
3020 (instr->VCValue() == 0x1) &&
3021 (instr->Bit(23) == 0x0)) {
3023 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3024 double dd_value = get_double_from_d_register(vd);
3026 memcpy(data, &dd_value, 8);
3027 data[instr->Bit(21)] = get_register(instr->RtValue());
3028 memcpy(&dd_value, data, 8);
3029 set_d_register_from_double(vd, dd_value);
3030 }
else if ((instr->VLValue() == 0x1) &&
3031 (instr->VCValue() == 0x1) &&
3032 (instr->Bit(23) == 0x0)) {
3034 int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3035 double dn_value = get_double_from_d_register(vn);
3037 memcpy(data, &dn_value, 8);
3038 set_register(instr->RtValue(), data[instr->Bit(21)]);
3039 }
else if ((instr->VLValue() == 0x1) &&
3040 (instr->VCValue() == 0x0) &&
3041 (instr->VAValue() == 0x7) &&
3042 (instr->Bits(19, 16) == 0x1)) {
3046 Copy_FPSCR_to_APSR();
3049 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3050 (z_flag_FPSCR_ << 30) |
3051 (c_flag_FPSCR_ << 29) |
3052 (v_flag_FPSCR_ << 28) |
3053 (FPSCR_default_NaN_mode_ << 25) |
3054 (inexact_vfp_flag_ << 4) |
3055 (underflow_vfp_flag_ << 3) |
3056 (overflow_vfp_flag_ << 2) |
3057 (div_zero_vfp_flag_ << 1) |
3058 (inv_op_vfp_flag_ << 0) |
3059 (FPSCR_rounding_mode_);
3060 set_register(rt, fpscr);
3062 }
else if ((instr->VLValue() == 0x0) &&
3063 (instr->VCValue() == 0x0) &&
3064 (instr->VAValue() == 0x7) &&
3065 (instr->Bits(19, 16) == 0x1)) {
3071 uint32_t rt_value = get_register(rt);
3072 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3073 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3074 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3075 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3076 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3077 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3078 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3079 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3080 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3081 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3082 FPSCR_rounding_mode_ =
3092 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3093 Instruction* instr) {
3094 DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3095 (instr->VAValue() == 0x0));
3097 int t = instr->RtValue();
3099 bool to_arm_register = (instr->VLValue() == 0x1);
3101 if (to_arm_register) {
3102 int32_t int_value = get_sinteger_from_s_register(n);
3103 set_register(t, int_value);
3105 int32_t rs_val = get_register(t);
3106 set_s_register_from_sinteger(n, rs_val);
3111 void Simulator::DecodeVCMP(Instruction* instr) {
3112 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3113 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3114 (instr->Opc3Value() & 0x1));
3118 if (instr->SzValue() == 1) {
3122 int d = instr->VFPDRegValue(precision);
3124 if (instr->Opc2Value() == 0x4) {
3125 m = instr->VFPMRegValue(precision);
3129 double dd_value = get_double_from_d_register(d);
3130 double dm_value = 0.0;
3131 if (instr->Opc2Value() == 0x4) {
3132 dm_value = get_double_from_d_register(m);
3136 if (instr->Bit(7) == 1) {
3137 if (std::isnan(dd_value)) {
3138 inv_op_vfp_flag_ =
true;
3142 Compute_FPSCR_Flags(dd_value, dm_value);
3149 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3150 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3151 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3155 if (instr->SzValue() == 1) {
3160 int dst = instr->VFPDRegValue(dst_precision);
3161 int src = instr->VFPMRegValue(src_precision);
3164 double val = get_double_from_d_register(src);
3165 set_s_register_from_float(dst,
static_cast<float>(val));
3167 float val = get_float_from_s_register(src);
3168 set_d_register_from_double(dst,
static_cast<double>(val));
3176 double max_uint =
static_cast<double>(0xffffffffu);
3177 double max_int =
static_cast<double>(
kMaxInt);
3178 double min_int =
static_cast<double>(
kMinInt);
3189 return unsigned_ ? (val >= (max_uint + 0.5)) ||
3191 : (val >= (max_int + 0.5)) ||
3192 (val < (min_int - 0.5));
3195 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3197 : (val >= (max_int + 1.0)) ||
3201 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3203 : (val >= (max_int + 1.0)) ||
3204 (val <= (min_int - 1.0));
3214 int VFPConversionSaturate(
double val,
bool unsigned_res) {
3219 return (val < 0) ? 0 : 0xffffffffu;
3227 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3228 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3229 (instr->Bits(27, 23) == 0x1D));
3230 DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3231 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3234 bool to_integer = (instr->Bit(18) == 1);
3248 int src = instr->VFPMRegValue(src_precision);
3256 bool unsigned_integer = (instr->Bit(16) == 0);
3259 double val = double_precision ? get_double_from_d_register(src)
3260 : get_float_from_s_register(src);
3262 int temp = unsigned_integer ?
static_cast<uint32_t>(val)
3265 inv_op_vfp_flag_ = get_inv_op_vfp_flag(
mode, val, unsigned_integer);
3268 unsigned_integer ? std::fabs(val -
static_cast<uint32_t>(temp))
3269 : std::fabs(val - temp);
3271 inexact_vfp_flag_ = (abs_diff != 0);
3273 if (inv_op_vfp_flag_) {
3274 temp = VFPConversionSaturate(val, unsigned_integer);
3278 int val_sign = (val > 0) ? 1 : -1;
3279 if (abs_diff > 0.5) {
3281 }
else if (abs_diff == 0.5) {
3283 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3289 temp = temp > val ? temp - 1 : temp;
3302 set_s_register_from_sinteger(dst, temp);
3305 bool unsigned_integer = (instr->Bit(7) == 0);
3307 int dst = instr->VFPDRegValue(src_precision);
3310 int val = get_sinteger_from_s_register(src);
3313 if (unsigned_integer) {
3314 set_d_register_from_double(
3315 dst,
static_cast<double>(
static_cast<uint32_t>(val)));
3317 set_d_register_from_double(dst,
static_cast<double>(val));
3320 if (unsigned_integer) {
3321 set_s_register_from_float(
3322 dst,
static_cast<float>(
static_cast<uint32_t>(val)));
3324 set_s_register_from_float(dst,
static_cast<float>(val));
3337 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3338 DCHECK((instr->TypeValue() == 6));
3340 if (instr->CoprocessorValue() == 0xA) {
3341 switch (instr->OpcodeValue()) {
3346 int rn = instr->RnValue();
3348 int offset = instr->Immed8Value();
3349 if (!instr->HasU()) {
3353 int32_t address = get_register(rn) + 4 * offset;
3354 if (instr->HasL()) {
3356 set_s_register_from_sinteger(vd, ReadW(address, instr));
3359 WriteW(address, get_sinteger_from_s_register(vd), instr);
3375 }
else if (instr->CoprocessorValue() == 0xB) {
3376 switch (instr->OpcodeValue()) {
3379 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3382 int rt = instr->RtValue();
3383 int rn = instr->RnValue();
3385 if (instr->HasL()) {
3387 double d = get_double_from_d_register(vm);
3388 memcpy(data, &d, 8);
3389 set_register(rt, data[0]);
3390 set_register(rn, data[1]);
3392 int32_t data[] = { get_register(rt), get_register(rn) };
3394 memcpy(&d, data, 8);
3395 set_d_register_from_double(vm, d);
3403 int rn = instr->RnValue();
3405 int offset = instr->Immed8Value();
3406 if (!instr->HasU()) {
3409 int32_t address = get_register(rn) + 4 * offset;
3410 if (instr->HasL()) {
3413 ReadW(address, instr),
3414 ReadW(address + 4, instr)
3417 memcpy(&val, data, 8);
3418 set_d_register_from_double(vd, val);
3422 double val = get_double_from_d_register(vd);
3423 memcpy(data, &val, 8);
3424 WriteW(address, data[0], instr);
3425 WriteW(address + 4, data[1], instr);
3447 void Simulator::DecodeSpecialCondition(Instruction* instr) {
3448 switch (instr->SpecialValue()) {
3450 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3451 (instr->Bit(4) == 1)) {
3454 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3455 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3456 int imm3 = instr->Bits(21, 19);
3457 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4))
UNIMPLEMENTED();
3458 int esize = 8 * imm3;
3459 int elements = 64 / esize;
3461 get_d_register(Vm,
reinterpret_cast<uint64_t*
>(from));
3464 while (e < elements) {
3468 set_q_register(Vd,
reinterpret_cast<uint64_t*
>(
to));
3474 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3475 (instr->Bit(4) == 1)) {
3478 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3479 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3480 int imm3 = instr->Bits(21, 19);
3481 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4))
UNIMPLEMENTED();
3482 int esize = 8 * imm3;
3483 int elements = 64 / esize;
3485 get_d_register(Vm,
reinterpret_cast<uint64_t*
>(from));
3488 while (e < elements) {
3492 set_q_register(Vd,
reinterpret_cast<uint64_t*
>(
to));
3498 if (instr->Bits(21, 20) == 0) {
3500 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3501 int Rn = instr->VnValue();
3502 int type = instr->Bits(11, 8);
3503 int Rm = instr->VmValue();
3504 int32_t address = get_register(Rn);
3526 get_d_register(Vd + r, data);
3527 WriteW(address, data[0], instr);
3528 WriteW(address + 4, data[1], instr);
3534 set_register(Rn, address);
3536 set_register(Rn, get_register(Rn) + get_register(Rm));
3539 }
else if (instr->Bits(21, 20) == 2) {
3541 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3542 int Rn = instr->VnValue();
3543 int type = instr->Bits(11, 8);
3544 int Rm = instr->VmValue();
3545 int32_t address = get_register(Rn);
3567 data[0] = ReadW(address, instr);
3568 data[1] = ReadW(address + 4, instr);
3569 set_d_register(Vd + r, data);
3575 set_register(Rn, address);
3577 set_register(Rn, get_register(Rn) + get_register(Rm));
3586 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
3600 void Simulator::InstructionDecode(Instruction* instr) {
3601 if (v8::internal::FLAG_check_icache) {
3602 CheckICache(isolate_->simulator_i_cache(), instr);
3604 pc_modified_ =
false;
3605 if (::v8::internal::FLAG_trace_sim) {
3610 dasm.InstructionDecode(buffer,
3611 reinterpret_cast<byte*
>(instr));
3612 PrintF(
" 0x%08x %s\n",
reinterpret_cast<intptr_t
>(instr), buffer.
start());
3615 DecodeSpecialCondition(instr);
3616 }
else if (ConditionallyExecute(instr)) {
3617 switch (instr->TypeValue()) {
3620 DecodeType01(instr);
3654 }
else if (instr->IsStop()) {
3655 set_pc(get_pc() + 2 * Instruction::kInstrSize);
3657 if (!pc_modified_) {
3658 set_register(
pc,
reinterpret_cast<int32_t>(instr)
3659 + Instruction::kInstrSize);
3664 void Simulator::Execute() {
3667 int program_counter = get_pc();
3669 if (::v8::internal::FLAG_stop_sim_at == 0) {
3672 while (program_counter != end_sim_pc) {
3673 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3675 InstructionDecode(instr);
3676 program_counter = get_pc();
3681 while (program_counter != end_sim_pc) {
3682 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3684 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3685 ArmDebugger dbg(
this);
3688 InstructionDecode(instr);
3690 program_counter = get_pc();
3696 void Simulator::CallInternal(
byte* entry) {
3698 set_register(
pc,
reinterpret_cast<int32_t>(entry));
3702 set_register(
lr, end_sim_pc);
3718 int32_t callee_saved_value = icount_;
3719 set_register(
r4, callee_saved_value);
3720 set_register(
r5, callee_saved_value);
3721 set_register(
r6, callee_saved_value);
3722 set_register(
r7, callee_saved_value);
3723 set_register(
r8, callee_saved_value);
3724 set_register(
r9, callee_saved_value);
3725 set_register(
r10, callee_saved_value);
3726 set_register(
r11, callee_saved_value);
3732 CHECK_EQ(callee_saved_value, get_register(
r4));
3733 CHECK_EQ(callee_saved_value, get_register(
r5));
3734 CHECK_EQ(callee_saved_value, get_register(
r6));
3735 CHECK_EQ(callee_saved_value, get_register(
r7));
3736 CHECK_EQ(callee_saved_value, get_register(
r8));
3737 CHECK_EQ(callee_saved_value, get_register(
r9));
3742 set_register(
r4, r4_val);
3743 set_register(
r5, r5_val);
3744 set_register(
r6, r6_val);
3745 set_register(
r7, r7_val);
3746 set_register(
r8, r8_val);
3747 set_register(
r9, r9_val);
3748 set_register(
r10, r10_val);
3749 set_register(
r11, r11_val);
3753 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
3755 va_start(parameters, argument_count);
3759 DCHECK(argument_count >= 4);
3760 set_register(
r0, va_arg(parameters,
int32_t));
3761 set_register(
r1, va_arg(parameters,
int32_t));
3762 set_register(
r2, va_arg(parameters,
int32_t));
3763 set_register(
r3, va_arg(parameters,
int32_t));
3766 int original_stack = get_register(
sp);
3768 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t));
3769 if (base::OS::ActivationFrameAlignment() != 0) {
3770 entry_stack &= -base::OS::ActivationFrameAlignment();
3773 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
3774 for (
int i = 4;
i < argument_count;
i++) {
3775 stack_argument[
i - 4] = va_arg(parameters,
int32_t);
3778 set_register(
sp, entry_stack);
3780 CallInternal(entry);
3784 set_register(
sp, original_stack);
3791 void Simulator::CallFP(
byte* entry,
double d0,
double d1) {
3792 if (use_eabi_hardfloat()) {
3793 set_d_register_from_double(0,
d0);
3794 set_d_register_from_double(1,
d1);
3796 set_register_pair_from_double(0, &
d0);
3797 set_register_pair_from_double(2, &
d1);
3799 CallInternal(entry);
3803 int32_t Simulator::CallFPReturnsInt(
byte* entry,
double d0,
double d1) {
3804 CallFP(entry,
d0,
d1);
3810 double Simulator::CallFPReturnsDouble(
byte* entry,
double d0,
double d1) {
3811 CallFP(entry,
d0,
d1);
3812 if (use_eabi_hardfloat()) {
3813 return get_double_from_d_register(0);
3815 return get_double_from_register_pair(0);
3821 int new_sp = get_register(
sp) -
sizeof(
uintptr_t);
3823 *stack_slot = address;
3824 set_register(
sp, new_sp);
3830 int current_sp = get_register(
sp);
static int Number(const char *name)
static const char * Name(int reg)
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
static int Number(const char *name, bool *is_double)
static const char * Name(int reg, bool is_double)
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 expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
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 mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
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
enable harmony numeric enable harmony object literal extensions Optimize object Array shift
#define CHECK_EQ(expected, value)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define OFFSET_OF(type, field)
void DeleteArray(T *array)
char * ReadLine(const char *prompt)
TypeImpl< ZoneTypeConfig > Type
const LowDwVfpRegister d1
const uint32_t kMaxStopCode
const LowDwVfpRegister d0
kSerializedDataOffset Object
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
void PrintF(const char *format,...)
const uint32_t kVFPRoundingModeMask
const uint32_t kStopCodeMask
Debugger support for the V8 JavaScript engine.
static int NumRegisters()