9#if defined(USE_SIMULATOR)
40 Simulator::GlobalMonitor::Get)
52 explicit ArmDebugger(Simulator* sim) : sim_(sim) {}
54 bool ExecDebugCommand(ArrayUniquePtr<char> line_ptr);
57 static const Instr kBreakpointInstr =
59 static const Instr kNopInstr = (
al | (13 *
B21));
63 int32_t GetRegisterValue(
int regnum);
64 double GetRegisterPairDoubleValue(
int regnum);
65 double GetVFPDoubleRegisterValue(
int regnum);
66 bool GetValue(
const char* desc, int32_t* value);
67 bool GetVFPSingleValue(
const char* desc,
float* value);
68 bool GetVFPDoubleValue(
const char* desc,
double* value);
71 bool SetBreakpoint(Instruction* breakpc);
72 void DeleteBreakpoint();
76 void UndoBreakpoint();
77 void RedoBreakpoint();
80void Simulator::DebugAtNextPC() {
81 PrintF(
"Starting debugger on the next instruction:\n");
83 ArmDebugger(
this).Debug();
86void Simulator::AdvancedSIMDElementOrStructureLoadStoreWriteback(
int Rn,
int Rm,
90 set_register(Rn, get_register(Rn) + ebytes);
92 set_register(Rn, get_register(Rn) + get_register(Rm));
97int32_t ArmDebugger::GetRegisterValue(
int regnum) {
99 return sim_->get_pc();
101 return sim_->get_register(regnum);
105double ArmDebugger::GetRegisterPairDoubleValue(
int regnum) {
106 return sim_->get_double_from_register_pair(regnum);
109double ArmDebugger::GetVFPDoubleRegisterValue(
int regnum) {
110 return sim_->get_double_from_d_register(regnum).get_scalar();
113bool ArmDebugger::GetValue(
const char* desc, int32_t* value) {
116 *value = GetRegisterValue(regnum);
119 if (strncmp(desc,
"0x", 2) == 0)
120 return SScanF(desc + 2,
"%x",
reinterpret_cast<uint32_t*
>(value)) == 1;
121 return SScanF(desc,
"%u",
reinterpret_cast<uint32_t*
>(value)) == 1;
124bool ArmDebugger::GetVFPSingleValue(
const char* desc,
float* value) {
128 *value = sim_->get_float_from_s_register(regnum).get_scalar();
134bool ArmDebugger::GetVFPDoubleValue(
const char* desc,
double* value) {
138 *value = sim_->get_double_from_d_register(regnum).get_scalar();
144bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
146 if (sim_->break_pc_ !=
nullptr) {
151 sim_->break_pc_ = breakpc;
152 sim_->break_instr_ = breakpc->InstructionBits();
161void SetInstructionBitsInCodeSpace(Instruction*
instr,
Instr value,
163 CodePageMemoryModificationScopeForDebugging scope(
169void ArmDebugger::DeleteBreakpoint() {
171 sim_->break_pc_ =
nullptr;
172 sim_->break_instr_ = 0;
175void ArmDebugger::UndoBreakpoint() {
176 if (sim_->break_pc_ !=
nullptr) {
177 SetInstructionBitsInCodeSpace(sim_->break_pc_, sim_->break_instr_,
178 sim_->isolate_->heap());
182void ArmDebugger::RedoBreakpoint() {
183 if (sim_->break_pc_ !=
nullptr) {
184 SetInstructionBitsInCodeSpace(sim_->break_pc_, kBreakpointInstr,
185 sim_->isolate_->heap());
189void ArmDebugger::Debug() {
190 if (
v8_flags.correctness_fuzzer_suppressions) {
191 PrintF(
"Debugger disabled for differential fuzzing.\n");
194 intptr_t last_pc = -1;
201 while (!done && !sim_->has_bad_pc()) {
202 if (last_pc != sim_->get_pc()) {
207 dasm.InstructionDecode(buffer,
208 reinterpret_cast<uint8_t*
>(sim_->get_pc()));
209 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.
begin());
210 last_pc = sim_->get_pc();
214 done = ExecDebugCommand(std::move(line));
223#define COMMAND_SIZE 63
227#define XSTR(a) STR(a)
229 char cmd[COMMAND_SIZE + 1];
230 char arg1[ARG_SIZE + 1];
231 char arg2[ARG_SIZE + 1];
232 char* argv[3] = {cmd, arg1, arg2};
235 cmd[COMMAND_SIZE] = 0;
239 if (line_ptr ==
nullptr)
return true;
242 const char* line = line_ptr.get();
243 const char* last_input = sim_->last_debugger_input();
244 if (strcmp(line,
"\n") == 0 && (last_input !=
nullptr)) {
249 sim_->set_last_debugger_input(std::move(line_ptr));
254 int argc = SScanF(line,
255 "%" XSTR(COMMAND_SIZE)
"s "
256 "%" XSTR(ARG_SIZE)
"s "
257 "%" XSTR(ARG_SIZE)
"s",
259 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
260 sim_->InstructionDecode(
reinterpret_cast<Instruction*
>(sim_->get_pc()));
261 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
263 sim_->InstructionDecode(
reinterpret_cast<Instruction*
>(sim_->get_pc()));
266 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
267 if (argc == 2 || (argc == 3 && strcmp(arg2,
"fp") == 0)) {
271 if (strcmp(arg1,
"all") == 0) {
273 value = GetRegisterValue(
i);
276 if ((argc == 3 && strcmp(arg2,
"fp") == 0) &&
i < 8 && (
i % 2) == 0) {
277 dvalue = GetRegisterPairDoubleValue(
i);
278 PrintF(
" (%f)\n", dvalue);
284 dvalue = GetVFPDoubleRegisterValue(
i);
287 static_cast<uint32_t
>(as_words >> 32),
288 static_cast<uint32_t
>(as_words & 0xFFFFFFFF));
291 if (GetValue(arg1, &value)) {
292 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
293 }
else if (GetVFPSingleValue(arg1, &svalue)) {
295 PrintF(
"%s: %f 0x%08x\n", arg1, svalue, as_word);
296 }
else if (GetVFPDoubleValue(arg1, &dvalue)) {
298 PrintF(
"%s: %f 0x%08x %08x\n", arg1, dvalue,
299 static_cast<uint32_t
>(as_words >> 32),
300 static_cast<uint32_t
>(as_words & 0xFFFFFFFF));
302 PrintF(
"%s unrecognized\n", arg1);
306 PrintF(
"print <register>\n");
308 }
else if ((strcmp(cmd,
"po") == 0) || (strcmp(cmd,
"printobject") == 0)) {
312 if (GetValue(arg1, &value)) {
314 os << arg1 <<
": \n";
319 os << Brief(obj) <<
"\n";
322 os << arg1 <<
" unrecognized\n";
325 PrintF(
"printobject <value>\n");
327 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0 ||
328 strcmp(cmd,
"dump") == 0) {
333 if (strcmp(cmd,
"stack") == 0) {
334 cur =
reinterpret_cast<int32_t*
>(sim_->get_register(Simulator::sp));
337 if (!GetValue(arg1, &value)) {
338 PrintF(
"%s unrecognized\n", arg1);
346 if (argc == next_arg) {
349 if (!GetValue(argv[next_arg], &words)) {
355 bool skip_obj_print = (strcmp(cmd,
"dump") == 0);
358 reinterpret_cast<intptr_t
>(cur), *cur, *cur);
360 Heap* current_heap = sim_->isolate_->heap();
361 if (!skip_obj_print) {
376 }
else if (strcmp(cmd,
"disasm") == 0 || strcmp(cmd,
"di") == 0) {
382 uint8_t* prev =
nullptr;
383 uint8_t* cur =
nullptr;
384 uint8_t*
end =
nullptr;
387 cur =
reinterpret_cast<uint8_t*
>(sim_->get_pc());
389 }
else if (argc == 2) {
391 if (regnum !=
kNoRegister || strncmp(arg1,
"0x", 2) == 0) {
394 if (GetValue(arg1, &value)) {
395 cur =
reinterpret_cast<uint8_t*
>(
value);
402 if (GetValue(arg1, &value)) {
403 cur =
reinterpret_cast<uint8_t*
>(sim_->get_pc());
411 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
412 cur =
reinterpret_cast<uint8_t*
>(value1);
419 cur += dasm.InstructionDecode(buffer, cur);
423 }
else if (strcmp(cmd,
"gdb") == 0) {
424 PrintF(
"relinquishing control to gdb\n");
426 PrintF(
"regaining control from gdb\n");
427 }
else if (strcmp(cmd,
"break") == 0) {
430 if (GetValue(arg1, &value)) {
431 if (!SetBreakpoint(
reinterpret_cast<Instruction*
>(value))) {
432 PrintF(
"setting breakpoint failed\n");
435 PrintF(
"%s unrecognized\n", arg1);
438 PrintF(
"break <address>\n");
440 }
else if (strcmp(cmd,
"backtrace") == 0 || strcmp(cmd,
"bt") == 0) {
442 int32_t lr = sim_->get_register(Simulator::lr);
443 int32_t sp = sim_->get_register(Simulator::sp);
444 int32_t fp = sim_->get_register(Simulator::fp);
448 PrintF(
"#%d: 0x%08x (sp=0x%08x, fp=0x%08x)\n",
i,
pc, sp, fp);
451 if (
pc == Simulator::end_sim_pc) {
454 lr = *(
reinterpret_cast<int32_t*
>(fp) + 1);
455 fp = *
reinterpret_cast<int32_t*
>(fp);
458 PrintF(
"Too many frames\n");
462 }
else if (strcmp(cmd,
"del") == 0) {
464 }
else if (strcmp(cmd,
"flags") == 0) {
465 PrintF(
"N flag: %d; ", sim_->n_flag_);
466 PrintF(
"Z flag: %d; ", sim_->z_flag_);
467 PrintF(
"C flag: %d; ", sim_->c_flag_);
468 PrintF(
"V flag: %d\n", sim_->v_flag_);
469 PrintF(
"INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
470 PrintF(
"DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
471 PrintF(
"OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
472 PrintF(
"UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
473 PrintF(
"INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
474 }
else if (strcmp(cmd,
"stop") == 0) {
476 intptr_t stop_pc = sim_->get_pc() -
kInstrSize;
477 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
478 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
480 if (stop_instr->IsStop()) {
481 SetInstructionBitsInCodeSpace(stop_instr, kNopInstr,
482 sim_->isolate_->heap());
484 PrintF(
"Not at debugger stop.\n");
486 }
else if (argc == 3) {
488 if (strcmp(arg1,
"info") == 0) {
489 if (strcmp(arg2,
"all") == 0) {
490 PrintF(
"Stop information:\n");
491 for (uint32_t
i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
492 sim_->PrintStopInfo(
i);
494 }
else if (GetValue(arg2, &value)) {
495 sim_->PrintStopInfo(value);
497 PrintF(
"Unrecognized argument.\n");
499 }
else if (strcmp(arg1,
"enable") == 0) {
501 if (strcmp(arg2,
"all") == 0) {
502 for (uint32_t
i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
505 }
else if (GetValue(arg2, &value)) {
506 sim_->EnableStop(value);
508 PrintF(
"Unrecognized argument.\n");
510 }
else if (strcmp(arg1,
"disable") == 0) {
512 if (strcmp(arg2,
"all") == 0) {
513 for (uint32_t
i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
514 sim_->DisableStop(
i);
516 }
else if (GetValue(arg2, &value)) {
517 sim_->DisableStop(value);
519 PrintF(
"Unrecognized argument.\n");
523 PrintF(
"Wrong usage. Use help command for more information.\n");
525 }
else if ((strcmp(cmd,
"t") == 0) || strcmp(cmd,
"trace") == 0) {
526 sim_->ToggleInstructionTracing();
527 PrintF(
"Trace of executed instructions is %s\n",
528 sim_->InstructionTracingEnabled() ?
"on" :
"off");
529 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
531 PrintF(
" continue execution (alias 'c')\n");
533 PrintF(
" step one instruction (alias 'si')\n");
534 PrintF(
"print <register>\n");
535 PrintF(
" print register content (alias 'p')\n");
536 PrintF(
" use register name 'all' to print all registers\n");
537 PrintF(
" add argument 'fp' to print register pair double values\n");
538 PrintF(
"printobject <register>\n");
539 PrintF(
" print an object from a register (alias 'po')\n");
542 PrintF(
"stack [<words>]\n");
543 PrintF(
" dump stack content, default dump 10 words)\n");
544 PrintF(
"mem <address> [<words>]\n");
545 PrintF(
" dump memory content, default dump 10 words)\n");
546 PrintF(
"dump [<words>]\n");
548 " dump memory content without pretty printing JS objects, default "
550 PrintF(
"disasm [<instructions>]\n");
551 PrintF(
"disasm [<address/register>]\n");
552 PrintF(
"disasm [[<address/register>] <instructions>]\n");
553 PrintF(
" disassemble code, default is 10 instructions\n");
554 PrintF(
" from pc (alias 'di')\n");
557 PrintF(
"break <address>\n");
558 PrintF(
" set a break point on the address\n");
559 PrintF(
"backtrace / bt\n");
560 PrintF(
" Walk the frame pointers, dumping the pc/sp/fp for each frame.\n");
562 PrintF(
" delete the breakpoint\n");
563 PrintF(
"trace (alias 't')\n");
564 PrintF(
" toogle the tracing of all executed statements\n");
565 PrintF(
"stop feature:\n");
566 PrintF(
" Description:\n");
567 PrintF(
" Stops are debug instructions inserted by\n");
568 PrintF(
" the Assembler::stop() function.\n");
569 PrintF(
" When hitting a stop, the Simulator will\n");
570 PrintF(
" stop and give control to the ArmDebugger.\n");
571 PrintF(
" The first %d stop codes are watched:\n",
572 Simulator::kNumOfWatchedStops);
573 PrintF(
" - They can be enabled / disabled: the Simulator\n");
574 PrintF(
" will / won't stop when hitting them.\n");
575 PrintF(
" - The Simulator keeps track of how many times they \n");
576 PrintF(
" are met. (See the info command.) Going over a\n");
577 PrintF(
" disabled stop still increases its counter. \n");
579 PrintF(
" stop info all/<code> : print infos about number <code>\n");
580 PrintF(
" or all stop(s).\n");
581 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
582 PrintF(
" all or number <code> stop(s)\n");
584 PrintF(
" ignore the stop instruction at the current location\n");
587 PrintF(
"Unknown command: %s\n", cmd);
598bool Simulator::InstructionTracingEnabled() {
return instruction_tracing_; }
600void Simulator::ToggleInstructionTracing() {
601 instruction_tracing_ = !instruction_tracing_;
604bool Simulator::ICacheMatch(
void*
one,
void* two) {
605 DCHECK_EQ(
reinterpret_cast<intptr_t
>(
one) & CachePage::kPageMask, 0);
606 DCHECK_EQ(
reinterpret_cast<intptr_t
>(two) & CachePage::kPageMask, 0);
610static uint32_t ICacheHash(
void*
key) {
611 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(
key)) >> 2;
614static bool AllOnOnePage(uintptr_t
start,
int size) {
615 intptr_t start_page = (
start & ~CachePage::kPageMask);
616 intptr_t end_page = ((
start +
size) & ~CachePage::kPageMask);
617 return start_page == end_page;
620void Simulator::SetRedirectInstruction(Instruction* instruction) {
625 void* start_addr,
size_t size) {
626 intptr_t
start =
reinterpret_cast<intptr_t
>(start_addr);
627 int intra_line = (
start & CachePage::kLineMask);
630 size = ((size - 1) | CachePage::kLineMask) + 1;
632 while (!AllOnOnePage(
start, size - 1)) {
633 int bytes_to_flush = CachePage::kPageSize -
offset;
634 FlushOnePage(i_cache,
start, bytes_to_flush);
635 start += bytes_to_flush;
636 size -= bytes_to_flush;
641 FlushOnePage(i_cache,
start, size);
648 if (entry->value ==
nullptr) {
649 CachePage* new_page =
new CachePage();
650 entry->value = new_page;
652 return reinterpret_cast<CachePage*
>(entry->value);
657 intptr_t
start,
int size) {
661 DCHECK_EQ(size & CachePage::kLineMask, 0);
662 void* page =
reinterpret_cast<void*
>(
start & (~CachePage::kPageMask));
664 CachePage* cache_page = GetCachePage(i_cache, page);
665 char* valid_bytemap = cache_page->ValidityByte(
offset);
666 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
670 Instruction*
instr) {
671 intptr_t address =
reinterpret_cast<intptr_t
>(
instr);
672 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
673 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
674 int offset = (address & CachePage::kPageMask);
675 CachePage* cache_page = GetCachePage(i_cache, page);
676 char* cache_valid_byte = cache_page->ValidityByte(
offset);
677 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
678 char* cached_line = cache_page->CachedData(
offset & ~CachePage::kLineMask);
685 memcpy(cached_line, line, CachePage::kLineLength);
686 *cache_valid_byte = CachePage::LINE_VALID;
690Simulator::Simulator(Isolate* isolate) :
isolate_(isolate) {
693 stack_ =
reinterpret_cast<uint8_t*
>(base::Malloc(kAllocatedStackSize));
694 pc_modified_ =
false;
701 for (
int i = 0;
i < num_registers;
i++) {
713 for (
int i = 0;
i < num_d_registers * 2;
i++) {
714 vfp_registers_[
i] = 0;
716 n_flag_FPSCR_ =
false;
717 z_flag_FPSCR_ =
false;
718 c_flag_FPSCR_ =
false;
719 v_flag_FPSCR_ =
false;
720 FPSCR_rounding_mode_ =
RN;
721 FPSCR_default_NaN_mode_ =
false;
723 inv_op_vfp_flag_ =
false;
724 div_zero_vfp_flag_ =
false;
725 overflow_vfp_flag_ =
false;
726 underflow_vfp_flag_ =
false;
727 inexact_vfp_flag_ =
false;
737 last_debugger_input_ =
nullptr;
739 global_monitor_ = GlobalMonitor::Get();
740 global_monitor_->PrependProcessor(&global_monitor_processor_);
743 SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
746Simulator::~Simulator() {
747 global_monitor_->RemoveProcessor(&global_monitor_processor_);
752Simulator* Simulator::current(Isolate* isolate) {
754 isolate->FindOrAllocatePerThreadDataForThisThread();
757 Simulator* sim = isolate_data->simulator();
758 if (sim ==
nullptr) {
760 sim =
new Simulator(isolate);
761 isolate_data->set_simulator(sim);
768void Simulator::set_register(
int reg, int32_t value) {
778int32_t Simulator::get_register(
int reg)
const {
782 if (
reg >= num_registers)
return 0;
787double Simulator::get_double_from_register_pair(
int reg) {
793 char buffer[2 *
sizeof(vfp_registers_[0])];
795 memcpy(&dm_val, buffer, 2 *
sizeof(
registers_[0]));
799void Simulator::set_register_pair_from_double(
int reg,
double* value) {
804void Simulator::set_dw_register(
int dreg,
const int* dbl) {
805 DCHECK((dreg >= 0) && (dreg < num_d_registers));
810void Simulator::get_d_register(
int dreg, uint64_t* value) {
811 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::SupportedRegisterCount()));
812 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value));
815void Simulator::set_d_register(
int dreg,
const uint64_t* value) {
816 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::SupportedRegisterCount()));
817 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value));
820void Simulator::get_d_register(
int dreg, uint32_t* value) {
821 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::SupportedRegisterCount()));
822 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value) * 2);
825void Simulator::set_d_register(
int dreg,
const uint32_t* value) {
826 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::SupportedRegisterCount()));
827 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value) * 2);
830template <
typename T,
int SIZE>
831void Simulator::get_neon_register(
int reg, T (&value)[
SIZE /
sizeof(T)]) {
835 memcpy(value, vfp_registers_ +
reg * (
SIZE / 4),
SIZE);
838template <
typename T,
int SIZE>
839void Simulator::set_neon_register(
int reg,
const T (&value)[
SIZE /
sizeof(T)]) {
843 memcpy(vfp_registers_ +
reg * (
SIZE / 4), value,
SIZE);
847void Simulator::set_pc(int32_t value) {
852bool Simulator::has_bad_pc()
const {
860void Simulator::set_s_register(
int sreg,
unsigned int value) {
861 DCHECK((sreg >= 0) && (sreg < num_s_registers));
862 vfp_registers_[sreg] =
value;
865unsigned int Simulator::get_s_register(
int sreg)
const {
866 DCHECK((sreg >= 0) && (sreg < num_s_registers));
867 return vfp_registers_[sreg];
870template <
class InputType,
int register_size>
871void Simulator::SetVFPRegister(
int reg_index,
const InputType& value) {
872 unsigned bytes = register_size *
sizeof(vfp_registers_[0]);
875 if (register_size == 1)
DCHECK(reg_index < num_s_registers);
876 if (register_size == 2)
877 DCHECK(reg_index < DwVfpRegister::SupportedRegisterCount());
879 memcpy(&vfp_registers_[reg_index * register_size], &value, bytes);
882template <
class ReturnType,
int register_size>
883ReturnType Simulator::GetFromVFPRegister(
int reg_index) {
884 unsigned bytes = register_size *
sizeof(vfp_registers_[0]);
887 if (register_size == 1)
DCHECK(reg_index < num_s_registers);
888 if (register_size == 2)
889 DCHECK(reg_index < DwVfpRegister::SupportedRegisterCount());
892 memcpy(&value, &vfp_registers_[register_size * reg_index], bytes);
896void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask,
899 if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) {
900 n_flag_ = ((value & (1 << 31)) != 0);
901 z_flag_ = ((value & (1 << 30)) != 0);
902 c_flag_ = ((value & (1 << 29)) != 0);
903 v_flag_ = ((value & (1 << 28)) != 0);
909uint32_t Simulator::GetFromSpecialRegister(SRegister
reg) {
913 if (n_flag_)
result |= (1 << 31);
914 if (z_flag_)
result |= (1 << 30);
915 if (c_flag_)
result |= (1 << 29);
916 if (v_flag_)
result |= (1 << 28);
927void Simulator::GetFpArgs(
double*
x,
double*
y, int32_t*
z) {
928 if (use_eabi_hardfloat()) {
929 *
x = get_double_from_d_register(0).get_scalar();
930 *
y = get_double_from_d_register(1).get_scalar();
931 *
z = get_register(0);
934 *
x = get_double_from_register_pair(0);
936 *
y = get_double_from_register_pair(2);
938 *
z = get_register(2);
943void Simulator::SetFpResult(
const double&
result) {
944 if (use_eabi_hardfloat()) {
945 char buffer[2 *
sizeof(vfp_registers_[0])];
946 memcpy(buffer, &
result,
sizeof(buffer));
948 memcpy(vfp_registers_, buffer,
sizeof(buffer));
951 memcpy(buffer, &
result,
sizeof(buffer));
957void Simulator::TrashCallerSaveRegisters() {
966 static const uint64_t v = 0x7ff000007f801000UL;
968 for (
int i = 0;
i < 8;
i++) {
969 set_d_register(
i, &v);
971 if (DoubleRegister::SupportedRegisterCount() > 16) {
973 for (
int i = 16;
i < 32;
i++) {
974 set_d_register(
i, &v);
979int Simulator::ReadW(int32_t addr) {
982 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
983 local_monitor_.NotifyLoad(addr);
984 return base::ReadUnalignedValue<intptr_t>(addr);
987int Simulator::ReadExW(int32_t addr) {
988 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
989 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
990 global_monitor_->NotifyLoadExcl_Locked(addr, &global_monitor_processor_);
991 return base::ReadUnalignedValue<intptr_t>(addr);
994void Simulator::WriteW(int32_t addr,
int value) {
997 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
998 local_monitor_.NotifyStore(addr);
999 global_monitor_->NotifyStore_Locked(addr, &global_monitor_processor_);
1000 base::WriteUnalignedValue<intptr_t>(addr, value);
1003int Simulator::WriteExW(int32_t addr,
int value) {
1004 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1005 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
1006 global_monitor_->NotifyStoreExcl_Locked(addr,
1007 &global_monitor_processor_)) {
1008 base::WriteUnalignedValue<intptr_t>(addr, value);
1015uint16_t Simulator::ReadHU(int32_t addr) {
1018 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1019 local_monitor_.NotifyLoad(addr);
1020 return base::ReadUnalignedValue<uint16_t>(addr);
1023int16_t Simulator::ReadH(int32_t addr) {
1026 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1027 local_monitor_.NotifyLoad(addr);
1028 return base::ReadUnalignedValue<int16_t>(addr);
1031uint16_t Simulator::ReadExHU(int32_t addr) {
1032 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1033 local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord);
1034 global_monitor_->NotifyLoadExcl_Locked(addr, &global_monitor_processor_);
1035 return base::ReadUnalignedValue<uint16_t>(addr);
1038void Simulator::WriteH(int32_t addr, uint16_t value) {
1041 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1042 local_monitor_.NotifyStore(addr);
1043 global_monitor_->NotifyStore_Locked(addr, &global_monitor_processor_);
1044 base::WriteUnalignedValue(addr, value);
1047void Simulator::WriteH(int32_t addr, int16_t value) {
1050 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1051 local_monitor_.NotifyStore(addr);
1052 global_monitor_->NotifyStore_Locked(addr, &global_monitor_processor_);
1053 base::WriteUnalignedValue(addr, value);
1056int Simulator::WriteExH(int32_t addr, uint16_t value) {
1057 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1058 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) &&
1059 global_monitor_->NotifyStoreExcl_Locked(addr,
1060 &global_monitor_processor_)) {
1061 base::WriteUnalignedValue(addr, value);
1068uint8_t Simulator::ReadBU(int32_t addr) {
1069 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1070 local_monitor_.NotifyLoad(addr);
1071 return base::ReadUnalignedValue<uint8_t>(addr);
1074int8_t Simulator::ReadB(int32_t addr) {
1075 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1076 local_monitor_.NotifyLoad(addr);
1077 return base::ReadUnalignedValue<int8_t>(addr);
1080uint8_t Simulator::ReadExBU(int32_t addr) {
1081 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1082 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte);
1083 global_monitor_->NotifyLoadExcl_Locked(addr, &global_monitor_processor_);
1084 return base::ReadUnalignedValue<uint8_t>(addr);
1087void Simulator::WriteB(int32_t addr, uint8_t value) {
1088 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1089 local_monitor_.NotifyStore(addr);
1090 global_monitor_->NotifyStore_Locked(addr, &global_monitor_processor_);
1091 base::WriteUnalignedValue(addr, value);
1094void Simulator::WriteB(int32_t addr, int8_t value) {
1095 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1096 local_monitor_.NotifyStore(addr);
1097 global_monitor_->NotifyStore_Locked(addr, &global_monitor_processor_);
1098 base::WriteUnalignedValue(addr, value);
1101int Simulator::WriteExB(int32_t addr, uint8_t value) {
1102 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1103 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) &&
1104 global_monitor_->NotifyStoreExcl_Locked(addr,
1105 &global_monitor_processor_)) {
1106 base::WriteUnalignedValue(addr, value);
1113int32_t* Simulator::ReadDW(int32_t addr) {
1116 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1117 local_monitor_.NotifyLoad(addr);
1118 return reinterpret_cast<int32_t*
>(addr);
1121int32_t* Simulator::ReadExDW(int32_t addr) {
1122 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1123 local_monitor_.NotifyLoadExcl(addr, TransactionSize::DoubleWord);
1124 global_monitor_->NotifyLoadExcl_Locked(addr, &global_monitor_processor_);
1125 return reinterpret_cast<int32_t*
>(addr);
1128void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1131 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1132 local_monitor_.NotifyStore(addr);
1133 global_monitor_->NotifyStore_Locked(addr, &global_monitor_processor_);
1134 base::WriteUnalignedValue(addr, value1);
1135 base::WriteUnalignedValue(addr +
sizeof(value1), value2);
1138int Simulator::WriteExDW(int32_t addr, int32_t value1, int32_t value2) {
1139 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
1140 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::DoubleWord) &&
1141 global_monitor_->NotifyStoreExcl_Locked(addr,
1142 &global_monitor_processor_)) {
1143 base::WriteUnalignedValue(addr, value1);
1144 base::WriteUnalignedValue(addr +
sizeof(value1), value2);
1152uintptr_t Simulator::StackLimit(uintptr_t c_limit)
const {
1155 if (base::Stack::GetCurrentStackPosition() < c_limit) {
1156 return reinterpret_cast<uintptr_t
>(get_sp());
1161 return reinterpret_cast<uintptr_t
>(stack_) + kAdditionalStackMargin;
1164uintptr_t Simulator::StackBase()
const {
1165 return reinterpret_cast<uintptr_t
>(stack_) + kUsableStackSize;
1168base::Vector<uint8_t> Simulator::GetCentralStackView()
const {
1172 return base::VectorOf(stack_, kUsableStackSize);
1176 for (
int i = 0;
i < num_registers; ++
i) {
1177 visitor->
VisitPointer(
reinterpret_cast<const void*
>(get_register(
i)));
1180 for (
const void*
const* current =
1181 reinterpret_cast<const void* const*
>(get_sp());
1183 const void* address = *
current;
1184 if (address ==
nullptr) {
1192void Simulator::Format(Instruction*
instr,
const char* format) {
1193 PrintF(
"Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
1194 reinterpret_cast<intptr_t
>(
instr), format);
1200bool Simulator::ConditionallyExecute(Instruction*
instr) {
1201 switch (
instr->ConditionField()) {
1219 return c_flag_ && !z_flag_;
1221 return !c_flag_ || z_flag_;
1223 return n_flag_ == v_flag_;
1225 return n_flag_ != v_flag_;
1227 return !z_flag_ && (n_flag_ == v_flag_);
1229 return z_flag_ || (n_flag_ != v_flag_);
1238void Simulator::SetNZFlags(int32_t val) {
1239 n_flag_ = (val < 0);
1240 z_flag_ = (val == 0);
1244void Simulator::SetCFlag(
bool val) { c_flag_ = val; }
1247void Simulator::SetVFlag(
bool val) { v_flag_ = val; }
1250bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1251 uint32_t uleft =
static_cast<uint32_t
>(left);
1252 uint32_t uright =
static_cast<uint32_t
>(right);
1253 uint32_t urest = 0xFFFFFFFFU - uleft;
1255 return (uright > urest) ||
1256 (
carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1260bool Simulator::BorrowFrom(int32_t left, int32_t right, int32_t carry) {
1261 uint32_t uleft =
static_cast<uint32_t
>(left);
1262 uint32_t uright =
static_cast<uint32_t
>(right);
1264 return (uright > uleft) ||
1265 (!
carry && (((uright + 1) > uleft) || (uright > (uleft - 1))));
1269bool Simulator::OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
1274 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1276 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1279 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1281 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1287void Simulator::Compute_FPSCR_Flags(
float val1,
float val2) {
1288 if (std::isnan(val1) || std::isnan(val2)) {
1289 n_flag_FPSCR_ =
false;
1290 z_flag_FPSCR_ =
false;
1291 c_flag_FPSCR_ =
true;
1292 v_flag_FPSCR_ =
true;
1294 }
else if (val1 == val2) {
1295 n_flag_FPSCR_ =
false;
1296 z_flag_FPSCR_ =
true;
1297 c_flag_FPSCR_ =
true;
1298 v_flag_FPSCR_ =
false;
1299 }
else if (val1 < val2) {
1300 n_flag_FPSCR_ =
true;
1301 z_flag_FPSCR_ =
false;
1302 c_flag_FPSCR_ =
false;
1303 v_flag_FPSCR_ =
false;
1306 n_flag_FPSCR_ =
false;
1307 z_flag_FPSCR_ =
false;
1308 c_flag_FPSCR_ =
true;
1309 v_flag_FPSCR_ =
false;
1313void Simulator::Compute_FPSCR_Flags(
double val1,
double val2) {
1314 if (std::isnan(val1) || std::isnan(val2)) {
1315 n_flag_FPSCR_ =
false;
1316 z_flag_FPSCR_ =
false;
1317 c_flag_FPSCR_ =
true;
1318 v_flag_FPSCR_ =
true;
1320 }
else if (val1 == val2) {
1321 n_flag_FPSCR_ =
false;
1322 z_flag_FPSCR_ =
true;
1323 c_flag_FPSCR_ =
true;
1324 v_flag_FPSCR_ =
false;
1325 }
else if (val1 < val2) {
1326 n_flag_FPSCR_ =
true;
1327 z_flag_FPSCR_ =
false;
1328 c_flag_FPSCR_ =
false;
1329 v_flag_FPSCR_ =
false;
1332 n_flag_FPSCR_ =
false;
1333 z_flag_FPSCR_ =
false;
1334 c_flag_FPSCR_ =
true;
1335 v_flag_FPSCR_ =
false;
1339void Simulator::Copy_FPSCR_to_APSR() {
1340 n_flag_ = n_flag_FPSCR_;
1341 z_flag_ = z_flag_FPSCR_;
1342 c_flag_ = c_flag_FPSCR_;
1343 v_flag_ = v_flag_FPSCR_;
1348int32_t Simulator::GetShiftRm(Instruction*
instr,
bool* carry_out) {
1350 int shift_amount =
instr->ShiftAmountValue();
1352 if (
instr->Bit(4) == 0) {
1354 if ((shift == ROR) && (shift_amount == 0)) {
1356 }
else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1361 if (shift_amount == 0) {
1370 result >>= (shift_amount - 1);
1371 *carry_out = (
result & 1) == 1;
1378 if (shift_amount == 0) {
1379 *carry_out = c_flag_;
1381 result =
static_cast<uint32_t
>(
result) << (shift_amount - 1);
1382 *carry_out = (
result < 0);
1389 if (shift_amount == 0) {
1391 *carry_out = c_flag_;
1393 uint32_t uresult =
static_cast<uint32_t
>(
result);
1394 uresult >>= (shift_amount - 1);
1395 *carry_out = (uresult & 1) == 1;
1403 if (shift_amount == 0) {
1404 *carry_out = c_flag_;
1406 result = base::bits::RotateRight32(
result, shift_amount);
1407 *carry_out = (
static_cast<uint32_t
>(
result) >> 31) != 0;
1418 int rs =
instr->RsValue();
1419 shift_amount = get_register(rs) & 0xFF;
1422 if (shift_amount == 0) {
1423 *carry_out = c_flag_;
1424 }
else if (shift_amount < 32) {
1425 result >>= (shift_amount - 1);
1426 *carry_out = (
result & 1) == 1;
1442 if (shift_amount == 0) {
1443 *carry_out = c_flag_;
1444 }
else if (shift_amount < 32) {
1445 result =
static_cast<uint32_t
>(
result) << (shift_amount - 1);
1446 *carry_out = (
result < 0);
1448 }
else if (shift_amount == 32) {
1449 *carry_out = (
result & 1) == 1;
1460 if (shift_amount == 0) {
1461 *carry_out = c_flag_;
1462 }
else if (shift_amount < 32) {
1463 uint32_t uresult =
static_cast<uint32_t
>(
result);
1464 uresult >>= (shift_amount - 1);
1465 *carry_out = (uresult & 1) == 1;
1468 }
else if (shift_amount == 32) {
1469 *carry_out = (
result < 0);
1479 if (shift_amount == 0) {
1480 *carry_out = c_flag_;
1483 result = base::bits::RotateRight32(
result, shift_amount & 31);
1484 *carry_out = (
static_cast<uint32_t
>(
result) >> 31) != 0;
1499int32_t Simulator::GetImm(Instruction*
instr,
bool* carry_out) {
1500 int rotate =
instr->RotateValue() * 2;
1501 int immed8 =
instr->Immed8Value();
1502 int imm = base::bits::RotateRight32(immed8, rotate);
1503 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1507static int count_bits(
int bit_vector) {
1509 while (bit_vector != 0) {
1510 if ((bit_vector & 1) != 0) {
1518int32_t Simulator::ProcessPU(Instruction*
instr,
int num_regs,
int reg_size,
1519 intptr_t* start_address, intptr_t* end_address) {
1520 int rn =
instr->RnValue();
1521 int32_t rn_val = get_register(rn);
1522 switch (
instr->PUField()) {
1527 *start_address = rn_val;
1528 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1529 rn_val = rn_val + (num_regs * reg_size);
1533 *start_address = rn_val - (num_regs * reg_size);
1534 *end_address = rn_val - reg_size;
1535 rn_val = *start_address;
1539 *start_address = rn_val + reg_size;
1540 *end_address = rn_val + (num_regs * reg_size);
1541 rn_val = *end_address;
1552void Simulator::HandleRList(Instruction*
instr,
bool load) {
1553 int rlist =
instr->RlistValue();
1554 int num_regs = count_bits(rlist);
1556 intptr_t start_address = 0;
1557 intptr_t end_address = 0;
1559 ProcessPU(
instr, num_regs, kPointerSize, &start_address, &end_address);
1561 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1563 DCHECK(start_address > 8191 || start_address < 0);
1565 while (rlist != 0) {
1566 if ((rlist & 1) != 0) {
1568 set_register(
reg, *address);
1570 *address = get_register(
reg);
1577 DCHECK(end_address == ((intptr_t)address) - 4);
1578 if (
instr->HasW()) {
1579 set_register(
instr->RnValue(), rn_val);
1584void Simulator::HandleVList(Instruction*
instr) {
1589 bool load = (
instr->VLValue() == 0x1);
1595 num_regs =
instr->Immed8Value();
1597 num_regs =
instr->Immed8Value() / 2;
1600 intptr_t start_address = 0;
1601 intptr_t end_address = 0;
1603 ProcessPU(
instr, num_regs, operand_size, &start_address, &end_address);
1605 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1606 for (
int reg = vd;
reg < vd + num_regs;
reg++) {
1609 set_s_register_from_sinteger(
reg,
1610 ReadW(
reinterpret_cast<int32_t>(address)));
1612 WriteW(
reinterpret_cast<int32_t>(address),
1613 get_sinteger_from_s_register(
reg));
1619 ReadW(
reinterpret_cast<int32_t>(address + 1))};
1620 set_d_register(
reg,
reinterpret_cast<uint32_t*
>(data));
1623 get_d_register(
reg, data);
1624 WriteW(
reinterpret_cast<int32_t>(address), data[0]);
1625 WriteW(
reinterpret_cast<int32_t>(address + 1), data[1]);
1630 DCHECK(
reinterpret_cast<intptr_t
>(address) - operand_size == end_address);
1631 if (
instr->HasW()) {
1632 set_register(
instr->RnValue(), rn_val);
1642using SimulatorRuntimeCall = int64_t (*)(
1649using SimulatorRuntimeCompareCall = int64_t (*)(
double darg0,
double darg1);
1650using SimulatorRuntimeFPFPCall = double (*)(
double darg0,
double darg1);
1651using SimulatorRuntimeFPCall = double (*)(
double darg0);
1652using SimulatorRuntimeFPIntCall = double (*)(
double darg0,
int32_t arg0);
1653using SimulatorRuntimeIntFPCall =
int32_t (*)(
double darg0);
1656using SimulatorRuntimeFPTaggedCall = double (*)(
int32_t arg0,
int32_t arg1,
1661using SimulatorRuntimeDirectApiCall = void (*)(
int32_t arg0);
1664using SimulatorRuntimeDirectGetterCall = void (*)(
int32_t arg0,
int32_t arg1);
1670int64_t UnsafeGenericFunctionCall(intptr_t function, int32_t arg0, int32_t arg1,
1671 int32_t arg2, int32_t arg3, int32_t arg4,
1672 int32_t arg5, int32_t arg6, int32_t arg7,
1673 int32_t arg8, int32_t arg9, int32_t arg10,
1674 int32_t arg11, int32_t arg12, int32_t arg13,
1675 int32_t arg14, int32_t arg15, int32_t arg16,
1676 int32_t arg17, int32_t arg18, int32_t arg19) {
1677 SimulatorRuntimeCall target =
1678 reinterpret_cast<SimulatorRuntimeCall
>(function);
1679 return target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
1680 arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18,
1686void Simulator::SoftwareInterrupt(Instruction*
instr) {
1687 int svc =
instr->SvcValue();
1692 bool stack_aligned =
1693 (get_register(sp) & (
v8_flags.sim_stack_alignment - 1)) == 0;
1694 Redirection* redirection = Redirection::FromInstruction(
instr);
1695 int32_t arg0 = get_register(r0);
1696 int32_t arg1 = get_register(r1);
1697 int32_t arg2 = get_register(r2);
1698 int32_t arg3 = get_register(r3);
1699 int32_t* stack_pointer =
reinterpret_cast<int32_t*
>(get_register(sp));
1700 int32_t arg4 = stack_pointer[0];
1701 int32_t arg5 = stack_pointer[1];
1702 int32_t arg6 = stack_pointer[2];
1703 int32_t arg7 = stack_pointer[3];
1704 int32_t arg8 = stack_pointer[4];
1705 int32_t arg9 = stack_pointer[5];
1706 int32_t arg10 = stack_pointer[6];
1707 int32_t arg11 = stack_pointer[7];
1708 int32_t arg12 = stack_pointer[8];
1709 int32_t arg13 = stack_pointer[9];
1710 int32_t arg14 = stack_pointer[10];
1711 int32_t arg15 = stack_pointer[11];
1712 int32_t arg16 = stack_pointer[12];
1713 int32_t arg17 = stack_pointer[13];
1714 int32_t arg18 = stack_pointer[14];
1715 int32_t arg19 = stack_pointer[15];
1716 static_assert(kMaxCParameters == 20);
1719 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1720 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1721 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1722 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL) ||
1723 (redirection->type() == ExternalReference::BUILTIN_INT_FP_CALL);
1726 int32_t saved_lr = get_register(lr);
1728 reinterpret_cast<intptr_t
>(redirection->external_function());
1730 double dval0, dval1;
1732 int64_t iresult = 0;
1734 GetFpArgs(&dval0, &dval1, &ival);
1735 if (InstructionTracingEnabled() || !stack_aligned) {
1736 SimulatorRuntimeCall generic_target =
1737 reinterpret_cast<SimulatorRuntimeCall
>(external);
1738 switch (redirection->type()) {
1739 case ExternalReference::BUILTIN_FP_FP_CALL:
1740 case ExternalReference::BUILTIN_COMPARE_CALL:
1741 PrintF(
"Call to host function at %p with args %f, %f",
1745 case ExternalReference::BUILTIN_FP_CALL:
1746 PrintF(
"Call to host function at %p with arg %f",
1750 case ExternalReference::BUILTIN_FP_INT_CALL:
1751 PrintF(
"Call to host function at %p with args %f, %d",
1755 case ExternalReference::BUILTIN_INT_FP_CALL:
1756 PrintF(
"Call to host function at %p with args %f",
1763 if (!stack_aligned) {
1764 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1768 CHECK(stack_aligned);
1769 switch (redirection->type()) {
1770 case ExternalReference::BUILTIN_COMPARE_CALL: {
1771 SimulatorRuntimeCompareCall target =
1772 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
1773 iresult =
target(dval0, dval1);
1775 TrashCallerSaveRegisters();
1777 set_register(r0,
static_cast<int32_t>(iresult));
1778 set_register(r1,
static_cast<int32_t>(iresult >> 32));
1781 case ExternalReference::BUILTIN_FP_FP_CALL: {
1782 SimulatorRuntimeFPFPCall target =
1783 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
1784 dresult =
target(dval0, dval1);
1786 TrashCallerSaveRegisters();
1788 SetFpResult(dresult);
1791 case ExternalReference::BUILTIN_FP_CALL: {
1792 SimulatorRuntimeFPCall target =
1793 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1796 TrashCallerSaveRegisters();
1798 SetFpResult(dresult);
1801 case ExternalReference::BUILTIN_FP_INT_CALL: {
1802 SimulatorRuntimeFPIntCall target =
1803 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
1804 dresult =
target(dval0, ival);
1806 TrashCallerSaveRegisters();
1808 SetFpResult(dresult);
1811 case ExternalReference::BUILTIN_INT_FP_CALL: {
1812 SimulatorRuntimeIntFPCall target =
1813 reinterpret_cast<SimulatorRuntimeIntFPCall
>(external);
1816 TrashCallerSaveRegisters();
1818 set_register(r0,
static_cast<int32_t>(iresult));
1824 if (InstructionTracingEnabled()) {
1825 switch (redirection->type()) {
1826 case ExternalReference::BUILTIN_COMPARE_CALL:
1827 case ExternalReference::BUILTIN_INT_FP_CALL:
1830 case ExternalReference::BUILTIN_FP_FP_CALL:
1831 case ExternalReference::BUILTIN_FP_CALL:
1832 case ExternalReference::BUILTIN_FP_INT_CALL:
1833 PrintF(
"Returned %f\n", dresult);
1839 }
else if (redirection->type() ==
1840 ExternalReference::BUILTIN_FP_POINTER_CALL) {
1841 if (InstructionTracingEnabled() || !stack_aligned) {
1842 PrintF(
"Call to host function at %p args %08x",
1843 reinterpret_cast<void*
>(external), arg0);
1844 if (!stack_aligned) {
1845 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1849 CHECK(stack_aligned);
1850 SimulatorRuntimeFPTaggedCall target =
1851 reinterpret_cast<SimulatorRuntimeFPTaggedCall
>(external);
1852 double dresult =
target(arg0, arg1, arg2, arg3);
1854 TrashCallerSaveRegisters();
1856 SetFpResult(dresult);
1857 if (InstructionTracingEnabled()) {
1858 PrintF(
"Returned %f\n", dresult);
1860 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1862 if (InstructionTracingEnabled() || !stack_aligned) {
1863 PrintF(
"Call to host function at %p args %08x",
1864 reinterpret_cast<void*
>(external), arg0);
1865 if (!stack_aligned) {
1866 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1870 CHECK(stack_aligned);
1871 SimulatorRuntimeDirectApiCall target =
1872 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1875 TrashCallerSaveRegisters();
1877 }
else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1879 if (InstructionTracingEnabled() || !stack_aligned) {
1880 PrintF(
"Call to host function at %p args %08x %08x",
1881 reinterpret_cast<void*
>(external), arg0, arg1);
1882 if (!stack_aligned) {
1883 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1887 CHECK(stack_aligned);
1888 SimulatorRuntimeDirectGetterCall target =
1889 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1892 TrashCallerSaveRegisters();
1906 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
1907 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR ||
1908 redirection->type() == ExternalReference::FAST_C_CALL);
1909 if (InstructionTracingEnabled() || !stack_aligned) {
1911 "Call to host function at %p "
1912 "args %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, "
1913 "%08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, "
1915 reinterpret_cast<void*
>(external), arg0, arg1, arg2, arg3, arg4,
1916 arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,
1917 arg15, arg16, arg17, arg18, arg19);
1918 if (!stack_aligned) {
1919 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1923 CHECK(stack_aligned);
1924 int64_t
result = UnsafeGenericFunctionCall(
1925 external, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
1926 arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18,
1929 TrashCallerSaveRegisters();
1933 if (InstructionTracingEnabled()) {
1934 PrintF(
"Returned %08x\n", lo_res);
1936 set_register(r0, lo_res);
1937 set_register(r1, hi_res);
1939 set_register(lr, saved_lr);
1940 set_pc(get_register(lr));
1944 ArmDebugger(
this).Debug();
1948 if (svc >= (1 << 23)) {
1950 if (isWatchedStop(code)) {
1951 IncreaseStopCounter(code);
1955 if (isEnabledStop(code)) {
1956 if (code != kMaxStopCode) {
1957 PrintF(
"Simulator hit stop %u. ", code);
1959 PrintF(
"Simulator hit stop. ");
1970float Simulator::canonicalizeNaN(
float value) {
1973 constexpr uint32_t kDefaultNaN = 0x7FC00000u;
1974 if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1975 value = base::bit_cast<float>(kDefaultNaN);
1980Float32 Simulator::canonicalizeNaN(Float32 value) {
1983 constexpr Float32 kDefaultNaN = Float32::FromBits(0x7FC00000u);
1984 return FPSCR_default_NaN_mode_ && value.is_nan() ? kDefaultNaN :
value;
1987double Simulator::canonicalizeNaN(
double value) {
1990 constexpr uint64_t kDefaultNaN = uint64_t{0x7FF8000000000000};
1991 if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1992 value = base::bit_cast<double>(kDefaultNaN);
1997Float64 Simulator::canonicalizeNaN(Float64 value) {
2000 constexpr Float64 kDefaultNaN =
2001 Float64::FromBits(uint64_t{0x7FF8000000000000});
2002 return FPSCR_default_NaN_mode_ && value.is_nan() ? kDefaultNaN :
value;
2006bool Simulator::isWatchedStop(uint32_t code) {
2008 return code < kNumOfWatchedStops;
2011bool Simulator::isEnabledStop(uint32_t code) {
2014 return !isWatchedStop(code) ||
2015 !(watched_stops_[
code].count & kStopDisabledBit);
2018void Simulator::EnableStop(uint32_t code) {
2019 DCHECK(isWatchedStop(code));
2020 if (!isEnabledStop(code)) {
2021 watched_stops_[
code].count &= ~kStopDisabledBit;
2025void Simulator::DisableStop(uint32_t code) {
2026 DCHECK(isWatchedStop(code));
2027 if (isEnabledStop(code)) {
2028 watched_stops_[
code].count |= kStopDisabledBit;
2032void Simulator::IncreaseStopCounter(uint32_t code) {
2034 DCHECK(isWatchedStop(code));
2035 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
2037 "Stop counter for code %i has overflowed.\n"
2038 "Enabling this code and reseting the counter to 0.\n",
2040 watched_stops_[
code].count = 0;
2043 watched_stops_[
code].count++;
2048void Simulator::PrintStopInfo(uint32_t code) {
2050 if (!isWatchedStop(code)) {
2051 PrintF(
"Stop not watched.");
2053 const char* state = isEnabledStop(code) ?
"Enabled" :
"Disabled";
2054 int32_t count = watched_stops_[
code].count & ~kStopDisabledBit;
2057 if (watched_stops_[code].desc) {
2058 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", code, code,
2059 state, count, watched_stops_[code].desc);
2061 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n", code, code, state,
2072void Simulator::DecodeType01(Instruction*
instr) {
2073 int type =
instr->TypeValue();
2074 if ((type == 0) &&
instr->IsSpecialType0()) {
2076 if (
instr->Bits(7, 4) == 9) {
2077 if (
instr->Bit(24) == 0) {
2080 int rn =
instr->RnValue();
2081 int rm =
instr->RmValue();
2082 int rs =
instr->RsValue();
2083 int32_t rs_val = get_register(rs);
2084 int32_t rm_val = get_register(rm);
2085 if (
instr->Bit(23) == 0) {
2086 if (
instr->Bit(21) == 0) {
2092 int32_t alu_out = base::MulWithWraparound(rm_val, rs_val);
2093 set_register(rd, alu_out);
2094 if (
instr->HasS()) {
2095 SetNZFlags(alu_out);
2098 int rd =
instr->RdValue();
2099 int32_t acc_value = get_register(rd);
2100 if (
instr->Bit(22) == 0) {
2106 int32_t mul_out = base::MulWithWraparound(rm_val, rs_val);
2107 int32_t result = base::AddWithWraparound(acc_value, mul_out);
2108 set_register(rn,
result);
2111 int32_t mul_out = base::MulWithWraparound(rm_val, rs_val);
2112 int32_t result = base::SubWithWraparound(acc_value, mul_out);
2113 set_register(rn,
result);
2128 int rd_lo =
instr->RdValue();
2131 if (
instr->Bit(22) == 1) {
2132 int64_t left_op =
static_cast<int32_t>(rm_val);
2133 int64_t right_op =
static_cast<int32_t>(rs_val);
2134 uint64_t
result = left_op * right_op;
2139 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
2140 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
2141 uint64_t
result = left_op * right_op;
2145 set_register(rd_lo, lo_res);
2146 set_register(rd_hi, hi_res);
2147 if (
instr->HasS()) {
2152 if (
instr->Bits(24, 23) == 3) {
2153 if (
instr->Bit(20) == 1) {
2155 int rt =
instr->RtValue();
2156 int rn =
instr->RnValue();
2157 int32_t addr = get_register(rn);
2158 switch (
instr->Bits(22, 21)) {
2161 int value = ReadExW(addr);
2162 set_register(rt, value);
2167 int* rn_data = ReadExDW(addr);
2168 set_dw_register(rt, rn_data);
2173 uint8_t value = ReadExBU(addr);
2174 set_register(rt, value);
2180 set_register(rt, value);
2189 int rd =
instr->RdValue();
2190 int rt =
instr->RmValue();
2191 int rn =
instr->RnValue();
2194 int32_t addr = get_register(rn);
2195 switch (
instr->Bits(22, 21)) {
2198 int value = get_register(rt);
2199 int status = WriteExW(addr, value);
2200 set_register(rd, status);
2206 int32_t value1 = get_register(rt);
2207 int32_t value2 = get_register(rt + 1);
2208 int status = WriteExDW(addr, value1, value2);
2209 set_register(rd, status);
2214 uint8_t value = get_register(rt);
2215 int status = WriteExB(addr, value);
2216 set_register(rd, status);
2222 int status = WriteExH(addr, value);
2223 set_register(rd, status);
2236 int rd =
instr->RdValue();
2237 int rn =
instr->RnValue();
2238 int32_t rn_val = get_register(rn);
2240 if (
instr->Bit(22) == 0) {
2241 int rm =
instr->RmValue();
2242 int32_t rm_val = get_register(rm);
2243 switch (
instr->PUField()) {
2248 rn_val = base::SubWithWraparound(rn_val, rm_val);
2249 set_register(rn, rn_val);
2256 rn_val = base::AddWithWraparound(rn_val, rm_val);
2257 set_register(rn, rn_val);
2262 rn_val = base::SubWithWraparound(rn_val, rm_val);
2264 if (
instr->HasW()) {
2265 set_register(rn, rn_val);
2271 rn_val = base::AddWithWraparound(rn_val, rm_val);
2273 if (
instr->HasW()) {
2274 set_register(rn, rn_val);
2285 switch (
instr->PUField()) {
2290 rn_val = base::SubWithWraparound(rn_val, imm_val);
2291 set_register(rn, rn_val);
2298 rn_val = base::AddWithWraparound(rn_val, imm_val);
2299 set_register(rn, rn_val);
2304 rn_val = base::SubWithWraparound(rn_val, imm_val);
2306 if (
instr->HasW()) {
2307 set_register(rn, rn_val);
2313 rn_val = base::AddWithWraparound(rn_val, imm_val);
2315 if (
instr->HasW()) {
2316 set_register(rn, rn_val);
2326 if (((
instr->Bits(7, 4) & 0xD) == 0xD) && (
instr->Bit(20) == 0)) {
2328 if (
instr->HasH()) {
2330 int32_t value1 = get_register(rd);
2331 int32_t value2 = get_register(rd + 1);
2332 WriteDW(addr, value1, value2);
2335 int* rn_data = ReadDW(addr);
2336 set_dw_register(rd, rn_data);
2338 }
else if (
instr->HasH()) {
2339 if (
instr->HasSign()) {
2340 if (
instr->HasL()) {
2342 set_register(rd, val);
2344 int16_t val = get_register(rd);
2348 if (
instr->HasL()) {
2350 set_register(rd, val);
2360 int8_t val = ReadB(addr);
2361 set_register(rd, val);
2365 }
else if ((type == 0) &&
instr->IsMiscType0()) {
2366 if ((
instr->Bits(27, 23) == 2) && (
instr->Bits(21, 20) == 2) &&
2367 (
instr->Bits(15, 4) == 0xF00)) {
2369 int rm =
instr->RmValue();
2372 instr->BitField(22, 22) |
instr->BitField(19, 16);
2373 SetSpecialRegister(sreg_and_mask, get_register(rm));
2374 }
else if ((
instr->Bits(27, 23) == 2) && (
instr->Bits(21, 20) == 0) &&
2375 (
instr->Bits(11, 0) == 0)) {
2377 int rd =
instr->RdValue();
2380 set_register(rd, GetFromSpecialRegister(sreg));
2381 }
else if (
instr->Bits(22, 21) == 1) {
2382 int rm =
instr->RmValue();
2383 switch (
instr->BitField(7, 4)) {
2385 set_pc(get_register(rm));
2388 uint32_t old_pc = get_pc();
2389 set_pc(get_register(rm));
2390 set_register(lr, old_pc + kInstrSize);
2394 PrintF(
"Simulator hit BKPT. ");
2400 }
else if (
instr->Bits(22, 21) == 3) {
2401 int rm =
instr->RmValue();
2402 int rd =
instr->RdValue();
2403 switch (
instr->BitField(7, 4)) {
2405 uint32_t bits = get_register(rm);
2410 while ((bits & 0x80000000u) == 0) {
2415 set_register(rd, leading_zeros);
2425 }
else if ((type == 1) &&
instr->IsNopLikeType1()) {
2426 if (
instr->BitField(7, 0) == 0) {
2428 }
else if (
instr->BitField(7, 0) == 20) {
2435 int rd =
instr->RdValue();
2436 int rn =
instr->RnValue();
2437 int32_t rn_val = get_register(rn);
2439 bool shifter_carry_out =
false;
2441 shifter_operand = GetShiftRm(
instr, &shifter_carry_out);
2444 shifter_operand = GetImm(
instr, &shifter_carry_out);
2448 switch (
instr->OpcodeField()) {
2452 alu_out = rn_val & shifter_operand;
2453 set_register(rd, alu_out);
2454 if (
instr->HasS()) {
2455 SetNZFlags(alu_out);
2456 SetCFlag(shifter_carry_out);
2464 alu_out = rn_val ^ shifter_operand;
2465 set_register(rd, alu_out);
2466 if (
instr->HasS()) {
2467 SetNZFlags(alu_out);
2468 SetCFlag(shifter_carry_out);
2476 alu_out = base::SubWithWraparound(rn_val, shifter_operand);
2477 set_register(rd, alu_out);
2478 if (
instr->HasS()) {
2479 SetNZFlags(alu_out);
2480 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2481 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2489 alu_out = base::SubWithWraparound(shifter_operand, rn_val);
2490 set_register(rd, alu_out);
2491 if (
instr->HasS()) {
2492 SetNZFlags(alu_out);
2493 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2494 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val,
false));
2502 alu_out = base::AddWithWraparound(rn_val, shifter_operand);
2503 set_register(rd, alu_out);
2504 if (
instr->HasS()) {
2505 SetNZFlags(alu_out);
2506 SetCFlag(CarryFrom(rn_val, shifter_operand));
2507 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2515 alu_out = base::AddWithWraparound(
2516 base::AddWithWraparound(rn_val, shifter_operand), GetCarry());
2517 set_register(rd, alu_out);
2518 if (
instr->HasS()) {
2519 SetNZFlags(alu_out);
2520 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2521 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2529 alu_out = base::SubWithWraparound(
2530 base::SubWithWraparound(rn_val, shifter_operand),
2531 (GetCarry() ? 0 : 1));
2532 set_register(rd, alu_out);
2533 if (
instr->HasS()) {
2534 SetNZFlags(alu_out);
2535 SetCFlag(!BorrowFrom(rn_val, shifter_operand, GetCarry()));
2536 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2542 Format(
instr,
"rsc'cond's 'rd, 'rn, 'shift_rm");
2543 Format(
instr,
"rsc'cond's 'rd, 'rn, 'imm");
2548 if (
instr->HasS()) {
2551 alu_out = rn_val & shifter_operand;
2552 SetNZFlags(alu_out);
2553 SetCFlag(shifter_carry_out);
2556 alu_out =
instr->ImmedMovwMovtValue();
2557 set_register(rd, alu_out);
2563 if (
instr->HasS()) {
2566 alu_out = rn_val ^ shifter_operand;
2567 SetNZFlags(alu_out);
2568 SetCFlag(shifter_carry_out);
2578 if (
instr->HasS()) {
2581 alu_out = base::SubWithWraparound(rn_val, shifter_operand);
2582 SetNZFlags(alu_out);
2583 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2584 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2588 (get_register(rd) & 0xFFFF) | (
instr->ImmedMovwMovtValue() << 16);
2589 set_register(rd, alu_out);
2595 if (
instr->HasS()) {
2598 alu_out = base::AddWithWraparound(rn_val, shifter_operand);
2599 SetNZFlags(alu_out);
2600 SetCFlag(CarryFrom(rn_val, shifter_operand));
2601 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2613 alu_out = rn_val | shifter_operand;
2614 set_register(rd, alu_out);
2615 if (
instr->HasS()) {
2616 SetNZFlags(alu_out);
2617 SetCFlag(shifter_carry_out);
2625 alu_out = shifter_operand;
2626 set_register(rd, alu_out);
2627 if (
instr->HasS()) {
2628 SetNZFlags(alu_out);
2629 SetCFlag(shifter_carry_out);
2637 alu_out = rn_val & ~shifter_operand;
2638 set_register(rd, alu_out);
2639 if (
instr->HasS()) {
2640 SetNZFlags(alu_out);
2641 SetCFlag(shifter_carry_out);
2649 alu_out = ~shifter_operand;
2650 set_register(rd, alu_out);
2651 if (
instr->HasS()) {
2652 SetNZFlags(alu_out);
2653 SetCFlag(shifter_carry_out);
2665void Simulator::DecodeType2(Instruction*
instr) {
2666 int rd =
instr->RdValue();
2667 int rn =
instr->RnValue();
2668 int32_t rn_val = get_register(rn);
2671 switch (
instr->PUField()) {
2677 set_register(rn, rn_val);
2685 set_register(rn, rn_val);
2692 if (
instr->HasW()) {
2693 set_register(rn, rn_val);
2701 if (
instr->HasW()) {
2702 set_register(rn, rn_val);
2710 if (
instr->HasB()) {
2711 if (
instr->HasL()) {
2712 uint8_t val = ReadBU(addr);
2713 set_register(rd, val);
2715 uint8_t val = get_register(rd);
2719 if (
instr->HasL()) {
2720 set_register(rd, ReadW(addr));
2722 WriteW(addr, get_register(rd));
2727void Simulator::DecodeType3(Instruction*
instr) {
2728 int rd =
instr->RdValue();
2729 int rn =
instr->RnValue();
2730 int32_t rn_val = get_register(rn);
2731 bool shifter_carry_out =
false;
2732 int32_t shifter_operand = GetShiftRm(
instr, &shifter_carry_out);
2734 switch (
instr->PUField()) {
2737 Format(
instr,
"'memop'cond'b 'rd, ['rn], -'shift_rm");
2741 if (
instr->Bit(4) == 0) {
2744 if (
instr->Bit(5) == 0) {
2745 switch (
instr->Bits(22, 21)) {
2747 if (
instr->Bit(20) == 0) {
2748 if (
instr->Bit(6) == 0) {
2750 uint32_t rn_val = get_register(rn);
2751 uint32_t rm_val = get_register(
instr->RmValue());
2754 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2757 uint32_t rn_val = get_register(rn);
2764 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2777 int32_t sat_val = (1 << sat_pos) - 1;
2781 if (shift_type == 0) {
2789 if (rm_val > sat_val) {
2791 }
else if (rm_val < 0) {
2794 set_register(rd, rm_val);
2799 switch (
instr->Bits(22, 21)) {
2803 if (
instr->Bits(9, 6) == 1) {
2804 if (
instr->Bit(20) == 0) {
2805 if (
instr->Bits(19, 16) == 0xF) {
2813 rm_val = (rm_val >> 8) | (rm_val << 24);
2816 rm_val = (rm_val >> 16) | (rm_val << 16);
2819 rm_val = (rm_val >> 24) | (rm_val << 8);
2822 set_register(rd,
static_cast<int8_t
>(rm_val));
2825 int32_t rn_val = get_register(rn);
2832 rm_val = (rm_val >> 8) | (rm_val << 24);
2835 rm_val = (rm_val >> 16) | (rm_val << 16);
2838 rm_val = (rm_val >> 24) | (rm_val << 8);
2841 set_register(rd, rn_val +
static_cast<int8_t
>(rm_val));
2844 if (
instr->Bits(19, 16) == 0xF) {
2852 rm_val = (rm_val >> 8) | (rm_val << 24);
2855 rm_val = (rm_val >> 16) | (rm_val << 16);
2858 rm_val = (rm_val >> 24) | (rm_val << 8);
2861 set_register(rd,
static_cast<int16_t>(rm_val));
2864 int32_t rn_val = get_register(rn);
2871 rm_val = (rm_val >> 8) | (rm_val << 24);
2874 rm_val = (rm_val >> 16) | (rm_val << 16);
2877 rm_val = (rm_val >> 24) | (rm_val << 8);
2880 set_register(rd, rn_val +
static_cast<int16_t>(rm_val));
2883 }
else if (
instr->Bits(27, 16) == 0x6BF &&
2884 instr->Bits(11, 4) == 0xF3) {
2886 uint32_t rm_val = get_register(
instr->RmValue());
2887 set_register(rd, ByteReverse(rm_val));
2893 if ((
instr->Bit(20) == 0) && (
instr->Bits(9, 6) == 1)) {
2894 if (
instr->Bits(19, 16) == 0xF) {
2896 uint32_t rm_val = get_register(
instr->RmValue());
2902 rm_val = (rm_val >> 8) | (rm_val << 24);
2905 rm_val = (rm_val >> 16) | (rm_val << 16);
2908 rm_val = (rm_val >> 24) | (rm_val << 8);
2911 set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
2920 if ((
instr->Bits(9, 6) == 1)) {
2921 if (
instr->Bit(20) == 0) {
2922 if (
instr->Bits(19, 16) == 0xF) {
2924 uint32_t rm_val = get_register(
instr->RmValue());
2930 rm_val = (rm_val >> 8) | (rm_val << 24);
2933 rm_val = (rm_val >> 16) | (rm_val << 16);
2936 rm_val = (rm_val >> 24) | (rm_val << 8);
2939 set_register(rd, (rm_val & 0xFF));
2942 uint32_t rn_val = get_register(rn);
2943 uint32_t rm_val = get_register(
instr->RmValue());
2949 rm_val = (rm_val >> 8) | (rm_val << 24);
2952 rm_val = (rm_val >> 16) | (rm_val << 16);
2955 rm_val = (rm_val >> 24) | (rm_val << 8);
2958 set_register(rd, rn_val + (rm_val & 0xFF));
2961 if (
instr->Bits(19, 16) == 0xF) {
2963 uint32_t rm_val = get_register(
instr->RmValue());
2969 rm_val = (rm_val >> 8) | (rm_val << 24);
2972 rm_val = (rm_val >> 16) | (rm_val << 16);
2975 rm_val = (rm_val >> 24) | (rm_val << 8);
2978 set_register(rd, (rm_val & 0xFFFF));
2981 uint32_t rn_val = get_register(rn);
2982 uint32_t rm_val = get_register(
instr->RmValue());
2988 rm_val = (rm_val >> 8) | (rm_val << 24);
2991 rm_val = (rm_val >> 16) | (rm_val << 16);
2994 rm_val = (rm_val >> 24) | (rm_val << 8);
2997 set_register(rd, rn_val + (rm_val & 0xFFFF));
3002 if ((
instr->Bits(20, 16) == 0x1F) &&
3003 (
instr->Bits(11, 4) == 0xF3)) {
3005 uint32_t rm_val = get_register(
instr->RmValue());
3006 set_register(rd, base::bits::ReverseBits(rm_val));
3019 if (
instr->Bits(22, 20) == 0x5) {
3020 if (
instr->Bits(7, 4) == 0x1) {
3021 int rm =
instr->RmValue();
3022 int32_t rm_val = get_register(rm);
3023 int rs =
instr->RsValue();
3024 int32_t rs_val = get_register(rs);
3025 if (
instr->Bits(15, 12) == 0xF) {
3028 rn_val = base::bits::SignedMulHigh32(rm_val, rs_val);
3032 int rd =
instr->RdValue();
3033 int32_t rd_val = get_register(rd);
3034 rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val);
3036 set_register(rn, rn_val);
3040 if (
instr->Bits(5, 4) == 0x1) {
3041 if ((
instr->Bit(22) == 0x0) && (
instr->Bit(20) == 0x1)) {
3044 int rm =
instr->RmValue();
3045 int32_t rm_val = get_register(rm);
3046 int rs =
instr->RsValue();
3047 int32_t rs_val = get_register(rs);
3050 if (
instr->Bit(21) == 0x1) {
3051 ret_val = base::bit_cast<int32_t>(
3052 base::bits::UnsignedDiv32(base::bit_cast<uint32_t>(rm_val),
3053 base::bit_cast<uint32_t>(rs_val)));
3055 ret_val = base::bits::SignedDiv32(rm_val, rs_val);
3057 set_register(rn, ret_val);
3062 addr = rn_val - shifter_operand;
3063 if (
instr->HasW()) {
3064 set_register(rn, addr);
3069 if (
instr->HasW() && (
instr->Bits(6, 4) == 0x5)) {
3070 uint32_t widthminus1 =
static_cast<uint32_t
>(
instr->Bits(20, 16));
3071 uint32_t lsbit =
static_cast<uint32_t
>(
instr->Bits(11, 7));
3072 uint32_t msbit = widthminus1 + lsbit;
3074 if (
instr->Bit(22)) {
3077 static_cast<uint32_t
>(get_register(
instr->RmValue()));
3078 uint32_t extr_val = rm_val << (31 - msbit);
3079 extr_val = extr_val >> (31 - widthminus1);
3080 set_register(
instr->RdValue(), extr_val);
3084 int32_t extr_val =
static_cast<uint32_t
>(rm_val) << (31 - msbit);
3085 extr_val = extr_val >> (31 - widthminus1);
3086 set_register(
instr->RdValue(), extr_val);
3092 }
else if (!
instr->HasW() && (
instr->Bits(6, 4) == 0x1)) {
3093 uint32_t lsbit =
static_cast<uint32_t
>(
instr->Bits(11, 7));
3094 uint32_t msbit =
static_cast<uint32_t
>(
instr->Bits(20, 16));
3095 if (msbit >= lsbit) {
3098 static_cast<uint32_t
>(get_register(
instr->RdValue()));
3099 uint32_t bitcount = msbit - lsbit + 1;
3100 uint32_t
mask = 0xFFFFFFFFu >> (32 - bitcount);
3101 rd_val &= ~(
mask << lsbit);
3102 if (
instr->RmValue() != 15) {
3105 static_cast<uint32_t
>(get_register(
instr->RmValue()));
3107 rd_val |= rm_val << lsbit;
3109 set_register(
instr->RdValue(), rd_val);
3116 addr = base::AddWithWraparound(rn_val, shifter_operand);
3117 if (
instr->HasW()) {
3118 set_register(rn, addr);
3127 if (
instr->HasB()) {
3128 if (
instr->HasL()) {
3129 uint8_t
byte = ReadB(addr);
3130 set_register(rd,
byte);
3132 uint8_t
byte = get_register(rd);
3136 if (
instr->HasL()) {
3137 set_register(rd, ReadW(addr));
3139 WriteW(addr, get_register(rd));
3144void Simulator::DecodeType4(Instruction*
instr) {
3146 if (
instr->HasL()) {
3148 HandleRList(
instr,
true);
3151 HandleRList(
instr,
false);
3155void Simulator::DecodeType5(Instruction*
instr) {
3158 static_cast<int>(
static_cast<uint32_t
>(
instr->SImmed24Value()) << 2);
3159 intptr_t pc_address = get_pc();
3160 if (
instr->HasLink()) {
3161 set_register(lr, pc_address + kInstrSize);
3163 int pc_reg = get_register(
pc);
3164 set_pc(pc_reg + off);
3167void Simulator::DecodeType6(Instruction*
instr) {
3168 DecodeType6CoprocessorIns(
instr);
3171void Simulator::DecodeType7(Instruction*
instr) {
3172 if (
instr->Bit(24) == 1) {
3173 SoftwareInterrupt(
instr);
3175 switch (
instr->CoprocessorValue()) {
3178 DecodeTypeVFP(
instr);
3181 DecodeTypeCP15(
instr);
3214void Simulator::DecodeTypeVFP(Instruction*
instr) {
3218 int m =
instr->VFPMRegValue(kSinglePrecision);
3219 int d =
instr->VFPDRegValue(kSinglePrecision);
3220 int n =
instr->VFPNRegValue(kSinglePrecision);
3222 int vm =
instr->VFPMRegValue(kDoublePrecision);
3223 int vd =
instr->VFPDRegValue(kDoublePrecision);
3224 int vn =
instr->VFPNRegValue(kDoublePrecision);
3226 if (
instr->Bit(4) == 0) {
3227 if (
instr->Opc1Value() == 0x7) {
3229 if ((
instr->Opc2Value() == 0x0) && (
instr->Opc3Value() == 0x1)) {
3231 if (
instr->SzValue() == 0x1) {
3233 get_d_register(vm, data);
3234 set_d_register(vd, data);
3236 set_s_register(d, get_s_register(
m));
3238 }
else if ((
instr->Opc2Value() == 0x0) && (
instr->Opc3Value() == 0x3)) {
3240 if (
instr->SzValue() == 0x1) {
3241 Float64 dm = get_double_from_d_register(vm);
3242 constexpr uint64_t kSignBit64 = uint64_t{1} << 63;
3243 Float64 dd = Float64::FromBits(dm.get_bits() & ~kSignBit64);
3244 dd = canonicalizeNaN(dd);
3245 set_d_register_from_double(vd, dd);
3247 Float32 sm = get_float_from_s_register(
m);
3248 constexpr uint32_t kSignBit32 = uint32_t{1} << 31;
3249 Float32 sd = Float32::FromBits(sm.get_bits() & ~kSignBit32);
3250 sd = canonicalizeNaN(sd);
3251 set_s_register_from_float(d, sd);
3253 }
else if ((
instr->Opc2Value() == 0x1) && (
instr->Opc3Value() == 0x1)) {
3255 if (
instr->SzValue() == 0x1) {
3256 Float64 dm = get_double_from_d_register(vm);
3257 constexpr uint64_t kSignBit64 = uint64_t{1} << 63;
3258 Float64 dd = Float64::FromBits(dm.get_bits() ^ kSignBit64);
3259 dd = canonicalizeNaN(dd);
3260 set_d_register_from_double(vd, dd);
3262 Float32 sm = get_float_from_s_register(
m);
3263 constexpr uint32_t kSignBit32 = uint32_t{1} << 31;
3264 Float32 sd = Float32::FromBits(sm.get_bits() ^ kSignBit32);
3265 sd = canonicalizeNaN(sd);
3266 set_s_register_from_float(d, sd);
3268 }
else if ((
instr->Opc2Value() == 0x7) && (
instr->Opc3Value() == 0x3)) {
3269 DecodeVCVTBetweenDoubleAndSingle(
instr);
3270 }
else if ((
instr->Opc2Value() == 0x8) && (
instr->Opc3Value() & 0x1)) {
3271 DecodeVCVTBetweenFloatingPointAndInteger(
instr);
3272 }
else if ((
instr->Opc2Value() == 0xA) && (
instr->Opc3Value() == 0x3) &&
3273 (
instr->Bit(8) == 1)) {
3275 int fraction_bits = 32 - ((
instr->Bits(3, 0) << 1) |
instr->Bit(5));
3276 int fixed_value = get_sinteger_from_s_register(vd * 2);
3277 double divide = 1 << fraction_bits;
3278 set_d_register_from_double(vd, fixed_value / divide);
3279 }
else if (((
instr->Opc2Value() >> 1) == 0x6) &&
3280 (
instr->Opc3Value() & 0x1)) {
3281 DecodeVCVTBetweenFloatingPointAndInteger(
instr);
3282 }
else if (((
instr->Opc2Value() == 0x4) || (
instr->Opc2Value() == 0x5)) &&
3283 (
instr->Opc3Value() & 0x1)) {
3285 }
else if (((
instr->Opc2Value() == 0x1)) && (
instr->Opc3Value() == 0x3)) {
3287 if (
instr->SzValue() == 0x1) {
3288 double dm_value = get_double_from_d_register(vm).get_scalar();
3289 double dd_value = std::sqrt(dm_value);
3290 dd_value = canonicalizeNaN(dd_value);
3291 set_d_register_from_double(vd, dd_value);
3293 float sm_value = get_float_from_s_register(
m).get_scalar();
3294 float sd_value = std::sqrt(sm_value);
3295 sd_value = canonicalizeNaN(sd_value);
3296 set_s_register_from_float(d, sd_value);
3298 }
else if (
instr->Opc3Value() == 0x0) {
3300 if (
instr->SzValue() == 0x1) {
3301 set_d_register_from_double(vd,
instr->DoubleImmedVmov());
3304 float value =
instr->DoubleImmedVmov().get_scalar();
3305 set_s_register_from_float(d, value);
3307 }
else if (((
instr->Opc2Value() == 0x6)) && (
instr->Opc3Value() == 0x3)) {
3309 if (
instr->SzValue() == 0x1) {
3310 double dm_value = get_double_from_d_register(vm).get_scalar();
3311 double dd_value = trunc(dm_value);
3312 dd_value = canonicalizeNaN(dd_value);
3313 set_d_register_from_double(vd, dd_value);
3315 float sm_value = get_float_from_s_register(
m).get_scalar();
3316 float sd_value = truncf(sm_value);
3317 sd_value = canonicalizeNaN(sd_value);
3318 set_s_register_from_float(d, sd_value);
3323 }
else if (
instr->Opc1Value() == 0x3) {
3324 if (
instr->Opc3Value() & 0x1) {
3326 if (
instr->SzValue() == 0x1) {
3327 double dn_value = get_double_from_d_register(vn).get_scalar();
3328 double dm_value = get_double_from_d_register(vm).get_scalar();
3329 double dd_value = dn_value - dm_value;
3330 dd_value = canonicalizeNaN(dd_value);
3331 set_d_register_from_double(vd, dd_value);
3333 float sn_value = get_float_from_s_register(n).get_scalar();
3334 float sm_value = get_float_from_s_register(
m).get_scalar();
3335 float sd_value = sn_value - sm_value;
3336 sd_value = canonicalizeNaN(sd_value);
3337 set_s_register_from_float(d, sd_value);
3341 if (
instr->SzValue() == 0x1) {
3342 double dn_value = get_double_from_d_register(vn).get_scalar();
3343 double dm_value = get_double_from_d_register(vm).get_scalar();
3344 double dd_value = dn_value + dm_value;
3345 dd_value = canonicalizeNaN(dd_value);
3346 set_d_register_from_double(vd, dd_value);
3348 float sn_value = get_float_from_s_register(n).get_scalar();
3349 float sm_value = get_float_from_s_register(
m).get_scalar();
3350 float sd_value = sn_value + sm_value;
3351 sd_value = canonicalizeNaN(sd_value);
3352 set_s_register_from_float(d, sd_value);
3355 }
else if ((
instr->Opc1Value() == 0x2) && !(
instr->Opc3Value() & 0x1)) {
3357 if (
instr->SzValue() == 0x1) {
3358 double dn_value = get_double_from_d_register(vn).get_scalar();
3359 double dm_value = get_double_from_d_register(vm).get_scalar();
3360 double dd_value = dn_value * dm_value;
3361 dd_value = canonicalizeNaN(dd_value);
3362 set_d_register_from_double(vd, dd_value);
3364 float sn_value = get_float_from_s_register(n).get_scalar();
3365 float sm_value = get_float_from_s_register(
m).get_scalar();
3366 float sd_value = sn_value * sm_value;
3367 sd_value = canonicalizeNaN(sd_value);
3368 set_s_register_from_float(d, sd_value);
3370 }
else if ((
instr->Opc1Value() == 0x0)) {
3372 const bool is_vmls = (
instr->Opc3Value() & 0x1);
3373 if (
instr->SzValue() == 0x1) {
3374 const double dd_val = get_double_from_d_register(vd).get_scalar();
3375 const double dn_val = get_double_from_d_register(vn).get_scalar();
3376 const double dm_val = get_double_from_d_register(vm).get_scalar();
3380 const double res = dn_val * dm_val;
3381 set_d_register_from_double(vd, res);
3383 set_d_register_from_double(vd, canonicalizeNaN(dd_val - res));
3385 set_d_register_from_double(vd, canonicalizeNaN(dd_val + res));
3388 const float sd_val = get_float_from_s_register(d).get_scalar();
3389 const float sn_val = get_float_from_s_register(n).get_scalar();
3390 const float sm_val = get_float_from_s_register(
m).get_scalar();
3394 const float res = sn_val * sm_val;
3395 set_s_register_from_float(d, res);
3397 set_s_register_from_float(d, canonicalizeNaN(sd_val - res));
3399 set_s_register_from_float(d, canonicalizeNaN(sd_val + res));
3402 }
else if ((
instr->Opc1Value() == 0x4) && !(
instr->Opc3Value() & 0x1)) {
3404 if (
instr->SzValue() == 0x1) {
3405 double dn_value = get_double_from_d_register(vn).get_scalar();
3406 double dm_value = get_double_from_d_register(vm).get_scalar();
3407 double dd_value = base::Divide(dn_value, dm_value);
3408 div_zero_vfp_flag_ = (dm_value == 0);
3409 dd_value = canonicalizeNaN(dd_value);
3410 set_d_register_from_double(vd, dd_value);
3412 float sn_value = get_float_from_s_register(n).get_scalar();
3413 float sm_value = get_float_from_s_register(
m).get_scalar();
3414 float sd_value = base::Divide(sn_value, sm_value);
3415 div_zero_vfp_flag_ = (sm_value == 0);
3416 sd_value = canonicalizeNaN(sd_value);
3417 set_s_register_from_float(d, sd_value);
3423 if ((
instr->VCValue() == 0x0) && (
instr->VAValue() == 0x0)) {
3424 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
instr);
3425 }
else if ((
instr->VLValue() == 0x0) && (
instr->VCValue() == 0x1)) {
3426 if (
instr->Bit(23) == 0) {
3428 int vd =
instr->VFPNRegValue(kDoublePrecision);
3429 int rt =
instr->RtValue();
3430 int opc1_opc2 = (
instr->Bits(22, 21) << 2) |
instr->Bits(6, 5);
3431 if ((opc1_opc2 & 0xB) == 0) {
3434 get_d_register(vd, data);
3435 data[
instr->Bit(21)] = get_register(rt);
3436 set_d_register(vd, data);
3439 get_d_register(vd, &data);
3440 uint64_t rt_value = get_register(rt);
3441 if ((opc1_opc2 & 0x8) != 0) {
3443 int i = opc1_opc2 & 0x7;
3445 const uint64_t
mask = 0xFF;
3446 data &= ~(
mask << shift);
3447 data |= (rt_value &
mask) << shift;
3448 set_d_register(vd, &data);
3449 }
else if ((opc1_opc2 & 0x1) != 0) {
3451 int i = (opc1_opc2 >> 1) & 0x3;
3453 const uint64_t
mask = 0xFFFF;
3454 data &= ~(
mask << shift);
3455 data |= (rt_value &
mask) << shift;
3456 set_d_register(vd, &data);
3464 if (
instr->Bit(5) != 0)
3466 else if (
instr->Bit(22) != 0)
3468 int vd =
instr->VFPNRegValue(kSimd128Precision);
3469 int rt =
instr->RtValue();
3470 uint32_t rt_value = get_register(rt);
3475 uint8_t* dst =
reinterpret_cast<uint8_t*
>(q_data);
3476 for (
int i = 0;
i < 16;
i++) {
3483 rt_value &= 0xFFFFu;
3484 uint32_t rt_rt = (rt_value << 16) | (rt_value & 0xFFFFu);
3485 for (
int i = 0;
i < 4;
i++) {
3491 for (
int i = 0;
i < 4;
i++) {
3492 q_data[
i] = rt_value;
3499 set_neon_register(vd, q_data);
3501 }
else if ((
instr->VLValue() == 0x1) && (
instr->VCValue() == 0x1)) {
3503 int vn =
instr->VFPNRegValue(kDoublePrecision);
3504 int rt =
instr->RtValue();
3505 int opc1_opc2 = (
instr->Bits(22, 21) << 2) |
instr->Bits(6, 5);
3507 get_d_register(vn, &data);
3508 if ((opc1_opc2 & 0xB) == 0) {
3512 memcpy(int_data, &data,
sizeof(int_data));
3513 set_register(rt, int_data[
instr->Bit(21)]);
3516 get_d_register(vn, &data);
3517 bool u =
instr->Bit(23) != 0;
3518 if ((opc1_opc2 & 0x8) != 0) {
3520 int i = opc1_opc2 & 0x7;
3522 uint32_t scalar = (data >> shift) & 0xFFu;
3523 if (!u && (scalar & 0x80) != 0) scalar |= 0xFFFFFF00;
3524 set_register(rt, scalar);
3525 }
else if ((opc1_opc2 & 0x1) != 0) {
3527 int i = (opc1_opc2 >> 1) & 0x3;
3529 uint32_t scalar = (data >> shift) & 0xFFFFu;
3530 if (!u && (scalar & 0x8000) != 0) scalar |= 0xFFFF0000;
3531 set_register(rt, scalar);
3536 }
else if ((
instr->VLValue() == 0x1) && (
instr->VCValue() == 0x0) &&
3537 (
instr->VAValue() == 0x7) && (
instr->Bits(19, 16) == 0x1)) {
3539 uint32_t rt =
instr->RtValue();
3541 Copy_FPSCR_to_APSR();
3544 uint32_t fpscr = (n_flag_FPSCR_ << 31) | (z_flag_FPSCR_ << 30) |
3545 (c_flag_FPSCR_ << 29) | (v_flag_FPSCR_ << 28) |
3546 (FPSCR_default_NaN_mode_ << 25) |
3547 (inexact_vfp_flag_ << 4) | (underflow_vfp_flag_ << 3) |
3548 (overflow_vfp_flag_ << 2) | (div_zero_vfp_flag_ << 1) |
3549 (inv_op_vfp_flag_ << 0) | (FPSCR_rounding_mode_);
3550 set_register(rt, fpscr);
3552 }
else if ((
instr->VLValue() == 0x0) && (
instr->VCValue() == 0x0) &&
3553 (
instr->VAValue() == 0x7) && (
instr->Bits(19, 16) == 0x1)) {
3555 uint32_t rt =
instr->RtValue();
3559 uint32_t rt_value = get_register(rt);
3560 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3561 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3562 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3563 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3564 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3565 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3566 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3567 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3568 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3569 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3570 FPSCR_rounding_mode_ =
3579void Simulator::DecodeTypeCP15(Instruction*
instr) {
3583 if (
instr->Bit(4) == 1) {
3585 int crn =
instr->Bits(19, 16);
3586 int crm =
instr->Bits(3, 0);
3587 int opc1 =
instr->Bits(23, 21);
3588 int opc2 =
instr->Bits(7, 5);
3589 if ((opc1 == 0) && (crn == 7)) {
3592 if (((crm == 10) && (opc2 == 5)) ||
3593 ((crm == 10) && (opc2 == 4)) ||
3594 ((crm == 5) && (opc2 == 4))) {
3605void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3606 Instruction*
instr) {
3608 (
instr->VAValue() == 0x0));
3610 int t =
instr->RtValue();
3611 int n =
instr->VFPNRegValue(kSinglePrecision);
3612 bool to_arm_register = (
instr->VLValue() == 0x1);
3614 if (to_arm_register) {
3615 int32_t int_value = get_sinteger_from_s_register(n);
3616 set_register(t, int_value);
3618 int32_t rs_val = get_register(t);
3619 set_s_register_from_sinteger(n, rs_val);
3623void Simulator::DecodeVCMP(Instruction*
instr) {
3626 (
instr->Opc3Value() & 0x1));
3630 if (
instr->SzValue() == 0x1) {
3636 if (
instr->Opc2Value() == 0x4) {
3641 double dd_value = get_double_from_d_register(d).get_scalar();
3642 double dm_value = 0.0;
3643 if (
instr->Opc2Value() == 0x4) {
3644 dm_value = get_double_from_d_register(
m).get_scalar();
3648 if (
instr->Bit(7) == 1) {
3649 if (std::isnan(dd_value)) {
3650 inv_op_vfp_flag_ =
true;
3654 Compute_FPSCR_Flags(dd_value, dm_value);
3656 float sd_value = get_float_from_s_register(d).get_scalar();
3657 float sm_value = 0.0;
3658 if (
instr->Opc2Value() == 0x4) {
3659 sm_value = get_float_from_s_register(
m).get_scalar();
3663 if (
instr->Bit(7) == 1) {
3664 if (std::isnan(sd_value)) {
3665 inv_op_vfp_flag_ =
true;
3669 Compute_FPSCR_Flags(sd_value, sm_value);
3673void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction*
instr) {
3679 if (
instr->SzValue() == 1) {
3684 int dst =
instr->VFPDRegValue(dst_precision);
3685 int src =
instr->VFPMRegValue(src_precision);
3687 if (dst_precision == kSinglePrecision) {
3688 double val = get_double_from_d_register(src).get_scalar();
3689 set_s_register_from_float(dst,
static_cast<float>(val));
3691 float val = get_float_from_s_register(src).get_scalar();
3692 set_d_register_from_double(dst,
static_cast<double>(val));
3696bool get_inv_op_vfp_flag(VFPRoundingMode mode,
double val,
bool unsigned_) {
3697 DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
3698 double max_uint =
static_cast<double>(0xFFFFFFFFu);
3699 double max_int =
static_cast<double>(
kMaxInt);
3700 double min_int =
static_cast<double>(
kMinInt);
3711 return unsigned_ ? (val >= (max_uint + 0.5)) || (val < -0.5)
3712 : (val >= (max_int + 0.5)) || (val < (min_int - 0.5));
3715 return unsigned_ ? (val >= (max_uint + 1.0)) || (val < 0)
3716 : (val >= (max_int + 1.0)) || (val < min_int);
3719 return unsigned_ ? (val >= (max_uint + 1.0)) || (val <= -1)
3720 : (val >= (max_int + 1.0)) || (val <= (min_int - 1.0));
3728int VFPConversionSaturate(
double val,
bool unsigned_res) {
3733 return (val < 0) ? 0 : 0xFFFFFFFFu;
3740int32_t Simulator::ConvertDoubleToInt(
double val,
bool unsigned_integer,
3741 VFPRoundingMode mode) {
3743 if (unsigned_integer) {
3747 using limits = std::numeric_limits<uint32_t>;
3748 if (val > limits::max()) {
3750 }
else if (!(val >= 0)) {
3753 result =
static_cast<uint32_t
>(val);
3759 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3761 double abs_diff = unsigned_integer
3762 ? std::fabs(val -
static_cast<uint32_t
>(
result))
3765 inexact_vfp_flag_ = (abs_diff != 0);
3767 if (inv_op_vfp_flag_) {
3768 result = VFPConversionSaturate(val, unsigned_integer);
3772 int val_sign = (val > 0) ? 1 : -1;
3773 if (abs_diff > 0.5) {
3775 }
else if (abs_diff == 0.5) {
3799void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction*
instr) {
3801 (
instr->Bits(27, 23) == 0x1D));
3803 (((
instr->Opc2Value() >> 1) == 0x6) && (
instr->Opc3Value() & 0x1)));
3806 bool to_integer = (
instr->Bit(18) == 1);
3819 int dst =
instr->VFPDRegValue(kSinglePrecision);
3820 int src =
instr->VFPMRegValue(src_precision);
3825 DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
3827 bool unsigned_integer = (
instr->Bit(16) == 0);
3830 double val = double_precision ? get_double_from_d_register(src).get_scalar()
3831 : get_float_from_s_register(src).get_scalar();
3833 int32_t temp = ConvertDoubleToInt(val, unsigned_integer, mode);
3836 set_s_register_from_sinteger(dst, temp);
3839 bool unsigned_integer = (
instr->Bit(7) == 0);
3841 int dst =
instr->VFPDRegValue(src_precision);
3842 int src =
instr->VFPMRegValue(kSinglePrecision);
3844 int val = get_sinteger_from_s_register(src);
3846 if (src_precision == kDoublePrecision) {
3847 if (unsigned_integer) {
3848 set_d_register_from_double(
3849 dst,
static_cast<double>(
static_cast<uint32_t
>(val)));
3851 set_d_register_from_double(dst,
static_cast<double>(val));
3854 if (unsigned_integer) {
3855 set_s_register_from_float(
3856 dst,
static_cast<float>(
static_cast<uint32_t
>(val)));
3858 set_s_register_from_float(dst,
static_cast<float>(val));
3870void Simulator::DecodeType6CoprocessorIns(Instruction*
instr) {
3873 if (
instr->CoprocessorValue() == 0xA) {
3874 switch (
instr->OpcodeValue()) {
3879 int rn =
instr->RnValue();
3880 int vd =
instr->VFPDRegValue(kSinglePrecision);
3882 if (!
instr->HasU()) {
3890 if (
instr->HasL()) {
3892 set_s_register_from_sinteger(vd, ReadW(address));
3895 WriteW(address, get_sinteger_from_s_register(vd));
3911 }
else if (
instr->CoprocessorValue() == 0xB) {
3912 switch (
instr->OpcodeValue()) {
3915 if (
instr->Bits(7, 6) != 0 ||
instr->Bit(4) != 1) {
3918 int rt =
instr->RtValue();
3919 int rn =
instr->RnValue();
3920 int vm =
instr->VFPMRegValue(kDoublePrecision);
3921 if (
instr->HasL()) {
3923 get_d_register(vm, data);
3924 set_register(rt, data[0]);
3925 set_register(rn, data[1]);
3927 int32_t data[] = {get_register(rt), get_register(rn)};
3928 set_d_register(vm,
reinterpret_cast<uint32_t*
>(data));
3936 int rn =
instr->RnValue();
3937 int vd =
instr->VFPDRegValue(kDoublePrecision);
3939 if (!
instr->HasU()) {
3946 if (
instr->HasL()) {
3948 int32_t data[] = {ReadW(address), ReadW(address + 4)};
3949 set_d_register(vd,
reinterpret_cast<uint32_t*
>(data));
3953 get_d_register(vd, data);
3954 WriteW(address, data[0]);
3955 WriteW(address + 4, data[1]);
3978template <
typename T,
int SIZE = kSimd128Size>
3979void Unop(Simulator* simulator,
int Vd,
int Vm, std::function<
T(T)> unop) {
3980 static const int kLanes =
SIZE /
sizeof(
T);
3982 simulator->get_neon_register<
T,
SIZE>(Vm, src);
3983 for (
int i = 0;
i < kLanes;
i++) {
3984 src[
i] = unop(src[
i]);
3986 simulator->set_neon_register<
T,
SIZE>(Vd, src);
3989template <
typename T,
int SIZE = kSimd128Size>
3990void Binop(Simulator* simulator,
int Vd,
int Vm,
int Vn,
3991 std::function<
T(T, T)> binop) {
3992 static const int kLanes =
SIZE /
sizeof(
T);
3993 T src1[kLanes], src2[kLanes];
3994 simulator->get_neon_register<
T,
SIZE>(Vn, src1);
3995 simulator->get_neon_register<
T,
SIZE>(Vm, src2);
3996 for (
int i = 0;
i < kLanes;
i++) {
3997 src1[
i] = binop(src1[
i], src2[
i]);
3999 simulator->set_neon_register<
T,
SIZE>(Vd, src1);
4003template <
typename T,
typename U>
4005 static_assert(
sizeof(int64_t) >
sizeof(
T),
"T must be int32_t or smaller");
4006 static_assert(
sizeof(
U) >
sizeof(
T),
"T must smaller than U");
4007 return static_cast<U>(
value);
4010template <
typename T,
typename U>
4011void Widen(Simulator* simulator,
int Vd,
int Vm) {
4012 static const int kLanes = 8 /
sizeof(
T);
4016 for (
int i = 0;
i < kLanes;
i++) {
4017 dst[
i] = Widen<T, U>(src[
i]);
4019 simulator->set_neon_register(Vd, dst);
4022template <
typename T,
int SIZE>
4023void Abs(Simulator* simulator,
int Vd,
int Vm) {
4024 Unop<T>(simulator, Vd, Vm, [](T
x) {
return std::abs(
x); });
4027template <
typename T,
int SIZE>
4028void Neg(Simulator* simulator,
int Vd,
int Vm) {
4029 Unop<T>(simulator, Vd, Vm, [](T
x) {
4031 return x == std::numeric_limits<T>::min() ?
x : -
x;
4035template <
typename T,
typename U>
4036void SaturatingNarrow(Simulator* simulator,
int Vd,
int Vm) {
4037 static const int kLanes = 16 /
sizeof(
T);
4040 simulator->get_neon_register(Vm, src);
4041 for (
int i = 0;
i < kLanes;
i++) {
4042 dst[
i] = base::saturated_cast<U>(src[
i]);
4047template <
typename T>
4048void AddSat(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4049 Binop<T>(simulator, Vd, Vm, Vn, SaturateAdd<T>);
4052template <
typename T>
4053void SubSat(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4054 Binop<T>(simulator, Vd, Vm, Vn, SaturateSub<T>);
4057template <
typename T,
int SIZE>
4058void Zip(Simulator* simulator,
int Vd,
int Vm) {
4059 static const int kElems =
SIZE /
sizeof(
T);
4060 static const int kPairs = kElems / 2;
4061 T src1[kElems], src2[kElems], dst1[kElems], dst2[kElems];
4062 simulator->get_neon_register<
T,
SIZE>(Vd, src1);
4063 simulator->get_neon_register<
T,
SIZE>(Vm, src2);
4064 for (
int i = 0;
i < kPairs;
i++) {
4065 dst1[
i * 2] = src1[
i];
4066 dst1[
i * 2 + 1] = src2[
i];
4067 dst2[
i * 2] = src1[
i + kPairs];
4068 dst2[
i * 2 + 1] = src2[
i + kPairs];
4070 simulator->set_neon_register<
T,
SIZE>(Vd, dst1);
4071 simulator->set_neon_register<
T,
SIZE>(Vm, dst2);
4074template <
typename T,
int SIZE>
4075void Unzip(Simulator* simulator,
int Vd,
int Vm) {
4076 static const int kElems =
SIZE /
sizeof(
T);
4077 static const int kPairs = kElems / 2;
4078 T src1[kElems], src2[kElems], dst1[kElems], dst2[kElems];
4079 simulator->get_neon_register<
T,
SIZE>(Vd, src1);
4080 simulator->get_neon_register<
T,
SIZE>(Vm, src2);
4081 for (
int i = 0;
i < kPairs;
i++) {
4082 dst1[
i] = src1[
i * 2];
4083 dst1[
i + kPairs] = src2[
i * 2];
4084 dst2[
i] = src1[
i * 2 + 1];
4085 dst2[
i + kPairs] = src2[
i * 2 + 1];
4087 simulator->set_neon_register<
T,
SIZE>(Vd, dst1);
4088 simulator->set_neon_register<
T,
SIZE>(Vm, dst2);
4091template <
typename T,
int SIZE>
4092void Transpose(Simulator* simulator,
int Vd,
int Vm) {
4093 static const int kElems =
SIZE /
sizeof(
T);
4094 static const int kPairs = kElems / 2;
4095 T src1[kElems], src2[kElems];
4096 simulator->get_neon_register<
T,
SIZE>(Vd, src1);
4097 simulator->get_neon_register<
T,
SIZE>(Vm, src2);
4098 for (
int i = 0;
i < kPairs;
i++) {
4099 std::swap(src1[2 *
i + 1], src2[2 *
i]);
4101 simulator->set_neon_register<
T,
SIZE>(Vd, src1);
4102 simulator->set_neon_register<
T,
SIZE>(Vm, src2);
4105template <
typename T,
int SIZE>
4106void Test(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4107 auto test = [](T
x, T
y) {
return (
x &
y) ? -1 : 0; };
4108 Binop<T>(simulator, Vd, Vm, Vn, test);
4111template <
typename T,
int SIZE>
4112void Add(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4113 Binop<T>(simulator, Vd, Vm, Vn, std::plus<T>());
4116template <
typename T,
int SIZE>
4117void Sub(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4118 Binop<T>(simulator, Vd, Vm, Vn, std::minus<T>());
4122uint32_t Multiply(uint32_t a, uint32_t b) {
return a * b; }
4123uint8_t Multiply(uint8_t a, uint8_t b) {
return a * b; }
4126uint16_t Multiply(uint16_t a, uint16_t b) {
4127 uint32_t
result =
static_cast<uint32_t
>(
a) *
static_cast<uint32_t
>(b);
4131void VmovImmediate(Simulator* simulator, Instruction*
instr) {
4132 uint8_t cmode =
instr->Bits(11, 8);
4133 int vd =
instr->VFPDRegValue(kDoublePrecision);
4134 int q =
instr->Bit(6);
4135 int regs = q ? 2 : 1;
4136 uint8_t imm =
instr->Bit(24) << 7;
4137 imm |=
instr->Bits(18, 16) << 4;
4138 imm |=
instr->Bits(3, 0);
4142 uint64_t imm64 = imm;
4143 for (
int r = 0;
r < regs;
r++) {
4144 simulator->set_d_register(vd +
r, &imm64);
4151 std::fill_n(imms, kSimd128Size, imm);
4153 memcpy(&imm64, imms, 8);
4154 for (
int r = 0;
r < regs;
r++) {
4155 simulator->set_d_register(vd +
r, &imm64);
4166template <
typename T,
int SIZE>
4167void Mul(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4168 static const int kElems =
SIZE /
sizeof(
T);
4169 T src1[kElems], src2[kElems];
4170 simulator->get_neon_register<
T,
SIZE>(Vn, src1);
4171 simulator->get_neon_register<
T,
SIZE>(Vm, src2);
4172 for (
int i = 0;
i < kElems;
i++) {
4173 src1[
i] = Multiply(src1[
i], src2[
i]);
4175 simulator->set_neon_register<
T,
SIZE>(Vd, src1);
4178template <
typename T,
int SIZE>
4179void ShiftLeft(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4180 Unop<T>(simulator, Vd, Vm, [shift](T
x) {
return x << shift; });
4183template <
typename T,
int SIZE>
4184void LogicalShiftRight(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4185 Unop<T, SIZE>(simulator, Vd, Vm, [shift](T
x) {
return x >> shift; });
4188template <
typename T,
int SIZE>
4189void ArithmeticShiftRight(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4191 std::bind(ArithmeticShiftRight<T>, std::placeholders::_1, shift);
4192 Unop<T, SIZE>(simulator, Vd, Vm, shift_fn);
4195template <
typename T,
int SIZE>
4196void ShiftRight(Simulator* simulator,
int Vd,
int Vm,
int shift,
4199 using unsigned_T = std::make_unsigned_t<T>;
4200 LogicalShiftRight<unsigned_T, SIZE>(simulator, Vd, Vm, shift);
4202 ArithmeticShiftRight<T, SIZE>(simulator, Vd, Vm, shift);
4206template <
typename T,
int SIZE>
4207void ShiftRightAccumulate(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4208 Binop<T, SIZE>(simulator, Vd, Vm, Vd,
4209 [shift](T a, T
x) {
return a + (
x >> shift); });
4212template <
typename T,
int SIZE>
4213void ArithmeticShiftRightAccumulate(Simulator* simulator,
int Vd,
int Vm,
4215 Binop<T, SIZE>(simulator, Vd, Vm, Vd, [shift](T a, T
x) {
4216 T
result = ArithmeticShiftRight<T>(
x, shift);
4221template <
typename T,
int SIZE>
4222void ShiftLeftAndInsert(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4223 static const int kElems =
SIZE /
sizeof(
T);
4226 simulator->get_neon_register<
T,
SIZE>(Vm, src);
4227 simulator->get_neon_register<
T,
SIZE>(Vd, dst);
4228 uint64_t
mask = (1llu << shift) - 1llu;
4229 for (
int i = 0;
i < kElems;
i++) {
4230 dst[
i] = (src[
i] << shift) | (dst[
i] &
mask);
4232 simulator->set_neon_register<
T,
SIZE>(Vd, dst);
4235template <
typename T,
int SIZE>
4236void ShiftRightAndInsert(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4237 static const int kElems =
SIZE /
sizeof(
T);
4240 simulator->get_neon_register<
T,
SIZE>(Vm, src);
4241 simulator->get_neon_register<
T,
SIZE>(Vd, dst);
4243 for (
int i = 0;
i < kElems;
i++) {
4244 dst[
i] = (src[
i] >> shift) | (dst[
i] &
mask);
4246 simulator->set_neon_register<
T,
SIZE>(Vd, dst);
4249template <
typename T,
typename S_T,
int SIZE>
4250void ShiftByRegister(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4251 static const int kElems =
SIZE /
sizeof(
T);
4254 simulator->get_neon_register<
T,
SIZE>(Vm, src);
4255 simulator->get_neon_register<S_T,
SIZE>(Vn, shift);
4256 for (
int i = 0;
i < kElems;
i++) {
4259 int8_t shift_value =
static_cast<int8_t
>(shift[
i]);
4260 int size =
static_cast<int>(
sizeof(
T) * 8);
4263 if ((shift_value) >= 0) {
4265 if (shift_value >= size) {
4268 using unsignedT = std::make_unsigned_t<T>;
4269 src[
i] =
static_cast<unsignedT
>(src[
i]) << shift_value;
4273 if (-shift_value >= size) {
4276 src[
i] = ArithmeticShiftRight(src[
i], -shift_value);
4280 simulator->set_neon_register<
T,
SIZE>(Vd, src);
4283template <
typename T,
int SIZE>
4284void CompareEqual(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4285 Binop<T>(simulator, Vd, Vm, Vn, [](T
x, T
y) {
return x ==
y ? -1 : 0; });
4288template <
typename T,
int SIZE>
4289void CompareGreater(Simulator* simulator,
int Vd,
int Vm,
int Vn,
bool ge) {
4291 Binop<T>(simulator, Vd, Vm, Vn, [](T
x, T
y) {
return x >=
y ? -1 : 0; });
4293 Binop<T>(simulator, Vd, Vm, Vn, [](T
x, T
y) {
return x >
y ? -1 : 0; });
4297float MinMax(
float a,
float b,
bool is_min) {
4300template <
typename T>
4301T MinMax(T a, T b,
bool is_min) {
4302 return is_min ? std::min(a, b) :
std::max(a, b);
4305template <
typename T,
int SIZE>
4306void MinMax(Simulator* simulator,
int Vd,
int Vm,
int Vn,
bool min) {
4308 Binop<T>(simulator, Vd, Vm, Vn,
4309 [](
auto x,
auto y) {
return std::min<T>(
x,
y); });
4311 Binop<T>(simulator, Vd, Vm, Vn,
4312 [](
auto x,
auto y) {
return std::max<T>(
x,
y); });
4316template <
typename T>
4317void PairwiseMinMax(Simulator* simulator,
int Vd,
int Vm,
int Vn,
bool min) {
4319 static const int kPairs = kElems / 2;
4320 T dst[kElems], src1[kElems], src2[kElems];
4321 simulator->get_neon_register<
T,
kDoubleSize>(Vn, src1);
4322 simulator->get_neon_register<
T,
kDoubleSize>(Vm, src2);
4323 for (
int i = 0;
i < kPairs;
i++) {
4324 dst[
i] = MinMax(src1[
i * 2], src1[
i * 2 + 1], min);
4325 dst[
i + kPairs] = MinMax(src2[
i * 2], src2[
i * 2 + 1], min);
4330template <
typename T>
4331void PairwiseAdd(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4333 static const int kPairs = kElems / 2;
4334 T dst[kElems], src1[kElems], src2[kElems];
4335 simulator->get_neon_register<
T,
kDoubleSize>(Vn, src1);
4336 simulator->get_neon_register<
T,
kDoubleSize>(Vm, src2);
4337 for (
int i = 0;
i < kPairs;
i++) {
4338 dst[
i] = src1[
i * 2] + src1[
i * 2 + 1];
4339 dst[
i + kPairs] = src2[
i * 2] + src2[
i * 2 + 1];
4344template <
typename NarrowType,
typename W
ideType,
int SIZE = kSimd128Size>
4345void PairwiseAddLong(Simulator* simulator,
int Vd,
int Vm) {
4346 DCHECK_EQ(
sizeof(WideType), 2 *
sizeof(NarrowType));
4347 static constexpr int kSElems =
SIZE /
sizeof(NarrowType);
4348 static constexpr int kTElems =
SIZE /
sizeof(WideType);
4349 NarrowType src[kSElems];
4350 WideType dst[kTElems];
4351 simulator->get_neon_register<NarrowType,
SIZE>(Vm, src);
4352 for (
int i = 0;
i < kTElems;
i++) {
4353 dst[
i] = WideType{src[
i * 2]} + WideType{src[
i * 2 + 1]};
4355 simulator->set_neon_register<WideType,
SIZE>(Vd, dst);
4358template <
typename NarrowType,
typename W
ideType,
int SIZE = kSimd128Size>
4359void PairwiseAddAccumulateLong(Simulator* simulator,
int Vd,
int Vm) {
4360 DCHECK_EQ(
sizeof(WideType), 2 *
sizeof(NarrowType));
4361 static constexpr int kSElems =
SIZE /
sizeof(NarrowType);
4362 static constexpr int kTElems =
SIZE /
sizeof(WideType);
4363 NarrowType src[kSElems];
4364 WideType dst[kTElems];
4365 simulator->get_neon_register<NarrowType,
SIZE>(Vm, src);
4366 simulator->get_neon_register<WideType,
SIZE>(Vd, dst);
4367 for (
int i = 0;
i < kTElems;
i++) {
4368 dst[
i] += WideType{src[
i * 2]} + WideType{src[
i * 2 + 1]};
4370 simulator->set_neon_register<WideType,
SIZE>(Vd, dst);
4373template <
typename NarrowType,
typename W
ideType>
4374void MultiplyLong(Simulator* simulator,
int Vd,
int Vn,
int Vm) {
4375 DCHECK_EQ(
sizeof(WideType), 2 *
sizeof(NarrowType));
4376 static const int kElems =
kSimd128Size /
sizeof(WideType);
4377 NarrowType src1[kElems], src2[kElems];
4378 WideType dst[kElems];
4383 simulator->get_d_register(Vn, &tmp);
4384 memcpy(src1, &tmp,
sizeof(tmp));
4385 simulator->get_d_register(Vm, &tmp);
4386 memcpy(src2, &tmp,
sizeof(tmp));
4388 for (
int i = 0;
i < kElems;
i++) {
4389 dst[
i] = WideType{src1[
i]} * WideType{src2[
i]};
4392 simulator->set_neon_register<WideType>(Vd, dst);
4395void Simulator::DecodeUnconditional(Instruction*
instr) {
4397 int op0 =
instr->Bits(26, 25);
4398 int op1 =
instr->Bit(20);
4406 DecodeAdvancedSIMDDataProcessing(
instr);
4407 }
else if ((op0 & 0b10) == 0b10 && op1) {
4408 DecodeMemoryHintsAndBarriers(
instr);
4409 }
else if (op0 == 0b10 && !op1) {
4410 DecodeAdvancedSIMDElementOrStructureLoadStore(
instr);
4416void Simulator::DecodeAdvancedSIMDTwoOrThreeRegisters(Instruction*
instr) {
4418 int op0 =
instr->Bit(24);
4419 int op1 =
instr->Bits(21, 20);
4420 int op2 =
instr->Bits(11, 10);
4421 int op3 =
instr->Bit(6);
4422 if (!op0 && op1 == 0b11) {
4424 int imm4 =
instr->Bits(11, 8);
4425 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4426 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4427 int Vn =
instr->VFPNRegValue(kSimd128Precision);
4428 uint8_t src1[16], src2[16], dst[16];
4429 get_neon_register(Vn, src1);
4430 get_neon_register(Vm, src2);
4433 for (;
i < boundary;
i++) {
4434 dst[
i] = src1[
i + imm4];
4436 for (;
i < 16;
i++) {
4437 dst[
i] = src2[
i - boundary];
4439 set_neon_register(Vd, dst);
4440 }
else if (op0 && op1 == 0b11 && ((op2 >> 1) == 0)) {
4442 int size =
instr->Bits(19, 18);
4443 int opc1 =
instr->Bits(17, 16);
4444 int opc2 =
instr->Bits(10, 7);
4445 int q =
instr->Bit(6);
4447 if (opc1 == 0 && (opc2 >> 2) == 0) {
4449 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4450 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4458 get_neon_register(Vm, src);
4459 for (
int i = 0;
i < 16;
i += 2) {
4460 std::swap(src[
i], src[
i + 1]);
4462 set_neon_register(Vd, src);
4469 get_neon_register(Vm, src);
4470 for (
int i = 0;
i < 8;
i += 2) {
4471 std::swap(src[
i], src[
i + 1]);
4473 set_neon_register(Vd, src);
4478 get_neon_register(Vm, src);
4479 for (
int i = 0;
i < 4;
i++) {
4480 std::swap(src[
i * 4], src[
i * 4 + 3]);
4481 std::swap(src[
i * 4 + 1], src[
i * 4 + 2]);
4483 set_neon_register(Vd, src);
4495 get_neon_register(Vm, src);
4496 std::swap(src[0], src[1]);
4497 std::swap(src[2], src[3]);
4498 set_neon_register(Vd, src);
4503 get_neon_register(Vm, src);
4504 for (
int i = 0;
i < 2;
i++) {
4505 std::swap(src[
i * 4], src[
i * 4 + 3]);
4506 std::swap(src[
i * 4 + 1], src[
i * 4 + 2]);
4508 set_neon_register(Vd, src);
4513 get_neon_register(Vm, src);
4514 for (
int i = 0;
i < 4;
i++) {
4515 std::swap(src[
i], src[7 -
i]);
4516 std::swap(src[
i + 8], src[15 -
i]);
4518 set_neon_register(Vd, src);
4529 }
else if (opc1 == 0 && (opc2 == 0b0100 || opc2 == 0b0101)) {
4531 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4532 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4537 is_signed ? PairwiseAddLong<int8_t, int16_t>(
this, Vd, Vm)
4538 : PairwiseAddLong<uint8_t,
uint16_t>(this, Vd, Vm);
4541 is_signed ? PairwiseAddLong<int16_t, int32_t>(
this, Vd, Vm)
4542 : PairwiseAddLong<
uint16_t, uint32_t>(this, Vd, Vm);
4545 is_signed ? PairwiseAddLong<int32_t, int64_t>(
this, Vd, Vm)
4546 : PairwiseAddLong<uint32_t, uint64_t>(this, Vd, Vm);
4551 }
else if (opc1 == 0 && (opc2 == 0b1100 || opc2 == 0b1101)) {
4553 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4554 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4560 ? PairwiseAddAccumulateLong<int8_t, int16_t>(
this, Vd, Vm)
4561 : PairwiseAddAccumulateLong<uint8_t,
uint16_t>(this, Vd, Vm);
4565 ? PairwiseAddAccumulateLong<int16_t, int32_t>(
this, Vd, Vm)
4566 : PairwiseAddAccumulateLong<
uint16_t, uint32_t>(this, Vd, Vm);
4570 ? PairwiseAddAccumulateLong<int32_t, int64_t>(
this, Vd, Vm)
4571 : PairwiseAddAccumulateLong<uint32_t, uint64_t>(this, Vd, Vm);
4576 }
else if (size == 0 && opc1 == 0b10 && opc2 == 0) {
4577 if (
instr->Bit(6) == 0) {
4579 uint64_t dval, mval;
4580 int vd =
instr->VFPDRegValue(kDoublePrecision);
4581 int vm =
instr->VFPMRegValue(kDoublePrecision);
4582 get_d_register(vd, &dval);
4583 get_d_register(vm, &mval);
4584 set_d_register(vm, &dval);
4585 set_d_register(vd, &mval);
4588 uint32_t dval[4], mval[4];
4589 int vd =
instr->VFPDRegValue(kSimd128Precision);
4590 int vm =
instr->VFPMRegValue(kSimd128Precision);
4591 get_neon_register(vd, dval);
4592 get_neon_register(vm, mval);
4593 set_neon_register(vm, dval);
4594 set_neon_register(vd, mval);
4596 }
else if (opc1 == 0 && opc2 == 0b1010) {
4599 int vd =
instr->VFPDRegValue(q ? kSimd128Precision : kDoublePrecision);
4600 int vm =
instr->VFPMRegValue(q ? kSimd128Precision : kDoublePrecision);
4602 get_neon_register(vm, q_data);
4603 for (
int i = 0;
i < 16;
i++) {
4604 q_data[
i] = base::bits::CountPopulation(q_data[
i]);
4606 set_neon_register(vd, q_data);
4607 }
else if (opc1 == 0 && opc2 == 0b1011) {
4609 int vd =
instr->VFPDRegValue(kSimd128Precision);
4610 int vm =
instr->VFPMRegValue(kSimd128Precision);
4612 get_neon_register(vm, q_data);
4613 for (
int i = 0;
i < 4;
i++) q_data[
i] = ~q_data[
i];
4614 set_neon_register(vd, q_data);
4615 }
else if (opc1 == 0b01 && opc2 == 0b0010) {
4617 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4618 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4621 Unop<int8_t>(
this, Vd, Vm, [](int8_t
x) {
return x == 0 ? -1 : 0; });
4624 Unop<int16_t>(
this, Vd, Vm,
4625 [](int16_t
x) {
return x == 0 ? -1 : 0; });
4628 Unop<int32_t>(
this, Vd, Vm,
4629 [](int32_t
x) {
return x == 0 ? -1 : 0; });
4634 }
else if (opc1 == 0b01 && opc2 == 0b0100) {
4636 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4637 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4640 Unop<int8_t>(
this, Vd, Vm, [](int8_t
x) {
return x < 0 ? -1 : 0; });
4643 Unop<int16_t>(
this, Vd, Vm, [](int16_t
x) {
return x < 0 ? -1 : 0; });
4646 Unop<int32_t>(
this, Vd, Vm, [](int32_t
x) {
return x < 0 ? -1 : 0; });
4651 }
else if (opc1 == 0b01 && (opc2 & 0b0111) == 0b110) {
4653 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4654 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4655 if (
instr->Bit(10) != 0) {
4658 get_neon_register(Vm, src);
4659 for (
int i = 0;
i < 4;
i++) {
4660 src[
i] &= ~0x80000000;
4662 set_neon_register(Vd, src);
4667 Abs<int8_t, kSimd128Size>(
this, Vd, Vm);
4670 Abs<int16_t, kSimd128Size>(
this, Vd, Vm);
4673 Abs<int32_t, kSimd128Size>(
this, Vd, Vm);
4679 }
else if (opc1 == 0b01 && (opc2 & 0b0111) == 0b111) {
4680 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4681 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4683 if (
instr->Bit(10) != 0) {
4686 get_neon_register(Vm, src);
4687 for (
int i = 0;
i < 4;
i++) {
4688 src[
i] ^= 0x80000000;
4690 set_neon_register(Vd, src);
4695 Neg<int8_t, kSimd128Size>(
this, Vd, Vm);
4698 Neg<int16_t, kSimd128Size>(
this, Vd, Vm);
4701 Neg<int32_t, kSimd128Size>(
this, Vd, Vm);
4707 }
else if (opc1 == 0b10 && opc2 == 0b0001) {
4709 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4710 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4714 Transpose<uint8_t, kSimd128Size>(
this, Vd, Vm);
4717 Transpose<uint16_t, kSimd128Size>(
this, Vd, Vm);
4720 Transpose<uint32_t, kSimd128Size>(
this, Vd, Vm);
4726 int Vd =
instr->VFPDRegValue(kDoublePrecision);
4727 int Vm =
instr->VFPMRegValue(kDoublePrecision);
4731 Transpose<uint8_t, kDoubleSize>(
this, Vd, Vm);
4734 Transpose<uint16_t, kDoubleSize>(
this, Vd, Vm);
4737 Transpose<uint32_t, kDoubleSize>(
this, Vd, Vm);
4743 }
else if (opc1 == 0b10 && (opc2 & 0b1110) == 0b0010) {
4746 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4747 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4748 if (
instr->Bit(7) == 1) {
4752 Zip<uint8_t, kSimd128Size>(
this, Vd, Vm);
4755 Zip<uint16_t, kSimd128Size>(
this, Vd, Vm);
4758 Zip<uint32_t, kSimd128Size>(
this, Vd, Vm);
4767 Unzip<uint8_t, kSimd128Size>(
this, Vd, Vm);
4770 Unzip<uint16_t, kSimd128Size>(
this, Vd, Vm);
4773 Unzip<uint32_t, kSimd128Size>(
this, Vd, Vm);
4780 int Vd =
instr->VFPDRegValue(kDoublePrecision);
4781 int Vm =
instr->VFPMRegValue(kDoublePrecision);
4782 if (
instr->Bit(7) == 1) {
4786 Zip<uint8_t, kDoubleSize>(
this, Vd, Vm);
4789 Zip<uint16_t, kDoubleSize>(
this, Vd, Vm);
4800 Unzip<uint8_t, kDoubleSize>(
this, Vd, Vm);
4803 Unzip<uint16_t, kDoubleSize>(
this, Vd, Vm);
4812 }
else if (opc1 == 0b10 && (opc2 & 0b1110) == 0b0100) {
4814 int Vd =
instr->VFPDRegValue(kDoublePrecision);
4815 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4817 bool dst_unsigned =
instr->Bit(6) != 0;
4818 bool src_unsigned =
instr->Bits(7, 6) == 0b11;
4823 SaturatingNarrow<uint16_t, uint8_t>(
this, Vd, Vm);
4824 }
else if (dst_unsigned) {
4825 SaturatingNarrow<int16_t, uint8_t>(
this, Vd, Vm);
4827 SaturatingNarrow<int16_t, int8_t>(
this, Vd, Vm);
4833 SaturatingNarrow<uint32_t, uint16_t>(
this, Vd, Vm);
4834 }
else if (dst_unsigned) {
4835 SaturatingNarrow<int32_t, uint16_t>(
this, Vd, Vm);
4837 SaturatingNarrow<int32_t, int16_t>(
this, Vd, Vm);
4843 SaturatingNarrow<uint64_t, uint32_t>(
this, Vd, Vm);
4844 }
else if (dst_unsigned) {
4845 SaturatingNarrow<int64_t, uint32_t>(
this, Vd, Vm);
4847 SaturatingNarrow<int64_t, int32_t>(
this, Vd, Vm);
4854 }
else if (opc1 == 0b10 &&
instr->Bit(10) == 1) {
4858 int regs =
instr->Bit(6) + 1;
4860 float (*fproundint)(float) =
nullptr;
4863 fproundint = &nearbyintf;
4866 fproundint = &truncf;
4869 fproundint = &floorf;
4872 fproundint = &ceilf;
4877 int vm =
instr->VFPMRegValue(kDoublePrecision);
4878 int vd =
instr->VFPDRegValue(kDoublePrecision);
4881 for (
int r = 0;
r < regs;
r++) {
4884 get_neon_register<float, kDoubleSize>(vm +
r, floats);
4885 for (
int e = 0; e < 2; e++) {
4886 floats[e] = canonicalizeNaN(fproundint(floats[e]));
4888 set_neon_register<float, kDoubleSize>(vd +
r, floats);
4890 }
else if (opc1 == 0b11 && (opc2 & 0b1100) == 0b1000) {
4892 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4893 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4895 get_neon_register(Vm, src);
4896 if (
instr->Bit(7) == 0) {
4897 for (
int i = 0;
i < 4;
i++) {
4898 float denom = base::bit_cast<float>(src[
i]);
4899 div_zero_vfp_flag_ = (denom == 0);
4900 float result = 1.0f / denom;
4902 src[
i] = base::bit_cast<uint32_t>(
result);
4905 for (
int i = 0;
i < 4;
i++) {
4906 float radicand = base::bit_cast<float>(src[
i]);
4907 float result = 1.0f / std::sqrt(radicand);
4909 src[
i] = base::bit_cast<uint32_t>(
result);
4912 set_neon_register(Vd, src);
4913 }
else if (opc1 == 0b11 && (opc2 & 0b1100) == 0b1100) {
4915 int Vd =
instr->VFPDRegValue(kSimd128Precision);
4916 int Vm =
instr->VFPMRegValue(kSimd128Precision);
4918 get_neon_register(Vm, q_data);
4919 int op =
instr->Bits(8, 7);
4920 for (
int i = 0;
i < 4;
i++) {
4924 q_data[
i] = base::bit_cast<uint32_t>(std::round(
4925 static_cast<float>(base::bit_cast<int32_t>(q_data[
i]))));
4929 q_data[
i] = base::bit_cast<uint32_t>(
4930 std::round(
static_cast<float>(q_data[
i])));
4934 q_data[
i] =
static_cast<uint32_t
>(ConvertDoubleToInt(
4935 base::bit_cast<float>(q_data[
i]),
false, RZ));
4939 q_data[
i] =
static_cast<uint32_t
>(
4940 ConvertDoubleToInt(base::bit_cast<float>(q_data[
i]),
true, RZ));
4944 set_neon_register(Vd, q_data);
4948 }
else if (op0 && op1 == 0b11 && op2 == 0b10) {
4950 int vd =
instr->VFPDRegValue(kDoublePrecision);
4951 int vn =
instr->VFPNRegValue(kDoublePrecision);
4952 int vm =
instr->VFPMRegValue(kDoublePrecision);
4954 bool vtbx =
instr->Bit(6) != 0;
4957 get_d_register(vm, &indices);
4960 int index = (indices >> shift) & 0xFF;
4961 if (index < table_len) {
4963 get_d_register(vn + index / kDoubleSize, &table);
4970 set_d_register(vd, &
result);
4971 }
else if (op0 && op1 == 0b11 && op2 == 0b11) {
4973 if (
instr->Bits(9, 7) == 0) {
4976 int vm =
instr->VFPMRegValue(kDoublePrecision);
4977 int imm4 =
instr->Bits(19, 16);
4978 int size = 0, index = 0,
mask = 0;
4979 if ((imm4 & 0x1) != 0) {
4983 }
else if ((imm4 & 0x2) != 0) {
4993 get_d_register(vm, &d_data);
4994 uint32_t scalar = (d_data >> (size *
index)) &
mask;
4995 uint32_t duped = scalar;
4996 for (
int i = 1;
i < 32 /
size;
i++) {
5000 uint32_t
result[4] = {duped, duped, duped, duped};
5001 if (
instr->Bit(6) == 0) {
5002 int vd =
instr->VFPDRegValue(kDoublePrecision);
5003 set_d_register(vd,
result);
5005 int vd =
instr->VFPDRegValue(kSimd128Precision);
5006 set_neon_register(vd,
result);
5011 }
else if (op1 != 0b11 && !op3) {
5013 int u =
instr->Bit(24);
5014 int opc =
instr->Bits(11, 8);
5016 if (opc == 0b1000) {
5020 int Vd =
instr->VFPDRegValue(kSimd128Precision);
5021 int Vn =
instr->VFPNRegValue(kDoublePrecision);
5022 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5023 uint64_t src1, src2, dst[2];
5025 get_neon_register<uint64_t>(Vd, dst);
5026 get_d_register(Vn, &src1);
5027 get_d_register(Vm, &src2);
5028 dst[0] += (src1 & 0xFFFFFFFFULL) * (src2 & 0xFFFFFFFFULL);
5029 dst[1] += (src1 >> 32) * (src2 >> 32);
5030 set_neon_register<uint64_t>(Vd, dst);
5031 }
else if (opc == 0b1100) {
5032 int Vd =
instr->VFPDRegValue(kSimd128Precision);
5033 int Vn =
instr->VFPNRegValue(kDoublePrecision);
5034 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5039 MultiplyLong<uint8_t, uint16_t>(
this, Vd, Vn, Vm);
5043 MultiplyLong<uint16_t, uint32_t>(
this, Vd, Vn, Vm);
5047 MultiplyLong<uint32_t, uint64_t>(
this, Vd, Vn, Vm);
5058 MultiplyLong<int8_t, int16_t>(
this, Vd, Vn, Vm);
5062 MultiplyLong<int16_t, int32_t>(
this, Vd, Vn, Vm);
5066 MultiplyLong<int32_t, int64_t>(
this, Vd, Vn, Vm);
5075 }
else if (op1 != 0b11 && op3) {
5083void Simulator::DecodeAdvancedSIMDDataProcessing(Instruction*
instr) {
5084 int op0 =
instr->Bit(23);
5085 int op1 =
instr->Bit(4);
5089 int u =
instr->Bit(24);
5090 int opc =
instr->Bits(11, 8);
5091 int q =
instr->Bit(6);
5092 int sz =
instr->Bits(21, 20);
5095 Vd =
instr->VFPDRegValue(kSimd128Precision);
5096 Vm =
instr->VFPMRegValue(kSimd128Precision);
5097 Vn =
instr->VFPNRegValue(kSimd128Precision);
5099 Vd =
instr->VFPDRegValue(kDoublePrecision);
5100 Vm =
instr->VFPMRegValue(kDoublePrecision);
5101 Vn =
instr->VFPNRegValue(kDoublePrecision);
5104 if (!u && opc == 0 && op1) {
5109 AddSat<int8_t>(
this, Vd, Vm, Vn);
5112 AddSat<int16_t>(
this, Vd, Vm, Vn);
5115 AddSat<int32_t>(
this, Vd, Vm, Vn);
5120 }
else if (!u && opc == 1 && sz == 2 && q && op1) {
5124 get_neon_register(Vm, src1);
5127 get_neon_register(Vn, src2);
5128 for (
int i = 0;
i < 4;
i++) {
5129 src1[
i] = src1[
i] | src2[
i];
5132 set_neon_register(Vd, src1);
5133 }
else if (!u && opc == 1 && sz == 3 && q && op1) {
5136 Binop<uint32_t>(
this, Vd, Vm, Vn,
5137 [](uint32_t
x, uint32_t
y) {
return x | (~y); });
5138 }
else if (!u && opc == 1 && sz == 0 && q && op1) {
5140 uint32_t src1[4], src2[4];
5141 get_neon_register(Vn, src1);
5142 get_neon_register(Vm, src2);
5143 for (
int i = 0;
i < 4;
i++) {
5144 src1[
i] = src1[
i] & src2[
i];
5146 set_neon_register(Vd, src1);
5147 }
else if (!u && opc == 1 && sz == 1 && q && op1) {
5149 uint32_t src1[4], src2[4];
5150 get_neon_register(Vn, src1);
5151 get_neon_register(Vm, src2);
5152 for (
int i = 0;
i < 4;
i++) {
5153 src1[
i] = src1[
i] & ~src2[
i];
5155 set_neon_register(Vd, src1);
5156 }
else if (!u && opc == 2 && op1) {
5161 SubSat<int8_t>(
this, Vd, Vm, Vn);
5164 SubSat<int16_t>(
this, Vd, Vm, Vn);
5167 SubSat<int32_t>(
this, Vd, Vm, Vn);
5170 SubSat<int64_t>(
this, Vd, Vm, Vn);
5175 }
else if (!u && opc == 3) {
5181 CompareGreater<int8_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
5184 CompareGreater<int16_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
5187 CompareGreater<int32_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
5192 }
else if (!u && opc == 4 && !op1) {
5197 ShiftByRegister<int8_t, int8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5200 ShiftByRegister<int16_t, int16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5203 ShiftByRegister<int32_t, int32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5206 ShiftByRegister<int64_t, int64_t, kSimd128Size>(
this, Vd, Vm, Vn);
5211 }
else if (!u && opc == 6) {
5214 bool min =
instr->Bit(4) != 0;
5217 MinMax<int8_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
5220 MinMax<int16_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
5223 MinMax<int32_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
5228 }
else if (!u && opc == 8 && op1) {
5233 Test<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5236 Test<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5239 Test<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5244 }
else if (!u && opc == 8 && !op1) {
5249 Add<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5252 Add<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5255 Add<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5258 Add<uint64_t, kSimd128Size>(
this, Vd, Vm, Vn);
5261 }
else if (opc == 9 && op1) {
5266 Mul<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5269 Mul<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5272 Mul<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5277 }
else if (!u && opc == 0xA) {
5280 bool min =
instr->Bit(4) != 0;
5283 PairwiseMinMax<int8_t>(
this, Vd, Vm, Vn, min);
5286 PairwiseMinMax<int16_t>(
this, Vd, Vm, Vn, min);
5289 PairwiseMinMax<int32_t>(
this, Vd, Vm, Vn, min);
5294 }
else if (!u && opc == 0xB) {
5299 PairwiseAdd<int8_t>(
this, Vd, Vm, Vn);
5302 PairwiseAdd<int16_t>(
this, Vd, Vm, Vn);
5305 PairwiseAdd<int32_t>(
this, Vd, Vm, Vn);
5310 }
else if (!u && opc == 0xD && !op1) {
5311 float src1[4], src2[4];
5312 get_neon_register(Vn, src1);
5313 get_neon_register(Vm, src2);
5314 for (
int i = 0;
i < 4;
i++) {
5315 if (
instr->Bit(21) == 0) {
5317 src1[
i] = src1[
i] + src2[
i];
5320 src1[
i] = src1[
i] - src2[
i];
5323 set_neon_register(Vd, src1);
5324 }
else if (!u && opc == 0xE && !sz && !op1) {
5326 float src1[4], src2[4];
5327 get_neon_register(Vn, src1);
5328 get_neon_register(Vm, src2);
5330 for (
int i = 0;
i < 4;
i++) {
5331 dst[
i] = (src1[
i] == src2[
i]) ? 0xFFFFFFFF : 0;
5333 set_neon_register(Vd, dst);
5334 }
else if (!u && opc == 0xF && op1) {
5335 float src1[4], src2[4];
5336 get_neon_register(Vn, src1);
5337 get_neon_register(Vm, src2);
5338 if (
instr->Bit(21) == 0) {
5340 for (
int i = 0;
i < 4;
i++) {
5341 src1[
i] = 2.0f - src1[
i] * src2[
i];
5345 for (
int i = 0;
i < 4;
i++) {
5346 src1[
i] = (3.0f - src1[
i] * src2[
i]) * 0.5f;
5349 set_neon_register(Vd, src1);
5350 }
else if (!u && opc == 0xF && !op1) {
5351 float src1[4], src2[4];
5352 get_neon_register(Vn, src1);
5353 get_neon_register(Vm, src2);
5355 bool min =
instr->Bit(21) == 1;
5356 bool saved = FPSCR_default_NaN_mode_;
5357 FPSCR_default_NaN_mode_ =
true;
5358 for (
int i = 0;
i < 4;
i++) {
5360 src1[
i] = canonicalizeNaN(MinMax(src1[
i], src2[
i], min));
5362 FPSCR_default_NaN_mode_ = saved;
5363 set_neon_register(Vd, src1);
5364 }
else if (u && opc == 0 && op1) {
5369 AddSat<uint8_t>(
this, Vd, Vm, Vn);
5372 AddSat<uint16_t>(
this, Vd, Vm, Vn);
5375 AddSat<uint32_t>(
this, Vd, Vm, Vn);
5380 }
else if (u && opc == 1 && sz == 1 && op1) {
5382 uint32_t dst[4], src1[4], src2[4];
5383 get_neon_register(Vd, dst);
5384 get_neon_register(Vn, src1);
5385 get_neon_register(Vm, src2);
5386 for (
int i = 0;
i < 4;
i++) {
5387 dst[
i] = (dst[
i] & src1[
i]) | (~dst[
i] & src2[
i]);
5389 set_neon_register(Vd, dst);
5390 }
else if (u && opc == 1 && sz == 0 && !q && op1) {
5392 uint64_t src1, src2;
5393 get_d_register(Vn, &src1);
5394 get_d_register(Vm, &src2);
5396 set_d_register(Vd, &src1);
5397 }
else if (u && opc == 1 && sz == 0 && q && op1) {
5399 uint32_t src1[4], src2[4];
5400 get_neon_register(Vn, src1);
5401 get_neon_register(Vm, src2);
5402 for (
int i = 0;
i < 4;
i++) src1[
i] ^= src2[
i];
5403 set_neon_register(Vd, src1);
5404 }
else if (u && opc == 1 && !op1) {
5409 Binop<uint8_t>(
this, Vd, Vm, Vn, RoundingAverageUnsigned<uint8_t>);
5412 Binop<uint16_t>(
this, Vd, Vm, Vn, RoundingAverageUnsigned<uint16_t>);
5415 Binop<uint32_t>(
this, Vd, Vm, Vn, RoundingAverageUnsigned<uint32_t>);
5420 }
else if (u && opc == 2 && op1) {
5425 SubSat<uint8_t>(
this, Vd, Vm, Vn);
5428 SubSat<uint16_t>(
this, Vd, Vm, Vn);
5431 SubSat<uint32_t>(
this, Vd, Vm, Vn);
5436 }
else if (u && opc == 3) {
5442 CompareGreater<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
5445 CompareGreater<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
5448 CompareGreater<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
5453 }
else if (u && opc == 4 && !op1) {
5458 ShiftByRegister<uint8_t, int8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5461 ShiftByRegister<uint16_t, int16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5464 ShiftByRegister<uint32_t, int32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5467 ShiftByRegister<uint64_t, int64_t, kSimd128Size>(
this, Vd, Vm, Vn);
5472 }
else if (u && opc == 6) {
5475 bool min =
instr->Bit(4) != 0;
5478 MinMax<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
5481 MinMax<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
5484 MinMax<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
5489 }
else if (u && opc == 8 && !op1) {
5494 Sub<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5497 Sub<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5500 Sub<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5503 Sub<uint64_t, kSimd128Size>(
this, Vd, Vm, Vn);
5506 }
else if (u && opc == 8 && op1) {
5511 CompareEqual<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
5514 CompareEqual<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
5517 CompareEqual<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
5522 }
else if (u && opc == 0xA) {
5525 bool min =
instr->Bit(4) != 0;
5528 PairwiseMinMax<uint8_t>(
this, Vd, Vm, Vn, min);
5531 PairwiseMinMax<uint16_t>(
this, Vd, Vm, Vn, min);
5534 PairwiseMinMax<uint32_t>(
this, Vd, Vm, Vn, min);
5539 }
else if (u && opc == 0xD && sz == 0 && q && op1) {
5541 float src1[4], src2[4];
5542 get_neon_register(Vn, src1);
5543 get_neon_register(Vm, src2);
5544 for (
int i = 0;
i < 4;
i++) {
5545 src1[
i] = src1[
i] * src2[
i];
5547 set_neon_register(Vd, src1);
5548 }
else if (u && opc == 0xD && sz == 0 && !q && !op1) {
5550 PairwiseAdd<float>(
this, Vd, Vm, Vn);
5551 }
else if (u && opc == 0xE && !op1) {
5553 bool ge =
instr->Bit(21) == 0;
5554 float src1[4], src2[4];
5555 get_neon_register(Vn, src1);
5556 get_neon_register(Vm, src2);
5558 for (
int i = 0;
i < 4;
i++) {
5560 dst[
i] = src1[
i] >= src2[
i] ? 0xFFFFFFFFu : 0;
5562 dst[
i] = src1[
i] > src2[
i] ? 0xFFFFFFFFu : 0;
5565 set_neon_register(Vd, dst);
5566 }
else if (u && opc == 0xB) {
5569 if (size == Neon16) {
5570 Binop<int16_t>(
this, Vd, Vm, Vn, SaturateRoundingQMul<int16_t>);
5573 Binop<int32_t>(
this, Vd, Vm, Vn, SaturateRoundingQMul<int32_t>);
5579 }
else if (op0 == 1 && op1 == 0) {
5580 DecodeAdvancedSIMDTwoOrThreeRegisters(
instr);
5581 }
else if (op0 == 1 && op1 == 1) {
5583 if (
instr->Bits(21, 19) == 0 &&
instr->Bit(7) == 0) {
5584 VmovImmediate(
this,
instr);
5587 int u =
instr->Bit(24);
5588 int imm3H =
instr->Bits(21, 19);
5589 int imm3L =
instr->Bits(18, 16);
5590 int opc =
instr->Bits(11, 8);
5591 int l =
instr->Bit(7);
5592 int q =
instr->Bit(6);
5593 int imm3H_L = imm3H << 1 | l;
5594 int imm7 =
instr->Bits(21, 16);
5596 int size = base::bits::RoundDownToPowerOfTwo32(imm7);
5598 static_cast<NeonSize>(base::bits::WhichPowerOfTwo(size >> 3));
5600 if (imm3H_L != 0 && opc == 0) {
5602 int shift = 2 * size - imm7;
5603 int Vd =
instr->VFPDRegValue(q ? kSimd128Precision : kDoublePrecision);
5604 int Vm =
instr->VFPMRegValue(q ? kSimd128Precision : kDoublePrecision);
5607 q ? ShiftRight<int8_t, kSimd128Size>(
this, Vd, Vm, shift, u)
5608 : ShiftRight<int8_t,
kDoubleSize>(this, Vd, Vm, shift, u);
5611 q ? ShiftRight<int16_t, kSimd128Size>(
this, Vd, Vm, shift, u)
5615 q ? ShiftRight<int32_t, kSimd128Size>(
this, Vd, Vm, shift, u)
5619 q ? ShiftRight<int64_t, kSimd128Size>(
this, Vd, Vm, shift, u)
5620 : ShiftRight<int64_t,
kDoubleSize>(this, Vd, Vm, shift, u);
5623 }
else if (imm3H_L != 0 && opc == 1) {
5626 int shift = 2 * size - imm7;
5627 int Vd =
instr->VFPDRegValue(kDoublePrecision);
5628 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5632 ShiftRightAccumulate<uint8_t, kDoubleSize>(
this, Vd, Vm, shift);
5635 ShiftRightAccumulate<uint16_t, kDoubleSize>(
this, Vd, Vm, shift);
5638 ShiftRightAccumulate<uint32_t, kDoubleSize>(
this, Vd, Vm, shift);
5641 ShiftRightAccumulate<uint64_t, kDoubleSize>(
this, Vd, Vm, shift);
5647 ArithmeticShiftRightAccumulate<int8_t, kDoubleSize>(
this, Vd, Vm,
5651 ArithmeticShiftRightAccumulate<int16_t, kDoubleSize>(
this, Vd, Vm,
5655 ArithmeticShiftRightAccumulate<int32_t, kDoubleSize>(
this, Vd, Vm,
5659 ArithmeticShiftRightAccumulate<int64_t, kDoubleSize>(
this, Vd, Vm,
5664 }
else if (imm3H_L != 0 && imm3L == 0 && opc == 0b1010 && !q) {
5668 int Vd =
instr->VFPDRegValue(kSimd128Precision);
5669 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5672 Widen<uint8_t, uint16_t>(
this, Vd, Vm);
5675 Widen<uint16_t, uint32_t>(
this, Vd, Vm);
5678 Widen<uint32_t, uint64_t>(
this, Vd, Vm);
5686 int Vd =
instr->VFPDRegValue(kSimd128Precision);
5687 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5690 Widen<int8_t, int16_t>(
this, Vd, Vm);
5693 Widen<int16_t, int32_t>(
this, Vd, Vm);
5696 Widen<int32_t, int64_t>(
this, Vd, Vm);
5702 }
else if (!u && imm3H_L != 0 && opc == 0b0101) {
5704 int shift = imm7 -
size;
5705 int Vd =
instr->VFPDRegValue(kSimd128Precision);
5706 int Vm =
instr->VFPMRegValue(kSimd128Precision);
5708 static_cast<NeonSize>(base::bits::WhichPowerOfTwo(size >> 3));
5711 ShiftLeft<uint8_t, kSimd128Size>(
this, Vd, Vm, shift);
5714 ShiftLeft<uint16_t, kSimd128Size>(
this, Vd, Vm, shift);
5717 ShiftLeft<uint32_t, kSimd128Size>(
this, Vd, Vm, shift);
5720 ShiftLeft<uint64_t, kSimd128Size>(
this, Vd, Vm, shift);
5723 }
else if (u && imm3H_L != 0 && opc == 0b0100) {
5725 int shift = 2 * size - imm7;
5726 int Vd =
instr->VFPDRegValue(kDoublePrecision);
5727 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5730 ShiftRightAndInsert<uint8_t, kDoubleSize>(
this, Vd, Vm, shift);
5733 ShiftRightAndInsert<uint16_t, kDoubleSize>(
this, Vd, Vm, shift);
5736 ShiftRightAndInsert<uint32_t, kDoubleSize>(
this, Vd, Vm, shift);
5739 ShiftRightAndInsert<uint64_t, kDoubleSize>(
this, Vd, Vm, shift);
5744 }
else if (u && imm3H_L != 0 && opc == 0b0101) {
5746 int shift = imm7 -
size;
5747 int Vd =
instr->VFPDRegValue(kDoublePrecision);
5748 int Vm =
instr->VFPMRegValue(kDoublePrecision);
5751 ShiftLeftAndInsert<uint8_t, kDoubleSize>(
this, Vd, Vm, shift);
5754 ShiftLeftAndInsert<uint16_t, kDoubleSize>(
this, Vd, Vm, shift);
5757 ShiftLeftAndInsert<uint32_t, kDoubleSize>(
this, Vd, Vm, shift);
5760 ShiftLeftAndInsert<uint64_t, kDoubleSize>(
this, Vd, Vm, shift);
5771void Simulator::DecodeMemoryHintsAndBarriers(Instruction*
instr) {
5772 switch (
instr->SpecialValue()) {
5775 if ((
instr->Bits(22, 20) == 5) && (
instr->Bits(15, 12) == 0xF)) {
5777 }
else if (
instr->SpecialValue() == 0xA &&
instr->Bits(22, 20) == 7) {
5790void Simulator::DecodeAdvancedSIMDElementOrStructureLoadStore(
5791 Instruction*
instr) {
5792 int op0 =
instr->Bit(23);
5793 int op1 =
instr->Bits(11, 10);
5796 DecodeAdvancedSIMDLoadStoreMultipleStructures(
instr);
5797 }
else if (op1 == 0b11) {
5798 DecodeAdvancedSIMDLoadSingleStructureToAllLanes(
instr);
5800 DecodeAdvancedSIMDLoadStoreSingleStructureToOneLane(
instr);
5804void Simulator::DecodeAdvancedSIMDLoadStoreMultipleStructures(
5805 Instruction*
instr) {
5806 int Vd =
instr->VFPDRegValue(kDoublePrecision);
5807 int Rn =
instr->VnValue();
5808 int Rm =
instr->VmValue();
5809 int type =
instr->Bits(11, 8);
5810 int32_t address = get_register(Rn);
5828 if (
instr->Bit(21)) {
5833 data[0] = ReadW(address);
5834 data[1] = ReadW(address + 4);
5835 set_d_register(Vd +
r, data);
5844 get_d_register(Vd +
r, data);
5845 WriteW(address, data[0]);
5846 WriteW(address + 4, data[1]);
5851 AdvancedSIMDElementOrStructureLoadStoreWriteback(Rn, Rm, 8 * regs);
5854void Simulator::DecodeAdvancedSIMDLoadSingleStructureToAllLanes(
5855 Instruction*
instr) {
5857 int N =
instr->Bits(9, 8);
5859 int Vd =
instr->VFPDRegValue(kDoublePrecision);
5860 int Rn =
instr->VnValue();
5861 int Rm =
instr->VmValue();
5862 int32_t address = get_register(Rn);
5866 int regs =
instr->Bit(5) + 1;
5867 int size =
instr->Bits(7, 6);
5871 uint8_t data = ReadBU(address);
5872 uint8_t* dst =
reinterpret_cast<uint8_t*
>(q_data);
5873 for (
int i = 0;
i < 8;
i++) {
5881 for (
int i = 0;
i < 4;
i++) {
5887 uint32_t data = ReadW(address);
5888 for (
int i = 0;
i < 2;
i++) {
5894 for (
int r = 0;
r < regs;
r++) {
5895 set_neon_register<uint32_t, kDoubleSize>(Vd +
r, q_data);
5897 AdvancedSIMDElementOrStructureLoadStoreWriteback(Rn, Rm, 1 << size);
5903void Simulator::DecodeAdvancedSIMDLoadStoreSingleStructureToOneLane(
5904 Instruction*
instr) {
5906 int size =
instr->Bits(11, 10);
5907 int N =
instr->Bits(9, 8);
5908 int Vd =
instr->VFPDRegValue(kDoublePrecision);
5909 int Rn =
instr->VnValue();
5910 int Rm =
instr->VmValue();
5911 int32_t address = get_register(Rn);
5917 get_d_register(Vd, &dreg);
5920 uint64_t data = ReadBU(address);
5922 int i =
instr->Bits(7, 5) * 8;
5923 dreg = (dreg & ~(uint64_t{0xff} <<
i)) | (data <<
i);
5928 uint64_t data = ReadHU(address);
5929 int i =
instr->Bits(7, 6) * 16;
5930 dreg = (dreg & ~(uint64_t{0xffff} <<
i)) | (data <<
i);
5935 uint64_t data =
static_cast<unsigned>(ReadW(address));
5936 int i =
instr->Bit(7) * 32;
5937 dreg = (dreg & ~(uint64_t{0xffffffff} <<
i)) | (data <<
i);
5945 set_d_register(Vd, &dreg);
5946 AdvancedSIMDElementOrStructureLoadStoreWriteback(Rn, Rm, 1 << size);
5947 }
else if (!L && N == 0) {
5951 get_d_register(Vd, &dreg);
5955 int i =
instr->Bits(7, 5) * 8;
5956 dreg = (dreg >>
i) & 0xff;
5957 WriteB(address,
static_cast<uint8_t
>(dreg));
5962 int i =
instr->Bits(7, 6) * 16;
5963 dreg = (dreg >>
i) & 0xffff;
5964 WriteH(address,
static_cast<uint16_t>(dreg));
5969 int i =
instr->Bit(7) * 32;
5970 dreg = (dreg >>
i) & 0xffffffff;
5971 WriteW(address, base::bit_cast<int>(
static_cast<uint32_t
>(dreg)));
5979 AdvancedSIMDElementOrStructureLoadStoreWriteback(Rn, Rm, 1 << size);
5985void Simulator::DecodeFloatingPointDataProcessing(Instruction*
instr) {
5986 switch (
instr->SpecialValue()) {
5988 if (
instr->Opc1Value() == 0x7 &&
instr->Opc3Value() == 0x1 &&
5989 instr->Bits(11, 9) == 0x5 &&
instr->Bits(19, 18) == 0x2) {
5990 if (
instr->SzValue() == 0x1) {
5991 int vm =
instr->VFPMRegValue(kDoublePrecision);
5992 int vd =
instr->VFPDRegValue(kDoublePrecision);
5993 double dm_value = get_double_from_d_register(vm).get_scalar();
5994 double dd_value = 0.0;
5998 dd_value = round(dm_value);
6001 dd_value = nearbyint(dm_value);
6005 dd_value = ceil(dm_value);
6008 dd_value = floor(dm_value);
6013 dd_value = canonicalizeNaN(dd_value);
6014 set_d_register_from_double(vd, dd_value);
6016 int m =
instr->VFPMRegValue(kSinglePrecision);
6017 int d =
instr->VFPDRegValue(kSinglePrecision);
6018 float sm_value = get_float_from_s_register(
m).get_scalar();
6019 float sd_value = 0.0;
6023 sd_value = roundf(sm_value);
6026 sd_value = nearbyintf(sm_value);
6030 sd_value = ceilf(sm_value);
6033 sd_value = floorf(sm_value);
6038 sd_value = canonicalizeNaN(sd_value);
6039 set_s_register_from_float(d, sd_value);
6041 }
else if ((
instr->Opc1Value() == 0x4) && (
instr->Bits(11, 9) == 0x5) &&
6042 (
instr->Bit(4) == 0x0)) {
6043 if (
instr->SzValue() == 0x1) {
6044 int m =
instr->VFPMRegValue(kDoublePrecision);
6045 int n =
instr->VFPNRegValue(kDoublePrecision);
6046 int d =
instr->VFPDRegValue(kDoublePrecision);
6047 double dn_value = get_double_from_d_register(n).get_scalar();
6048 double dm_value = get_double_from_d_register(
m).get_scalar();
6050 if (
instr->Bit(6) == 0x1) {
6051 if ((dn_value < dm_value) || std::isnan(dm_value)) {
6052 dd_value = dn_value;
6053 }
else if ((dm_value < dn_value) || std::isnan(dn_value)) {
6054 dd_value = dm_value;
6058 dd_value = std::signbit(dn_value) ? dn_value : dm_value;
6061 if ((dn_value > dm_value) || std::isnan(dm_value)) {
6062 dd_value = dn_value;
6063 }
else if ((dm_value > dn_value) || std::isnan(dn_value)) {
6064 dd_value = dm_value;
6068 dd_value = std::signbit(dn_value) ? dm_value : dn_value;
6071 dd_value = canonicalizeNaN(dd_value);
6072 set_d_register_from_double(d, dd_value);
6074 int m =
instr->VFPMRegValue(kSinglePrecision);
6075 int n =
instr->VFPNRegValue(kSinglePrecision);
6076 int d =
instr->VFPDRegValue(kSinglePrecision);
6077 float sn_value = get_float_from_s_register(n).get_scalar();
6078 float sm_value = get_float_from_s_register(
m).get_scalar();
6080 if (
instr->Bit(6) == 0x1) {
6081 if ((sn_value < sm_value) || std::isnan(sm_value)) {
6082 sd_value = sn_value;
6083 }
else if ((sm_value < sn_value) || std::isnan(sn_value)) {
6084 sd_value = sm_value;
6088 sd_value = std::signbit(sn_value) ? sn_value : sm_value;
6091 if ((sn_value > sm_value) || std::isnan(sm_value)) {
6092 sd_value = sn_value;
6093 }
else if ((sm_value > sn_value) || std::isnan(sn_value)) {
6094 sd_value = sm_value;
6098 sd_value = std::signbit(sn_value) ? sm_value : sn_value;
6101 sd_value = canonicalizeNaN(sd_value);
6102 set_s_register_from_float(d, sd_value);
6109 if ((
instr->Bits(11, 9) == 0x5) && (
instr->Bit(6) == 0) &&
6110 (
instr->Bit(4) == 0)) {
6112 bool condition_holds;
6113 switch (
instr->Bits(21, 20)) {
6115 condition_holds = (z_flag_ == 1);
6118 condition_holds = (v_flag_ == 1);
6121 condition_holds = (n_flag_ == v_flag_);
6124 condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_));
6129 if (
instr->SzValue() == 0x1) {
6130 int n =
instr->VFPNRegValue(kDoublePrecision);
6131 int m =
instr->VFPMRegValue(kDoublePrecision);
6132 int d =
instr->VFPDRegValue(kDoublePrecision);
6133 Float64 result = get_double_from_d_register(condition_holds ? n :
m);
6134 set_d_register_from_double(d,
result);
6136 int n =
instr->VFPNRegValue(kSinglePrecision);
6137 int m =
instr->VFPMRegValue(kSinglePrecision);
6138 int d =
instr->VFPDRegValue(kSinglePrecision);
6139 Float32 result = get_float_from_s_register(condition_holds ? n :
m);
6140 set_s_register_from_float(d,
result);
6151void Simulator::DecodeSpecialCondition(Instruction*
instr) {
6152 int op0 =
instr->Bits(25, 24);
6153 int op1 =
instr->Bits(11, 9);
6154 int op2 =
instr->Bit(4);
6156 if (
instr->Bit(27) == 0) {
6157 DecodeUnconditional(
instr);
6158 }
else if ((
instr->Bits(27, 26) == 0b11) && (op0 == 0b10) &&
6159 ((op1 >> 1) == 0b10) && !op2) {
6160 DecodeFloatingPointDataProcessing(
instr);
6167void Simulator::InstructionDecode(Instruction*
instr) {
6169 CheckICache(i_cache(),
instr);
6171 pc_modified_ =
false;
6172 if (InstructionTracingEnabled()) {
6177 dasm.InstructionDecode(buffer,
reinterpret_cast<uint8_t*
>(
instr));
6181 if (
instr->ConditionField() == kSpecialCondition) {
6182 DecodeSpecialCondition(
instr);
6183 }
else if (ConditionallyExecute(
instr)) {
6184 switch (
instr->TypeValue()) {
6187 DecodeType01(
instr);
6219 if (!pc_modified_) {
6224void Simulator::Execute() {
6227 int program_counter = get_pc();
6232 while (program_counter != end_sim_pc) {
6233 Instruction*
instr =
reinterpret_cast<Instruction*
>(program_counter);
6234 icount_ = base::AddWithWraparound(icount_, 1);
6235 InstructionDecode(
instr);
6236 program_counter = get_pc();
6241 while (program_counter != end_sim_pc) {
6242 Instruction*
instr =
reinterpret_cast<Instruction*
>(program_counter);
6243 icount_ = base::AddWithWraparound(icount_, 1);
6244 if (icount_ ==
v8_flags.stop_sim_at) {
6245 ArmDebugger dbg(
this);
6248 InstructionDecode(
instr);
6250 program_counter = get_pc();
6255void Simulator::CallInternal(Address entry) {
6257 isolate_->stack_guard()->AdjustStackLimitForSimulator();
6260 set_register(
pc,
static_cast<int32_t>(entry));
6264 set_register(lr, end_sim_pc);
6269 int32_t r4_val = get_register(r4);
6270 int32_t r5_val = get_register(r5);
6271 int32_t r6_val = get_register(r6);
6272 int32_t r7_val = get_register(r7);
6273 int32_t r8_val = get_register(r8);
6274 int32_t r9_val = get_register(r9);
6275 int32_t r10_val = get_register(r10);
6276 int32_t r11_val = get_register(r11);
6280 int32_t callee_saved_value = icount_;
6281 set_register(r4, callee_saved_value);
6282 set_register(r5, callee_saved_value);
6283 set_register(r6, callee_saved_value);
6284 set_register(r7, callee_saved_value);
6285 set_register(r8, callee_saved_value);
6286 set_register(r9, callee_saved_value);
6287 set_register(r10, callee_saved_value);
6288 set_register(r11, callee_saved_value);
6294 CHECK_EQ(callee_saved_value, get_register(r4));
6295 CHECK_EQ(callee_saved_value, get_register(r5));
6296 CHECK_EQ(callee_saved_value, get_register(r6));
6297 CHECK_EQ(callee_saved_value, get_register(r7));
6298 CHECK_EQ(callee_saved_value, get_register(r8));
6299 CHECK_EQ(callee_saved_value, get_register(r9));
6300 CHECK_EQ(callee_saved_value, get_register(r10));
6301 CHECK_EQ(callee_saved_value, get_register(r11));
6304 set_register(r4, r4_val);
6305 set_register(r5, r5_val);
6306 set_register(r6, r6_val);
6307 set_register(r7, r7_val);
6308 set_register(r8, r8_val);
6309 set_register(r9, r9_val);
6310 set_register(r10, r10_val);
6311 set_register(r11, r11_val);
6314intptr_t Simulator::CallImpl(Address entry,
int argument_count,
6315 const intptr_t* arguments) {
6319 int reg_arg_count = std::min(4, argument_count);
6320 if (reg_arg_count > 0) set_register(r0, arguments[0]);
6321 if (reg_arg_count > 1) set_register(r1, arguments[1]);
6322 if (reg_arg_count > 2) set_register(r2, arguments[2]);
6323 if (reg_arg_count > 3) set_register(r3, arguments[3]);
6326 int original_stack = get_register(sp);
6328 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(
int32_t));
6329 if (base::OS::ActivationFrameAlignment() != 0) {
6330 entry_stack &= -base::OS::ActivationFrameAlignment();
6333 memcpy(
reinterpret_cast<intptr_t*
>(entry_stack), arguments + reg_arg_count,
6334 (argument_count - reg_arg_count) *
sizeof(*arguments));
6335 set_register(sp, entry_stack);
6337 CallInternal(entry);
6340 CHECK_EQ(entry_stack, get_register(sp));
6341 set_register(sp, original_stack);
6343 return get_register(r0);
6346intptr_t Simulator::CallFPImpl(Address entry,
double d0,
double d1) {
6347 if (use_eabi_hardfloat()) {
6348 set_d_register_from_double(0, d0);
6349 set_d_register_from_double(1, d1);
6351 set_register_pair_from_double(0, &d0);
6352 set_register_pair_from_double(2, &d1);
6354 CallInternal(entry);
6355 return get_register(r0);
6358uintptr_t Simulator::PushAddress(uintptr_t address) {
6359 int new_sp = get_register(sp) -
sizeof(uintptr_t);
6360 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
6361 *stack_slot = address;
6362 set_register(sp, new_sp);
6366uintptr_t Simulator::PopAddress() {
6367 int current_sp = get_register(sp);
6368 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
6369 uintptr_t address = *stack_slot;
6370 set_register(sp, current_sp +
sizeof(uintptr_t));
6374Simulator::LocalMonitor::LocalMonitor()
6375 : access_state_(MonitorAccess::Open),
6379void Simulator::LocalMonitor::Clear() {
6380 access_state_ = MonitorAccess::Open;
6382 size_ = TransactionSize::None;
6385void Simulator::LocalMonitor::NotifyLoad(int32_t addr) {
6386 if (access_state_ == MonitorAccess::Exclusive) {
6394void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr,
6395 TransactionSize size) {
6396 access_state_ = MonitorAccess::Exclusive;
6397 tagged_addr_ = addr;
6401void Simulator::LocalMonitor::NotifyStore(int32_t addr) {
6402 if (access_state_ == MonitorAccess::Exclusive) {
6414bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr,
6415 TransactionSize size) {
6416 if (access_state_ == MonitorAccess::Exclusive) {
6419 if (addr == tagged_addr_ &&
size_ == size) {
6431 DCHECK(access_state_ == MonitorAccess::Open);
6436Simulator::GlobalMonitor::Processor::Processor()
6437 : access_state_(MonitorAccess::Open),
6441 failure_counter_(0) {}
6443void Simulator::GlobalMonitor::Processor::Clear_Locked() {
6444 access_state_ = MonitorAccess::Open;
6448void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
6449 access_state_ = MonitorAccess::Exclusive;
6450 tagged_addr_ = addr;
6453void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
6454 int32_t addr,
bool is_requesting_processor) {
6455 if (access_state_ == MonitorAccess::Exclusive) {
6472bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
6473 int32_t addr,
bool is_requesting_processor) {
6474 if (access_state_ == MonitorAccess::Exclusive) {
6475 if (is_requesting_processor) {
6478 if (addr == tagged_addr_) {
6487 if (failure_counter_++ >= kMaxFailureCounter) {
6488 failure_counter_ = 0;
6494 }
else if ((addr & kExclusiveTaggedAddrMask) ==
6495 (tagged_addr_ & kExclusiveTaggedAddrMask)) {
6506void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
6507 Processor* processor) {
6508 processor->NotifyLoadExcl_Locked(addr);
6511void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr,
6512 Processor* processor) {
6514 for (Processor* iter = head_; iter; iter = iter->next_) {
6515 bool is_requesting_processor = iter == processor;
6516 iter->NotifyStore_Locked(addr, is_requesting_processor);
6520bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr,
6521 Processor* processor) {
6522 if (processor->NotifyStoreExcl_Locked(addr,
true)) {
6524 for (Processor* iter = head_; iter; iter = iter->next_) {
6525 if (iter != processor) {
6526 iter->NotifyStoreExcl_Locked(addr,
false);
6535void Simulator::GlobalMonitor::PrependProcessor(Processor* processor) {
6536 base::MutexGuard lock_guard(&
mutex_);
6538 head_->prev_ = processor;
6540 processor->prev_ =
nullptr;
6541 processor->next_ = head_;
6546void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
6547 base::MutexGuard lock_guard(&
mutex_);
6548 if (processor->prev_) {
6549 processor->prev_->next_ = processor->next_;
6551 head_ = processor->next_;
6553 if (processor->next_) {
6554 processor->next_->prev_ = processor->prev_;
6556 processor->prev_ =
nullptr;
6557 processor->next_ =
nullptr;
6570 const char* command) {
6573 fprintf(stderr,
"No V8 Isolate found\n");
6576 i::Simulator* simulator = i::Simulator::current(isolate);
6578 fprintf(stderr,
"No Arm simulator found\n");
6582 size_t len = strlen(command);
6584 i::MemCopy(command_copy.get(), command, len + 1);
6585 return i::ArmDebugger(simulator).ExecDebugCommand(std::move(command_copy));
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
virtual void VisitPointer(const void *address)=0
TemplateHashMapEntry< void *, void * > Entry
constexpr T * begin() const
static int SupportedRegisterCount()
V8_EXPORT_PRIVATE void SetInstructionBits(Instr value, WritableJitAllocation *jit_allocation=nullptr)
static constexpr Register from_code(int code)
static int Number(const char *name)
static constexpr int ToInt(const Tagged< Object > object)
static const char * Name(int reg, bool is_double)
static int Number(const char *name, bool *is_double)
#define SIZE(Type, type, TYPE, ctype)
std::optional< TNode< JSArray > > a
RoundingMode rounding_mode
ZoneVector< RpoNumber > & result
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
InstructionOperand destination
V8_INLINE Dest bit_cast(Source const &source)
template unsigned leading_zeros
CustomMatcherTemplateHashMapImpl< DefaultAllocationPolicy > CustomMatcherHashMap
void Add(RWDigits Z, Digits X, Digits Y)
Zip(Iterables... iterables) -> Zip< Iterables... >
FloatWithBits< 32 > Float32
FloatWithBits< 64 > Float64
void Sub(LiftoffAssembler *lasm, Register dst, Register lhs, Register rhs)
constexpr MiscInstructionsBits74 CLZ
constexpr BlockAddrMode ia_x
Wide MultiplyLong(Narrow a, Narrow b)
std::make_unsigned< T >::type Abs(T a)
constexpr int kSimd128Size
constexpr int kBitsPerByte
constexpr int kPCRegister
constexpr NeonSize Neon32
constexpr BlockAddrMode db_x
void PrintF(const char *format,...)
char * ReadLine(const char *prompt)
constexpr NeonSize Neon64
constexpr NeonListType nlt_3
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
uint32_t SRegisterFieldMask
constexpr NeonListType nlt_2
constexpr MiscInstructionsBits74 BKPT
constexpr SoftwareInterruptCodes kBreakpoint
std::unique_ptr< T, ArrayDeleter< T > > ArrayUniquePtr
constexpr VFPRoundingMode RM
void Print(Tagged< Object > obj)
constexpr NeonSize Neon16
constexpr VFPRegPrecision kDoublePrecision
constexpr SoftwareInterruptCodes kCallRtRedirected
constexpr BlockAddrMode da_x
void ShortPrint(Tagged< Object > obj, FILE *out)
constexpr int kNoRegister
constexpr VFPRoundingMode RZ
constexpr MiscInstructionsBits74 BLX
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr VFPRoundingMode RN
constexpr uint8_t kInstrSize
const uint32_t kVFPRoundingModeMask
constexpr NeonListType nlt_1
constexpr int kDoubleSize
constexpr MiscInstructionsBits74 BX
constexpr NeonListType nlt_4
void MemCopy(void *dest, const void *src, size_t size)
constexpr VFPRegPrecision kSinglePrecision
int FastD2IChecked(double x)
T * NewArray(size_t size)
constexpr BlockAddrMode ib_x
bool is_signed(Condition cond)
V8_WARN_UNUSED_RESULT bool IsValidHeapObject(Heap *heap, Tagged< HeapObject > object)
constexpr uint32_t kStopCodeMask
constexpr int kNumRegisters
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
base::SmallVector< RegisterT, kStaticCapacity > registers_
#define V8_DEBUGGING_EXPORT
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
std::unique_ptr< ValueMirror > value