11 #include "src/arm/constants-arm.h" 12 #include "src/arm/simulator-arm.h" 13 #include "src/assembler-inl.h" 14 #include "src/base/bits.h" 15 #include "src/codegen.h" 16 #include "src/disasm.h" 17 #include "src/macro-assembler.h" 18 #include "src/objects-inl.h" 19 #include "src/runtime/runtime-utils.h" 21 #if defined(USE_SIMULATOR) 28 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
29 LAZY_INSTANCE_INITIALIZER;
35 #define SScanF sscanf // NOLINT 41 explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
43 void Stop(Instruction* instr);
47 static const Instr kBreakpointInstr =
48 (al | (7*B25) | (1*B24) | kBreakpoint);
49 static const Instr kNopInstr = (al | (13*B21));
53 int32_t GetRegisterValue(
int regnum);
54 double GetRegisterPairDoubleValue(
int regnum);
55 double GetVFPDoubleRegisterValue(
int regnum);
56 bool GetValue(
const char* desc, int32_t* value);
57 bool GetVFPSingleValue(
const char* desc,
float* value);
58 bool GetVFPDoubleValue(
const char* desc,
double* value);
61 bool SetBreakpoint(Instruction* breakpc);
62 bool DeleteBreakpoint(Instruction* breakpc);
66 void UndoBreakpoints();
67 void RedoBreakpoints();
70 void ArmDebugger::Stop(Instruction* instr) {
72 uint32_t code = instr->SvcValue() & kStopCodeMask;
74 if (code != kMaxStopCode) {
75 PrintF(
"Simulator hit stop %u\n", code);
77 PrintF(
"Simulator hit\n");
82 int32_t ArmDebugger::GetRegisterValue(
int regnum) {
83 if (regnum == kPCRegister) {
84 return sim_->get_pc();
86 return sim_->get_register(regnum);
90 double ArmDebugger::GetRegisterPairDoubleValue(
int regnum) {
91 return sim_->get_double_from_register_pair(regnum);
95 double ArmDebugger::GetVFPDoubleRegisterValue(
int regnum) {
96 return sim_->get_double_from_d_register(regnum).get_scalar();
100 bool ArmDebugger::GetValue(
const char* desc, int32_t* value) {
101 int regnum = Registers::Number(desc);
102 if (regnum != kNoRegister) {
103 *value = GetRegisterValue(regnum);
106 if (strncmp(desc,
"0x", 2) == 0) {
107 return SScanF(desc + 2,
"%x", reinterpret_cast<uint32_t*>(value)) == 1;
109 return SScanF(desc,
"%u", reinterpret_cast<uint32_t*>(value)) == 1;
116 bool ArmDebugger::GetVFPSingleValue(
const char* desc,
float* value) {
118 int regnum = VFPRegisters::Number(desc, &is_double);
119 if (regnum != kNoRegister && !is_double) {
120 *value = sim_->get_float_from_s_register(regnum).get_scalar();
127 bool ArmDebugger::GetVFPDoubleValue(
const char* desc,
double* value) {
129 int regnum = VFPRegisters::Number(desc, &is_double);
130 if (regnum != kNoRegister && is_double) {
131 *value = sim_->get_double_from_d_register(regnum).get_scalar();
138 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
140 if (sim_->break_pc_ !=
nullptr) {
145 sim_->break_pc_ = breakpc;
146 sim_->break_instr_ = breakpc->InstructionBits();
153 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
154 if (sim_->break_pc_ !=
nullptr) {
155 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
158 sim_->break_pc_ =
nullptr;
159 sim_->break_instr_ = 0;
164 void ArmDebugger::UndoBreakpoints() {
165 if (sim_->break_pc_ !=
nullptr) {
166 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
171 void ArmDebugger::RedoBreakpoints() {
172 if (sim_->break_pc_ !=
nullptr) {
173 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
178 void ArmDebugger::Debug() {
179 intptr_t last_pc = -1;
182 #define COMMAND_SIZE 63 186 #define XSTR(a) STR(a) 188 char cmd[COMMAND_SIZE + 1];
189 char arg1[ARG_SIZE + 1];
190 char arg2[ARG_SIZE + 1];
191 char* argv[3] = { cmd, arg1, arg2 };
194 cmd[COMMAND_SIZE] = 0;
202 while (!done && !sim_->has_bad_pc()) {
203 if (last_pc != sim_->get_pc()) {
208 dasm.InstructionDecode(buffer,
209 reinterpret_cast<byte*>(sim_->get_pc()));
210 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.start());
211 last_pc = sim_->get_pc();
213 char* line = ReadLine(
"sim> ");
214 if (line ==
nullptr) {
217 char* last_input = sim_->last_debugger_input();
218 if (strcmp(line,
"\n") == 0 && last_input !=
nullptr) {
222 sim_->set_last_debugger_input(line);
226 int argc = SScanF(line,
227 "%" XSTR(COMMAND_SIZE)
"s " 228 "%" XSTR(ARG_SIZE)
"s " 229 "%" XSTR(ARG_SIZE)
"s",
231 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
232 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
233 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
235 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
238 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
239 if (argc == 2 || (argc == 3 && strcmp(arg2,
"fp") == 0)) {
243 if (strcmp(arg1,
"all") == 0) {
244 for (
int i = 0;
i < kNumRegisters;
i++) {
245 value = GetRegisterValue(
i);
246 PrintF(
"%3s: 0x%08x %10d", RegisterName(Register::from_code(
i)),
248 if ((argc == 3 && strcmp(arg2,
"fp") == 0) &&
251 dvalue = GetRegisterPairDoubleValue(
i);
252 PrintF(
" (%f)\n", dvalue);
257 for (
int i = 0;
i < DwVfpRegister::NumRegisters();
i++) {
258 dvalue = GetVFPDoubleRegisterValue(
i);
259 uint64_t as_words = bit_cast<uint64_t>(dvalue);
260 PrintF(
"%3s: %f 0x%08x %08x\n", VFPRegisters::Name(
i,
true),
261 dvalue, static_cast<uint32_t>(as_words >> 32),
262 static_cast<uint32_t>(as_words & 0xFFFFFFFF));
265 if (GetValue(arg1, &value)) {
266 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
267 }
else if (GetVFPSingleValue(arg1, &svalue)) {
269 PrintF(
"%s: %f 0x%08x\n", arg1, svalue, as_word);
270 }
else if (GetVFPDoubleValue(arg1, &dvalue)) {
271 uint64_t as_words = bit_cast<uint64_t>(dvalue);
272 PrintF(
"%s: %f 0x%08x %08x\n", arg1, dvalue,
273 static_cast<uint32_t>(as_words >> 32),
274 static_cast<uint32_t>(as_words & 0xFFFFFFFF));
276 PrintF(
"%s unrecognized\n", arg1);
280 PrintF(
"print <register>\n");
282 }
else if ((strcmp(cmd,
"po") == 0)
283 || (strcmp(cmd,
"printobject") == 0)) {
287 if (GetValue(arg1, &value)) {
288 Object* obj =
reinterpret_cast<Object*
>(value);
289 os << arg1 <<
": \n";
294 os << Brief(obj) <<
"\n";
297 os << arg1 <<
" unrecognized\n";
300 PrintF(
"printobject <value>\n");
302 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
303 int32_t* cur =
nullptr;
304 int32_t* end =
nullptr;
307 if (strcmp(cmd,
"stack") == 0) {
308 cur =
reinterpret_cast<int32_t*
>(sim_->get_register(Simulator::sp));
311 if (!GetValue(arg1, &value)) {
312 PrintF(
"%s unrecognized\n", arg1);
315 cur =
reinterpret_cast<int32_t*
>(value);
320 if (argc == next_arg) {
323 if (!GetValue(argv[next_arg], &words)) {
330 PrintF(
" 0x%08" V8PRIxPTR
": 0x%08x %10d",
331 reinterpret_cast<intptr_t>(cur), *cur, *cur);
332 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
334 Heap* current_heap = sim_->isolate_->heap();
335 if (((value & 1) == 0) || current_heap->Contains(obj)) {
337 if ((value & 1) == 0) {
338 PrintF(
"smi %d", value / 2);
347 }
else if (strcmp(cmd,
"disasm") == 0 || strcmp(cmd,
"di") == 0) {
353 byte* prev =
nullptr;
358 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
359 end = cur + (10 * kInstrSize);
360 }
else if (argc == 2) {
361 int regnum = Registers::Number(arg1);
362 if (regnum != kNoRegister || strncmp(arg1,
"0x", 2) == 0) {
365 if (GetValue(arg1, &value)) {
366 cur =
reinterpret_cast<byte*
>(value);
368 end = cur + (10 * kInstrSize);
373 if (GetValue(arg1, &value)) {
374 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
376 end = cur + (value * kInstrSize);
382 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
383 cur =
reinterpret_cast<byte*
>(value1);
384 end = cur + (value2 * kInstrSize);
390 cur += dasm.InstructionDecode(buffer, cur);
391 PrintF(
" 0x%08" V8PRIxPTR
" %s\n", reinterpret_cast<intptr_t>(prev),
394 }
else if (strcmp(cmd,
"gdb") == 0) {
395 PrintF(
"relinquishing control to gdb\n");
396 v8::base::OS::DebugBreak();
397 PrintF(
"regaining control from gdb\n");
398 }
else if (strcmp(cmd,
"break") == 0) {
401 if (GetValue(arg1, &value)) {
402 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
403 PrintF(
"setting breakpoint failed\n");
406 PrintF(
"%s unrecognized\n", arg1);
409 PrintF(
"break <address>\n");
411 }
else if (strcmp(cmd,
"del") == 0) {
412 if (!DeleteBreakpoint(
nullptr)) {
413 PrintF(
"deleting breakpoint failed\n");
415 }
else if (strcmp(cmd,
"flags") == 0) {
416 PrintF(
"N flag: %d; ", sim_->n_flag_);
417 PrintF(
"Z flag: %d; ", sim_->z_flag_);
418 PrintF(
"C flag: %d; ", sim_->c_flag_);
419 PrintF(
"V flag: %d\n", sim_->v_flag_);
420 PrintF(
"INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
421 PrintF(
"DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
422 PrintF(
"OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
423 PrintF(
"UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
424 PrintF(
"INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
425 }
else if (strcmp(cmd,
"stop") == 0) {
427 intptr_t stop_pc = sim_->get_pc() - kInstrSize;
428 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
429 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
431 if (sim_->isStopInstruction(stop_instr)) {
432 stop_instr->SetInstructionBits(kNopInstr);
434 PrintF(
"Not at debugger stop.\n");
436 }
else if (argc == 3) {
438 if (strcmp(arg1,
"info") == 0) {
439 if (strcmp(arg2,
"all") == 0) {
440 PrintF(
"Stop information:\n");
441 for (
uint32_t i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
442 sim_->PrintStopInfo(
i);
444 }
else if (GetValue(arg2, &value)) {
445 sim_->PrintStopInfo(value);
447 PrintF(
"Unrecognized argument.\n");
449 }
else if (strcmp(arg1,
"enable") == 0) {
451 if (strcmp(arg2,
"all") == 0) {
452 for (
uint32_t i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
455 }
else if (GetValue(arg2, &value)) {
456 sim_->EnableStop(value);
458 PrintF(
"Unrecognized argument.\n");
460 }
else if (strcmp(arg1,
"disable") == 0) {
462 if (strcmp(arg2,
"all") == 0) {
463 for (
uint32_t i = 0;
i < sim_->kNumOfWatchedStops;
i++) {
464 sim_->DisableStop(
i);
466 }
else if (GetValue(arg2, &value)) {
467 sim_->DisableStop(value);
469 PrintF(
"Unrecognized argument.\n");
473 PrintF(
"Wrong usage. Use help command for more information.\n");
475 }
else if ((strcmp(cmd,
"t") == 0) || strcmp(cmd,
"trace") == 0) {
476 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
477 PrintF(
"Trace of executed instructions is %s\n",
478 ::v8::internal::FLAG_trace_sim ?
"on" :
"off");
479 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
481 PrintF(
" continue execution (alias 'c')\n");
483 PrintF(
" step one instruction (alias 'si')\n");
484 PrintF(
"print <register>\n");
485 PrintF(
" print register content (alias 'p')\n");
486 PrintF(
" use register name 'all' to print all registers\n");
487 PrintF(
" add argument 'fp' to print register pair double values\n");
488 PrintF(
"printobject <register>\n");
489 PrintF(
" print an object from a register (alias 'po')\n");
491 PrintF(
" print flags\n");
492 PrintF(
"stack [<words>]\n");
493 PrintF(
" dump stack content, default dump 10 words)\n");
494 PrintF(
"mem <address> [<words>]\n");
495 PrintF(
" dump memory content, default dump 10 words)\n");
496 PrintF(
"disasm [<instructions>]\n");
497 PrintF(
"disasm [<address/register>]\n");
498 PrintF(
"disasm [[<address/register>] <instructions>]\n");
499 PrintF(
" disassemble code, default is 10 instructions\n");
500 PrintF(
" from pc (alias 'di')\n");
502 PrintF(
" enter gdb\n");
503 PrintF(
"break <address>\n");
504 PrintF(
" set a break point on the address\n");
506 PrintF(
" delete the breakpoint\n");
507 PrintF(
"trace (alias 't')\n");
508 PrintF(
" toogle the tracing of all executed statements\n");
509 PrintF(
"stop feature:\n");
510 PrintF(
" Description:\n");
511 PrintF(
" Stops are debug instructions inserted by\n");
512 PrintF(
" the Assembler::stop() function.\n");
513 PrintF(
" When hitting a stop, the Simulator will\n");
514 PrintF(
" stop and give control to the ArmDebugger.\n");
515 PrintF(
" The first %d stop codes are watched:\n",
516 Simulator::kNumOfWatchedStops);
517 PrintF(
" - They can be enabled / disabled: the Simulator\n");
518 PrintF(
" will / won't stop when hitting them.\n");
519 PrintF(
" - The Simulator keeps track of how many times they \n");
520 PrintF(
" are met. (See the info command.) Going over a\n");
521 PrintF(
" disabled stop still increases its counter. \n");
522 PrintF(
" Commands:\n");
523 PrintF(
" stop info all/<code> : print infos about number <code>\n");
524 PrintF(
" or all stop(s).\n");
525 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
526 PrintF(
" all or number <code> stop(s)\n");
527 PrintF(
" stop unstop\n");
528 PrintF(
" ignore the stop instruction at the current location\n");
529 PrintF(
" from now on\n");
531 PrintF(
"Unknown command: %s\n", cmd);
547 bool Simulator::ICacheMatch(
void* one,
void* two) {
548 DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
549 DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
554 static uint32_t ICacheHash(
void* key) {
559 static bool AllOnOnePage(
uintptr_t start,
int size) {
560 intptr_t start_page = (start & ~CachePage::kPageMask);
561 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
562 return start_page == end_page;
565 void Simulator::set_last_debugger_input(
char* input) {
566 DeleteArray(last_debugger_input_);
567 last_debugger_input_ = input;
570 void Simulator::SetRedirectInstruction(Instruction* instruction) {
571 instruction->SetInstructionBits(al | (0xF * B24) | kCallRtRedirected);
574 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
575 void* start_addr,
size_t size) {
576 intptr_t start =
reinterpret_cast<intptr_t
>(start_addr);
577 int intra_line = (start & CachePage::kLineMask);
580 size = ((size - 1) | CachePage::kLineMask) + 1;
581 int offset = (start & CachePage::kPageMask);
582 while (!AllOnOnePage(start, size - 1)) {
583 int bytes_to_flush = CachePage::kPageSize - offset;
584 FlushOnePage(i_cache, start, bytes_to_flush);
585 start += bytes_to_flush;
586 size -= bytes_to_flush;
587 DCHECK_EQ(0, start & CachePage::kPageMask);
591 FlushOnePage(i_cache, start, size);
595 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
597 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
598 if (entry->value ==
nullptr) {
599 CachePage* new_page =
new CachePage();
600 entry->value = new_page;
602 return reinterpret_cast<CachePage*
>(entry->value);
607 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
608 intptr_t start,
int size) {
609 DCHECK_LE(size, CachePage::kPageSize);
610 DCHECK(AllOnOnePage(start, size - 1));
611 DCHECK_EQ(start & CachePage::kLineMask, 0);
612 DCHECK_EQ(size & CachePage::kLineMask, 0);
613 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
614 int offset = (start & CachePage::kPageMask);
615 CachePage* cache_page = GetCachePage(i_cache, page);
616 char* valid_bytemap = cache_page->ValidityByte(offset);
617 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
620 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
621 Instruction* instr) {
622 intptr_t address =
reinterpret_cast<intptr_t
>(instr);
623 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
624 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
625 int offset = (address & CachePage::kPageMask);
626 CachePage* cache_page = GetCachePage(i_cache, page);
627 char* cache_valid_byte = cache_page->ValidityByte(offset);
628 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
629 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
632 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
633 cache_page->CachedData(offset), kInstrSize));
636 memcpy(cached_line, line, CachePage::kLineLength);
637 *cache_valid_byte = CachePage::LINE_VALID;
642 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
645 size_t stack_size = 1 * 1024*1024;
646 stack_ =
reinterpret_cast<char*
>(malloc(stack_size));
647 pc_modified_ =
false;
654 for (
int i = 0;
i < num_registers;
i++) {
666 for (
int i = 0;
i < num_d_registers * 2;
i++) {
667 vfp_registers_[
i] = 0;
669 n_flag_FPSCR_ =
false;
670 z_flag_FPSCR_ =
false;
671 c_flag_FPSCR_ =
false;
672 v_flag_FPSCR_ =
false;
673 FPSCR_rounding_mode_ = RN;
674 FPSCR_default_NaN_mode_ =
false;
676 inv_op_vfp_flag_ =
false;
677 div_zero_vfp_flag_ =
false;
678 overflow_vfp_flag_ =
false;
679 underflow_vfp_flag_ =
false;
680 inexact_vfp_flag_ =
false;
685 registers_[sp] =
reinterpret_cast<int32_t
>(stack_) + stack_size - 64;
688 registers_[pc] = bad_lr;
689 registers_[lr] = bad_lr;
691 last_debugger_input_ =
nullptr;
694 Simulator::~Simulator() {
695 global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
701 Simulator* Simulator::current(Isolate* isolate) {
703 isolate->FindOrAllocatePerThreadDataForThisThread();
704 DCHECK_NOT_NULL(isolate_data);
706 Simulator* sim = isolate_data->simulator();
707 if (sim ==
nullptr) {
709 sim =
new Simulator(isolate);
710 isolate_data->set_simulator(sim);
718 void Simulator::set_register(
int reg, int32_t value) {
719 DCHECK((reg >= 0) && (reg < num_registers));
723 registers_[reg] = value;
729 int32_t Simulator::get_register(
int reg)
const {
730 DCHECK((reg >= 0) && (reg < num_registers));
733 if (reg >= num_registers)
return 0;
735 return registers_[reg] + ((reg == pc) ? Instruction::kPcLoadDelta : 0);
739 double Simulator::get_double_from_register_pair(
int reg) {
740 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
745 char buffer[2 *
sizeof(vfp_registers_[0])];
746 memcpy(buffer, ®isters_[reg], 2 *
sizeof(registers_[0]));
747 memcpy(&dm_val, buffer, 2 *
sizeof(registers_[0]));
752 void Simulator::set_register_pair_from_double(
int reg,
double* value) {
753 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
754 memcpy(registers_ + reg, value,
sizeof(*value));
758 void Simulator::set_dw_register(
int dreg,
const int* dbl) {
759 DCHECK((dreg >= 0) && (dreg < num_d_registers));
760 registers_[dreg] = dbl[0];
761 registers_[dreg + 1] = dbl[1];
765 void Simulator::get_d_register(
int dreg, uint64_t* value) {
766 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
767 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value));
771 void Simulator::set_d_register(
int dreg,
const uint64_t* value) {
772 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
773 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value));
777 void Simulator::get_d_register(
int dreg,
uint32_t* value) {
778 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
779 memcpy(value, vfp_registers_ + dreg * 2,
sizeof(*value) * 2);
783 void Simulator::set_d_register(
int dreg,
const uint32_t* value) {
784 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
785 memcpy(vfp_registers_ + dreg * 2, value,
sizeof(*value) * 2);
788 template <
typename T,
int SIZE>
789 void Simulator::get_neon_register(
int reg, T (&value)[SIZE /
sizeof(T)]) {
790 DCHECK(SIZE == kSimd128Size || SIZE == kDoubleSize);
792 DCHECK_GT(SIZE == kSimd128Size ? num_q_registers : num_d_registers, reg);
793 memcpy(value, vfp_registers_ + reg * (SIZE / 4), SIZE);
796 template <
typename T,
int SIZE>
797 void Simulator::set_neon_register(
int reg,
const T (&value)[SIZE /
sizeof(T)]) {
798 DCHECK(SIZE == kSimd128Size || SIZE == kDoubleSize);
800 DCHECK_GT(SIZE == kSimd128Size ? num_q_registers : num_d_registers, reg);
801 memcpy(vfp_registers_ + reg * (SIZE / 4), value, SIZE);
805 void Simulator::set_pc(int32_t value) {
807 registers_[pc] = value;
811 bool Simulator::has_bad_pc()
const {
812 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
817 int32_t Simulator::get_pc()
const {
818 return registers_[pc];
823 void Simulator::set_s_register(
int sreg,
unsigned int value) {
824 DCHECK((sreg >= 0) && (sreg < num_s_registers));
825 vfp_registers_[sreg] = value;
829 unsigned int Simulator::get_s_register(
int sreg)
const {
830 DCHECK((sreg >= 0) && (sreg < num_s_registers));
831 return vfp_registers_[sreg];
835 template<
class InputType,
int register_size>
836 void Simulator::SetVFPRegister(
int reg_index,
const InputType& value) {
837 unsigned bytes = register_size *
sizeof(vfp_registers_[0]);
838 DCHECK_EQ(
sizeof(InputType), bytes);
839 DCHECK_GE(reg_index, 0);
840 if (register_size == 1) DCHECK(reg_index < num_s_registers);
841 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
843 memcpy(&vfp_registers_[reg_index * register_size], &value, bytes);
847 template<
class ReturnType,
int register_size>
848 ReturnType Simulator::GetFromVFPRegister(
int reg_index) {
849 unsigned bytes = register_size *
sizeof(vfp_registers_[0]);
850 DCHECK_EQ(
sizeof(ReturnType), bytes);
851 DCHECK_GE(reg_index, 0);
852 if (register_size == 1) DCHECK(reg_index < num_s_registers);
853 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
856 memcpy(&value, &vfp_registers_[register_size * reg_index], bytes);
860 void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask,
863 if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) {
864 n_flag_ = ((value & (1 << 31)) != 0);
865 z_flag_ = ((value & (1 << 30)) != 0);
866 c_flag_ = ((value & (1 << 29)) != 0);
867 v_flag_ = ((value & (1 << 28)) != 0);
873 uint32_t Simulator::GetFromSpecialRegister(SRegister reg) {
877 if (n_flag_) result |= (1 << 31);
878 if (z_flag_) result |= (1 << 30);
879 if (c_flag_) result |= (1 << 29);
880 if (v_flag_) result |= (1 << 28);
891 void Simulator::GetFpArgs(
double* x,
double* y, int32_t* z) {
892 if (use_eabi_hardfloat()) {
893 *x = get_double_from_d_register(0).get_scalar();
894 *y = get_double_from_d_register(1).get_scalar();
895 *z = get_register(0);
898 *x = get_double_from_register_pair(0);
900 *y = get_double_from_register_pair(2);
902 *z = get_register(2);
908 void Simulator::SetFpResult(
const double& result) {
909 if (use_eabi_hardfloat()) {
910 char buffer[2 *
sizeof(vfp_registers_[0])];
911 memcpy(buffer, &result,
sizeof(buffer));
913 memcpy(vfp_registers_, buffer,
sizeof(buffer));
915 char buffer[2 *
sizeof(registers_[0])];
916 memcpy(buffer, &result,
sizeof(buffer));
918 memcpy(registers_, buffer,
sizeof(buffer));
923 void Simulator::TrashCallerSaveRegisters() {
925 registers_[2] = 0x50BAD4U;
926 registers_[3] = 0x50BAD4U;
927 registers_[12] = 0x50BAD4U;
930 int Simulator::ReadW(int32_t addr) {
933 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
934 local_monitor_.NotifyLoad(addr);
935 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
939 int Simulator::ReadExW(int32_t addr) {
940 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
941 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
942 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
943 &global_monitor_processor_);
944 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
948 void Simulator::WriteW(int32_t addr,
int value) {
951 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
952 local_monitor_.NotifyStore(addr);
953 global_monitor_.Pointer()->NotifyStore_Locked(addr,
954 &global_monitor_processor_);
955 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
959 int Simulator::WriteExW(int32_t addr,
int value) {
960 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
961 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
962 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
963 addr, &global_monitor_processor_)) {
964 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
972 uint16_t Simulator::ReadHU(int32_t addr) {
975 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
976 local_monitor_.NotifyLoad(addr);
977 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
981 int16_t Simulator::ReadH(int32_t addr) {
984 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
985 local_monitor_.NotifyLoad(addr);
986 int16_t* ptr =
reinterpret_cast<int16_t*
>(addr);
990 uint16_t Simulator::ReadExHU(int32_t addr) {
991 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
992 local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord);
993 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
994 &global_monitor_processor_);
995 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
999 void Simulator::WriteH(int32_t addr, uint16_t value) {
1002 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1003 local_monitor_.NotifyStore(addr);
1004 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1005 &global_monitor_processor_);
1006 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
1010 void Simulator::WriteH(int32_t addr, int16_t value) {
1013 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1014 local_monitor_.NotifyStore(addr);
1015 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1016 &global_monitor_processor_);
1017 int16_t* ptr =
reinterpret_cast<int16_t*
>(addr);
1021 int Simulator::WriteExH(int32_t addr, uint16_t value) {
1022 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1023 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) &&
1024 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1025 addr, &global_monitor_processor_)) {
1026 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
1034 uint8_t Simulator::ReadBU(int32_t addr) {
1035 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1036 local_monitor_.NotifyLoad(addr);
1037 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1041 int8_t Simulator::ReadB(int32_t addr) {
1042 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1043 local_monitor_.NotifyLoad(addr);
1044 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1048 uint8_t Simulator::ReadExBU(int32_t addr) {
1049 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1050 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte);
1051 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1052 &global_monitor_processor_);
1053 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1057 void Simulator::WriteB(int32_t addr, uint8_t value) {
1058 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1059 local_monitor_.NotifyStore(addr);
1060 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1061 &global_monitor_processor_);
1062 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1066 void Simulator::WriteB(int32_t addr, int8_t value) {
1067 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1068 local_monitor_.NotifyStore(addr);
1069 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1070 &global_monitor_processor_);
1071 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
1075 int Simulator::WriteExB(int32_t addr, uint8_t value) {
1076 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1077 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) &&
1078 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1079 addr, &global_monitor_processor_)) {
1080 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
1088 int32_t* Simulator::ReadDW(int32_t addr) {
1091 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1092 local_monitor_.NotifyLoad(addr);
1093 int32_t* ptr =
reinterpret_cast<int32_t*
>(addr);
1097 int32_t* Simulator::ReadExDW(int32_t addr) {
1098 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1099 local_monitor_.NotifyLoadExcl(addr, TransactionSize::DoubleWord);
1100 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1101 &global_monitor_processor_);
1102 int32_t* ptr =
reinterpret_cast<int32_t*
>(addr);
1106 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1109 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1110 local_monitor_.NotifyStore(addr);
1111 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1112 &global_monitor_processor_);
1113 int32_t* ptr =
reinterpret_cast<int32_t*
>(addr);
1118 int Simulator::WriteExDW(int32_t addr, int32_t value1, int32_t value2) {
1119 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1120 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::DoubleWord) &&
1121 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1122 addr, &global_monitor_processor_)) {
1123 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1136 if (GetCurrentStackPosition() < c_limit) {
1137 return reinterpret_cast<uintptr_t>(get_sp());
1142 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1147 void Simulator::Format(Instruction* instr,
const char* format) {
1148 PrintF(
"Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR
": %s\n",
1149 reinterpret_cast<intptr_t>(instr), format);
1156 bool Simulator::ConditionallyExecute(Instruction* instr) {
1157 switch (instr->ConditionField()) {
1158 case eq:
return z_flag_;
1159 case ne:
return !z_flag_;
1160 case cs:
return c_flag_;
1161 case cc:
return !c_flag_;
1162 case mi:
return n_flag_;
1163 case pl:
return !n_flag_;
1164 case vs:
return v_flag_;
1165 case vc:
return !v_flag_;
1166 case hi:
return c_flag_ && !z_flag_;
1167 case ls:
return !c_flag_ || z_flag_;
1168 case ge:
return n_flag_ == v_flag_;
1169 case lt:
return n_flag_ != v_flag_;
1170 case gt:
return !z_flag_ && (n_flag_ == v_flag_);
1171 case le:
return z_flag_ || (n_flag_ != v_flag_);
1172 case al:
return true;
1173 default: UNREACHABLE();
1180 void Simulator::SetNZFlags(int32_t val) {
1181 n_flag_ = (val < 0);
1182 z_flag_ = (val == 0);
1187 void Simulator::SetCFlag(
bool val) {
1193 void Simulator::SetVFlag(
bool val) {
1199 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1202 uint32_t urest = 0xFFFFFFFFU - uleft;
1204 return (uright > urest) ||
1205 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1210 bool Simulator::BorrowFrom(int32_t left, int32_t right, int32_t carry) {
1214 return (uright > uleft) ||
1215 (!carry && (((uright + 1) > uleft) || (uright > (uleft - 1))));
1220 bool Simulator::OverflowFrom(int32_t alu_out,
1221 int32_t left, int32_t right,
bool addition) {
1225 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1227 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1230 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1232 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1239 void Simulator::Compute_FPSCR_Flags(
float val1,
float val2) {
1240 if (std::isnan(val1) || std::isnan(val2)) {
1241 n_flag_FPSCR_ =
false;
1242 z_flag_FPSCR_ =
false;
1243 c_flag_FPSCR_ =
true;
1244 v_flag_FPSCR_ =
true;
1246 }
else if (val1 == val2) {
1247 n_flag_FPSCR_ =
false;
1248 z_flag_FPSCR_ =
true;
1249 c_flag_FPSCR_ =
true;
1250 v_flag_FPSCR_ =
false;
1251 }
else if (val1 < val2) {
1252 n_flag_FPSCR_ =
true;
1253 z_flag_FPSCR_ =
false;
1254 c_flag_FPSCR_ =
false;
1255 v_flag_FPSCR_ =
false;
1258 n_flag_FPSCR_ =
false;
1259 z_flag_FPSCR_ =
false;
1260 c_flag_FPSCR_ =
true;
1261 v_flag_FPSCR_ =
false;
1266 void Simulator::Compute_FPSCR_Flags(
double val1,
double val2) {
1267 if (std::isnan(val1) || std::isnan(val2)) {
1268 n_flag_FPSCR_ =
false;
1269 z_flag_FPSCR_ =
false;
1270 c_flag_FPSCR_ =
true;
1271 v_flag_FPSCR_ =
true;
1273 }
else if (val1 == val2) {
1274 n_flag_FPSCR_ =
false;
1275 z_flag_FPSCR_ =
true;
1276 c_flag_FPSCR_ =
true;
1277 v_flag_FPSCR_ =
false;
1278 }
else if (val1 < val2) {
1279 n_flag_FPSCR_ =
true;
1280 z_flag_FPSCR_ =
false;
1281 c_flag_FPSCR_ =
false;
1282 v_flag_FPSCR_ =
false;
1285 n_flag_FPSCR_ =
false;
1286 z_flag_FPSCR_ =
false;
1287 c_flag_FPSCR_ =
true;
1288 v_flag_FPSCR_ =
false;
1293 void Simulator::Copy_FPSCR_to_APSR() {
1294 n_flag_ = n_flag_FPSCR_;
1295 z_flag_ = z_flag_FPSCR_;
1296 c_flag_ = c_flag_FPSCR_;
1297 v_flag_ = v_flag_FPSCR_;
1303 int32_t Simulator::GetShiftRm(Instruction* instr,
bool* carry_out) {
1304 ShiftOp shift = instr->ShiftField();
1305 int shift_amount = instr->ShiftAmountValue();
1306 int32_t result = get_register(instr->RmValue());
1307 if (instr->Bit(4) == 0) {
1309 if ((shift == ROR) && (shift_amount == 0)) {
1312 }
else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1317 if (shift_amount == 0) {
1319 result = 0xFFFFFFFF;
1326 result >>= (shift_amount - 1);
1327 *carry_out = (result & 1) == 1;
1334 if (shift_amount == 0) {
1335 *carry_out = c_flag_;
1337 result <<= (shift_amount - 1);
1338 *carry_out = (result < 0);
1345 if (shift_amount == 0) {
1347 *carry_out = c_flag_;
1350 uresult >>= (shift_amount - 1);
1351 *carry_out = (uresult & 1) == 1;
1353 result =
static_cast<int32_t
>(uresult);
1359 if (shift_amount == 0) {
1360 *carry_out = c_flag_;
1364 result = right | left;
1365 *carry_out = (
static_cast<uint32_t>(result) >> 31) != 0;
1377 int rs = instr->RsValue();
1378 shift_amount = get_register(rs) & 0xFF;
1381 if (shift_amount == 0) {
1382 *carry_out = c_flag_;
1383 }
else if (shift_amount < 32) {
1384 result >>= (shift_amount - 1);
1385 *carry_out = (result & 1) == 1;
1388 DCHECK_GE(shift_amount, 32);
1391 result = 0xFFFFFFFF;
1401 if (shift_amount == 0) {
1402 *carry_out = c_flag_;
1403 }
else if (shift_amount < 32) {
1404 result <<= (shift_amount - 1);
1405 *carry_out = (result < 0);
1407 }
else if (shift_amount == 32) {
1408 *carry_out = (result & 1) == 1;
1411 DCHECK_GT(shift_amount, 32);
1419 if (shift_amount == 0) {
1420 *carry_out = c_flag_;
1421 }
else if (shift_amount < 32) {
1423 uresult >>= (shift_amount - 1);
1424 *carry_out = (uresult & 1) == 1;
1426 result =
static_cast<int32_t
>(uresult);
1427 }
else if (shift_amount == 32) {
1428 *carry_out = (result < 0);
1438 if (shift_amount == 0) {
1439 *carry_out = c_flag_;
1443 result = right | left;
1444 *carry_out = (
static_cast<uint32_t>(result) >> 31) != 0;
1461 int32_t Simulator::GetImm(Instruction* instr,
bool* carry_out) {
1462 int rotate = instr->RotateValue() * 2;
1463 int immed8 = instr->Immed8Value();
1464 int imm = base::bits::RotateRight32(immed8, rotate);
1465 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1470 static int count_bits(
int bit_vector) {
1472 while (bit_vector != 0) {
1473 if ((bit_vector & 1) != 0) {
1482 int32_t Simulator::ProcessPU(Instruction* instr,
1485 intptr_t* start_address,
1486 intptr_t* end_address) {
1487 int rn = instr->RnValue();
1488 int32_t rn_val = get_register(rn);
1489 switch (instr->PUField()) {
1495 *start_address = rn_val;
1496 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1497 rn_val = rn_val + (num_regs * reg_size);
1501 *start_address = rn_val - (num_regs * reg_size);
1502 *end_address = rn_val - reg_size;
1503 rn_val = *start_address;
1507 *start_address = rn_val + reg_size;
1508 *end_address = rn_val + (num_regs * reg_size);
1509 rn_val = *end_address;
1522 void Simulator::HandleRList(Instruction* instr,
bool load) {
1523 int rlist = instr->RlistValue();
1524 int num_regs = count_bits(rlist);
1526 intptr_t start_address = 0;
1527 intptr_t end_address = 0;
1529 ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1531 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1533 DCHECK(start_address > 8191 || start_address < 0);
1535 while (rlist != 0) {
1536 if ((rlist & 1) != 0) {
1538 set_register(reg, *address);
1540 *address = get_register(reg);
1547 DCHECK(end_address == ((intptr_t)address) - 4);
1548 if (instr->HasW()) {
1549 set_register(instr->RnValue(), rn_val);
1555 void Simulator::HandleVList(Instruction* instr) {
1556 VFPRegPrecision precision =
1557 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1558 int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1560 bool load = (instr->VLValue() == 0x1);
1564 vd = instr->VFPDRegValue(precision);
1565 if (precision == kSinglePrecision) {
1566 num_regs = instr->Immed8Value();
1568 num_regs = instr->Immed8Value() / 2;
1571 intptr_t start_address = 0;
1572 intptr_t end_address = 0;
1574 ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1576 intptr_t* address =
reinterpret_cast<intptr_t*
>(start_address);
1577 for (
int reg = vd; reg < vd + num_regs; reg++) {
1578 if (precision == kSinglePrecision) {
1580 set_s_register_from_sinteger(reg,
1581 ReadW(reinterpret_cast<int32_t>(address)));
1583 WriteW(reinterpret_cast<int32_t>(address),
1584 get_sinteger_from_s_register(reg));
1589 int32_t data[] = {ReadW(reinterpret_cast<int32_t>(address)),
1590 ReadW(reinterpret_cast<int32_t>(address + 1))};
1591 set_d_register(reg, reinterpret_cast<uint32_t*>(data));
1594 get_d_register(reg, data);
1595 WriteW(reinterpret_cast<int32_t>(address), data[0]);
1596 WriteW(reinterpret_cast<int32_t>(address + 1), data[1]);
1601 DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1602 if (instr->HasW()) {
1603 set_register(instr->RnValue(), rn_val);
1614 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, int32_t arg1,
1615 int32_t arg2, int32_t arg3,
1616 int32_t arg4, int32_t arg5,
1617 int32_t arg6, int32_t arg7,
1621 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
1622 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
1623 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
1624 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0, int32_t arg0);
1628 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1629 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0,
void* arg1);
1632 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1633 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1634 int32_t arg0, int32_t arg1,
void* arg2);
1638 void Simulator::SoftwareInterrupt(Instruction* instr) {
1639 int svc = instr->SvcValue();
1641 case kCallRtRedirected: {
1644 bool stack_aligned =
1646 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1647 Redirection* redirection = Redirection::FromInstruction(instr);
1648 int32_t arg0 = get_register(r0);
1649 int32_t arg1 = get_register(r1);
1650 int32_t arg2 = get_register(r2);
1651 int32_t arg3 = get_register(r3);
1652 int32_t* stack_pointer =
reinterpret_cast<int32_t*
>(get_register(sp));
1653 int32_t arg4 = stack_pointer[0];
1654 int32_t arg5 = stack_pointer[1];
1655 int32_t arg6 = stack_pointer[2];
1656 int32_t arg7 = stack_pointer[3];
1657 int32_t arg8 = stack_pointer[4];
1658 STATIC_ASSERT(kMaxCParameters == 9);
1661 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1662 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1663 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1664 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1667 int32_t saved_lr = get_register(lr);
1669 reinterpret_cast<intptr_t
>(redirection->external_function());
1671 double dval0, dval1;
1675 GetFpArgs(&dval0, &dval1, &ival);
1676 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1677 SimulatorRuntimeCall generic_target =
1678 reinterpret_cast<SimulatorRuntimeCall
>(external);
1679 switch (redirection->type()) {
1680 case ExternalReference::BUILTIN_FP_FP_CALL:
1681 case ExternalReference::BUILTIN_COMPARE_CALL:
1682 PrintF(
"Call to host function at %p with args %f, %f",
1683 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1686 case ExternalReference::BUILTIN_FP_CALL:
1687 PrintF(
"Call to host function at %p with arg %f",
1688 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1691 case ExternalReference::BUILTIN_FP_INT_CALL:
1692 PrintF(
"Call to host function at %p with args %f, %d",
1693 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
1700 if (!stack_aligned) {
1701 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1705 CHECK(stack_aligned);
1706 switch (redirection->type()) {
1707 case ExternalReference::BUILTIN_COMPARE_CALL: {
1708 SimulatorRuntimeCompareCall target =
1709 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
1710 iresult = target(dval0, dval1);
1711 set_register(r0, static_cast<int32_t>(iresult));
1712 set_register(r1, static_cast<int32_t>(iresult >> 32));
1715 case ExternalReference::BUILTIN_FP_FP_CALL: {
1716 SimulatorRuntimeFPFPCall target =
1717 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
1718 dresult = target(dval0, dval1);
1719 SetFpResult(dresult);
1722 case ExternalReference::BUILTIN_FP_CALL: {
1723 SimulatorRuntimeFPCall target =
1724 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
1725 dresult = target(dval0);
1726 SetFpResult(dresult);
1729 case ExternalReference::BUILTIN_FP_INT_CALL: {
1730 SimulatorRuntimeFPIntCall target =
1731 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
1732 dresult = target(dval0, ival);
1733 SetFpResult(dresult);
1740 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1741 switch (redirection->type()) {
1742 case ExternalReference::BUILTIN_COMPARE_CALL:
1743 PrintF(
"Returned %08x\n", static_cast<int32_t>(iresult));
1745 case ExternalReference::BUILTIN_FP_FP_CALL:
1746 case ExternalReference::BUILTIN_FP_CALL:
1747 case ExternalReference::BUILTIN_FP_INT_CALL:
1748 PrintF(
"Returned %f\n", dresult);
1755 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1756 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1757 PrintF(
"Call to host function at %p args %08x",
1758 reinterpret_cast<void*>(external), arg0);
1759 if (!stack_aligned) {
1760 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1764 CHECK(stack_aligned);
1765 SimulatorRuntimeDirectApiCall target =
1766 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
1769 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1770 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1771 PrintF(
"Call to host function at %p args %08x %08x",
1772 reinterpret_cast<void*>(external), arg0, arg1);
1773 if (!stack_aligned) {
1774 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1778 CHECK(stack_aligned);
1779 SimulatorRuntimeProfilingApiCall target =
1780 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
1781 target(arg0, Redirection::ReverseRedirection(arg1));
1783 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1784 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1785 PrintF(
"Call to host function at %p args %08x %08x",
1786 reinterpret_cast<void*>(external), arg0, arg1);
1787 if (!stack_aligned) {
1788 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1792 CHECK(stack_aligned);
1793 SimulatorRuntimeDirectGetterCall target =
1794 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
1797 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1798 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1799 PrintF(
"Call to host function at %p args %08x %08x %08x",
1800 reinterpret_cast<void*>(external), arg0, arg1, arg2);
1801 if (!stack_aligned) {
1802 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1806 CHECK(stack_aligned);
1807 SimulatorRuntimeProfilingGetterCall target =
1808 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(
1810 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1813 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
1814 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
1815 SimulatorRuntimeCall target =
1816 reinterpret_cast<SimulatorRuntimeCall
>(external);
1817 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1819 "Call to host function at %p " 1820 "args %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x",
1821 reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2,
1822 arg3, arg4, arg5, arg6, arg7, arg8);
1823 if (!stack_aligned) {
1824 PrintF(
" with unaligned stack %08x\n", get_register(sp));
1828 CHECK(stack_aligned);
1830 target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
1831 int32_t lo_res =
static_cast<int32_t
>(result);
1832 int32_t hi_res =
static_cast<int32_t
>(result >> 32);
1833 if (::v8::internal::FLAG_trace_sim) {
1834 PrintF(
"Returned %08x\n", lo_res);
1836 set_register(r0, lo_res);
1837 set_register(r1, hi_res);
1839 set_register(lr, saved_lr);
1840 set_pc(get_register(lr));
1844 ArmDebugger dbg(
this);
1850 if (svc >= (1 << 23)) {
1851 uint32_t code = svc & kStopCodeMask;
1852 if (isWatchedStop(code)) {
1853 IncreaseStopCounter(code);
1857 if (isEnabledStop(code)) {
1858 ArmDebugger dbg(
this);
1871 float Simulator::canonicalizeNaN(
float value) {
1874 constexpr
uint32_t kDefaultNaN = 0x7FC00000u;
1875 if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1876 value = bit_cast<
float>(kDefaultNaN);
1881 Float32 Simulator::canonicalizeNaN(Float32 value) {
1884 constexpr Float32 kDefaultNaN = Float32::FromBits(0x7FC00000u);
1885 return FPSCR_default_NaN_mode_ && value.is_nan() ? kDefaultNaN : value;
1888 double Simulator::canonicalizeNaN(
double value) {
1891 constexpr uint64_t kDefaultNaN = uint64_t{0x7FF8000000000000};
1892 if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1893 value = bit_cast<
double>(kDefaultNaN);
1898 Float64 Simulator::canonicalizeNaN(Float64 value) {
1901 constexpr Float64 kDefaultNaN =
1902 Float64::FromBits(uint64_t{0x7FF8000000000000});
1903 return FPSCR_default_NaN_mode_ && value.is_nan() ? kDefaultNaN : value;
1907 bool Simulator::isStopInstruction(Instruction* instr) {
1908 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1912 bool Simulator::isWatchedStop(
uint32_t code) {
1913 DCHECK_LE(code, kMaxStopCode);
1914 return code < kNumOfWatchedStops;
1918 bool Simulator::isEnabledStop(
uint32_t code) {
1919 DCHECK_LE(code, kMaxStopCode);
1921 return !isWatchedStop(code) ||
1922 !(watched_stops_[code].count & kStopDisabledBit);
1926 void Simulator::EnableStop(
uint32_t code) {
1927 DCHECK(isWatchedStop(code));
1928 if (!isEnabledStop(code)) {
1929 watched_stops_[code].count &= ~kStopDisabledBit;
1934 void Simulator::DisableStop(
uint32_t code) {
1935 DCHECK(isWatchedStop(code));
1936 if (isEnabledStop(code)) {
1937 watched_stops_[code].count |= kStopDisabledBit;
1942 void Simulator::IncreaseStopCounter(
uint32_t code) {
1943 DCHECK_LE(code, kMaxStopCode);
1944 DCHECK(isWatchedStop(code));
1945 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
1946 PrintF(
"Stop counter for code %i has overflowed.\n" 1947 "Enabling this code and reseting the counter to 0.\n", code);
1948 watched_stops_[code].count = 0;
1951 watched_stops_[code].count++;
1957 void Simulator::PrintStopInfo(
uint32_t code) {
1958 DCHECK_LE(code, kMaxStopCode);
1959 if (!isWatchedStop(code)) {
1960 PrintF(
"Stop not watched.");
1962 const char* state = isEnabledStop(code) ?
"Enabled" :
"Disabled";
1963 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1966 if (watched_stops_[code].desc) {
1967 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1968 code, code, state, count, watched_stops_[code].desc);
1970 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
1971 code, code, state, count);
1982 void Simulator::DecodeType01(Instruction* instr) {
1983 int type = instr->TypeValue();
1984 if ((type == 0) && instr->IsSpecialType0()) {
1986 if (instr->Bits(7, 4) == 9) {
1987 if (instr->Bit(24) == 0) {
1990 int rn = instr->RnValue();
1991 int rm = instr->RmValue();
1992 int rs = instr->RsValue();
1993 int32_t rs_val = get_register(rs);
1994 int32_t rm_val = get_register(rm);
1995 if (instr->Bit(23) == 0) {
1996 if (instr->Bit(21) == 0) {
2002 int32_t alu_out = rm_val * rs_val;
2003 set_register(rd, alu_out);
2004 if (instr->HasS()) {
2005 SetNZFlags(alu_out);
2008 int rd = instr->RdValue();
2009 int32_t acc_value = get_register(rd);
2010 if (instr->Bit(22) == 0) {
2016 int32_t mul_out = rm_val * rs_val;
2017 int32_t result = acc_value + mul_out;
2018 set_register(rn, result);
2021 int32_t mul_out = rm_val * rs_val;
2022 int32_t result = acc_value - mul_out;
2023 set_register(rn, result);
2038 int rd_lo = instr->RdValue();
2041 if (instr->Bit(22) == 1) {
2042 int64_t left_op =
static_cast<int32_t
>(rm_val);
2043 int64_t right_op =
static_cast<int32_t
>(rs_val);
2044 uint64_t result = left_op * right_op;
2045 hi_res =
static_cast<int32_t
>(result >> 32);
2046 lo_res =
static_cast<int32_t
>(result & 0xFFFFFFFF);
2049 uint64_t left_op =
static_cast<uint32_t>(rm_val);
2050 uint64_t right_op =
static_cast<uint32_t>(rs_val);
2051 uint64_t result = left_op * right_op;
2052 hi_res =
static_cast<int32_t
>(result >> 32);
2053 lo_res =
static_cast<int32_t
>(result & 0xFFFFFFFF);
2055 set_register(rd_lo, lo_res);
2056 set_register(rd_hi, hi_res);
2057 if (instr->HasS()) {
2062 if (instr->Bits(24, 23) == 3) {
2063 if (instr->Bit(20) == 1) {
2065 int rt = instr->RtValue();
2066 int rn = instr->RnValue();
2067 int32_t addr = get_register(rn);
2068 switch (instr->Bits(22, 21)) {
2071 int value = ReadExW(addr);
2072 set_register(rt, value);
2077 int* rn_data = ReadExDW(addr);
2078 set_dw_register(rt, rn_data);
2083 uint8_t value = ReadExBU(addr);
2084 set_register(rt, value);
2089 uint16_t value = ReadExHU(addr);
2090 set_register(rt, value);
2100 int rd = instr->RdValue();
2101 int rt = instr->RmValue();
2102 int rn = instr->RnValue();
2105 int32_t addr = get_register(rn);
2106 switch (instr->Bits(22, 21)) {
2109 int value = get_register(rt);
2110 int status = WriteExW(addr, value);
2111 set_register(rd, status);
2116 DCHECK_EQ(rt % 2, 0);
2117 int32_t value1 = get_register(rt);
2118 int32_t value2 = get_register(rt + 1);
2119 int status = WriteExDW(addr, value1, value2);
2120 set_register(rd, status);
2125 uint8_t value = get_register(rt);
2126 int status = WriteExB(addr, value);
2127 set_register(rd, status);
2132 uint16_t value = get_register(rt);
2133 int status = WriteExH(addr, value);
2134 set_register(rd, status);
2148 int rd = instr->RdValue();
2149 int rn = instr->RnValue();
2150 int32_t rn_val = get_register(rn);
2152 if (instr->Bit(22) == 0) {
2153 int rm = instr->RmValue();
2154 int32_t rm_val = get_register(rm);
2155 switch (instr->PUField()) {
2158 DCHECK(!instr->HasW());
2161 set_register(rn, rn_val);
2166 DCHECK(!instr->HasW());
2169 set_register(rn, rn_val);
2176 if (instr->HasW()) {
2177 set_register(rn, rn_val);
2185 if (instr->HasW()) {
2186 set_register(rn, rn_val);
2197 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2198 switch (instr->PUField()) {
2201 DCHECK(!instr->HasW());
2204 set_register(rn, rn_val);
2209 DCHECK(!instr->HasW());
2212 set_register(rn, rn_val);
2219 if (instr->HasW()) {
2220 set_register(rn, rn_val);
2228 if (instr->HasW()) {
2229 set_register(rn, rn_val);
2240 if (((instr->Bits(7, 4) & 0xD) == 0xD) && (instr->Bit(20) == 0)) {
2241 DCHECK_EQ(rd % 2, 0);
2242 if (instr->HasH()) {
2244 int32_t value1 = get_register(rd);
2245 int32_t value2 = get_register(rd+1);
2246 WriteDW(addr, value1, value2);
2249 int* rn_data = ReadDW(addr);
2250 set_dw_register(rd, rn_data);
2252 }
else if (instr->HasH()) {
2253 if (instr->HasSign()) {
2254 if (instr->HasL()) {
2255 int16_t val = ReadH(addr);
2256 set_register(rd, val);
2258 int16_t val = get_register(rd);
2262 if (instr->HasL()) {
2263 uint16_t val = ReadHU(addr);
2264 set_register(rd, val);
2266 uint16_t val = get_register(rd);
2272 DCHECK(instr->HasSign());
2273 DCHECK(instr->HasL());
2274 int8_t val = ReadB(addr);
2275 set_register(rd, val);
2279 }
else if ((type == 0) && instr->IsMiscType0()) {
2280 if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
2281 (instr->Bits(15, 4) == 0xF00)) {
2283 int rm = instr->RmValue();
2285 SRegisterFieldMask sreg_and_mask =
2286 instr->BitField(22, 22) | instr->BitField(19, 16);
2287 SetSpecialRegister(sreg_and_mask, get_register(rm));
2288 }
else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
2289 (instr->Bits(11, 0) == 0)) {
2291 int rd = instr->RdValue();
2293 SRegister sreg =
static_cast<SRegister
>(instr->BitField(22, 22));
2294 set_register(rd, GetFromSpecialRegister(sreg));
2295 }
else if (instr->Bits(22, 21) == 1) {
2296 int rm = instr->RmValue();
2297 switch (instr->BitField(7, 4)) {
2299 set_pc(get_register(rm));
2303 set_pc(get_register(rm));
2304 set_register(lr, old_pc + kInstrSize);
2308 ArmDebugger dbg(
this);
2309 PrintF(
"Simulator hit BKPT.\n");
2316 }
else if (instr->Bits(22, 21) == 3) {
2317 int rm = instr->RmValue();
2318 int rd = instr->RdValue();
2319 switch (instr->BitField(7, 4)) {
2322 int leading_zeros = 0;
2326 while ((bits & 0x80000000u) == 0) {
2331 set_register(rd, leading_zeros);
2338 PrintF(
"%08x\n", instr->InstructionBits());
2341 }
else if ((type == 1) && instr->IsNopLikeType1()) {
2342 if (instr->BitField(7, 0) == 0) {
2344 }
else if (instr->BitField(7, 0) == 20) {
2347 PrintF(
"%08x\n", instr->InstructionBits());
2351 int rd = instr->RdValue();
2352 int rn = instr->RnValue();
2353 int32_t rn_val = get_register(rn);
2354 int32_t shifter_operand = 0;
2355 bool shifter_carry_out = 0;
2357 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2359 DCHECK_EQ(instr->TypeValue(), 1);
2360 shifter_operand = GetImm(instr, &shifter_carry_out);
2364 switch (instr->OpcodeField()) {
2368 alu_out = rn_val & shifter_operand;
2369 set_register(rd, alu_out);
2370 if (instr->HasS()) {
2371 SetNZFlags(alu_out);
2372 SetCFlag(shifter_carry_out);
2380 alu_out = rn_val ^ shifter_operand;
2381 set_register(rd, alu_out);
2382 if (instr->HasS()) {
2383 SetNZFlags(alu_out);
2384 SetCFlag(shifter_carry_out);
2392 alu_out = rn_val - shifter_operand;
2393 set_register(rd, alu_out);
2394 if (instr->HasS()) {
2395 SetNZFlags(alu_out);
2396 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2397 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2405 alu_out = shifter_operand - rn_val;
2406 set_register(rd, alu_out);
2407 if (instr->HasS()) {
2408 SetNZFlags(alu_out);
2409 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2410 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val,
false));
2418 alu_out = rn_val + shifter_operand;
2419 set_register(rd, alu_out);
2420 if (instr->HasS()) {
2421 SetNZFlags(alu_out);
2422 SetCFlag(CarryFrom(rn_val, shifter_operand));
2423 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2431 alu_out = rn_val + shifter_operand + GetCarry();
2432 set_register(rd, alu_out);
2433 if (instr->HasS()) {
2434 SetNZFlags(alu_out);
2435 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2436 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2444 alu_out = (rn_val - shifter_operand) - (GetCarry() ? 0 : 1);
2445 set_register(rd, alu_out);
2446 if (instr->HasS()) {
2447 SetNZFlags(alu_out);
2448 SetCFlag(!BorrowFrom(rn_val, shifter_operand, GetCarry()));
2449 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2455 Format(instr,
"rsc'cond's 'rd, 'rn, 'shift_rm");
2456 Format(instr,
"rsc'cond's 'rd, 'rn, 'imm");
2461 if (instr->HasS()) {
2464 alu_out = rn_val & shifter_operand;
2465 SetNZFlags(alu_out);
2466 SetCFlag(shifter_carry_out);
2469 alu_out = instr->ImmedMovwMovtValue();
2470 set_register(rd, alu_out);
2476 if (instr->HasS()) {
2479 alu_out = rn_val ^ shifter_operand;
2480 SetNZFlags(alu_out);
2481 SetCFlag(shifter_carry_out);
2491 if (instr->HasS()) {
2494 alu_out = rn_val - shifter_operand;
2495 SetNZFlags(alu_out);
2496 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2497 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
false));
2501 (get_register(rd) & 0xFFFF) | (instr->ImmedMovwMovtValue() << 16);
2502 set_register(rd, alu_out);
2508 if (instr->HasS()) {
2511 alu_out = rn_val + shifter_operand;
2512 SetNZFlags(alu_out);
2513 SetCFlag(CarryFrom(rn_val, shifter_operand));
2514 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand,
true));
2526 alu_out = rn_val | shifter_operand;
2527 set_register(rd, alu_out);
2528 if (instr->HasS()) {
2529 SetNZFlags(alu_out);
2530 SetCFlag(shifter_carry_out);
2538 alu_out = shifter_operand;
2539 set_register(rd, alu_out);
2540 if (instr->HasS()) {
2541 SetNZFlags(alu_out);
2542 SetCFlag(shifter_carry_out);
2550 alu_out = rn_val & ~shifter_operand;
2551 set_register(rd, alu_out);
2552 if (instr->HasS()) {
2553 SetNZFlags(alu_out);
2554 SetCFlag(shifter_carry_out);
2562 alu_out = ~shifter_operand;
2563 set_register(rd, alu_out);
2564 if (instr->HasS()) {
2565 SetNZFlags(alu_out);
2566 SetCFlag(shifter_carry_out);
2580 void Simulator::DecodeType2(Instruction* instr) {
2581 int rd = instr->RdValue();
2582 int rn = instr->RnValue();
2583 int32_t rn_val = get_register(rn);
2584 int32_t im_val = instr->Offset12Value();
2586 switch (instr->PUField()) {
2589 DCHECK(!instr->HasW());
2592 set_register(rn, rn_val);
2597 DCHECK(!instr->HasW());
2600 set_register(rn, rn_val);
2607 if (instr->HasW()) {
2608 set_register(rn, rn_val);
2616 if (instr->HasW()) {
2617 set_register(rn, rn_val);
2626 if (instr->HasB()) {
2627 if (instr->HasL()) {
2628 byte val = ReadBU(addr);
2629 set_register(rd, val);
2631 byte val = get_register(rd);
2635 if (instr->HasL()) {
2636 set_register(rd, ReadW(addr));
2638 WriteW(addr, get_register(rd));
2644 void Simulator::DecodeType3(Instruction* instr) {
2645 int rd = instr->RdValue();
2646 int rn = instr->RnValue();
2647 int32_t rn_val = get_register(rn);
2648 bool shifter_carry_out = 0;
2649 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2651 switch (instr->PUField()) {
2653 DCHECK(!instr->HasW());
2654 Format(instr,
"'memop'cond'b 'rd, ['rn], -'shift_rm");
2659 if (instr->Bit(4) == 0) {
2662 if (instr->Bit(5) == 0) {
2663 switch (instr->Bits(22, 21)) {
2665 if (instr->Bit(20) == 0) {
2666 if (instr->Bit(6) == 0) {
2668 uint32_t rn_val = get_register(rn);
2669 uint32_t rm_val = get_register(instr->RmValue());
2670 int32_t shift = instr->Bits(11, 7);
2672 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2675 uint32_t rn_val = get_register(rn);
2676 int32_t rm_val = get_register(instr->RmValue());
2677 int32_t shift = instr->Bits(11, 7);
2682 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2696 int32_t sat_pos = instr->Bits(20, 16);
2697 int32_t sat_val = (1 << sat_pos) - 1;
2698 int32_t shift = instr->Bits(11, 7);
2699 int32_t shift_type = instr->Bit(6);
2700 int32_t rm_val = get_register(instr->RmValue());
2701 if (shift_type == 0) {
2709 if (rm_val > sat_val) {
2711 }
else if (rm_val < 0) {
2714 set_register(rd, rm_val);
2719 switch (instr->Bits(22, 21)) {
2724 if (instr->Bits(9, 6) == 1) {
2725 if (instr->Bit(20) == 0) {
2726 if (instr->Bits(19, 16) == 0xF) {
2728 int32_t rm_val = get_register(instr->RmValue());
2729 int32_t rotate = instr->Bits(11, 10);
2734 rm_val = (rm_val >> 8) | (rm_val << 24);
2737 rm_val = (rm_val >> 16) | (rm_val << 16);
2740 rm_val = (rm_val >> 24) | (rm_val << 8);
2743 set_register(rd, static_cast<int8_t>(rm_val));
2746 int32_t rn_val = get_register(rn);
2747 int32_t rm_val = get_register(instr->RmValue());
2748 int32_t rotate = instr->Bits(11, 10);
2753 rm_val = (rm_val >> 8) | (rm_val << 24);
2756 rm_val = (rm_val >> 16) | (rm_val << 16);
2759 rm_val = (rm_val >> 24) | (rm_val << 8);
2762 set_register(rd, rn_val + static_cast<int8_t>(rm_val));
2765 if (instr->Bits(19, 16) == 0xF) {
2767 int32_t rm_val = get_register(instr->RmValue());
2768 int32_t rotate = instr->Bits(11, 10);
2773 rm_val = (rm_val >> 8) | (rm_val << 24);
2776 rm_val = (rm_val >> 16) | (rm_val << 16);
2779 rm_val = (rm_val >> 24) | (rm_val << 8);
2782 set_register(rd, static_cast<int16_t>(rm_val));
2785 int32_t rn_val = get_register(rn);
2786 int32_t rm_val = get_register(instr->RmValue());
2787 int32_t rotate = instr->Bits(11, 10);
2792 rm_val = (rm_val >> 8) | (rm_val << 24);
2795 rm_val = (rm_val >> 16) | (rm_val << 16);
2798 rm_val = (rm_val >> 24) | (rm_val << 8);
2801 set_register(rd, rn_val + static_cast<int16_t>(rm_val));
2804 }
else if (instr->Bits(27, 16) == 0x6BF &&
2805 instr->Bits(11, 4) == 0xF3) {
2807 uint32_t rm_val = get_register(instr->RmValue());
2808 set_register(rd, ByteReverse(rm_val));
2814 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2815 if (instr->Bits(19, 16) == 0xF) {
2817 uint32_t rm_val = get_register(instr->RmValue());
2818 int32_t rotate = instr->Bits(11, 10);
2823 rm_val = (rm_val >> 8) | (rm_val << 24);
2826 rm_val = (rm_val >> 16) | (rm_val << 16);
2829 rm_val = (rm_val >> 24) | (rm_val << 8);
2832 set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
2841 if ((instr->Bits(9, 6) == 1)) {
2842 if (instr->Bit(20) == 0) {
2843 if (instr->Bits(19, 16) == 0xF) {
2845 uint32_t rm_val = get_register(instr->RmValue());
2846 int32_t rotate = instr->Bits(11, 10);
2851 rm_val = (rm_val >> 8) | (rm_val << 24);
2854 rm_val = (rm_val >> 16) | (rm_val << 16);
2857 rm_val = (rm_val >> 24) | (rm_val << 8);
2860 set_register(rd, (rm_val & 0xFF));
2863 uint32_t rn_val = get_register(rn);
2864 uint32_t rm_val = get_register(instr->RmValue());
2865 int32_t rotate = instr->Bits(11, 10);
2870 rm_val = (rm_val >> 8) | (rm_val << 24);
2873 rm_val = (rm_val >> 16) | (rm_val << 16);
2876 rm_val = (rm_val >> 24) | (rm_val << 8);
2879 set_register(rd, rn_val + (rm_val & 0xFF));
2882 if (instr->Bits(19, 16) == 0xF) {
2884 uint32_t rm_val = get_register(instr->RmValue());
2885 int32_t rotate = instr->Bits(11, 10);
2890 rm_val = (rm_val >> 8) | (rm_val << 24);
2893 rm_val = (rm_val >> 16) | (rm_val << 16);
2896 rm_val = (rm_val >> 24) | (rm_val << 8);
2899 set_register(rd, (rm_val & 0xFFFF));
2902 uint32_t rn_val = get_register(rn);
2903 uint32_t rm_val = get_register(instr->RmValue());
2904 int32_t rotate = instr->Bits(11, 10);
2909 rm_val = (rm_val >> 8) | (rm_val << 24);
2912 rm_val = (rm_val >> 16) | (rm_val << 16);
2915 rm_val = (rm_val >> 24) | (rm_val << 8);
2918 set_register(rd, rn_val + (rm_val & 0xFFFF));
2923 if ((instr->Bits(20, 16) == 0x1F) &&
2924 (instr->Bits(11, 4) == 0xF3)) {
2926 uint32_t rm_val = get_register(instr->RmValue());
2927 set_register(rd, base::bits::ReverseBits(rm_val));
2940 if (instr->Bits(22, 20) == 0x5) {
2941 if (instr->Bits(7, 4) == 0x1) {
2942 int rm = instr->RmValue();
2943 int32_t rm_val = get_register(rm);
2944 int rs = instr->RsValue();
2945 int32_t rs_val = get_register(rs);
2946 if (instr->Bits(15, 12) == 0xF) {
2949 rn_val = base::bits::SignedMulHigh32(rm_val, rs_val);
2953 int rd = instr->RdValue();
2954 int32_t rd_val = get_register(rd);
2955 rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val);
2957 set_register(rn, rn_val);
2961 if (instr->Bits(5, 4) == 0x1) {
2962 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2965 int rm = instr->RmValue();
2966 int32_t rm_val = get_register(rm);
2967 int rs = instr->RsValue();
2968 int32_t rs_val = get_register(rs);
2969 int32_t ret_val = 0;
2971 if (instr->Bit(21) == 0x1) {
2972 ret_val = bit_cast<int32_t>(base::bits::UnsignedDiv32(
2973 bit_cast<uint32_t>(rm_val), bit_cast<uint32_t>(rs_val)));
2975 ret_val = base::bits::SignedDiv32(rm_val, rs_val);
2977 set_register(rn, ret_val);
2982 addr = rn_val - shifter_operand;
2983 if (instr->HasW()) {
2984 set_register(rn, addr);
2989 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2992 uint32_t msbit = widthminus1 + lsbit;
2994 if (instr->Bit(22)) {
2997 static_cast<uint32_t>(get_register(instr->RmValue()));
2998 uint32_t extr_val = rm_val << (31 - msbit);
2999 extr_val = extr_val >> (31 - widthminus1);
3000 set_register(instr->RdValue(), extr_val);
3003 int32_t rm_val = get_register(instr->RmValue());
3004 int32_t extr_val = rm_val << (31 - msbit);
3005 extr_val = extr_val >> (31 - widthminus1);
3006 set_register(instr->RdValue(), extr_val);
3012 }
else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
3015 if (msbit >= lsbit) {
3018 static_cast<uint32_t>(get_register(instr->RdValue()));
3019 uint32_t bitcount = msbit - lsbit + 1;
3020 uint32_t mask = 0xFFFFFFFFu >> (32 - bitcount);
3021 rd_val &= ~(mask << lsbit);
3022 if (instr->RmValue() != 15) {
3025 static_cast<uint32_t>(get_register(instr->RmValue()));
3027 rd_val |= rm_val << lsbit;
3029 set_register(instr->RdValue(), rd_val);
3036 addr = rn_val + shifter_operand;
3037 if (instr->HasW()) {
3038 set_register(rn, addr);
3048 if (instr->HasB()) {
3049 if (instr->HasL()) {
3050 uint8_t byte = ReadB(addr);
3051 set_register(rd, byte);
3053 uint8_t byte = get_register(rd);
3057 if (instr->HasL()) {
3058 set_register(rd, ReadW(addr));
3060 WriteW(addr, get_register(rd));
3066 void Simulator::DecodeType4(Instruction* instr) {
3067 DCHECK_EQ(instr->Bit(22), 0);
3068 if (instr->HasL()) {
3070 HandleRList(instr,
true);
3073 HandleRList(instr,
false);
3078 void Simulator::DecodeType5(Instruction* instr) {
3080 int off = (instr->SImmed24Value() << 2);
3081 intptr_t pc_address = get_pc();
3082 if (instr->HasLink()) {
3083 set_register(lr, pc_address + kInstrSize);
3085 int pc_reg = get_register(pc);
3086 set_pc(pc_reg + off);
3090 void Simulator::DecodeType6(Instruction* instr) {
3091 DecodeType6CoprocessorIns(instr);
3095 void Simulator::DecodeType7(Instruction* instr) {
3096 if (instr->Bit(24) == 1) {
3097 SoftwareInterrupt(instr);
3099 switch (instr->CoprocessorValue()) {
3102 DecodeTypeVFP(instr);
3105 DecodeTypeCP15(instr);
3139 void Simulator::DecodeTypeVFP(Instruction* instr) {
3140 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
3141 DCHECK_EQ(instr->Bits(11, 9), 0x5);
3143 int m = instr->VFPMRegValue(kSinglePrecision);
3144 int d = instr->VFPDRegValue(kSinglePrecision);
3145 int n = instr->VFPNRegValue(kSinglePrecision);
3147 int vm = instr->VFPMRegValue(kDoublePrecision);
3148 int vd = instr->VFPDRegValue(kDoublePrecision);
3149 int vn = instr->VFPNRegValue(kDoublePrecision);
3151 if (instr->Bit(4) == 0) {
3152 if (instr->Opc1Value() == 0x7) {
3154 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
3156 if (instr->SzValue() == 0x1) {
3158 get_d_register(vm, data);
3159 set_d_register(vd, data);
3161 set_s_register(d, get_s_register(m));
3163 }
else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
3165 if (instr->SzValue() == 0x1) {
3166 Float64 dm = get_double_from_d_register(vm);
3167 constexpr uint64_t kSignBit64 = uint64_t{1} << 63;
3168 Float64 dd = Float64::FromBits(dm.get_bits() & ~kSignBit64);
3169 dd = canonicalizeNaN(dd);
3170 set_d_register_from_double(vd, dd);
3172 Float32 sm = get_float_from_s_register(m);
3174 Float32 sd = Float32::FromBits(sm.get_bits() & ~kSignBit32);
3175 sd = canonicalizeNaN(sd);
3176 set_s_register_from_float(d, sd);
3178 }
else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
3180 if (instr->SzValue() == 0x1) {
3181 Float64 dm = get_double_from_d_register(vm);
3182 constexpr uint64_t kSignBit64 = uint64_t{1} << 63;
3183 Float64 dd = Float64::FromBits(dm.get_bits() ^ kSignBit64);
3184 dd = canonicalizeNaN(dd);
3185 set_d_register_from_double(vd, dd);
3187 Float32 sm = get_float_from_s_register(m);
3189 Float32 sd = Float32::FromBits(sm.get_bits() ^ kSignBit32);
3190 sd = canonicalizeNaN(sd);
3191 set_s_register_from_float(d, sd);
3193 }
else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
3194 DecodeVCVTBetweenDoubleAndSingle(instr);
3195 }
else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
3196 DecodeVCVTBetweenFloatingPointAndInteger(instr);
3197 }
else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
3198 (instr->Bit(8) == 1)) {
3200 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
3201 int fixed_value = get_sinteger_from_s_register(vd * 2);
3202 double divide = 1 << fraction_bits;
3203 set_d_register_from_double(vd, fixed_value / divide);
3204 }
else if (((instr->Opc2Value() >> 1) == 0x6) &&
3205 (instr->Opc3Value() & 0x1)) {
3206 DecodeVCVTBetweenFloatingPointAndInteger(instr);
3207 }
else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3208 (instr->Opc3Value() & 0x1)) {
3210 }
else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
3212 lazily_initialize_fast_sqrt();
3213 if (instr->SzValue() == 0x1) {
3214 double dm_value = get_double_from_d_register(vm).get_scalar();
3215 double dd_value = fast_sqrt(dm_value);
3216 dd_value = canonicalizeNaN(dd_value);
3217 set_d_register_from_double(vd, dd_value);
3219 float sm_value = get_float_from_s_register(m).get_scalar();
3220 float sd_value = fast_sqrt(sm_value);
3221 sd_value = canonicalizeNaN(sd_value);
3222 set_s_register_from_float(d, sd_value);
3224 }
else if (instr->Opc3Value() == 0x0) {
3226 if (instr->SzValue() == 0x1) {
3227 set_d_register_from_double(vd, instr->DoubleImmedVmov());
3230 float value = instr->DoubleImmedVmov().get_scalar();
3231 set_s_register_from_float(d, value);
3233 }
else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) {
3235 if (instr->SzValue() == 0x1) {
3236 double dm_value = get_double_from_d_register(vm).get_scalar();
3237 double dd_value = trunc(dm_value);
3238 dd_value = canonicalizeNaN(dd_value);
3239 set_d_register_from_double(vd, dd_value);
3241 float sm_value = get_float_from_s_register(m).get_scalar();
3242 float sd_value = truncf(sm_value);
3243 sd_value = canonicalizeNaN(sd_value);
3244 set_s_register_from_float(d, sd_value);
3249 }
else if (instr->Opc1Value() == 0x3) {
3250 if (instr->Opc3Value() & 0x1) {
3252 if (instr->SzValue() == 0x1) {
3253 double dn_value = get_double_from_d_register(vn).get_scalar();
3254 double dm_value = get_double_from_d_register(vm).get_scalar();
3255 double dd_value = dn_value - dm_value;
3256 dd_value = canonicalizeNaN(dd_value);
3257 set_d_register_from_double(vd, dd_value);
3259 float sn_value = get_float_from_s_register(n).get_scalar();
3260 float sm_value = get_float_from_s_register(m).get_scalar();
3261 float sd_value = sn_value - sm_value;
3262 sd_value = canonicalizeNaN(sd_value);
3263 set_s_register_from_float(d, sd_value);
3267 if (instr->SzValue() == 0x1) {
3268 double dn_value = get_double_from_d_register(vn).get_scalar();
3269 double dm_value = get_double_from_d_register(vm).get_scalar();
3270 double dd_value = dn_value + dm_value;
3271 dd_value = canonicalizeNaN(dd_value);
3272 set_d_register_from_double(vd, dd_value);
3274 float sn_value = get_float_from_s_register(n).get_scalar();
3275 float sm_value = get_float_from_s_register(m).get_scalar();
3276 float sd_value = sn_value + sm_value;
3277 sd_value = canonicalizeNaN(sd_value);
3278 set_s_register_from_float(d, sd_value);
3281 }
else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
3283 if (instr->SzValue() == 0x1) {
3284 double dn_value = get_double_from_d_register(vn).get_scalar();
3285 double dm_value = get_double_from_d_register(vm).get_scalar();
3286 double dd_value = dn_value * dm_value;
3287 dd_value = canonicalizeNaN(dd_value);
3288 set_d_register_from_double(vd, dd_value);
3290 float sn_value = get_float_from_s_register(n).get_scalar();
3291 float sm_value = get_float_from_s_register(m).get_scalar();
3292 float sd_value = sn_value * sm_value;
3293 sd_value = canonicalizeNaN(sd_value);
3294 set_s_register_from_float(d, sd_value);
3296 }
else if ((instr->Opc1Value() == 0x0)) {
3298 const bool is_vmls = (instr->Opc3Value() & 0x1);
3299 if (instr->SzValue() == 0x1) {
3300 const double dd_val = get_double_from_d_register(vd).get_scalar();
3301 const double dn_val = get_double_from_d_register(vn).get_scalar();
3302 const double dm_val = get_double_from_d_register(vm).get_scalar();
3306 const double res = dn_val * dm_val;
3307 set_d_register_from_double(vd, res);
3309 set_d_register_from_double(vd, canonicalizeNaN(dd_val - res));
3311 set_d_register_from_double(vd, canonicalizeNaN(dd_val + res));
3314 const float sd_val = get_float_from_s_register(d).get_scalar();
3315 const float sn_val = get_float_from_s_register(n).get_scalar();
3316 const float sm_val = get_float_from_s_register(m).get_scalar();
3320 const float res = sn_val * sm_val;
3321 set_s_register_from_float(d, res);
3323 set_s_register_from_float(d, canonicalizeNaN(sd_val - res));
3325 set_s_register_from_float(d, canonicalizeNaN(sd_val + res));
3328 }
else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3330 if (instr->SzValue() == 0x1) {
3331 double dn_value = get_double_from_d_register(vn).get_scalar();
3332 double dm_value = get_double_from_d_register(vm).get_scalar();
3333 double dd_value = dn_value / dm_value;
3334 div_zero_vfp_flag_ = (dm_value == 0);
3335 dd_value = canonicalizeNaN(dd_value);
3336 set_d_register_from_double(vd, dd_value);
3338 float sn_value = get_float_from_s_register(n).get_scalar();
3339 float sm_value = get_float_from_s_register(m).get_scalar();
3340 float sd_value = sn_value / sm_value;
3341 div_zero_vfp_flag_ = (sm_value == 0);
3342 sd_value = canonicalizeNaN(sd_value);
3343 set_s_register_from_float(d, sd_value);
3349 if ((instr->VCValue() == 0x0) &&
3350 (instr->VAValue() == 0x0)) {
3351 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3352 }
else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
3353 if (instr->Bit(23) == 0) {
3355 int vd = instr->VFPNRegValue(kDoublePrecision);
3356 int rt = instr->RtValue();
3357 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
3358 if ((opc1_opc2 & 0xB) == 0) {
3361 get_d_register(vd, data);
3362 data[instr->Bit(21)] = get_register(rt);
3363 set_d_register(vd, data);
3366 get_d_register(vd, &data);
3367 uint64_t rt_value = get_register(rt);
3368 if ((opc1_opc2 & 0x8) != 0) {
3370 int i = opc1_opc2 & 0x7;
3371 int shift =
i * kBitsPerByte;
3372 const uint64_t mask = 0xFF;
3373 data &= ~(mask << shift);
3374 data |= (rt_value & mask) << shift;
3375 set_d_register(vd, &data);
3376 }
else if ((opc1_opc2 & 0x1) != 0) {
3378 int i = (opc1_opc2 >> 1) & 0x3;
3379 int shift =
i * kBitsPerByte * kShortSize;
3380 const uint64_t mask = 0xFFFF;
3381 data &= ~(mask << shift);
3382 data |= (rt_value & mask) << shift;
3383 set_d_register(vd, &data);
3390 NeonSize size = Neon32;
3391 if (instr->Bit(5) != 0)
3393 else if (instr->Bit(22) != 0)
3395 int vd = instr->VFPNRegValue(kSimd128Precision);
3396 int rt = instr->RtValue();
3397 uint32_t rt_value = get_register(rt);
3402 uint8_t* dst =
reinterpret_cast<uint8_t*
>(q_data);
3403 for (
int i = 0;
i < 16;
i++) {
3410 rt_value &= 0xFFFFu;
3411 uint32_t rt_rt = (rt_value << 16) | (rt_value & 0xFFFFu);
3412 for (
int i = 0;
i < 4;
i++) {
3418 for (
int i = 0;
i < 4;
i++) {
3419 q_data[
i] = rt_value;
3427 set_neon_register(vd, q_data);
3429 }
else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
3431 int vn = instr->VFPNRegValue(kDoublePrecision);
3432 int rt = instr->RtValue();
3433 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
3435 get_d_register(vn, &data);
3436 if ((opc1_opc2 & 0xB) == 0) {
3438 int32_t int_data[2];
3439 memcpy(int_data, &data,
sizeof(int_data));
3440 set_register(rt, int_data[instr->Bit(21)]);
3443 get_d_register(vn, &data);
3444 bool u = instr->Bit(23) != 0;
3445 if ((opc1_opc2 & 0x8) != 0) {
3447 int i = opc1_opc2 & 0x7;
3448 int shift =
i * kBitsPerByte;
3449 uint32_t scalar = (data >> shift) & 0xFFu;
3450 if (!u && (scalar & 0x80) != 0) scalar |= 0xFFFFFF00;
3451 set_register(rt, scalar);
3452 }
else if ((opc1_opc2 & 0x1) != 0) {
3454 int i = (opc1_opc2 >> 1) & 0x3;
3455 int shift =
i * kBitsPerByte * kShortSize;
3456 uint32_t scalar = (data >> shift) & 0xFFFFu;
3457 if (!u && (scalar & 0x8000) != 0) scalar |= 0xFFFF0000;
3458 set_register(rt, scalar);
3463 }
else if ((instr->VLValue() == 0x1) &&
3464 (instr->VCValue() == 0x0) &&
3465 (instr->VAValue() == 0x7) &&
3466 (instr->Bits(19, 16) == 0x1)) {
3470 Copy_FPSCR_to_APSR();
3473 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3474 (z_flag_FPSCR_ << 30) |
3475 (c_flag_FPSCR_ << 29) |
3476 (v_flag_FPSCR_ << 28) |
3477 (FPSCR_default_NaN_mode_ << 25) |
3478 (inexact_vfp_flag_ << 4) |
3479 (underflow_vfp_flag_ << 3) |
3480 (overflow_vfp_flag_ << 2) |
3481 (div_zero_vfp_flag_ << 1) |
3482 (inv_op_vfp_flag_ << 0) |
3483 (FPSCR_rounding_mode_);
3484 set_register(rt, fpscr);
3486 }
else if ((instr->VLValue() == 0x0) &&
3487 (instr->VCValue() == 0x0) &&
3488 (instr->VAValue() == 0x7) &&
3489 (instr->Bits(19, 16) == 0x1)) {
3495 uint32_t rt_value = get_register(rt);
3496 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3497 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3498 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3499 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3500 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3501 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3502 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3503 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3504 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3505 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3506 FPSCR_rounding_mode_ =
3507 static_cast<VFPRoundingMode
>((rt_value) & kVFPRoundingModeMask);
3515 void Simulator::DecodeTypeCP15(Instruction* instr) {
3516 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
3517 DCHECK_EQ(instr->CoprocessorValue(), 15);
3519 if (instr->Bit(4) == 1) {
3521 int crn = instr->Bits(19, 16);
3522 int crm = instr->Bits(3, 0);
3523 int opc1 = instr->Bits(23, 21);
3524 int opc2 = instr->Bits(7, 5);
3525 if ((opc1 == 0) && (crn == 7)) {
3528 if (((crm == 10) && (opc2 == 5)) ||
3529 ((crm == 10) && (opc2 == 4)) ||
3530 ((crm == 5) && (opc2 == 4))) {
3541 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3542 Instruction* instr) {
3543 DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3544 (instr->VAValue() == 0x0));
3546 int t = instr->RtValue();
3547 int n = instr->VFPNRegValue(kSinglePrecision);
3548 bool to_arm_register = (instr->VLValue() == 0x1);
3550 if (to_arm_register) {
3551 int32_t int_value = get_sinteger_from_s_register(n);
3552 set_register(t, int_value);
3554 int32_t rs_val = get_register(t);
3555 set_s_register_from_sinteger(n, rs_val);
3560 void Simulator::DecodeVCMP(Instruction* instr) {
3561 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3562 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3563 (instr->Opc3Value() & 0x1));
3566 VFPRegPrecision precision = kSinglePrecision;
3567 if (instr->SzValue() == 0x1) {
3568 precision = kDoublePrecision;
3571 int d = instr->VFPDRegValue(precision);
3573 if (instr->Opc2Value() == 0x4) {
3574 m = instr->VFPMRegValue(precision);
3577 if (precision == kDoublePrecision) {
3578 double dd_value = get_double_from_d_register(d).get_scalar();
3579 double dm_value = 0.0;
3580 if (instr->Opc2Value() == 0x4) {
3581 dm_value = get_double_from_d_register(m).get_scalar();
3585 if (instr->Bit(7) == 1) {
3586 if (std::isnan(dd_value)) {
3587 inv_op_vfp_flag_ =
true;
3591 Compute_FPSCR_Flags(dd_value, dm_value);
3593 float sd_value = get_float_from_s_register(d).get_scalar();
3594 float sm_value = 0.0;
3595 if (instr->Opc2Value() == 0x4) {
3596 sm_value = get_float_from_s_register(m).get_scalar();
3600 if (instr->Bit(7) == 1) {
3601 if (std::isnan(sd_value)) {
3602 inv_op_vfp_flag_ =
true;
3606 Compute_FPSCR_Flags(sd_value, sm_value);
3611 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3612 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3613 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3615 VFPRegPrecision dst_precision = kDoublePrecision;
3616 VFPRegPrecision src_precision = kSinglePrecision;
3617 if (instr->SzValue() == 1) {
3618 dst_precision = kSinglePrecision;
3619 src_precision = kDoublePrecision;
3622 int dst = instr->VFPDRegValue(dst_precision);
3623 int src = instr->VFPMRegValue(src_precision);
3625 if (dst_precision == kSinglePrecision) {
3626 double val = get_double_from_d_register(src).get_scalar();
3627 set_s_register_from_float(dst, static_cast<float>(val));
3629 float val = get_float_from_s_register(src).get_scalar();
3630 set_d_register_from_double(dst, static_cast<double>(val));
3634 bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3637 DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
3638 double max_uint =
static_cast<double>(0xFFFFFFFFu);
3639 double max_int =
static_cast<double>(kMaxInt);
3640 double min_int =
static_cast<double>(kMinInt);
3651 return unsigned_ ? (val >= (max_uint + 0.5)) ||
3653 : (val >= (max_int + 0.5)) ||
3654 (val < (min_int - 0.5));
3657 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3659 : (val >= (max_int + 1.0)) ||
3663 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3665 : (val >= (max_int + 1.0)) ||
3666 (val <= (min_int - 1.0));
3675 int VFPConversionSaturate(
double val,
bool unsigned_res) {
3680 return (val < 0) ? 0 : 0xFFFFFFFFu;
3682 return (val < 0) ? kMinInt : kMaxInt;
3687 int32_t Simulator::ConvertDoubleToInt(
double val,
bool unsigned_integer,
3688 VFPRoundingMode mode) {
3692 unsigned_integer ?
static_cast<uint32_t>(val) : static_cast<int32_t>(val);
3694 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3696 double abs_diff = unsigned_integer
3697 ? std::fabs(val - static_cast<uint32_t>(result))
3698 :
std::fabs(val - result);
3700 inexact_vfp_flag_ = (abs_diff != 0);
3702 if (inv_op_vfp_flag_) {
3703 result = VFPConversionSaturate(val, unsigned_integer);
3707 int val_sign = (val > 0) ? 1 : -1;
3708 if (abs_diff > 0.5) {
3710 }
else if (abs_diff == 0.5) {
3712 result = ((result % 2) == 0) ? result : result + val_sign;
3718 result = result > val ? result - 1 : result;
3732 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3733 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3734 (instr->Bits(27, 23) == 0x1D));
3735 DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3736 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3739 bool to_integer = (instr->Bit(18) == 1);
3741 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3752 int dst = instr->VFPDRegValue(kSinglePrecision);
3753 int src = instr->VFPMRegValue(src_precision);
3757 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3759 DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
3761 bool unsigned_integer = (instr->Bit(16) == 0);
3762 bool double_precision = (src_precision == kDoublePrecision);
3764 double val = double_precision ? get_double_from_d_register(src).get_scalar()
3765 : get_float_from_s_register(src).get_scalar();
3767 int32_t temp = ConvertDoubleToInt(val, unsigned_integer, mode);
3770 set_s_register_from_sinteger(dst, temp);
3773 bool unsigned_integer = (instr->Bit(7) == 0);
3775 int dst = instr->VFPDRegValue(src_precision);
3776 int src = instr->VFPMRegValue(kSinglePrecision);
3778 int val = get_sinteger_from_s_register(src);
3780 if (src_precision == kDoublePrecision) {
3781 if (unsigned_integer) {
3782 set_d_register_from_double(
3783 dst, static_cast<double>(static_cast<uint32_t>(val)));
3785 set_d_register_from_double(dst, static_cast<double>(val));
3788 if (unsigned_integer) {
3789 set_s_register_from_float(
3790 dst, static_cast<float>(static_cast<uint32_t>(val)));
3792 set_s_register_from_float(dst, static_cast<float>(val));
3805 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3806 DCHECK_EQ(instr->TypeValue(), 6);
3808 if (instr->CoprocessorValue() == 0xA) {
3809 switch (instr->OpcodeValue()) {
3814 int rn = instr->RnValue();
3815 int vd = instr->VFPDRegValue(kSinglePrecision);
3816 int offset = instr->Immed8Value();
3817 if (!instr->HasU()) {
3821 int32_t address = get_register(rn) + 4 * offset;
3824 DCHECK_EQ(address % 4, 0);
3825 if (instr->HasL()) {
3827 set_s_register_from_sinteger(vd, ReadW(address));
3830 WriteW(address, get_sinteger_from_s_register(vd));
3846 }
else if (instr->CoprocessorValue() == 0xB) {
3847 switch (instr->OpcodeValue()) {
3850 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3853 int rt = instr->RtValue();
3854 int rn = instr->RnValue();
3855 int vm = instr->VFPMRegValue(kDoublePrecision);
3856 if (instr->HasL()) {
3858 get_d_register(vm, data);
3859 set_register(rt, data[0]);
3860 set_register(rn, data[1]);
3862 int32_t data[] = { get_register(rt), get_register(rn) };
3863 set_d_register(vm, reinterpret_cast<uint32_t*>(data));
3871 int rn = instr->RnValue();
3872 int vd = instr->VFPDRegValue(kDoublePrecision);
3873 int offset = instr->Immed8Value();
3874 if (!instr->HasU()) {
3877 int32_t address = get_register(rn) + 4 * offset;
3880 DCHECK_EQ(address % 4, 0);
3881 if (instr->HasL()) {
3883 int32_t data[] = {ReadW(address), ReadW(address + 4)};
3884 set_d_register(vd, reinterpret_cast<uint32_t*>(data));
3888 get_d_register(vd, data);
3889 WriteW(address, data[0]);
3890 WriteW(address + 4, data[1]);
3912 template <
typename T,
typename U>
3914 static_assert(
sizeof(
int64_t) >
sizeof(T),
"T must be int32_t or smaller");
3915 static_assert(
sizeof(U) >
sizeof(T),
"T must smaller than U");
3916 return static_cast<U
>(value);
3919 template <
typename T,
typename U>
3921 static_assert(
sizeof(int8_t) <
sizeof(T),
"T must be int16_t or larger");
3922 static_assert(
sizeof(U) <
sizeof(T),
"T must larger than U");
3923 static_assert(std::is_unsigned<T>() == std::is_unsigned<U>(),
3924 "Signed-ness of T and U must match");
3927 DCHECK_LE(std::numeric_limits<T>::min(), value);
3928 DCHECK_GE(std::numeric_limits<T>::max(), value);
3929 return static_cast<U
>(value);
3932 template <
typename T>
3934 static_assert(
sizeof(
int64_t) >
sizeof(T),
"T must be int32_t or smaller");
3935 int64_t min =
static_cast<int64_t>(std::numeric_limits<T>::min());
3936 int64_t max =
static_cast<int64_t>(std::numeric_limits<T>::max());
3937 int64_t clamped = std::max(min, std::min(max, value));
3938 return static_cast<T
>(clamped);
3941 template <
typename T,
typename U>
3942 void Widen(Simulator* simulator,
int Vd,
int Vm) {
3943 static const int kLanes = 8 /
sizeof(T);
3946 simulator->get_neon_register<T, kDoubleSize>(Vm, src);
3947 for (
int i = 0;
i < kLanes;
i++) {
3948 dst[
i] = Widen<T, U>(src[
i]);
3950 simulator->set_neon_register(Vd, dst);
3953 template <
typename T,
int SIZE>
3954 void Abs(Simulator* simulator,
int Vd,
int Vm) {
3955 static const int kElems = SIZE /
sizeof(T);
3957 simulator->get_neon_register<T, SIZE>(Vm, src);
3958 for (
int i = 0;
i < kElems;
i++) {
3959 src[
i] = std::abs(src[
i]);
3961 simulator->set_neon_register<T, SIZE>(Vd, src);
3964 template <
typename T,
int SIZE>
3965 void Neg(Simulator* simulator,
int Vd,
int Vm) {
3966 static const int kElems = SIZE /
sizeof(T);
3968 simulator->get_neon_register<T, SIZE>(Vm, src);
3969 for (
int i = 0;
i < kElems;
i++) {
3972 simulator->set_neon_register<T, SIZE>(Vd, src);
3975 template <
typename T,
typename U>
3976 void SaturatingNarrow(Simulator* simulator,
int Vd,
int Vm) {
3977 static const int kLanes = 16 /
sizeof(T);
3980 simulator->get_neon_register(Vm, src);
3981 for (
int i = 0;
i < kLanes;
i++) {
3982 dst[
i] = Narrow<T, U>(Clamp<U>(src[
i]));
3984 simulator->set_neon_register<U, kDoubleSize>(Vd, dst);
3987 template <
typename T>
3988 void AddSaturate(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
3989 static const int kLanes = 16 /
sizeof(T);
3990 T src1[kLanes], src2[kLanes];
3991 simulator->get_neon_register(Vn, src1);
3992 simulator->get_neon_register(Vm, src2);
3993 for (
int i = 0;
i < kLanes;
i++) {
3994 src1[
i] = Clamp<T>(Widen<T, int64_t>(src1[
i]) + Widen<T, int64_t>(src2[
i]));
3996 simulator->set_neon_register(Vd, src1);
3999 template <
typename T>
4000 void SubSaturate(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4001 static const int kLanes = 16 /
sizeof(T);
4002 T src1[kLanes], src2[kLanes];
4003 simulator->get_neon_register(Vn, src1);
4004 simulator->get_neon_register(Vm, src2);
4005 for (
int i = 0;
i < kLanes;
i++) {
4006 src1[
i] = Clamp<T>(Widen<T, int64_t>(src1[
i]) - Widen<T, int64_t>(src2[
i]));
4008 simulator->set_neon_register(Vd, src1);
4011 template <
typename T,
int SIZE>
4012 void Zip(Simulator* simulator,
int Vd,
int Vm) {
4013 static const int kElems = SIZE /
sizeof(T);
4014 static const int kPairs = kElems / 2;
4015 T src1[kElems], src2[kElems], dst1[kElems], dst2[kElems];
4016 simulator->get_neon_register<T, SIZE>(Vd, src1);
4017 simulator->get_neon_register<T, SIZE>(Vm, src2);
4018 for (
int i = 0;
i < kPairs;
i++) {
4019 dst1[
i * 2] = src1[
i];
4020 dst1[
i * 2 + 1] = src2[
i];
4021 dst2[
i * 2] = src1[
i + kPairs];
4022 dst2[
i * 2 + 1] = src2[
i + kPairs];
4024 simulator->set_neon_register<T, SIZE>(Vd, dst1);
4025 simulator->set_neon_register<T, SIZE>(Vm, dst2);
4028 template <
typename T,
int SIZE>
4029 void Unzip(Simulator* simulator,
int Vd,
int Vm) {
4030 static const int kElems = SIZE /
sizeof(T);
4031 static const int kPairs = kElems / 2;
4032 T src1[kElems], src2[kElems], dst1[kElems], dst2[kElems];
4033 simulator->get_neon_register<T, SIZE>(Vd, src1);
4034 simulator->get_neon_register<T, SIZE>(Vm, src2);
4035 for (
int i = 0;
i < kPairs;
i++) {
4036 dst1[
i] = src1[
i * 2];
4037 dst1[
i + kPairs] = src2[
i * 2];
4038 dst2[
i] = src1[
i * 2 + 1];
4039 dst2[
i + kPairs] = src2[
i * 2 + 1];
4041 simulator->set_neon_register<T, SIZE>(Vd, dst1);
4042 simulator->set_neon_register<T, SIZE>(Vm, dst2);
4045 template <
typename T,
int SIZE>
4046 void Transpose(Simulator* simulator,
int Vd,
int Vm) {
4047 static const int kElems = SIZE /
sizeof(T);
4048 static const int kPairs = kElems / 2;
4049 T src1[kElems], src2[kElems];
4050 simulator->get_neon_register<T, SIZE>(Vd, src1);
4051 simulator->get_neon_register<T, SIZE>(Vm, src2);
4052 for (
int i = 0;
i < kPairs;
i++) {
4053 std::swap(src1[2 *
i + 1], src2[2 *
i]);
4055 simulator->set_neon_register<T, SIZE>(Vd, src1);
4056 simulator->set_neon_register<T, SIZE>(Vm, src2);
4059 template <
typename T,
int SIZE>
4060 void Test(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4061 static const int kElems = SIZE /
sizeof(T);
4062 T src1[kElems], src2[kElems];
4063 simulator->get_neon_register<T, SIZE>(Vn, src1);
4064 simulator->get_neon_register<T, SIZE>(Vm, src2);
4065 for (
int i = 0;
i < kElems;
i++) {
4066 src1[
i] = (src1[
i] & src2[
i]) != 0 ? -1 : 0;
4068 simulator->set_neon_register<T, SIZE>(Vd, src1);
4071 template <
typename T,
int SIZE>
4072 void Add(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4073 static const int kElems = SIZE /
sizeof(T);
4074 T src1[kElems], src2[kElems];
4075 simulator->get_neon_register<T, SIZE>(Vn, src1);
4076 simulator->get_neon_register<T, SIZE>(Vm, src2);
4077 for (
int i = 0;
i < kElems;
i++) {
4080 simulator->set_neon_register<T, SIZE>(Vd, src1);
4083 template <
typename T,
int SIZE>
4084 void Sub(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4085 static const int kElems = SIZE /
sizeof(T);
4086 T src1[kElems], src2[kElems];
4087 simulator->get_neon_register<T, SIZE>(Vn, src1);
4088 simulator->get_neon_register<T, SIZE>(Vm, src2);
4089 for (
int i = 0;
i < kElems;
i++) {
4092 simulator->set_neon_register<T, SIZE>(Vd, src1);
4095 template <
typename T,
int SIZE>
4096 void Mul(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4097 static const int kElems = SIZE /
sizeof(T);
4098 T src1[kElems], src2[kElems];
4099 simulator->get_neon_register<T, SIZE>(Vn, src1);
4100 simulator->get_neon_register<T, SIZE>(Vm, src2);
4101 for (
int i = 0;
i < kElems;
i++) {
4104 simulator->set_neon_register<T, SIZE>(Vd, src1);
4107 template <
typename T,
int SIZE>
4108 void ShiftLeft(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4109 static const int kElems = SIZE /
sizeof(T);
4111 simulator->get_neon_register<T, SIZE>(Vm, src);
4112 for (
int i = 0;
i < kElems;
i++) {
4115 simulator->set_neon_register<T, SIZE>(Vd, src);
4118 template <
typename T,
int SIZE>
4119 void ShiftRight(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4120 static const int kElems = SIZE /
sizeof(T);
4122 simulator->get_neon_register<T, SIZE>(Vm, src);
4123 for (
int i = 0;
i < kElems;
i++) {
4126 simulator->set_neon_register<T, SIZE>(Vd, src);
4129 template <
typename T,
int SIZE>
4130 void ArithmeticShiftRight(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4131 static const int kElems = SIZE /
sizeof(T);
4133 simulator->get_neon_register<T, SIZE>(Vm, src);
4134 for (
int i = 0;
i < kElems;
i++) {
4135 src[
i] = ArithmeticShiftRight(src[
i], shift);
4137 simulator->set_neon_register<T, SIZE>(Vd, src);
4140 template <
typename T,
int SIZE>
4141 void ShiftLeftAndInsert(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4142 static const int kElems = SIZE /
sizeof(T);
4145 simulator->get_neon_register<T, SIZE>(Vm, src);
4146 simulator->get_neon_register<T, SIZE>(Vd, dst);
4147 uint64_t mask = (1llu << shift) - 1llu;
4148 for (
int i = 0;
i < kElems;
i++) {
4149 dst[
i] = (src[
i] << shift) | (dst[
i] & mask);
4151 simulator->set_neon_register<T, SIZE>(Vd, dst);
4154 template <
typename T,
int SIZE>
4155 void ShiftRightAndInsert(Simulator* simulator,
int Vd,
int Vm,
int shift) {
4156 static const int kElems = SIZE /
sizeof(T);
4159 simulator->get_neon_register<T, SIZE>(Vm, src);
4160 simulator->get_neon_register<T, SIZE>(Vd, dst);
4161 uint64_t mask = ~((1llu << (kBitsPerByte * SIZE - shift)) - 1llu);
4162 for (
int i = 0;
i < kElems;
i++) {
4163 dst[
i] = (src[
i] >> shift) | (dst[
i] & mask);
4165 simulator->set_neon_register<T, SIZE>(Vd, dst);
4168 template <
typename T,
int SIZE>
4169 void CompareEqual(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4170 static const int kElems = SIZE /
sizeof(T);
4171 T src1[kElems], src2[kElems];
4172 simulator->get_neon_register<T, SIZE>(Vn, src1);
4173 simulator->get_neon_register<T, SIZE>(Vm, src2);
4174 for (
int i = 0;
i < kElems;
i++) {
4175 src1[
i] = src1[
i] == src2[
i] ? -1 : 0;
4177 simulator->set_neon_register<T, SIZE>(Vd, src1);
4180 template <
typename T,
int SIZE>
4181 void CompareGreater(Simulator* simulator,
int Vd,
int Vm,
int Vn,
bool ge) {
4182 static const int kElems = SIZE /
sizeof(T);
4183 T src1[kElems], src2[kElems];
4184 simulator->get_neon_register<T, SIZE>(Vn, src1);
4185 simulator->get_neon_register<T, SIZE>(Vm, src2);
4186 for (
int i = 0;
i < kElems;
i++) {
4188 src1[
i] = src1[
i] >= src2[
i] ? -1 : 0;
4190 src1[
i] = src1[
i] > src2[
i] ? -1 : 0;
4192 simulator->set_neon_register<T, SIZE>(Vd, src1);
4195 template <
typename T>
4196 T MinMax(T a, T b,
bool is_min) {
4197 return is_min ? std::min(a, b) :
std::max(a, b);
4200 template <
typename T,
int SIZE>
4201 void MinMax(Simulator* simulator,
int Vd,
int Vm,
int Vn,
bool min) {
4202 static const int kElems = SIZE /
sizeof(T);
4203 T src1[kElems], src2[kElems];
4204 simulator->get_neon_register<T, SIZE>(Vn, src1);
4205 simulator->get_neon_register<T, SIZE>(Vm, src2);
4206 for (
int i = 0;
i < kElems;
i++) {
4207 src1[
i] = MinMax(src1[
i], src2[
i], min);
4209 simulator->set_neon_register<T, SIZE>(Vd, src1);
4212 template <
typename T>
4213 void PairwiseMinMax(Simulator* simulator,
int Vd,
int Vm,
int Vn,
bool min) {
4214 static const int kElems = kDoubleSize /
sizeof(T);
4215 static const int kPairs = kElems / 2;
4216 T dst[kElems], src1[kElems], src2[kElems];
4217 simulator->get_neon_register<T, kDoubleSize>(Vn, src1);
4218 simulator->get_neon_register<T, kDoubleSize>(Vm, src2);
4219 for (
int i = 0;
i < kPairs;
i++) {
4220 dst[
i] = MinMax(src1[
i * 2], src1[
i * 2 + 1], min);
4221 dst[
i + kPairs] = MinMax(src2[
i * 2], src2[
i * 2 + 1], min);
4223 simulator->set_neon_register<T, kDoubleSize>(Vd, dst);
4226 template <
typename T>
4227 void PairwiseAdd(Simulator* simulator,
int Vd,
int Vm,
int Vn) {
4228 static const int kElems = kDoubleSize /
sizeof(T);
4229 static const int kPairs = kElems / 2;
4230 T dst[kElems], src1[kElems], src2[kElems];
4231 simulator->get_neon_register<T, kDoubleSize>(Vn, src1);
4232 simulator->get_neon_register<T, kDoubleSize>(Vm, src2);
4233 for (
int i = 0;
i < kPairs;
i++) {
4234 dst[
i] = src1[
i * 2] + src1[
i * 2 + 1];
4235 dst[
i + kPairs] = src2[
i * 2] + src2[
i * 2 + 1];
4237 simulator->set_neon_register<T, kDoubleSize>(Vd, dst);
4240 void Simulator::DecodeSpecialCondition(Instruction* instr) {
4241 switch (instr->SpecialValue()) {
4244 if (instr->Bit(6) == 0) {
4245 Vd = instr->VFPDRegValue(kDoublePrecision);
4246 Vm = instr->VFPMRegValue(kDoublePrecision);
4247 Vn = instr->VFPNRegValue(kDoublePrecision);
4249 Vd = instr->VFPDRegValue(kSimd128Precision);
4250 Vm = instr->VFPMRegValue(kSimd128Precision);
4251 Vn = instr->VFPNRegValue(kSimd128Precision);
4253 switch (instr->Bits(11, 8)) {
4255 if (instr->Bit(4) == 1) {
4257 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4260 AddSaturate<int8_t>(
this, Vd, Vm, Vn);
4263 AddSaturate<int16_t>(
this, Vd, Vm, Vn);
4266 AddSaturate<int32_t>(
this, Vd, Vm, Vn);
4278 if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
4279 instr->Bit(4) == 1) {
4283 get_neon_register(Vm, src1);
4286 get_neon_register(Vn, src2);
4287 for (
int i = 0;
i < 4;
i++) {
4288 src1[
i] = src1[
i] | src2[
i];
4291 set_neon_register(Vd, src1);
4292 }
else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
4293 instr->Bit(4) == 1) {
4296 get_neon_register(Vn, src1);
4297 get_neon_register(Vm, src2);
4298 for (
int i = 0;
i < 4;
i++) {
4299 src1[
i] = src1[
i] & src2[
i];
4301 set_neon_register(Vd, src1);
4308 if (instr->Bit(4) == 1) {
4310 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4313 SubSaturate<int8_t>(
this, Vd, Vm, Vn);
4316 SubSaturate<int16_t>(
this, Vd, Vm, Vn);
4319 SubSaturate<int32_t>(
this, Vd, Vm, Vn);
4332 bool ge = instr->Bit(4) == 1;
4333 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4336 CompareGreater<int8_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
4339 CompareGreater<int16_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
4342 CompareGreater<int32_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
4352 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4353 bool min = instr->Bit(4) != 0;
4356 MinMax<int8_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
4359 MinMax<int16_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
4362 MinMax<int32_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
4372 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4373 if (instr->Bit(4) == 0) {
4377 Add<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
4380 Add<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
4383 Add<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
4393 Test<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
4396 Test<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
4399 Test<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
4409 if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
4411 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4414 Mul<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
4417 Mul<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
4420 Mul<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
4433 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4434 bool min = instr->Bit(4) != 0;
4437 PairwiseMinMax<int8_t>(
this, Vd, Vm, Vn, min);
4440 PairwiseMinMax<int16_t>(
this, Vd, Vm, Vn, min);
4443 PairwiseMinMax<int32_t>(
this, Vd, Vm, Vn, min);
4453 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4456 PairwiseAdd<int8_t>(
this, Vd, Vm, Vn);
4459 PairwiseAdd<int16_t>(
this, Vd, Vm, Vn);
4462 PairwiseAdd<int32_t>(
this, Vd, Vm, Vn);
4471 if (instr->Bit(4) == 0) {
4472 float src1[4], src2[4];
4473 get_neon_register(Vn, src1);
4474 get_neon_register(Vm, src2);
4475 for (
int i = 0;
i < 4;
i++) {
4476 if (instr->Bit(21) == 0) {
4478 src1[
i] = src1[
i] + src2[
i];
4481 src1[
i] = src1[
i] - src2[
i];
4484 set_neon_register(Vd, src1);
4491 if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
4493 float src1[4], src2[4];
4494 get_neon_register(Vn, src1);
4495 get_neon_register(Vm, src2);
4497 for (
int i = 0;
i < 4;
i++) {
4498 dst[
i] = (src1[
i] == src2[
i]) ? 0xFFFFFFFF : 0;
4500 set_neon_register(Vd, dst);
4507 if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
4508 float src1[4], src2[4];
4509 get_neon_register(Vn, src1);
4510 get_neon_register(Vm, src2);
4511 if (instr->Bit(4) == 1) {
4512 if (instr->Bit(21) == 0) {
4514 for (
int i = 0;
i < 4;
i++) {
4515 src1[
i] = 2.0f - src1[
i] * src2[
i];
4519 for (
int i = 0;
i < 4;
i++) {
4520 src1[
i] = (3.0f - src1[
i] * src2[
i]) * 0.5f;
4525 bool min = instr->Bit(21) == 1;
4526 for (
int i = 0;
i < 4;
i++) {
4527 src1[
i] = MinMax(src1[
i], src2[
i], min);
4530 set_neon_register(Vd, src1);
4543 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
4544 (instr->Bit(4) == 1)) {
4546 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
4547 int Vd = instr->VFPDRegValue(kSimd128Precision);
4548 int Vm = instr->VFPMRegValue(kDoublePrecision);
4549 int imm3 = instr->Bits(21, 19);
4552 Widen<int8_t, int16_t>(
this, Vd, Vm);
4555 Widen<int16_t, int32_t>(
this, Vd, Vm);
4558 Widen<int32_t, int64_t>(
this, Vd, Vm);
4564 }
else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
4566 int imm4 = instr->Bits(11, 8);
4567 int Vd = instr->VFPDRegValue(kSimd128Precision);
4568 int Vm = instr->VFPMRegValue(kSimd128Precision);
4569 int Vn = instr->VFPNRegValue(kSimd128Precision);
4570 uint8_t src1[16], src2[16], dst[16];
4571 get_neon_register(Vn, src1);
4572 get_neon_register(Vm, src2);
4573 int boundary = kSimd128Size - imm4;
4575 for (;
i < boundary;
i++) {
4576 dst[
i] = src1[
i + imm4];
4578 for (;
i < 16;
i++) {
4579 dst[
i] = src2[
i - boundary];
4581 set_neon_register(Vd, dst);
4582 }
else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
4584 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
4585 int shift = instr->Bits(21, 16) - size;
4586 int Vd = instr->VFPDRegValue(kSimd128Precision);
4587 int Vm = instr->VFPMRegValue(kSimd128Precision);
4588 NeonSize ns =
static_cast<NeonSize
>(size / 16);
4591 ShiftLeft<uint8_t, kSimd128Size>(
this, Vd, Vm, shift);
4594 ShiftLeft<uint16_t, kSimd128Size>(
this, Vd, Vm, shift);
4597 ShiftLeft<uint32_t, kSimd128Size>(
this, Vd, Vm, shift);
4603 }
else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
4605 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
4606 int shift = 2 * size - instr->Bits(21, 16);
4607 int Vd = instr->VFPDRegValue(kSimd128Precision);
4608 int Vm = instr->VFPMRegValue(kSimd128Precision);
4609 NeonSize ns =
static_cast<NeonSize
>(size / 16);
4612 ArithmeticShiftRight<int8_t, kSimd128Size>(
this, Vd, Vm, shift);
4615 ArithmeticShiftRight<int16_t, kSimd128Size>(
this, Vd, Vm, shift);
4618 ArithmeticShiftRight<int32_t, kSimd128Size>(
this, Vd, Vm, shift);
4630 if (instr->Bit(6) == 0) {
4631 Vd = instr->VFPDRegValue(kDoublePrecision);
4632 Vm = instr->VFPMRegValue(kDoublePrecision);
4633 Vn = instr->VFPNRegValue(kDoublePrecision);
4635 Vd = instr->VFPDRegValue(kSimd128Precision);
4636 Vm = instr->VFPMRegValue(kSimd128Precision);
4637 Vn = instr->VFPNRegValue(kSimd128Precision);
4639 switch (instr->Bits(11, 8)) {
4641 if (instr->Bit(4) == 1) {
4643 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4646 AddSaturate<uint8_t>(
this, Vd, Vm, Vn);
4649 AddSaturate<uint16_t>(
this, Vd, Vm, Vn);
4652 AddSaturate<uint32_t>(
this, Vd, Vm, Vn);
4664 if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
4667 get_neon_register(Vd, dst);
4668 get_neon_register(Vn, src1);
4669 get_neon_register(Vm, src2);
4670 for (
int i = 0;
i < 4;
i++) {
4671 dst[
i] = (dst[
i] & src1[
i]) | (~dst[
i] & src2[
i]);
4673 set_neon_register(Vd, dst);
4674 }
else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
4675 if (instr->Bit(6) == 0) {
4677 uint64_t src1, src2;
4678 get_d_register(Vn, &src1);
4679 get_d_register(Vm, &src2);
4681 set_d_register(Vd, &src1);
4686 get_neon_register(Vn, src1);
4687 get_neon_register(Vm, src2);
4688 for (
int i = 0;
i < 4;
i++) src1[
i] ^= src2[
i];
4689 set_neon_register(Vd, src1);
4697 if (instr->Bit(4) == 1) {
4699 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4702 SubSaturate<uint8_t>(
this, Vd, Vm, Vn);
4705 SubSaturate<uint16_t>(
this, Vd, Vm, Vn);
4708 SubSaturate<uint32_t>(
this, Vd, Vm, Vn);
4721 bool ge = instr->Bit(4) == 1;
4722 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4725 CompareGreater<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
4728 CompareGreater<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
4731 CompareGreater<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn, ge);
4741 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4742 bool min = instr->Bit(4) != 0;
4745 MinMax<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
4748 MinMax<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
4751 MinMax<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn, min);
4760 if (instr->Bit(4) == 0) {
4762 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4765 Sub<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
4768 Sub<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
4771 Sub<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
4779 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4782 CompareEqual<uint8_t, kSimd128Size>(
this, Vd, Vm, Vn);
4785 CompareEqual<uint16_t, kSimd128Size>(
this, Vd, Vm, Vn);
4788 CompareEqual<uint32_t, kSimd128Size>(
this, Vd, Vm, Vn);
4799 NeonSize size =
static_cast<NeonSize
>(instr->Bits(21, 20));
4800 bool min = instr->Bit(4) != 0;
4803 PairwiseMinMax<uint8_t>(
this, Vd, Vm, Vn, min);
4806 PairwiseMinMax<uint16_t>(
this, Vd, Vm, Vn, min);
4809 PairwiseMinMax<uint32_t>(
this, Vd, Vm, Vn, min);
4818 if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
4819 instr->Bit(4) == 1) {
4821 float src1[4], src2[4];
4822 get_neon_register(Vn, src1);
4823 get_neon_register(Vm, src2);
4824 for (
int i = 0;
i < 4;
i++) {
4825 src1[
i] = src1[
i] * src2[
i];
4827 set_neon_register(Vd, src1);
4828 }
else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 0 &&
4829 instr->Bit(4) == 0) {
4831 PairwiseAdd<float>(
this, Vd, Vm, Vn);
4838 if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
4840 bool ge = instr->Bit(21) == 0;
4841 float src1[4], src2[4];
4842 get_neon_register(Vn, src1);
4843 get_neon_register(Vm, src2);
4845 for (
int i = 0;
i < 4;
i++) {
4847 dst[
i] = src1[
i] >= src2[
i] ? 0xFFFFFFFFu : 0;
4849 dst[
i] = src1[
i] > src2[
i] ? 0xFFFFFFFFu : 0;
4852 set_neon_register(Vd, dst);
4865 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
4866 (instr->Bit(4) == 1)) {
4868 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
4869 int Vd = instr->VFPDRegValue(kSimd128Precision);
4870 int Vm = instr->VFPMRegValue(kDoublePrecision);
4871 int imm3 = instr->Bits(21, 19);
4874 Widen<uint8_t, uint16_t>(
this, Vd, Vm);
4877 Widen<uint16_t, uint32_t>(
this, Vd, Vm);
4880 Widen<uint32_t, uint64_t>(
this, Vd, Vm);
4886 }
else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
4887 if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
4888 instr->Bit(6) == 1) {
4890 int Vd = instr->VFPDRegValue(kSimd128Precision);
4891 int Vm = instr->VFPMRegValue(kSimd128Precision);
4893 get_neon_register(Vm, q_data);
4894 int op = instr->Bits(8, 7);
4895 for (
int i = 0;
i < 4;
i++) {
4899 q_data[
i] = bit_cast<
uint32_t>(std::round(
4900 static_cast<float>(bit_cast<int32_t>(q_data[
i]))));
4905 std::round(static_cast<float>(q_data[
i])));
4910 ConvertDoubleToInt(bit_cast<float>(q_data[
i]),
false, RZ));
4915 ConvertDoubleToInt(bit_cast<float>(q_data[
i]),
true, RZ));
4919 set_neon_register(Vd, q_data);
4920 }
else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
4921 if (instr->Bit(6) == 0) {
4923 uint64_t dval, mval;
4924 int vd = instr->VFPDRegValue(kDoublePrecision);
4925 int vm = instr->VFPMRegValue(kDoublePrecision);
4926 get_d_register(vd, &dval);
4927 get_d_register(vm, &mval);
4928 set_d_register(vm, &dval);
4929 set_d_register(vd, &mval);
4933 int vd = instr->VFPDRegValue(kSimd128Precision);
4934 int vm = instr->VFPMRegValue(kSimd128Precision);
4935 get_neon_register(vd, dval);
4936 get_neon_register(vm, mval);
4937 set_neon_register(vm, dval);
4938 set_neon_register(vd, mval);
4940 }
else if (instr->Bits(11, 7) == 0x18) {
4943 int vm = instr->VFPMRegValue(kDoublePrecision);
4944 int imm4 = instr->Bits(19, 16);
4945 int size = 0, index = 0, mask = 0;
4946 if ((imm4 & 0x1) != 0) {
4950 }
else if ((imm4 & 0x2) != 0) {
4960 get_d_register(vm, &d_data);
4961 uint32_t scalar = (d_data >> (size * index)) & mask;
4963 for (
int i = 1;
i < 32 / size;
i++) {
4967 uint32_t result[4] = {duped, duped, duped, duped};
4968 if (instr->Bit(6) == 0) {
4969 int vd = instr->VFPDRegValue(kDoublePrecision);
4970 set_d_register(vd, result);
4972 int vd = instr->VFPDRegValue(kSimd128Precision);
4973 set_neon_register(vd, result);
4975 }
else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
4977 int vd = instr->VFPDRegValue(kSimd128Precision);
4978 int vm = instr->VFPMRegValue(kSimd128Precision);
4980 get_neon_register(vm, q_data);
4981 for (
int i = 0;
i < 4;
i++) q_data[
i] = ~q_data[
i];
4982 set_neon_register(vd, q_data);
4983 }
else if (instr->Bits(11, 10) == 0x2) {
4985 int vd = instr->VFPDRegValue(kDoublePrecision);
4986 int vn = instr->VFPNRegValue(kDoublePrecision);
4987 int vm = instr->VFPMRegValue(kDoublePrecision);
4988 int table_len = (instr->Bits(9, 8) + 1) * kDoubleSize;
4989 bool vtbx = instr->Bit(6) != 0;
4990 uint64_t destination = 0, indices = 0, result = 0;
4991 get_d_register(vd, &destination);
4992 get_d_register(vm, &indices);
4993 for (
int i = 0;
i < kDoubleSize;
i++) {
4994 int shift =
i * kBitsPerByte;
4995 int index = (indices >> shift) & 0xFF;
4996 if (index < table_len) {
4998 get_d_register(vn + index / kDoubleSize, &table);
5000 ((table >> ((index % kDoubleSize) * kBitsPerByte)) & 0xFF)
5003 result |= destination & (0xFFull << shift);
5006 set_d_register(vd, &result);
5007 }
else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x1) {
5008 NeonSize size =
static_cast<NeonSize
>(instr->Bits(19, 18));
5009 if (instr->Bit(6) == 0) {
5010 int Vd = instr->VFPDRegValue(kDoublePrecision);
5011 int Vm = instr->VFPMRegValue(kDoublePrecision);
5012 if (instr->Bit(7) == 1) {
5016 Zip<uint8_t, kDoubleSize>(
this, Vd, Vm);
5019 Zip<uint16_t, kDoubleSize>(
this, Vd, Vm);
5032 Unzip<uint8_t, kDoubleSize>(
this, Vd, Vm);
5035 Unzip<uint16_t, kDoubleSize>(
this, Vd, Vm);
5046 int Vd = instr->VFPDRegValue(kSimd128Precision);
5047 int Vm = instr->VFPMRegValue(kSimd128Precision);
5048 if (instr->Bit(7) == 1) {
5052 Zip<uint8_t, kSimd128Size>(
this, Vd, Vm);
5055 Zip<uint16_t, kSimd128Size>(
this, Vd, Vm);
5058 Zip<uint32_t, kSimd128Size>(
this, Vd, Vm);
5068 Unzip<uint8_t, kSimd128Size>(
this, Vd, Vm);
5071 Unzip<uint16_t, kSimd128Size>(
this, Vd, Vm);
5074 Unzip<uint32_t, kSimd128Size>(
this, Vd, Vm);
5082 }
else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) {
5084 int Vd = instr->VFPDRegValue(kSimd128Precision);
5085 int Vm = instr->VFPMRegValue(kSimd128Precision);
5086 NeonSize size =
static_cast<NeonSize
>(instr->Bits(19, 18));
5087 NeonSize op =
static_cast<NeonSize
>(
static_cast<int>(Neon64) -
5091 DCHECK_EQ(Neon8, size);
5093 get_neon_register(Vm, src);
5094 for (
int i = 0;
i < 16;
i += 2) {
5095 std::swap(src[
i], src[
i + 1]);
5097 set_neon_register(Vd, src);
5104 get_neon_register(Vm, src);
5105 for (
int i = 0;
i < 8;
i += 2) {
5106 std::swap(src[
i], src[
i + 1]);
5108 set_neon_register(Vd, src);
5113 get_neon_register(Vm, src);
5114 for (
int i = 0;
i < 4;
i++) {
5115 std::swap(src[
i * 4], src[
i * 4 + 3]);
5116 std::swap(src[
i * 4 + 1], src[
i * 4 + 2]);
5118 set_neon_register(Vd, src);
5131 get_neon_register(Vm, src);
5132 std::swap(src[0], src[1]);
5133 std::swap(src[2], src[3]);
5134 set_neon_register(Vd, src);
5139 get_neon_register(Vm, src);
5140 for (
int i = 0;
i < 2;
i++) {
5141 std::swap(src[
i * 4], src[
i * 4 + 3]);
5142 std::swap(src[
i * 4 + 1], src[
i * 4 + 2]);
5144 set_neon_register(Vd, src);
5149 get_neon_register(Vm, src);
5150 for (
int i = 0;
i < 4;
i++) {
5151 std::swap(src[
i], src[7 -
i]);
5152 std::swap(src[
i + 8], src[15 -
i]);
5154 set_neon_register(Vd, src);
5167 }
else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0x1) {
5168 NeonSize size =
static_cast<NeonSize
>(instr->Bits(19, 18));
5169 if (instr->Bit(6) == 0) {
5170 int Vd = instr->VFPDRegValue(kDoublePrecision);
5171 int Vm = instr->VFPMRegValue(kDoublePrecision);
5175 Transpose<uint8_t, kDoubleSize>(
this, Vd, Vm);
5178 Transpose<uint16_t, kDoubleSize>(
this, Vd, Vm);
5181 Transpose<uint32_t, kDoubleSize>(
this, Vd, Vm);
5188 int Vd = instr->VFPDRegValue(kSimd128Precision);
5189 int Vm = instr->VFPMRegValue(kSimd128Precision);
5193 Transpose<uint8_t, kSimd128Size>(
this, Vd, Vm);
5196 Transpose<uint16_t, kSimd128Size>(
this, Vd, Vm);
5199 Transpose<uint32_t, kSimd128Size>(
this, Vd, Vm);
5206 }
else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) {
5207 int Vd = instr->VFPDRegValue(kSimd128Precision);
5208 int Vm = instr->VFPMRegValue(kSimd128Precision);
5209 NeonSize size =
static_cast<NeonSize
>(instr->Bits(19, 18));
5210 if (instr->Bits(9, 6) == 0xD) {
5212 if (instr->Bit(10) != 0) {
5215 get_neon_register(Vm, src);
5216 for (
int i = 0;
i < 4;
i++) {
5217 src[
i] &= ~0x80000000;
5219 set_neon_register(Vd, src);
5224 Abs<int8_t, kSimd128Size>(
this, Vd, Vm);
5227 Abs<int16_t, kSimd128Size>(
this, Vd, Vm);
5230 Abs<int32_t, kSimd128Size>(
this, Vd, Vm);
5237 }
else if (instr->Bits(9, 6) == 0xF) {
5239 if (instr->Bit(10) != 0) {
5242 get_neon_register(Vm, src);
5243 for (
int i = 0;
i < 4;
i++) {
5244 src[
i] ^= 0x80000000;
5246 set_neon_register(Vd, src);
5251 Neg<int8_t, kSimd128Size>(
this, Vd, Vm);
5254 Neg<int16_t, kSimd128Size>(
this, Vd, Vm);
5257 Neg<int32_t, kSimd128Size>(
this, Vd, Vm);
5267 }
else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) {
5269 int Vd = instr->VFPDRegValue(kSimd128Precision);
5270 int Vm = instr->VFPMRegValue(kSimd128Precision);
5272 get_neon_register(Vm, src);
5273 if (instr->Bit(7) == 0) {
5274 for (
int i = 0;
i < 4;
i++) {
5275 float denom = bit_cast<
float>(src[
i]);
5276 div_zero_vfp_flag_ = (denom == 0);
5277 float result = 1.0f / denom;
5278 result = canonicalizeNaN(result);
5282 lazily_initialize_fast_sqrt();
5283 for (
int i = 0;
i < 4;
i++) {
5284 float radicand = bit_cast<
float>(src[
i]);
5285 float result = 1.0f / fast_sqrt(radicand);
5286 result = canonicalizeNaN(result);
5290 set_neon_register(Vd, src);
5291 }
else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x2 &&
5292 instr->Bits(7, 6) != 0) {
5294 int Vd = instr->VFPDRegValue(kDoublePrecision);
5295 int Vm = instr->VFPMRegValue(kSimd128Precision);
5296 NeonSize size =
static_cast<NeonSize
>(instr->Bits(19, 18));
5297 bool is_unsigned = instr->Bit(6) != 0;
5301 SaturatingNarrow<uint16_t, uint8_t>(
this, Vd, Vm);
5303 SaturatingNarrow<int16_t, int8_t>(
this, Vd, Vm);
5309 SaturatingNarrow<uint32_t, uint16_t>(
this, Vd, Vm);
5311 SaturatingNarrow<int32_t, int16_t>(
this, Vd, Vm);
5317 SaturatingNarrow<uint64_t, uint32_t>(
this, Vd, Vm);
5319 SaturatingNarrow<int64_t, int32_t>(
this, Vd, Vm);
5330 }
else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
5332 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
5333 int shift = 2 * size - instr->Bits(21, 16);
5334 int Vd = instr->VFPDRegValue(kSimd128Precision);
5335 int Vm = instr->VFPMRegValue(kSimd128Precision);
5336 NeonSize ns =
static_cast<NeonSize
>(size / 16);
5339 ShiftRight<uint8_t, kSimd128Size>(
this, Vd, Vm, shift);
5342 ShiftRight<uint16_t, kSimd128Size>(
this, Vd, Vm, shift);
5345 ShiftRight<uint32_t, kSimd128Size>(
this, Vd, Vm, shift);
5351 }
else if (instr->Bits(11, 8) == 0x5 && instr->Bit(6) == 0 &&
5352 instr->Bit(4) == 1) {
5354 int imm7 = instr->Bits(21, 16);
5355 if (instr->Bit(7) != 0) imm7 += 64;
5356 int size = base::bits::RoundDownToPowerOfTwo32(imm7);
5357 int shift = imm7 - size;
5358 int Vd = instr->VFPDRegValue(kDoublePrecision);
5359 int Vm = instr->VFPMRegValue(kDoublePrecision);
5362 ShiftLeftAndInsert<uint8_t, kDoubleSize>(
this, Vd, Vm, shift);
5365 ShiftLeftAndInsert<uint16_t, kDoubleSize>(
this, Vd, Vm, shift);
5368 ShiftLeftAndInsert<uint32_t, kDoubleSize>(
this, Vd, Vm, shift);
5371 ShiftLeftAndInsert<uint64_t, kDoubleSize>(
this, Vd, Vm, shift);
5377 }
else if (instr->Bits(11, 8) == 0x4 && instr->Bit(6) == 0 &&
5378 instr->Bit(4) == 1) {
5380 int imm7 = instr->Bits(21, 16);
5381 if (instr->Bit(7) != 0) imm7 += 64;
5382 int size = base::bits::RoundDownToPowerOfTwo32(imm7);
5383 int shift = 2 * size - imm7;
5384 int Vd = instr->VFPDRegValue(kDoublePrecision);
5385 int Vm = instr->VFPMRegValue(kDoublePrecision);
5388 ShiftRightAndInsert<uint8_t, kDoubleSize>(
this, Vd, Vm, shift);
5391 ShiftRightAndInsert<uint16_t, kDoubleSize>(
this, Vd, Vm, shift);
5394 ShiftRightAndInsert<uint32_t, kDoubleSize>(
this, Vd, Vm, shift);
5397 ShiftRightAndInsert<uint64_t, kDoubleSize>(
this, Vd, Vm, shift);
5408 if (instr->Bits(21, 20) == 0) {
5410 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
5411 int Rn = instr->VnValue();
5412 int type = instr->Bits(11, 8);
5413 int Rm = instr->VmValue();
5414 int32_t address = get_register(Rn);
5436 get_d_register(Vd + r, data);
5437 WriteW(address, data[0]);
5438 WriteW(address + 4, data[1]);
5444 set_register(Rn, address);
5446 set_register(Rn, get_register(Rn) + get_register(Rm));
5449 }
else if (instr->Bits(21, 20) == 2) {
5451 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
5452 int Rn = instr->VnValue();
5453 int type = instr->Bits(11, 8);
5454 int Rm = instr->VmValue();
5455 int32_t address = get_register(Rn);
5477 data[0] = ReadW(address);
5478 data[1] = ReadW(address + 4);
5479 set_d_register(Vd + r, data);
5485 set_register(Rn, address);
5487 set_register(Rn, get_register(Rn) + get_register(Rm));
5496 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xF)) {
5498 }
else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
5507 if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 &&
5508 instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2) {
5509 if (instr->SzValue() == 0x1) {
5510 int vm = instr->VFPMRegValue(kDoublePrecision);
5511 int vd = instr->VFPDRegValue(kDoublePrecision);
5512 double dm_value = get_double_from_d_register(vm).get_scalar();
5513 double dd_value = 0.0;
5514 int rounding_mode = instr->Bits(17, 16);
5515 switch (rounding_mode) {
5517 dd_value = round(dm_value);
5520 dd_value = nearbyint(dm_value);
5524 dd_value = ceil(dm_value);
5527 dd_value = floor(dm_value);
5533 dd_value = canonicalizeNaN(dd_value);
5534 set_d_register_from_double(vd, dd_value);
5536 int m = instr->VFPMRegValue(kSinglePrecision);
5537 int d = instr->VFPDRegValue(kSinglePrecision);
5538 float sm_value = get_float_from_s_register(m).get_scalar();
5539 float sd_value = 0.0;
5540 int rounding_mode = instr->Bits(17, 16);
5541 switch (rounding_mode) {
5543 sd_value = roundf(sm_value);
5546 sd_value = nearbyintf(sm_value);
5550 sd_value = ceilf(sm_value);
5553 sd_value = floorf(sm_value);
5559 sd_value = canonicalizeNaN(sd_value);
5560 set_s_register_from_float(d, sd_value);
5562 }
else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
5563 (instr->Bit(4) == 0x0)) {
5564 if (instr->SzValue() == 0x1) {
5565 int m = instr->VFPMRegValue(kDoublePrecision);
5566 int n = instr->VFPNRegValue(kDoublePrecision);
5567 int d = instr->VFPDRegValue(kDoublePrecision);
5568 double dn_value = get_double_from_d_register(n).get_scalar();
5569 double dm_value = get_double_from_d_register(m).get_scalar();
5571 if (instr->Bit(6) == 0x1) {
5572 if ((dn_value < dm_value) || std::isnan(dm_value)) {
5573 dd_value = dn_value;
5574 }
else if ((dm_value < dn_value) || std::isnan(dn_value)) {
5575 dd_value = dm_value;
5577 DCHECK_EQ(dn_value, dm_value);
5579 dd_value = std::signbit(dn_value) ? dn_value : dm_value;
5582 if ((dn_value > dm_value) || std::isnan(dm_value)) {
5583 dd_value = dn_value;
5584 }
else if ((dm_value > dn_value) || std::isnan(dn_value)) {
5585 dd_value = dm_value;
5587 DCHECK_EQ(dn_value, dm_value);
5589 dd_value = std::signbit(dn_value) ? dm_value : dn_value;
5592 dd_value = canonicalizeNaN(dd_value);
5593 set_d_register_from_double(d, dd_value);
5595 int m = instr->VFPMRegValue(kSinglePrecision);
5596 int n = instr->VFPNRegValue(kSinglePrecision);
5597 int d = instr->VFPDRegValue(kSinglePrecision);
5598 float sn_value = get_float_from_s_register(n).get_scalar();
5599 float sm_value = get_float_from_s_register(m).get_scalar();
5601 if (instr->Bit(6) == 0x1) {
5602 if ((sn_value < sm_value) || std::isnan(sm_value)) {
5603 sd_value = sn_value;
5604 }
else if ((sm_value < sn_value) || std::isnan(sn_value)) {
5605 sd_value = sm_value;
5607 DCHECK_EQ(sn_value, sm_value);
5609 sd_value = std::signbit(sn_value) ? sn_value : sm_value;
5612 if ((sn_value > sm_value) || std::isnan(sm_value)) {
5613 sd_value = sn_value;
5614 }
else if ((sm_value > sn_value) || std::isnan(sn_value)) {
5615 sd_value = sm_value;
5617 DCHECK_EQ(sn_value, sm_value);
5619 sd_value = std::signbit(sn_value) ? sm_value : sn_value;
5622 sd_value = canonicalizeNaN(sd_value);
5623 set_s_register_from_float(d, sd_value);
5630 if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
5631 (instr->Bit(4) == 0)) {
5633 bool condition_holds;
5634 switch (instr->Bits(21, 20)) {
5636 condition_holds = (z_flag_ == 1);
5639 condition_holds = (v_flag_ == 1);
5642 condition_holds = (n_flag_ == v_flag_);
5645 condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_));
5651 if (instr->SzValue() == 0x1) {
5652 int n = instr->VFPNRegValue(kDoublePrecision);
5653 int m = instr->VFPMRegValue(kDoublePrecision);
5654 int d = instr->VFPDRegValue(kDoublePrecision);
5655 Float64 result = get_double_from_d_register(condition_holds ? n : m);
5656 set_d_register_from_double(d, result);
5658 int n = instr->VFPNRegValue(kSinglePrecision);
5659 int m = instr->VFPMRegValue(kSinglePrecision);
5660 int d = instr->VFPDRegValue(kSinglePrecision);
5661 Float32 result = get_float_from_s_register(condition_holds ? n : m);
5662 set_s_register_from_float(d, result);
5676 void Simulator::InstructionDecode(Instruction* instr) {
5677 if (v8::internal::FLAG_check_icache) {
5678 CheckICache(i_cache(), instr);
5680 pc_modified_ =
false;
5681 if (::v8::internal::FLAG_trace_sim) {
5686 dasm.InstructionDecode(buffer,
5687 reinterpret_cast<byte*>(instr));
5688 PrintF(
" 0x%08" V8PRIxPTR
" %s\n", reinterpret_cast<intptr_t>(instr),
5691 if (instr->ConditionField() == kSpecialCondition) {
5692 DecodeSpecialCondition(instr);
5693 }
else if (ConditionallyExecute(instr)) {
5694 switch (instr->TypeValue()) {
5697 DecodeType01(instr);
5730 if (!pc_modified_) {
5731 set_register(pc, reinterpret_cast<int32_t>(instr) + kInstrSize);
5735 void Simulator::Execute() {
5738 int program_counter = get_pc();
5740 if (::v8::internal::FLAG_stop_sim_at == 0) {
5743 while (program_counter != end_sim_pc) {
5744 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
5746 InstructionDecode(instr);
5747 program_counter = get_pc();
5752 while (program_counter != end_sim_pc) {
5753 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
5755 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
5756 ArmDebugger dbg(
this);
5759 InstructionDecode(instr);
5761 program_counter = get_pc();
5766 void Simulator::CallInternal(Address entry) {
5768 isolate_->stack_guard()->AdjustStackLimitForSimulator();
5771 set_register(pc, static_cast<int32_t>(entry));
5775 set_register(lr, end_sim_pc);
5780 int32_t r4_val = get_register(r4);
5781 int32_t r5_val = get_register(r5);
5782 int32_t r6_val = get_register(r6);
5783 int32_t r7_val = get_register(r7);
5784 int32_t r8_val = get_register(r8);
5785 int32_t r9_val = get_register(r9);
5786 int32_t r10_val = get_register(r10);
5787 int32_t r11_val = get_register(r11);
5791 int32_t callee_saved_value = icount_;
5792 set_register(r4, callee_saved_value);
5793 set_register(r5, callee_saved_value);
5794 set_register(r6, callee_saved_value);
5795 set_register(r7, callee_saved_value);
5796 set_register(r8, callee_saved_value);
5797 set_register(r9, callee_saved_value);
5798 set_register(r10, callee_saved_value);
5799 set_register(r11, callee_saved_value);
5805 CHECK_EQ(callee_saved_value, get_register(r4));
5806 CHECK_EQ(callee_saved_value, get_register(r5));
5807 CHECK_EQ(callee_saved_value, get_register(r6));
5808 CHECK_EQ(callee_saved_value, get_register(r7));
5809 CHECK_EQ(callee_saved_value, get_register(r8));
5810 CHECK_EQ(callee_saved_value, get_register(r9));
5811 CHECK_EQ(callee_saved_value, get_register(r10));
5812 CHECK_EQ(callee_saved_value, get_register(r11));
5815 set_register(r4, r4_val);
5816 set_register(r5, r5_val);
5817 set_register(r6, r6_val);
5818 set_register(r7, r7_val);
5819 set_register(r8, r8_val);
5820 set_register(r9, r9_val);
5821 set_register(r10, r10_val);
5822 set_register(r11, r11_val);
5825 intptr_t Simulator::CallImpl(Address entry,
int argument_count,
5826 const intptr_t* arguments) {
5830 int reg_arg_count = std::min(4, argument_count);
5831 if (reg_arg_count > 0) set_register(r0, arguments[0]);
5832 if (reg_arg_count > 1) set_register(r1, arguments[1]);
5833 if (reg_arg_count > 2) set_register(r2, arguments[2]);
5834 if (reg_arg_count > 3) set_register(r3, arguments[3]);
5837 int original_stack = get_register(sp);
5839 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(int32_t));
5840 if (base::OS::ActivationFrameAlignment() != 0) {
5841 entry_stack &= -base::OS::ActivationFrameAlignment();
5844 memcpy(reinterpret_cast<intptr_t*>(entry_stack), arguments + reg_arg_count,
5845 (argument_count - reg_arg_count) *
sizeof(*arguments));
5846 set_register(sp, entry_stack);
5848 CallInternal(entry);
5851 CHECK_EQ(entry_stack, get_register(sp));
5852 set_register(sp, original_stack);
5854 return get_register(r0);
5857 intptr_t Simulator::CallFPImpl(Address entry,
double d0,
double d1) {
5858 if (use_eabi_hardfloat()) {
5859 set_d_register_from_double(0, d0);
5860 set_d_register_from_double(1, d1);
5862 set_register_pair_from_double(0, &d0);
5863 set_register_pair_from_double(2, &d1);
5865 CallInternal(entry);
5866 return get_register(r0);
5871 int new_sp = get_register(sp) -
sizeof(
uintptr_t);
5873 *stack_slot = address;
5874 set_register(sp, new_sp);
5880 int current_sp = get_register(sp);
5883 set_register(sp, current_sp +
sizeof(
uintptr_t));
5887 Simulator::LocalMonitor::LocalMonitor()
5888 : access_state_(MonitorAccess::Open),
5890 size_(TransactionSize::
None) {}
5892 void Simulator::LocalMonitor::Clear() {
5893 access_state_ = MonitorAccess::Open;
5895 size_ = TransactionSize::None;
5898 void Simulator::LocalMonitor::NotifyLoad(int32_t addr) {
5899 if (access_state_ == MonitorAccess::Exclusive) {
5907 void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr,
5908 TransactionSize size) {
5909 access_state_ = MonitorAccess::Exclusive;
5910 tagged_addr_ = addr;
5914 void Simulator::LocalMonitor::NotifyStore(int32_t addr) {
5915 if (access_state_ == MonitorAccess::Exclusive) {
5927 bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr,
5928 TransactionSize size) {
5929 if (access_state_ == MonitorAccess::Exclusive) {
5932 if (addr == tagged_addr_ && size_ == size) {
5944 DCHECK(access_state_ == MonitorAccess::Open);
5949 Simulator::GlobalMonitor::Processor::Processor()
5950 : access_state_(MonitorAccess::Open),
5954 failure_counter_(0) {}
5956 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
5957 access_state_ = MonitorAccess::Open;
5961 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
5962 access_state_ = MonitorAccess::Exclusive;
5963 tagged_addr_ = addr;
5966 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
5967 int32_t addr,
bool is_requesting_processor) {
5968 if (access_state_ == MonitorAccess::Exclusive) {
5985 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
5986 int32_t addr,
bool is_requesting_processor) {
5987 if (access_state_ == MonitorAccess::Exclusive) {
5988 if (is_requesting_processor) {
5991 if (addr == tagged_addr_) {
6000 if (failure_counter_++ >= kMaxFailureCounter) {
6001 failure_counter_ = 0;
6007 }
else if ((addr & kExclusiveTaggedAddrMask) ==
6008 (tagged_addr_ & kExclusiveTaggedAddrMask)) {
6019 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
6021 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
6022 Processor* processor) {
6023 processor->NotifyLoadExcl_Locked(addr);
6024 PrependProcessor_Locked(processor);
6027 void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr,
6028 Processor* processor) {
6030 for (Processor* iter = head_; iter; iter = iter->next_) {
6031 bool is_requesting_processor = iter == processor;
6032 iter->NotifyStore_Locked(addr, is_requesting_processor);
6036 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr,
6037 Processor* processor) {
6038 DCHECK(IsProcessorInLinkedList_Locked(processor));
6039 if (processor->NotifyStoreExcl_Locked(addr,
true)) {
6041 for (Processor* iter = head_; iter; iter = iter->next_) {
6042 if (iter != processor) {
6043 iter->NotifyStoreExcl_Locked(addr,
false);
6052 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
6053 Processor* processor)
const {
6054 return head_ == processor || processor->next_ || processor->prev_;
6057 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
6058 if (IsProcessorInLinkedList_Locked(processor)) {
6063 head_->prev_ = processor;
6065 processor->prev_ =
nullptr;
6066 processor->next_ = head_;
6070 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
6071 base::MutexGuard lock_guard(&mutex);
6072 if (!IsProcessorInLinkedList_Locked(processor)) {
6076 if (processor->prev_) {
6077 processor->prev_->next_ = processor->next_;
6079 head_ = processor->next_;
6081 if (processor->next_) {
6082 processor->next_->prev_ = processor->prev_;
6084 processor->prev_ =
nullptr;
6085 processor->next_ =
nullptr;
6091 #endif // USE_SIMULATOR 6093 #endif // V8_TARGET_ARCH_ARM