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;
279 while (!done && !sim_->has_bad_pc()) {
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 template<
class InputType,
int register_size>
949 void Simulator::SetVFPRegister(
int reg_index,
const InputType& value) {
951 if (register_size == 1)
ASSERT(reg_index < num_s_registers);
952 if (register_size == 2)
ASSERT(reg_index < num_d_registers);
954 char buffer[register_size *
sizeof(vfp_register[0])];
955 memcpy(buffer, &value, register_size *
sizeof(vfp_register[0]));
956 memcpy(&vfp_register[reg_index * register_size], buffer,
957 register_size *
sizeof(vfp_register[0]));
961 template<
class ReturnType,
int register_size>
962 ReturnType Simulator::GetFromVFPRegister(
int reg_index) {
964 if (register_size == 1)
ASSERT(reg_index < num_s_registers);
965 if (register_size == 2)
ASSERT(reg_index < num_d_registers);
967 ReturnType value = 0;
968 char buffer[register_size *
sizeof(vfp_register[0])];
969 memcpy(buffer, &vfp_register[register_size * reg_index],
970 register_size *
sizeof(vfp_register[0]));
971 memcpy(&value, buffer, register_size *
sizeof(vfp_register[0]));
978 void Simulator::GetFpArgs(
double* x,
double* y) {
979 if (use_eabi_hardfloat()) {
980 *x = vfp_register[0];
981 *y = vfp_register[1];
985 char buffer[
sizeof(*x)];
987 memcpy(buffer, registers_,
sizeof(*x));
988 memcpy(x, buffer,
sizeof(*x));
990 memcpy(buffer, registers_ + 2,
sizeof(*y));
991 memcpy(y, buffer,
sizeof(*y));
997 void Simulator::GetFpArgs(
double* x) {
998 if (use_eabi_hardfloat()) {
999 *x = vfp_register[0];
1003 char buffer[
sizeof(*x)];
1005 memcpy(buffer, registers_,
sizeof(*x));
1006 memcpy(x, buffer,
sizeof(*x));
1013 void Simulator::GetFpArgs(
double* x,
int32_t* y) {
1014 if (use_eabi_hardfloat()) {
1015 *x = vfp_register[0];
1020 char buffer[
sizeof(*x)];
1022 memcpy(buffer, registers_,
sizeof(*x));
1023 memcpy(x, buffer,
sizeof(*x));
1025 memcpy(buffer, registers_ + 2,
sizeof(*y));
1026 memcpy(y, buffer,
sizeof(*y));
1032 void Simulator::SetFpResult(
const double& result) {
1033 if (use_eabi_hardfloat()) {
1034 char buffer[2 *
sizeof(vfp_register[0])];
1035 memcpy(buffer, &result,
sizeof(buffer));
1037 memcpy(vfp_register, buffer,
sizeof(buffer));
1039 char buffer[2 *
sizeof(registers_[0])];
1040 memcpy(buffer, &result,
sizeof(buffer));
1042 memcpy(registers_, buffer,
sizeof(buffer));
1047 void Simulator::TrashCallerSaveRegisters() {
1049 registers_[2] = 0x50Bad4
U;
1050 registers_[3] = 0x50Bad4
U;
1051 registers_[12] = 0x50Bad4
U;
1068 int Simulator::ReadW(
int32_t addr, Instruction* instr) {
1069 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1070 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1075 reinterpret_cast<intptr_t>(instr));
1082 void Simulator::WriteW(
int32_t addr,
int value, 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 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1100 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1103 reinterpret_cast<intptr_t>(instr));
1111 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1115 PrintF(
"Unaligned signed halfword read at 0x%08x\n", addr);
1122 void Simulator::WriteH(
int32_t addr,
uint16_t value, Instruction* instr) {
1123 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1127 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1130 reinterpret_cast<intptr_t>(instr));
1136 void Simulator::WriteH(
int32_t addr,
int16_t value, Instruction* instr) {
1137 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1143 reinterpret_cast<intptr_t>(instr));
1149 uint8_t Simulator::ReadBU(
int32_t addr) {
1150 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1155 int8_t Simulator::ReadB(
int32_t addr) {
1156 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1161 void Simulator::WriteB(
int32_t addr, uint8_t value) {
1162 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1167 void Simulator::WriteB(
int32_t addr, int8_t value) {
1168 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1174 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1178 PrintF(
"Unaligned read at 0x%08x\n", addr);
1186 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1191 PrintF(
"Unaligned write at 0x%08x\n", addr);
1198 uintptr_t Simulator::StackLimit()
const {
1201 return reinterpret_cast<uintptr_t
>(stack_) + 1024;
1206 void Simulator::Format(Instruction* instr,
const char* format) {
1207 PrintF(
"Simulator found unsupported instruction:\n 0x%08x: %s\n",
1208 reinterpret_cast<intptr_t>(instr), format);
1215 bool Simulator::ConditionallyExecute(Instruction* instr) {
1216 switch (instr->ConditionField()) {
1217 case eq:
return z_flag_;
1218 case ne:
return !z_flag_;
1219 case cs:
return c_flag_;
1220 case cc:
return !c_flag_;
1221 case mi:
return n_flag_;
1222 case pl:
return !n_flag_;
1223 case vs:
return v_flag_;
1224 case vc:
return !v_flag_;
1225 case hi:
return c_flag_ && !z_flag_;
1226 case ls:
return !c_flag_ || z_flag_;
1227 case ge:
return n_flag_ == v_flag_;
1228 case lt:
return n_flag_ != v_flag_;
1229 case gt:
return !z_flag_ && (n_flag_ == v_flag_);
1230 case le:
return z_flag_ || (n_flag_ != v_flag_);
1231 case al:
return true;
1239 void Simulator::SetNZFlags(
int32_t val) {
1240 n_flag_ = (val < 0);
1241 z_flag_ = (val == 0);
1246 void Simulator::SetCFlag(
bool val) {
1252 void Simulator::SetVFlag(
bool val) {
1259 uint32_t uleft =
static_cast<uint32_t
>(left);
1260 uint32_t uright =
static_cast<uint32_t
>(right);
1261 uint32_t urest = 0xffffffff
U - uleft;
1263 return (uright > urest) ||
1264 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1270 uint32_t uleft =
static_cast<uint32_t
>(left);
1271 uint32_t uright =
static_cast<uint32_t
>(right);
1273 return (uright > uleft);
1278 bool Simulator::OverflowFrom(
int32_t alu_out,
1283 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1285 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1288 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1290 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1297 void Simulator::Compute_FPSCR_Flags(
double val1,
double val2) {
1299 n_flag_FPSCR_ =
false;
1300 z_flag_FPSCR_ =
false;
1301 c_flag_FPSCR_ =
true;
1302 v_flag_FPSCR_ =
true;
1304 }
else if (val1 == val2) {
1305 n_flag_FPSCR_ =
false;
1306 z_flag_FPSCR_ =
true;
1307 c_flag_FPSCR_ =
true;
1308 v_flag_FPSCR_ =
false;
1309 }
else if (val1 < val2) {
1310 n_flag_FPSCR_ =
true;
1311 z_flag_FPSCR_ =
false;
1312 c_flag_FPSCR_ =
false;
1313 v_flag_FPSCR_ =
false;
1316 n_flag_FPSCR_ =
false;
1317 z_flag_FPSCR_ =
false;
1318 c_flag_FPSCR_ =
true;
1319 v_flag_FPSCR_ =
false;
1324 void Simulator::Copy_FPSCR_to_APSR() {
1325 n_flag_ = n_flag_FPSCR_;
1326 z_flag_ = z_flag_FPSCR_;
1327 c_flag_ = c_flag_FPSCR_;
1328 v_flag_ = v_flag_FPSCR_;
1334 int32_t Simulator::GetShiftRm(Instruction* instr,
bool* carry_out) {
1335 ShiftOp shift = instr->ShiftField();
1336 int shift_amount = instr->ShiftAmountValue();
1337 int32_t result = get_register(instr->RmValue());
1338 if (instr->Bit(4) == 0) {
1340 if ((shift ==
ROR) && (shift_amount == 0)) {
1343 }
else if (((shift ==
LSR) || (shift ==
ASR)) && (shift_amount == 0)) {
1348 if (shift_amount == 0) {
1350 result = 0xffffffff;
1357 result >>= (shift_amount - 1);
1358 *carry_out = (result & 1) == 1;
1365 if (shift_amount == 0) {
1366 *carry_out = c_flag_;
1368 result <<= (shift_amount - 1);
1369 *carry_out = (result < 0);
1376 if (shift_amount == 0) {
1378 *carry_out = c_flag_;
1380 uint32_t uresult =
static_cast<uint32_t
>(result);
1381 uresult >>= (shift_amount - 1);
1382 *carry_out = (uresult & 1) == 1;
1384 result =
static_cast<int32_t>(uresult);
1401 int rs = instr->RsValue();
1402 shift_amount = get_register(rs) &0xff;
1405 if (shift_amount == 0) {
1406 *carry_out = c_flag_;
1407 }
else if (shift_amount < 32) {
1408 result >>= (shift_amount - 1);
1409 *carry_out = (result & 1) == 1;
1412 ASSERT(shift_amount >= 32);
1415 result = 0xffffffff;
1425 if (shift_amount == 0) {
1426 *carry_out = c_flag_;
1427 }
else if (shift_amount < 32) {
1428 result <<= (shift_amount - 1);
1429 *carry_out = (result < 0);
1431 }
else if (shift_amount == 32) {
1432 *carry_out = (result & 1) == 1;
1435 ASSERT(shift_amount > 32);
1443 if (shift_amount == 0) {
1444 *carry_out = c_flag_;
1445 }
else if (shift_amount < 32) {
1446 uint32_t uresult =
static_cast<uint32_t
>(result);
1447 uresult >>= (shift_amount - 1);
1448 *carry_out = (uresult & 1) == 1;
1450 result =
static_cast<int32_t>(uresult);
1451 }
else if (shift_amount == 32) {
1452 *carry_out = (result < 0);
1478 int32_t Simulator::GetImm(Instruction* instr,
bool* carry_out) {
1479 int rotate = instr->RotateValue() * 2;
1480 int immed8 = instr->Immed8Value();
1481 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1482 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1487 static int count_bits(
int bit_vector) {
1489 while (bit_vector != 0) {
1490 if ((bit_vector & 1) != 0) {
1499 void Simulator::ProcessPUW(Instruction* instr,
1502 intptr_t* start_address,
1503 intptr_t* end_address) {
1504 int rn = instr->RnValue();
1505 int32_t rn_val = get_register(rn);
1506 switch (instr->PUField()) {
1512 *start_address = rn_val;
1513 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1514 rn_val = rn_val + (num_regs * reg_size);
1518 *start_address = rn_val - (num_regs * reg_size);
1519 *end_address = rn_val - reg_size;
1520 rn_val = *start_address;
1524 *start_address = rn_val + reg_size;
1525 *end_address = rn_val + (num_regs * reg_size);
1526 rn_val = *end_address;
1534 if (instr->HasW()) {
1535 set_register(rn, rn_val);
1540 void Simulator::HandleRList(Instruction* instr,
bool load) {
1541 int rlist = instr->RlistValue();
1542 int num_regs = count_bits(rlist);
1544 intptr_t start_address = 0;
1545 intptr_t end_address = 0;
1546 ProcessPUW(instr, num_regs,
kPointerSize, &start_address, &end_address);
1548 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1550 ASSERT(start_address > 8191 || start_address < 0);
1552 while (rlist != 0) {
1553 if ((rlist & 1) != 0) {
1555 set_register(reg, *address);
1557 *address = get_register(reg);
1564 ASSERT(end_address == ((intptr_t)address) - 4);
1569 void Simulator::HandleVList(Instruction* instr) {
1574 bool load = (instr->VLValue() == 0x1);
1578 vd = instr->VFPDRegValue(precision);
1580 num_regs = instr->Immed8Value();
1582 num_regs = instr->Immed8Value() / 2;
1585 intptr_t start_address = 0;
1586 intptr_t end_address = 0;
1587 ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address);
1589 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1590 for (
int reg = vd; reg < vd + num_regs; reg++) {
1593 set_s_register_from_sinteger(
1594 reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1596 WriteW(reinterpret_cast<int32_t>(address),
1597 get_sinteger_from_s_register(reg), instr);
1602 set_s_register_from_sinteger(
1603 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1604 set_s_register_from_sinteger(
1605 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr));
1607 WriteW(reinterpret_cast<int32_t>(address),
1608 get_sinteger_from_s_register(2 * reg), instr);
1609 WriteW(reinterpret_cast<int32_t>(address + 1),
1610 get_sinteger_from_s_register(2 * reg + 1), instr);
1615 ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1625 typedef int64_t (*SimulatorRuntimeCall)(
int32_t arg0,
1631 typedef double (*SimulatorRuntimeFPCall)(
int32_t arg0,
1646 void Simulator::SoftwareInterrupt(Instruction* instr) {
1647 int svc = instr->SvcValue();
1652 bool stack_aligned =
1654 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1655 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1661 int32_t arg4 = stack_pointer[0];
1662 int32_t arg5 = stack_pointer[1];
1664 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1665 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1666 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1667 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1668 if (use_eabi_hardfloat()) {
1673 switch (redirection->type()) {
1674 case ExternalReference::BUILTIN_FP_FP_CALL:
1675 case ExternalReference::BUILTIN_COMPARE_CALL:
1676 arg0 = vfp_register[0];
1677 arg1 = vfp_register[1];
1678 arg2 = vfp_register[2];
1679 arg3 = vfp_register[3];
1681 case ExternalReference::BUILTIN_FP_CALL:
1682 arg0 = vfp_register[0];
1683 arg1 = vfp_register[1];
1685 case ExternalReference::BUILTIN_FP_INT_CALL:
1686 arg0 = vfp_register[0];
1687 arg1 = vfp_register[1];
1688 arg2 = get_register(0);
1698 reinterpret_cast<intptr_t
>(redirection->external_function());
1700 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1701 SimulatorRuntimeFPCall target =
1702 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1703 double dval0, dval1;
1705 switch (redirection->type()) {
1706 case ExternalReference::BUILTIN_FP_FP_CALL:
1707 case ExternalReference::BUILTIN_COMPARE_CALL:
1708 GetFpArgs(&dval0, &dval1);
1709 PrintF(
"Call to host function at %p with args %f, %f",
1712 case ExternalReference::BUILTIN_FP_CALL:
1714 PrintF(
"Call to host function at %p with arg %f",
1717 case ExternalReference::BUILTIN_FP_INT_CALL:
1718 GetFpArgs(&dval0, &ival);
1719 PrintF(
"Call to host function at %p with args %f, %d",
1726 if (!stack_aligned) {
1727 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1731 CHECK(stack_aligned);
1732 if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
1733 SimulatorRuntimeFPCall target =
1734 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1735 double result = target(arg0, arg1, arg2, arg3);
1736 SetFpResult(result);
1738 SimulatorRuntimeCall target =
1739 reinterpret_cast<SimulatorRuntimeCall
>(external);
1740 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1743 if (::v8::internal::FLAG_trace_sim) {
1744 PrintF(
"Returned %08x\n", lo_res);
1746 set_register(
r0, lo_res);
1747 set_register(
r1, hi_res);
1749 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1750 SimulatorRuntimeDirectApiCall target =
1751 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1752 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1753 PrintF(
"Call to host function at %p args %08x",
1755 if (!stack_aligned) {
1756 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1760 CHECK(stack_aligned);
1762 if (::v8::internal::FLAG_trace_sim) {
1763 PrintF(
"Returned %p\n", reinterpret_cast<void *>(*result));
1766 }
else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1767 SimulatorRuntimeDirectGetterCall target =
1768 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1769 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1770 PrintF(
"Call to host function at %p args %08x %08x",
1772 if (!stack_aligned) {
1773 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1777 CHECK(stack_aligned);
1779 if (::v8::internal::FLAG_trace_sim) {
1780 PrintF(
"Returned %p\n", reinterpret_cast<void *>(*result));
1785 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1786 SimulatorRuntimeCall target =
1787 reinterpret_cast<SimulatorRuntimeCall
>(external);
1788 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1790 "Call to host function at %p"
1791 "args %08x, %08x, %08x, %08x, %08x, %08x",
1799 if (!stack_aligned) {
1800 PrintF(
" with unaligned stack %08x\n", get_register(
sp));
1804 CHECK(stack_aligned);
1805 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1808 if (::v8::internal::FLAG_trace_sim) {
1809 PrintF(
"Returned %08x\n", lo_res);
1811 set_register(
r0, lo_res);
1812 set_register(
r1, hi_res);
1814 set_register(
lr, saved_lr);
1815 set_pc(get_register(
lr));
1819 ArmDebugger dbg(
this);
1825 if (svc >= (1 << 23)) {
1827 if (isWatchedStop(code)) {
1828 IncreaseStopCounter(code);
1832 if (isEnabledStop(code)) {
1833 ArmDebugger dbg(
this);
1849 bool Simulator::isStopInstruction(Instruction* instr) {
1850 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >=
kStopCode);
1854 bool Simulator::isWatchedStop(uint32_t code) {
1856 return code < kNumOfWatchedStops;
1860 bool Simulator::isEnabledStop(uint32_t code) {
1863 return !isWatchedStop(code) ||
1864 !(watched_stops[
code].count & kStopDisabledBit);
1868 void Simulator::EnableStop(uint32_t code) {
1869 ASSERT(isWatchedStop(code));
1870 if (!isEnabledStop(code)) {
1871 watched_stops[
code].count &= ~kStopDisabledBit;
1876 void Simulator::DisableStop(uint32_t code) {
1877 ASSERT(isWatchedStop(code));
1878 if (isEnabledStop(code)) {
1879 watched_stops[
code].count |= kStopDisabledBit;
1884 void Simulator::IncreaseStopCounter(uint32_t code) {
1886 ASSERT(isWatchedStop(code));
1887 if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
1888 PrintF(
"Stop counter for code %i has overflowed.\n"
1889 "Enabling this code and reseting the counter to 0.\n", code);
1890 watched_stops[
code].count = 0;
1893 watched_stops[
code].count++;
1899 void Simulator::PrintStopInfo(uint32_t code) {
1901 if (!isWatchedStop(code)) {
1902 PrintF(
"Stop not watched.");
1904 const char* state = isEnabledStop(code) ?
"Enabled" :
"Disabled";
1905 int32_t count = watched_stops[
code].count & ~kStopDisabledBit;
1908 if (watched_stops[code].desc) {
1909 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1910 code, code, state, count, watched_stops[code].desc);
1912 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
1913 code, code, state, count);
1924 void Simulator::DecodeType01(Instruction* instr) {
1925 int type = instr->TypeValue();
1926 if ((type == 0) && instr->IsSpecialType0()) {
1928 if (instr->Bits(7, 4) == 9) {
1929 if (instr->Bit(24) == 0) {
1932 int rn = instr->RnValue();
1933 int rm = instr->RmValue();
1934 int rs = instr->RsValue();
1935 int32_t rs_val = get_register(rs);
1936 int32_t rm_val = get_register(rm);
1937 if (instr->Bit(23) == 0) {
1938 if (instr->Bit(21) == 0) {
1944 int32_t alu_out = rm_val * rs_val;
1945 set_register(rd, alu_out);
1946 if (instr->HasS()) {
1947 SetNZFlags(alu_out);
1950 int rd = instr->RdValue();
1951 int32_t acc_value = get_register(rd);
1952 if (instr->Bit(22) == 0) {
1958 int32_t mul_out = rm_val * rs_val;
1959 int32_t result = acc_value + mul_out;
1960 set_register(rn, result);
1963 int32_t mul_out = rm_val * rs_val;
1964 int32_t result = acc_value - mul_out;
1965 set_register(rn, result);
1980 int rd_lo = instr->RdValue();
1983 if (instr->Bit(22) == 1) {
1984 int64_t left_op =
static_cast<int32_t>(rm_val);
1985 int64_t right_op =
static_cast<int32_t>(rs_val);
1986 uint64_t result = left_op * right_op;
1987 hi_res =
static_cast<int32_t>(result >> 32);
1988 lo_res =
static_cast<int32_t>(result & 0xffffffff);
1991 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1992 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1993 uint64_t result = left_op * right_op;
1994 hi_res =
static_cast<int32_t>(result >> 32);
1995 lo_res =
static_cast<int32_t>(result & 0xffffffff);
1997 set_register(rd_lo, lo_res);
1998 set_register(rd_hi, hi_res);
1999 if (instr->HasS()) {
2008 int rd = instr->RdValue();
2009 int rn = instr->RnValue();
2010 int32_t rn_val = get_register(rn);
2012 if (instr->Bit(22) == 0) {
2013 int rm = instr->RmValue();
2014 int32_t rm_val = get_register(rm);
2015 switch (instr->PUField()) {
2021 set_register(rn, rn_val);
2029 set_register(rn, rn_val);
2036 if (instr->HasW()) {
2037 set_register(rn, rn_val);
2045 if (instr->HasW()) {
2046 set_register(rn, rn_val);
2057 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2058 switch (instr->PUField()) {
2064 set_register(rn, rn_val);
2072 set_register(rn, rn_val);
2079 if (instr->HasW()) {
2080 set_register(rn, rn_val);
2088 if (instr->HasW()) {
2089 set_register(rn, rn_val);
2100 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2102 if (instr->HasH()) {
2104 int32_t value1 = get_register(rd);
2105 int32_t value2 = get_register(rd+1);
2106 WriteDW(addr, value1, value2);
2109 int* rn_data = ReadDW(addr);
2110 set_dw_register(rd, rn_data);
2112 }
else if (instr->HasH()) {
2113 if (instr->HasSign()) {
2114 if (instr->HasL()) {
2115 int16_t val = ReadH(addr, instr);
2116 set_register(rd, val);
2118 int16_t val = get_register(rd);
2119 WriteH(addr, val, instr);
2122 if (instr->HasL()) {
2123 uint16_t val = ReadHU(addr, instr);
2124 set_register(rd, val);
2127 WriteH(addr, val, instr);
2132 ASSERT(instr->HasSign());
2134 int8_t val = ReadB(addr);
2135 set_register(rd, val);
2139 }
else if ((type == 0) && instr->IsMiscType0()) {
2140 if (instr->Bits(22, 21) == 1) {
2141 int rm = instr->RmValue();
2142 switch (instr->BitField(7, 4)) {
2144 set_pc(get_register(rm));
2147 uint32_t old_pc = get_pc();
2148 set_pc(get_register(rm));
2153 ArmDebugger dbg(
this);
2154 PrintF(
"Simulator hit BKPT.\n");
2161 }
else if (instr->Bits(22, 21) == 3) {
2162 int rm = instr->RmValue();
2163 int rd = instr->RdValue();
2164 switch (instr->BitField(7, 4)) {
2166 uint32_t bits = get_register(rm);
2167 int leading_zeros = 0;
2171 while ((bits & 0x80000000u) == 0) {
2176 set_register(rd, leading_zeros);
2183 PrintF(
"%08x\n", instr->InstructionBits());
2186 }
else if ((type == 1) && instr->IsNopType1()) {
2189 int rd = instr->RdValue();
2190 int rn = instr->RnValue();
2191 int32_t rn_val = get_register(rn);
2193 bool shifter_carry_out = 0;
2195 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2197 ASSERT(instr->TypeValue() == 1);
2198 shifter_operand = GetImm(instr, &shifter_carry_out);
2202 switch (instr->OpcodeField()) {
2206 alu_out = rn_val & shifter_operand;
2207 set_register(rd, alu_out);
2208 if (instr->HasS()) {
2209 SetNZFlags(alu_out);
2210 SetCFlag(shifter_carry_out);
2218 alu_out = rn_val ^ shifter_operand;
2219 set_register(rd, alu_out);
2220 if (instr->HasS()) {
2221 SetNZFlags(alu_out);
2222 SetCFlag(shifter_carry_out);
2230 alu_out = rn_val - shifter_operand;
2231 set_register(rd, alu_out);
2232 if (instr->HasS()) {
2233 SetNZFlags(alu_out);
2234 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2235 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2243 alu_out = shifter_operand - rn_val;
2244 set_register(rd, alu_out);
2245 if (instr->HasS()) {
2246 SetNZFlags(alu_out);
2247 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2248 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val,
false));
2256 alu_out = rn_val + shifter_operand;
2257 set_register(rd, alu_out);
2258 if (instr->HasS()) {
2259 SetNZFlags(alu_out);
2260 SetCFlag(CarryFrom(rn_val, shifter_operand));
2261 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2269 alu_out = rn_val + shifter_operand + GetCarry();
2270 set_register(rd, alu_out);
2271 if (instr->HasS()) {
2272 SetNZFlags(alu_out);
2273 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2274 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2280 Format(instr,
"sbc'cond's 'rd, 'rn, 'shift_rm");
2281 Format(instr,
"sbc'cond's 'rd, 'rn, 'imm");
2286 Format(instr,
"rsc'cond's 'rd, 'rn, 'shift_rm");
2287 Format(instr,
"rsc'cond's 'rd, 'rn, 'imm");
2292 if (instr->HasS()) {
2295 alu_out = rn_val & shifter_operand;
2296 SetNZFlags(alu_out);
2297 SetCFlag(shifter_carry_out);
2300 alu_out = instr->ImmedMovwMovtValue();
2301 set_register(rd, alu_out);
2307 if (instr->HasS()) {
2310 alu_out = rn_val ^ shifter_operand;
2311 SetNZFlags(alu_out);
2312 SetCFlag(shifter_carry_out);
2322 if (instr->HasS()) {
2325 alu_out = rn_val - shifter_operand;
2326 SetNZFlags(alu_out);
2327 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2328 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2331 alu_out = (get_register(rd) & 0xffff) |
2332 (instr->ImmedMovwMovtValue() << 16);
2333 set_register(rd, alu_out);
2339 if (instr->HasS()) {
2342 alu_out = rn_val + shifter_operand;
2343 SetNZFlags(alu_out);
2344 SetCFlag(CarryFrom(rn_val, shifter_operand));
2345 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2357 alu_out = rn_val | shifter_operand;
2358 set_register(rd, alu_out);
2359 if (instr->HasS()) {
2360 SetNZFlags(alu_out);
2361 SetCFlag(shifter_carry_out);
2369 alu_out = shifter_operand;
2370 set_register(rd, alu_out);
2371 if (instr->HasS()) {
2372 SetNZFlags(alu_out);
2373 SetCFlag(shifter_carry_out);
2381 alu_out = rn_val & ~shifter_operand;
2382 set_register(rd, alu_out);
2383 if (instr->HasS()) {
2384 SetNZFlags(alu_out);
2385 SetCFlag(shifter_carry_out);
2393 alu_out = ~shifter_operand;
2394 set_register(rd, alu_out);
2395 if (instr->HasS()) {
2396 SetNZFlags(alu_out);
2397 SetCFlag(shifter_carry_out);
2411 void Simulator::DecodeType2(Instruction* instr) {
2412 int rd = instr->RdValue();
2413 int rn = instr->RnValue();
2414 int32_t rn_val = get_register(rn);
2415 int32_t im_val = instr->Offset12Value();
2417 switch (instr->PUField()) {
2423 set_register(rn, rn_val);
2431 set_register(rn, rn_val);
2438 if (instr->HasW()) {
2439 set_register(rn, rn_val);
2447 if (instr->HasW()) {
2448 set_register(rn, rn_val);
2457 if (instr->HasB()) {
2458 if (instr->HasL()) {
2459 byte val = ReadBU(addr);
2460 set_register(rd, val);
2462 byte val = get_register(rd);
2466 if (instr->HasL()) {
2467 set_register(rd, ReadW(addr, instr));
2469 WriteW(addr, get_register(rd), instr);
2475 void Simulator::DecodeType3(Instruction* instr) {
2476 int rd = instr->RdValue();
2477 int rn = instr->RnValue();
2478 int32_t rn_val = get_register(rn);
2479 bool shifter_carry_out = 0;
2480 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2482 switch (instr->PUField()) {
2485 Format(instr,
"'memop'cond'b 'rd, ['rn], -'shift_rm");
2490 if (instr->HasW()) {
2491 ASSERT(instr->Bits(5, 4) == 0x1);
2493 if (instr->Bit(22) == 0x1) {
2494 int32_t sat_pos = instr->Bits(20, 16);
2495 int32_t sat_val = (1 << sat_pos) - 1;
2496 int32_t shift = instr->Bits(11, 7);
2497 int32_t shift_type = instr->Bit(6);
2498 int32_t rm_val = get_register(instr->RmValue());
2499 if (shift_type == 0) {
2507 if (rm_val > sat_val) {
2509 }
else if (rm_val < 0) {
2512 set_register(rd, rm_val);
2518 Format(instr,
"'memop'cond'b 'rd, ['rn], +'shift_rm");
2524 if (FLAG_enable_sudiv) {
2525 if (!instr->HasW()) {
2526 if (instr->Bits(5, 4) == 0x1) {
2527 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2530 int rm = instr->RmValue();
2531 int32_t rm_val = get_register(rm);
2532 int rs = instr->RsValue();
2533 int32_t rs_val = get_register(rs);
2536 ret_val = rm_val/rs_val;
2537 set_register(rn, ret_val);
2544 addr = rn_val - shifter_operand;
2545 if (instr->HasW()) {
2546 set_register(rn, addr);
2551 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2552 uint32_t widthminus1 =
static_cast<uint32_t
>(instr->Bits(20, 16));
2553 uint32_t lsbit =
static_cast<uint32_t
>(instr->Bits(11, 7));
2554 uint32_t msbit = widthminus1 + lsbit;
2556 if (instr->Bit(22)) {
2559 static_cast<uint32_t
>(get_register(instr->RmValue()));
2560 uint32_t extr_val = rm_val << (31 - msbit);
2561 extr_val = extr_val >> (31 - widthminus1);
2562 set_register(instr->RdValue(), extr_val);
2565 int32_t rm_val = get_register(instr->RmValue());
2566 int32_t extr_val = rm_val << (31 - msbit);
2567 extr_val = extr_val >> (31 - widthminus1);
2568 set_register(instr->RdValue(), extr_val);
2574 }
else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2575 uint32_t lsbit =
static_cast<uint32_t
>(instr->Bits(11, 7));
2576 uint32_t msbit =
static_cast<uint32_t
>(instr->Bits(20, 16));
2577 if (msbit >= lsbit) {
2580 static_cast<uint32_t
>(get_register(instr->RdValue()));
2581 uint32_t bitcount = msbit - lsbit + 1;
2582 uint32_t mask = (1 << bitcount) - 1;
2583 rd_val &= ~(mask << lsbit);
2584 if (instr->RmValue() != 15) {
2587 static_cast<uint32_t
>(get_register(instr->RmValue()));
2589 rd_val |= rm_val << lsbit;
2591 set_register(instr->RdValue(), rd_val);
2598 addr = rn_val + shifter_operand;
2599 if (instr->HasW()) {
2600 set_register(rn, addr);
2610 if (instr->HasB()) {
2611 if (instr->HasL()) {
2612 uint8_t
byte = ReadB(addr);
2613 set_register(rd, byte);
2615 uint8_t
byte = get_register(rd);
2619 if (instr->HasL()) {
2620 set_register(rd, ReadW(addr, instr));
2622 WriteW(addr, get_register(rd), instr);
2628 void Simulator::DecodeType4(Instruction* instr) {
2629 ASSERT(instr->Bit(22) == 0);
2630 if (instr->HasL()) {
2632 HandleRList(instr,
true);
2635 HandleRList(instr,
false);
2640 void Simulator::DecodeType5(Instruction* instr) {
2642 int off = (instr->SImmed24Value() << 2);
2643 intptr_t pc_address = get_pc();
2644 if (instr->HasLink()) {
2647 int pc_reg = get_register(
pc);
2648 set_pc(pc_reg + off);
2652 void Simulator::DecodeType6(Instruction* instr) {
2653 DecodeType6CoprocessorIns(instr);
2657 void Simulator::DecodeType7(Instruction* instr) {
2658 if (instr->Bit(24) == 1) {
2659 SoftwareInterrupt(instr);
2661 DecodeTypeVFP(instr);
2681 void Simulator::DecodeTypeVFP(Instruction* instr) {
2682 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2683 ASSERT(instr->Bits(11, 9) == 0x5);
2690 if (instr->Bit(4) == 0) {
2691 if (instr->Opc1Value() == 0x7) {
2693 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2695 if (instr->SzValue() == 0x1) {
2698 set_d_register_from_double(d, get_double_from_d_register(m));
2702 set_s_register_from_float(d, get_float_from_s_register(m));
2704 }
else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2706 double dm_value = get_double_from_d_register(vm);
2707 double dd_value = fabs(dm_value);
2708 set_d_register_from_double(vd, dd_value);
2709 }
else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2711 double dm_value = get_double_from_d_register(vm);
2712 double dd_value = -dm_value;
2713 set_d_register_from_double(vd, dd_value);
2714 }
else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2715 DecodeVCVTBetweenDoubleAndSingle(instr);
2716 }
else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2717 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2718 }
else if (((instr->Opc2Value() >> 1) == 0x6) &&
2719 (instr->Opc3Value() & 0x1)) {
2720 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2721 }
else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2722 (instr->Opc3Value() & 0x1)) {
2724 }
else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2726 double dm_value = get_double_from_d_register(vm);
2727 double dd_value = sqrt(dm_value);
2728 set_d_register_from_double(vd, dd_value);
2729 }
else if (instr->Opc3Value() == 0x0) {
2731 if (instr->SzValue() == 0x1) {
2732 set_d_register_from_double(vd, instr->DoubleImmedVmov());
2739 }
else if (instr->Opc1Value() == 0x3) {
2740 if (instr->SzValue() != 0x1) {
2744 if (instr->Opc3Value() & 0x1) {
2746 double dn_value = get_double_from_d_register(vn);
2747 double dm_value = get_double_from_d_register(vm);
2748 double dd_value = dn_value - dm_value;
2749 set_d_register_from_double(vd, dd_value);
2752 double dn_value = get_double_from_d_register(vn);
2753 double dm_value = get_double_from_d_register(vm);
2754 double dd_value = dn_value + dm_value;
2755 set_d_register_from_double(vd, dd_value);
2757 }
else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2759 if (instr->SzValue() != 0x1) {
2763 double dn_value = get_double_from_d_register(vn);
2764 double dm_value = get_double_from_d_register(vm);
2765 double dd_value = dn_value * dm_value;
2766 set_d_register_from_double(vd, dd_value);
2767 }
else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
2769 if (instr->SzValue() != 0x1) {
2773 double dn_value = get_double_from_d_register(vn);
2774 double dm_value = get_double_from_d_register(vm);
2775 double dd_value = dn_value / dm_value;
2776 div_zero_vfp_flag_ = (dm_value == 0);
2777 set_d_register_from_double(vd, dd_value);
2782 if ((instr->VCValue() == 0x0) &&
2783 (instr->VAValue() == 0x0)) {
2784 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
2785 }
else if ((instr->VLValue() == 0x1) &&
2786 (instr->VCValue() == 0x0) &&
2787 (instr->VAValue() == 0x7) &&
2788 (instr->Bits(19, 16) == 0x1)) {
2790 uint32_t rt = instr->RtValue();
2792 Copy_FPSCR_to_APSR();
2795 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
2796 (z_flag_FPSCR_ << 30) |
2797 (c_flag_FPSCR_ << 29) |
2798 (v_flag_FPSCR_ << 28) |
2799 (inexact_vfp_flag_ << 4) |
2800 (underflow_vfp_flag_ << 3) |
2801 (overflow_vfp_flag_ << 2) |
2802 (div_zero_vfp_flag_ << 1) |
2803 (inv_op_vfp_flag_ << 0) |
2804 (FPSCR_rounding_mode_);
2805 set_register(rt, fpscr);
2807 }
else if ((instr->VLValue() == 0x0) &&
2808 (instr->VCValue() == 0x0) &&
2809 (instr->VAValue() == 0x7) &&
2810 (instr->Bits(19, 16) == 0x1)) {
2812 uint32_t rt = instr->RtValue();
2816 uint32_t rt_value = get_register(rt);
2817 n_flag_FPSCR_ = (rt_value >> 31) & 1;
2818 z_flag_FPSCR_ = (rt_value >> 30) & 1;
2819 c_flag_FPSCR_ = (rt_value >> 29) & 1;
2820 v_flag_FPSCR_ = (rt_value >> 28) & 1;
2821 inexact_vfp_flag_ = (rt_value >> 4) & 1;
2822 underflow_vfp_flag_ = (rt_value >> 3) & 1;
2823 overflow_vfp_flag_ = (rt_value >> 2) & 1;
2824 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
2825 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
2826 FPSCR_rounding_mode_ =
2836 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
2837 Instruction* instr) {
2838 ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
2839 (instr->VAValue() == 0x0));
2841 int t = instr->RtValue();
2843 bool to_arm_register = (instr->VLValue() == 0x1);
2845 if (to_arm_register) {
2846 int32_t int_value = get_sinteger_from_s_register(n);
2847 set_register(t, int_value);
2849 int32_t rs_val = get_register(t);
2850 set_s_register_from_sinteger(n, rs_val);
2855 void Simulator::DecodeVCMP(Instruction* instr) {
2856 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
2857 ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2858 (instr->Opc3Value() & 0x1));
2862 if (instr->SzValue() == 1) {
2866 int d = instr->VFPDRegValue(precision);
2868 if (instr->Opc2Value() == 0x4) {
2869 m = instr->VFPMRegValue(precision);
2873 double dd_value = get_double_from_d_register(d);
2874 double dm_value = 0.0;
2875 if (instr->Opc2Value() == 0x4) {
2876 dm_value = get_double_from_d_register(m);
2880 if (instr->Bit(7) == 1) {
2881 if (
isnan(dd_value)) {
2882 inv_op_vfp_flag_ =
true;
2886 Compute_FPSCR_Flags(dd_value, dm_value);
2893 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
2894 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
2895 ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
2899 if (instr->SzValue() == 1) {
2904 int dst = instr->VFPDRegValue(dst_precision);
2905 int src = instr->VFPMRegValue(src_precision);
2908 double val = get_double_from_d_register(src);
2909 set_s_register_from_float(dst, static_cast<float>(val));
2911 float val = get_float_from_s_register(src);
2912 set_d_register_from_double(dst, static_cast<double>(val));
2920 double max_uint =
static_cast<double>(0xffffffffu);
2921 double max_int =
static_cast<double>(
kMaxInt);
2922 double min_int =
static_cast<double>(
kMinInt);
2933 return unsigned_ ? (val >= (max_uint + 0.5)) ||
2935 : (val >= (max_int + 0.5)) ||
2936 (val < (min_int - 0.5));
2939 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2941 : (val >= (max_int + 1.0)) ||
2945 return unsigned_ ? (val >= (max_uint + 1.0)) ||
2947 : (val >= (max_int + 1.0)) ||
2948 (val <= (min_int - 1.0));
2958 int VFPConversionSaturate(
double val,
bool unsigned_res) {
2963 return (val < 0) ? 0 : 0xffffffffu;
2971 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
2972 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
2973 (instr->Bits(27, 23) == 0x1D));
2974 ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
2975 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
2978 bool to_integer = (instr->Bit(18) == 1);
2992 int src = instr->VFPMRegValue(src_precision);
3000 bool unsigned_integer = (instr->Bit(16) == 0);
3003 double val = double_precision ? get_double_from_d_register(src)
3004 : get_float_from_s_register(src);
3006 int temp = unsigned_integer ?
static_cast<uint32_t
>(val)
3007 : static_cast<int32_t>(val);
3009 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3012 unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
3015 inexact_vfp_flag_ = (abs_diff != 0);
3017 if (inv_op_vfp_flag_) {
3018 temp = VFPConversionSaturate(val, unsigned_integer);
3022 int val_sign = (val > 0) ? 1 : -1;
3023 if (abs_diff > 0.5) {
3025 }
else if (abs_diff == 0.5) {
3027 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3033 temp = temp > val ? temp - 1 : temp;
3046 set_s_register_from_sinteger(dst, temp);
3049 bool unsigned_integer = (instr->Bit(7) == 0);
3051 int dst = instr->VFPDRegValue(src_precision);
3054 int val = get_sinteger_from_s_register(src);
3057 if (unsigned_integer) {
3058 set_d_register_from_double(dst,
3059 static_cast<double>((uint32_t)val));
3061 set_d_register_from_double(dst, static_cast<double>(val));
3064 if (unsigned_integer) {
3065 set_s_register_from_float(dst,
3066 static_cast<float>((uint32_t)val));
3068 set_s_register_from_float(dst, static_cast<float>(val));
3081 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3082 ASSERT((instr->TypeValue() == 6));
3084 if (instr->CoprocessorValue() == 0xA) {
3085 switch (instr->OpcodeValue()) {
3090 int rn = instr->RnValue();
3092 int offset = instr->Immed8Value();
3093 if (!instr->HasU()) {
3097 int32_t address = get_register(rn) + 4 * offset;
3098 if (instr->HasL()) {
3100 set_s_register_from_sinteger(vd, ReadW(address, instr));
3103 WriteW(address, get_sinteger_from_s_register(vd), instr);
3119 }
else if (instr->CoprocessorValue() == 0xB) {
3120 switch (instr->OpcodeValue()) {
3123 if (instr->Bits(7, 4) != 0x1) {
3126 int rt = instr->RtValue();
3127 int rn = instr->RnValue();
3128 int vm = instr->VmValue();
3129 if (instr->HasL()) {
3130 int32_t rt_int_value = get_sinteger_from_s_register(2*vm);
3131 int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1);
3133 set_register(rt, rt_int_value);
3134 set_register(rn, rn_int_value);
3136 int32_t rs_val = get_register(rt);
3137 int32_t rn_val = get_register(rn);
3139 set_s_register_from_sinteger(2*vm, rs_val);
3140 set_s_register_from_sinteger((2*vm+1), rn_val);
3146 int rn = instr->RnValue();
3147 int vd = instr->VdValue();
3148 int offset = instr->Immed8Value();
3149 if (!instr->HasU()) {
3152 int32_t address = get_register(rn) + 4 * offset;
3153 if (instr->HasL()) {
3155 set_s_register_from_sinteger(2*vd, ReadW(address, instr));
3156 set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr));
3159 WriteW(address, get_sinteger_from_s_register(2*vd), instr);
3160 WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr);
3180 void Simulator::InstructionDecode(Instruction* instr) {
3181 if (v8::internal::FLAG_check_icache) {
3182 CheckICache(isolate_->simulator_i_cache(), instr);
3184 pc_modified_ =
false;
3185 if (::v8::internal::FLAG_trace_sim) {
3190 dasm.InstructionDecode(buffer,
3191 reinterpret_cast<byte*>(instr));
3192 PrintF(
" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.
start());
3196 }
else if (ConditionallyExecute(instr)) {
3197 switch (instr->TypeValue()) {
3200 DecodeType01(instr);
3234 }
else if (instr->IsStop()) {
3237 if (!pc_modified_) {
3238 set_register(
pc, reinterpret_cast<int32_t>(instr)
3244 void Simulator::Execute() {
3247 int program_counter = get_pc();
3249 if (::v8::internal::FLAG_stop_sim_at == 0) {
3252 while (program_counter != end_sim_pc) {
3253 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3255 InstructionDecode(instr);
3256 program_counter = get_pc();
3261 while (program_counter != end_sim_pc) {
3262 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
3264 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3265 ArmDebugger dbg(
this);
3268 InstructionDecode(instr);
3270 program_counter = get_pc();
3276 int32_t Simulator::Call(
byte* entry,
int argument_count, ...) {
3278 va_start(parameters, argument_count);
3282 ASSERT(argument_count >= 4);
3283 set_register(
r0, va_arg(parameters,
int32_t));
3284 set_register(
r1, va_arg(parameters,
int32_t));
3285 set_register(
r2, va_arg(parameters,
int32_t));
3286 set_register(
r3, va_arg(parameters,
int32_t));
3289 int original_stack = get_register(
sp);
3291 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t));
3296 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
3297 for (
int i = 4; i < argument_count; i++) {
3298 stack_argument[i - 4] = va_arg(parameters,
int32_t);
3301 set_register(
sp, entry_stack);
3304 set_register(
pc, reinterpret_cast<int32_t>(entry));
3308 set_register(
lr, end_sim_pc);
3324 int32_t callee_saved_value = icount_;
3325 set_register(
r4, callee_saved_value);
3326 set_register(
r5, callee_saved_value);
3327 set_register(
r6, callee_saved_value);
3328 set_register(
r7, callee_saved_value);
3329 set_register(
r8, callee_saved_value);
3330 set_register(
r9, callee_saved_value);
3331 set_register(
r10, callee_saved_value);
3332 set_register(
r11, callee_saved_value);
3338 CHECK_EQ(callee_saved_value, get_register(
r4));
3339 CHECK_EQ(callee_saved_value, get_register(
r5));
3340 CHECK_EQ(callee_saved_value, get_register(
r6));
3341 CHECK_EQ(callee_saved_value, get_register(
r7));
3342 CHECK_EQ(callee_saved_value, get_register(
r8));
3343 CHECK_EQ(callee_saved_value, get_register(
r9));
3348 set_register(
r4, r4_val);
3349 set_register(
r5, r5_val);
3350 set_register(
r6, r6_val);
3351 set_register(
r7, r7_val);
3352 set_register(
r8, r8_val);
3353 set_register(
r9, r9_val);
3354 set_register(
r10, r10_val);
3355 set_register(
r11, r11_val);
3359 set_register(
sp, original_stack);
3366 uintptr_t Simulator::PushAddress(uintptr_t address) {
3367 int new_sp = get_register(
sp) -
sizeof(uintptr_t);
3368 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
3369 *stack_slot = address;
3370 set_register(
sp, new_sp);
3375 uintptr_t Simulator::PopAddress() {
3376 int current_sp = get_register(
sp);
3377 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
3378 uintptr_t address = *stack_slot;
3379 set_register(
sp, current_sp +
sizeof(uintptr_t));
3385 #endif // USE_SIMULATOR
3387 #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)
static int ActivationFrameAlignment()
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
const uint32_t kVFPRoundingModeMask
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
void DeleteArray(T *array)
const int kNumVFPDoubleRegisters