33 #if defined(V8_TARGET_ARCH_ARM)
40 #if defined(USE_SIMULATOR)
50 #define SScanF sscanf // NOLINT
56 explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
59 void Stop(Instruction* instr);
63 static const Instr kBreakpointInstr =
65 static const Instr kNopInstr = (
al | (13*
B21));
69 int32_t GetRegisterValue(
int regnum);
70 double GetRegisterPairDoubleValue(
int regnum);
71 double GetVFPDoubleRegisterValue(
int regnum);
72 bool GetValue(
const char* desc,
int32_t* value);
73 bool GetVFPSingleValue(
const char* desc,
float* value);
74 bool GetVFPDoubleValue(
const char* desc,
double* value);
77 bool SetBreakpoint(Instruction* breakpc);
78 bool DeleteBreakpoint(Instruction* breakpc);
82 void UndoBreakpoints();
83 void RedoBreakpoints();
87 ArmDebugger::~ArmDebugger() {
92 #ifdef GENERATED_CODE_COVERAGE
93 static FILE* coverage_log =
NULL;
96 static void InitializeCoverage() {
97 char* file_name = getenv(
"V8_GENERATED_CODE_COVERAGE_LOG");
98 if (file_name !=
NULL) {
99 coverage_log = fopen(file_name,
"aw+");
104 void ArmDebugger::Stop(Instruction* instr) {
110 char* msg = *msg_address;
114 if (isWatchedStop(code) && !watched_stops[code].desc) {
115 watched_stops[code].desc = msg;
118 if (strlen(msg) > 0) {
119 if (coverage_log !=
NULL) {
120 fprintf(coverage_log,
"%s\n", msg);
121 fflush(coverage_log);
124 instr->SetInstructionBits(kNopInstr);
125 reinterpret_cast<Instruction*
>(msg_address)->SetInstructionBits(kNopInstr);
130 #else // ndef GENERATED_CODE_COVERAGE
132 static void InitializeCoverage() {
136 void ArmDebugger::Stop(Instruction* instr) {
140 char* msg = *
reinterpret_cast<char**
>(sim_->get_pc()
143 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
144 sim_->watched_stops[code].desc = msg;
148 PrintF(
"Simulator hit stop %u: %s\n", code, msg);
150 PrintF(
"Simulator hit %s\n", msg);
158 int32_t ArmDebugger::GetRegisterValue(
int regnum) {
160 return sim_->get_pc();
162 return sim_->get_register(regnum);
167 double ArmDebugger::GetRegisterPairDoubleValue(
int regnum) {
168 return sim_->get_double_from_register_pair(regnum);
172 double ArmDebugger::GetVFPDoubleRegisterValue(
int regnum) {
173 return sim_->get_double_from_d_register(regnum);
177 bool ArmDebugger::GetValue(
const char* desc,
int32_t* value) {
180 *value = GetRegisterValue(regnum);
183 if (strncmp(desc,
"0x", 2) == 0) {
184 return SScanF(desc + 2,
"%x", reinterpret_cast<uint32_t*>(value)) == 1;
186 return SScanF(desc,
"%u", reinterpret_cast<uint32_t*>(value)) == 1;
193 bool ArmDebugger::GetVFPSingleValue(
const char* desc,
float* value) {
197 *value = sim_->get_float_from_s_register(regnum);
204 bool ArmDebugger::GetVFPDoubleValue(
const char* desc,
double* value) {
208 *value = sim_->get_double_from_d_register(regnum);
215 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
217 if (sim_->break_pc_ !=
NULL) {
222 sim_->break_pc_ = breakpc;
223 sim_->break_instr_ = breakpc->InstructionBits();
230 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
231 if (sim_->break_pc_ !=
NULL) {
232 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
235 sim_->break_pc_ =
NULL;
236 sim_->break_instr_ = 0;
241 void ArmDebugger::UndoBreakpoints() {
242 if (sim_->break_pc_ !=
NULL) {
243 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
248 void ArmDebugger::RedoBreakpoints() {
249 if (sim_->break_pc_ !=
NULL) {
250 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
255 void ArmDebugger::Debug() {
256 intptr_t last_pc = -1;
259 #define COMMAND_SIZE 63
263 #define XSTR(a) STR(a)
265 char cmd[COMMAND_SIZE + 1];
266 char arg1[ARG_SIZE + 1];
267 char arg2[ARG_SIZE + 1];
268 char* argv[3] = { cmd, arg1, arg2 };
271 cmd[COMMAND_SIZE] = 0;
280 if (last_pc != sim_->get_pc()) {
285 dasm.InstructionDecode(buffer,
286 reinterpret_cast<byte*>(sim_->get_pc()));
287 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.
start());
288 last_pc = sim_->get_pc();
294 char* last_input = sim_->last_debugger_input();
295 if (strcmp(line,
"\n") == 0 && last_input !=
NULL) {
299 sim_->set_last_debugger_input(line);
303 int argc = SScanF(line,
304 "%" XSTR(COMMAND_SIZE)
"s "
305 "%" XSTR(ARG_SIZE)
"s "
306 "%" XSTR(ARG_SIZE)
"s",
308 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
309 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
310 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
312 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
315 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
316 if (argc == 2 || (argc == 3 && strcmp(arg2,
"fp") == 0)) {
320 if (strcmp(arg1,
"all") == 0) {
322 value = GetRegisterValue(i);
324 if ((argc == 3 && strcmp(arg2,
"fp") == 0) &&
327 dvalue = GetRegisterPairDoubleValue(i);
328 PrintF(
" (%f)\n", dvalue);
334 dvalue = GetVFPDoubleRegisterValue(i);
335 uint64_t as_words = BitCast<uint64_t>(dvalue);
336 PrintF(
"%3s: %f 0x%08x %08x\n",
339 static_cast<uint32_t>(as_words >> 32),
340 static_cast<uint32_t>(as_words & 0xffffffff));
343 if (GetValue(arg1, &value)) {
344 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
345 }
else if (GetVFPSingleValue(arg1, &svalue)) {
346 uint32_t as_word = BitCast<uint32_t>(svalue);
347 PrintF(
"%s: %f 0x%08x\n", arg1, svalue, as_word);
348 }
else if (GetVFPDoubleValue(arg1, &dvalue)) {
349 uint64_t as_words = BitCast<uint64_t>(dvalue);
350 PrintF(
"%s: %f 0x%08x %08x\n",
353 static_cast<uint32_t>(as_words >> 32),
354 static_cast<uint32_t>(as_words & 0xffffffff));
356 PrintF(
"%s unrecognized\n", arg1);
360 PrintF(
"print <register>\n");
362 }
else if ((strcmp(cmd,
"po") == 0)
363 || (strcmp(cmd,
"printobject") == 0)) {
366 if (GetValue(arg1, &value)) {
376 PrintF(
"%s unrecognized\n", arg1);
379 PrintF(
"printobject <value>\n");
381 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
386 if (strcmp(cmd,
"stack") == 0) {
390 if (!GetValue(arg1, &value)) {
391 PrintF(
"%s unrecognized\n", arg1);
394 cur =
reinterpret_cast<int32_t*
>(value);
399 if (argc == next_arg) {
401 }
else if (argc == next_arg + 1) {
402 if (!GetValue(argv[next_arg], &words)) {
409 PrintF(
" 0x%08x: 0x%08x %10d",
410 reinterpret_cast<intptr_t>(cur), *cur, *cur);
411 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
413 Heap* current_heap = v8::internal::Isolate::Current()->heap();
414 if (current_heap->Contains(obj) || ((value & 1) == 0)) {
416 if ((value & 1) == 0) {
417 PrintF(
"smi %d", value / 2);
426 }
else if (strcmp(cmd,
"disasm") == 0 || strcmp(cmd,
"di") == 0) {
437 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
439 }
else if (argc == 2) {
441 if (regnum !=
kNoRegister || strncmp(arg1,
"0x", 2) == 0) {
444 if (GetValue(arg1, &value)) {
445 cur =
reinterpret_cast<byte*
>(value);
452 if (GetValue(arg1, &value)) {
453 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
461 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
462 cur =
reinterpret_cast<byte*
>(value1);
469 cur += dasm.InstructionDecode(buffer, cur);
471 reinterpret_cast<intptr_t>(prev), buffer.
start());
473 }
else if (strcmp(cmd,
"gdb") == 0) {
474 PrintF(
"relinquishing control to gdb\n");
476 PrintF(
"regaining control from gdb\n");
477 }
else if (strcmp(cmd,
"break") == 0) {
480 if (GetValue(arg1, &value)) {
481 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
482 PrintF(
"setting breakpoint failed\n");
485 PrintF(
"%s unrecognized\n", arg1);
488 PrintF(
"break <address>\n");
490 }
else if (strcmp(cmd,
"del") == 0) {
491 if (!DeleteBreakpoint(
NULL)) {
492 PrintF(
"deleting breakpoint failed\n");
494 }
else if (strcmp(cmd,
"flags") == 0) {
495 PrintF(
"N flag: %d; ", sim_->n_flag_);
496 PrintF(
"Z flag: %d; ", sim_->z_flag_);
497 PrintF(
"C flag: %d; ", sim_->c_flag_);
498 PrintF(
"V flag: %d\n", sim_->v_flag_);
499 PrintF(
"INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
500 PrintF(
"DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
501 PrintF(
"OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
502 PrintF(
"UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
503 PrintF(
"INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
504 }
else if (strcmp(cmd,
"stop") == 0) {
507 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
508 Instruction* msg_address =
510 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
512 if (sim_->isStopInstruction(stop_instr)) {
513 stop_instr->SetInstructionBits(kNopInstr);
514 msg_address->SetInstructionBits(kNopInstr);
516 PrintF(
"Not at debugger stop.\n");
518 }
else if (argc == 3) {
520 if (strcmp(arg1,
"info") == 0) {
521 if (strcmp(arg2,
"all") == 0) {
522 PrintF(
"Stop information:\n");
523 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
524 sim_->PrintStopInfo(i);
526 }
else if (GetValue(arg2, &value)) {
527 sim_->PrintStopInfo(value);
529 PrintF(
"Unrecognized argument.\n");
531 }
else if (strcmp(arg1,
"enable") == 0) {
533 if (strcmp(arg2,
"all") == 0) {
534 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
537 }
else if (GetValue(arg2, &value)) {
538 sim_->EnableStop(value);
540 PrintF(
"Unrecognized argument.\n");
542 }
else if (strcmp(arg1,
"disable") == 0) {
544 if (strcmp(arg2,
"all") == 0) {
545 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
546 sim_->DisableStop(i);
548 }
else if (GetValue(arg2, &value)) {
549 sim_->DisableStop(value);
551 PrintF(
"Unrecognized argument.\n");
555 PrintF(
"Wrong usage. Use help command for more information.\n");
557 }
else if ((strcmp(cmd,
"t") == 0) || strcmp(cmd,
"trace") == 0) {
558 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
559 PrintF(
"Trace of executed instructions is %s\n",
560 ::v8::internal::FLAG_trace_sim ?
"on" :
"off");
561 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
563 PrintF(
" continue execution (alias 'c')\n");
565 PrintF(
" step one instruction (alias 'si')\n");
566 PrintF(
"print <register>\n");
567 PrintF(
" print register content (alias 'p')\n");
568 PrintF(
" use register name 'all' to print all registers\n");
569 PrintF(
" add argument 'fp' to print register pair double values\n");
570 PrintF(
"printobject <register>\n");
571 PrintF(
" print an object from a register (alias 'po')\n");
574 PrintF(
"stack [<words>]\n");
575 PrintF(
" dump stack content, default dump 10 words)\n");
576 PrintF(
"mem <address> [<words>]\n");
577 PrintF(
" dump memory content, default dump 10 words)\n");
578 PrintF(
"disasm [<instructions>]\n");
579 PrintF(
"disasm [<address/register>]\n");
580 PrintF(
"disasm [[<address/register>] <instructions>]\n");
581 PrintF(
" disassemble code, default is 10 instructions\n");
582 PrintF(
" from pc (alias 'di')\n");
585 PrintF(
"break <address>\n");
586 PrintF(
" set a break point on the address\n");
588 PrintF(
" delete the breakpoint\n");
589 PrintF(
"trace (alias 't')\n");
590 PrintF(
" toogle the tracing of all executed statements\n");
591 PrintF(
"stop feature:\n");
592 PrintF(
" Description:\n");
593 PrintF(
" Stops are debug instructions inserted by\n");
594 PrintF(
" the Assembler::stop() function.\n");
595 PrintF(
" When hitting a stop, the Simulator will\n");
596 PrintF(
" stop and and give control to the ArmDebugger.\n");
597 PrintF(
" The first %d stop codes are watched:\n",
598 Simulator::kNumOfWatchedStops);
599 PrintF(
" - They can be enabled / disabled: the Simulator\n");
600 PrintF(
" will / won't stop when hitting them.\n");
601 PrintF(
" - The Simulator keeps track of how many times they \n");
602 PrintF(
" are met. (See the info command.) Going over a\n");
603 PrintF(
" disabled stop still increases its counter. \n");
605 PrintF(
" stop info all/<code> : print infos about number <code>\n");
606 PrintF(
" or all stop(s).\n");
607 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
608 PrintF(
" all or number <code> stop(s)\n");
610 PrintF(
" ignore the stop instruction at the current location\n");
613 PrintF(
"Unknown command: %s\n", cmd);
630 static bool ICacheMatch(
void* one,
void* two) {
631 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
632 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
637 static uint32_t ICacheHash(
void* key) {
638 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(key)) >> 2;
642 static bool AllOnOnePage(uintptr_t start,
int size) {
643 intptr_t start_page = (start & ~CachePage::kPageMask);
644 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
645 return start_page == end_page;
649 void Simulator::set_last_debugger_input(
char* input) {
651 last_debugger_input_ = input;
658 intptr_t start =
reinterpret_cast<intptr_t
>(start_addr);
659 int intra_line = (start & CachePage::kLineMask);
662 size = ((size - 1) | CachePage::kLineMask) + 1;
663 int offset = (start & CachePage::kPageMask);
664 while (!AllOnOnePage(start, size - 1)) {
665 int bytes_to_flush = CachePage::kPageSize - offset;
666 FlushOnePage(i_cache, start, bytes_to_flush);
667 start += bytes_to_flush;
668 size -= bytes_to_flush;
669 ASSERT_EQ(0, start & CachePage::kPageMask);
673 FlushOnePage(i_cache, start, size);
679 v8::internal::HashMap::Entry* entry = i_cache->
Lookup(page,
682 if (entry->value ==
NULL) {
683 CachePage* new_page =
new CachePage();
684 entry->value = new_page;
686 return reinterpret_cast<CachePage*
>(entry->value);
694 ASSERT(size <= CachePage::kPageSize);
695 ASSERT(AllOnOnePage(start, size - 1));
696 ASSERT((start & CachePage::kLineMask) == 0);
697 ASSERT((size & CachePage::kLineMask) == 0);
698 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
699 int offset = (start & CachePage::kPageMask);
700 CachePage* cache_page = GetCachePage(i_cache, page);
701 char* valid_bytemap = cache_page->ValidityByte(offset);
702 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
707 Instruction* instr) {
708 intptr_t address =
reinterpret_cast<intptr_t
>(instr);
709 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
710 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
711 int offset = (address & CachePage::kPageMask);
712 CachePage* cache_page = GetCachePage(i_cache, page);
713 char* cache_valid_byte = cache_page->ValidityByte(offset);
714 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
715 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
718 CHECK(memcmp(reinterpret_cast<void*>(instr),
719 cache_page->CachedData(offset),
723 memcpy(cached_line, line, CachePage::kLineLength);
724 *cache_valid_byte = CachePage::LINE_VALID;
729 void Simulator::Initialize(Isolate* isolate) {
730 if (isolate->simulator_initialized())
return;
731 isolate->set_simulator_initialized(
true);
732 ::v8::internal::ExternalReference::set_redirector(isolate,
733 &RedirectExternalReference);
737 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
738 i_cache_ = isolate_->simulator_i_cache();
739 if (i_cache_ ==
NULL) {
741 isolate_->set_simulator_i_cache(i_cache_);
746 size_t stack_size = 1 * 1024*1024;
747 stack_ =
reinterpret_cast<char*
>(malloc(stack_size));
748 pc_modified_ =
false;
755 for (
int i = 0; i < num_registers; i++) {
767 for (
int i = 0; i < num_s_registers; i++) {
770 n_flag_FPSCR_ =
false;
771 z_flag_FPSCR_ =
false;
772 c_flag_FPSCR_ =
false;
773 v_flag_FPSCR_ =
false;
774 FPSCR_rounding_mode_ =
RZ;
776 inv_op_vfp_flag_ =
false;
777 div_zero_vfp_flag_ =
false;
778 overflow_vfp_flag_ =
false;
779 underflow_vfp_flag_ =
false;
780 inexact_vfp_flag_ =
false;
785 registers_[
sp] =
reinterpret_cast<int32_t>(stack_) + stack_size - 64;
788 registers_[
pc] = bad_lr;
789 registers_[
lr] = bad_lr;
790 InitializeCoverage();
792 last_debugger_input_ =
NULL;
805 Redirection(
void* external_function, ExternalReference::Type
type)
806 : external_function_(external_function),
810 Isolate* isolate = Isolate::Current();
811 next_ = isolate->simulator_redirection();
812 Simulator::current(isolate)->
813 FlushICache(isolate->simulator_i_cache(),
814 reinterpret_cast<void*
>(&swi_instruction_),
816 isolate->set_simulator_redirection(
this);
819 void* address_of_swi_instruction() {
820 return reinterpret_cast<void*
>(&swi_instruction_);
823 void* external_function() {
return external_function_; }
824 ExternalReference::Type
type() {
return type_; }
826 static Redirection* Get(
void* external_function,
827 ExternalReference::Type type) {
828 Isolate* isolate = Isolate::Current();
829 Redirection* current = isolate->simulator_redirection();
830 for (; current !=
NULL; current = current->next_) {
831 if (current->external_function_ == external_function)
return current;
833 return new Redirection(external_function, type);
836 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
837 char* addr_of_swi =
reinterpret_cast<char*
>(swi_instruction);
838 char* addr_of_redirection =
839 addr_of_swi -
OFFSET_OF(Redirection, swi_instruction_);
840 return reinterpret_cast<Redirection*
>(addr_of_redirection);
844 void* external_function_;
845 uint32_t swi_instruction_;
846 ExternalReference::Type
type_;
851 void* Simulator::RedirectExternalReference(
void* external_function,
852 ExternalReference::Type type) {
853 Redirection* redirection = Redirection::Get(external_function, type);
854 return redirection->address_of_swi_instruction();
859 Simulator* Simulator::current(Isolate* isolate) {
861 isolate->FindOrAllocatePerThreadDataForThisThread();
864 Simulator* sim = isolate_data->simulator();
867 sim =
new Simulator(isolate);
868 isolate_data->set_simulator(sim);
876 void Simulator::set_register(
int reg,
int32_t value) {
877 ASSERT((reg >= 0) && (reg < num_registers));
881 registers_[reg] = value;
887 int32_t Simulator::get_register(
int reg)
const {
888 ASSERT((reg >= 0) && (reg < num_registers));
891 if (reg >= num_registers)
return 0;
897 double Simulator::get_double_from_register_pair(
int reg) {
898 ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
903 char buffer[2 *
sizeof(vfp_register[0])];
904 memcpy(buffer, ®isters_[reg], 2 *
sizeof(registers_[0]));
905 memcpy(&dm_val, buffer, 2 *
sizeof(registers_[0]));
910 void Simulator::set_dw_register(
int dreg,
const int* dbl) {
911 ASSERT((dreg >= 0) && (dreg < num_d_registers));
912 registers_[dreg] = dbl[0];
913 registers_[dreg + 1] = dbl[1];
918 void Simulator::set_pc(
int32_t value) {
920 registers_[
pc] = value;
924 bool Simulator::has_bad_pc()
const {
925 return ((registers_[
pc] == bad_lr) || (registers_[
pc] == end_sim_pc));
930 int32_t Simulator::get_pc()
const {
931 return registers_[
pc];
936 void Simulator::set_s_register(
int sreg,
unsigned int value) {
937 ASSERT((sreg >= 0) && (sreg < num_s_registers));
938 vfp_register[sreg] = value;
942 unsigned int Simulator::get_s_register(
int sreg)
const {
943 ASSERT((sreg >= 0) && (sreg < num_s_registers));
944 return vfp_register[sreg];
948 void Simulator::set_s_register_from_float(
int sreg,
const float flt) {
949 ASSERT((sreg >= 0) && (sreg < num_s_registers));
952 char buffer[
sizeof(vfp_register[0])];
953 memcpy(buffer, &flt,
sizeof(vfp_register[0]));
954 memcpy(&vfp_register[sreg], buffer,
sizeof(vfp_register[0]));
958 void Simulator::set_s_register_from_sinteger(
int sreg,
const int sint) {
959 ASSERT((sreg >= 0) && (sreg < num_s_registers));
962 char buffer[
sizeof(vfp_register[0])];
963 memcpy(buffer, &sint,
sizeof(vfp_register[0]));
964 memcpy(&vfp_register[sreg], buffer,
sizeof(vfp_register[0]));
968 void Simulator::set_d_register_from_double(
int dreg,
const double& dbl) {
969 ASSERT((dreg >= 0) && (dreg < num_d_registers));
973 char buffer[2 *
sizeof(vfp_register[0])];
974 memcpy(buffer, &dbl, 2 *
sizeof(vfp_register[0]));
975 memcpy(&vfp_register[dreg * 2], buffer, 2 *
sizeof(vfp_register[0]));
979 float Simulator::get_float_from_s_register(
int sreg) {
980 ASSERT((sreg >= 0) && (sreg < num_s_registers));
985 char buffer[
sizeof(vfp_register[0])];
986 memcpy(buffer, &vfp_register[sreg],
sizeof(vfp_register[0]));
987 memcpy(&sm_val, buffer,
sizeof(vfp_register[0]));
992 int Simulator::get_sinteger_from_s_register(
int sreg) {
993 ASSERT((sreg >= 0) && (sreg < num_s_registers));
998 char buffer[
sizeof(vfp_register[0])];
999 memcpy(buffer, &vfp_register[sreg],
sizeof(vfp_register[0]));
1000 memcpy(&sm_val, buffer,
sizeof(vfp_register[0]));
1005 double Simulator::get_double_from_d_register(
int dreg) {
1006 ASSERT((dreg >= 0) && (dreg < num_d_registers));
1008 double dm_val = 0.0;
1011 char buffer[2 *
sizeof(vfp_register[0])];
1012 memcpy(buffer, &vfp_register[2 * dreg], 2 *
sizeof(vfp_register[0]));
1013 memcpy(&dm_val, buffer, 2 *
sizeof(vfp_register[0]));
1020 void Simulator::GetFpArgs(
double* x,
double* y) {
1021 if (use_eabi_hardfloat()) {
1022 *x = vfp_register[0];
1023 *y = vfp_register[1];
1027 char buffer[
sizeof(*x)];
1029 memcpy(buffer, registers_,
sizeof(*x));
1030 memcpy(x, buffer,
sizeof(*x));
1032 memcpy(buffer, registers_ + 2,
sizeof(*y));
1033 memcpy(y, buffer,
sizeof(*y));
1039 void Simulator::GetFpArgs(
double* x) {
1040 if (use_eabi_hardfloat()) {
1041 *x = vfp_register[0];
1045 char buffer[
sizeof(*x)];
1047 memcpy(buffer, registers_,
sizeof(*x));
1048 memcpy(x, buffer,
sizeof(*x));
1055 void Simulator::GetFpArgs(
double* x,
int32_t* y) {
1056 if (use_eabi_hardfloat()) {
1057 *x = vfp_register[0];
1062 char buffer[
sizeof(*x)];
1064 memcpy(buffer, registers_,
sizeof(*x));
1065 memcpy(x, buffer,
sizeof(*x));
1067 memcpy(buffer, registers_ + 2,
sizeof(*y));
1068 memcpy(y, buffer,
sizeof(*y));
1074 void Simulator::SetFpResult(
const double& result) {
1075 if (use_eabi_hardfloat()) {
1076 char buffer[2 *
sizeof(vfp_register[0])];
1077 memcpy(buffer, &result,
sizeof(buffer));
1079 memcpy(vfp_register, buffer,
sizeof(buffer));
1081 char buffer[2 *
sizeof(registers_[0])];
1082 memcpy(buffer, &result,
sizeof(buffer));
1084 memcpy(registers_, buffer,
sizeof(buffer));
1089 void Simulator::TrashCallerSaveRegisters() {
1091 registers_[2] = 0x50Bad4
U;
1092 registers_[3] = 0x50Bad4
U;
1093 registers_[12] = 0x50Bad4
U;
1110 int Simulator::ReadW(
int32_t addr, Instruction* instr) {
1111 #if V8_TARGET_CAN_READ_UNALIGNED
1112 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1115 if ((addr & 3) == 0) {
1116 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1121 reinterpret_cast<intptr_t>(instr));
1128 void Simulator::WriteW(
int32_t addr,
int value, Instruction* instr) {
1129 #if V8_TARGET_CAN_READ_UNALIGNED
1130 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1134 if ((addr & 3) == 0) {
1135 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1141 reinterpret_cast<intptr_t>(instr));
1148 #if V8_TARGET_CAN_READ_UNALIGNED
1152 if ((addr & 1) == 0) {
1156 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1158 reinterpret_cast<intptr_t>(instr));
1166 #if V8_TARGET_CAN_READ_UNALIGNED
1170 if ((addr & 1) == 0) {
1174 PrintF(
"Unaligned signed halfword read at 0x%08x\n", addr);
1181 void Simulator::WriteH(
int32_t addr,
uint16_t value, Instruction* instr) {
1182 #if V8_TARGET_CAN_READ_UNALIGNED
1187 if ((addr & 1) == 0) {
1192 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1194 reinterpret_cast<intptr_t>(instr));
1200 void Simulator::WriteH(
int32_t addr,
int16_t value, Instruction* instr) {
1201 #if V8_TARGET_CAN_READ_UNALIGNED
1206 if ((addr & 1) == 0) {
1213 reinterpret_cast<intptr_t>(instr));
1219 uint8_t Simulator::ReadBU(
int32_t addr) {
1220 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1225 int8_t Simulator::ReadB(
int32_t addr) {
1226 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1231 void Simulator::WriteB(
int32_t addr, uint8_t value) {
1232 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1237 void Simulator::WriteB(
int32_t addr, int8_t value) {
1238 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1244 #if V8_TARGET_CAN_READ_UNALIGNED
1248 if ((addr & 3) == 0) {
1252 PrintF(
"Unaligned read at 0x%08x\n", addr);
1260 #if V8_TARGET_CAN_READ_UNALIGNED
1266 if ((addr & 3) == 0) {
1272 PrintF(
"Unaligned write at 0x%08x\n", addr);
1279 uintptr_t Simulator::StackLimit()
const {
1282 return reinterpret_cast<uintptr_t
>(stack_) + 1024;
1287 void Simulator::Format(Instruction* instr,
const char* format) {
1288 PrintF(
"Simulator found unsupported instruction:\n 0x%08x: %s\n",
1289 reinterpret_cast<intptr_t>(instr), format);
1296 bool Simulator::ConditionallyExecute(Instruction* instr) {
1297 switch (instr->ConditionField()) {
1298 case eq:
return z_flag_;
1299 case ne:
return !z_flag_;
1300 case cs:
return c_flag_;
1301 case cc:
return !c_flag_;
1302 case mi:
return n_flag_;
1303 case pl:
return !n_flag_;
1304 case vs:
return v_flag_;
1305 case vc:
return !v_flag_;
1306 case hi:
return c_flag_ && !z_flag_;
1307 case ls:
return !c_flag_ || z_flag_;
1308 case ge:
return n_flag_ == v_flag_;
1309 case lt:
return n_flag_ != v_flag_;
1310 case gt:
return !z_flag_ && (n_flag_ == v_flag_);
1311 case le:
return z_flag_ || (n_flag_ != v_flag_);
1312 case al:
return true;
1320 void Simulator::SetNZFlags(
int32_t val) {
1321 n_flag_ = (val < 0);
1322 z_flag_ = (val == 0);
1327 void Simulator::SetCFlag(
bool val) {
1333 void Simulator::SetVFlag(
bool val) {
1340 uint32_t uleft =
static_cast<uint32_t
>(left);
1341 uint32_t uright =
static_cast<uint32_t
>(right);
1342 uint32_t urest = 0xffffffff
U - uleft;
1344 return (uright > urest) ||
1345 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1351 uint32_t uleft =
static_cast<uint32_t
>(left);
1352 uint32_t uright =
static_cast<uint32_t
>(right);
1354 return (uright > uleft);
1359 bool Simulator::OverflowFrom(
int32_t alu_out,
1364 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1366 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1369 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1371 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1378 void Simulator::Compute_FPSCR_Flags(
double val1,
double val2) {
1380 n_flag_FPSCR_ =
false;
1381 z_flag_FPSCR_ =
false;
1382 c_flag_FPSCR_ =
true;
1383 v_flag_FPSCR_ =
true;
1385 }
else if (val1 == val2) {
1386 n_flag_FPSCR_ =
false;
1387 z_flag_FPSCR_ =
true;
1388 c_flag_FPSCR_ =
true;
1389 v_flag_FPSCR_ =
false;
1390 }
else if (val1 < val2) {
1391 n_flag_FPSCR_ =
true;
1392 z_flag_FPSCR_ =
false;
1393 c_flag_FPSCR_ =
false;
1394 v_flag_FPSCR_ =
false;
1397 n_flag_FPSCR_ =
false;
1398 z_flag_FPSCR_ =
false;
1399 c_flag_FPSCR_ =
true;
1400 v_flag_FPSCR_ =
false;
1405 void Simulator::Copy_FPSCR_to_APSR() {
1406 n_flag_ = n_flag_FPSCR_;
1407 z_flag_ = z_flag_FPSCR_;
1408 c_flag_ = c_flag_FPSCR_;
1409 v_flag_ = v_flag_FPSCR_;
1415 int32_t Simulator::GetShiftRm(Instruction* instr,
bool* carry_out) {
1416 ShiftOp shift = instr->ShiftField();
1417 int shift_amount = instr->ShiftAmountValue();
1418 int32_t result = get_register(instr->RmValue());
1419 if (instr->Bit(4) == 0) {
1421 if ((shift ==
ROR) && (shift_amount == 0)) {
1424 }
else if (((shift ==
LSR) || (shift ==
ASR)) && (shift_amount == 0)) {
1429 if (shift_amount == 0) {
1431 result = 0xffffffff;
1438 result >>= (shift_amount - 1);
1439 *carry_out = (result & 1) == 1;
1446 if (shift_amount == 0) {
1447 *carry_out = c_flag_;
1449 result <<= (shift_amount - 1);
1450 *carry_out = (result < 0);
1457 if (shift_amount == 0) {
1459 *carry_out = c_flag_;
1461 uint32_t uresult =
static_cast<uint32_t
>(result);
1462 uresult >>= (shift_amount - 1);
1463 *carry_out = (uresult & 1) == 1;
1465 result =
static_cast<int32_t>(uresult);
1482 int rs = instr->RsValue();
1483 shift_amount = get_register(rs) &0xff;
1486 if (shift_amount == 0) {
1487 *carry_out = c_flag_;
1488 }
else if (shift_amount < 32) {
1489 result >>= (shift_amount - 1);
1490 *carry_out = (result & 1) == 1;
1493 ASSERT(shift_amount >= 32);
1496 result = 0xffffffff;
1506 if (shift_amount == 0) {
1507 *carry_out = c_flag_;
1508 }
else if (shift_amount < 32) {
1509 result <<= (shift_amount - 1);
1510 *carry_out = (result < 0);
1512 }
else if (shift_amount == 32) {
1513 *carry_out = (result & 1) == 1;
1516 ASSERT(shift_amount > 32);
1524 if (shift_amount == 0) {
1525 *carry_out = c_flag_;
1526 }
else if (shift_amount < 32) {
1527 uint32_t uresult =
static_cast<uint32_t
>(result);
1528 uresult >>= (shift_amount - 1);
1529 *carry_out = (uresult & 1) == 1;
1531 result =
static_cast<int32_t>(uresult);
1532 }
else if (shift_amount == 32) {
1533 *carry_out = (result < 0);
1559 int32_t Simulator::GetImm(Instruction* instr,
bool* carry_out) {
1560 int rotate = instr->RotateValue() * 2;
1561 int immed8 = instr->Immed8Value();
1562 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1563 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1568 static int count_bits(
int bit_vector) {
1570 while (bit_vector != 0) {
1571 if ((bit_vector & 1) != 0) {
1580 void Simulator::ProcessPUW(Instruction* instr,
1583 intptr_t* start_address,
1584 intptr_t* end_address) {
1585 int rn = instr->RnValue();
1586 int32_t rn_val = get_register(rn);
1587 switch (instr->PUField()) {
1593 *start_address = rn_val;
1594 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1595 rn_val = rn_val + (num_regs * reg_size);
1599 *start_address = rn_val - (num_regs * reg_size);
1600 *end_address = rn_val - reg_size;
1601 rn_val = *start_address;
1605 *start_address = rn_val + reg_size;
1606 *end_address = rn_val + (num_regs * reg_size);
1607 rn_val = *end_address;
1615 if (instr->HasW()) {
1616 set_register(rn, rn_val);
1621 void Simulator::HandleRList(Instruction* instr,
bool load) {
1622 int rlist = instr->RlistValue();
1623 int num_regs = count_bits(rlist);
1625 intptr_t start_address = 0;
1626 intptr_t end_address = 0;
1627 ProcessPUW(instr, num_regs,
kPointerSize, &start_address, &end_address);
1629 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1631 ASSERT(start_address > 8191 || start_address < 0);
1633 while (rlist != 0) {
1634 if ((rlist & 1) != 0) {
1636 set_register(reg, *address);
1638 *address = get_register(reg);
1645 ASSERT(end_address == ((intptr_t)address) - 4);
1650 void Simulator::HandleVList(Instruction* instr) {
1655 bool load = (instr->VLValue() == 0x1);
1659 vd = instr->VFPDRegValue(precision);
1661 num_regs = instr->Immed8Value();
1663 num_regs = instr->Immed8Value() / 2;
1666 intptr_t start_address = 0;
1667 intptr_t end_address = 0;
1668 ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address);
1670 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1671 for (
int reg = vd; reg < vd + num_regs; reg++) {
1674 set_s_register_from_sinteger(
1675 reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1677 WriteW(reinterpret_cast<int32_t>(address),
1678 get_sinteger_from_s_register(reg), instr);
1683 set_s_register_from_sinteger(
1684 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1685 set_s_register_from_sinteger(
1686 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr));
1688 WriteW(reinterpret_cast<int32_t>(address),
1689 get_sinteger_from_s_register(2 * reg), instr);
1690 WriteW(reinterpret_cast<int32_t>(address + 1),
1691 get_sinteger_from_s_register(2 * reg + 1), instr);
1696 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1706 typedef int64_t (*SimulatorRuntimeCall)(
int32_t arg0,
1712 typedef double (*SimulatorRuntimeFPCall)(
int32_t arg0,
1727 void Simulator::SoftwareInterrupt(Instruction* instr) {
1728 int svc = instr->SvcValue();
1733 bool stack_aligned =
1735 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1736 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1742 int32_t arg4 = stack_pointer[0];
1743 int32_t arg5 = stack_pointer[1];
1745 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1746 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1747 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1748 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1749 if (use_eabi_hardfloat()) {
1754 switch (redirection->type()) {
1755 case ExternalReference::BUILTIN_FP_FP_CALL:
1756 case ExternalReference::BUILTIN_COMPARE_CALL:
1757 arg0 = vfp_register[0];
1758 arg1 = vfp_register[1];
1759 arg2 = vfp_register[2];
1760 arg3 = vfp_register[3];
1762 case ExternalReference::BUILTIN_FP_CALL:
1763 arg0 = vfp_register[0];
1764 arg1 = vfp_register[1];
1766 case ExternalReference::BUILTIN_FP_INT_CALL:
1767 arg0 = vfp_register[0];
1768 arg1 = vfp_register[1];
1769 arg2 = get_register(0);
1779 reinterpret_cast<intptr_t
>(redirection->external_function());
1781 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1782 SimulatorRuntimeFPCall target =
1783 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1784 double dval0, dval1;
1786 switch (redirection->type()) {
1787 case ExternalReference::BUILTIN_FP_FP_CALL:
1788 case ExternalReference::BUILTIN_COMPARE_CALL:
1789 GetFpArgs(&dval0, &dval1);
1790 PrintF(
"Call to host function at %p with args %f, %f",
1793 case ExternalReference::BUILTIN_FP_CALL:
1795 PrintF(
"Call to host function at %p with arg %f",
1798 case ExternalReference::BUILTIN_FP_INT_CALL:
1799 GetFpArgs(&dval0, &ival);
1800 PrintF(
"Call to host function at %p with args %f, %d",
1807 if (!stack_aligned) {
1808 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1812 CHECK(stack_aligned);
1813 if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
1814 SimulatorRuntimeFPCall target =
1815 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1816 double result = target(arg0, arg1, arg2, arg3);
1817 SetFpResult(result);
1819 SimulatorRuntimeCall target =
1820 reinterpret_cast<SimulatorRuntimeCall
>(external);
1821 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1824 if (::v8::internal::FLAG_trace_sim) {
1825 PrintF(
"Returned %08x\n", lo_res);
1827 set_register(
r0, lo_res);
1828 set_register(
r1, hi_res);
1830 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1831 SimulatorRuntimeDirectApiCall target =
1832 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1833 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1834 PrintF(
"Call to host function at %p args %08x",
1836 if (!stack_aligned) {
1837 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1841 CHECK(stack_aligned);
1843 if (::v8::internal::FLAG_trace_sim) {
1844 PrintF(
"Returned %p\n", reinterpret_cast<void *>(*result));
1847 }
else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1848 SimulatorRuntimeDirectGetterCall target =
1849 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1850 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1851 PrintF(
"Call to host function at %p args %08x %08x",
1853 if (!stack_aligned) {
1854 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1858 CHECK(stack_aligned);
1860 if (::v8::internal::FLAG_trace_sim) {
1861 PrintF(
"Returned %p\n", reinterpret_cast<void *>(*result));
1866 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1867 SimulatorRuntimeCall target =
1868 reinterpret_cast<SimulatorRuntimeCall
>(external);
1869 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1871 "Call to host function at %p"
1872 "args %08x, %08x, %08x, %08x, %08x, %08x",
1880 if (!stack_aligned) {
1881 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1885 CHECK(stack_aligned);
1886 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1889 if (::v8::internal::FLAG_trace_sim) {
1890 PrintF(
"Returned %08x\n", lo_res);
1892 set_register(
r0, lo_res);
1893 set_register(
r1, hi_res);
1895 set_register(
lr, saved_lr);
1896 set_pc(get_register(
lr));
1900 ArmDebugger dbg(
this);
1906 if (svc >= (1 << 23)) {
1908 if (isWatchedStop(code)) {
1909 IncreaseStopCounter(code);
1913 if (isEnabledStop(code)) {
1914 ArmDebugger dbg(
this);
1930 bool Simulator::isStopInstruction(Instruction* instr) {
1931 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >=
kStopCode);
1935 bool Simulator::isWatchedStop(uint32_t code) {
1937 return code < kNumOfWatchedStops;
1941 bool Simulator::isEnabledStop(uint32_t code) {
1944 return !isWatchedStop(code) ||
1945 !(watched_stops[code].count & kStopDisabledBit);
1949 void Simulator::EnableStop(uint32_t code) {
1950 ASSERT(isWatchedStop(code));
1951 if (!isEnabledStop(code)) {
1952 watched_stops[code].count &= ~kStopDisabledBit;
1957 void Simulator::DisableStop(uint32_t code) {
1958 ASSERT(isWatchedStop(code));
1959 if (isEnabledStop(code)) {
1960 watched_stops[code].count |= kStopDisabledBit;
1965 void Simulator::IncreaseStopCounter(uint32_t code) {
1967 ASSERT(isWatchedStop(code));
1968 if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
1969 PrintF(
"Stop counter for code %i has overflowed.\n"
1970 "Enabling this code and reseting the counter to 0.\n", code);
1971 watched_stops[code].count = 0;
1974 watched_stops[code].count++;
1980 void Simulator::PrintStopInfo(uint32_t code) {
1982 if (!isWatchedStop(code)) {
1983 PrintF(
"Stop not watched.");
1985 const char* state = isEnabledStop(code) ?
"Enabled" :
"Disabled";
1986 int32_t count = watched_stops[code].count & ~kStopDisabledBit;
1989 if (watched_stops[code].desc) {
1990 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1991 code, code, state, count, watched_stops[code].desc);
1993 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
1994 code, code, state, count);
2005 void Simulator::DecodeType01(Instruction* instr) {
2006 int type = instr->TypeValue();
2007 if ((type == 0) && instr->IsSpecialType0()) {
2009 if (instr->Bits(7, 4) == 9) {
2010 if (instr->Bit(24) == 0) {
2013 int rn = instr->RnValue();
2014 int rm = instr->RmValue();
2015 int rs = instr->RsValue();
2016 int32_t rs_val = get_register(rs);
2017 int32_t rm_val = get_register(rm);
2018 if (instr->Bit(23) == 0) {
2019 if (instr->Bit(21) == 0) {
2025 int32_t alu_out = rm_val * rs_val;
2026 set_register(rd, alu_out);
2027 if (instr->HasS()) {
2028 SetNZFlags(alu_out);
2035 Format(instr,
"mla'cond's 'rn, 'rm, 'rs, 'rd");
2049 int rd_lo = instr->RdValue();
2052 if (instr->Bit(22) == 1) {
2053 int64_t left_op =
static_cast<int32_t>(rm_val);
2054 int64_t right_op =
static_cast<int32_t>(rs_val);
2055 uint64_t result = left_op * right_op;
2056 hi_res =
static_cast<int32_t>(result >> 32);
2057 lo_res =
static_cast<int32_t>(result & 0xffffffff);
2060 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
2061 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
2062 uint64_t result = left_op * right_op;
2063 hi_res =
static_cast<int32_t>(result >> 32);
2064 lo_res =
static_cast<int32_t>(result & 0xffffffff);
2066 set_register(rd_lo, lo_res);
2067 set_register(rd_hi, hi_res);
2068 if (instr->HasS()) {
2077 int rd = instr->RdValue();
2078 int rn = instr->RnValue();
2079 int32_t rn_val = get_register(rn);
2081 if (instr->Bit(22) == 0) {
2082 int rm = instr->RmValue();
2083 int32_t rm_val = get_register(rm);
2084 switch (instr->PUField()) {
2090 set_register(rn, rn_val);
2098 set_register(rn, rn_val);
2105 if (instr->HasW()) {
2106 set_register(rn, rn_val);
2114 if (instr->HasW()) {
2115 set_register(rn, rn_val);
2126 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2127 switch (instr->PUField()) {
2133 set_register(rn, rn_val);
2141 set_register(rn, rn_val);
2148 if (instr->HasW()) {
2149 set_register(rn, rn_val);
2157 if (instr->HasW()) {
2158 set_register(rn, rn_val);
2169 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2171 if (instr->HasH()) {
2173 int32_t value1 = get_register(rd);
2174 int32_t value2 = get_register(rd+1);
2175 WriteDW(addr, value1, value2);
2178 int* rn_data = ReadDW(addr);
2179 set_dw_register(rd, rn_data);
2181 }
else if (instr->HasH()) {
2182 if (instr->HasSign()) {
2183 if (instr->HasL()) {
2184 int16_t val = ReadH(addr, instr);
2185 set_register(rd, val);
2187 int16_t val = get_register(rd);
2188 WriteH(addr, val, instr);
2191 if (instr->HasL()) {
2192 uint16_t val = ReadHU(addr, instr);
2193 set_register(rd, val);
2196 WriteH(addr, val, instr);
2201 ASSERT(instr->HasSign());
2203 int8_t val = ReadB(addr);
2204 set_register(rd, val);
2208 }
else if ((type == 0) && instr->IsMiscType0()) {
2209 if (instr->Bits(22, 21) == 1) {
2210 int rm = instr->RmValue();
2211 switch (instr->BitField(7, 4)) {
2213 set_pc(get_register(rm));
2216 uint32_t old_pc = get_pc();
2217 set_pc(get_register(rm));
2222 ArmDebugger dbg(
this);
2223 PrintF(
"Simulator hit BKPT.\n");
2230 }
else if (instr->Bits(22, 21) == 3) {
2231 int rm = instr->RmValue();
2232 int rd = instr->RdValue();
2233 switch (instr->BitField(7, 4)) {
2235 uint32_t bits = get_register(rm);
2236 int leading_zeros = 0;
2240 while ((bits & 0x80000000u) == 0) {
2245 set_register(rd, leading_zeros);
2252 PrintF(
"%08x\n", instr->InstructionBits());
2256 int rd = instr->RdValue();
2257 int rn = instr->RnValue();
2258 int32_t rn_val = get_register(rn);
2260 bool shifter_carry_out = 0;
2262 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2264 ASSERT(instr->TypeValue() == 1);
2265 shifter_operand = GetImm(instr, &shifter_carry_out);
2269 switch (instr->OpcodeField()) {
2273 alu_out = rn_val & shifter_operand;
2274 set_register(rd, alu_out);
2275 if (instr->HasS()) {
2276 SetNZFlags(alu_out);
2277 SetCFlag(shifter_carry_out);
2285 alu_out = rn_val ^ shifter_operand;
2286 set_register(rd, alu_out);
2287 if (instr->HasS()) {
2288 SetNZFlags(alu_out);
2289 SetCFlag(shifter_carry_out);
2297 alu_out = rn_val - shifter_operand;
2298 set_register(rd, alu_out);
2299 if (instr->HasS()) {
2300 SetNZFlags(alu_out);
2301 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2302 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2310 alu_out = shifter_operand - rn_val;
2311 set_register(rd, alu_out);
2312 if (instr->HasS()) {
2313 SetNZFlags(alu_out);
2314 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2315 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val,
false));
2323 alu_out = rn_val + shifter_operand;
2324 set_register(rd, alu_out);
2325 if (instr->HasS()) {
2326 SetNZFlags(alu_out);
2327 SetCFlag(CarryFrom(rn_val, shifter_operand));
2328 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2336 alu_out = rn_val + shifter_operand + GetCarry();
2337 set_register(rd, alu_out);
2338 if (instr->HasS()) {
2339 SetNZFlags(alu_out);
2340 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2341 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2347 Format(instr,
"sbc'cond's 'rd, 'rn, 'shift_rm");
2348 Format(instr,
"sbc'cond's 'rd, 'rn, 'imm");
2353 Format(instr,
"rsc'cond's 'rd, 'rn, 'shift_rm");
2354 Format(instr,
"rsc'cond's 'rd, 'rn, 'imm");
2359 if (instr->HasS()) {
2362 alu_out = rn_val & shifter_operand;
2363 SetNZFlags(alu_out);
2364 SetCFlag(shifter_carry_out);
2367 alu_out = instr->ImmedMovwMovtValue();
2368 set_register(rd, alu_out);
2374 if (instr->HasS()) {
2377 alu_out = rn_val ^ shifter_operand;
2378 SetNZFlags(alu_out);
2379 SetCFlag(shifter_carry_out);
2389 if (instr->HasS()) {
2392 alu_out = rn_val - shifter_operand;
2393 SetNZFlags(alu_out);
2394 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2395 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2398 alu_out = (get_register(rd) & 0xffff) |
2399 (instr->ImmedMovwMovtValue() << 16);
2400 set_register(rd, alu_out);
2406 if (instr->HasS()) {
2409 alu_out = rn_val + shifter_operand;
2410 SetNZFlags(alu_out);
2411 SetCFlag(!CarryFrom(rn_val, shifter_operand));
2412 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2424 alu_out = rn_val | shifter_operand;
2425 set_register(rd, alu_out);
2426 if (instr->HasS()) {
2427 SetNZFlags(alu_out);
2428 SetCFlag(shifter_carry_out);
2436 alu_out = shifter_operand;
2437 set_register(rd, alu_out);
2438 if (instr->HasS()) {
2439 SetNZFlags(alu_out);
2440 SetCFlag(shifter_carry_out);
2448 alu_out = rn_val & ~shifter_operand;
2449 set_register(rd, alu_out);
2450 if (instr->HasS()) {
2451 SetNZFlags(alu_out);
2452 SetCFlag(shifter_carry_out);
2460 alu_out = ~shifter_operand;
2461 set_register(rd, alu_out);
2462 if (instr->HasS()) {
2463 SetNZFlags(alu_out);
2464 SetCFlag(shifter_carry_out);
2478 void Simulator::DecodeType2(Instruction* instr) {
2479 int rd = instr->RdValue();
2480 int rn = instr->RnValue();
2481 int32_t rn_val = get_register(rn);
2482 int32_t im_val = instr->Offset12Value();
2484 switch (instr->PUField()) {
2490 set_register(rn, rn_val);
2498 set_register(rn, rn_val);
2505 if (instr->HasW()) {
2506 set_register(rn, rn_val);
2514 if (instr->HasW()) {
2515 set_register(rn, rn_val);
2524 if (instr->HasB()) {
2525 if (instr->HasL()) {
2526 byte val = ReadBU(addr);
2527 set_register(rd, val);
2529 byte val = get_register(rd);
2533 if (instr->HasL()) {
2534 set_register(rd, ReadW(addr, instr));
2536 WriteW(addr, get_register(rd), instr);
2542 void Simulator::DecodeType3(Instruction* instr) {
2543 int rd = instr->RdValue();
2544 int rn = instr->RnValue();
2545 int32_t rn_val = get_register(rn);
2546 bool shifter_carry_out = 0;
2547 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2549 switch (instr->PUField()) {
2552 Format(instr,
"'memop'cond'b 'rd, ['rn], -'shift_rm");
2557 if (instr->HasW()) {
2558 ASSERT(instr->Bits(5, 4) == 0x1);
2560 if (instr->Bit(22) == 0x1) {
2561 int32_t sat_pos = instr->Bits(20, 16);
2562 int32_t sat_val = (1 << sat_pos) - 1;
2563 int32_t shift = instr->Bits(11, 7);
2564 int32_t shift_type = instr->Bit(6);
2565 int32_t rm_val = get_register(instr->RmValue());
2566 if (shift_type == 0) {
2574 if (rm_val > sat_val) {
2576 }
else if (rm_val < 0) {
2579 set_register(rd, rm_val);
2585 Format(instr,
"'memop'cond'b 'rd, ['rn], +'shift_rm");
2592 addr = rn_val - shifter_operand;
2593 if (instr->HasW()) {
2594 set_register(rn, addr);
2599 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2600 uint32_t widthminus1 =
static_cast<uint32_t
>(instr->Bits(20, 16));
2601 uint32_t lsbit =
static_cast<uint32_t
>(instr->Bits(11, 7));
2602 uint32_t msbit = widthminus1 + lsbit;
2604 if (instr->Bit(22)) {
2607 static_cast<uint32_t
>(get_register(instr->RmValue()));
2608 uint32_t extr_val = rm_val << (31 - msbit);
2609 extr_val = extr_val >> (31 - widthminus1);
2610 set_register(instr->RdValue(), extr_val);
2613 int32_t rm_val = get_register(instr->RmValue());
2614 int32_t extr_val = rm_val << (31 - msbit);
2615 extr_val = extr_val >> (31 - widthminus1);
2616 set_register(instr->RdValue(), extr_val);
2622 }
else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2623 uint32_t lsbit =
static_cast<uint32_t
>(instr->Bits(11, 7));
2624 uint32_t msbit =
static_cast<uint32_t
>(instr->Bits(20, 16));
2625 if (msbit >= lsbit) {
2628 static_cast<uint32_t
>(get_register(instr->RdValue()));
2629 uint32_t bitcount = msbit - lsbit + 1;
2630 uint32_t mask = (1 << bitcount) - 1;
2631 rd_val &= ~(mask << lsbit);
2632 if (instr->RmValue() != 15) {
2635 static_cast<uint32_t
>(get_register(instr->RmValue()));
2637 rd_val |= rm_val << lsbit;
2639 set_register(instr->RdValue(), rd_val);
2646 addr = rn_val + shifter_operand;
2647 if (instr->HasW()) {
2648 set_register(rn, addr);
2658 if (instr->HasB()) {
2659 if (instr->HasL()) {
2660 uint8_t
byte = ReadB(addr);
2661 set_register(rd, byte);
2663 uint8_t
byte = get_register(rd);
2667 if (instr->HasL()) {
2668 set_register(rd, ReadW(addr, instr));
2670 WriteW(addr, get_register(rd), instr);
2676 void Simulator::DecodeType4(Instruction* instr) {
2677 ASSERT(instr->Bit(22) == 0);
2678 if (instr->HasL()) {
2680 HandleRList(instr,
true);
2683 HandleRList(instr,
false);
2688 void Simulator::DecodeType5(Instruction* instr) {
2690 int off = (instr->SImmed24Value() << 2);
2691 intptr_t pc_address = get_pc();
2692 if (instr->HasLink()) {
2695 int pc_reg = get_register(
pc);
2696 set_pc(pc_reg + off);
2700 void Simulator::DecodeType6(Instruction* instr) {
2701 DecodeType6CoprocessorIns(instr);
2705 void Simulator::DecodeType7(Instruction* instr) {
2706 if (instr->Bit(24) == 1) {
2707 SoftwareInterrupt(instr);
2709 DecodeTypeVFP(instr);
2729 void Simulator::DecodeTypeVFP(Instruction* instr) {
2730 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2731 ASSERT(instr->Bits(11, 9) == 0x5);
2738 if (instr->Bit(4) == 0) {
2739 if (instr->Opc1Value() == 0x7) {
2741 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2743 if (instr->SzValue() == 0x1) {
2746 set_d_register_from_double(d, get_double_from_d_register(m));
2750 set_s_register_from_float(d, get_float_from_s_register(m));
2752 }
else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2754 double dm_value = get_double_from_d_register(vm);
2755 double dd_value = fabs(dm_value);
2756 set_d_register_from_double(vd, dd_value);
2757 }
else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2759 double dm_value = get_double_from_d_register(vm);
2760 double dd_value = -dm_value;
2761 set_d_register_from_double(vd, dd_value);
2762 }
else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2763 DecodeVCVTBetweenDoubleAndSingle(instr);
2764 }
else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2765 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2766 }
else if (((instr->Opc2Value() >> 1) == 0x6) &&
2767 (instr->Opc3Value() & 0x1)) {
2768 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2769 }
else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2770 (instr->Opc3Value() & 0x1)) {
2772 }
else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2774 double dm_value = get_double_from_d_register(vm);
2775 double dd_value = sqrt(dm_value);
2776 set_d_register_from_double(vd, dd_value);
2777 }
else if (instr->Opc3Value() == 0x0) {
2779 if (instr->SzValue() == 0x1) {
2780 set_d_register_from_double(vd, instr->DoubleImmedVmov());
2787 }
else if (instr->Opc1Value() == 0x3) {
2788 if (instr->SzValue() != 0x1) {
2792 if (instr->Opc3Value() & 0x1) {
2794 double dn_value = get_double_from_d_register(vn);
2795 double dm_value = get_double_from_d_register(vm);
2796 double dd_value = dn_value - dm_value;
2797 set_d_register_from_double(vd, dd_value);
2800 double dn_value = get_double_from_d_register(vn);
2801 double dm_value = get_double_from_d_register(vm);
2802 double dd_value = dn_value + dm_value;
2803 set_d_register_from_double(vd, dd_value);
2805 }
else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2807 if (instr->SzValue() != 0x1) {
2811 double dn_value = get_double_from_d_register(vn);
2812 double dm_value = get_double_from_d_register(vm);
2813 double dd_value = dn_value * dm_value;
2814 set_d_register_from_double(vd, dd_value);
2815 }
else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
2817 if (instr->SzValue() != 0x1) {
2821 double dn_value = get_double_from_d_register(vn);
2822 double dm_value = get_double_from_d_register(vm);
2823 double dd_value = dn_value / dm_value;
2824 div_zero_vfp_flag_ = (dm_value == 0);
2825 set_d_register_from_double(vd, dd_value);
2830 if ((instr->VCValue() == 0x0) &&
2831 (instr->VAValue() == 0x0)) {
2832 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
2833 }
else if ((instr->VLValue() == 0x1) &&
2834 (instr->VCValue() == 0x0) &&
2835 (instr->VAValue() == 0x7) &&
2836 (instr->Bits(19, 16) == 0x1)) {
2838 uint32_t rt = instr->RtValue();
2840 Copy_FPSCR_to_APSR();
2843 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
2844 (z_flag_FPSCR_ << 30) |
2845 (c_flag_FPSCR_ << 29) |
2846 (v_flag_FPSCR_ << 28) |
2847 (inexact_vfp_flag_ << 4) |
2848 (underflow_vfp_flag_ << 3) |
2849 (overflow_vfp_flag_ << 2) |
2850 (div_zero_vfp_flag_ << 1) |
2851 (inv_op_vfp_flag_ << 0) |
2852 (FPSCR_rounding_mode_);
2853 set_register(rt, fpscr);
2855 }
else if ((instr->VLValue() == 0x0) &&
2856 (instr->VCValue() == 0x0) &&
2857 (instr->VAValue() == 0x7) &&
2858 (instr->Bits(19, 16) == 0x1)) {
2860 uint32_t rt = instr->RtValue();
2864 uint32_t rt_value = get_register(rt);
2865 n_flag_FPSCR_ = (rt_value >> 31) & 1;
2866 z_flag_FPSCR_ = (rt_value >> 30) & 1;
2867 c_flag_FPSCR_ = (rt_value >> 29) & 1;
2868 v_flag_FPSCR_ = (rt_value >> 28) & 1;
2869 inexact_vfp_flag_ = (rt_value >> 4) & 1;
2870 underflow_vfp_flag_ = (rt_value >> 3) & 1;
2871 overflow_vfp_flag_ = (rt_value >> 2) & 1;
2872 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
2873 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
2874 FPSCR_rounding_mode_ =
2884 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
2885 Instruction* instr) {
2886 ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
2887 (instr->VAValue() == 0x0));
2889 int t = instr->RtValue();
2891 bool to_arm_register = (instr->VLValue() == 0x1);
2893 if (to_arm_register) {
2894 int32_t int_value = get_sinteger_from_s_register(n);
2895 set_register(t, int_value);
2897 int32_t rs_val = get_register(t);
2898 set_s_register_from_sinteger(n, rs_val);
2903 void Simulator::DecodeVCMP(Instruction* instr) {
2904 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
2905 ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2906 (instr->Opc3Value() & 0x1));
2910 if (instr->SzValue() == 1) {
2914 int d = instr->VFPDRegValue(precision);
2916 if (instr->Opc2Value() == 0x4) {
2917 m = instr->VFPMRegValue(precision);
2921 double dd_value = get_double_from_d_register(d);
2922 double dm_value = 0.0;
2923 if (instr->Opc2Value() == 0x4) {
2924 dm_value = get_double_from_d_register(m);
2928 if (instr->Bit(7) == 1) {
2929 if (
isnan(dd_value)) {
2930 inv_op_vfp_flag_ =
true;
2934 Compute_FPSCR_Flags(dd_value, dm_value);
2941 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
2942 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
2943 ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
2947 if (instr->SzValue() == 1) {
2952 int dst = instr->VFPDRegValue(dst_precision);
2953 int src = instr->VFPMRegValue(src_precision);
2956 double val = get_double_from_d_register(src);
2957 set_s_register_from_float(dst, static_cast<float>(val));
2959 float val = get_float_from_s_register(src);
2960 set_d_register_from_double(dst, static_cast<double>(val));
2968 double max_uint =
static_cast<double>(0xffffffffu);
2969 double max_int =
static_cast<double>(
kMaxInt);
2970 double min_int =
static_cast<double>(
kMinInt);
2981 return unsigned_ ? (val >= (max_uint + 0.5)) ||
2983 : (val >= (max_int + 0.5)) ||
2984 (val < (min_int - 0.5));
2987 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2989 : (val >= (max_int + 1.0)) ||
2993 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2995 : (val >= (max_int + 1.0)) ||
2996 (val <= (min_int - 1.0));
3006 int VFPConversionSaturate(
double val,
bool unsigned_res) {
3011 return (val < 0) ? 0 : 0xffffffffu;
3019 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3020 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3021 (instr->Bits(27, 23) == 0x1D));
3022 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3023 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3026 bool to_integer = (instr->Bit(18) == 1);
3040 int src = instr->VFPMRegValue(src_precision);
3048 bool unsigned_integer = (instr->Bit(16) == 0);
3051 double val = double_precision ? get_double_from_d_register(src)
3052 : get_float_from_s_register(src);
3054 int temp = unsigned_integer ?
static_cast<uint32_t
>(val)
3055 : static_cast<int32_t>(val);
3057 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3060 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
3063 inexact_vfp_flag_ = (abs_diff != 0);
3065 if (inv_op_vfp_flag_) {
3066 temp = VFPConversionSaturate(val, unsigned_integer);
3070 int val_sign = (val > 0) ? 1 : -1;
3071 if (abs_diff > 0.5) {
3073 }
else if (abs_diff == 0.5) {
3075 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3081 temp = temp > val ? temp - 1 : temp;
3094 set_s_register_from_sinteger(dst, temp);
3097 bool unsigned_integer = (instr->Bit(7) == 0);
3099 int dst = instr->VFPDRegValue(src_precision);
3102 int val = get_sinteger_from_s_register(src);
3105 if (unsigned_integer) {
3106 set_d_register_from_double(dst,
3107 static_cast<double>((uint32_t)val));
3109 set_d_register_from_double(dst, static_cast<double>(val));
3112 if (unsigned_integer) {
3113 set_s_register_from_float(dst,
3114 static_cast<float>((uint32_t)val));
3116 set_s_register_from_float(dst, static_cast<float>(val));
3129 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3130 ASSERT((instr->TypeValue() == 6));
3132 if (instr->CoprocessorValue() == 0xA) {
3133 switch (instr->OpcodeValue()) {
3138 int rn = instr->RnValue();
3140 int offset = instr->Immed8Value();
3141 if (!instr->HasU()) {
3145 int32_t address = get_register(rn) + 4 * offset;
3146 if (instr->HasL()) {
3148 set_s_register_from_sinteger(vd, ReadW(address, instr));
3151 WriteW(address, get_sinteger_from_s_register(vd), instr);
3167 }
else if (instr->CoprocessorValue() == 0xB) {
3168 switch (instr->OpcodeValue()) {
3171 if (instr->Bits(7, 4) != 0x1) {
3174 int rt = instr->RtValue();
3175 int rn = instr->RnValue();
3176 int vm = instr->VmValue();
3177 if (instr->HasL()) {
3178 int32_t rt_int_value = get_sinteger_from_s_register(2*vm);
3179 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1);
3181 set_register(rt, rt_int_value);
3182 set_register(rn, rn_int_value);
3184 int32_t rs_val = get_register(rt);
3185 int32_t rn_val = get_register(rn);
3187 set_s_register_from_sinteger(2*vm, rs_val);
3188 set_s_register_from_sinteger((2*vm+1), rn_val);
3194 int rn = instr->RnValue();
3195 int vd = instr->VdValue();
3196 int offset = instr->Immed8Value();
3197 if (!instr->HasU()) {
3200 int32_t address = get_register(rn) + 4 * offset;
3201 if (instr->HasL()) {
3203 set_s_register_from_sinteger(2*vd, ReadW(address, instr));
3204 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr));
3207 WriteW(address, get_sinteger_from_s_register(2*vd), instr);
3208 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr);
3228 void Simulator::InstructionDecode(Instruction* instr) {
3229 if (v8::internal::FLAG_check_icache) {
3230 CheckICache(isolate_->simulator_i_cache(), instr);
3232 pc_modified_ =
false;
3233 if (::v8::internal::FLAG_trace_sim) {
3238 dasm.InstructionDecode(buffer,
3239 reinterpret_cast<byte*>(instr));
3240 PrintF(
" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.
start());
3244 }
else if (ConditionallyExecute(instr)) {
3245 switch (instr->TypeValue()) {
3248 DecodeType01(instr);
3282 }
else if (instr->IsStop()) {
3285 if (!pc_modified_) {
3286 set_register(
pc, reinterpret_cast<int32_t>(instr)
3292 void Simulator::Execute() {
3295 int program_counter = get_pc();
3297 if (::v8::internal::FLAG_stop_sim_at == 0) {
3300 while (program_counter != end_sim_pc) {
3301 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3303 InstructionDecode(instr);
3304 program_counter = get_pc();
3309 while (program_counter != end_sim_pc) {
3310 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3312 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3313 ArmDebugger dbg(
this);
3316 InstructionDecode(instr);
3318 program_counter = get_pc();
3324 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
3326 va_start(parameters, argument_count);
3330 ASSERT(argument_count >= 4);
3331 set_register(
r0, va_arg(parameters,
int32_t));
3332 set_register(
r1, va_arg(parameters,
int32_t));
3333 set_register(
r2, va_arg(parameters,
int32_t));
3334 set_register(
r3, va_arg(parameters,
int32_t));
3337 int original_stack = get_register(
sp);
3339 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t));
3344 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
3345 for (
int i = 4; i < argument_count; i++) {
3346 stack_argument[i - 4] = va_arg(parameters,
int32_t);
3349 set_register(
sp, entry_stack);
3352 set_register(
pc, reinterpret_cast<int32_t>(entry));
3356 set_register(
lr, end_sim_pc);
3372 int32_t callee_saved_value = icount_;
3373 set_register(
r4, callee_saved_value);
3374 set_register(
r5, callee_saved_value);
3375 set_register(
r6, callee_saved_value);
3376 set_register(
r7, callee_saved_value);
3377 set_register(
r8, callee_saved_value);
3378 set_register(
r9, callee_saved_value);
3379 set_register(
r10, callee_saved_value);
3380 set_register(
r11, callee_saved_value);
3386 CHECK_EQ(callee_saved_value, get_register(
r4));
3387 CHECK_EQ(callee_saved_value, get_register(
r5));
3388 CHECK_EQ(callee_saved_value, get_register(
r6));
3389 CHECK_EQ(callee_saved_value, get_register(
r7));
3390 CHECK_EQ(callee_saved_value, get_register(
r8));
3391 CHECK_EQ(callee_saved_value, get_register(
r9));
3396 set_register(
r4, r4_val);
3397 set_register(
r5, r5_val);
3398 set_register(
r6, r6_val);
3399 set_register(
r7, r7_val);
3400 set_register(
r8, r8_val);
3401 set_register(
r9, r9_val);
3402 set_register(
r10, r10_val);
3403 set_register(
r11, r11_val);
3407 set_register(
sp, original_stack);
3414 uintptr_t Simulator::PushAddress(uintptr_t address) {
3415 int new_sp = get_register(
sp) -
sizeof(uintptr_t);
3416 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
3417 *stack_slot = address;
3418 set_register(
sp, new_sp);
3423 uintptr_t Simulator::PopAddress() {
3424 int current_sp = get_register(
sp);
3425 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
3426 uintptr_t address = *stack_slot;
3427 set_register(
sp, current_sp +
sizeof(uintptr_t));
3433 #endif // USE_SIMULATOR
3435 #endif // V8_TARGET_ARCH_ARM
#define CHECK_EQ(expected, value)
void PrintF(const char *format,...)
static const char * Name(int reg, bool is_double)
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)
static int Number(const char *name)
#define OFFSET_OF(type, field)
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
#define ASSERT_EQ(v1, v2)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static int ActivationFrameAlignment()
const uint32_t kVFPRoundingModeMask
void DeleteArray(T *array)
const int kNumVFPDoubleRegisters