10 #if V8_TARGET_ARCH_ARM64 12 #include "src/arm64/decoder-arm64-inl.h" 13 #include "src/arm64/simulator-arm64.h" 14 #include "src/assembler-inl.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/ostreams.h" 20 #include "src/runtime/runtime-utils.h" 25 #if defined(USE_SIMULATOR) 32 #define SScanF sscanf // NOLINT 36 #define COLOUR(colour_code) "\033[0;" colour_code "m" 37 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m" 48 typedef char const *
const TEXT_COLOUR;
49 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) :
"";
50 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) :
"";
51 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) :
"";
52 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) :
"";
53 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) :
"";
54 TEXT_COLOUR clr_vreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) :
"";
55 TEXT_COLOUR clr_vreg_value = FLAG_log_colour ? COLOUR(MAGENTA) :
"";
56 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) :
"";
57 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) :
"";
58 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) :
"";
59 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) :
"";
62 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
63 LAZY_INSTANCE_INITIALIZER;
66 void Simulator::TraceSim(
const char* format, ...) {
69 va_start(arguments, format);
70 base::OS::VFPrint(stream_, format, arguments);
75 const Instruction* Simulator::kEndOfSimAddress =
nullptr;
77 void SimSystemRegister::SetBits(
int msb,
int lsb,
uint32_t bits) {
78 int width = msb - lsb + 1;
79 DCHECK(is_uintn(bits, width) || is_intn(bits, width));
82 uint32_t mask = ((1 << width) - 1) << lsb;
83 DCHECK_EQ(mask & write_ignore_mask_, 0);
85 value_ = (value_ & ~mask) | (bits & mask);
89 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister
id) {
92 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
94 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
102 Simulator* Simulator::current(Isolate* isolate) {
103 Isolate::PerIsolateThreadData* isolate_data =
104 isolate->FindOrAllocatePerThreadDataForThisThread();
105 DCHECK_NOT_NULL(isolate_data);
107 Simulator* sim = isolate_data->simulator();
108 if (sim ==
nullptr) {
109 if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) {
110 sim =
new Simulator(
new Decoder<DispatchingDecoderVisitor>(), isolate);
112 sim =
new Decoder<Simulator>();
113 sim->isolate_ = isolate;
115 isolate_data->set_simulator(sim);
120 void Simulator::CallImpl(Address entry, CallArgument* args) {
124 std::vector<int64_t> stack_args(0);
125 for (
int i = 0; !args[
i].IsEnd();
i++) {
126 CallArgument arg = args[
i];
127 if (arg.IsX() && (index_x < 8)) {
128 set_xreg(index_x++, arg.bits());
129 }
else if (arg.IsD() && (index_d < 8)) {
130 set_dreg_bits(index_d++, arg.bits());
132 DCHECK(arg.IsD() || arg.IsX());
133 stack_args.push_back(arg.bits());
140 stack_args.size() *
sizeof(stack_args[0]);
141 if (base::OS::ActivationFrameAlignment() != 0) {
142 entry_stack &= -base::OS::ActivationFrameAlignment();
144 char * stack =
reinterpret_cast<char*
>(entry_stack);
145 std::vector<int64_t>::const_iterator it;
146 for (it = stack_args.begin(); it != stack_args.end(); it++) {
147 memcpy(stack, &(*it),
sizeof(*it));
148 stack +=
sizeof(*it);
151 DCHECK(reinterpret_cast<uintptr_t>(stack) <= original_stack);
156 set_lr(kEndOfSimAddress);
157 CheckPCSComplianceAndRun();
159 set_sp(original_stack);
162 void Simulator::CheckPCSComplianceAndRun() {
164 isolate_->stack_guard()->AdjustStackLimitForSimulator();
167 DCHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
168 DCHECK_EQ(kNumberOfCalleeSavedVRegisters, kCalleeSavedV.Count());
170 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
171 uint64_t saved_fpregisters[kNumberOfCalleeSavedVRegisters];
173 CPURegList register_list = kCalleeSaved;
174 CPURegList fpregister_list = kCalleeSavedV;
176 for (
int i = 0;
i < kNumberOfCalleeSavedRegisters;
i++) {
179 saved_registers[
i] = xreg(register_list.PopLowestIndex().code());
181 for (
int i = 0;
i < kNumberOfCalleeSavedVRegisters;
i++) {
182 saved_fpregisters[
i] =
183 dreg_bits(fpregister_list.PopLowestIndex().code());
190 DCHECK_EQ(original_stack, sp());
192 register_list = kCalleeSaved;
193 fpregister_list = kCalleeSavedV;
194 for (
int i = 0;
i < kNumberOfCalleeSavedRegisters;
i++) {
195 DCHECK_EQ(saved_registers[
i], xreg(register_list.PopLowestIndex().code()));
197 for (
int i = 0;
i < kNumberOfCalleeSavedVRegisters;
i++) {
198 DCHECK(saved_fpregisters[
i] ==
199 dreg_bits(fpregister_list.PopLowestIndex().code()));
206 register_list = kCallerSaved;
207 register_list.Remove(x0);
208 register_list.Remove(x1);
212 fpregister_list = kCallerSavedV;
213 fpregister_list.Remove(d0);
215 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
216 CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
224 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
225 if (list->type() == CPURegister::kRegister) {
226 while (!list->IsEmpty()) {
227 unsigned code = list->PopLowestIndex().code();
228 set_xreg(code, value | code);
231 DCHECK_EQ(list->type(), CPURegister::kVRegister);
232 while (!list->IsEmpty()) {
233 unsigned code = list->PopLowestIndex().code();
234 set_dreg_bits(code, value | code);
240 void Simulator::CorruptAllCallerSavedCPURegisters() {
242 CPURegList register_list = kCallerSaved;
243 CPURegList fpregister_list = kCallerSavedV;
245 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
246 CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
253 DCHECK(
sizeof(
uintptr_t) < 2 * kXRegSize);
254 intptr_t new_sp = sp() - 2 * kXRegSize;
256 reinterpret_cast<uintptr_t*
>(new_sp + kXRegSize);
257 memcpy(alignment_slot, &kSlotsZapValue, kPointerSize);
259 memcpy(stack_slot, &address, kPointerSize);
266 intptr_t current_sp = sp();
269 DCHECK_LT(
sizeof(
uintptr_t), 2 * kXRegSize);
270 set_sp(current_sp + 2 * kXRegSize);
279 if (GetCurrentStackPosition() < c_limit) {
285 return stack_limit_ + 1024;
288 void Simulator::SetRedirectInstruction(Instruction* instruction) {
289 instruction->SetInstructionBits(
290 HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall));
293 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
294 Isolate* isolate, FILE* stream)
296 last_debugger_input_(nullptr),
297 log_parameters_(NO_PARAM),
300 decoder_->AppendVisitor(
this);
304 if (FLAG_trace_sim) {
305 decoder_->InsertVisitorBefore(print_disasm_,
this);
306 log_parameters_ = LOG_ALL;
309 if (FLAG_log_instruction_stats) {
310 instrument_ =
new Instrument(FLAG_log_instruction_file,
311 FLAG_log_instruction_period);
312 decoder_->AppendVisitor(instrument_);
316 Simulator::Simulator()
318 last_debugger_input_(nullptr),
319 log_parameters_(NO_PARAM),
322 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats);
326 void Simulator::Init(FILE* stream) {
330 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_);
331 stack_ =
reinterpret_cast<uintptr_t>(
new byte[stack_size_]);
332 stack_limit_ = stack_ + stack_protection_size_;
333 uintptr_t tos = stack_ + stack_size_ - stack_protection_size_;
335 set_sp(tos & ~0xFULL);
338 print_disasm_ =
new PrintDisassembler(stream_);
342 disassembler_decoder_ =
new Decoder<DispatchingDecoderVisitor>();
343 disassembler_decoder_->AppendVisitor(print_disasm_);
347 void Simulator::ResetState() {
349 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
350 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
354 for (
unsigned i = 0;
i < kNumberOfRegisters;
i++) {
355 set_xreg(
i, 0xBADBEEF);
357 for (
unsigned i = 0;
i < kNumberOfVRegisters;
i++) {
359 set_dreg_bits(
i, 0x7FF000007F800001UL);
362 set_lr(kEndOfSimAddress);
365 breakpoints_.clear();
366 break_on_next_ =
false;
370 Simulator::~Simulator() {
371 global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
372 delete[]
reinterpret_cast<byte*
>(stack_);
373 if (FLAG_log_instruction_stats) {
376 delete disassembler_decoder_;
377 delete print_disasm_;
378 DeleteArray(last_debugger_input_);
383 void Simulator::Run() {
386 LogAllWrittenRegisters();
388 pc_modified_ =
false;
389 while (pc_ != kEndOfSimAddress) {
390 ExecuteInstruction();
395 void Simulator::RunFrom(Instruction* start) {
406 #if defined(V8_OS_WIN) 414 typedef ObjectPair (*SimulatorRuntimeCall)(
int64_t arg0,
int64_t arg1,
420 typedef int64_t (*SimulatorRuntimeCompareCall)(
double arg1,
double arg2);
421 typedef double (*SimulatorRuntimeFPFPCall)(
double arg1,
double arg2);
422 typedef double (*SimulatorRuntimeFPCall)(
double arg1);
423 typedef double (*SimulatorRuntimeFPIntCall)(
double arg1, int32_t arg2);
427 typedef void (*SimulatorRuntimeDirectApiCall)(
int64_t arg0);
428 typedef void (*SimulatorRuntimeProfilingApiCall)(
int64_t arg0,
void* arg1);
431 typedef void (*SimulatorRuntimeDirectGetterCall)(
int64_t arg0,
int64_t arg1);
432 typedef void (*SimulatorRuntimeProfilingGetterCall)(
int64_t arg0,
int64_t arg1,
435 void Simulator::DoRuntimeCall(Instruction* instr) {
436 Redirection* redirection = Redirection::FromInstruction(instr);
441 Instruction* return_address = lr();
444 reinterpret_cast<int64_t>(redirection->external_function());
446 TraceSim(
"Call to host function at %p\n", redirection->external_function());
449 bool stack_alignment_exception = ((sp() & 0xF) != 0);
450 if (stack_alignment_exception) {
451 TraceSim(
" with unaligned stack 0x%016" PRIx64
".\n", sp());
452 FATAL(
"ALIGNMENT EXCEPTION");
465 const int64_t arg8 = stack_pointer[0];
466 STATIC_ASSERT(kMaxCParameters == 9);
468 switch (redirection->type()) {
470 TraceSim(
"Type: Unknown.\n");
474 case ExternalReference::BUILTIN_CALL:
475 #if defined(V8_OS_WIN) 478 TraceSim(
"Type: BUILTIN_CALL\n");
491 "0x%016" PRIx64
", 0x%016" PRIx64
493 "0x%016" PRIx64
", 0x%016" PRIx64
495 "0x%016" PRIx64
", 0x%016" PRIx64
497 "0x%016" PRIx64
", 0x%016" PRIx64
500 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
502 SimulatorRuntimeCall_ReturnPtr target =
503 reinterpret_cast<SimulatorRuntimeCall_ReturnPtr
>(external);
506 target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
507 TraceSim(
"Returned: 0x%16\n", result);
509 CorruptAllCallerSavedCPURegisters();
516 case ExternalReference::BUILTIN_CALL_PAIR: {
519 TraceSim(
"Type: BUILTIN_CALL\n");
526 "0x%016" PRIx64
", 0x%016" PRIx64
528 "0x%016" PRIx64
", 0x%016" PRIx64
530 "0x%016" PRIx64
", 0x%016" PRIx64
532 "0x%016" PRIx64
", 0x%016" PRIx64
535 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
536 SimulatorRuntimeCall target =
537 reinterpret_cast<SimulatorRuntimeCall
>(external);
539 target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
540 TraceSim(
"Returned: {%p, %p}\n", static_cast<void*>(result.x),
541 static_cast<void*>(result.y));
543 CorruptAllCallerSavedCPURegisters();
545 set_xreg(0, reinterpret_cast<int64_t>(result.x));
546 set_xreg(1, reinterpret_cast<int64_t>(result.y));
550 case ExternalReference::DIRECT_API_CALL: {
552 TraceSim(
"Type: DIRECT_API_CALL\n");
553 SimulatorRuntimeDirectApiCall target =
554 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
555 TraceSim(
"Arguments: 0x%016" PRIx64
"\n", xreg(0));
557 TraceSim(
"No return value.");
559 CorruptAllCallerSavedCPURegisters();
564 case ExternalReference::BUILTIN_COMPARE_CALL: {
566 TraceSim(
"Type: BUILTIN_COMPARE_CALL\n");
567 SimulatorRuntimeCompareCall target =
568 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
569 TraceSim(
"Arguments: %f, %f\n", dreg(0), dreg(1));
570 int64_t result = target(dreg(0), dreg(1));
571 TraceSim(
"Returned: %" PRId64
"\n", result);
573 CorruptAllCallerSavedCPURegisters();
579 case ExternalReference::BUILTIN_FP_CALL: {
581 TraceSim(
"Type: BUILTIN_FP_CALL\n");
582 SimulatorRuntimeFPCall target =
583 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
584 TraceSim(
"Argument: %f\n", dreg(0));
585 double result = target(dreg(0));
586 TraceSim(
"Returned: %f\n", result);
588 CorruptAllCallerSavedCPURegisters();
594 case ExternalReference::BUILTIN_FP_FP_CALL: {
596 TraceSim(
"Type: BUILTIN_FP_FP_CALL\n");
597 SimulatorRuntimeFPFPCall target =
598 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
599 TraceSim(
"Arguments: %f, %f\n", dreg(0), dreg(1));
600 double result = target(dreg(0), dreg(1));
601 TraceSim(
"Returned: %f\n", result);
603 CorruptAllCallerSavedCPURegisters();
609 case ExternalReference::BUILTIN_FP_INT_CALL: {
611 TraceSim(
"Type: BUILTIN_FP_INT_CALL\n");
612 SimulatorRuntimeFPIntCall target =
613 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
614 TraceSim(
"Arguments: %f, %d\n", dreg(0), wreg(0));
615 double result = target(dreg(0), wreg(0));
616 TraceSim(
"Returned: %f\n", result);
618 CorruptAllCallerSavedCPURegisters();
624 case ExternalReference::DIRECT_GETTER_CALL: {
626 TraceSim(
"Type: DIRECT_GETTER_CALL\n");
627 SimulatorRuntimeDirectGetterCall target =
628 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
629 TraceSim(
"Arguments: 0x%016" PRIx64
", 0x%016" PRIx64
"\n",
631 target(xreg(0), xreg(1));
632 TraceSim(
"No return value.");
634 CorruptAllCallerSavedCPURegisters();
639 case ExternalReference::PROFILING_API_CALL: {
641 TraceSim(
"Type: PROFILING_API_CALL\n");
642 SimulatorRuntimeProfilingApiCall target =
643 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
644 void* arg1 = Redirection::ReverseRedirection(xreg(1));
645 TraceSim(
"Arguments: 0x%016" PRIx64
", %p\n", xreg(0), arg1);
646 target(xreg(0), arg1);
647 TraceSim(
"No return value.");
649 CorruptAllCallerSavedCPURegisters();
654 case ExternalReference::PROFILING_GETTER_CALL: {
657 TraceSim(
"Type: PROFILING_GETTER_CALL\n");
658 SimulatorRuntimeProfilingGetterCall target =
659 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(
661 void* arg2 = Redirection::ReverseRedirection(xreg(2));
662 TraceSim(
"Arguments: 0x%016" PRIx64
", 0x%016" PRIx64
", %p\n",
663 xreg(0), xreg(1), arg2);
664 target(xreg(0), xreg(1), arg2);
665 TraceSim(
"No return value.");
667 CorruptAllCallerSavedCPURegisters();
673 set_lr(return_address);
674 set_pc(return_address);
677 const char* Simulator::xreg_names[] = {
678 "x0",
"x1",
"x2",
"x3",
"x4",
"x5",
"x6",
"x7",
"x8",
"x9",
"x10",
679 "x11",
"x12",
"x13",
"x14",
"x15",
"ip0",
"ip1",
"x18",
"x19",
"x20",
"x21",
680 "x22",
"x23",
"x24",
"x25",
"x26",
"cp",
"x28",
"fp",
"lr",
"xzr",
"sp"};
682 const char* Simulator::wreg_names[] = {
683 "w0",
"w1",
"w2",
"w3",
"w4",
"w5",
"w6",
"w7",
"w8",
684 "w9",
"w10",
"w11",
"w12",
"w13",
"w14",
"w15",
"w16",
"w17",
685 "w18",
"w19",
"w20",
"w21",
"w22",
"w23",
"w24",
"w25",
"w26",
686 "wcp",
"w28",
"wfp",
"wlr",
"wzr",
"wsp"};
688 const char* Simulator::sreg_names[] = {
689 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
690 "s8",
"s9",
"s10",
"s11",
"s12",
"s13",
"s14",
"s15",
691 "s16",
"s17",
"s18",
"s19",
"s20",
"s21",
"s22",
"s23",
692 "s24",
"s25",
"s26",
"s27",
"s28",
"s29",
"s30",
"s31"};
694 const char* Simulator::dreg_names[] = {
695 "d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
696 "d8",
"d9",
"d10",
"d11",
"d12",
"d13",
"d14",
"d15",
697 "d16",
"d17",
"d18",
"d19",
"d20",
"d21",
"d22",
"d23",
698 "d24",
"d25",
"d26",
"d27",
"d28",
"d29",
"d30",
"d31"};
700 const char* Simulator::vreg_names[] = {
701 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
702 "v8",
"v9",
"v10",
"v11",
"v12",
"v13",
"v14",
"v15",
703 "v16",
"v17",
"v18",
"v19",
"v20",
"v21",
"v22",
"v23",
704 "v24",
"v25",
"v26",
"v27",
"v28",
"v29",
"v30",
"v31"};
707 const char* Simulator::WRegNameForCode(
unsigned code, Reg31Mode mode) {
708 static_assert(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1),
709 "Array must be large enough to hold all register names.");
710 DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
713 code %= kNumberOfRegisters;
716 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
717 code = kZeroRegCode + 1;
719 return wreg_names[code];
723 const char* Simulator::XRegNameForCode(
unsigned code, Reg31Mode mode) {
724 static_assert(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1),
725 "Array must be large enough to hold all register names.");
726 DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
727 code %= kNumberOfRegisters;
730 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
731 code = kZeroRegCode + 1;
733 return xreg_names[code];
737 const char* Simulator::SRegNameForCode(
unsigned code) {
738 static_assert(arraysize(Simulator::sreg_names) == kNumberOfVRegisters,
739 "Array must be large enough to hold all register names.");
740 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
741 return sreg_names[code % kNumberOfVRegisters];
745 const char* Simulator::DRegNameForCode(
unsigned code) {
746 static_assert(arraysize(Simulator::dreg_names) == kNumberOfVRegisters,
747 "Array must be large enough to hold all register names.");
748 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
749 return dreg_names[code % kNumberOfVRegisters];
753 const char* Simulator::VRegNameForCode(
unsigned code) {
754 static_assert(arraysize(Simulator::vreg_names) == kNumberOfVRegisters,
755 "Array must be large enough to hold all register names.");
756 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
757 return vreg_names[code % kNumberOfVRegisters];
760 void LogicVRegister::ReadUintFromMem(VectorFormat vform,
int index,
761 uint64_t addr)
const {
762 switch (LaneSizeInBitsFromFormat(vform)) {
764 register_.Insert(index, SimMemory::Read<uint8_t>(addr));
767 register_.Insert(index, SimMemory::Read<uint16_t>(addr));
770 register_.Insert(index, SimMemory::Read<uint32_t>(addr));
773 register_.Insert(index, SimMemory::Read<uint64_t>(addr));
781 void LogicVRegister::WriteUintToMem(VectorFormat vform,
int index,
782 uint64_t addr)
const {
783 switch (LaneSizeInBitsFromFormat(vform)) {
785 SimMemory::Write<uint8_t>(addr,
static_cast<uint8_t
>(Uint(vform, index)));
788 SimMemory::Write<uint16_t>(addr,
789 static_cast<uint16_t
>(Uint(vform, index)));
792 SimMemory::Write<uint32_t>(addr,
793 static_cast<uint32_t>(Uint(vform, index)));
796 SimMemory::Write<uint64_t>(addr, Uint(vform, index));
805 int Simulator::CodeFromName(
const char* name) {
806 for (
unsigned i = 0;
i < kNumberOfRegisters;
i++) {
807 if ((strcmp(xreg_names[
i], name) == 0) ||
808 (strcmp(wreg_names[
i], name) == 0)) {
812 for (
unsigned i = 0;
i < kNumberOfVRegisters;
i++) {
813 if ((strcmp(vreg_names[
i], name) == 0) ||
814 (strcmp(dreg_names[
i], name) == 0) ||
815 (strcmp(sreg_names[
i], name) == 0)) {
819 if ((strcmp(
"sp", name) == 0) || (strcmp(
"wsp", name) == 0)) {
820 return kSPRegInternalCode;
827 template <
typename T>
828 T Simulator::AddWithCarry(
bool set_flags, T left, T right,
int carry_in) {
830 static_assert(std::is_unsigned<T>::value,
"operands must be unsigned");
831 static_assert((
sizeof(T) == kWRegSize) || (
sizeof(T) == kXRegSize),
832 "Only W- or X-sized operands are tested");
834 DCHECK((carry_in == 0) || (carry_in == 1));
835 T result = left + right + carry_in;
838 nzcv().SetN(CalcNFlag(result));
839 nzcv().SetZ(CalcZFlag(result));
842 T max_uint_2op = std::numeric_limits<T>::max() - carry_in;
843 nzcv().SetC((left > max_uint_2op) || ((max_uint_2op - left) < right));
847 T sign_mask = T(1) << (
sizeof(T) * 8 - 1);
848 T left_sign = left & sign_mask;
849 T right_sign = right & sign_mask;
850 T result_sign = result & sign_mask;
851 nzcv().SetV((left_sign == right_sign) && (left_sign != result_sign));
853 LogSystemRegister(NZCV);
860 void Simulator::AddSubWithCarry(Instruction* instr) {
862 static_assert(std::is_unsigned<T>::value,
"operands must be unsigned");
864 T op2 = reg<T>(instr->Rm());
867 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
871 new_val = AddWithCarry<T>(instr->FlagsUpdate(),
876 set_reg<T>(instr->Rd(), new_val);
879 template <
typename T>
880 T Simulator::ShiftOperand(T value, Shift shift_type,
unsigned amount) {
881 typedef typename std::make_unsigned<T>::type unsignedT;
887 switch (shift_type) {
889 return value << amount;
891 return static_cast<unsignedT
>(value) >> amount;
893 return value >> amount;
895 unsignedT mask = (
static_cast<unsignedT
>(1) << amount) - 1;
896 return (static_cast<unsignedT>(value) >> amount) |
897 ((value & mask) << (
sizeof(mask) * 8 - amount));
906 template <
typename T>
907 T Simulator::ExtendValue(T value, Extend extend_type,
unsigned left_shift) {
908 const unsigned kSignExtendBShift = (
sizeof(T) - 1) * 8;
909 const unsigned kSignExtendHShift = (
sizeof(T) - 2) * 8;
910 const unsigned kSignExtendWShift = (
sizeof(T) - 4) * 8;
912 switch (extend_type) {
917 value &= kHalfWordMask;
923 value = (value << kSignExtendBShift) >> kSignExtendBShift;
926 value = (value << kSignExtendHShift) >> kSignExtendHShift;
929 value = (value << kSignExtendWShift) >> kSignExtendWShift;
937 return value << left_shift;
941 template <
typename T>
942 void Simulator::Extract(Instruction* instr) {
943 unsigned lsb = instr->ImmS();
944 T op2 = reg<T>(instr->Rm());
948 T op1 = reg<T>(instr->Rn());
949 result = op2 >> lsb | (op1 << ((
sizeof(T) * 8) - lsb));
951 set_reg<T>(instr->Rd(), result);
955 void Simulator::FPCompare(
double val0,
double val1) {
956 AssertSupportedFPCR();
960 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
961 nzcv().SetRawValue(FPUnorderedFlag);
962 }
else if (val0 < val1) {
963 nzcv().SetRawValue(FPLessThanFlag);
964 }
else if (val0 > val1) {
965 nzcv().SetRawValue(FPGreaterThanFlag);
966 }
else if (val0 == val1) {
967 nzcv().SetRawValue(FPEqualFlag);
971 LogSystemRegister(NZCV);
974 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
975 size_t reg_size,
size_t lane_size) {
976 DCHECK_GE(reg_size, lane_size);
979 if (reg_size != lane_size) {
984 format = kPrintRegAsQVector;
987 format = kPrintRegAsDVector;
996 format |= kPrintReg1Q;
999 format |= kPrintReg1D;
1002 format |= kPrintReg1S;
1005 format |= kPrintReg1H;
1008 format |= kPrintReg1B;
1013 static_assert(kXRegSize == kDRegSize,
"X and D registers must be same size.");
1014 static_assert(kWRegSize == kSRegSize,
"W and S registers must be same size.");
1015 static_assert(kPrintXReg == kPrintReg1D,
1016 "X and D register printing code is shared.");
1017 static_assert(kPrintWReg == kPrintReg1S,
1018 "W and S register printing code is shared.");
1020 return static_cast<PrintRegisterFormat
>(format);
1023 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
1024 VectorFormat vform) {
1029 return kPrintReg16B;
1056 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1057 VectorFormat vform) {
1062 return kPrintReg4SFP;
1064 return kPrintReg2SFP;
1066 return kPrintReg2DFP;
1068 return kPrintReg1DFP;
1071 return kPrintReg1SFP;
1073 return kPrintReg1DFP;
1077 void Simulator::SetBreakpoint(Instruction* location) {
1078 for (
unsigned i = 0;
i < breakpoints_.size();
i++) {
1079 if (breakpoints_.at(
i).location == location) {
1081 "Existing breakpoint at %p was %s\n",
1082 reinterpret_cast<void*>(location),
1083 breakpoints_.at(
i).enabled ?
"disabled" :
"enabled");
1084 breakpoints_.at(
i).enabled = !breakpoints_.at(
i).enabled;
1088 Breakpoint new_breakpoint = {location,
true};
1089 breakpoints_.push_back(new_breakpoint);
1091 "Set a breakpoint at %p\n", reinterpret_cast<void*>(location));
1095 void Simulator::ListBreakpoints() {
1096 PrintF(stream_,
"Breakpoints:\n");
1097 for (
unsigned i = 0;
i < breakpoints_.size();
i++) {
1098 PrintF(stream_,
"%p : %s\n",
1099 reinterpret_cast<void*>(breakpoints_.at(
i).location),
1100 breakpoints_.at(
i).enabled ?
"enabled" :
"disabled");
1105 void Simulator::CheckBreakpoints() {
1106 bool hit_a_breakpoint =
false;
1107 for (
unsigned i = 0;
i < breakpoints_.size();
i++) {
1108 if ((breakpoints_.at(
i).location == pc_) &&
1109 breakpoints_.at(
i).enabled) {
1110 hit_a_breakpoint =
true;
1112 breakpoints_.at(
i).enabled =
false;
1115 if (hit_a_breakpoint) {
1116 PrintF(stream_,
"Hit and disabled a breakpoint at %p.\n",
1117 reinterpret_cast<void*>(pc_));
1123 void Simulator::CheckBreakNext() {
1125 if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) {
1126 SetBreakpoint(pc_->following());
1127 break_on_next_ =
false;
1132 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1133 Instruction* end = start->InstructionAtOffset(count * kInstrSize);
1134 for (Instruction* pc = start; pc < end; pc = pc->following()) {
1135 disassembler_decoder_->Decode(pc);
1139 void Simulator::PrintWrittenRegisters() {
1140 for (
unsigned i = 0;
i < kNumberOfRegisters;
i++) {
1141 if (registers_[
i].WrittenSinceLastLog()) PrintRegister(
i);
1145 void Simulator::PrintWrittenVRegisters() {
1146 for (
unsigned i = 0;
i < kNumberOfVRegisters;
i++) {
1148 if (vregisters_[
i].WrittenSinceLastLog()) PrintVRegister(
i, kPrintReg1Q);
1152 void Simulator::PrintSystemRegisters() {
1153 PrintSystemRegister(NZCV);
1154 PrintSystemRegister(FPCR);
1158 void Simulator::PrintRegisters() {
1159 for (
unsigned i = 0;
i < kNumberOfRegisters;
i++) {
1164 void Simulator::PrintVRegisters() {
1165 for (
unsigned i = 0;
i < kNumberOfVRegisters;
i++) {
1167 PrintVRegister(
i, kPrintReg1Q);
1172 void Simulator::PrintRegister(
unsigned code, Reg31Mode r31mode) {
1173 registers_[code].NotifyRegisterLogged();
1176 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1184 PrintRegisterRawHelper(code, r31mode);
1185 fprintf(stream_,
"\n");
1196 void Simulator::PrintVRegisterRawHelper(
unsigned code,
int bytes,
int lsb) {
1201 fprintf(stream_,
"# %s%5s: %s", clr_vreg_name, VRegNameForCode(code),
1204 int msb = lsb + bytes - 1;
1205 int byte = kQRegSize - 1;
1208 while (byte > msb) {
1209 fprintf(stream_,
" ");
1214 qreg_t rawbits = qreg(code);
1215 fprintf(stream_,
"0x");
1216 while (byte >= lsb) {
1217 fprintf(stream_,
"%02x", rawbits.val[byte]);
1223 fprintf(stream_,
" ");
1226 fprintf(stream_,
"%s", clr_normal);
1237 void Simulator::PrintVRegisterFPHelper(
unsigned code,
1238 unsigned lane_size_in_bytes,
1239 int lane_count,
int rightmost_lane) {
1240 DCHECK((lane_size_in_bytes == kSRegSize) ||
1241 (lane_size_in_bytes == kDRegSize));
1243 unsigned msb = (lane_count + rightmost_lane) * lane_size_in_bytes;
1244 DCHECK_LE(msb, static_cast<unsigned>(kQRegSize));
1252 if ((lane_count == 1) && (rightmost_lane == 0)) {
1253 const char* name = (lane_size_in_bytes == kSRegSize)
1254 ? SRegNameForCode(code)
1255 : DRegNameForCode(code);
1256 fprintf(stream_,
" (%s%s: ", clr_vreg_name, name);
1258 if (msb < (kQRegSize - 1)) {
1259 fprintf(stream_,
" (..., ");
1261 fprintf(stream_,
" (");
1266 const char* separator =
"";
1267 int leftmost_lane = rightmost_lane + lane_count - 1;
1268 for (
int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
1269 double value = (lane_size_in_bytes == kSRegSize)
1270 ? vreg(code).Get<
float>(lane)
1271 : vreg(code).Get<
double>(lane);
1272 fprintf(stream_,
"%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
1276 if (rightmost_lane > 0) {
1277 fprintf(stream_,
", ...");
1279 fprintf(stream_,
")");
1294 void Simulator::PrintRegisterRawHelper(
unsigned code, Reg31Mode r31mode,
1295 int size_in_bytes) {
1301 unsigned padding_chars = (kXRegSize - size_in_bytes) * 2;
1303 const char* name =
"";
1304 const char* suffix =
"";
1305 switch (size_in_bytes) {
1307 name = XRegNameForCode(code, r31mode);
1310 name = WRegNameForCode(code, r31mode);
1313 name = WRegNameForCode(code, r31mode);
1315 padding_chars -= strlen(suffix);
1318 name = WRegNameForCode(code, r31mode);
1320 padding_chars -= strlen(suffix);
1325 fprintf(stream_,
"# %s%5s%s: ", clr_reg_name, name, suffix);
1328 DCHECK_LT(padding_chars, kXRegSize * 2U);
1329 for (
unsigned i = 0;
i < padding_chars;
i++) {
1334 uint64_t bits = reg<uint64_t>(code, r31mode);
1335 bits &= kXRegMask >> ((kXRegSize - size_in_bytes) * 8);
1336 static_assert(
sizeof(bits) == kXRegSize,
1337 "X registers and uint64_t must be the same size.");
1339 int chars = size_in_bytes * 2;
1340 fprintf(stream_,
"%s0x%0*" PRIx64
"%s", clr_reg_value, chars, bits,
1344 void Simulator::PrintVRegister(
unsigned code, PrintRegisterFormat format) {
1345 vregisters_[code].NotifyRegisterLogged();
1347 int lane_size_log2 = format & kPrintRegLaneSizeMask;
1350 if (format & kPrintRegAsQVector) {
1351 reg_size_log2 = kQRegSizeLog2;
1352 }
else if (format & kPrintRegAsDVector) {
1353 reg_size_log2 = kDRegSizeLog2;
1356 reg_size_log2 = lane_size_log2;
1359 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1360 int lane_size = 1 << lane_size_log2;
1369 PrintVRegisterRawHelper(code);
1370 if (format & kPrintRegAsFP) {
1371 PrintVRegisterFPHelper(code, lane_size, lane_count);
1374 fprintf(stream_,
"\n");
1378 void Simulator::PrintSystemRegister(SystemRegister
id) {
1381 fprintf(stream_,
"# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1382 clr_flag_name, clr_flag_value,
1383 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().
V(),
1387 static const char * rmode[] = {
1388 "0b00 (Round to Nearest)",
1389 "0b01 (Round towards Plus Infinity)",
1390 "0b10 (Round towards Minus Infinity)",
1391 "0b11 (Round towards Zero)" 1393 DCHECK(fpcr().RMode() < arraysize(rmode));
1395 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1396 clr_flag_name, clr_flag_value,
1397 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1406 void Simulator::PrintRead(
uintptr_t address,
unsigned reg_code,
1407 PrintRegisterFormat format) {
1408 registers_[reg_code].NotifyRegisterLogged();
1413 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1414 fprintf(stream_,
" <- %s0x%016" PRIxPTR
"%s\n",
1415 clr_memory_address, address, clr_normal);
1418 void Simulator::PrintVRead(
uintptr_t address,
unsigned reg_code,
1419 PrintRegisterFormat format,
unsigned lane) {
1420 vregisters_[reg_code].NotifyRegisterLogged();
1423 PrintVRegisterRawHelper(reg_code);
1424 if (format & kPrintRegAsFP) {
1425 PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
1426 GetPrintRegLaneCount(format), lane);
1428 fprintf(stream_,
" <- %s0x%016" PRIxPTR
"%s\n",
1429 clr_memory_address, address, clr_normal);
1432 void Simulator::PrintWrite(
uintptr_t address,
unsigned reg_code,
1433 PrintRegisterFormat format) {
1434 DCHECK_EQ(GetPrintRegLaneCount(format), 1U);
1438 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
1439 GetPrintRegSizeInBytes(format));
1440 fprintf(stream_,
" -> %s0x%016" PRIxPTR
"%s\n",
1441 clr_memory_address, address, clr_normal);
1444 void Simulator::PrintVWrite(
uintptr_t address,
unsigned reg_code,
1445 PrintRegisterFormat format,
unsigned lane) {
1454 int lane_count = GetPrintRegLaneCount(format);
1455 int lane_size = GetPrintRegLaneSizeInBytes(format);
1456 int reg_size = GetPrintRegSizeInBytes(format);
1457 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1458 if (format & kPrintRegAsFP) {
1459 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1461 fprintf(stream_,
" -> %s0x%016" PRIxPTR
"%s\n",
1462 clr_memory_address, address, clr_normal);
1468 void Simulator::VisitUnimplemented(Instruction* instr) {
1469 fprintf(stream_,
"Unimplemented instruction at %p: 0x%08" PRIx32
"\n",
1470 reinterpret_cast<void*>(instr), instr->InstructionBits());
1475 void Simulator::VisitUnallocated(Instruction* instr) {
1476 fprintf(stream_,
"Unallocated instruction at %p: 0x%08" PRIx32
"\n",
1477 reinterpret_cast<void*>(instr), instr->InstructionBits());
1482 void Simulator::VisitPCRelAddressing(Instruction* instr) {
1483 switch (instr->Mask(PCRelAddressingMask)) {
1485 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
1497 void Simulator::VisitUnconditionalBranch(Instruction* instr) {
1498 switch (instr->Mask(UnconditionalBranchMask)) {
1500 set_lr(instr->following());
1503 set_pc(instr->ImmPCOffsetTarget());
1511 void Simulator::VisitConditionalBranch(Instruction* instr) {
1512 DCHECK(instr->Mask(ConditionalBranchMask) == B_cond);
1513 if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
1514 set_pc(instr->ImmPCOffsetTarget());
1519 void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
1520 Instruction* target = reg<Instruction*>(instr->Rn());
1521 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1523 set_lr(instr->following());
1524 if (instr->Rn() == 31) {
1532 case RET: set_pc(target);
break;
1533 default: UNIMPLEMENTED();
1538 void Simulator::VisitTestBranch(Instruction* instr) {
1539 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
1540 instr->ImmTestBranchBit40();
1541 bool take_branch = ((xreg(instr->Rt()) & (1ULL << bit_pos)) == 0);
1542 switch (instr->Mask(TestBranchMask)) {
1544 case TBNZ: take_branch = !take_branch;
break;
1545 default: UNIMPLEMENTED();
1548 set_pc(instr->ImmPCOffsetTarget());
1553 void Simulator::VisitCompareBranch(Instruction* instr) {
1554 unsigned rt = instr->Rt();
1555 bool take_branch =
false;
1556 switch (instr->Mask(CompareBranchMask)) {
1557 case CBZ_w: take_branch = (wreg(rt) == 0);
break;
1558 case CBZ_x: take_branch = (xreg(rt) == 0);
break;
1559 case CBNZ_w: take_branch = (wreg(rt) != 0);
break;
1560 case CBNZ_x: take_branch = (xreg(rt) != 0);
break;
1561 default: UNIMPLEMENTED();
1564 set_pc(instr->ImmPCOffsetTarget());
1569 template<
typename T>
1570 void Simulator::AddSubHelper(Instruction* instr, T op2) {
1572 static_assert(std::is_unsigned<T>::value,
"operands must be unsigned");
1574 bool set_flags = instr->FlagsUpdate();
1576 Instr operation = instr->Mask(AddSubOpMask);
1578 switch (operation) {
1581 new_val = AddWithCarry<T>(set_flags,
1582 reg<T>(instr->Rn(), instr->RnMode()),
1588 new_val = AddWithCarry<T>(set_flags,
1589 reg<T>(instr->Rn(), instr->RnMode()),
1594 default: UNREACHABLE();
1597 set_reg<T>(instr->Rd(), new_val, instr->RdMode());
1601 void Simulator::VisitAddSubShifted(Instruction* instr) {
1602 Shift shift_type =
static_cast<Shift
>(instr->ShiftDP());
1603 unsigned shift_amount = instr->ImmDPShift();
1605 if (instr->SixtyFourBits()) {
1606 uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1607 AddSubHelper(instr, op2);
1609 uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1610 AddSubHelper(instr, op2);
1615 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1616 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1617 if (instr->SixtyFourBits()) {
1618 AddSubHelper(instr, static_cast<uint64_t>(op2));
1620 AddSubHelper(instr, static_cast<uint32_t>(op2));
1625 void Simulator::VisitAddSubExtended(Instruction* instr) {
1626 Extend ext =
static_cast<Extend
>(instr->ExtendMode());
1627 unsigned left_shift = instr->ImmExtendShift();
1628 if (instr->SixtyFourBits()) {
1629 uint64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
1630 AddSubHelper(instr, op2);
1632 uint32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
1633 AddSubHelper(instr, op2);
1638 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1639 if (instr->SixtyFourBits()) {
1640 AddSubWithCarry<uint64_t>(instr);
1642 AddSubWithCarry<uint32_t>(instr);
1647 void Simulator::VisitLogicalShifted(Instruction* instr) {
1648 Shift shift_type =
static_cast<Shift
>(instr->ShiftDP());
1649 unsigned shift_amount = instr->ImmDPShift();
1651 if (instr->SixtyFourBits()) {
1652 uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1653 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1654 LogicalHelper(instr, op2);
1656 uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1657 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1658 LogicalHelper(instr, op2);
1663 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1664 if (instr->SixtyFourBits()) {
1665 LogicalHelper(instr, static_cast<uint64_t>(instr->ImmLogical()));
1667 LogicalHelper(instr, static_cast<uint32_t>(instr->ImmLogical()));
1672 template<
typename T>
1673 void Simulator::LogicalHelper(Instruction* instr, T op2) {
1674 T op1 = reg<T>(instr->Rn());
1676 bool update_flags =
false;
1680 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1681 case ANDS: update_flags =
true; V8_FALLTHROUGH;
1682 case AND: result = op1 & op2;
break;
1683 case ORR: result = op1 | op2;
break;
1684 case EOR: result = op1 ^ op2;
break;
1690 nzcv().SetN(CalcNFlag(result));
1691 nzcv().SetZ(CalcZFlag(result));
1694 LogSystemRegister(NZCV);
1697 set_reg<T>(instr->Rd(), result, instr->RdMode());
1701 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1702 if (instr->SixtyFourBits()) {
1703 ConditionalCompareHelper(instr, static_cast<uint64_t>(xreg(instr->Rm())));
1705 ConditionalCompareHelper(instr, static_cast<uint32_t>(wreg(instr->Rm())));
1710 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1711 if (instr->SixtyFourBits()) {
1712 ConditionalCompareHelper(instr, static_cast<uint64_t>(instr->ImmCondCmp()));
1714 ConditionalCompareHelper(instr, static_cast<uint32_t>(instr->ImmCondCmp()));
1719 template<
typename T>
1720 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
1722 static_assert(std::is_unsigned<T>::value,
"operands must be unsigned");
1724 T op1 = reg<T>(instr->Rn());
1726 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1729 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1730 AddWithCarry<T>(
true, op1, ~op2, 1);
1732 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN);
1733 AddWithCarry<T>(
true, op1, op2, 0);
1737 nzcv().SetFlags(instr->Nzcv());
1738 LogSystemRegister(NZCV);
1743 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
1744 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1745 LoadStoreHelper(instr, offset, Offset);
1749 void Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
1750 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1754 void Simulator::VisitLoadStorePreIndex(Instruction* instr) {
1755 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1759 void Simulator::VisitLoadStorePostIndex(Instruction* instr) {
1760 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1764 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
1765 Extend ext =
static_cast<Extend
>(instr->ExtendMode());
1766 DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1767 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1769 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount);
1770 LoadStoreHelper(instr, offset, Offset);
1774 void Simulator::LoadStoreHelper(Instruction* instr,
1776 AddrMode addrmode) {
1777 unsigned srcdst = instr->Rt();
1778 unsigned addr_reg = instr->Rn();
1779 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1783 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1784 if (instr->IsLoad()) {
1785 local_monitor_.NotifyLoad();
1787 local_monitor_.NotifyStore();
1788 global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
1799 if (instr->IsStore()) {
1800 LoadStoreWriteBack(addr_reg, offset, addrmode);
1807 LoadStoreOp op =
static_cast<LoadStoreOp
>(instr->Mask(LoadStoreMask));
1811 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address));
break;
1812 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address));
break;
1813 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address));
break;
1814 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address));
break;
1815 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address));
break;
1816 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address));
break;
1817 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address));
break;
1818 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address));
break;
1819 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address));
break;
1821 set_breg_no_log(srcdst, MemoryRead<uint8_t>(address));
1824 set_hreg_no_log(srcdst, MemoryRead<uint16_t>(address));
1826 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address));
break;
1827 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address));
break;
1829 set_qreg_no_log(srcdst, MemoryRead<qreg_t>(address));
1832 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst));
break;
1833 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst));
break;
1834 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst));
break;
1835 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst));
break;
1837 MemoryWrite<uint8_t>(address, breg(srcdst));
1840 MemoryWrite<uint16_t>(address, hreg(srcdst));
1842 case STR_s: MemoryWrite<float>(address, sreg(srcdst));
break;
1843 case STR_d: MemoryWrite<double>(address, dreg(srcdst));
break;
1845 MemoryWrite<qreg_t>(address, qreg(srcdst));
1848 default: UNIMPLEMENTED();
1853 unsigned access_size = 1 << instr->SizeLS();
1854 if (instr->IsLoad()) {
1855 if ((op == LDR_s) || (op == LDR_d)) {
1856 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1857 }
else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1858 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1860 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1863 if ((op == STR_s) || (op == STR_d)) {
1864 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1865 }
else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1866 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1868 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1876 if (instr->IsLoad()) {
1881 LoadStoreWriteBack(addr_reg, offset, addrmode);
1886 CheckMemoryAccess(address, stack);
1890 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1891 LoadStorePairHelper(instr, Offset);
1895 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1896 LoadStorePairHelper(instr, PreIndex);
1900 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1901 LoadStorePairHelper(instr, PostIndex);
1905 void Simulator::LoadStorePairHelper(Instruction* instr,
1906 AddrMode addrmode) {
1907 unsigned rt = instr->Rt();
1908 unsigned rt2 = instr->Rt2();
1909 unsigned addr_reg = instr->Rn();
1910 size_t access_size = 1ULL << instr->SizeLSPair();
1911 int64_t offset = instr->ImmLSPair() * access_size;
1912 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
1913 uintptr_t address2 = address + access_size;
1917 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
1918 if (instr->IsLoad()) {
1919 local_monitor_.NotifyLoad();
1921 local_monitor_.NotifyStore();
1922 global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
1933 if (instr->IsStore()) {
1934 LoadStoreWriteBack(addr_reg, offset, addrmode);
1941 LoadStorePairOp op =
1942 static_cast<LoadStorePairOp
>(instr->Mask(LoadStorePairMask));
1945 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1951 DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1952 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1953 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
1957 DCHECK_EQ(access_size, static_cast<unsigned>(kSRegSize));
1958 set_sreg_no_log(rt, MemoryRead<float>(address));
1959 set_sreg_no_log(rt2, MemoryRead<float>(address2));
1963 DCHECK_EQ(access_size, static_cast<unsigned>(kXRegSize));
1964 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1965 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
1969 DCHECK_EQ(access_size, static_cast<unsigned>(kDRegSize));
1970 set_dreg_no_log(rt, MemoryRead<double>(address));
1971 set_dreg_no_log(rt2, MemoryRead<double>(address2));
1975 DCHECK_EQ(access_size, static_cast<unsigned>(kQRegSize));
1976 set_qreg(rt, MemoryRead<qreg_t>(address), NoRegLog);
1977 set_qreg(rt2, MemoryRead<qreg_t>(address2), NoRegLog);
1981 DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1982 set_xreg_no_log(rt, MemoryRead<int32_t>(address));
1983 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
1987 DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1988 MemoryWrite<uint32_t>(address, wreg(rt));
1989 MemoryWrite<uint32_t>(address2, wreg(rt2));
1993 DCHECK_EQ(access_size, static_cast<unsigned>(kSRegSize));
1994 MemoryWrite<float>(address, sreg(rt));
1995 MemoryWrite<float>(address2, sreg(rt2));
1999 DCHECK_EQ(access_size, static_cast<unsigned>(kXRegSize));
2000 MemoryWrite<uint64_t>(address, xreg(rt));
2001 MemoryWrite<uint64_t>(address2, xreg(rt2));
2005 DCHECK_EQ(access_size, static_cast<unsigned>(kDRegSize));
2006 MemoryWrite<double>(address, dreg(rt));
2007 MemoryWrite<double>(address2, dreg(rt2));
2011 DCHECK_EQ(access_size, static_cast<unsigned>(kQRegSize));
2012 MemoryWrite<qreg_t>(address, qreg(rt));
2013 MemoryWrite<qreg_t>(address2, qreg(rt2));
2016 default: UNREACHABLE();
2021 if (instr->IsLoad()) {
2022 if ((op == LDP_s) || (op == LDP_d)) {
2023 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
2024 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2025 }
else if (op == LDP_q) {
2026 LogVRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2027 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2029 LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2030 LogRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2033 if ((op == STP_s) || (op == STP_d)) {
2034 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
2035 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2036 }
else if (op == STP_q) {
2037 LogVWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2038 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2040 LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2041 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2049 if (instr->IsLoad()) {
2054 LoadStoreWriteBack(addr_reg, offset, addrmode);
2059 CheckMemoryAccess(address, stack);
2063 void Simulator::VisitLoadLiteral(Instruction* instr) {
2064 uintptr_t address = instr->LiteralAddress();
2065 unsigned rt = instr->Rt();
2068 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
2069 local_monitor_.NotifyLoad();
2072 switch (instr->Mask(LoadLiteralMask)) {
2076 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2077 LogRead(address, rt, kPrintWReg);
2080 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2081 LogRead(address, rt, kPrintXReg);
2084 set_sreg_no_log(rt, MemoryRead<float>(address));
2085 LogVRead(address, rt, kPrintSReg);
2088 set_dreg_no_log(rt, MemoryRead<double>(address));
2089 LogVRead(address, rt, kPrintDReg);
2091 default: UNREACHABLE();
2097 AddrMode addrmode) {
2098 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
2099 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
2100 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
2104 FATAL(
"ALIGNMENT EXCEPTION");
2107 if ((addrmode == Offset) || (addrmode == PreIndex)) {
2115 void Simulator::LoadStoreWriteBack(
unsigned addr_reg,
2117 AddrMode addrmode) {
2118 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2119 DCHECK_NE(offset, 0);
2120 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
2121 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
2125 Simulator::TransactionSize Simulator::get_transaction_size(
unsigned size) {
2128 return TransactionSize::None;
2130 return TransactionSize::Byte;
2132 return TransactionSize::HalfWord;
2134 return TransactionSize::Word;
2136 return TransactionSize::DoubleWord;
2140 return TransactionSize::None;
2143 void Simulator::VisitLoadStoreAcquireRelease(Instruction* instr) {
2144 unsigned rt = instr->Rt();
2145 unsigned rn = instr->Rn();
2146 LoadStoreAcquireReleaseOp op =
static_cast<LoadStoreAcquireReleaseOp
>(
2147 instr->Mask(LoadStoreAcquireReleaseMask));
2148 int32_t is_acquire_release = instr->LoadStoreXAcquireRelease();
2149 int32_t is_exclusive = (instr->LoadStoreXNotExclusive() == 0);
2150 int32_t is_load = instr->LoadStoreXLoad();
2151 int32_t is_pair = instr->LoadStoreXPair();
2152 USE(is_acquire_release);
2154 DCHECK_NE(is_acquire_release, 0);
2155 DCHECK_EQ(is_pair, 0);
2156 unsigned access_size = 1 << instr->LoadStoreXSizeLog2();
2157 uintptr_t address = LoadStoreAddress(rn, 0, AddrMode::Offset);
2158 DCHECK_EQ(address % access_size, 0);
2159 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
2162 local_monitor_.NotifyLoadExcl(address, get_transaction_size(access_size));
2163 global_monitor_.Pointer()->NotifyLoadExcl_Locked(
2164 address, &global_monitor_processor_);
2166 local_monitor_.NotifyLoad();
2171 set_wreg_no_log(rt, MemoryRead<uint8_t>(address));
2175 set_wreg_no_log(rt, MemoryRead<uint16_t>(address));
2179 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2183 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2188 LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2191 unsigned rs = instr->Rs();
2194 if (local_monitor_.NotifyStoreExcl(address,
2195 get_transaction_size(access_size)) &&
2196 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
2197 address, &global_monitor_processor_)) {
2200 MemoryWrite<uint8_t>(address, wreg(rt));
2203 MemoryWrite<uint16_t>(address, wreg(rt));
2206 MemoryWrite<uint32_t>(address, wreg(rt));
2209 MemoryWrite<uint64_t>(address, xreg(rt));
2214 LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2220 local_monitor_.NotifyStore();
2221 global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
2224 MemoryWrite<uint8_t>(address, wreg(rt));
2227 MemoryWrite<uint16_t>(address, wreg(rt));
2230 MemoryWrite<uint32_t>(address, wreg(rt));
2233 MemoryWrite<uint64_t>(address, xreg(rt));
2243 if ((address >= stack_limit_) && (address < stack)) {
2244 fprintf(stream_,
"ACCESS BELOW STACK POINTER:\n");
2245 fprintf(stream_,
" sp is here: 0x%016" PRIx64
"\n",
2246 static_cast<uint64_t>(stack));
2247 fprintf(stream_,
" access was here: 0x%016" PRIx64
"\n",
2248 static_cast<uint64_t>(address));
2249 fprintf(stream_,
" stack limit is here: 0x%016" PRIx64
"\n",
2250 static_cast<uint64_t>(stack_limit_));
2251 fprintf(stream_,
"\n");
2252 FATAL(
"ACCESS BELOW STACK POINTER");
2257 void Simulator::VisitMoveWideImmediate(Instruction* instr) {
2258 MoveWideImmediateOp mov_op =
2259 static_cast<MoveWideImmediateOp
>(instr->Mask(MoveWideImmediateMask));
2262 bool is_64_bits = instr->SixtyFourBits() == 1;
2264 DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2));
2267 int64_t shift = instr->ShiftMoveWide() * 16;
2268 int64_t shifted_imm16 =
static_cast<int64_t>(instr->ImmMoveWide()) << shift;
2274 new_xn_val = ~shifted_imm16;
2275 if (!is_64_bits) new_xn_val &= kWRegMask;
2280 unsigned reg_code = instr->Rd();
2281 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
2283 new_xn_val = (prev_xn_val & ~(0xFFFFL << shift)) | shifted_imm16;
2288 new_xn_val = shifted_imm16;
2296 set_xreg(instr->Rd(), new_xn_val);
2300 void Simulator::VisitConditionalSelect(Instruction* instr) {
2301 uint64_t new_val = xreg(instr->Rn());
2302 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
2303 new_val = xreg(instr->Rm());
2304 switch (instr->Mask(ConditionalSelectMask)) {
2318 new_val = (uint64_t)(-(
int64_t)new_val);
2320 default: UNIMPLEMENTED();
2323 if (instr->SixtyFourBits()) {
2324 set_xreg(instr->Rd(), new_val);
2326 set_wreg(instr->Rd(),
static_cast<uint32_t>(new_val));
2331 void Simulator::VisitDataProcessing1Source(Instruction* instr) {
2332 unsigned dst = instr->Rd();
2333 unsigned src = instr->Rn();
2335 switch (instr->Mask(DataProcessing1SourceMask)) {
2337 set_wreg(dst, base::bits::ReverseBits(wreg(src)));
2340 set_xreg(dst, base::bits::ReverseBits(xreg(src)));
2343 set_wreg(dst, ReverseBytes(wreg(src), 1));
2346 set_xreg(dst, ReverseBytes(xreg(src), 1));
2349 set_wreg(dst, ReverseBytes(wreg(src), 2));
2352 set_xreg(dst, ReverseBytes(xreg(src), 2));
2355 set_xreg(dst, ReverseBytes(xreg(src), 3));
2357 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits));
2359 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits));
2362 set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits));
2366 set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits));
2369 default: UNIMPLEMENTED();
2374 template <
typename T>
2375 void Simulator::DataProcessing2Source(Instruction* instr) {
2376 Shift shift_op = NO_SHIFT;
2378 switch (instr->Mask(DataProcessing2SourceMask)) {
2381 T rn = reg<T>(instr->Rn());
2382 T rm = reg<T>(instr->Rm());
2383 if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) {
2384 result = std::numeric_limits<T>::min();
2385 }
else if (rm == 0) {
2395 typedef typename std::make_unsigned<T>::type unsignedT;
2396 unsignedT rn =
static_cast<unsignedT
>(reg<T>(instr->Rn()));
2397 unsignedT rm =
static_cast<unsignedT
>(reg<T>(instr->Rm()));
2407 case LSLV_x: shift_op = LSL;
break;
2409 case LSRV_x: shift_op = LSR;
break;
2411 case ASRV_x: shift_op = ASR;
break;
2413 case RORV_x: shift_op = ROR;
break;
2414 default: UNIMPLEMENTED();
2417 if (shift_op != NO_SHIFT) {
2420 unsigned shift = wreg(instr->Rm());
2421 if (
sizeof(T) == kWRegSize) {
2422 shift &= kShiftAmountWRegMask;
2424 shift &= kShiftAmountXRegMask;
2426 result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift);
2428 set_reg<T>(instr->Rd(), result);
2432 void Simulator::VisitDataProcessing2Source(Instruction* instr) {
2433 if (instr->SixtyFourBits()) {
2434 DataProcessing2Source<int64_t>(instr);
2436 DataProcessing2Source<int32_t>(instr);
2445 uint64_t u0, v0, w0;
2448 u0 = u & 0xFFFFFFFFLL;
2450 v0 = v & 0xFFFFFFFFLL;
2454 t = u1 * v0 + (w0 >> 32);
2455 w1 = t & 0xFFFFFFFFLL;
2459 return u1 * v1 + w2 + (w1 >> 32);
2463 void Simulator::VisitDataProcessing3Source(Instruction* instr) {
2466 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
2467 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
2468 int64_t rn_s32 = reg<int32_t>(instr->Rn());
2469 int64_t rm_s32 = reg<int32_t>(instr->Rm());
2470 switch (instr->Mask(DataProcessing3SourceMask)) {
2473 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
2477 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
2479 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32);
break;
2480 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32);
break;
2481 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32);
break;
2482 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32);
break;
2484 DCHECK_EQ(instr->Ra(), kZeroRegCode);
2485 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
2487 default: UNIMPLEMENTED();
2490 if (instr->SixtyFourBits()) {
2491 set_xreg(instr->Rd(), result);
2493 set_wreg(instr->Rd(),
static_cast<int32_t
>(result));
2498 template <
typename T>
2499 void Simulator::BitfieldHelper(Instruction* instr) {
2500 typedef typename std::make_unsigned<T>::type unsignedT;
2501 T reg_size =
sizeof(T) * 8;
2502 T R = instr->ImmR();
2503 T S = instr->ImmS();
2507 mask = diff < reg_size - 1 ? (
static_cast<T
>(1) << (diff + 1)) - 1
2508 : static_cast<T>(-1);
2510 uint64_t umask = ((1LL << (S + 1)) - 1);
2511 umask = (umask >> R) | (umask << (reg_size - R));
2512 mask =
static_cast<T
>(umask);
2519 bool inzero =
false;
2520 bool extend =
false;
2521 switch (instr->Mask(BitfieldMask)) {
2538 T dst = inzero ? 0 : reg<T>(instr->Rd());
2539 T src = reg<T>(instr->Rn());
2541 T result = (
static_cast<unsignedT
>(src) >> R) | (src << (reg_size - R));
2543 T topbits_preshift = (
static_cast<T
>(1) << (reg_size - diff - 1)) - 1;
2544 T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0)
2548 result = signbits | (result & mask) | (dst & ~mask);
2550 set_reg<T>(instr->Rd(), result);
2554 void Simulator::VisitBitfield(Instruction* instr) {
2555 if (instr->SixtyFourBits()) {
2556 BitfieldHelper<int64_t>(instr);
2558 BitfieldHelper<int32_t>(instr);
2563 void Simulator::VisitExtract(Instruction* instr) {
2564 if (instr->SixtyFourBits()) {
2565 Extract<uint64_t>(instr);
2567 Extract<uint32_t>(instr);
2572 void Simulator::VisitFPImmediate(Instruction* instr) {
2573 AssertSupportedFPCR();
2575 unsigned dest = instr->Rd();
2576 switch (instr->Mask(FPImmediateMask)) {
2577 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32());
break;
2578 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64());
break;
2579 default: UNREACHABLE();
2584 void Simulator::VisitFPIntegerConvert(Instruction* instr) {
2585 AssertSupportedFPCR();
2587 unsigned dst = instr->Rd();
2588 unsigned src = instr->Rn();
2590 FPRounding round = fpcr().RMode();
2592 switch (instr->Mask(FPIntegerConvertMask)) {
2593 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway));
break;
2594 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway));
break;
2595 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway));
break;
2596 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway));
break;
2597 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway));
break;
2598 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway));
break;
2599 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway));
break;
2600 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway));
break;
2602 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
2605 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
2608 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
2611 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
2614 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
2617 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
2620 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
2623 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
2625 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven));
break;
2626 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven));
break;
2627 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven));
break;
2628 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven));
break;
2629 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven));
break;
2630 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven));
break;
2631 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven));
break;
2632 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven));
break;
2633 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero));
break;
2634 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero));
break;
2635 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero));
break;
2636 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero));
break;
2637 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero));
break;
2638 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero));
break;
2639 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero));
break;
2640 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero));
break;
2641 case FMOV_ws: set_wreg(dst, sreg_bits(src));
break;
2642 case FMOV_xd: set_xreg(dst, dreg_bits(src));
break;
2643 case FMOV_sw: set_sreg_bits(dst, wreg(src));
break;
2644 case FMOV_dx: set_dreg_bits(dst, xreg(src));
break;
2648 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round));
break;
2649 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round));
break;
2650 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round));
break;
2652 set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round));
2655 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round));
break;
2656 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round));
break;
2657 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round));
break;
2659 set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round));
2663 default: UNREACHABLE();
2668 void Simulator::VisitFPFixedPointConvert(Instruction* instr) {
2669 AssertSupportedFPCR();
2671 unsigned dst = instr->Rd();
2672 unsigned src = instr->Rn();
2673 int fbits = 64 - instr->FPScale();
2675 FPRounding round = fpcr().RMode();
2677 switch (instr->Mask(FPFixedPointConvertMask)) {
2680 case SCVTF_dx_fixed:
2681 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2683 case SCVTF_dw_fixed:
2684 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2686 case UCVTF_dx_fixed:
2687 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2689 case UCVTF_dw_fixed: {
2691 UFixedToDouble(reg<uint32_t>(src), fbits, round));
2694 case SCVTF_sx_fixed:
2695 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2697 case SCVTF_sw_fixed:
2698 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2700 case UCVTF_sx_fixed:
2701 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2703 case UCVTF_sw_fixed: {
2705 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2708 default: UNREACHABLE();
2713 void Simulator::VisitFPCompare(Instruction* instr) {
2714 AssertSupportedFPCR();
2716 switch (instr->Mask(FPCompareMask)) {
2718 FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2721 FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2724 FPCompare(sreg(instr->Rn()), 0.0f);
2727 FPCompare(dreg(instr->Rn()), 0.0);
2729 default: UNIMPLEMENTED();
2734 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2735 AssertSupportedFPCR();
2737 switch (instr->Mask(FPConditionalCompareMask)) {
2739 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2740 FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2742 nzcv().SetFlags(instr->Nzcv());
2743 LogSystemRegister(NZCV);
2747 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2748 FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2751 nzcv().SetFlags(instr->Nzcv());
2752 LogSystemRegister(NZCV);
2756 default: UNIMPLEMENTED();
2761 void Simulator::VisitFPConditionalSelect(Instruction* instr) {
2762 AssertSupportedFPCR();
2765 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2766 selected = instr->Rn();
2768 selected = instr->Rm();
2771 switch (instr->Mask(FPConditionalSelectMask)) {
2772 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected));
break;
2773 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected));
break;
2774 default: UNIMPLEMENTED();
2779 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2780 AssertSupportedFPCR();
2782 FPRounding fpcr_rounding =
static_cast<FPRounding
>(fpcr().RMode());
2783 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2784 SimVRegister& rd = vreg(instr->Rd());
2785 SimVRegister& rn = vreg(instr->Rn());
2786 bool inexact_exception =
false;
2788 unsigned fd = instr->Rd();
2789 unsigned fn = instr->Rn();
2791 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2793 set_sreg(fd, sreg(fn));
2796 set_dreg(fd, dreg(fn));
2800 fabs_(vform, vreg(fd), vreg(fn));
2802 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2806 fneg(vform, vreg(fd), vreg(fn));
2808 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2811 set_dreg(fd, FPToDouble(sreg(fn)));
2814 set_sreg(fd, FPToFloat(dreg(fn), FPTieEven));
2817 set_hreg(fd, FPToFloat16(sreg(fn), FPTieEven));
2820 set_sreg(fd, FPToFloat(hreg(fn)));
2823 set_dreg(fd, FPToDouble(FPToFloat(hreg(fn))));
2826 set_hreg(fd, FPToFloat16(dreg(fn), FPTieEven));
2830 fsqrt(vform, rd, rn);
2832 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2839 inexact_exception =
true;
2843 fpcr_rounding = FPTieAway;
2847 fpcr_rounding = FPNegativeInfinity;
2851 fpcr_rounding = FPTieEven;
2855 fpcr_rounding = FPPositiveInfinity;
2859 fpcr_rounding = FPZero;
2866 frint(vform, rd, rn, fpcr_rounding, inexact_exception);
2868 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2871 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2872 AssertSupportedFPCR();
2874 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2875 SimVRegister& rd = vreg(instr->Rd());
2876 SimVRegister& rn = vreg(instr->Rn());
2877 SimVRegister& rm = vreg(instr->Rm());
2879 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2882 fadd(vform, rd, rn, rm);
2886 fsub(vform, rd, rn, rm);
2890 fmul(vform, rd, rn, rm);
2894 fnmul(vform, rd, rn, rm);
2898 fdiv(vform, rd, rn, rm);
2902 fmax(vform, rd, rn, rm);
2906 fmin(vform, rd, rn, rm);
2910 fmaxnm(vform, rd, rn, rm);
2914 fminnm(vform, rd, rn, rm);
2920 LogVRegister(instr->Rd(), GetPrintRegisterFormatFP(vform));
2923 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2924 AssertSupportedFPCR();
2926 unsigned fd = instr->Rd();
2927 unsigned fn = instr->Rn();
2928 unsigned fm = instr->Rm();
2929 unsigned fa = instr->Ra();
2931 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2934 set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm)));
2937 set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm)));
2940 set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm)));
2943 set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm)));
2947 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2950 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2953 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2956 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2963 bool Simulator::FPProcessNaNs(Instruction* instr) {
2964 unsigned fd = instr->Rd();
2965 unsigned fn = instr->Rn();
2966 unsigned fm = instr->Rm();
2969 if (instr->Mask(FP64) == FP64) {
2970 double result = FPProcessNaNs(dreg(fn), dreg(fm));
2971 if (std::isnan(result)) {
2972 set_dreg(fd, result);
2976 float result = FPProcessNaNs(sreg(fn), sreg(fm));
2977 if (std::isnan(result)) {
2978 set_sreg(fd, result);
2987 void Simulator::VisitSystem(Instruction* instr) {
2991 if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2992 switch (instr->Mask(SystemSysRegMask)) {
2994 switch (instr->ImmSystemRegister()) {
2995 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue());
break;
2996 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue());
break;
2997 default: UNIMPLEMENTED();
3002 switch (instr->ImmSystemRegister()) {
3004 nzcv().SetRawValue(wreg(instr->Rt()));
3005 LogSystemRegister(NZCV);
3008 fpcr().SetRawValue(wreg(instr->Rt()));
3009 LogSystemRegister(FPCR);
3011 default: UNIMPLEMENTED();
3016 }
else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3017 DCHECK(instr->Mask(SystemHintMask) == HINT);
3018 switch (instr->ImmHint()) {
3022 default: UNIMPLEMENTED();
3024 }
else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3025 #if defined(V8_OS_WIN) 3028 __sync_synchronize();
3036 bool Simulator::GetValue(
const char* desc,
int64_t* value) {
3037 int regnum = CodeFromName(desc);
3039 unsigned code = regnum;
3040 if (code == kZeroRegCode) {
3044 }
else if (code == kSPRegInternalCode) {
3048 if (desc[0] ==
'w') {
3049 *value = wreg(code, Reg31IsStackPointer);
3051 *value = xreg(code, Reg31IsStackPointer);
3054 }
else if (strncmp(desc,
"0x", 2) == 0) {
3055 return SScanF(desc + 2,
"%" SCNx64,
3056 reinterpret_cast<uint64_t*>(value)) == 1;
3058 return SScanF(desc,
"%" SCNu64,
3059 reinterpret_cast<uint64_t*>(value)) == 1;
3064 bool Simulator::PrintValue(
const char* desc) {
3065 if (strcmp(desc,
"sp") == 0) {
3066 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3067 PrintF(stream_,
"%s sp:%s 0x%016" PRIx64
"%s\n", clr_reg_name,
3068 clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3070 }
else if (strcmp(desc,
"wsp") == 0) {
3071 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3072 PrintF(stream_,
"%s wsp:%s 0x%08" PRIx32
"%s\n", clr_reg_name,
3073 clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3077 int i = CodeFromName(desc);
3078 static_assert(kNumberOfRegisters == kNumberOfVRegisters,
3079 "Must be same number of Registers as VRegisters.");
3080 if (
i < 0 || static_cast<unsigned>(
i) >= kNumberOfVRegisters)
return false;
3082 if (desc[0] ==
'v') {
3083 PrintF(stream_,
"%s %s:%s 0x%016" PRIx64
"%s (%s%s:%s %g%s %s:%s %g%s)\n",
3084 clr_vreg_name, VRegNameForCode(
i), clr_vreg_value,
3085 bit_cast<uint64_t>(dreg(
i)), clr_normal, clr_vreg_name,
3086 DRegNameForCode(
i), clr_vreg_value, dreg(
i), clr_vreg_name,
3087 SRegNameForCode(
i), clr_vreg_value, sreg(
i), clr_normal);
3089 }
else if (desc[0] ==
'd') {
3090 PrintF(stream_,
"%s %s:%s %g%s\n", clr_vreg_name, DRegNameForCode(
i),
3091 clr_vreg_value, dreg(
i), clr_normal);
3093 }
else if (desc[0] ==
's') {
3094 PrintF(stream_,
"%s %s:%s %g%s\n", clr_vreg_name, SRegNameForCode(
i),
3095 clr_vreg_value, sreg(
i), clr_normal);
3097 }
else if (desc[0] ==
'w') {
3098 PrintF(stream_,
"%s %s:%s 0x%08" PRIx32
"%s\n",
3099 clr_reg_name, WRegNameForCode(
i), clr_reg_value, wreg(
i), clr_normal);
3104 PrintF(stream_,
"%s %s:%s 0x%016" PRIx64
"%s\n",
3105 clr_reg_name, XRegNameForCode(
i), clr_reg_value, xreg(
i), clr_normal);
3111 void Simulator::Debug() {
3112 #define COMMAND_SIZE 63 3113 #define ARG_SIZE 255 3116 #define XSTR(a) STR(a) 3118 char cmd[COMMAND_SIZE + 1];
3119 char arg1[ARG_SIZE + 1];
3120 char arg2[ARG_SIZE + 1];
3121 char* argv[3] = { cmd, arg1, arg2 };
3124 cmd[COMMAND_SIZE] = 0;
3129 bool cleared_log_disasm_bit =
false;
3133 PrintInstructionsAt(pc_, 1);
3135 char* line = ReadLine(
"sim> ");
3136 if (line ==
nullptr) {
3140 char* last_input = last_debugger_input();
3141 if (strcmp(line,
"\n") == 0 && (last_input !=
nullptr)) {
3146 set_last_debugger_input(line);
3151 int argc = SScanF(line,
3152 "%" XSTR(COMMAND_SIZE)
"s " 3153 "%" XSTR(ARG_SIZE)
"s " 3154 "%" XSTR(ARG_SIZE)
"s",
3158 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
3163 pc_modified_ =
false;
3166 ExecuteInstruction();
3168 int64_t number_of_instructions_to_execute = 1;
3169 GetValue(arg1, &number_of_instructions_to_execute);
3171 set_log_parameters(log_parameters() | LOG_DISASM);
3172 while (number_of_instructions_to_execute-- > 0) {
3173 ExecuteInstruction();
3175 set_log_parameters(log_parameters() & ~LOG_DISASM);
3182 pc_modified_ =
true;
3185 }
else if ((strcmp(cmd,
"next") == 0) || (strcmp(cmd,
"n") == 0)) {
3187 break_on_next_ =
true;
3192 }
else if ((strcmp(cmd,
"continue") == 0) ||
3193 (strcmp(cmd,
"cont") == 0) ||
3194 (strcmp(cmd,
"c") == 0)) {
3199 }
else if (strcmp(cmd,
"disassemble") == 0 ||
3200 strcmp(cmd,
"disasm") == 0 ||
3201 strcmp(cmd,
"di") == 0) {
3202 int64_t n_of_instrs_to_disasm = 10;
3205 GetValue(arg1, &n_of_instrs_to_disasm);
3208 GetValue(arg2, &address);
3212 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3213 n_of_instrs_to_disasm);
3217 }
else if ((strcmp(cmd,
"print") == 0) || (strcmp(cmd,
"p") == 0)) {
3219 if (strcmp(arg1,
"all") == 0) {
3223 if (!PrintValue(arg1)) {
3224 PrintF(
"%s unrecognized\n", arg1);
3229 "print <register>\n" 3230 " Print the content of a register. (alias 'p')\n" 3231 " 'print all' will print all registers.\n" 3232 " Use 'printobject' to get more details about the value.\n");
3236 }
else if ((strcmp(cmd,
"printobject") == 0) ||
3237 (strcmp(cmd,
"po") == 0)) {
3241 if (GetValue(arg1, &value)) {
3242 Object* obj =
reinterpret_cast<Object*
>(value);
3243 os << arg1 <<
": \n";
3248 os << Brief(obj) <<
"\n";
3251 os << arg1 <<
" unrecognized\n";
3254 PrintF(
"printobject <value>\n" 3255 "printobject <register>\n" 3256 " Print details about the value. (alias 'po')\n");
3260 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
3265 if (strcmp(cmd,
"stack") == 0) {
3266 cur =
reinterpret_cast<int64_t*
>(sp());
3270 if (!GetValue(arg1, &value)) {
3271 PrintF(
"%s unrecognized\n", arg1);
3274 cur =
reinterpret_cast<int64_t*
>(value);
3279 if (argc == next_arg) {
3281 }
else if (argc == next_arg + 1) {
3282 if (!GetValue(argv[next_arg], &words)) {
3283 PrintF(
"%s unrecognized\n", argv[next_arg]);
3284 PrintF(
"Printing 10 double words by default");
3293 PrintF(
" 0x%016" PRIx64
": 0x%016" PRIx64
" %10" PRId64,
3294 reinterpret_cast<uint64_t>(cur), *cur, *cur);
3295 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
3297 Heap* current_heap = isolate_->heap();
3298 if (((value & 1) == 0) || current_heap->Contains(obj)) {
3300 if ((value & kSmiTagMask) == 0) {
3301 DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
3302 int32_t untagged = (value >> kSmiShift) & 0xFFFFFFFF;
3303 PrintF(
"smi %" PRId32, untagged);
3314 }
else if (strcmp(cmd,
"trace") == 0 || strcmp(cmd,
"t") == 0) {
3315 if ((log_parameters() & (LOG_DISASM | LOG_REGS)) !=
3316 (LOG_DISASM | LOG_REGS)) {
3317 PrintF(
"Enabling disassembly and registers tracing\n");
3318 set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS);
3320 PrintF(
"Disabling disassembly and registers tracing\n");
3321 set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS));
3325 }
else if (strcmp(cmd,
"break") == 0 || strcmp(cmd,
"b") == 0) {
3328 if (GetValue(arg1, &value)) {
3329 SetBreakpoint(reinterpret_cast<Instruction*>(value));
3331 PrintF(
"%s unrecognized\n", arg1);
3335 PrintF(
"Use `break <address>` to set or disable a breakpoint\n");
3339 }
else if (strcmp(cmd,
"gdb") == 0) {
3340 PrintF(
"Relinquishing control to gdb.\n");
3341 base::OS::DebugBreak();
3342 PrintF(
"Regaining control from gdb.\n");
3345 }
else if (strcmp(cmd,
"sysregs") == 0) {
3346 PrintSystemRegisters();
3349 }
else if (strcmp(cmd,
"help") == 0 || strcmp(cmd,
"h") == 0) {
3353 " Step <n> instructions.\n" 3355 " Continue execution until a BL instruction is reached.\n" 3356 " At this point a breakpoint is set just after this BL.\n" 3357 " Then execution is resumed. It will probably later hit the\n" 3358 " breakpoint just set.\n" 3359 "continue / cont / c\n" 3360 " Continue execution from here.\n" 3361 "disassemble / disasm / di\n" 3362 " disassemble <n> <address>\n" 3363 " Disassemble <n> instructions from current <address>.\n" 3364 " By default <n> is 20 and <address> is the current pc.\n" 3366 " print <register>\n" 3367 " Print the content of a register.\n" 3368 " 'print all' will print all registers.\n" 3369 " Use 'printobject' to get more details about the value.\n" 3370 "printobject / po\n" 3371 " printobject <value>\n" 3372 " printobject <register>\n" 3373 " Print details about the value.\n" 3375 " stack [<words>]\n" 3376 " Dump stack content, default dump 10 words\n" 3378 " mem <address> [<words>]\n" 3379 " Dump memory content, default dump 10 words\n" 3381 " Toggle disassembly and register tracing\n" 3383 " break : list all breakpoints\n" 3384 " break <address> : set / enable / disable a breakpoint.\n" 3388 " Print all system registers (including NZCV).\n");
3390 PrintF(
"Unknown command: %s\n", cmd);
3391 PrintF(
"Use 'help' for more information.\n");
3394 if (cleared_log_disasm_bit ==
true) {
3395 set_log_parameters(log_parameters_ | LOG_DISASM);
3401 void Simulator::VisitException(Instruction* instr) {
3402 switch (instr->Mask(ExceptionMask)) {
3404 if (instr->ImmException() == kImmExceptionIsDebug) {
3410 pc_->InstructionAtOffset(kDebugCodeOffset),
3413 pc_->InstructionAtOffset(kDebugParamsOffset),
3414 sizeof(parameters));
3415 char const *message =
3416 reinterpret_cast<char const*
>(
3417 pc_->InstructionAtOffset(kDebugMessageOffset));
3422 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) {
3423 if (message !=
nullptr) {
3425 "# %sDebugger hit %d: %s%s%s\n",
3433 "# %sDebugger hit %d.%s\n",
3441 switch (parameters & kDebuggerTracingDirectivesMask) {
3443 set_log_parameters(log_parameters() | parameters);
3444 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3445 if (parameters & LOG_REGS) { PrintRegisters(); }
3446 if (parameters & LOG_VREGS) {
3451 set_log_parameters(log_parameters() & ~parameters);
3453 case TRACE_OVERRIDE:
3454 set_log_parameters(parameters);
3458 DCHECK_EQ(parameters & LOG_DISASM, 0);
3460 parameters &= ~log_parameters();
3462 if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3463 if (parameters & LOG_REGS) PrintRegisters();
3464 if (parameters & LOG_VREGS) PrintVRegisters();
3469 size_t size = kDebugMessageOffset + strlen(message) + 1;
3470 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstrSize));
3472 DCHECK(pc_->Mask(ExceptionMask) == HLT);
3473 DCHECK_EQ(pc_->ImmException(), kImmExceptionIsUnreachable);
3475 set_pc(pc_->following());
3478 if (parameters & BREAK) Debug();
3480 }
else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3481 DoRuntimeCall(instr);
3482 }
else if (instr->ImmException() == kImmExceptionIsPrintf) {
3485 }
else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3486 fprintf(stream_,
"Hit UNREACHABLE marker at PC=%p.\n",
3487 reinterpret_cast<void*>(pc_));
3491 base::OS::DebugBreak();
3496 base::OS::DebugBreak();
3503 void Simulator::VisitNEON2RegMisc(Instruction* instr) {
3504 NEONFormatDecoder nfd(instr);
3505 VectorFormat vf = nfd.GetVectorFormat();
3508 static const NEONFormatMap map_lp = {
3509 {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
3510 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
3512 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
3513 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
3515 static const NEONFormatMap map_fcvtn = {{22, 30},
3516 {NF_4H, NF_8H, NF_2S, NF_4S}};
3517 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
3519 SimVRegister& rd = vreg(instr->Rd());
3520 SimVRegister& rn = vreg(instr->Rn());
3522 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
3525 switch (instr->Mask(NEON2RegMiscMask)) {
3551 abs(vf, rd, rn).SignedSaturate(vf);
3554 neg(vf, rd, rn).SignedSaturate(vf);
3556 case NEON_CMGT_zero:
3557 cmp(vf, rd, rn, 0, gt);
3559 case NEON_CMGE_zero:
3560 cmp(vf, rd, rn, 0, ge);
3562 case NEON_CMEQ_zero:
3563 cmp(vf, rd, rn, 0, eq);
3565 case NEON_CMLE_zero:
3566 cmp(vf, rd, rn, 0, le);
3568 case NEON_CMLT_zero:
3569 cmp(vf, rd, rn, 0, lt);
3578 saddlp(vf_lp, rd, rn);
3581 uaddlp(vf_lp, rd, rn);
3584 sadalp(vf_lp, rd, rn);
3587 uadalp(vf_lp, rd, rn);
3590 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3591 switch (instr->FPType()) {
3604 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
3605 FPRounding fpcr_rounding =
static_cast<FPRounding
>(fpcr().RMode());
3606 bool inexact_exception =
false;
3610 switch (instr->Mask(NEON2RegMiscFPMask)) {
3621 if (instr->Mask(NEON_Q)) {
3622 fcvtl2(vf_fcvtl, rd, rn);
3624 fcvtl(vf_fcvtl, rd, rn);
3628 if (instr->Mask(NEON_Q)) {
3629 fcvtn2(vf_fcvtn, rd, rn);
3631 fcvtn(vf_fcvtn, rd, rn);
3635 if (instr->Mask(NEON_Q)) {
3636 fcvtxn2(vf_fcvtn, rd, rn);
3638 fcvtxn(vf_fcvtn, rd, rn);
3647 inexact_exception =
true;
3650 fpcr_rounding = FPTieAway;
3653 fpcr_rounding = FPNegativeInfinity;
3656 fpcr_rounding = FPTieEven;
3659 fpcr_rounding = FPPositiveInfinity;
3662 fpcr_rounding = FPZero;
3667 fcvts(fpf, rd, rn, FPTieEven);
3670 fcvtu(fpf, rd, rn, FPTieEven);
3673 fcvts(fpf, rd, rn, FPPositiveInfinity);
3676 fcvtu(fpf, rd, rn, FPPositiveInfinity);
3679 fcvts(fpf, rd, rn, FPNegativeInfinity);
3682 fcvtu(fpf, rd, rn, FPNegativeInfinity);
3685 fcvts(fpf, rd, rn, FPZero);
3688 fcvtu(fpf, rd, rn, FPZero);
3691 fcvts(fpf, rd, rn, FPTieAway);
3694 fcvtu(fpf, rd, rn, FPTieAway);
3697 scvtf(fpf, rd, rn, 0, fpcr_rounding);
3700 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
3703 ursqrte(fpf, rd, rn);
3706 urecpe(fpf, rd, rn);
3709 frsqrte(fpf, rd, rn);
3712 frecpe(fpf, rd, rn, fpcr_rounding);
3714 case NEON_FCMGT_zero:
3715 fcmp_zero(fpf, rd, rn, gt);
3717 case NEON_FCMGE_zero:
3718 fcmp_zero(fpf, rd, rn, ge);
3720 case NEON_FCMEQ_zero:
3721 fcmp_zero(fpf, rd, rn, eq);
3723 case NEON_FCMLE_zero:
3724 fcmp_zero(fpf, rd, rn, le);
3726 case NEON_FCMLT_zero:
3727 fcmp_zero(fpf, rd, rn, lt);
3730 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
3731 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
3732 switch (instr->Mask(NEON2RegMiscMask)) {
3746 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3747 if (instr->Mask(NEON_Q)) {
3762 frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
3766 void Simulator::VisitNEON3Same(Instruction* instr) {
3767 NEONFormatDecoder nfd(instr);
3768 SimVRegister& rd = vreg(instr->Rd());
3769 SimVRegister& rn = vreg(instr->Rn());
3770 SimVRegister& rm = vreg(instr->Rm());
3772 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
3773 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3774 switch (instr->Mask(NEON3SameLogicalMask)) {
3776 and_(vf, rd, rn, rm);
3779 orr(vf, rd, rn, rm);
3782 orn(vf, rd, rn, rm);
3785 eor(vf, rd, rn, rm);
3788 bic(vf, rd, rn, rm);
3791 bif(vf, rd, rn, rm);
3794 bit(vf, rd, rn, rm);
3797 bsl(vf, rd, rn, rm);
3802 }
else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
3803 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3804 switch (instr->Mask(NEON3SameFPMask)) {
3806 fadd(vf, rd, rn, rm);
3809 fsub(vf, rd, rn, rm);
3812 fmul(vf, rd, rn, rm);
3815 fdiv(vf, rd, rn, rm);
3818 fmax(vf, rd, rn, rm);
3821 fmin(vf, rd, rn, rm);
3824 fmaxnm(vf, rd, rn, rm);
3827 fminnm(vf, rd, rn, rm);
3830 fmla(vf, rd, rn, rm);
3833 fmls(vf, rd, rn, rm);
3836 fmulx(vf, rd, rn, rm);
3839 fabscmp(vf, rd, rn, rm, ge);
3842 fabscmp(vf, rd, rn, rm, gt);
3845 fcmp(vf, rd, rn, rm, eq);
3848 fcmp(vf, rd, rn, rm, ge);
3851 fcmp(vf, rd, rn, rm, gt);
3854 frecps(vf, rd, rn, rm);
3857 frsqrts(vf, rd, rn, rm);
3860 fabd(vf, rd, rn, rm);
3863 faddp(vf, rd, rn, rm);
3866 fmaxp(vf, rd, rn, rm);
3869 fmaxnmp(vf, rd, rn, rm);
3872 fminp(vf, rd, rn, rm);
3875 fminnmp(vf, rd, rn, rm);
3881 VectorFormat vf = nfd.GetVectorFormat();
3882 switch (instr->Mask(NEON3SameMask)) {
3884 add(vf, rd, rn, rm);
3887 addp(vf, rd, rn, rm);
3890 cmp(vf, rd, rn, rm, eq);
3893 cmp(vf, rd, rn, rm, ge);
3896 cmp(vf, rd, rn, rm, gt);
3899 cmp(vf, rd, rn, rm, hi);
3902 cmp(vf, rd, rn, rm, hs);
3905 cmptst(vf, rd, rn, rm);
3908 mls(vf, rd, rn, rm);
3911 mla(vf, rd, rn, rm);
3914 mul(vf, rd, rn, rm);
3917 pmul(vf, rd, rn, rm);
3920 smax(vf, rd, rn, rm);
3923 smaxp(vf, rd, rn, rm);
3926 smin(vf, rd, rn, rm);
3929 sminp(vf, rd, rn, rm);
3932 sub(vf, rd, rn, rm);
3935 umax(vf, rd, rn, rm);
3938 umaxp(vf, rd, rn, rm);
3941 umin(vf, rd, rn, rm);
3944 uminp(vf, rd, rn, rm);
3947 sshl(vf, rd, rn, rm);
3950 ushl(vf, rd, rn, rm);
3953 AbsDiff(vf, rd, rn, rm,
true);
3956 AbsDiff(vf, rd, rn, rm,
false);
3959 saba(vf, rd, rn, rm);
3962 uaba(vf, rd, rn, rm);
3965 add(vf, rd, rn, rm).UnsignedSaturate(vf);
3968 add(vf, rd, rn, rm).SignedSaturate(vf);
3971 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
3974 sub(vf, rd, rn, rm).SignedSaturate(vf);
3977 sqdmulh(vf, rd, rn, rm);
3980 sqrdmulh(vf, rd, rn, rm);
3983 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
3986 sshl(vf, rd, rn, rm).SignedSaturate(vf);
3989 ushl(vf, rd, rn, rm).Round(vf);
3992 sshl(vf, rd, rn, rm).Round(vf);
3995 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
3998 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
4001 add(vf, rd, rn, rm).Uhalve(vf);
4004 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
4007 add(vf, rd, rn, rm).Halve(vf);
4010 add(vf, rd, rn, rm).Halve(vf).Round(vf);
4013 sub(vf, rd, rn, rm).Uhalve(vf);
4016 sub(vf, rd, rn, rm).Halve(vf);
4024 void Simulator::VisitNEON3Different(Instruction* instr) {
4025 NEONFormatDecoder nfd(instr);
4026 VectorFormat vf = nfd.GetVectorFormat();
4027 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4029 SimVRegister& rd = vreg(instr->Rd());
4030 SimVRegister& rn = vreg(instr->Rn());
4031 SimVRegister& rm = vreg(instr->Rm());
4033 switch (instr->Mask(NEON3DifferentMask)) {
4035 pmull(vf_l, rd, rn, rm);
4038 pmull2(vf_l, rd, rn, rm);
4041 uaddl(vf_l, rd, rn, rm);
4044 uaddl2(vf_l, rd, rn, rm);
4047 saddl(vf_l, rd, rn, rm);
4050 saddl2(vf_l, rd, rn, rm);
4053 usubl(vf_l, rd, rn, rm);
4056 usubl2(vf_l, rd, rn, rm);
4059 ssubl(vf_l, rd, rn, rm);
4062 ssubl2(vf_l, rd, rn, rm);
4065 sabal(vf_l, rd, rn, rm);
4068 sabal2(vf_l, rd, rn, rm);
4071 uabal(vf_l, rd, rn, rm);
4074 uabal2(vf_l, rd, rn, rm);
4077 sabdl(vf_l, rd, rn, rm);
4080 sabdl2(vf_l, rd, rn, rm);
4083 uabdl(vf_l, rd, rn, rm);
4086 uabdl2(vf_l, rd, rn, rm);
4089 smlal(vf_l, rd, rn, rm);
4092 smlal2(vf_l, rd, rn, rm);
4095 umlal(vf_l, rd, rn, rm);
4098 umlal2(vf_l, rd, rn, rm);
4101 smlsl(vf_l, rd, rn, rm);
4104 smlsl2(vf_l, rd, rn, rm);
4107 umlsl(vf_l, rd, rn, rm);
4110 umlsl2(vf_l, rd, rn, rm);
4113 smull(vf_l, rd, rn, rm);
4116 smull2(vf_l, rd, rn, rm);
4119 umull(vf_l, rd, rn, rm);
4122 umull2(vf_l, rd, rn, rm);
4125 sqdmlal(vf_l, rd, rn, rm);
4128 sqdmlal2(vf_l, rd, rn, rm);
4131 sqdmlsl(vf_l, rd, rn, rm);
4134 sqdmlsl2(vf_l, rd, rn, rm);
4137 sqdmull(vf_l, rd, rn, rm);
4140 sqdmull2(vf_l, rd, rn, rm);
4143 uaddw(vf_l, rd, rn, rm);
4146 uaddw2(vf_l, rd, rn, rm);
4149 saddw(vf_l, rd, rn, rm);
4152 saddw2(vf_l, rd, rn, rm);
4155 usubw(vf_l, rd, rn, rm);
4158 usubw2(vf_l, rd, rn, rm);
4161 ssubw(vf_l, rd, rn, rm);
4164 ssubw2(vf_l, rd, rn, rm);
4167 addhn(vf, rd, rn, rm);
4170 addhn2(vf, rd, rn, rm);
4173 raddhn(vf, rd, rn, rm);
4176 raddhn2(vf, rd, rn, rm);
4179 subhn(vf, rd, rn, rm);
4182 subhn2(vf, rd, rn, rm);
4185 rsubhn(vf, rd, rn, rm);
4188 rsubhn2(vf, rd, rn, rm);
4195 void Simulator::VisitNEONAcrossLanes(Instruction* instr) {
4196 NEONFormatDecoder nfd(instr);
4198 SimVRegister& rd = vreg(instr->Rd());
4199 SimVRegister& rn = vreg(instr->Rn());
4202 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
4203 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4205 switch (instr->Mask(NEONAcrossLanesFPMask)) {
4213 fmaxnmv(vf, rd, rn);
4216 fminnmv(vf, rd, rn);
4222 VectorFormat vf = nfd.GetVectorFormat();
4224 switch (instr->Mask(NEONAcrossLanesMask)) {
4252 void Simulator::VisitNEONByIndexedElement(Instruction* instr) {
4253 NEONFormatDecoder nfd(instr);
4254 VectorFormat vf_r = nfd.GetVectorFormat();
4255 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4257 SimVRegister& rd = vreg(instr->Rd());
4258 SimVRegister& rn = vreg(instr->Rn());
4260 ByElementOp Op =
nullptr;
4262 int rm_reg = instr->Rm();
4263 int index = (instr->NEONH() << 1) | instr->NEONL();
4264 if (instr->NEONSize() == 1) {
4266 index = (index << 1) | instr->NEONM();
4269 switch (instr->Mask(NEONByIndexedElementMask)) {
4270 case NEON_MUL_byelement:
4271 Op = &Simulator::mul;
4274 case NEON_MLA_byelement:
4275 Op = &Simulator::mla;
4278 case NEON_MLS_byelement:
4279 Op = &Simulator::mls;
4282 case NEON_SQDMULH_byelement:
4283 Op = &Simulator::sqdmulh;
4286 case NEON_SQRDMULH_byelement:
4287 Op = &Simulator::sqrdmulh;
4290 case NEON_SMULL_byelement:
4291 if (instr->Mask(NEON_Q)) {
4292 Op = &Simulator::smull2;
4294 Op = &Simulator::smull;
4297 case NEON_UMULL_byelement:
4298 if (instr->Mask(NEON_Q)) {
4299 Op = &Simulator::umull2;
4301 Op = &Simulator::umull;
4304 case NEON_SMLAL_byelement:
4305 if (instr->Mask(NEON_Q)) {
4306 Op = &Simulator::smlal2;
4308 Op = &Simulator::smlal;
4311 case NEON_UMLAL_byelement:
4312 if (instr->Mask(NEON_Q)) {
4313 Op = &Simulator::umlal2;
4315 Op = &Simulator::umlal;
4318 case NEON_SMLSL_byelement:
4319 if (instr->Mask(NEON_Q)) {
4320 Op = &Simulator::smlsl2;
4322 Op = &Simulator::smlsl;
4325 case NEON_UMLSL_byelement:
4326 if (instr->Mask(NEON_Q)) {
4327 Op = &Simulator::umlsl2;
4329 Op = &Simulator::umlsl;
4332 case NEON_SQDMULL_byelement:
4333 if (instr->Mask(NEON_Q)) {
4334 Op = &Simulator::sqdmull2;
4336 Op = &Simulator::sqdmull;
4339 case NEON_SQDMLAL_byelement:
4340 if (instr->Mask(NEON_Q)) {
4341 Op = &Simulator::sqdmlal2;
4343 Op = &Simulator::sqdmlal;
4346 case NEON_SQDMLSL_byelement:
4347 if (instr->Mask(NEON_Q)) {
4348 Op = &Simulator::sqdmlsl2;
4350 Op = &Simulator::sqdmlsl;
4354 index = instr->NEONH();
4355 if ((instr->FPType() & 1) == 0) {
4356 index = (index << 1) | instr->NEONL();
4359 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4361 switch (instr->Mask(NEONByIndexedElementFPMask)) {
4362 case NEON_FMUL_byelement:
4363 Op = &Simulator::fmul;
4365 case NEON_FMLA_byelement:
4366 Op = &Simulator::fmla;
4368 case NEON_FMLS_byelement:
4369 Op = &Simulator::fmls;
4371 case NEON_FMULX_byelement:
4372 Op = &Simulator::fmulx;
4379 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
4382 void Simulator::VisitNEONCopy(Instruction* instr) {
4383 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
4384 VectorFormat vf = nfd.GetVectorFormat();
4386 SimVRegister& rd = vreg(instr->Rd());
4387 SimVRegister& rn = vreg(instr->Rn());
4388 int imm5 = instr->ImmNEON5();
4389 int lsb = LowestSetBitPosition(imm5);
4390 int reg_index = imm5 >> lsb;
4392 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
4393 int imm4 = instr->ImmNEON4();
4395 int rn_index = imm4 >> (lsb - 1);
4396 ins_element(vf, rd, reg_index, rn, rn_index);
4397 }
else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
4398 ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
4399 }
else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
4400 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
4401 value &= MaxUintFromFormat(vf);
4402 set_xreg(instr->Rd(), value);
4403 }
else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
4404 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
4405 if (instr->NEONQ()) {
4406 set_xreg(instr->Rd(), value);
4408 DCHECK(is_int32(value));
4409 set_wreg(instr->Rd(),
static_cast<int32_t
>(value));
4411 }
else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
4412 dup_element(vf, rd, rn, reg_index);
4413 }
else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
4414 dup_immediate(vf, rd, xreg(instr->Rn()));
4420 void Simulator::VisitNEONExtract(Instruction* instr) {
4421 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
4422 VectorFormat vf = nfd.GetVectorFormat();
4423 SimVRegister& rd = vreg(instr->Rd());
4424 SimVRegister& rn = vreg(instr->Rn());
4425 SimVRegister& rm = vreg(instr->Rm());
4426 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
4427 int index = instr->ImmNEONExt();
4428 ext(vf, rd, rn, rm, index);
4434 void Simulator::NEONLoadStoreMultiStructHelper(
const Instruction* instr,
4435 AddrMode addr_mode) {
4436 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4437 VectorFormat vf = nfd.GetVectorFormat();
4439 uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
4440 int reg_size = RegisterSizeInBytesFromFormat(vf);
4444 for (
int i = 0;
i < 4;
i++) {
4445 reg[
i] = (instr->Rt() +
i) % kNumberOfVRegisters;
4446 addr[
i] = addr_base + (
i * reg_size);
4449 bool log_read =
true;
4454 if ((instr->Bit(23) == 0) && (instr->Bits(20, 16) != 0)) {
4460 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
4462 case NEON_LD1_4v_post:
4463 ld1(vf, vreg(reg[3]), addr[3]);
4467 case NEON_LD1_3v_post:
4468 ld1(vf, vreg(reg[2]), addr[2]);
4472 case NEON_LD1_2v_post:
4473 ld1(vf, vreg(reg[1]), addr[1]);
4477 case NEON_LD1_1v_post:
4478 ld1(vf, vreg(reg[0]), addr[0]);
4481 case NEON_ST1_4v_post:
4482 st1(vf, vreg(reg[3]), addr[3]);
4486 case NEON_ST1_3v_post:
4487 st1(vf, vreg(reg[2]), addr[2]);
4491 case NEON_ST1_2v_post:
4492 st1(vf, vreg(reg[1]), addr[1]);
4496 case NEON_ST1_1v_post:
4497 st1(vf, vreg(reg[0]), addr[0]);
4502 ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4507 st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4513 ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4518 st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4524 ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4529 st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4538 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
4540 local_monitor_.NotifyLoad();
4542 local_monitor_.NotifyStore();
4543 global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
4548 for (
int i = 0;
i < count;
i++) {
4550 int lane_size = LaneSizeInBytesFromFormat(vf);
4551 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
4552 GetPrintRegisterFormatForSize(reg_size, lane_size));
4554 LogVRead(addr_base, reg[
i], format);
4556 LogVWrite(addr_base, reg[
i], format);
4560 if (addr_mode == PostIndex) {
4561 int rm = instr->Rm();
4565 (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count : xreg(rm);
4566 set_xreg(instr->Rn(), addr_base);
4568 DCHECK_EQ(addr_mode, Offset);
4572 void Simulator::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
4573 NEONLoadStoreMultiStructHelper(instr, Offset);
4576 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(Instruction* instr) {
4577 NEONLoadStoreMultiStructHelper(instr, PostIndex);
4580 void Simulator::NEONLoadStoreSingleStructHelper(
const Instruction* instr,
4581 AddrMode addr_mode) {
4582 uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
4583 int rt = instr->Rt();
4588 DCHECK_IMPLIES(instr->Bit(23) == 0, instr->Bits(20, 16) == 0);
4590 bool do_load =
false;
4592 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4593 VectorFormat vf_t = nfd.GetVectorFormat();
4595 VectorFormat vf = kFormat16B;
4598 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
4600 case NEON_LD1_b_post:
4602 case NEON_LD2_b_post:
4604 case NEON_LD3_b_post:
4606 case NEON_LD4_b_post:
4610 case NEON_ST1_b_post:
4612 case NEON_ST2_b_post:
4614 case NEON_ST3_b_post:
4616 case NEON_ST4_b_post:
4620 case NEON_LD1_h_post:
4622 case NEON_LD2_h_post:
4624 case NEON_LD3_h_post:
4626 case NEON_LD4_h_post:
4630 case NEON_ST1_h_post:
4632 case NEON_ST2_h_post:
4634 case NEON_ST3_h_post:
4636 case NEON_ST4_h_post:
4641 case NEON_LD1_s_post:
4643 case NEON_LD2_s_post:
4645 case NEON_LD3_s_post:
4647 case NEON_LD4_s_post:
4651 case NEON_ST1_s_post:
4653 case NEON_ST2_s_post:
4655 case NEON_ST3_s_post:
4657 case NEON_ST4_s_post: {
4658 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
4659 "LSB of size distinguishes S and D registers.");
4661 (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post,
4662 "LSB of size distinguishes S and D registers.");
4663 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
4664 "LSB of size distinguishes S and D registers.");
4666 (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post,
4667 "LSB of size distinguishes S and D registers.");
4668 vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
4673 case NEON_LD1R_post: {
4675 ld1r(vf, vreg(rt), addr);
4681 case NEON_LD2R_post: {
4683 int rt2 = (rt + 1) % kNumberOfVRegisters;
4684 ld2r(vf, vreg(rt), vreg(rt2), addr);
4690 case NEON_LD3R_post: {
4692 int rt2 = (rt + 1) % kNumberOfVRegisters;
4693 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4694 ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
4700 case NEON_LD4R_post: {
4702 int rt2 = (rt + 1) % kNumberOfVRegisters;
4703 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4704 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4705 ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
4713 PrintRegisterFormat print_format =
4714 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
4717 static_cast<PrintRegisterFormat
>(print_format & ~kPrintRegAsVectorMask);
4719 int esize = LaneSizeInBytesFromFormat(vf);
4720 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
4721 int lane = instr->NEONLSIndex(index_shift);
4723 int rt2 = (rt + 1) % kNumberOfVRegisters;
4724 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4725 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4726 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
4727 case NEONLoadStoreSingle1:
4730 ld1(vf, vreg(rt), lane, addr);
4731 LogVRead(addr, rt, print_format, lane);
4733 st1(vf, vreg(rt), lane, addr);
4734 LogVWrite(addr, rt, print_format, lane);
4737 case NEONLoadStoreSingle2:
4740 ld2(vf, vreg(rt), vreg(rt2), lane, addr);
4741 LogVRead(addr, rt, print_format, lane);
4742 LogVRead(addr + esize, rt2, print_format, lane);
4744 st2(vf, vreg(rt), vreg(rt2), lane, addr);
4745 LogVWrite(addr, rt, print_format, lane);
4746 LogVWrite(addr + esize, rt2, print_format, lane);
4749 case NEONLoadStoreSingle3:
4752 ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4753 LogVRead(addr, rt, print_format, lane);
4754 LogVRead(addr + esize, rt2, print_format, lane);
4755 LogVRead(addr + (2 * esize), rt3, print_format, lane);
4757 st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4758 LogVWrite(addr, rt, print_format, lane);
4759 LogVWrite(addr + esize, rt2, print_format, lane);
4760 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4763 case NEONLoadStoreSingle4:
4766 ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4767 LogVRead(addr, rt, print_format, lane);
4768 LogVRead(addr + esize, rt2, print_format, lane);
4769 LogVRead(addr + (2 * esize), rt3, print_format, lane);
4770 LogVRead(addr + (3 * esize), rt4, print_format, lane);
4772 st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4773 LogVWrite(addr, rt, print_format, lane);
4774 LogVWrite(addr + esize, rt2, print_format, lane);
4775 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4776 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
4784 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
4786 local_monitor_.NotifyLoad();
4788 local_monitor_.NotifyStore();
4789 global_monitor_.Pointer()->NotifyStore_Locked(&global_monitor_processor_);
4793 if (addr_mode == PostIndex) {
4794 int rm = instr->Rm();
4795 int lane_size = LaneSizeInBytesFromFormat(vf);
4796 set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
4800 void Simulator::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
4801 NEONLoadStoreSingleStructHelper(instr, Offset);
4804 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(Instruction* instr) {
4805 NEONLoadStoreSingleStructHelper(instr, PostIndex);
4808 void Simulator::VisitNEONModifiedImmediate(Instruction* instr) {
4809 SimVRegister& rd = vreg(instr->Rd());
4810 int cmode = instr->NEONCmode();
4811 int cmode_3_1 = (cmode >> 1) & 7;
4812 int cmode_3 = (cmode >> 3) & 1;
4813 int cmode_2 = (cmode >> 2) & 1;
4814 int cmode_1 = (cmode >> 1) & 1;
4815 int cmode_0 = cmode & 1;
4816 int q = instr->NEONQ();
4817 int op_bit = instr->NEONModImmOp();
4818 uint64_t imm8 = instr->ImmNEONabcdefgh();
4822 VectorFormat vform = kFormatUndefined;
4823 switch (cmode_3_1) {
4828 vform = (q == 1) ? kFormat4S : kFormat2S;
4829 imm = imm8 << (8 * cmode_3_1);
4833 vform = (q == 1) ? kFormat8H : kFormat4H;
4834 imm = imm8 << (8 * cmode_1);
4837 vform = (q == 1) ? kFormat4S : kFormat2S;
4839 imm = imm8 << 8 | 0x000000FF;
4841 imm = imm8 << 16 | 0x0000FFFF;
4845 if (cmode_0 == 0 && op_bit == 0) {
4846 vform = q ? kFormat16B : kFormat8B;
4848 }
else if (cmode_0 == 0 && op_bit == 1) {
4849 vform = q ? kFormat2D : kFormat1D;
4851 for (
int i = 0;
i < 8; ++
i) {
4852 if (imm8 & (1ULL <<
i)) {
4853 imm |= (UINT64_C(0xFF) << (8 *
i));
4858 vform = q ? kFormat4S : kFormat2S;
4859 imm = bit_cast<
uint32_t>(instr->ImmNEONFP32());
4860 }
else if (q == 1) {
4862 imm = bit_cast<uint64_t>(instr->ImmNEONFP64());
4864 DCHECK((q == 0) && (op_bit == 1) && (cmode == 0xF));
4865 VisitUnallocated(instr);
4874 NEONModifiedImmediateOp op;
4877 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4879 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4884 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4886 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4890 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4893 op = NEONModifiedImmediate_MOVI;
4895 op = NEONModifiedImmediate_MOVI;
4903 case NEONModifiedImmediate_ORR:
4904 orr(vform, rd, rd, imm);
4906 case NEONModifiedImmediate_BIC:
4907 bic(vform, rd, rd, imm);
4909 case NEONModifiedImmediate_MOVI:
4910 movi(vform, rd, imm);
4912 case NEONModifiedImmediate_MVNI:
4913 mvni(vform, rd, imm);
4916 VisitUnimplemented(instr);
4920 void Simulator::VisitNEONScalar2RegMisc(Instruction* instr) {
4921 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4922 VectorFormat vf = nfd.GetVectorFormat();
4924 SimVRegister& rd = vreg(instr->Rd());
4925 SimVRegister& rn = vreg(instr->Rn());
4927 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
4930 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4931 case NEON_CMEQ_zero_scalar:
4932 cmp(vf, rd, rn, 0, eq);
4934 case NEON_CMGE_zero_scalar:
4935 cmp(vf, rd, rn, 0, ge);
4937 case NEON_CMGT_zero_scalar:
4938 cmp(vf, rd, rn, 0, gt);
4940 case NEON_CMLT_zero_scalar:
4941 cmp(vf, rd, rn, 0, lt);
4943 case NEON_CMLE_zero_scalar:
4944 cmp(vf, rd, rn, 0, le);
4946 case NEON_ABS_scalar:
4949 case NEON_SQABS_scalar:
4950 abs(vf, rd, rn).SignedSaturate(vf);
4952 case NEON_NEG_scalar:
4955 case NEON_SQNEG_scalar:
4956 neg(vf, rd, rn).SignedSaturate(vf);
4958 case NEON_SUQADD_scalar:
4961 case NEON_USQADD_scalar:
4969 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
4970 FPRounding fpcr_rounding =
static_cast<FPRounding
>(fpcr().RMode());
4974 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
4975 case NEON_FRECPE_scalar:
4976 frecpe(fpf, rd, rn, fpcr_rounding);
4978 case NEON_FRECPX_scalar:
4979 frecpx(fpf, rd, rn);
4981 case NEON_FRSQRTE_scalar:
4982 frsqrte(fpf, rd, rn);
4984 case NEON_FCMGT_zero_scalar:
4985 fcmp_zero(fpf, rd, rn, gt);
4987 case NEON_FCMGE_zero_scalar:
4988 fcmp_zero(fpf, rd, rn, ge);
4990 case NEON_FCMEQ_zero_scalar:
4991 fcmp_zero(fpf, rd, rn, eq);
4993 case NEON_FCMLE_zero_scalar:
4994 fcmp_zero(fpf, rd, rn, le);
4996 case NEON_FCMLT_zero_scalar:
4997 fcmp_zero(fpf, rd, rn, lt);
4999 case NEON_SCVTF_scalar:
5000 scvtf(fpf, rd, rn, 0, fpcr_rounding);
5002 case NEON_UCVTF_scalar:
5003 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
5005 case NEON_FCVTNS_scalar:
5006 fcvts(fpf, rd, rn, FPTieEven);
5008 case NEON_FCVTNU_scalar:
5009 fcvtu(fpf, rd, rn, FPTieEven);
5011 case NEON_FCVTPS_scalar:
5012 fcvts(fpf, rd, rn, FPPositiveInfinity);
5014 case NEON_FCVTPU_scalar:
5015 fcvtu(fpf, rd, rn, FPPositiveInfinity);
5017 case NEON_FCVTMS_scalar:
5018 fcvts(fpf, rd, rn, FPNegativeInfinity);
5020 case NEON_FCVTMU_scalar:
5021 fcvtu(fpf, rd, rn, FPNegativeInfinity);
5023 case NEON_FCVTZS_scalar:
5024 fcvts(fpf, rd, rn, FPZero);
5026 case NEON_FCVTZU_scalar:
5027 fcvtu(fpf, rd, rn, FPZero);
5029 case NEON_FCVTAS_scalar:
5030 fcvts(fpf, rd, rn, FPTieAway);
5032 case NEON_FCVTAU_scalar:
5033 fcvtu(fpf, rd, rn, FPTieAway);
5035 case NEON_FCVTXN_scalar:
5038 DCHECK_EQ(instr->Bit(22), 1);
5039 fcvtxn(kFormatS, rd, rn);
5042 switch (instr->Mask(NEONScalar2RegMiscMask)) {
5043 case NEON_SQXTN_scalar:
5046 case NEON_UQXTN_scalar:
5049 case NEON_SQXTUN_scalar:
5059 void Simulator::VisitNEONScalar3Diff(Instruction* instr) {
5060 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5061 VectorFormat vf = nfd.GetVectorFormat();
5063 SimVRegister& rd = vreg(instr->Rd());
5064 SimVRegister& rn = vreg(instr->Rn());
5065 SimVRegister& rm = vreg(instr->Rm());
5066 switch (instr->Mask(NEONScalar3DiffMask)) {
5067 case NEON_SQDMLAL_scalar:
5068 sqdmlal(vf, rd, rn, rm);
5070 case NEON_SQDMLSL_scalar:
5071 sqdmlsl(vf, rd, rn, rm);
5073 case NEON_SQDMULL_scalar:
5074 sqdmull(vf, rd, rn, rm);
5081 void Simulator::VisitNEONScalar3Same(Instruction* instr) {
5082 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
5083 VectorFormat vf = nfd.GetVectorFormat();
5085 SimVRegister& rd = vreg(instr->Rd());
5086 SimVRegister& rn = vreg(instr->Rn());
5087 SimVRegister& rm = vreg(instr->Rm());
5089 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
5090 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5091 switch (instr->Mask(NEONScalar3SameFPMask)) {
5092 case NEON_FMULX_scalar:
5093 fmulx(vf, rd, rn, rm);
5095 case NEON_FACGE_scalar:
5096 fabscmp(vf, rd, rn, rm, ge);
5098 case NEON_FACGT_scalar:
5099 fabscmp(vf, rd, rn, rm, gt);
5101 case NEON_FCMEQ_scalar:
5102 fcmp(vf, rd, rn, rm, eq);
5104 case NEON_FCMGE_scalar:
5105 fcmp(vf, rd, rn, rm, ge);
5107 case NEON_FCMGT_scalar:
5108 fcmp(vf, rd, rn, rm, gt);
5110 case NEON_FRECPS_scalar:
5111 frecps(vf, rd, rn, rm);
5113 case NEON_FRSQRTS_scalar:
5114 frsqrts(vf, rd, rn, rm);
5116 case NEON_FABD_scalar:
5117 fabd(vf, rd, rn, rm);
5123 switch (instr->Mask(NEONScalar3SameMask)) {
5124 case NEON_ADD_scalar:
5125 add(vf, rd, rn, rm);
5127 case NEON_SUB_scalar:
5128 sub(vf, rd, rn, rm);
5130 case NEON_CMEQ_scalar:
5131 cmp(vf, rd, rn, rm, eq);
5133 case NEON_CMGE_scalar:
5134 cmp(vf, rd, rn, rm, ge);
5136 case NEON_CMGT_scalar:
5137 cmp(vf, rd, rn, rm, gt);
5139 case NEON_CMHI_scalar:
5140 cmp(vf, rd, rn, rm, hi);
5142 case NEON_CMHS_scalar:
5143 cmp(vf, rd, rn, rm, hs);
5145 case NEON_CMTST_scalar:
5146 cmptst(vf, rd, rn, rm);
5148 case NEON_USHL_scalar:
5149 ushl(vf, rd, rn, rm);
5151 case NEON_SSHL_scalar:
5152 sshl(vf, rd, rn, rm);
5154 case NEON_SQDMULH_scalar:
5155 sqdmulh(vf, rd, rn, rm);
5157 case NEON_SQRDMULH_scalar:
5158 sqrdmulh(vf, rd, rn, rm);
5160 case NEON_UQADD_scalar:
5161 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5163 case NEON_SQADD_scalar:
5164 add(vf, rd, rn, rm).SignedSaturate(vf);
5166 case NEON_UQSUB_scalar:
5167 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5169 case NEON_SQSUB_scalar:
5170 sub(vf, rd, rn, rm).SignedSaturate(vf);
5172 case NEON_UQSHL_scalar:
5173 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5175 case NEON_SQSHL_scalar:
5176 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5178 case NEON_URSHL_scalar:
5179 ushl(vf, rd, rn, rm).Round(vf);
5181 case NEON_SRSHL_scalar:
5182 sshl(vf, rd, rn, rm).Round(vf);
5184 case NEON_UQRSHL_scalar:
5185 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5187 case NEON_SQRSHL_scalar:
5188 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5196 void Simulator::VisitNEONScalarByIndexedElement(Instruction* instr) {
5197 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5198 VectorFormat vf = nfd.GetVectorFormat();
5199 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
5201 SimVRegister& rd = vreg(instr->Rd());
5202 SimVRegister& rn = vreg(instr->Rn());
5203 ByElementOp Op =
nullptr;
5205 int rm_reg = instr->Rm();
5206 int index = (instr->NEONH() << 1) | instr->NEONL();
5207 if (instr->NEONSize() == 1) {
5209 index = (index << 1) | instr->NEONM();
5212 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
5213 case NEON_SQDMULL_byelement_scalar:
5214 Op = &Simulator::sqdmull;
5216 case NEON_SQDMLAL_byelement_scalar:
5217 Op = &Simulator::sqdmlal;
5219 case NEON_SQDMLSL_byelement_scalar:
5220 Op = &Simulator::sqdmlsl;
5222 case NEON_SQDMULH_byelement_scalar:
5223 Op = &Simulator::sqdmulh;
5226 case NEON_SQRDMULH_byelement_scalar:
5227 Op = &Simulator::sqrdmulh;
5231 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5232 index = instr->NEONH();
5233 if ((instr->FPType() & 1) == 0) {
5234 index = (index << 1) | instr->NEONL();
5236 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
5237 case NEON_FMUL_byelement_scalar:
5238 Op = &Simulator::fmul;
5240 case NEON_FMLA_byelement_scalar:
5241 Op = &Simulator::fmla;
5243 case NEON_FMLS_byelement_scalar:
5244 Op = &Simulator::fmls;
5246 case NEON_FMULX_byelement_scalar:
5247 Op = &Simulator::fmulx;
5254 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
5257 void Simulator::VisitNEONScalarCopy(Instruction* instr) {
5258 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
5259 VectorFormat vf = nfd.GetVectorFormat();
5261 SimVRegister& rd = vreg(instr->Rd());
5262 SimVRegister& rn = vreg(instr->Rn());
5264 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
5265 int imm5 = instr->ImmNEON5();
5266 int lsb = LowestSetBitPosition(imm5);
5267 int rn_index = imm5 >> lsb;
5268 dup_element(vf, rd, rn, rn_index);
5274 void Simulator::VisitNEONScalarPairwise(Instruction* instr) {
5275 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
5276 VectorFormat vf = nfd.GetVectorFormat();
5278 SimVRegister& rd = vreg(instr->Rd());
5279 SimVRegister& rn = vreg(instr->Rn());
5280 switch (instr->Mask(NEONScalarPairwiseMask)) {
5281 case NEON_ADDP_scalar:
5284 case NEON_FADDP_scalar:
5287 case NEON_FMAXP_scalar:
5290 case NEON_FMAXNMP_scalar:
5291 fmaxnmp(vf, rd, rn);
5293 case NEON_FMINP_scalar:
5296 case NEON_FMINNMP_scalar:
5297 fminnmp(vf, rd, rn);
5304 void Simulator::VisitNEONScalarShiftImmediate(Instruction* instr) {
5305 SimVRegister& rd = vreg(instr->Rd());
5306 SimVRegister& rn = vreg(instr->Rn());
5307 FPRounding fpcr_rounding =
static_cast<FPRounding
>(fpcr().RMode());
5309 static const NEONFormatMap map = {
5311 {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
5312 NF_D, NF_D, NF_D, NF_D, NF_D}};
5313 NEONFormatDecoder nfd(instr, &map);
5314 VectorFormat vf = nfd.GetVectorFormat();
5316 int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5317 int immhimmb = instr->ImmNEONImmhImmb();
5318 int right_shift = (16 << highestSetBit) - immhimmb;
5319 int left_shift = immhimmb - (8 << highestSetBit);
5320 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
5321 case NEON_SHL_scalar:
5322 shl(vf, rd, rn, left_shift);
5324 case NEON_SLI_scalar:
5325 sli(vf, rd, rn, left_shift);
5327 case NEON_SQSHL_imm_scalar:
5328 sqshl(vf, rd, rn, left_shift);
5330 case NEON_UQSHL_imm_scalar:
5331 uqshl(vf, rd, rn, left_shift);
5333 case NEON_SQSHLU_scalar:
5334 sqshlu(vf, rd, rn, left_shift);
5336 case NEON_SRI_scalar:
5337 sri(vf, rd, rn, right_shift);
5339 case NEON_SSHR_scalar:
5340 sshr(vf, rd, rn, right_shift);
5342 case NEON_USHR_scalar:
5343 ushr(vf, rd, rn, right_shift);
5345 case NEON_SRSHR_scalar:
5346 sshr(vf, rd, rn, right_shift).Round(vf);
5348 case NEON_URSHR_scalar:
5349 ushr(vf, rd, rn, right_shift).Round(vf);
5351 case NEON_SSRA_scalar:
5352 ssra(vf, rd, rn, right_shift);
5354 case NEON_USRA_scalar:
5355 usra(vf, rd, rn, right_shift);
5357 case NEON_SRSRA_scalar:
5358 srsra(vf, rd, rn, right_shift);
5360 case NEON_URSRA_scalar:
5361 ursra(vf, rd, rn, right_shift);
5363 case NEON_UQSHRN_scalar:
5364 uqshrn(vf, rd, rn, right_shift);
5366 case NEON_UQRSHRN_scalar:
5367 uqrshrn(vf, rd, rn, right_shift);
5369 case NEON_SQSHRN_scalar:
5370 sqshrn(vf, rd, rn, right_shift);
5372 case NEON_SQRSHRN_scalar:
5373 sqrshrn(vf, rd, rn, right_shift);
5375 case NEON_SQSHRUN_scalar:
5376 sqshrun(vf, rd, rn, right_shift);
5378 case NEON_SQRSHRUN_scalar:
5379 sqrshrun(vf, rd, rn, right_shift);
5381 case NEON_FCVTZS_imm_scalar:
5382 fcvts(vf, rd, rn, FPZero, right_shift);
5384 case NEON_FCVTZU_imm_scalar:
5385 fcvtu(vf, rd, rn, FPZero, right_shift);
5387 case NEON_SCVTF_imm_scalar:
5388 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5390 case NEON_UCVTF_imm_scalar:
5391 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5398 void Simulator::VisitNEONShiftImmediate(Instruction* instr) {
5399 SimVRegister& rd = vreg(instr->Rd());
5400 SimVRegister& rn = vreg(instr->Rn());
5401 FPRounding fpcr_rounding =
static_cast<FPRounding
>(fpcr().RMode());
5405 static const NEONFormatMap map = {
5406 {22, 21, 20, 19, 30},
5407 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
5408 NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
5409 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
5410 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
5411 NEONFormatDecoder nfd(instr, &map);
5412 VectorFormat vf = nfd.GetVectorFormat();
5415 static const NEONFormatMap map_l = {
5417 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
5418 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
5420 int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5421 int immhimmb = instr->ImmNEONImmhImmb();
5422 int right_shift = (16 << highestSetBit) - immhimmb;
5423 int left_shift = immhimmb - (8 << highestSetBit);
5425 switch (instr->Mask(NEONShiftImmediateMask)) {
5427 shl(vf, rd, rn, left_shift);
5430 sli(vf, rd, rn, left_shift);
5433 sqshlu(vf, rd, rn, left_shift);
5436 sri(vf, rd, rn, right_shift);
5439 sshr(vf, rd, rn, right_shift);
5442 ushr(vf, rd, rn, right_shift);
5445 sshr(vf, rd, rn, right_shift).Round(vf);
5448 ushr(vf, rd, rn, right_shift).Round(vf);
5451 ssra(vf, rd, rn, right_shift);
5454 usra(vf, rd, rn, right_shift);
5457 srsra(vf, rd, rn, right_shift);
5460 ursra(vf, rd, rn, right_shift);
5462 case NEON_SQSHL_imm:
5463 sqshl(vf, rd, rn, left_shift);
5465 case NEON_UQSHL_imm:
5466 uqshl(vf, rd, rn, left_shift);
5468 case NEON_SCVTF_imm:
5469 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5471 case NEON_UCVTF_imm:
5472 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5474 case NEON_FCVTZS_imm:
5475 fcvts(vf, rd, rn, FPZero, right_shift);
5477 case NEON_FCVTZU_imm:
5478 fcvtu(vf, rd, rn, FPZero, right_shift);
5482 if (instr->Mask(NEON_Q)) {
5483 sshll2(vf, rd, rn, left_shift);
5485 sshll(vf, rd, rn, left_shift);
5490 if (instr->Mask(NEON_Q)) {
5491 ushll2(vf, rd, rn, left_shift);
5493 ushll(vf, rd, rn, left_shift);
5497 if (instr->Mask(NEON_Q)) {
5498 shrn2(vf, rd, rn, right_shift);
5500 shrn(vf, rd, rn, right_shift);
5504 if (instr->Mask(NEON_Q)) {
5505 rshrn2(vf, rd, rn, right_shift);
5507 rshrn(vf, rd, rn, right_shift);
5511 if (instr->Mask(NEON_Q)) {
5512 uqshrn2(vf, rd, rn, right_shift);
5514 uqshrn(vf, rd, rn, right_shift);
5518 if (instr->Mask(NEON_Q)) {
5519 uqrshrn2(vf, rd, rn, right_shift);
5521 uqrshrn(vf, rd, rn, right_shift);
5525 if (instr->Mask(NEON_Q)) {
5526 sqshrn2(vf, rd, rn, right_shift);
5528 sqshrn(vf, rd, rn, right_shift);
5532 if (instr->Mask(NEON_Q)) {
5533 sqrshrn2(vf, rd, rn, right_shift);
5535 sqrshrn(vf, rd, rn, right_shift);
5539 if (instr->Mask(NEON_Q)) {
5540 sqshrun2(vf, rd, rn, right_shift);
5542 sqshrun(vf, rd, rn, right_shift);
5546 if (instr->Mask(NEON_Q)) {
5547 sqrshrun2(vf, rd, rn, right_shift);
5549 sqrshrun(vf, rd, rn, right_shift);
5557 void Simulator::VisitNEONTable(Instruction* instr) {
5558 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5559 VectorFormat vf = nfd.GetVectorFormat();
5561 SimVRegister& rd = vreg(instr->Rd());
5562 SimVRegister& rn = vreg(instr->Rn());
5563 SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
5564 SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
5565 SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
5566 SimVRegister& rm = vreg(instr->Rm());
5568 switch (instr->Mask(NEONTableMask)) {
5570 tbl(vf, rd, rn, rm);
5573 tbl(vf, rd, rn, rn2, rm);
5576 tbl(vf, rd, rn, rn2, rn3, rm);
5579 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
5582 tbx(vf, rd, rn, rm);
5585 tbx(vf, rd, rn, rn2, rm);
5588 tbx(vf, rd, rn, rn2, rn3, rm);
5591 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
5598 void Simulator::VisitNEONPerm(Instruction* instr) {
5599 NEONFormatDecoder nfd(instr);
5600 VectorFormat vf = nfd.GetVectorFormat();
5602 SimVRegister& rd = vreg(instr->Rd());
5603 SimVRegister& rn = vreg(instr->Rn());
5604 SimVRegister& rm = vreg(instr->Rm());
5606 switch (instr->Mask(NEONPermMask)) {
5608 trn1(vf, rd, rn, rm);
5611 trn2(vf, rd, rn, rm);
5614 uzp1(vf, rd, rn, rm);
5617 uzp2(vf, rd, rn, rm);
5620 zip1(vf, rd, rn, rm);
5623 zip2(vf, rd, rn, rm);
5630 void Simulator::DoPrintf(Instruction* instr) {
5631 DCHECK((instr->Mask(ExceptionMask) == HLT) &&
5632 (instr->ImmException() == kImmExceptionIsPrintf));
5637 STATIC_ASSERT(
sizeof(*instr) == 1);
5639 instr + kPrintfArgCountOffset,
5641 memcpy(&arg_pattern_list,
5642 instr + kPrintfArgPatternListOffset,
5643 sizeof(arg_pattern_list));
5645 DCHECK_LE(arg_count, kPrintfMaxArgCount);
5646 DCHECK_EQ(arg_pattern_list >> (kPrintfArgPatternBits * arg_count), 0);
5657 const char * format_base = reg<const char *>(0);
5658 DCHECK_NOT_NULL(format_base);
5659 size_t length = strlen(format_base) + 1;
5660 char *
const format =
new char[length + arg_count];
5663 const char * chunks[kPrintfMaxArgCount];
5667 char * format_scratch = format;
5668 for (
size_t i = 0;
i < length;
i++) {
5669 if (format_base[
i] !=
'%') {
5670 *format_scratch++ = format_base[
i];
5672 if (format_base[
i + 1] ==
'%') {
5674 *format_scratch++ = format_base[
i];
5676 if (placeholder_count == 0) {
5682 *format_scratch++ = format_base[++
i];
5685 CHECK(placeholder_count < arg_count);
5687 *format_scratch++ =
'\0';
5688 chunks[placeholder_count++] = format_scratch;
5689 *format_scratch++ = format_base[
i];
5693 DCHECK(format_scratch <= (format + length + arg_count));
5694 CHECK(placeholder_count == arg_count);
5701 fprintf(stream_,
"%s", clr_printf);
5705 int result = fprintf(stream_,
"%s", format);
5709 for (
uint32_t i = 0;
i < placeholder_count;
i++) {
5710 int part_result = -1;
5712 uint32_t arg_pattern = arg_pattern_list >> (
i * kPrintfArgPatternBits);
5713 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
5714 switch (arg_pattern) {
5716 part_result = fprintf(stream_, chunks[
i], wreg(pcs_r++));
5719 part_result = fprintf(stream_, chunks[
i], xreg(pcs_r++));
5722 part_result = fprintf(stream_, chunks[
i], dreg(pcs_f++));
5724 default: UNREACHABLE();
5727 if (part_result < 0) {
5729 result = part_result;
5733 result += part_result;
5737 fprintf(stream_,
"%s", clr_normal);
5740 CorruptAllCallerSavedCPURegisters();
5744 set_xreg(0, result);
5747 set_pc(instr->InstructionAtOffset(kPrintfLength));
5755 Simulator::LocalMonitor::LocalMonitor()
5756 : access_state_(MonitorAccess::Open),
5758 size_(TransactionSize::
None) {}
5760 void Simulator::LocalMonitor::Clear() {
5761 access_state_ = MonitorAccess::Open;
5763 size_ = TransactionSize::None;
5766 void Simulator::LocalMonitor::NotifyLoad() {
5767 if (access_state_ == MonitorAccess::Exclusive) {
5774 void Simulator::LocalMonitor::NotifyLoadExcl(
uintptr_t addr,
5775 TransactionSize size) {
5776 access_state_ = MonitorAccess::Exclusive;
5777 tagged_addr_ = addr;
5781 void Simulator::LocalMonitor::NotifyStore() {
5782 if (access_state_ == MonitorAccess::Exclusive) {
5789 bool Simulator::LocalMonitor::NotifyStoreExcl(
uintptr_t addr,
5790 TransactionSize size) {
5791 if (access_state_ == MonitorAccess::Exclusive) {
5794 if (addr == tagged_addr_ && size_ == size) {
5805 DCHECK(access_state_ == MonitorAccess::Open);
5810 Simulator::GlobalMonitor::Processor::Processor()
5811 : access_state_(MonitorAccess::Open),
5815 failure_counter_(0) {}
5817 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
5818 access_state_ = MonitorAccess::Open;
5822 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(
5824 access_state_ = MonitorAccess::Exclusive;
5825 tagged_addr_ = addr;
5828 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
5829 bool is_requesting_processor) {
5830 if (access_state_ == MonitorAccess::Exclusive) {
5837 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
5838 uintptr_t addr,
bool is_requesting_processor) {
5839 if (access_state_ == MonitorAccess::Exclusive) {
5840 if (is_requesting_processor) {
5843 if (addr == tagged_addr_) {
5848 if (failure_counter_++ >= kMaxFailureCounter) {
5849 failure_counter_ = 0;
5855 }
else if ((addr & kExclusiveTaggedAddrMask) ==
5856 (tagged_addr_ & kExclusiveTaggedAddrMask)) {
5867 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
5869 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(
uintptr_t addr,
5870 Processor* processor) {
5871 processor->NotifyLoadExcl_Locked(addr);
5872 PrependProcessor_Locked(processor);
5875 void Simulator::GlobalMonitor::NotifyStore_Locked(Processor* processor) {
5877 for (Processor* iter = head_; iter; iter = iter->next_) {
5878 bool is_requesting_processor = iter == processor;
5879 iter->NotifyStore_Locked(is_requesting_processor);
5883 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(
uintptr_t addr,
5884 Processor* processor) {
5885 DCHECK(IsProcessorInLinkedList_Locked(processor));
5886 if (processor->NotifyStoreExcl_Locked(addr,
true)) {
5888 for (Processor* iter = head_; iter; iter = iter->next_) {
5889 if (iter != processor) {
5890 iter->NotifyStoreExcl_Locked(addr,
false);
5899 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
5900 Processor* processor)
const {
5901 return head_ == processor || processor->next_ || processor->prev_;
5904 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
5905 if (IsProcessorInLinkedList_Locked(processor)) {
5910 head_->prev_ = processor;
5912 processor->prev_ =
nullptr;
5913 processor->next_ = head_;
5917 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
5918 base::MutexGuard lock_guard(&mutex);
5919 if (!IsProcessorInLinkedList_Locked(processor)) {
5923 if (processor->prev_) {
5924 processor->prev_->next_ = processor->next_;
5926 head_ = processor->next_;
5928 if (processor->next_) {
5929 processor->next_->prev_ = processor->prev_;
5931 processor->prev_ =
nullptr;
5932 processor->next_ =
nullptr;
5935 #endif // USE_SIMULATOR 5940 #endif // V8_TARGET_ARCH_ARM64