9#if defined(USE_SIMULATOR)
36#if V8_ENABLE_WEBASSEMBLY
50#define COLOUR(colour_code) "\033[0;" colour_code "m"
51#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
62using TEXT_COLOUR =
char const*
const;
63TEXT_COLOUR clr_normal =
v8_flags.log_colour ? COLOUR(NORMAL) :
"";
64TEXT_COLOUR clr_flag_name =
v8_flags.log_colour ? COLOUR_BOLD(WHITE) :
"";
65TEXT_COLOUR clr_flag_value =
v8_flags.log_colour ? COLOUR(NORMAL) :
"";
66TEXT_COLOUR clr_reg_name =
v8_flags.log_colour ? COLOUR_BOLD(CYAN) :
"";
67TEXT_COLOUR clr_reg_value =
v8_flags.log_colour ? COLOUR(CYAN) :
"";
68TEXT_COLOUR clr_vreg_name =
v8_flags.log_colour ? COLOUR_BOLD(MAGENTA) :
"";
69TEXT_COLOUR clr_vreg_value =
v8_flags.log_colour ? COLOUR(MAGENTA) :
"";
70TEXT_COLOUR clr_memory_address =
v8_flags.log_colour ? COLOUR_BOLD(BLUE) :
"";
71TEXT_COLOUR clr_debug_number =
v8_flags.log_colour ? COLOUR_BOLD(YELLOW) :
"";
72TEXT_COLOUR clr_debug_message =
v8_flags.log_colour ? COLOUR(YELLOW) :
"";
73TEXT_COLOUR clr_printf =
v8_flags.log_colour ? COLOUR(GREEN) :
"";
76 Simulator::GlobalMonitor::Get)
78bool Simulator::ProbeMemory(uintptr_t address, uintptr_t access_size) {
79#if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
80 uintptr_t last_accessed_byte = address + access_size - 1;
81 uintptr_t current_pc =
reinterpret_cast<uintptr_t
>(
pc_);
82 uintptr_t landing_pad =
83 trap_handler::ProbeMemory(last_accessed_byte, current_pc);
84 if (!landing_pad)
return true;
94void Simulator::TraceSim(
const char* format, ...) {
97 va_start(arguments, format);
98 base::OS::VFPrint(stream_, format, arguments);
103const Instruction* Simulator::kEndOfSimAddress =
nullptr;
105void SimSystemRegister::SetBits(
int msb,
int lsb, uint32_t bits) {
106 int width = msb - lsb + 1;
110 uint32_t
mask = ((1 << width) - 1) << lsb;
116SimSystemRegister SimSystemRegister::DefaultValueFor(
SystemRegister id) {
119 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
121 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
128Simulator* Simulator::current(Isolate* isolate) {
129 Isolate::PerIsolateThreadData* isolate_data =
130 isolate->FindOrAllocatePerThreadDataForThisThread();
133 Simulator* sim = isolate_data->simulator();
134 if (sim ==
nullptr) {
136 sim =
new Simulator(
new Decoder<DispatchingDecoderVisitor>(), isolate);
138 sim =
new Decoder<Simulator>();
141 isolate_data->set_simulator(sim);
146void Simulator::CallImpl(
Address entry, CallArgument*
args) {
150 std::vector<int64_t> stack_args(0);
151 for (
int i = 0; !
args[
i].IsEnd();
i++) {
152 CallArgument arg =
args[
i];
153 if (arg.IsX() && (index_x < 8)) {
154 set_xreg(index_x++, arg.bits());
155 }
else if (arg.IsD() && (index_d < 8)) {
156 set_dreg_bits(index_d++, arg.bits());
158 DCHECK(arg.IsD() || arg.IsX());
159 stack_args.push_back(arg.bits());
164 uintptr_t original_stack =
sp();
165 uintptr_t entry_stack =
166 original_stack - stack_args.size() *
sizeof(stack_args[0]);
170 char* stack =
reinterpret_cast<char*
>(entry_stack);
171 std::vector<int64_t>::const_iterator it;
172 for (it = stack_args.begin(); it != stack_args.end(); it++) {
173 memcpy(stack, &(*it),
sizeof(*it));
174 stack +=
sizeof(*it);
177 DCHECK(
reinterpret_cast<uintptr_t
>(stack) <= original_stack);
182 set_lr(kEndOfSimAddress);
183 CheckPCSComplianceAndRun();
185 set_sp(original_stack);
190int PopLowestIndexAsCode(CPURegList* list) {
191 if (list->IsEmpty()) {
194 uint64_t reg_list = list->bits();
196 DCHECK((1LL << index) & reg_list);
204void Simulator::CheckPCSComplianceAndRun() {
221 saved_registers[
i] = xreg(PopLowestIndexAsCode(®ister_list));
224 saved_fpregisters[
i] = dreg_bits(PopLowestIndexAsCode(&fpregister_list));
226 int64_t original_stack =
sp();
227 int64_t original_fp = fp();
238 DCHECK_EQ(saved_registers[
i], xreg(PopLowestIndexAsCode(®ister_list)));
242 dreg_bits(PopLowestIndexAsCode(&fpregister_list)));
250 register_list.Remove(x0);
251 register_list.Remove(x1);
256 fpregister_list.Remove(d0);
258 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
259 CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
266void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
268 while (!list->IsEmpty()) {
269 unsigned code = PopLowestIndexAsCode(list);
270 set_xreg(code, value | code);
274 while (!list->IsEmpty()) {
275 unsigned code = PopLowestIndexAsCode(list);
276 set_dreg_bits(code, value | code);
281void Simulator::CorruptAllCallerSavedCPURegisters() {
286 CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue);
287 CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
292uintptr_t Simulator::PushAddress(uintptr_t address) {
295 uintptr_t* alignment_slot =
reinterpret_cast<uintptr_t*
>(new_sp +
kXRegSize);
297 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
303uintptr_t Simulator::PopAddress() {
304 intptr_t current_sp =
sp();
305 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
306 uintptr_t address = *stack_slot;
313uintptr_t Simulator::StackLimit(uintptr_t c_limit)
const {
325uintptr_t Simulator::StackBase()
const {
326 uintptr_t
result = stack_ + AllocatedStackSize() - kStackProtectionSize;
331void Simulator::SetStackLimit(uintptr_t limit) {
332 stack_limit_ =
static_cast<uintptr_t
>(limit - kAdditionalStackMargin);
335base::Vector<uint8_t> Simulator::GetCentralStackView()
const {
340 reinterpret_cast<uint8_t*
>(stack_ + kStackProtectionSize),
349 visitor->
VisitPointer(
reinterpret_cast<const void*
>(xreg(
i)));
351 for (
const void*
const* current =
352 reinterpret_cast<const void* const*
>(get_sp());
354 const void* address = *
current;
355 if (address ==
nullptr) {
362void Simulator::SetRedirectInstruction(Instruction* instruction) {
363 instruction->SetInstructionBits(
367Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
368 Isolate* isolate, FILE* stream)
371 last_debugger_input_(nullptr),
373 icount_for_stop_sim_at_(0),
376 decoder_->AppendVisitor(
this);
381 decoder_->InsertVisitorBefore(print_disasm_,
this);
386Simulator::Simulator()
389 last_debugger_input_(nullptr),
396void Simulator::Init(FILE* stream) {
400 size_t stack_size = AllocatedStackSize();
402 stack_ =
reinterpret_cast<uintptr_t
>(
new uint8_t[stack_size]());
407 print_disasm_ =
new PrintDisassembler(stream_);
411 disassembler_decoder_ =
new Decoder<DispatchingDecoderVisitor>();
412 disassembler_decoder_->AppendVisitor(print_disasm_);
414 global_monitor_ = GlobalMonitor::Get();
415 global_monitor_->PrependProcessor(&global_monitor_processor_);
418 SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
421void Simulator::ResetState() {
423 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
424 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
429 set_xreg(
i, 0xBADBEEF);
433 set_dreg_bits(
i, 0x7FF000007F800001UL);
436 set_lr(kEndOfSimAddress);
439 breakpoints_.clear();
440 break_on_next_ =
false;
442 btype_ = DefaultBType;
445Simulator::~Simulator() {
446 global_monitor_->RemoveProcessor(&global_monitor_processor_);
447 delete[]
reinterpret_cast<uint8_t*
>(stack_);
448 delete disassembler_decoder_;
449 delete print_disasm_;
453void Simulator::Run() {
456 LogAllWrittenRegisters();
458 pc_modified_ =
false;
463 while (
pc_ != kEndOfSimAddress) {
464 ExecuteInstruction();
469 while (
pc_ != kEndOfSimAddress) {
470 icount_for_stop_sim_at_ =
471 base::AddWithWraparound(icount_for_stop_sim_at_, 1);
472 if (icount_for_stop_sim_at_ ==
v8_flags.stop_sim_at) {
475 ExecuteInstruction();
480void Simulator::RunFrom(Instruction*
start) {
490#if defined(V8_OS_WIN)
491using SimulatorRuntimeCall_ReturnPtr = int64_t (*)(
492 int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4,
493 int64_t arg5, int64_t arg6, int64_t arg7, int64_t arg8, int64_t arg9,
494 int64_t arg10, int64_t arg11, int64_t arg12, int64_t arg13, int64_t arg14,
495 int64_t arg15, int64_t arg16, int64_t arg17, int64_t arg18, int64_t arg19);
499 int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4,
500 int64_t arg5, int64_t arg6, int64_t arg7, int64_t arg8, int64_t arg9,
501 int64_t arg10, int64_t arg11, int64_t arg12, int64_t arg13, int64_t arg14,
502 int64_t arg15, int64_t arg16, int64_t arg17, int64_t arg18, int64_t arg19);
504using SimulatorRuntimeCompareCall = int64_t (*)(
double arg1,
double arg2);
505using SimulatorRuntimeFPFPCall = double (*)(
double arg1,
double arg2);
506using SimulatorRuntimeFPCall = double (*)(
double arg1);
507using SimulatorRuntimeFPIntCall = double (*)(
double arg1,
int32_t arg2);
508using SimulatorRuntimeIntFPCall =
int32_t (*)(
double darg0);
511using SimulatorRuntimeFPTaggedCall = double (*)(int64_t arg0, int64_t arg1,
512 int64_t arg2, int64_t arg3);
516using SimulatorRuntimeDirectApiCall = void (*)(int64_t arg0);
519using SimulatorRuntimeDirectGetterCall = void (*)(int64_t arg0, int64_t arg1);
526 int64_t function, int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
527 int64_t arg4, int64_t arg5, int64_t arg6, int64_t arg7, int64_t arg8,
528 int64_t arg9, int64_t arg10, int64_t arg11, int64_t arg12, int64_t arg13,
529 int64_t arg14, int64_t arg15, int64_t arg16, int64_t arg17, int64_t arg18,
531 SimulatorRuntimeCall target =
532 reinterpret_cast<SimulatorRuntimeCall
>(function);
533 return target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
534 arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18,
538using MixedRuntimeCall_0 = AnyCType (*)();
540#define BRACKETS(ident, N) ident[N]
542#define REP_0(expr, FMT)
543#define REP_1(expr, FMT) FMT(expr, 0)
544#define REP_2(expr, FMT) REP_1(expr, FMT), FMT(expr, 1)
545#define REP_3(expr, FMT) REP_2(expr, FMT), FMT(expr, 2)
546#define REP_4(expr, FMT) REP_3(expr, FMT), FMT(expr, 3)
547#define REP_5(expr, FMT) REP_4(expr, FMT), FMT(expr, 4)
548#define REP_6(expr, FMT) REP_5(expr, FMT), FMT(expr, 5)
549#define REP_7(expr, FMT) REP_6(expr, FMT), FMT(expr, 6)
550#define REP_8(expr, FMT) REP_7(expr, FMT), FMT(expr, 7)
551#define REP_9(expr, FMT) REP_8(expr, FMT), FMT(expr, 8)
552#define REP_10(expr, FMT) REP_9(expr, FMT), FMT(expr, 9)
553#define REP_11(expr, FMT) REP_10(expr, FMT), FMT(expr, 10)
554#define REP_12(expr, FMT) REP_11(expr, FMT), FMT(expr, 11)
555#define REP_13(expr, FMT) REP_12(expr, FMT), FMT(expr, 12)
556#define REP_14(expr, FMT) REP_13(expr, FMT), FMT(expr, 13)
557#define REP_15(expr, FMT) REP_14(expr, FMT), FMT(expr, 14)
558#define REP_16(expr, FMT) REP_15(expr, FMT), FMT(expr, 15)
559#define REP_17(expr, FMT) REP_16(expr, FMT), FMT(expr, 16)
560#define REP_18(expr, FMT) REP_17(expr, FMT), FMT(expr, 17)
561#define REP_19(expr, FMT) REP_18(expr, FMT), FMT(expr, 18)
562#define REP_20(expr, FMT) REP_19(expr, FMT), FMT(expr, 19)
564#define GEN_MAX_PARAM_COUNT(V) \
587#define MIXED_RUNTIME_CALL(N) \
588 using MixedRuntimeCall_##N = AnyCType (*)(REP_##N(AnyCType arg, CONCAT));
590GEN_MAX_PARAM_COUNT(MIXED_RUNTIME_CALL)
591#undef MIXED_RUNTIME_CALL
593#define CALL_ARGS(N) REP_##N(args, BRACKETS)
594#define CALL_TARGET_VARARG(N) \
595 if (signature.ParameterCount() == N) { \
596 MixedRuntimeCall_##N target = \
597 reinterpret_cast<MixedRuntimeCall_##N>(target_address); \
598 result = target(CALL_ARGS(N)); \
601void Simulator::CallAnyCTypeFunction(Address target_address,
602 const EncodedCSignature& signature) {
603 TraceSim(
"Type: mixed types BUILTIN_CALL\n");
605 const int64_t* stack_pointer =
reinterpret_cast<int64_t*
>(
sp());
606 const double* double_stack_pointer =
reinterpret_cast<double*
>(
sp());
607 int num_gp_params = 0, num_fp_params = 0, num_stack_params = 0;
609 CHECK_LE(signature.ParameterCount(), kMaxCParameters);
610 static_assert(
sizeof(AnyCType) == 8,
"AnyCType is assumed to be 64-bit.");
611 AnyCType
args[kMaxCParameters];
619 for (
int i = 0;
i < signature.ParameterCount(); ++
i) {
620 if (signature.IsFloat(
i)) {
621 if (num_fp_params < 8) {
622 args[
i].double_value = dreg(num_fp_params++);
624 args[
i].double_value = double_stack_pointer[num_stack_params++];
627 if (num_gp_params < 8) {
628 args[
i].int64_value = xreg(num_gp_params++);
630 args[
i].int64_value = stack_pointer[num_stack_params++];
635 GEN_MAX_PARAM_COUNT(CALL_TARGET_VARARG)
639 static_assert(20 == kMaxCParameters,
640 "If you've changed kMaxCParameters, please change the "
641 "GEN_MAX_PARAM_COUNT macro.");
643#undef CALL_TARGET_VARARG
645#undef GEN_MAX_PARAM_COUNT
648 CorruptAllCallerSavedCPURegisters();
651 if (signature.IsReturnFloat()) {
652 set_dreg(0,
result.double_value);
654 set_xreg(0,
result.int64_value);
658void Simulator::DoRuntimeCall(Instruction*
instr) {
659 Redirection* redirection = Redirection::FromInstruction(
instr);
664 Instruction* return_address = lr();
667 reinterpret_cast<int64_t
>(redirection->external_function());
669 TraceSim(
"Call to host function at %p\n", redirection->external_function());
672 bool stack_alignment_exception = ((
sp() & 0xF) != 0);
673 if (stack_alignment_exception) {
674 TraceSim(
" with unaligned stack 0x%016" PRIx64
".\n",
sp());
675 FATAL(
"ALIGNMENT EXCEPTION");
679 reinterpret_cast<Address>(redirection->external_function());
680 SimulatorData* simulator_data =
isolate_->simulator_data();
682 const EncodedCSignature& signature =
683 simulator_data->GetSignatureForTarget(func_addr);
684 if (signature.IsValid()) {
685 CHECK(redirection->type() == ExternalReference::FAST_C_CALL);
686 CallAnyCTypeFunction(external, signature);
687 set_lr(return_address);
688 set_pc(return_address);
692 int64_t* stack_pointer =
reinterpret_cast<int64_t*
>(
sp());
694 const int64_t arg0 = xreg(0);
695 const int64_t arg1 = xreg(1);
696 const int64_t arg2 = xreg(2);
697 const int64_t arg3 = xreg(3);
698 const int64_t arg4 = xreg(4);
699 const int64_t arg5 = xreg(5);
700 const int64_t arg6 = xreg(6);
701 const int64_t arg7 = xreg(7);
702 const int64_t arg8 = stack_pointer[0];
703 const int64_t arg9 = stack_pointer[1];
704 const int64_t arg10 = stack_pointer[2];
705 const int64_t arg11 = stack_pointer[3];
706 const int64_t arg12 = stack_pointer[4];
707 const int64_t arg13 = stack_pointer[5];
708 const int64_t arg14 = stack_pointer[6];
709 const int64_t arg15 = stack_pointer[7];
710 const int64_t arg16 = stack_pointer[8];
711 const int64_t arg17 = stack_pointer[9];
712 const int64_t arg18 = stack_pointer[10];
713 const int64_t arg19 = stack_pointer[11];
714 static_assert(kMaxCParameters == 20);
716#ifdef V8_USE_MEMORY_SANITIZER
754 switch (redirection->type()) {
756 TraceSim(
"Type: Unknown.\n");
759 case ExternalReference::BUILTIN_CALL:
760#if defined(V8_OS_WIN)
763 TraceSim(
"Type: BUILTIN_CALL\n");
776 "0x%016" PRIx64
", 0x%016" PRIx64
778 "0x%016" PRIx64
", 0x%016" PRIx64
780 "0x%016" PRIx64
", 0x%016" PRIx64
782 "0x%016" PRIx64
", 0x%016" PRIx64
784 "0x%016" PRIx64
", 0x%016" PRIx64
786 "0x%016" PRIx64
", 0x%016" PRIx64
788 "0x%016" PRIx64
", 0x%016" PRIx64
790 "0x%016" PRIx64
", 0x%016" PRIx64
792 "0x%016" PRIx64
", 0x%016" PRIx64
794 "0x%016" PRIx64
", 0x%016" PRIx64,
795 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
796 arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
798 SimulatorRuntimeCall_ReturnPtr target =
799 reinterpret_cast<SimulatorRuntimeCall_ReturnPtr
>(external);
801 int64_t
result =
target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
802 arg8, arg9, arg10, arg11, arg12, arg13, arg14,
803 arg15, arg16, arg17, arg18, arg19);
804 TraceSim(
"Returned: 0x%16\n",
result);
806 CorruptAllCallerSavedCPURegisters();
813 case ExternalReference::BUILTIN_CALL_PAIR: {
816 TraceSim(
"Type: BUILTIN_CALL\n");
823 "0x%016" PRIx64
", 0x%016" PRIx64
825 "0x%016" PRIx64
", 0x%016" PRIx64
827 "0x%016" PRIx64
", 0x%016" PRIx64
829 "0x%016" PRIx64
", 0x%016" PRIx64
831 "0x%016" PRIx64
", 0x%016" PRIx64
833 "0x%016" PRIx64
", 0x%016" PRIx64
835 "0x%016" PRIx64
", 0x%016" PRIx64
837 "0x%016" PRIx64
", 0x%016" PRIx64
839 "0x%016" PRIx64
", 0x%016" PRIx64
841 "0x%016" PRIx64
", 0x%016" PRIx64,
842 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
843 arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
846 external, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
847 arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
848#ifdef V8_USE_MEMORY_SANITIZER
866 TraceSim(
"Returned: {%p, %p}\n",
reinterpret_cast<void*
>(
result.x),
867 reinterpret_cast<void*
>(
result.y));
869 CorruptAllCallerSavedCPURegisters();
871 set_xreg(0,
static_cast<int64_t
>(
result.x));
872 set_xreg(1,
static_cast<int64_t
>(
result.y));
876 case ExternalReference::BUILTIN_COMPARE_CALL: {
878 TraceSim(
"Type: BUILTIN_COMPARE_CALL\n");
879 SimulatorRuntimeCompareCall target =
880 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
881 TraceSim(
"Arguments: %f, %f\n", dreg(0), dreg(1));
883 TraceSim(
"Returned: %" PRId64
"\n",
result);
885 CorruptAllCallerSavedCPURegisters();
891 case ExternalReference::BUILTIN_FP_CALL: {
893 TraceSim(
"Type: BUILTIN_FP_CALL\n");
894 SimulatorRuntimeFPCall target =
895 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
896 TraceSim(
"Argument: %f\n", dreg(0));
898 TraceSim(
"Returned: %f\n",
result);
900 CorruptAllCallerSavedCPURegisters();
906 case ExternalReference::BUILTIN_FP_FP_CALL: {
908 TraceSim(
"Type: BUILTIN_FP_FP_CALL\n");
909 SimulatorRuntimeFPFPCall target =
910 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
911 TraceSim(
"Arguments: %f, %f\n", dreg(0), dreg(1));
913 TraceSim(
"Returned: %f\n",
result);
915 CorruptAllCallerSavedCPURegisters();
921 case ExternalReference::BUILTIN_FP_INT_CALL: {
923 TraceSim(
"Type: BUILTIN_FP_INT_CALL\n");
924 SimulatorRuntimeFPIntCall target =
925 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
926 TraceSim(
"Arguments: %f, %d\n", dreg(0), wreg(0));
928 TraceSim(
"Returned: %f\n",
result);
930 CorruptAllCallerSavedCPURegisters();
936 case ExternalReference::BUILTIN_INT_FP_CALL: {
938 TraceSim(
"Type: BUILTIN_INT_FP_CALL\n");
939 SimulatorRuntimeIntFPCall target =
940 reinterpret_cast<SimulatorRuntimeIntFPCall
>(external);
941 TraceSim(
"Argument: %f", dreg(0));
943 TraceSim(
"Returned: %d\n",
result);
945 CorruptAllCallerSavedCPURegisters();
951 case ExternalReference::BUILTIN_FP_POINTER_CALL: {
953 TraceSim(
"Type: BUILTIN_FP_POINTER_CALL\n");
954 SimulatorRuntimeFPTaggedCall target =
955 reinterpret_cast<SimulatorRuntimeFPTaggedCall
>(external);
958 "0x%016" PRIx64
", 0x%016" PRIx64
", 0x%016" PRIx64
", 0x%016" PRIx64,
959 arg0, arg1, arg2, arg3);
961 TraceSim(
"Returned: %f\n",
result);
963 CorruptAllCallerSavedCPURegisters();
969 case ExternalReference::DIRECT_API_CALL: {
971 TraceSim(
"Type: DIRECT_API_CALL\n");
972 TraceSim(
"Arguments: 0x%016" PRIx64
"\n", arg0);
973 SimulatorRuntimeDirectApiCall target =
974 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
976 TraceSim(
"No return value.");
978 CorruptAllCallerSavedCPURegisters();
983 case ExternalReference::DIRECT_GETTER_CALL: {
985 TraceSim(
"Type: DIRECT_GETTER_CALL\n");
986 TraceSim(
"Arguments: 0x%016" PRIx64
", 0x%016" PRIx64
"\n", arg0, arg1);
987 SimulatorRuntimeDirectGetterCall target =
988 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
990 TraceSim(
"No return value.");
992 CorruptAllCallerSavedCPURegisters();
998 set_lr(return_address);
999 set_pc(return_address);
1002const char* Simulator::xreg_names[] = {
1003 "x0",
"x1",
"x2",
"x3",
"x4",
"x5",
"x6",
"x7",
"x8",
"x9",
"x10",
1004 "x11",
"x12",
"x13",
"x14",
"x15",
"ip0",
"ip1",
"x18",
"x19",
"x20",
"x21",
1005 "x22",
"x23",
"x24",
"x25",
"x26",
"cp",
"x28",
"fp",
"lr",
"xzr",
"sp"};
1007const char* Simulator::wreg_names[] = {
1008 "w0",
"w1",
"w2",
"w3",
"w4",
"w5",
"w6",
"w7",
"w8",
1009 "w9",
"w10",
"w11",
"w12",
"w13",
"w14",
"w15",
"w16",
"w17",
1010 "w18",
"w19",
"w20",
"w21",
"w22",
"w23",
"w24",
"w25",
"w26",
1011 "wcp",
"w28",
"wfp",
"wlr",
"wzr",
"wsp"};
1013const char* Simulator::sreg_names[] = {
1014 "s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
"s10",
1015 "s11",
"s12",
"s13",
"s14",
"s15",
"s16",
"s17",
"s18",
"s19",
"s20",
"s21",
1016 "s22",
"s23",
"s24",
"s25",
"s26",
"s27",
"s28",
"s29",
"s30",
"s31"};
1018const char* Simulator::dreg_names[] = {
1019 "d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"d10",
1020 "d11",
"d12",
"d13",
"d14",
"d15",
"d16",
"d17",
"d18",
"d19",
"d20",
"d21",
1021 "d22",
"d23",
"d24",
"d25",
"d26",
"d27",
"d28",
"d29",
"d30",
"d31"};
1023const char* Simulator::vreg_names[] = {
1024 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
"v8",
"v9",
"v10",
1025 "v11",
"v12",
"v13",
"v14",
"v15",
"v16",
"v17",
"v18",
"v19",
"v20",
"v21",
1026 "v22",
"v23",
"v24",
"v25",
"v26",
"v27",
"v28",
"v29",
"v30",
"v31"};
1028const char* Simulator::WRegNameForCode(
unsigned code, Reg31Mode mode) {
1030 "Array must be large enough to hold all register names.");
1031 DCHECK_LT(code,
static_cast<unsigned>(kNumberOfRegisters));
1037 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
1040 return wreg_names[
code];
1043const char* Simulator::XRegNameForCode(
unsigned code, Reg31Mode mode) {
1045 "Array must be large enough to hold all register names.");
1046 DCHECK_LT(code,
static_cast<unsigned>(kNumberOfRegisters));
1050 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
1053 return xreg_names[
code];
1056const char* Simulator::SRegNameForCode(
unsigned code) {
1058 "Array must be large enough to hold all register names.");
1059 DCHECK_LT(code,
static_cast<unsigned>(kNumberOfVRegisters));
1063const char* Simulator::DRegNameForCode(
unsigned code) {
1065 "Array must be large enough to hold all register names.");
1066 DCHECK_LT(code,
static_cast<unsigned>(kNumberOfVRegisters));
1070const char* Simulator::VRegNameForCode(
unsigned code) {
1072 "Array must be large enough to hold all register names.");
1073 DCHECK_LT(code,
static_cast<unsigned>(kNumberOfVRegisters));
1077void LogicVRegister::ReadUintFromMem(VectorFormat vform,
int index,
1078 uint64_t addr)
const {
1081 register_.Insert(index, SimMemory::Read<uint8_t>(addr));
1084 register_.Insert(index, SimMemory::Read<uint16_t>(addr));
1087 register_.Insert(index, SimMemory::Read<uint32_t>(addr));
1090 register_.Insert(index, SimMemory::Read<uint64_t>(addr));
1097void LogicVRegister::WriteUintToMem(VectorFormat vform,
int index,
1098 uint64_t addr)
const {
1101 SimMemory::Write<uint8_t>(addr,
static_cast<uint8_t
>(Uint(vform, index)));
1104 SimMemory::Write<uint16_t>(addr,
1105 static_cast<uint16_t>(Uint(vform, index)));
1108 SimMemory::Write<uint32_t>(addr,
1109 static_cast<uint32_t
>(Uint(vform, index)));
1112 SimMemory::Write<uint64_t>(addr, Uint(vform, index));
1119int Simulator::CodeFromName(
const char* name) {
1121 if ((strcmp(xreg_names[
i], name) == 0) ||
1122 (strcmp(wreg_names[
i], name) == 0)) {
1127 if ((strcmp(vreg_names[
i], name) == 0) ||
1128 (strcmp(dreg_names[
i], name) == 0) ||
1129 (strcmp(sreg_names[
i], name) == 0)) {
1133 if ((strcmp(
"sp", name) == 0) || (strcmp(
"wsp", name) == 0)) {
1136 if (strcmp(
"x16", name) == 0)
return CodeFromName(
"ip0");
1137 if (strcmp(
"x17", name) == 0)
return CodeFromName(
"ip1");
1138 if (strcmp(
"x29", name) == 0)
return CodeFromName(
"fp");
1139 if (strcmp(
"x30", name) == 0)
return CodeFromName(
"lr");
1144template <
typename T>
1145T Simulator::AddWithCarry(
bool set_flags, T left, T right,
int carry_in) {
1147 static_assert(std::is_unsigned_v<T>,
"operands must be unsigned");
1149 "Only W- or X-sized operands are tested");
1151 DCHECK((carry_in == 0) || (carry_in == 1));
1152 T
result = left + right + carry_in;
1155 nzcv().SetN(CalcNFlag(
result));
1156 nzcv().SetZ(CalcZFlag(
result));
1159 T max_uint_2op = std::numeric_limits<T>::max() - carry_in;
1160 nzcv().SetC((left > max_uint_2op) || ((max_uint_2op - left) < right));
1164 T sign_mask =
T(1) << (
sizeof(
T) * 8 - 1);
1165 T left_sign = left & sign_mask;
1166 T right_sign = right & sign_mask;
1167 T result_sign =
result & sign_mask;
1168 nzcv().SetV((left_sign == right_sign) && (left_sign != result_sign));
1170 LogSystemRegister(NZCV);
1175template <
typename T>
1176void Simulator::AddSubWithCarry(Instruction*
instr) {
1178 static_assert(std::is_unsigned_v<T>,
"operands must be unsigned");
1183 if ((
instr->Mask(AddSubOpMask) == SUB) ||
instr->Mask(AddSubOpMask) == SUBS) {
1190 set_reg<T>(
instr->Rd(), new_val);
1193sim_uint128_t Simulator::PolynomialMult128(uint64_t op1, uint64_t op2,
1194 int lane_size_in_bits)
const {
1195 DCHECK_LE(
static_cast<unsigned>(lane_size_in_bits), kDRegSizeInBits);
1196 sim_uint128_t
result = std::make_pair(0, 0);
1197 sim_uint128_t op2q = std::make_pair(0, op2);
1198 for (
int i = 0;
i < lane_size_in_bits;
i++) {
1199 if ((op1 >>
i) & 1) {
1206sim_uint128_t Simulator::Lsl128(sim_uint128_t
x,
unsigned shift)
const {
1208 if (shift == 0)
return x;
1209 if (shift == 64)
return std::make_pair(
x.second, 0);
1210 uint64_t
lo =
x.second << shift;
1211 uint64_t
hi = (
x.first << shift) | (
x.second >> (64 - shift));
1212 return std::make_pair(hi, lo);
1215sim_uint128_t Simulator::Eor128(sim_uint128_t
x, sim_uint128_t
y)
const {
1216 return std::make_pair(
x.first ^
y.first,
x.second ^
y.second);
1219template <
typename T>
1220T Simulator::ShiftOperand(T value, Shift shift_type,
unsigned amount) {
1221 using unsignedT = std::make_unsigned_t<T>;
1227 DCHECK(amount <
sizeof(value) * kBitsPerByte);
1229 switch (shift_type) {
1231 return static_cast<unsignedT
>(
value) << amount;
1233 return static_cast<unsignedT
>(
value) >> amount;
1235 return value >> amount;
1237 unsignedT
mask = (
static_cast<unsignedT
>(1) << amount) - 1;
1238 return (
static_cast<unsignedT
>(value) >> amount) |
1239 ((value &
mask) << (
sizeof(
mask) * 8 - amount));
1247template <
typename T>
1248T Simulator::ExtendValue(T value, Extend extend_type,
unsigned left_shift) {
1249 const unsigned kSignExtendBShift = (
sizeof(
T) - 1) * 8;
1250 const unsigned kSignExtendHShift = (
sizeof(
T) - 2) * 8;
1251 const unsigned kSignExtendWShift = (
sizeof(
T) - 4) * 8;
1252 using unsignedT = std::make_unsigned_t<T>;
1254 switch (extend_type) {
1266 static_cast<T
>(
static_cast<unsignedT
>(
value) << kSignExtendBShift) >>
1271 static_cast<T
>(
static_cast<unsignedT
>(
value) << kSignExtendHShift) >>
1276 static_cast<T
>(
static_cast<unsignedT
>(
value) << kSignExtendWShift) >>
1285 return static_cast<T
>(
static_cast<unsignedT
>(
value) << left_shift);
1288template <
typename T>
1289void Simulator::Extract(Instruction*
instr) {
1290 unsigned lsb =
instr->ImmS();
1296 result = op2 >> lsb | (op1 << ((
sizeof(
T) * 8) - lsb));
1301void Simulator::FPCompare(
double val0,
double val1) {
1302 AssertSupportedFPCR();
1306 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
1307 nzcv().SetRawValue(FPUnorderedFlag);
1308 }
else if (val0 < val1) {
1309 nzcv().SetRawValue(FPLessThanFlag);
1310 }
else if (val0 > val1) {
1311 nzcv().SetRawValue(FPGreaterThanFlag);
1312 }
else if (val0 == val1) {
1313 nzcv().SetRawValue(FPEqualFlag);
1317 LogSystemRegister(NZCV);
1320Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
1321 size_t reg_size,
size_t lane_size) {
1324 uint32_t format = 0;
1325 if (reg_size != lane_size) {
1330 format = kPrintRegAsQVector;
1333 format = kPrintRegAsDVector;
1338 switch (lane_size) {
1342 format |= kPrintReg1Q;
1345 format |= kPrintReg1D;
1348 format |= kPrintReg1S;
1351 format |= kPrintReg1H;
1354 format |= kPrintReg1B;
1361 static_assert(kPrintXReg == kPrintReg1D,
1362 "X and D register printing code is shared.");
1363 static_assert(kPrintWReg == kPrintReg1S,
1364 "W and S register printing code is shared.");
1366 return static_cast<PrintRegisterFormat
>(format);
1369Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
1370 VectorFormat vform) {
1375 return kPrintReg16B;
1402Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1403 VectorFormat vform) {
1408 return kPrintReg4SFP;
1410 return kPrintReg2SFP;
1412 return kPrintReg2DFP;
1414 return kPrintReg1DFP;
1417 return kPrintReg1SFP;
1419 return kPrintReg1DFP;
1423void Simulator::SetBreakpoint(Instruction* location) {
1424 for (
unsigned i = 0;
i < breakpoints_.
size();
i++) {
1425 if (breakpoints_.at(
i).location == location) {
1426 PrintF(stream_,
"Existing breakpoint at %p was %s\n",
1427 reinterpret_cast<void*
>(location),
1428 breakpoints_.at(
i).enabled ?
"disabled" :
"enabled");
1429 breakpoints_.at(
i).enabled = !breakpoints_.at(
i).enabled;
1433 Breakpoint new_breakpoint = {location,
true};
1434 breakpoints_.push_back(new_breakpoint);
1435 PrintF(stream_,
"Set a breakpoint at %p\n",
1436 reinterpret_cast<void*
>(location));
1439void Simulator::ListBreakpoints() {
1440 PrintF(stream_,
"Breakpoints:\n");
1441 for (
unsigned i = 0;
i < breakpoints_.
size();
i++) {
1442 PrintF(stream_,
"%p : %s\n",
1443 reinterpret_cast<void*
>(breakpoints_.at(
i).location),
1444 breakpoints_.at(
i).enabled ?
"enabled" :
"disabled");
1448void Simulator::CheckBreakpoints() {
1449 bool hit_a_breakpoint =
false;
1450 for (
unsigned i = 0;
i < breakpoints_.
size();
i++) {
1451 if ((breakpoints_.at(
i).location ==
pc_) && breakpoints_.at(
i).enabled) {
1452 hit_a_breakpoint =
true;
1454 breakpoints_.at(
i).enabled =
false;
1457 if (hit_a_breakpoint) {
1458 PrintF(stream_,
"Hit and disabled a breakpoint at %p.\n",
1459 reinterpret_cast<void*
>(
pc_));
1464void Simulator::CheckBreakNext() {
1466 if (break_on_next_ &&
pc_->IsBranchAndLinkToRegister()) {
1467 SetBreakpoint(
pc_->following());
1468 break_on_next_ =
false;
1472void Simulator::PrintInstructionsAt(Instruction*
start, uint64_t count) {
1473 Instruction*
end =
start->InstructionAtOffset(count * kInstrSize);
1475 disassembler_decoder_->Decode(
pc);
1479void Simulator::PrintWrittenRegisters() {
1481 if (
registers_[
i].WrittenSinceLastLog()) PrintRegister(
i);
1485void Simulator::PrintWrittenVRegisters() {
1488 if (vregisters_[
i].WrittenSinceLastLog()) PrintVRegister(
i, kPrintReg1Q);
1492void Simulator::PrintSystemRegisters() {
1493 PrintSystemRegister(NZCV);
1494 PrintSystemRegister(FPCR);
1497void Simulator::PrintRegisters() {
1503void Simulator::PrintVRegisters() {
1506 PrintVRegister(
i, kPrintReg1Q);
1510void Simulator::PrintRegister(
unsigned code, Reg31Mode r31mode) {
1514 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1522 PrintRegisterRawHelper(code, r31mode);
1523 fprintf(stream_,
"\n");
1534void Simulator::PrintVRegisterRawHelper(
unsigned code,
int bytes,
int lsb) {
1539 fprintf(stream_,
"# %s%5s: %s", clr_vreg_name, VRegNameForCode(code),
1542 int msb = lsb + bytes - 1;
1546 while (
byte > msb) {
1547 fprintf(stream_,
" ");
1552 qreg_t rawbits = qreg(code);
1553 fprintf(stream_,
"0x");
1554 while (
byte >= lsb) {
1555 fprintf(stream_,
"%02x", rawbits.val[
byte]);
1561 fprintf(stream_,
" ");
1564 fprintf(stream_,
"%s", clr_normal);
1575void Simulator::PrintVRegisterFPHelper(
unsigned code,
1576 unsigned lane_size_in_bytes,
1577 int lane_count,
int rightmost_lane) {
1578 DCHECK((lane_size_in_bytes == kSRegSize) ||
1579 (lane_size_in_bytes == kDRegSize));
1581 unsigned msb = (lane_count + rightmost_lane) * lane_size_in_bytes;
1582 DCHECK_LE(msb,
static_cast<unsigned>(kQRegSize));
1590 if ((lane_count == 1) && (rightmost_lane == 0)) {
1591 const char* name = (lane_size_in_bytes ==
kSRegSize)
1592 ? SRegNameForCode(code)
1593 : DRegNameForCode(code);
1594 fprintf(stream_,
" (%s%s: ", clr_vreg_name, name);
1596 if (msb < (kQRegSize - 1)) {
1597 fprintf(stream_,
" (..., ");
1599 fprintf(stream_,
" (");
1605 int leftmost_lane = rightmost_lane + lane_count - 1;
1606 for (
int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
1607 double value = (lane_size_in_bytes ==
kSRegSize)
1608 ? vreg(code).Get<
float>(lane)
1609 : vreg(code).
Get<double>(lane);
1610 fprintf(stream_,
"%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
1614 if (rightmost_lane > 0) {
1615 fprintf(stream_,
", ...");
1617 fprintf(stream_,
")");
1632void Simulator::PrintRegisterRawHelper(
unsigned code, Reg31Mode r31mode,
1633 int size_in_bytes) {
1639 unsigned padding_chars = (
kXRegSize - size_in_bytes) * 2;
1641 const char* name =
"";
1642 const char* suffix =
"";
1643 switch (size_in_bytes) {
1645 name = XRegNameForCode(code, r31mode);
1648 name = WRegNameForCode(code, r31mode);
1651 name = WRegNameForCode(code, r31mode);
1653 padding_chars -= strlen(suffix);
1656 name = WRegNameForCode(code, r31mode);
1658 padding_chars -= strlen(suffix);
1663 fprintf(stream_,
"# %s%5s%s: ", clr_reg_name, name, suffix);
1666 DCHECK_LT(padding_chars, kXRegSize * 2U);
1667 for (
unsigned i = 0;
i < padding_chars;
i++) {
1674 static_assert(
sizeof(bits) ==
kXRegSize,
1675 "X registers and uint64_t must be the same size.");
1677 int chars = size_in_bytes * 2;
1678 fprintf(stream_,
"%s0x%0*" PRIx64
"%s", clr_reg_value, chars, bits,
1682void Simulator::PrintVRegister(
unsigned code, PrintRegisterFormat format) {
1683 vregisters_[
code].NotifyRegisterLogged();
1685 int lane_size_log2 = format & kPrintRegLaneSizeMask;
1688 if (format & kPrintRegAsQVector) {
1690 }
else if (format & kPrintRegAsDVector) {
1694 reg_size_log2 = lane_size_log2;
1697 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1698 int lane_size = 1 << lane_size_log2;
1707 PrintVRegisterRawHelper(code);
1708 if (format & kPrintRegAsFP) {
1709 PrintVRegisterFPHelper(code, lane_size, lane_count);
1712 fprintf(stream_,
"\n");
1715void Simulator::PrintSystemRegister(SystemRegister
id) {
1718 fprintf(stream_,
"# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n", clr_flag_name,
1719 clr_flag_value, nzcv().
N(), nzcv().Z(), nzcv().C(), nzcv().
V(),
1723 static const char* rmode[] = {
1724 "0b00 (Round to Nearest)",
"0b01 (Round towards Plus Infinity)",
1725 "0b10 (Round towards Minus Infinity)",
"0b11 (Round towards Zero)"};
1727 fprintf(stream_,
"# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1728 clr_flag_name, clr_flag_value, fpcr().AHP(), fpcr().DN(),
1729 fpcr().FZ(), rmode[fpcr().RMode()], clr_normal);
1737void Simulator::PrintRead(uintptr_t address,
unsigned reg_code,
1738 PrintRegisterFormat format) {
1744 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1745 fprintf(stream_,
" <- %s0x%016" PRIxPTR
"%s\n", clr_memory_address, address,
1749void Simulator::PrintVRead(uintptr_t address,
unsigned reg_code,
1750 PrintRegisterFormat format,
unsigned lane) {
1751 vregisters_[reg_code].NotifyRegisterLogged();
1754 PrintVRegisterRawHelper(reg_code);
1755 if (format & kPrintRegAsFP) {
1756 PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
1757 GetPrintRegLaneCount(format), lane);
1759 fprintf(stream_,
" <- %s0x%016" PRIxPTR
"%s\n", clr_memory_address, address,
1763void Simulator::PrintWrite(uintptr_t address,
unsigned reg_code,
1764 PrintRegisterFormat format) {
1765 DCHECK_EQ(GetPrintRegLaneCount(format), 1U);
1769 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
1770 GetPrintRegSizeInBytes(format));
1771 fprintf(stream_,
" -> %s0x%016" PRIxPTR
"%s\n", clr_memory_address, address,
1775void Simulator::PrintVWrite(uintptr_t address,
unsigned reg_code,
1776 PrintRegisterFormat format,
unsigned lane) {
1785 int lane_count = GetPrintRegLaneCount(format);
1786 int lane_size = GetPrintRegLaneSizeInBytes(format);
1787 int reg_size = GetPrintRegSizeInBytes(format);
1788 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1789 if (format & kPrintRegAsFP) {
1790 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1792 fprintf(stream_,
" -> %s0x%016" PRIxPTR
"%s\n", clr_memory_address, address,
1798void Simulator::VisitUnimplemented(Instruction*
instr) {
1799 fprintf(stream_,
"Unimplemented instruction at %p: 0x%08" PRIx32
"\n",
1800 reinterpret_cast<void*
>(
instr),
instr->InstructionBits());
1804void Simulator::VisitUnallocated(Instruction*
instr) {
1805 fprintf(stream_,
"Unallocated instruction at %p: 0x%08" PRIx32
"\n",
1806 reinterpret_cast<void*
>(
instr),
instr->InstructionBits());
1810void Simulator::VisitPCRelAddressing(Instruction*
instr) {
1811 switch (
instr->Mask(PCRelAddressingMask)) {
1813 set_reg(
instr->Rd(),
instr->ImmPCOffsetTarget());
1822void Simulator::VisitUnconditionalBranch(Instruction*
instr) {
1823 switch (
instr->Mask(UnconditionalBranchMask)) {
1825 set_lr(
instr->following());
1828 set_pc(
instr->ImmPCOffsetTarget());
1835void Simulator::VisitConditionalBranch(Instruction*
instr) {
1836 DCHECK(
instr->Mask(ConditionalBranchMask) == B_cond);
1837 if (ConditionPassed(
static_cast<Condition>(
instr->ConditionBranch()))) {
1838 set_pc(
instr->ImmPCOffsetTarget());
1842Simulator::BType Simulator::GetBTypeFromInstruction(
1843 const Instruction*
instr)
const {
1844 switch (
instr->Mask(UnconditionalBranchToRegisterMask)) {
1846 return BranchAndLink;
1848 if (!PcIsInGuardedPage() || (
instr->Rn() == 16) || (
instr->Rn() == 17)) {
1849 return BranchFromUnguardedOrToIP;
1851 return BranchFromGuardedNotToIP;
1853 return DefaultBType;
1856void Simulator::VisitUnconditionalBranchToRegister(Instruction*
instr) {
1858 switch (
instr->Mask(UnconditionalBranchToRegisterMask)) {
1860 set_lr(
instr->following());
1861 if (
instr->Rn() == 31) {
1875 set_btype(GetBTypeFromInstruction(
instr));
1878void Simulator::VisitTestBranch(Instruction*
instr) {
1880 (
instr->ImmTestBranchBit5() << 5) |
instr->ImmTestBranchBit40();
1881 bool take_branch = ((xreg(
instr->Rt()) & (1ULL << bit_pos)) == 0);
1882 switch (
instr->Mask(TestBranchMask)) {
1886 take_branch = !take_branch;
1892 set_pc(
instr->ImmPCOffsetTarget());
1896void Simulator::VisitCompareBranch(Instruction*
instr) {
1897 unsigned rt =
instr->Rt();
1898 bool take_branch =
false;
1899 switch (
instr->Mask(CompareBranchMask)) {
1901 take_branch = (wreg(rt) == 0);
1904 take_branch = (xreg(rt) == 0);
1907 take_branch = (wreg(rt) != 0);
1910 take_branch = (xreg(rt) != 0);
1916 set_pc(
instr->ImmPCOffsetTarget());
1920template <
typename T>
1921void Simulator::AddSubHelper(Instruction*
instr, T op2) {
1923 static_assert(std::is_unsigned_v<T>,
"operands must be unsigned");
1925 bool set_flags =
instr->FlagsUpdate();
1929 switch (operation) {
1946 set_reg<T>(
instr->Rd(), new_val,
instr->RdMode());
1949void Simulator::VisitAddSubShifted(Instruction*
instr) {
1951 unsigned shift_amount =
instr->ImmDPShift();
1953 if (
instr->SixtyFourBits()) {
1954 uint64_t op2 = ShiftOperand(xreg(
instr->Rm()), shift_type, shift_amount);
1955 AddSubHelper(
instr, op2);
1957 uint32_t op2 = ShiftOperand(wreg(
instr->Rm()), shift_type, shift_amount);
1958 AddSubHelper(
instr, op2);
1962void Simulator::VisitAddSubImmediate(Instruction*
instr) {
1963 int64_t op2 =
instr->ImmAddSub() << ((
instr->ShiftAddSub() == 1) ? 12 : 0);
1964 if (
instr->SixtyFourBits()) {
1965 AddSubHelper(
instr,
static_cast<uint64_t
>(op2));
1967 AddSubHelper(
instr,
static_cast<uint32_t
>(op2));
1971void Simulator::VisitAddSubExtended(Instruction*
instr) {
1973 unsigned left_shift =
instr->ImmExtendShift();
1974 if (
instr->SixtyFourBits()) {
1975 uint64_t op2 = ExtendValue(xreg(
instr->Rm()), ext, left_shift);
1976 AddSubHelper(
instr, op2);
1978 uint32_t op2 = ExtendValue(wreg(
instr->Rm()), ext, left_shift);
1979 AddSubHelper(
instr, op2);
1983void Simulator::VisitAddSubWithCarry(Instruction*
instr) {
1984 if (
instr->SixtyFourBits()) {
1985 AddSubWithCarry<uint64_t>(
instr);
1987 AddSubWithCarry<uint32_t>(
instr);
1991void Simulator::VisitLogicalShifted(Instruction*
instr) {
1993 unsigned shift_amount =
instr->ImmDPShift();
1995 if (
instr->SixtyFourBits()) {
1996 uint64_t op2 = ShiftOperand(xreg(
instr->Rm()), shift_type, shift_amount);
1997 op2 = (
instr->Mask(NOT) == NOT) ? ~op2 : op2;
1998 LogicalHelper(
instr, op2);
2000 uint32_t op2 = ShiftOperand(wreg(
instr->Rm()), shift_type, shift_amount);
2001 op2 = (
instr->Mask(NOT) == NOT) ? ~op2 : op2;
2002 LogicalHelper(
instr, op2);
2006void Simulator::VisitLogicalImmediate(Instruction*
instr) {
2007 if (
instr->SixtyFourBits()) {
2008 LogicalHelper(
instr,
static_cast<uint64_t
>(
instr->ImmLogical()));
2010 LogicalHelper(
instr,
static_cast<uint32_t
>(
instr->ImmLogical()));
2014template <
typename T>
2015void Simulator::LogicalHelper(Instruction*
instr, T op2) {
2018 bool update_flags =
false;
2022 switch (
instr->Mask(LogicalOpMask & ~NOT)) {
2024 update_flags =
true;
2040 nzcv().SetN(CalcNFlag(
result));
2041 nzcv().SetZ(CalcZFlag(
result));
2044 LogSystemRegister(NZCV);
2050void Simulator::VisitConditionalCompareRegister(Instruction*
instr) {
2051 if (
instr->SixtyFourBits()) {
2052 ConditionalCompareHelper(
instr,
static_cast<uint64_t
>(xreg(
instr->Rm())));
2054 ConditionalCompareHelper(
instr,
static_cast<uint32_t
>(wreg(
instr->Rm())));
2058void Simulator::VisitConditionalCompareImmediate(Instruction*
instr) {
2059 if (
instr->SixtyFourBits()) {
2060 ConditionalCompareHelper(
instr,
static_cast<uint64_t
>(
instr->ImmCondCmp()));
2062 ConditionalCompareHelper(
instr,
static_cast<uint32_t
>(
instr->ImmCondCmp()));
2066template <
typename T>
2067void Simulator::ConditionalCompareHelper(Instruction*
instr, T op2) {
2069 static_assert(std::is_unsigned_v<T>,
"operands must be unsigned");
2073 if (ConditionPassed(
static_cast<Condition>(
instr->Condition()))) {
2076 if (
instr->Mask(ConditionalCompareMask) == CCMP) {
2077 AddWithCarry<T>(
true, op1, ~op2, 1);
2079 DCHECK(
instr->Mask(ConditionalCompareMask) == CCMN);
2080 AddWithCarry<T>(
true, op1, op2, 0);
2084 nzcv().SetFlags(
instr->Nzcv());
2085 LogSystemRegister(NZCV);
2089void Simulator::VisitLoadStoreUnsignedOffset(Instruction*
instr) {
2094void Simulator::VisitLoadStoreUnscaledOffset(Instruction*
instr) {
2095 LoadStoreHelper(
instr,
instr->ImmLS(), Offset);
2098void Simulator::VisitLoadStorePreIndex(Instruction*
instr) {
2099 LoadStoreHelper(
instr,
instr->ImmLS(), PreIndex);
2102void Simulator::VisitLoadStorePostIndex(Instruction*
instr) {
2103 LoadStoreHelper(
instr,
instr->ImmLS(), PostIndex);
2106void Simulator::VisitLoadStoreRegisterOffset(Instruction*
instr) {
2108 DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
2109 unsigned shift_amount =
instr->ImmShiftLS() *
instr->SizeLS();
2111 int64_t
offset = ExtendValue(xreg(
instr->Rm()), ext, shift_amount);
2115void Simulator::LoadStoreHelper(Instruction*
instr, int64_t
offset,
2116 AddrMode addrmode) {
2117 unsigned srcdst =
instr->Rt();
2118 unsigned addr_reg =
instr->Rn();
2119 uintptr_t address = LoadStoreAddress(addr_reg,
offset, addrmode);
2120 uintptr_t stack = 0;
2122 unsigned access_size = 1 <<
instr->SizeLS();
2124 if (!ProbeMemory(address, access_size))
return;
2127 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2128 if (
instr->IsLoad()) {
2129 local_monitor_.NotifyLoad();
2131 local_monitor_.NotifyStore();
2132 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2143 if (
instr->IsStore()) {
2144 LoadStoreWriteBack(addr_reg,
offset, addrmode);
2156 set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address));
2159 set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address));
2162 set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address));
2165 set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address));
2168 set_wreg_no_log(srcdst, MemoryRead<int8_t>(address));
2171 set_wreg_no_log(srcdst, MemoryRead<int16_t>(address));
2174 set_xreg_no_log(srcdst, MemoryRead<int8_t>(address));
2177 set_xreg_no_log(srcdst, MemoryRead<int16_t>(address));
2180 set_xreg_no_log(srcdst, MemoryRead<int32_t>(address));
2183 set_breg_no_log(srcdst, MemoryRead<uint8_t>(address));
2186 set_hreg_no_log(srcdst, MemoryRead<uint16_t>(address));
2189 set_sreg_no_log(srcdst, MemoryRead<float>(address));
2192 set_dreg_no_log(srcdst, MemoryRead<double>(address));
2195 set_qreg_no_log(srcdst, MemoryRead<qreg_t>(address));
2199 MemoryWrite<uint8_t>(address, wreg(srcdst));
2202 MemoryWrite<uint16_t>(address, wreg(srcdst));
2205 MemoryWrite<uint32_t>(address, wreg(srcdst));
2208 MemoryWrite<uint64_t>(address, xreg(srcdst));
2211 MemoryWrite<uint8_t>(address, breg(srcdst));
2214 MemoryWrite<uint16_t>(address, hreg(srcdst));
2217 MemoryWrite<float>(address, sreg(srcdst));
2220 MemoryWrite<double>(address, dreg(srcdst));
2223 MemoryWrite<qreg_t>(address, qreg(srcdst));
2232 if (
instr->IsLoad()) {
2233 if ((op == LDR_s) || (op == LDR_d)) {
2234 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
2235 }
else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
2236 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2238 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2241 if ((op == STR_s) || (op == STR_d)) {
2242 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
2243 }
else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
2244 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2246 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2254 if (
instr->IsLoad()) {
2259 LoadStoreWriteBack(addr_reg,
offset, addrmode);
2264 CheckMemoryAccess(address, stack);
2267void Simulator::VisitLoadStorePairOffset(Instruction*
instr) {
2268 LoadStorePairHelper(
instr, Offset);
2271void Simulator::VisitLoadStorePairPreIndex(Instruction*
instr) {
2272 LoadStorePairHelper(
instr, PreIndex);
2275void Simulator::VisitLoadStorePairPostIndex(Instruction*
instr) {
2276 LoadStorePairHelper(
instr, PostIndex);
2279void Simulator::LoadStorePairHelper(Instruction*
instr, AddrMode addrmode) {
2280 unsigned rt =
instr->Rt();
2281 unsigned rt2 =
instr->Rt2();
2282 unsigned addr_reg =
instr->Rn();
2283 size_t access_size = 1ULL <<
instr->SizeLSPair();
2284 int64_t
offset =
instr->ImmLSPair() * access_size;
2285 uintptr_t address = LoadStoreAddress(addr_reg,
offset, addrmode);
2286 uintptr_t address2 = address + access_size;
2287 uintptr_t stack = 0;
2290 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2291 if (
instr->IsLoad()) {
2292 local_monitor_.NotifyLoad();
2294 local_monitor_.NotifyStore();
2295 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2306 if (
instr->IsStore()) {
2307 LoadStoreWriteBack(addr_reg,
offset, addrmode);
2318 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2324 DCHECK_EQ(access_size,
static_cast<unsigned>(kWRegSize));
2325 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2326 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
2330 DCHECK_EQ(access_size,
static_cast<unsigned>(kSRegSize));
2331 set_sreg_no_log(rt, MemoryRead<float>(address));
2332 set_sreg_no_log(rt2, MemoryRead<float>(address2));
2336 DCHECK_EQ(access_size,
static_cast<unsigned>(kXRegSize));
2337 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2338 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
2342 DCHECK_EQ(access_size,
static_cast<unsigned>(kDRegSize));
2343 set_dreg_no_log(rt, MemoryRead<double>(address));
2344 set_dreg_no_log(rt2, MemoryRead<double>(address2));
2348 DCHECK_EQ(access_size,
static_cast<unsigned>(kQRegSize));
2349 set_qreg(rt, MemoryRead<qreg_t>(address), NoRegLog);
2350 set_qreg(rt2, MemoryRead<qreg_t>(address2), NoRegLog);
2354 DCHECK_EQ(access_size,
static_cast<unsigned>(kWRegSize));
2355 set_xreg_no_log(rt, MemoryRead<int32_t>(address));
2356 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
2360 DCHECK_EQ(access_size,
static_cast<unsigned>(kWRegSize));
2361 MemoryWrite<uint32_t>(address, wreg(rt));
2362 MemoryWrite<uint32_t>(address2, wreg(rt2));
2366 DCHECK_EQ(access_size,
static_cast<unsigned>(kSRegSize));
2367 MemoryWrite<float>(address, sreg(rt));
2368 MemoryWrite<float>(address2, sreg(rt2));
2372 DCHECK_EQ(access_size,
static_cast<unsigned>(kXRegSize));
2373 MemoryWrite<uint64_t>(address, xreg(rt));
2374 MemoryWrite<uint64_t>(address2, xreg(rt2));
2378 DCHECK_EQ(access_size,
static_cast<unsigned>(kDRegSize));
2379 MemoryWrite<double>(address, dreg(rt));
2380 MemoryWrite<double>(address2, dreg(rt2));
2384 DCHECK_EQ(access_size,
static_cast<unsigned>(kQRegSize));
2385 MemoryWrite<qreg_t>(address, qreg(rt));
2386 MemoryWrite<qreg_t>(address2, qreg(rt2));
2395 if (
instr->IsLoad()) {
2396 if ((op == LDP_s) || (op == LDP_d)) {
2397 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
2398 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2399 }
else if (op == LDP_q) {
2400 LogVRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2401 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2403 LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2404 LogRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2407 if ((op == STP_s) || (op == STP_d)) {
2408 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
2409 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2410 }
else if (op == STP_q) {
2411 LogVWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2412 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2414 LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2415 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
2423 if (
instr->IsLoad()) {
2428 LoadStoreWriteBack(addr_reg,
offset, addrmode);
2433 CheckMemoryAccess(address, stack);
2436void Simulator::VisitLoadLiteral(Instruction*
instr) {
2437 uintptr_t address =
instr->LiteralAddress();
2438 unsigned rt =
instr->Rt();
2441 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2442 local_monitor_.NotifyLoad();
2445 switch (
instr->Mask(LoadLiteralMask)) {
2449 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2450 LogRead(address, rt, kPrintWReg);
2453 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2454 LogRead(address, rt, kPrintXReg);
2457 set_sreg_no_log(rt, MemoryRead<float>(address));
2458 LogVRead(address, rt, kPrintSReg);
2461 set_dreg_no_log(rt, MemoryRead<double>(address));
2462 LogVRead(address, rt, kPrintDReg);
2469uintptr_t Simulator::LoadStoreAddress(
unsigned addr_reg, int64_t
offset,
2470 AddrMode addrmode) {
2472 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
2473 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
2477 FATAL(
"ALIGNMENT EXCEPTION");
2480 if ((addrmode == Offset) || (addrmode == PreIndex)) {
2487void Simulator::LoadStoreWriteBack(
unsigned addr_reg, int64_t
offset,
2488 AddrMode addrmode) {
2489 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2491 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
2492 set_reg(addr_reg, address +
offset, Reg31IsStackPointer);
2496Simulator::TransactionSize Simulator::get_transaction_size(
unsigned size) {
2499 return TransactionSize::None;
2501 return TransactionSize::Byte;
2503 return TransactionSize::HalfWord;
2505 return TransactionSize::Word;
2507 return TransactionSize::DoubleWord;
2513void Simulator::VisitLoadStoreAcquireRelease(Instruction*
instr) {
2514 unsigned rt =
instr->Rt();
2515 unsigned rn =
instr->Rn();
2517 instr->Mask(LoadStoreAcquireReleaseMask));
2524 CompareAndSwapHelper<uint32_t>(
instr);
2530 CompareAndSwapHelper<uint64_t>(
instr);
2536 CompareAndSwapHelper<uint8_t>(
instr);
2542 CompareAndSwapHelper<uint16_t>(
instr);
2548 CompareAndSwapPairHelper<uint32_t>(
instr);
2554 CompareAndSwapPairHelper<uint64_t>(
instr);
2560 int32_t is_acquire_release =
instr->LoadStoreXAcquireRelease();
2561 int32_t is_exclusive = (
instr->LoadStoreXNotExclusive() == 0);
2564 USE(is_acquire_release);
2568 unsigned access_size = 1 <<
instr->LoadStoreXSizeLog2();
2569 uintptr_t address = LoadStoreAddress(rn, 0, AddrMode::Offset);
2572 if (!ProbeMemory(address, access_size))
return;
2573 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2577 local_monitor_.NotifyLoadExcl(address, get_transaction_size(access_size));
2578 global_monitor_->NotifyLoadExcl_Locked(address,
2579 &global_monitor_processor_);
2581 local_monitor_.NotifyLoad();
2586 set_wreg_no_log(rt, MemoryRead<uint8_t>(address));
2590 set_wreg_no_log(rt, MemoryRead<uint16_t>(address));
2594 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
2598 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
2603 LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2606 unsigned rs =
instr->Rs();
2609 if (local_monitor_.NotifyStoreExcl(address,
2610 get_transaction_size(access_size)) &&
2611 global_monitor_->NotifyStoreExcl_Locked(address,
2612 &global_monitor_processor_)) {
2615 MemoryWrite<uint8_t>(address, wreg(rt));
2618 MemoryWrite<uint16_t>(address, wreg(rt));
2621 MemoryWrite<uint32_t>(address, wreg(rt));
2624 MemoryWrite<uint64_t>(address, xreg(rt));
2629 LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2635 local_monitor_.NotifyStore();
2636 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2639 MemoryWrite<uint8_t>(address, wreg(rt));
2642 MemoryWrite<uint16_t>(address, wreg(rt));
2645 MemoryWrite<uint32_t>(address, wreg(rt));
2648 MemoryWrite<uint64_t>(address, xreg(rt));
2657template <
typename T>
2658void Simulator::CompareAndSwapHelper(
const Instruction*
instr) {
2659 unsigned rs =
instr->Rs();
2660 unsigned rt =
instr->Rt();
2661 unsigned rn =
instr->Rn();
2663 unsigned element_size =
sizeof(
T);
2667 if (!ProbeMemory(address, element_size))
return;
2669 bool is_acquire =
instr->Bit(22) == 1;
2670 bool is_release =
instr->Bit(15) == 1;
2672 T comparevalue =
reg<T>(rs);
2677 local_monitor_.NotifyLoad();
2679 T data = MemoryRead<T>(address);
2682 std::atomic_thread_fence(std::memory_order_seq_cst);
2685 if (data == comparevalue) {
2686 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2689 local_monitor_.NotifyStore();
2690 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2692 std::atomic_thread_fence(std::memory_order_seq_cst);
2695 MemoryWrite<T>(address, newvalue);
2696 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2699 set_reg<T>(rs, data);
2700 LogRead(address, rs, GetPrintRegisterFormatForSize(element_size));
2703template <
typename T>
2704void Simulator::CompareAndSwapPairHelper(
const Instruction*
instr) {
2705 DCHECK((
sizeof(T) == 4) || (
sizeof(T) == 8));
2706 unsigned rs =
instr->Rs();
2707 unsigned rt =
instr->Rt();
2708 unsigned rn =
instr->Rn();
2710 DCHECK((rs % 2 == 0) && (rt % 2 == 0));
2712 unsigned element_size =
sizeof(
T);
2715 uint64_t address2 = address + element_size;
2718 if (!ProbeMemory(address, element_size))
return;
2719 if (!ProbeMemory(address2, element_size))
return;
2721 bool is_acquire =
instr->Bit(22) == 1;
2722 bool is_release =
instr->Bit(15) == 1;
2724 T comparevalue_high =
reg<T>(rs + 1);
2725 T comparevalue_low =
reg<T>(rs);
2726 T newvalue_high =
reg<T>(rt + 1);
2727 T newvalue_low =
reg<T>(rt);
2731 local_monitor_.NotifyLoad();
2733 T data_low = MemoryRead<T>(address);
2734 T data_high = MemoryRead<T>(address2);
2738 std::atomic_thread_fence(std::memory_order_seq_cst);
2742 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2744 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2747 local_monitor_.NotifyStore();
2748 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2750 std::atomic_thread_fence(std::memory_order_seq_cst);
2753 MemoryWrite<T>(address, newvalue_low);
2754 MemoryWrite<T>(address2, newvalue_high);
2757 set_reg<T>(rs + 1, data_high);
2758 set_reg<T>(rs, data_low);
2760 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2761 LogRead(address, rs, format);
2762 LogRead(address2, rs + 1, format);
2765 LogWrite(address, rt, format);
2766 LogWrite(address2, rt + 1, format);
2770template <
typename T>
2771void Simulator::AtomicMemorySimpleHelper(
const Instruction*
instr) {
2772 unsigned rs =
instr->Rs();
2773 unsigned rt =
instr->Rt();
2774 unsigned rn =
instr->Rn();
2777 bool is_release =
instr->Bit(22) == 1;
2779 unsigned element_size =
sizeof(
T);
2780 uint64_t address = xreg(rn, Reg31IsStackPointer);
2784 if (!ProbeMemory(address, element_size))
return;
2786 local_monitor_.NotifyLoad();
2790 T data = MemoryRead<T>(address);
2794 std::atomic_thread_fence(std::memory_order_seq_cst);
2798 switch (
instr->Mask(AtomicMemorySimpleOpMask)) {
2803 DCHECK(!std::numeric_limits<T>::is_signed);
2807 DCHECK(!std::numeric_limits<T>::is_signed);
2811 DCHECK(!std::numeric_limits<T>::is_signed);
2827 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2828 local_monitor_.NotifyStore();
2829 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2831 std::atomic_thread_fence(std::memory_order_seq_cst);
2834 MemoryWrite<T>(address,
result);
2835 set_reg<T>(rt, data);
2837 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2838 LogRead(address, rt, format);
2839 LogWrite(address, rs, format);
2842template <
typename T>
2843void Simulator::AtomicMemorySwapHelper(
const Instruction*
instr) {
2844 unsigned rs =
instr->Rs();
2845 unsigned rt =
instr->Rt();
2846 unsigned rn =
instr->Rn();
2849 bool is_release =
instr->Bit(22) == 1;
2851 unsigned element_size =
sizeof(
T);
2852 uint64_t address = xreg(rn, Reg31IsStackPointer);
2855 if (!ProbeMemory(address, element_size))
return;
2857 local_monitor_.NotifyLoad();
2859 T data = MemoryRead<T>(address);
2862 std::atomic_thread_fence(std::memory_order_seq_cst);
2866 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
2867 local_monitor_.NotifyStore();
2868 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
2870 std::atomic_thread_fence(std::memory_order_seq_cst);
2872 MemoryWrite<T>(address,
reg<T>(rs));
2874 set_reg<T>(rt, data);
2876 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2877 LogRead(address, rt, format);
2878 LogWrite(address, rs, format);
2881#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2889#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2893void Simulator::VisitAtomicMemory(Instruction*
instr) {
2894 switch (
instr->Mask(AtomicMemoryMask)) {
2896#define SIM_FUNC_B(A) \
2901#define SIM_FUNC_H(A) \
2906#define SIM_FUNC_w(A) \
2911#define SIM_FUNC_x(A) \
2917 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2918 AtomicMemorySimpleHelper<uint8_t>(
instr);
2920 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2921 AtomicMemorySimpleHelper<int8_t>(
instr);
2923 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2924 AtomicMemorySimpleHelper<uint16_t>(
instr);
2926 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2927 AtomicMemorySimpleHelper<int16_t>(
instr);
2929 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2930 AtomicMemorySimpleHelper<uint32_t>(
instr);
2932 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2933 AtomicMemorySimpleHelper<int32_t>(
instr);
2935 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2936 AtomicMemorySimpleHelper<uint64_t>(
instr);
2938 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2939 AtomicMemorySimpleHelper<int64_t>(
instr);
2947 AtomicMemorySwapHelper<uint8_t>(
instr);
2953 AtomicMemorySwapHelper<uint16_t>(
instr);
2959 AtomicMemorySwapHelper<uint32_t>(
instr);
2965 AtomicMemorySwapHelper<uint64_t>(
instr);
2970void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
2972 fprintf(stream_,
"ACCESS BELOW STACK POINTER:\n");
2973 fprintf(stream_,
" sp is here: 0x%016" PRIx64
"\n",
2974 static_cast<uint64_t
>(stack));
2975 fprintf(stream_,
" access was here: 0x%016" PRIx64
"\n",
2976 static_cast<uint64_t
>(address));
2977 fprintf(stream_,
" stack limit is here: 0x%016" PRIx64
"\n",
2979 fprintf(stream_,
"\n");
2980 FATAL(
"ACCESS BELOW STACK POINTER");
2984void Simulator::VisitMoveWideImmediate(Instruction*
instr) {
2987 int64_t new_xn_val = 0;
2989 bool is_64_bits =
instr->SixtyFourBits() == 1;
2991 DCHECK(is_64_bits || (
instr->ShiftMoveWide() < 2));
2994 int64_t shift =
instr->ShiftMoveWide() * 16;
2995 int64_t shifted_imm16 =
static_cast<int64_t
>(
instr->ImmMoveWide()) << shift;
3001 new_xn_val = ~shifted_imm16;
3002 if (!is_64_bits) new_xn_val &=
kWRegMask;
3007 unsigned reg_code =
instr->Rd();
3008 int64_t prev_xn_val = is_64_bits ? xreg(reg_code) : wreg(reg_code);
3009 new_xn_val = (prev_xn_val & ~(INT64_C(0xFFFF) << shift)) | shifted_imm16;
3014 new_xn_val = shifted_imm16;
3022 set_xreg(
instr->Rd(), new_xn_val);
3025void Simulator::VisitConditionalSelect(Instruction*
instr) {
3026 uint64_t new_val = xreg(
instr->Rn());
3027 if (ConditionFailed(
static_cast<Condition>(
instr->Condition()))) {
3028 new_val = xreg(
instr->Rm());
3029 switch (
instr->Mask(ConditionalSelectMask)) {
3045 new_val = (~new_val) + 1;
3051 if (
instr->SixtyFourBits()) {
3052 set_xreg(
instr->Rd(), new_val);
3054 set_wreg(
instr->Rd(),
static_cast<uint32_t
>(new_val));
3058void Simulator::VisitDataProcessing1Source(Instruction*
instr) {
3059 unsigned dst =
instr->Rd();
3060 unsigned src =
instr->Rn();
3062 switch (
instr->Mask(DataProcessing1SourceMask)) {
3064 set_wreg(dst, base::bits::ReverseBits(wreg(src)));
3067 set_xreg(dst, base::bits::ReverseBits(xreg(src)));
3103template <
typename T>
3104void Simulator::DataProcessing2Source(Instruction*
instr) {
3107 switch (
instr->Mask(DataProcessing2SourceMask)) {
3112 if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) {
3113 result = std::numeric_limits<T>::min();
3114 }
else if (rm == 0) {
3124 using unsignedT = std::make_unsigned_t<T>;
3125 unsignedT rn =
static_cast<unsignedT
>(
reg<T>(
instr->Rn()));
3126 unsignedT rm =
static_cast<unsignedT
>(
reg<T>(
instr->Rm()));
3155 if (shift_op != NO_SHIFT) {
3158 unsigned shift = wreg(
instr->Rm());
3159 if (
sizeof(T) == kWRegSize) {
3169void Simulator::VisitDataProcessing2Source(Instruction*
instr) {
3170 if (
instr->SixtyFourBits()) {
3171 DataProcessing2Source<int64_t>(
instr);
3173 DataProcessing2Source<int32_t>(
instr);
3177void Simulator::VisitDataProcessing3Source(Instruction*
instr) {
3184 switch (
instr->Mask(DataProcessing3SourceMask)) {
3187 result = base::AddWithWraparound(
3189 base::MulWithWraparound(xreg(
instr->Rn()), xreg(
instr->Rm())));
3193 result = base::SubWithWraparound(
3195 base::MulWithWraparound(xreg(
instr->Rn()), xreg(
instr->Rm())));
3198 result = base::AddWithWraparound(xreg(
instr->Ra()), (rn_s32 * rm_s32));
3201 result = base::SubWithWraparound(xreg(
instr->Ra()), (rn_s32 * rm_s32));
3204 result =
static_cast<uint64_t
>(xreg(
instr->Ra())) + (rn_u32 * rm_u32);
3207 result =
static_cast<uint64_t
>(xreg(
instr->Ra())) - (rn_u32 * rm_u32);
3212 base::bits::SignedMulHigh64(xreg(
instr->Rn()), xreg(
instr->Rm()));
3217 base::bits::UnsignedMulHigh64(xreg(
instr->Rn()), xreg(
instr->Rm()));
3223 if (
instr->SixtyFourBits()) {
3230template <
typename T>
3231void Simulator::BitfieldHelper(Instruction*
instr) {
3232 using unsignedT = std::make_unsigned_t<T>;
3233 T reg_size =
sizeof(
T) * 8;
3234 T R =
instr->ImmR();
3239 mask = diff < reg_size - 1 ? (
static_cast<unsignedT
>(1) << (diff + 1)) - 1
3240 : static_cast<T>(-1);
3242 uint64_t umask = ((1ULL << (
S + 1)) - 1);
3243 umask = (umask >> R) | (umask << (reg_size - R));
3244 mask =
static_cast<T
>(umask);
3251 bool inzero =
false;
3252 bool extend =
false;
3253 switch (
instr->Mask(BitfieldMask)) {
3274 : (
static_cast<unsignedT
>(src) >> R) |
3275 (
static_cast<unsignedT
>(src) << (reg_size - R));
3277 T topbits_preshift = (
static_cast<unsignedT
>(1) << (reg_size - diff - 1)) - 1;
3279 diff >= reg_size - 1
3281 : ((extend && ((src >>
S) & 1) ? topbits_preshift : 0) << (diff + 1));
3289void Simulator::VisitBitfield(Instruction*
instr) {
3290 if (
instr->SixtyFourBits()) {
3291 BitfieldHelper<int64_t>(
instr);
3293 BitfieldHelper<int32_t>(
instr);
3297void Simulator::VisitExtract(Instruction*
instr) {
3298 if (
instr->SixtyFourBits()) {
3299 Extract<uint64_t>(
instr);
3301 Extract<uint32_t>(
instr);
3305void Simulator::VisitFPImmediate(Instruction*
instr) {
3306 AssertSupportedFPCR();
3308 unsigned dest =
instr->Rd();
3309 switch (
instr->Mask(FPImmediateMask)) {
3311 set_sreg(dest,
instr->ImmFP32());
3314 set_dreg(dest,
instr->ImmFP64());
3321void Simulator::VisitFPIntegerConvert(Instruction*
instr) {
3322 AssertSupportedFPCR();
3324 unsigned dst =
instr->Rd();
3325 unsigned src =
instr->Rn();
3329 switch (
instr->Mask(FPIntegerConvertMask)) {
3331 set_wreg(dst, FPToInt32(sreg(src), FPTieAway));
3334 set_xreg(dst, FPToInt64(sreg(src), FPTieAway));
3337 set_wreg(dst, FPToInt32(dreg(src), FPTieAway));
3340 set_xreg(dst, FPToInt64(dreg(src), FPTieAway));
3343 set_wreg(dst, FPToUInt32(sreg(src), FPTieAway));
3346 set_xreg(dst, FPToUInt64(sreg(src), FPTieAway));
3349 set_wreg(dst, FPToUInt32(dreg(src), FPTieAway));
3352 set_xreg(dst, FPToUInt64(dreg(src), FPTieAway));
3355 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
3358 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
3361 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
3364 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
3367 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
3370 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
3373 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
3376 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
3379 set_wreg(dst, FPToInt32(sreg(src), FPTieEven));
3382 set_xreg(dst, FPToInt64(sreg(src), FPTieEven));
3385 set_wreg(dst, FPToInt32(dreg(src), FPTieEven));
3388 set_xreg(dst, FPToInt64(dreg(src), FPTieEven));
3391 set_wreg(dst, FPToUInt32(sreg(src), FPTieEven));
3394 set_xreg(dst, FPToUInt64(sreg(src), FPTieEven));
3397 set_wreg(dst, FPToUInt32(dreg(src), FPTieEven));
3400 set_xreg(dst, FPToUInt64(dreg(src), FPTieEven));
3403 set_wreg(dst, FPToInt32(sreg(src), FPZero));
3406 set_xreg(dst, FPToInt64(sreg(src), FPZero));
3409 set_wreg(dst, FPToInt32(dreg(src), FPZero));
3412 set_xreg(dst, FPToInt64(dreg(src), FPZero));
3415 set_wreg(dst, FPToUInt32(sreg(src), FPZero));
3418 set_xreg(dst, FPToUInt64(sreg(src), FPZero));
3421 set_wreg(dst, FPToUInt32(dreg(src), FPZero));
3424 set_xreg(dst, FPToUInt64(dreg(src), FPZero));
3427 set_wreg(dst, FPToFixedJS(dreg(src)));
3430 set_wreg(dst, sreg_bits(src));
3433 set_xreg(dst, dreg_bits(src));
3436 set_sreg_bits(dst, wreg(src));
3439 set_dreg_bits(dst, xreg(src));
3445 set_dreg(dst, FixedToDouble(xreg(src), 0, round));
3448 set_dreg(dst, FixedToDouble(wreg(src), 0, round));
3451 set_dreg(dst, UFixedToDouble(xreg(src), 0, round));
3454 set_dreg(dst, UFixedToDouble(
reg<uint32_t>(src), 0, round));
3458 set_sreg(dst, FixedToFloat(xreg(src), 0, round));
3461 set_sreg(dst, FixedToFloat(wreg(src), 0, round));
3464 set_sreg(dst, UFixedToFloat(xreg(src), 0, round));
3476void Simulator::VisitFPFixedPointConvert(Instruction*
instr) {
3477 AssertSupportedFPCR();
3479 unsigned dst =
instr->Rd();
3480 unsigned src =
instr->Rn();
3481 int fbits = 64 -
instr->FPScale();
3485 switch (
instr->Mask(FPFixedPointConvertMask)) {
3489 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
3492 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
3495 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
3498 set_dreg(dst, UFixedToDouble(
reg<uint32_t>(src), fbits, round));
3502 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
3505 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
3508 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
3511 set_sreg(dst, UFixedToFloat(
reg<uint32_t>(src), fbits, round));
3519void Simulator::VisitFPCompare(Instruction*
instr) {
3520 AssertSupportedFPCR();
3522 switch (
instr->Mask(FPCompareMask)) {
3524 FPCompare(sreg(
instr->Rn()), sreg(
instr->Rm()));
3527 FPCompare(dreg(
instr->Rn()), dreg(
instr->Rm()));
3530 FPCompare(sreg(
instr->Rn()), 0.0f);
3533 FPCompare(dreg(
instr->Rn()), 0.0);
3540void Simulator::VisitFPConditionalCompare(Instruction*
instr) {
3541 AssertSupportedFPCR();
3543 switch (
instr->Mask(FPConditionalCompareMask)) {
3545 if (ConditionPassed(
static_cast<Condition>(
instr->Condition()))) {
3546 FPCompare(sreg(
instr->Rn()), sreg(
instr->Rm()));
3548 nzcv().SetFlags(
instr->Nzcv());
3549 LogSystemRegister(NZCV);
3553 if (ConditionPassed(
static_cast<Condition>(
instr->Condition()))) {
3554 FPCompare(dreg(
instr->Rn()), dreg(
instr->Rm()));
3557 nzcv().SetFlags(
instr->Nzcv());
3558 LogSystemRegister(NZCV);
3567void Simulator::VisitFPConditionalSelect(Instruction*
instr) {
3568 AssertSupportedFPCR();
3571 if (ConditionPassed(
static_cast<Condition>(
instr->Condition()))) {
3572 selected =
instr->Rn();
3574 selected =
instr->Rm();
3577 switch (
instr->Mask(FPConditionalSelectMask)) {
3579 set_sreg(
instr->Rd(), sreg(selected));
3582 set_dreg(
instr->Rd(), dreg(selected));
3589void Simulator::VisitFPDataProcessing1Source(Instruction*
instr) {
3590 AssertSupportedFPCR();
3594 SimVRegister& rd = vreg(
instr->Rd());
3595 SimVRegister& rn = vreg(
instr->Rn());
3596 bool inexact_exception =
false;
3598 unsigned fd =
instr->Rd();
3601 switch (
instr->Mask(FPDataProcessing1SourceMask)) {
3603 set_sreg(fd, sreg(
fn));
3606 set_dreg(fd, dreg(
fn));
3610 fabs_(vform, vreg(fd), vreg(
fn));
3612 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3616 fneg(vform, vreg(fd), vreg(
fn));
3618 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3621 set_dreg(fd, FPToDouble(sreg(
fn)));
3624 set_sreg(fd, FPToFloat(dreg(
fn), FPTieEven));
3627 set_hreg(fd, FPToFloat16(sreg(
fn), FPTieEven));
3630 set_sreg(fd, FPToFloat(hreg(
fn)));
3633 set_dreg(fd, FPToDouble(FPToFloat(hreg(
fn))));
3636 set_hreg(fd, FPToFloat16(dreg(
fn), FPTieEven));
3640 fsqrt(vform, rd, rn);
3642 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3649 inexact_exception =
true;
3676 frint(vform, rd, rn, fpcr_rounding, inexact_exception);
3678 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3681void Simulator::VisitFPDataProcessing2Source(Instruction*
instr) {
3682 AssertSupportedFPCR();
3685 SimVRegister& rd = vreg(
instr->Rd());
3686 SimVRegister& rn = vreg(
instr->Rn());
3687 SimVRegister& rm = vreg(
instr->Rm());
3689 switch (
instr->Mask(FPDataProcessing2SourceMask)) {
3692 fadd(vform, rd, rn, rm);
3696 fsub(vform, rd, rn, rm);
3700 fmul(vform, rd, rn, rm);
3704 fnmul(vform, rd, rn, rm);
3708 fdiv(vform, rd, rn, rm);
3712 fmax(vform, rd, rn, rm);
3716 fmin(vform, rd, rn, rm);
3720 fmaxnm(vform, rd, rn, rm);
3724 fminnm(vform, rd, rn, rm);
3730 LogVRegister(
instr->Rd(), GetPrintRegisterFormatFP(vform));
3733void Simulator::VisitFPDataProcessing3Source(Instruction*
instr) {
3734 AssertSupportedFPCR();
3736 unsigned fd =
instr->Rd();
3738 unsigned fm =
instr->Rm();
3739 unsigned fa =
instr->Ra();
3741 switch (
instr->Mask(FPDataProcessing3SourceMask)) {
3744 set_sreg(fd, FPMulAdd(sreg(fa), sreg(
fn), sreg(fm)));
3747 set_sreg(fd, FPMulAdd(sreg(fa), -sreg(
fn), sreg(fm)));
3750 set_dreg(fd, FPMulAdd(dreg(fa), dreg(
fn), dreg(fm)));
3753 set_dreg(fd, FPMulAdd(dreg(fa), -dreg(
fn), dreg(fm)));
3757 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(
fn), sreg(fm)));
3760 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(
fn), sreg(fm)));
3763 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(
fn), dreg(fm)));
3766 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(
fn), dreg(fm)));
3773bool Simulator::FPProcessNaNs(Instruction*
instr) {
3774 unsigned fd =
instr->Rd();
3776 unsigned fm =
instr->Rm();
3779 if (
instr->Mask(FP64) == FP64) {
3780 double result = FPProcessNaNs(dreg(
fn), dreg(fm));
3781 if (std::isnan(
result)) {
3786 float result = FPProcessNaNs(sreg(
fn), sreg(fm));
3787 if (std::isnan(
result)) {
3797#define PAUTH_SYSTEM_MODES(V) \
3798 V(B1716, 17, xreg(16), kPACKeyIB) \
3799 V(BSP, 30, xreg(31, Reg31IsStackPointer), kPACKeyIB)
3802void Simulator::VisitSystem(Instruction*
instr) {
3806 if (
instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
3808 switch (
instr->Mask(SystemPAuthMask)) {
3809#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
3810 case PACI##SUFFIX: \
3811 set_xreg(DST, AddPAC(xreg(DST), MOD, KEY, kInstructionPointer)); \
3813 case AUTI##SUFFIX: \
3814 set_xreg(DST, AuthPAC(xreg(DST), MOD, KEY, kInstructionPointer)); \
3817 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
3818#undef DEFINE_PAUTH_FUNCS
3819#undef PAUTH_SYSTEM_MODES
3821 }
else if (
instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3822 switch (
instr->Mask(SystemSysRegMask)) {
3824 switch (
instr->ImmSystemRegister()) {
3826 set_xreg(
instr->Rt(), nzcv().RawValue());
3829 set_xreg(
instr->Rt(), fpcr().RawValue());
3837 switch (
instr->ImmSystemRegister()) {
3839 nzcv().SetRawValue(wreg(
instr->Rt()));
3840 LogSystemRegister(NZCV);
3843 fpcr().SetRawValue(wreg(
instr->Rt()));
3844 LogSystemRegister(FPCR);
3852 }
else if (
instr->Mask(SystemHintFMask) == SystemHintFixed) {
3854 switch (
instr->ImmHint()) {
3867 }
else if (
instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
3868 std::atomic_thread_fence(std::memory_order_seq_cst);
3874bool Simulator::GetValue(
const char* desc, int64_t* value) {
3875 int regnum = CodeFromName(desc);
3877 unsigned code = regnum;
3878 if (code == kZeroRegCode) {
3882 }
else if (code == kSPRegInternalCode) {
3886 if (desc[0] ==
'w') {
3887 *value = wreg(code, Reg31IsStackPointer);
3889 *value = xreg(code, Reg31IsStackPointer);
3892 }
else if (strncmp(desc,
"0x", 2) == 0) {
3893 return SScanF(desc + 2,
"%" SCNx64,
reinterpret_cast<uint64_t*
>(value)) ==
3896 return SScanF(desc,
"%" SCNu64,
reinterpret_cast<uint64_t*
>(value)) == 1;
3900bool Simulator::PrintValue(
const char* desc) {
3901 if (strcmp(desc,
"sp") == 0) {
3902 DCHECK(CodeFromName(desc) ==
static_cast<int>(kSPRegInternalCode));
3903 PrintF(stream_,
"%s sp:%s 0x%016" PRIx64
"%s\n", clr_reg_name,
3904 clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3906 }
else if (strcmp(desc,
"wsp") == 0) {
3907 DCHECK(CodeFromName(desc) ==
static_cast<int>(kSPRegInternalCode));
3908 PrintF(stream_,
"%s wsp:%s 0x%08" PRIx32
"%s\n", clr_reg_name,
3909 clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3913 int i = CodeFromName(desc);
3915 "Must be same number of Registers as VRegisters.");
3916 if (
i < 0 ||
static_cast<unsigned>(
i) >= kNumberOfVRegisters)
return false;
3918 if (desc[0] ==
'v') {
3919 struct qreg_t
reg = qreg(
i);
3920 PrintF(stream_,
"%s %s:%s (%s0x%02x%s", clr_vreg_name, VRegNameForCode(
i),
3921 clr_normal, clr_vreg_value,
reg.val[0], clr_normal);
3923 PrintF(stream_,
", %s0x%02x%s", clr_vreg_value,
reg.val[b], clr_normal);
3927 }
else if (desc[0] ==
'd') {
3928 PrintF(stream_,
"%s %s:%s %g%s\n", clr_vreg_name, DRegNameForCode(
i),
3929 clr_vreg_value, dreg(
i), clr_normal);
3931 }
else if (desc[0] ==
's') {
3932 PrintF(stream_,
"%s %s:%s %g%s\n", clr_vreg_name, SRegNameForCode(
i),
3933 clr_vreg_value, sreg(
i), clr_normal);
3935 }
else if (desc[0] ==
'w') {
3936 PrintF(stream_,
"%s %s:%s 0x%08" PRIx32
"%s\n", clr_reg_name,
3937 WRegNameForCode(
i), clr_reg_value, wreg(
i), clr_normal);
3942 PrintF(stream_,
"%s %s:%s 0x%016" PRIx64
"%s\n", clr_reg_name,
3943 XRegNameForCode(
i), clr_reg_value, xreg(
i), clr_normal);
3948void Simulator::Debug() {
3949 if (
v8_flags.correctness_fuzzer_suppressions) {
3950 PrintF(
"Debugger disabled for differential fuzzing.\n");
3956 PrintInstructionsAt(
pc_, 1);
3958 ArrayUniquePtr<char> line(
ReadLine(
"sim> "));
3959 done = ExecDebugCommand(std::move(line));
3963bool Simulator::ExecDebugCommand(ArrayUniquePtr<char> line_ptr) {
3964#define COMMAND_SIZE 63
3968#define XSTR(a) STR(a)
3970 char cmd[COMMAND_SIZE + 1];
3971 char arg1[ARG_SIZE + 1];
3972 char arg2[ARG_SIZE + 1];
3973 char* argv[3] = {cmd, arg1, arg2};
3976 cmd[COMMAND_SIZE] = 0;
3980 bool cleared_log_disasm_bit =
false;
3982 if (line_ptr ==
nullptr)
return false;
3985 const char* line = line_ptr.get();
3986 const char* last_input = last_debugger_input();
3987 if (strcmp(line,
"\n") == 0 && (last_input !=
nullptr)) {
3992 set_last_debugger_input(std::move(line_ptr));
3997 int argc = SScanF(line,
3998 "%" XSTR(COMMAND_SIZE)
"s "
3999 "%" XSTR(ARG_SIZE)
"s "
4000 "%" XSTR(ARG_SIZE)
"s",
4004 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
4009 pc_modified_ =
false;
4012 ExecuteInstruction();
4014 int64_t number_of_instructions_to_execute = 1;
4015 GetValue(arg1, &number_of_instructions_to_execute);
4017 set_log_parameters(log_parameters() | LOG_DISASM);
4018 while (number_of_instructions_to_execute-- > 0) {
4019 ExecuteInstruction();
4021 set_log_parameters(log_parameters() & ~LOG_DISASM);
4028 pc_modified_ =
true;
4032 }
else if ((strcmp(cmd,
"next") == 0) || (strcmp(cmd,
"n") == 0)) {
4034 break_on_next_ =
true;
4040 }
else if ((strcmp(cmd,
"continue") == 0) || (strcmp(cmd,
"cont") == 0) ||
4041 (strcmp(cmd,
"c") == 0)) {
4047 }
else if (strcmp(cmd,
"disassemble") == 0 || strcmp(cmd,
"disasm") == 0 ||
4048 strcmp(cmd,
"di") == 0) {
4049 int64_t n_of_instrs_to_disasm = 10;
4050 int64_t address =
reinterpret_cast<int64_t
>(
pc_);
4052 GetValue(arg1, &n_of_instrs_to_disasm);
4055 GetValue(arg2, &address);
4059 PrintInstructionsAt(
reinterpret_cast<Instruction*
>(address),
4060 n_of_instrs_to_disasm);
4065 }
else if ((strcmp(cmd,
"print") == 0) || (strcmp(cmd,
"p") == 0)) {
4067 if (strcmp(arg1,
"all") == 0) {
4071 if (!PrintValue(arg1)) {
4072 PrintF(
"%s unrecognized\n", arg1);
4077 "print <register>\n"
4078 " Print the content of a register. (alias 'p')\n"
4079 " 'print all' will print all registers.\n"
4080 " Use 'printobject' to get more details about the value.\n");
4085 }
else if ((strcmp(cmd,
"printobject") == 0) || (strcmp(cmd,
"po") == 0)) {
4089 if (GetValue(arg1, &value)) {
4090 Tagged<Object> obj(value);
4091 os << arg1 <<
": \n";
4096 os << Brief(obj) <<
"\n";
4099 os << arg1 <<
" unrecognized\n";
4103 "printobject <value>\n"
4104 "printobject <register>\n"
4105 " Print details about the value. (alias 'po')\n");
4110 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0 ||
4111 strcmp(cmd,
"dump") == 0) {
4112 int64_t* cur =
nullptr;
4113 int64_t*
end =
nullptr;
4116 if (strcmp(cmd,
"stack") == 0) {
4117 cur =
reinterpret_cast<int64_t*
>(
sp());
4121 if (!GetValue(arg1, &value)) {
4122 PrintF(
"%s unrecognized\n", arg1);
4125 cur =
reinterpret_cast<int64_t*
>(
value);
4130 if (argc == next_arg) {
4132 }
else if (argc == next_arg + 1) {
4133 if (!GetValue(argv[next_arg], &words)) {
4134 PrintF(
"%s unrecognized\n", argv[next_arg]);
4135 PrintF(
"Printing 10 double words by default");
4143 bool skip_obj_print = (strcmp(cmd,
"dump") == 0);
4145 PrintF(
" 0x%016" PRIx64
": 0x%016" PRIx64
" %10" PRId64,
4146 reinterpret_cast<uint64_t
>(cur), *cur, *cur);
4147 if (!skip_obj_print) {
4148 Tagged<Object> obj(*cur);
4149 Heap* current_heap =
isolate_->heap();
4154 PrintF(
"smi %" PRId32, Smi::ToInt(obj));
4167 }
else if (strcmp(cmd,
"trace") == 0 || strcmp(cmd,
"t") == 0) {
4168 if ((log_parameters() & LOG_ALL) != LOG_ALL) {
4169 PrintF(
"Enabling disassembly, registers and memory write tracing\n");
4170 set_log_parameters(log_parameters() | LOG_ALL);
4172 PrintF(
"Disabling disassembly, registers and memory write tracing\n");
4173 set_log_parameters(log_parameters() & ~LOG_ALL);
4178 }
else if (strcmp(cmd,
"break") == 0 || strcmp(cmd,
"b") == 0) {
4181 if (GetValue(arg1, &value)) {
4182 SetBreakpoint(
reinterpret_cast<Instruction*
>(value));
4184 PrintF(
"%s unrecognized\n", arg1);
4188 PrintF(
"Use `break <address>` to set or disable a breakpoint\n");
4193 }
else if (strcmp(cmd,
"backtrace") == 0 || strcmp(cmd,
"bt") == 0) {
4206 if (
pc ==
reinterpret_cast<Address>(kEndOfSimAddress)) {
4209 lr = *(
reinterpret_cast<Address*
>(fp) + 1);
4210 fp = *
reinterpret_cast<Address*
>(fp);
4213 PrintF(
"Too many frames\n");
4220 }
else if (strcmp(cmd,
"gdb") == 0) {
4221 PrintF(
"Relinquishing control to gdb.\n");
4222 base::OS::DebugBreak();
4223 PrintF(
"Regaining control from gdb.\n");
4227 }
else if (strcmp(cmd,
"sysregs") == 0) {
4228 PrintSystemRegisters();
4232 }
else if (strcmp(cmd,
"help") == 0 || strcmp(cmd,
"h") == 0) {
4236 " Step <n> instructions.\n"
4238 " Continue execution until a BL instruction is reached.\n"
4239 " At this point a breakpoint is set just after this BL.\n"
4240 " Then execution is resumed. It will probably later hit the\n"
4241 " breakpoint just set.\n"
4242 "continue / cont / c\n"
4243 " Continue execution from here.\n"
4244 "disassemble / disasm / di\n"
4245 " disassemble <n> <address>\n"
4246 " Disassemble <n> instructions from current <address>.\n"
4247 " By default <n> is 20 and <address> is the current pc.\n"
4249 " print <register>\n"
4250 " Print the content of a register.\n"
4251 " 'print all' will print all registers.\n"
4252 " Use 'printobject' to get more details about the value.\n"
4253 "printobject / po\n"
4254 " printobject <value>\n"
4255 " printobject <register>\n"
4256 " Print details about the value.\n"
4258 " stack [<words>]\n"
4259 " Dump stack content, default dump 10 words\n"
4261 " mem <address> [<words>]\n"
4262 " Dump memory content, default dump 10 words\n"
4264 " dump <address> [<words>]\n"
4265 " Dump memory content without pretty printing JS objects, "
4266 "default dump 10 words\n"
4268 " Toggle disassembly and register tracing\n"
4270 " break : list all breakpoints\n"
4271 " break <address> : set / enable / disable a breakpoint.\n"
4273 " Walk the frame pointers, dumping the pc/sp/fp for each frame.\n"
4277 " Print all system registers (including NZCV).\n");
4279 PrintF(
"Unknown command: %s\n", cmd);
4280 PrintF(
"Use 'help' for more information.\n");
4283 if (cleared_log_disasm_bit ==
true) {
4284 set_log_parameters(log_parameters_ | LOG_DISASM);
4289void Simulator::VisitException(Instruction*
instr) {
4290 switch (
instr->Mask(ExceptionMask)) {
4292 if (
instr->ImmException() == kImmExceptionIsDebug) {
4295 uint32_t parameters;
4297 memcpy(&code,
pc_->InstructionAtOffset(kDebugCodeOffset),
sizeof(code));
4298 memcpy(¶meters,
pc_->InstructionAtOffset(kDebugParamsOffset),
4299 sizeof(parameters));
4300 char const* message =
reinterpret_cast<char const*
>(
4301 pc_->InstructionAtOffset(kDebugMessageOffset));
4307 (parameters &
BREAK)) {
4308 if (message !=
nullptr) {
4309 PrintF(stream_,
"# %sDebugger hit %d: %s%s%s\n", clr_debug_number,
4310 code, clr_debug_message, message, clr_normal);
4312 PrintF(stream_,
"# %sDebugger hit %d.%s\n", clr_debug_number, code,
4315 Builtin maybe_builtin = OffHeapInstructionStream::TryLookupCode(
4316 Isolate::Current(),
reinterpret_cast<Address>(
pc_));
4317 if (Builtins::IsBuiltinId(maybe_builtin)) {
4318 char const* name = Builtins::name(maybe_builtin);
4319 PrintF(stream_,
"# %s %sLOCATION: %s%s\n",
4320 clr_debug_number, clr_debug_message, name, clr_normal);
4325 switch (parameters & kDebuggerTracingDirectivesMask) {
4327 set_log_parameters(log_parameters() | parameters);
4328 if (parameters & LOG_SYS_REGS) {
4329 PrintSystemRegisters();
4331 if (parameters & LOG_REGS) {
4334 if (parameters & LOG_VREGS) {
4339 set_log_parameters(log_parameters() & ~parameters);
4342 set_log_parameters(parameters);
4348 parameters &= ~log_parameters();
4350 if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
4351 if (parameters & LOG_REGS) PrintRegisters();
4352 if (parameters & LOG_VREGS) PrintVRegisters();
4360 DCHECK(
pc_->Mask(ExceptionMask) == HLT);
4361 DCHECK_EQ(
pc_->ImmException(), kImmExceptionIsUnreachable);
4363 set_pc(
pc_->following());
4366 if (parameters &
BREAK) Debug();
4368 }
else if (
instr->ImmException() == kImmExceptionIsRedirectedCall) {
4369 DoRuntimeCall(
instr);
4370 }
else if (
instr->ImmException() == kImmExceptionIsPrintf) {
4372 }
else if (
instr->ImmException() == kImmExceptionIsSwitchStackLimit) {
4373 DoSwitchStackLimit(
instr);
4374 }
else if (
instr->ImmException() == kImmExceptionIsUnreachable) {
4375 fprintf(stream_,
"Hit UNREACHABLE marker at PC=%p.\n",
4376 reinterpret_cast<void*
>(
pc_));
4380 base::OS::DebugBreak();
4385 base::OS::DebugBreak();
4392void Simulator::VisitNEON2RegMisc(Instruction*
instr) {
4393 NEONFormatDecoder nfd(
instr);
4397 static const NEONFormatMap map_lp = {
4401 static const NEONFormatMap map_fcvtl = {{22}, {
NF_4S,
NF_2D}};
4402 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4404 static const NEONFormatMap map_fcvtn = {{22, 30},
4406 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4408 SimVRegister& rd = vreg(
instr->Rd());
4409 SimVRegister& rn = vreg(
instr->Rn());
4411 if (
instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4414 switch (
instr->Mask(NEON2RegMiscMask)) {
4440 abs(vf, rd, rn).SignedSaturate(vf);
4443 neg(vf, rd, rn).SignedSaturate(vf);
4446 cmp(vf, rd, rn, 0, gt);
4449 cmp(vf, rd, rn, 0, ge);
4452 cmp(vf, rd, rn, 0, eq);
4455 cmp(vf, rd, rn, 0, le);
4458 cmp(vf, rd, rn, 0, lt);
4467 saddlp(vf_lp, rd, rn);
4470 uaddlp(vf_lp, rd, rn);
4473 sadalp(vf_lp, rd, rn);
4476 uadalp(vf_lp, rd, rn);
4479 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4480 switch (
instr->FPType()) {
4495 ? nfd.FPHPFormatMap()
4496 : nfd.FPFormatMap());
4498 bool inexact_exception =
false;
4502 switch (
instr->Mask(NEON2RegMiscFPMask ^ NEON2RegMiscHPFixed)) {
4513 if (
instr->Mask(NEON_Q)) {
4514 fcvtl2(vf_fcvtl, rd, rn);
4516 fcvtl(vf_fcvtl, rd, rn);
4520 if (
instr->Mask(NEON_Q)) {
4521 fcvtn2(vf_fcvtn, rd, rn);
4523 fcvtn(vf_fcvtn, rd, rn);
4527 if (
instr->Mask(NEON_Q)) {
4528 fcvtxn2(vf_fcvtn, rd, rn);
4530 fcvtxn(vf_fcvtn, rd, rn);
4539 inexact_exception =
true;
4559 fcvts(fpf, rd, rn, FPTieEven);
4562 fcvtu(fpf, rd, rn, FPTieEven);
4565 fcvts(fpf, rd, rn, FPPositiveInfinity);
4568 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4571 fcvts(fpf, rd, rn, FPNegativeInfinity);
4574 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4577 fcvts(fpf, rd, rn, FPZero);
4580 fcvtu(fpf, rd, rn, FPZero);
4583 fcvts(fpf, rd, rn, FPTieAway);
4586 fcvtu(fpf, rd, rn, FPTieAway);
4589 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4592 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4595 ursqrte(fpf, rd, rn);
4598 urecpe(fpf, rd, rn);
4601 frsqrte(fpf, rd, rn);
4604 frecpe(fpf, rd, rn, fpcr_rounding);
4607 fcmp_zero(fpf, rd, rn, gt);
4610 fcmp_zero(fpf, rd, rn, ge);
4613 fcmp_zero(fpf, rd, rn, eq);
4616 fcmp_zero(fpf, rd, rn, le);
4619 fcmp_zero(fpf, rd, rn, lt);
4622 if ((NEON_XTN_opcode <= instr->
Mask(NEON2RegMiscOpcode)) &&
4623 (
instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4624 switch (
instr->Mask(NEON2RegMiscMask)) {
4638 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4639 if (
instr->Mask(NEON_Q)) {
4654 frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
4658void Simulator::VisitNEON3SameFP(NEON3SameOp op, VectorFormat vf,
4659 SimVRegister& rd, SimVRegister& rn,
4663 fadd(vf, rd, rn, rm);
4666 fsub(vf, rd, rn, rm);
4669 fmul(vf, rd, rn, rm);
4672 fdiv(vf, rd, rn, rm);
4675 fmax(vf, rd, rn, rm);
4678 fmin(vf, rd, rn, rm);
4681 fmaxnm(vf, rd, rn, rm);
4684 fminnm(vf, rd, rn, rm);
4687 fmla(vf, rd, rn, rm);
4690 fmls(vf, rd, rn, rm);
4693 fmulx(vf, rd, rn, rm);
4696 fabscmp(vf, rd, rn, rm, ge);
4699 fabscmp(vf, rd, rn, rm, gt);
4702 fcmp(vf, rd, rn, rm, eq);
4705 fcmp(vf, rd, rn, rm, ge);
4708 fcmp(vf, rd, rn, rm, gt);
4711 frecps(vf, rd, rn, rm);
4714 frsqrts(vf, rd, rn, rm);
4717 fabd(vf, rd, rn, rm);
4720 faddp(vf, rd, rn, rm);
4723 fmaxp(vf, rd, rn, rm);
4726 fmaxnmp(vf, rd, rn, rm);
4729 fminp(vf, rd, rn, rm);
4732 fminnmp(vf, rd, rn, rm);
4739void Simulator::VisitNEON3Same(Instruction*
instr) {
4740 NEONFormatDecoder nfd(
instr);
4741 SimVRegister& rd = vreg(
instr->Rd());
4742 SimVRegister& rn = vreg(
instr->Rn());
4743 SimVRegister& rm = vreg(
instr->Rm());
4745 if (
instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
4746 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4747 switch (
instr->Mask(NEON3SameLogicalMask)) {
4749 and_(vf, rd, rn, rm);
4752 orr(vf, rd, rn, rm);
4755 orn(vf, rd, rn, rm);
4758 eor(vf, rd, rn, rm);
4761 bic(vf, rd, rn, rm);
4764 bif(vf, rd, rn, rm);
4767 bit(vf, rd, rn, rm);
4770 bsl(vf, rd, rn, rm);
4775 }
else if (
instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
4776 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4777 VisitNEON3SameFP(
instr->Mask(NEON3SameFPMask), vf, rd, rn, rm);
4780 switch (
instr->Mask(NEON3SameMask)) {
4782 add(vf, rd, rn, rm);
4785 addp(vf, rd, rn, rm);
4788 cmp(vf, rd, rn, rm, eq);
4791 cmp(vf, rd, rn, rm, ge);
4794 cmp(vf, rd, rn, rm, gt);
4797 cmp(vf, rd, rn, rm, hi);
4800 cmp(vf, rd, rn, rm, hs);
4803 cmptst(vf, rd, rn, rm);
4806 mls(vf, rd, rn, rm);
4809 mla(vf, rd, rn, rm);
4812 mul(vf, rd, rn, rm);
4815 pmul(vf, rd, rn, rm);
4818 smax(vf, rd, rn, rm);
4821 smaxp(vf, rd, rn, rm);
4824 smin(vf, rd, rn, rm);
4827 sminp(vf, rd, rn, rm);
4830 sub(vf, rd, rn, rm);
4833 umax(vf, rd, rn, rm);
4836 umaxp(vf, rd, rn, rm);
4839 umin(vf, rd, rn, rm);
4842 uminp(vf, rd, rn, rm);
4845 sshl(vf, rd, rn, rm);
4848 ushl(vf, rd, rn, rm);
4851 AbsDiff(vf, rd, rn, rm,
true);
4854 AbsDiff(vf, rd, rn, rm,
false);
4857 saba(vf, rd, rn, rm);
4860 uaba(vf, rd, rn, rm);
4863 add(vf, rd, rn, rm).UnsignedSaturate(vf);
4866 add(vf, rd, rn, rm).SignedSaturate(vf);
4869 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
4872 sub(vf, rd, rn, rm).SignedSaturate(vf);
4875 sqdmulh(vf, rd, rn, rm);
4878 sqrdmulh(vf, rd, rn, rm);
4881 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
4884 sshl(vf, rd, rn, rm).SignedSaturate(vf);
4887 ushl(vf, rd, rn, rm).Round(vf);
4890 sshl(vf, rd, rn, rm).Round(vf);
4893 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
4896 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
4899 add(vf, rd, rn, rm).Uhalve(vf);
4902 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
4905 add(vf, rd, rn, rm).Halve(vf);
4908 add(vf, rd, rn, rm).Halve(vf).Round(vf);
4911 sub(vf, rd, rn, rm).Uhalve(vf);
4914 sub(vf, rd, rn, rm).Halve(vf);
4922void Simulator::VisitNEON3SameHP(Instruction*
instr) {
4923 NEONFormatDecoder nfd(
instr);
4924 SimVRegister& rd = vreg(
instr->Rd());
4925 SimVRegister& rn = vreg(
instr->Rn());
4926 SimVRegister& rm = vreg(
instr->Rm());
4927 VectorFormat vf = nfd.GetVectorFormat(nfd.FPHPFormatMap());
4928 VisitNEON3SameFP(
instr->Mask(NEON3SameFPMask) | NEON3SameHPMask, vf, rd, rn,
4932void Simulator::VisitNEON3Different(Instruction*
instr) {
4933 NEONFormatDecoder nfd(
instr);
4935 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4937 SimVRegister& rd = vreg(
instr->Rd());
4938 SimVRegister& rn = vreg(
instr->Rn());
4939 SimVRegister& rm = vreg(
instr->Rm());
4940 int size =
instr->NEONSize();
4942 switch (
instr->Mask(NEON3DifferentMask)) {
4944 if ((size == 1) || (size == 2)) {
4945 VisitUnallocated(
instr);
4948 pmull(vf_l, rd, rn, rm);
4952 if ((size == 1) || (size == 2)) {
4953 VisitUnallocated(
instr);
4956 pmull2(vf_l, rd, rn, rm);
4960 uaddl(vf_l, rd, rn, rm);
4963 uaddl2(vf_l, rd, rn, rm);
4966 saddl(vf_l, rd, rn, rm);
4969 saddl2(vf_l, rd, rn, rm);
4972 usubl(vf_l, rd, rn, rm);
4975 usubl2(vf_l, rd, rn, rm);
4978 ssubl(vf_l, rd, rn, rm);
4981 ssubl2(vf_l, rd, rn, rm);
4984 sabal(vf_l, rd, rn, rm);
4987 sabal2(vf_l, rd, rn, rm);
4990 uabal(vf_l, rd, rn, rm);
4993 uabal2(vf_l, rd, rn, rm);
4996 sabdl(vf_l, rd, rn, rm);
4999 sabdl2(vf_l, rd, rn, rm);
5002 uabdl(vf_l, rd, rn, rm);
5005 uabdl2(vf_l, rd, rn, rm);
5008 smlal(vf_l, rd, rn, rm);
5011 smlal2(vf_l, rd, rn, rm);
5014 umlal(vf_l, rd, rn, rm);
5017 umlal2(vf_l, rd, rn, rm);
5020 smlsl(vf_l, rd, rn, rm);
5023 smlsl2(vf_l, rd, rn, rm);
5026 umlsl(vf_l, rd, rn, rm);
5029 umlsl2(vf_l, rd, rn, rm);
5032 smull(vf_l, rd, rn, rm);
5035 smull2(vf_l, rd, rn, rm);
5038 umull(vf_l, rd, rn, rm);
5041 umull2(vf_l, rd, rn, rm);
5044 sqdmlal(vf_l, rd, rn, rm);
5047 sqdmlal2(vf_l, rd, rn, rm);
5050 sqdmlsl(vf_l, rd, rn, rm);
5053 sqdmlsl2(vf_l, rd, rn, rm);
5056 sqdmull(vf_l, rd, rn, rm);
5059 sqdmull2(vf_l, rd, rn, rm);
5062 uaddw(vf_l, rd, rn, rm);
5065 uaddw2(vf_l, rd, rn, rm);
5068 saddw(vf_l, rd, rn, rm);
5071 saddw2(vf_l, rd, rn, rm);
5074 usubw(vf_l, rd, rn, rm);
5077 usubw2(vf_l, rd, rn, rm);
5080 ssubw(vf_l, rd, rn, rm);
5083 ssubw2(vf_l, rd, rn, rm);
5086 addhn(vf, rd, rn, rm);
5089 addhn2(vf, rd, rn, rm);
5092 raddhn(vf, rd, rn, rm);
5095 raddhn2(vf, rd, rn, rm);
5098 subhn(vf, rd, rn, rm);
5101 subhn2(vf, rd, rn, rm);
5104 rsubhn(vf, rd, rn, rm);
5107 rsubhn2(vf, rd, rn, rm);
5114void Simulator::VisitNEON3Extension(Instruction*
instr) {
5115 NEONFormatDecoder nfd(
instr);
5116 SimVRegister& rd = vreg(
instr->Rd());
5117 SimVRegister& rm = vreg(
instr->Rm());
5118 SimVRegister& rn = vreg(
instr->Rn());
5121 switch (
instr->Mask(NEON3ExtensionMask)) {
5123 if (vf == kFormat4S || vf == kFormat2S) {
5124 sdot(vf, rd, rn, rm);
5126 VisitUnallocated(
instr);
5135void Simulator::VisitNEONAcrossLanes(Instruction*
instr) {
5136 NEONFormatDecoder nfd(
instr);
5138 SimVRegister& rd = vreg(
instr->Rd());
5139 SimVRegister& rn = vreg(
instr->Rn());
5142 if (
instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5143 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5145 switch (
instr->Mask(NEONAcrossLanesFPMask)) {
5153 fmaxnmv(vf, rd, rn);
5156 fminnmv(vf, rd, rn);
5164 switch (
instr->Mask(NEONAcrossLanesMask)) {
5192void Simulator::VisitNEONByIndexedElement(Instruction*
instr) {
5193 NEONFormatDecoder nfd(
instr);
5195 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5197 SimVRegister& rd = vreg(
instr->Rd());
5198 SimVRegister& rn = vreg(
instr->Rn());
5200 ByElementOp Op =
nullptr;
5202 int rm_reg =
instr->Rm();
5203 int index = (
instr->NEONH() << 1) |
instr->NEONL();
5204 if (
instr->NEONSize() == 1) {
5206 index = (index << 1) |
instr->NEONM();
5209 switch (
instr->Mask(NEONByIndexedElementMask)) {
5211 Op = &Simulator::mul;
5215 Op = &Simulator::mla;
5219 Op = &Simulator::mls;
5223 Op = &Simulator::sqdmulh;
5227 Op = &Simulator::sqrdmulh;
5231 if (
instr->Mask(NEON_Q)) {
5232 Op = &Simulator::smull2;
5234 Op = &Simulator::smull;
5238 if (
instr->Mask(NEON_Q)) {
5239 Op = &Simulator::umull2;
5241 Op = &Simulator::umull;
5245 if (
instr->Mask(NEON_Q)) {
5246 Op = &Simulator::smlal2;
5248 Op = &Simulator::smlal;
5252 if (
instr->Mask(NEON_Q)) {
5253 Op = &Simulator::umlal2;
5255 Op = &Simulator::umlal;
5259 if (
instr->Mask(NEON_Q)) {
5260 Op = &Simulator::smlsl2;
5262 Op = &Simulator::smlsl;
5266 if (
instr->Mask(NEON_Q)) {
5267 Op = &Simulator::umlsl2;
5269 Op = &Simulator::umlsl;
5273 if (
instr->Mask(NEON_Q)) {
5274 Op = &Simulator::sqdmull2;
5276 Op = &Simulator::sqdmull;
5280 if (
instr->Mask(NEON_Q)) {
5281 Op = &Simulator::sqdmlal2;
5283 Op = &Simulator::sqdmlal;
5287 if (
instr->Mask(NEON_Q)) {
5288 Op = &Simulator::sqdmlsl2;
5290 Op = &Simulator::sqdmlsl;
5294 index =
instr->NEONH();
5295 if ((
instr->FPType() & 1) == 0) {
5296 index = (index << 1) |
instr->NEONL();
5299 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5301 switch (
instr->Mask(NEONByIndexedElementFPMask)) {
5303 Op = &Simulator::fmul;
5306 Op = &Simulator::fmla;
5309 Op = &Simulator::fmls;
5312 Op = &Simulator::fmulx;
5319 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
5322void Simulator::VisitNEONCopy(Instruction*
instr) {
5323 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::TriangularFormatMap());
5326 SimVRegister& rd = vreg(
instr->Rd());
5327 SimVRegister& rn = vreg(
instr->Rn());
5328 int imm5 =
instr->ImmNEON5();
5330 int reg_index = imm5 >> lsb;
5332 if (
instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5333 int imm4 =
instr->ImmNEON4();
5335 int rn_index = imm4 >> (lsb - 1);
5336 ins_element(vf, rd, reg_index, rn, rn_index);
5337 }
else if (
instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5338 ins_immediate(vf, rd, reg_index, xreg(
instr->Rn()));
5339 }
else if (
instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5340 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5342 set_xreg(
instr->Rd(), value);
5343 }
else if (
instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5344 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5345 if (
instr->NEONQ()) {
5346 set_xreg(
instr->Rd(), value);
5351 }
else if (
instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5352 dup_element(vf, rd, rn, reg_index);
5353 }
else if (
instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5354 dup_immediate(vf, rd, xreg(
instr->Rn()));
5360void Simulator::VisitNEONExtract(Instruction*
instr) {
5361 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::LogicalFormatMap());
5363 SimVRegister& rd = vreg(
instr->Rd());
5364 SimVRegister& rn = vreg(
instr->Rn());
5365 SimVRegister& rm = vreg(
instr->Rm());
5366 if (
instr->Mask(NEONExtractMask) == NEON_EXT) {
5367 int index =
instr->ImmNEONExt();
5368 ext(vf, rd, rn, rm, index);
5374void Simulator::NEONLoadStoreMultiStructHelper(
const Instruction*
instr,
5375 AddrMode addr_mode) {
5376 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::LoadStoreFormatMap());
5379 uint64_t addr_base = xreg(
instr->Rn(), Reg31IsStackPointer);
5384 for (
int i = 0;
i < 4;
i++) {
5386 addr[
i] = addr_base + (
i * reg_size);
5389 bool log_read =
true;
5394 if ((
instr->Bit(23) == 0) && (
instr->Bits(20, 16) != 0)) {
5400 switch (
instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5403 ld1(vf, vreg(
reg[3]), addr[3]);
5408 ld1(vf, vreg(
reg[2]), addr[2]);
5413 ld1(vf, vreg(
reg[1]), addr[1]);
5418 ld1(vf, vreg(
reg[0]), addr[0]);
5422 st1(vf, vreg(
reg[3]), addr[3]);
5427 st1(vf, vreg(
reg[2]), addr[2]);
5432 st1(vf, vreg(
reg[1]), addr[1]);
5437 st1(vf, vreg(
reg[0]), addr[0]);
5442 ld2(vf, vreg(
reg[0]), vreg(
reg[1]), addr[0]);
5447 st2(vf, vreg(
reg[0]), vreg(
reg[1]), addr[0]);
5453 ld3(vf, vreg(
reg[0]), vreg(
reg[1]), vreg(
reg[2]), addr[0]);
5458 st3(vf, vreg(
reg[0]), vreg(
reg[1]), vreg(
reg[2]), addr[0]);
5464 ld4(vf, vreg(
reg[0]), vreg(
reg[1]), vreg(
reg[2]), vreg(
reg[3]), addr[0]);
5469 st4(vf, vreg(
reg[0]), vreg(
reg[1]), vreg(
reg[2]), vreg(
reg[3]), addr[0]);
5478 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
5480 local_monitor_.NotifyLoad();
5482 local_monitor_.NotifyStore();
5483 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
5491 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
5492 GetPrintRegisterFormatForSize(reg_size, lane_size));
5494 LogVRead(addr_base,
reg[
i], format);
5496 LogVWrite(addr_base,
reg[
i], format);
5500 if (addr_mode == PostIndex) {
5501 int rm =
instr->Rm();
5506 set_xreg(
instr->Rn(), addr_base);
5512void Simulator::VisitNEONLoadStoreMultiStruct(Instruction*
instr) {
5513 NEONLoadStoreMultiStructHelper(
instr, Offset);
5516void Simulator::VisitNEONLoadStoreMultiStructPostIndex(Instruction*
instr) {
5517 NEONLoadStoreMultiStructHelper(
instr, PostIndex);
5520void Simulator::NEONLoadStoreSingleStructHelper(
const Instruction*
instr,
5521 AddrMode addr_mode) {
5522 uint64_t addr = xreg(
instr->Rn(), Reg31IsStackPointer);
5523 int rt =
instr->Rt();
5530 bool do_load =
false;
5532 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::LoadStoreFormatMap());
5538 switch (
instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
5599 "LSB of size distinguishes S and D registers.");
5602 "LSB of size distinguishes S and D registers.");
5604 "LSB of size distinguishes S and D registers.");
5607 "LSB of size distinguishes S and D registers.");
5616 ld1r(vf, vreg(rt), addr);
5625 int rt2 = (rt + 1) % kNumberOfVRegisters;
5626 ld2r(vf, vreg(rt), vreg(rt2), addr);
5635 int rt2 = (rt + 1) % kNumberOfVRegisters;
5636 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5637 ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
5646 int rt2 = (rt + 1) % kNumberOfVRegisters;
5647 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5648 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5649 ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
5657 PrintRegisterFormat print_format =
5658 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
5661 static_cast<PrintRegisterFormat
>(print_format & ~kPrintRegAsVectorMask);
5665 int lane =
instr->NEONLSIndex(index_shift);
5667 int rt2 = (rt + 1) % kNumberOfVRegisters;
5668 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5669 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5670 switch (
instr->Mask(NEONLoadStoreSingleLenMask)) {
5673 if (!ProbeMemory(addr,
scale * esize))
return;
5675 ld1(vf, vreg(rt), lane, addr);
5676 LogVRead(addr, rt, print_format, lane);
5678 st1(vf, vreg(rt), lane, addr);
5679 LogVWrite(addr, rt, print_format, lane);
5684 if (!ProbeMemory(addr,
scale * esize))
return;
5686 ld2(vf, vreg(rt), vreg(rt2), lane, addr);
5687 LogVRead(addr, rt, print_format, lane);
5688 LogVRead(addr + esize, rt2, print_format, lane);
5690 st2(vf, vreg(rt), vreg(rt2), lane, addr);
5691 LogVWrite(addr, rt, print_format, lane);
5692 LogVWrite(addr + esize, rt2, print_format, lane);
5697 if (!ProbeMemory(addr,
scale * esize))
return;
5699 ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
5700 LogVRead(addr, rt, print_format, lane);
5701 LogVRead(addr + esize, rt2, print_format, lane);
5702 LogVRead(addr + (2 * esize), rt3, print_format, lane);
5704 st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
5705 LogVWrite(addr, rt, print_format, lane);
5706 LogVWrite(addr + esize, rt2, print_format, lane);
5707 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
5712 if (!ProbeMemory(addr,
scale * esize))
return;
5714 ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
5715 LogVRead(addr, rt, print_format, lane);
5716 LogVRead(addr + esize, rt2, print_format, lane);
5717 LogVRead(addr + (2 * esize), rt3, print_format, lane);
5718 LogVRead(addr + (3 * esize), rt4, print_format, lane);
5720 st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
5721 LogVWrite(addr, rt, print_format, lane);
5722 LogVWrite(addr + esize, rt2, print_format, lane);
5723 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
5724 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
5732 GlobalMonitor::SimulatorMutex lock_guard(global_monitor_);
5734 local_monitor_.NotifyLoad();
5736 local_monitor_.NotifyStore();
5737 global_monitor_->NotifyStore_Locked(&global_monitor_processor_);
5741 if (addr_mode == PostIndex) {
5742 int rm =
instr->Rm();
5744 set_xreg(
instr->Rn(), addr + ((rm == 31) ? (
scale * lane_size) : xreg(rm)));
5748void Simulator::VisitNEONLoadStoreSingleStruct(Instruction*
instr) {
5749 NEONLoadStoreSingleStructHelper(
instr, Offset);
5752void Simulator::VisitNEONLoadStoreSingleStructPostIndex(Instruction*
instr) {
5753 NEONLoadStoreSingleStructHelper(
instr, PostIndex);
5756void Simulator::VisitNEONModifiedImmediate(Instruction*
instr) {
5757 SimVRegister& rd = vreg(
instr->Rd());
5758 int cmode =
instr->NEONCmode();
5759 int cmode_3_1 = (cmode >> 1) & 7;
5760 int cmode_3 = (cmode >> 3) & 1;
5761 int cmode_2 = (cmode >> 2) & 1;
5762 int cmode_1 = (cmode >> 1) & 1;
5763 int cmode_0 = cmode & 1;
5764 int q =
instr->NEONQ();
5765 int op_bit =
instr->NEONModImmOp();
5766 uint64_t imm8 =
instr->ImmNEONabcdefgh();
5771 switch (cmode_3_1) {
5776 vform = (q == 1) ? kFormat4S :
kFormat2S;
5777 imm = imm8 << (8 * cmode_3_1);
5781 vform = (q == 1) ? kFormat8H :
kFormat4H;
5782 imm = imm8 << (8 * cmode_1);
5785 vform = (q == 1) ? kFormat4S :
kFormat2S;
5787 imm = imm8 << 8 | 0x000000FF;
5789 imm = imm8 << 16 | 0x0000FFFF;
5793 if (cmode_0 == 0 && op_bit == 0) {
5796 }
else if (cmode_0 == 0 && op_bit == 1) {
5799 for (
int i = 0;
i < 8; ++
i) {
5800 if (imm8 & (1ULL <<
i)) {
5801 imm |= (UINT64_C(0xFF) << (8 *
i));
5807 imm = base::bit_cast<uint32_t>(
instr->ImmNEONFP32());
5808 }
else if (q == 1) {
5810 imm = base::bit_cast<uint64_t>(
instr->ImmNEONFP64());
5812 DCHECK((q == 0) && (op_bit == 1) && (cmode == 0xF));
5813 VisitUnallocated(
instr);
5852 orr(vform, rd, rd, imm);
5855 bic(vform, rd, rd, imm);
5858 movi(vform, rd, imm);
5861 mvni(vform, rd, imm);
5864 VisitUnimplemented(
instr);
5868void Simulator::VisitNEONScalar2RegMisc(Instruction*
instr) {
5869 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::ScalarFormatMap());
5872 SimVRegister& rd = vreg(
instr->Rd());
5873 SimVRegister& rn = vreg(
instr->Rn());
5875 if (
instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
5878 switch (
instr->Mask(NEONScalar2RegMiscMask)) {
5880 cmp(vf, rd, rn, 0, eq);
5883 cmp(vf, rd, rn, 0, ge);
5886 cmp(vf, rd, rn, 0, gt);
5889 cmp(vf, rd, rn, 0, lt);
5892 cmp(vf, rd, rn, 0, le);
5898 abs(vf, rd, rn).SignedSaturate(vf);
5904 neg(vf, rd, rn).SignedSaturate(vf);
5916 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5921 switch (
instr->Mask(NEONScalar2RegMiscFPMask)) {
5923 frecpe(fpf, rd, rn, fpcr_rounding);
5926 frecpx(fpf, rd, rn);
5929 frsqrte(fpf, rd, rn);
5932 fcmp_zero(fpf, rd, rn, gt);
5935 fcmp_zero(fpf, rd, rn, ge);
5938 fcmp_zero(fpf, rd, rn, eq);
5941 fcmp_zero(fpf, rd, rn, le);
5944 fcmp_zero(fpf, rd, rn, lt);
5947 scvtf(fpf, rd, rn, 0, fpcr_rounding);
5950 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
5953 fcvts(fpf, rd, rn, FPTieEven);
5956 fcvtu(fpf, rd, rn, FPTieEven);
5959 fcvts(fpf, rd, rn, FPPositiveInfinity);
5962 fcvtu(fpf, rd, rn, FPPositiveInfinity);
5965 fcvts(fpf, rd, rn, FPNegativeInfinity);
5968 fcvtu(fpf, rd, rn, FPNegativeInfinity);
5971 fcvts(fpf, rd, rn, FPZero);
5974 fcvtu(fpf, rd, rn, FPZero);
5977 fcvts(fpf, rd, rn, FPTieAway);
5980 fcvtu(fpf, rd, rn, FPTieAway);
5986 fcvtxn(kFormatS, rd, rn);
5989 switch (
instr->Mask(NEONScalar2RegMiscMask)) {
6006void Simulator::VisitNEONScalar3Diff(Instruction*
instr) {
6007 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::LongScalarFormatMap());
6010 SimVRegister& rd = vreg(
instr->Rd());
6011 SimVRegister& rn = vreg(
instr->Rn());
6012 SimVRegister& rm = vreg(
instr->Rm());
6013 switch (
instr->Mask(NEONScalar3DiffMask)) {
6015 sqdmlal(vf, rd, rn, rm);
6018 sqdmlsl(vf, rd, rn, rm);
6021 sqdmull(vf, rd, rn, rm);
6028void Simulator::VisitNEONScalar3Same(Instruction*
instr) {
6029 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::ScalarFormatMap());
6032 SimVRegister& rd = vreg(
instr->Rd());
6033 SimVRegister& rn = vreg(
instr->Rn());
6034 SimVRegister& rm = vreg(
instr->Rm());
6036 if (
instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6037 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6038 switch (
instr->Mask(NEONScalar3SameFPMask)) {
6040 fmulx(vf, rd, rn, rm);
6043 fabscmp(vf, rd, rn, rm, ge);
6046 fabscmp(vf, rd, rn, rm, gt);
6049 fcmp(vf, rd, rn, rm, eq);
6052 fcmp(vf, rd, rn, rm, ge);
6055 fcmp(vf, rd, rn, rm, gt);
6058 frecps(vf, rd, rn, rm);
6061 frsqrts(vf, rd, rn, rm);
6064 fabd(vf, rd, rn, rm);
6070 switch (
instr->Mask(NEONScalar3SameMask)) {
6072 add(vf, rd, rn, rm);
6075 sub(vf, rd, rn, rm);
6078 cmp(vf, rd, rn, rm, eq);
6081 cmp(vf, rd, rn, rm, ge);
6084 cmp(vf, rd, rn, rm, gt);
6087 cmp(vf, rd, rn, rm, hi);
6090 cmp(vf, rd, rn, rm, hs);
6093 cmptst(vf, rd, rn, rm);
6096 ushl(vf, rd, rn, rm);
6099 sshl(vf, rd, rn, rm);
6102 sqdmulh(vf, rd, rn, rm);
6105 sqrdmulh(vf, rd, rn, rm);
6108 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6111 add(vf, rd, rn, rm).SignedSaturate(vf);
6114 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6117 sub(vf, rd, rn, rm).SignedSaturate(vf);
6120 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6123 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6126 ushl(vf, rd, rn, rm).Round(vf);
6129 sshl(vf, rd, rn, rm).Round(vf);
6132 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6135 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6143void Simulator::VisitNEONScalarByIndexedElement(Instruction*
instr) {
6144 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::LongScalarFormatMap());
6146 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6148 SimVRegister& rd = vreg(
instr->Rd());
6149 SimVRegister& rn = vreg(
instr->Rn());
6150 ByElementOp Op =
nullptr;
6152 int rm_reg =
instr->Rm();
6153 int index = (
instr->NEONH() << 1) |
instr->NEONL();
6154 if (
instr->NEONSize() == 1) {
6156 index = (index << 1) |
instr->NEONM();
6159 switch (
instr->Mask(NEONScalarByIndexedElementMask)) {
6161 Op = &Simulator::sqdmull;
6164 Op = &Simulator::sqdmlal;
6167 Op = &Simulator::sqdmlsl;
6170 Op = &Simulator::sqdmulh;
6174 Op = &Simulator::sqrdmulh;
6178 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6179 index =
instr->NEONH();
6180 if ((
instr->FPType() & 1) == 0) {
6181 index = (index << 1) |
instr->NEONL();
6183 switch (
instr->Mask(NEONScalarByIndexedElementFPMask)) {
6185 Op = &Simulator::fmul;
6188 Op = &Simulator::fmla;
6191 Op = &Simulator::fmls;
6194 Op = &Simulator::fmulx;
6201 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
6204void Simulator::VisitNEONScalarCopy(Instruction*
instr) {
6205 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::TriangularScalarFormatMap());
6208 SimVRegister& rd = vreg(
instr->Rd());
6209 SimVRegister& rn = vreg(
instr->Rn());
6211 if (
instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6212 int imm5 =
instr->ImmNEON5();
6214 int rn_index = imm5 >> lsb;
6215 dup_element(vf, rd, rn, rn_index);
6221void Simulator::VisitNEONScalarPairwise(Instruction*
instr) {
6222 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::FPScalarFormatMap());
6225 SimVRegister& rd = vreg(
instr->Rd());
6226 SimVRegister& rn = vreg(
instr->Rn());
6227 switch (
instr->Mask(NEONScalarPairwiseMask)) {
6238 fmaxnmp(vf, rd, rn);
6244 fminnmp(vf, rd, rn);
6251void Simulator::VisitNEONScalarShiftImmediate(Instruction*
instr) {
6252 SimVRegister& rd = vreg(
instr->Rd());
6253 SimVRegister& rn = vreg(
instr->Rn());
6256 static const NEONFormatMap map = {
6258 {
NF_UNDEF,
NF_B,
NF_H,
NF_H,
NF_S,
NF_S,
NF_S,
NF_S,
NF_D,
NF_D,
NF_D,
6260 NEONFormatDecoder nfd(
instr, &map);
6264 int immhimmb =
instr->ImmNEONImmhImmb();
6265 int right_shift = (16 << highestSetBit) - immhimmb;
6266 int left_shift = immhimmb - (8 << highestSetBit);
6267 switch (
instr->Mask(NEONScalarShiftImmediateMask)) {
6269 shl(vf, rd, rn, left_shift);
6272 sli(vf, rd, rn, left_shift);
6275 sqshl(vf, rd, rn, left_shift);
6278 uqshl(vf, rd, rn, left_shift);
6281 sqshlu(vf, rd, rn, left_shift);
6284 sri(vf, rd, rn, right_shift);
6287 sshr(vf, rd, rn, right_shift);
6290 ushr(vf, rd, rn, right_shift);
6293 sshr(vf, rd, rn, right_shift).Round(vf);
6296 ushr(vf, rd, rn, right_shift).Round(vf);
6299 ssra(vf, rd, rn, right_shift);
6302 usra(vf, rd, rn, right_shift);
6305 srsra(vf, rd, rn, right_shift);
6308 ursra(vf, rd, rn, right_shift);
6311 uqshrn(vf, rd, rn, right_shift);
6314 uqrshrn(vf, rd, rn, right_shift);
6317 sqshrn(vf, rd, rn, right_shift);
6320 sqrshrn(vf, rd, rn, right_shift);
6323 sqshrun(vf, rd, rn, right_shift);
6326 sqrshrun(vf, rd, rn, right_shift);
6329 fcvts(vf, rd, rn, FPZero, right_shift);
6332 fcvtu(vf, rd, rn, FPZero, right_shift);
6335 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6338 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6345void Simulator::VisitNEONShiftImmediate(Instruction*
instr) {
6346 SimVRegister& rd = vreg(
instr->Rd());
6347 SimVRegister& rn = vreg(
instr->Rn());
6352 static const NEONFormatMap map = {
6353 {22, 21, 20, 19, 30},
6358 NEONFormatDecoder nfd(
instr, &map);
6362 static const NEONFormatMap map_l = {
6368 int immhimmb =
instr->ImmNEONImmhImmb();
6369 int right_shift = (16 << highestSetBit) - immhimmb;
6370 int left_shift = immhimmb - (8 << highestSetBit);
6372 switch (
instr->Mask(NEONShiftImmediateMask)) {
6374 shl(vf, rd, rn, left_shift);
6377 sli(vf, rd, rn, left_shift);
6380 sqshlu(vf, rd, rn, left_shift);
6383 sri(vf, rd, rn, right_shift);
6386 sshr(vf, rd, rn, right_shift);
6389 ushr(vf, rd, rn, right_shift);
6392 sshr(vf, rd, rn, right_shift).Round(vf);
6395 ushr(vf, rd, rn, right_shift).Round(vf);
6398 ssra(vf, rd, rn, right_shift);
6401 usra(vf, rd, rn, right_shift);
6404 srsra(vf, rd, rn, right_shift);
6407 ursra(vf, rd, rn, right_shift);
6410 sqshl(vf, rd, rn, left_shift);
6413 uqshl(vf, rd, rn, left_shift);
6416 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6419 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6422 fcvts(vf, rd, rn, FPZero, right_shift);
6425 fcvtu(vf, rd, rn, FPZero, right_shift);
6429 if (
instr->Mask(NEON_Q)) {
6430 sshll2(vf, rd, rn, left_shift);
6432 sshll(vf, rd, rn, left_shift);
6437 if (
instr->Mask(NEON_Q)) {
6438 ushll2(vf, rd, rn, left_shift);
6440 ushll(vf, rd, rn, left_shift);
6444 if (
instr->Mask(NEON_Q)) {
6445 shrn2(vf, rd, rn, right_shift);
6447 shrn(vf, rd, rn, right_shift);
6451 if (
instr->Mask(NEON_Q)) {
6452 rshrn2(vf, rd, rn, right_shift);
6454 rshrn(vf, rd, rn, right_shift);
6458 if (
instr->Mask(NEON_Q)) {
6459 uqshrn2(vf, rd, rn, right_shift);
6461 uqshrn(vf, rd, rn, right_shift);
6465 if (
instr->Mask(NEON_Q)) {
6466 uqrshrn2(vf, rd, rn, right_shift);
6468 uqrshrn(vf, rd, rn, right_shift);
6472 if (
instr->Mask(NEON_Q)) {
6473 sqshrn2(vf, rd, rn, right_shift);
6475 sqshrn(vf, rd, rn, right_shift);
6479 if (
instr->Mask(NEON_Q)) {
6480 sqrshrn2(vf, rd, rn, right_shift);
6482 sqrshrn(vf, rd, rn, right_shift);
6486 if (
instr->Mask(NEON_Q)) {
6487 sqshrun2(vf, rd, rn, right_shift);
6489 sqshrun(vf, rd, rn, right_shift);
6493 if (
instr->Mask(NEON_Q)) {
6494 sqrshrun2(vf, rd, rn, right_shift);
6496 sqrshrun(vf, rd, rn, right_shift);
6504void Simulator::VisitNEONTable(Instruction*
instr) {
6505 NEONFormatDecoder nfd(
instr, NEONFormatDecoder::LogicalFormatMap());
6508 SimVRegister& rd = vreg(
instr->Rd());
6509 SimVRegister& rn = vreg(
instr->Rn());
6510 SimVRegister& rn2 = vreg((
instr->Rn() + 1) % kNumberOfVRegisters);
6511 SimVRegister& rn3 = vreg((
instr->Rn() + 2) % kNumberOfVRegisters);
6512 SimVRegister& rn4 = vreg((
instr->Rn() + 3) % kNumberOfVRegisters);
6513 SimVRegister& rm = vreg(
instr->Rm());
6515 switch (
instr->Mask(NEONTableMask)) {
6517 tbl(vf, rd, rn, rm);
6520 tbl(vf, rd, rn, rn2, rm);
6523 tbl(vf, rd, rn, rn2, rn3, rm);
6526 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
6529 tbx(vf, rd, rn, rm);
6532 tbx(vf, rd, rn, rn2, rm);
6535 tbx(vf, rd, rn, rn2, rn3, rm);
6538 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
6545void Simulator::VisitNEONSHA3(Instruction*
instr) {
6546 NEONFormatDecoder nfd(
instr);
6549 SimVRegister& rd = vreg(
instr->Rd());
6550 SimVRegister& rn = vreg(
instr->Rn());
6551 SimVRegister& rm = vreg(
instr->Rm());
6552 SimVRegister& ra = vreg(
instr->Ra());
6555 switch (
instr->Mask(NEONSHA3Mask)) {
6557 bic(vf, temp, rm, ra);
6558 eor(vf, rd, rn, temp);
6561 eor(vf, temp, rm, ra);
6562 eor(vf, rd, rn, temp);
6568void Simulator::VisitNEONPerm(Instruction*
instr) {
6569 NEONFormatDecoder nfd(
instr);
6572 SimVRegister& rd = vreg(
instr->Rd());
6573 SimVRegister& rn = vreg(
instr->Rn());
6574 SimVRegister& rm = vreg(
instr->Rm());
6576 switch (
instr->Mask(NEONPermMask)) {
6578 trn1(vf, rd, rn, rm);
6581 trn2(vf, rd, rn, rm);
6584 uzp1(vf, rd, rn, rm);
6587 uzp2(vf, rd, rn, rm);
6590 zip1(vf, rd, rn, rm);
6593 zip2(vf, rd, rn, rm);
6600void Simulator::DoSwitchStackLimit(Instruction*
instr) {
6601 const int64_t stack_limit = xreg(16);
6608 SetStackLimit(stack_limit);
6611void Simulator::DoPrintf(Instruction*
instr) {
6613 (
instr->ImmException() == kImmExceptionIsPrintf));
6617 uint32_t arg_pattern_list;
6618 static_assert(
sizeof(*instr) == 1);
6619 memcpy(&arg_count,
instr + kPrintfArgCountOffset,
sizeof(arg_count));
6620 memcpy(&arg_pattern_list,
instr + kPrintfArgPatternListOffset,
6621 sizeof(arg_pattern_list));
6623 DCHECK_LE(arg_count, kPrintfMaxArgCount);
6624 DCHECK_EQ(arg_pattern_list >> (kPrintfArgPatternBits * arg_count), 0);
6637 size_t length = strlen(format_base) + 1;
6638 char*
const format =
new char[length + arg_count];
6644 uint32_t placeholder_count = 0;
6645 char* format_scratch = format;
6647 if (format_base[
i] !=
'%') {
6648 *format_scratch++ = format_base[
i];
6650 if (format_base[
i + 1] ==
'%') {
6652 *format_scratch++ = format_base[
i];
6654 if (placeholder_count == 0) {
6660 *format_scratch++ = format_base[++
i];
6663 CHECK(placeholder_count < arg_count);
6665 *format_scratch++ =
'\0';
6666 chunks[placeholder_count++] = format_scratch;
6667 *format_scratch++ = format_base[
i];
6671 DCHECK(format_scratch <= (format + length + arg_count));
6672 CHECK(placeholder_count == arg_count);
6679 fprintf(stream_,
"%s", clr_printf);
6683 int result = fprintf(stream_,
"%s", format);
6687 for (uint32_t
i = 0;
i < placeholder_count;
i++) {
6688 int part_result = -1;
6690 uint32_t arg_pattern = arg_pattern_list >> (
i * kPrintfArgPatternBits);
6691 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
6692 switch (arg_pattern) {
6694 part_result = fprintf(stream_, chunks[
i], wreg(pcs_r++));
6697 part_result = fprintf(stream_, chunks[
i], xreg(pcs_r++));
6700 part_result = fprintf(stream_, chunks[
i], dreg(pcs_f++));
6706 if (part_result < 0) {
6716 fprintf(stream_,
"%s", clr_normal);
6719 CorruptAllCallerSavedCPURegisters();
6726 set_pc(
instr->InstructionAtOffset(kPrintfLength));
6734Simulator::LocalMonitor::LocalMonitor()
6735 : access_state_(MonitorAccess::Open),
6739void Simulator::LocalMonitor::Clear() {
6740 access_state_ = MonitorAccess::Open;
6742 size_ = TransactionSize::None;
6745void Simulator::LocalMonitor::NotifyLoad() {
6746 if (access_state_ == MonitorAccess::Exclusive) {
6753void Simulator::LocalMonitor::NotifyLoadExcl(uintptr_t addr,
6754 TransactionSize size) {
6755 access_state_ = MonitorAccess::Exclusive;
6756 tagged_addr_ = addr;
6760void Simulator::LocalMonitor::NotifyStore() {
6761 if (access_state_ == MonitorAccess::Exclusive) {
6768bool Simulator::LocalMonitor::NotifyStoreExcl(uintptr_t addr,
6769 TransactionSize size) {
6770 if (access_state_ == MonitorAccess::Exclusive) {
6773 if (addr == tagged_addr_ &&
size_ == size) {
6784 DCHECK(access_state_ == MonitorAccess::Open);
6789Simulator::GlobalMonitor::Processor::Processor()
6790 : access_state_(MonitorAccess::Open),
6794 failure_counter_(0) {}
6796void Simulator::GlobalMonitor::Processor::Clear_Locked() {
6797 access_state_ = MonitorAccess::Open;
6801void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(
6803 access_state_ = MonitorAccess::Exclusive;
6804 tagged_addr_ = addr;
6807void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
6808 bool is_requesting_processor) {
6809 if (access_state_ == MonitorAccess::Exclusive) {
6816bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
6817 uintptr_t addr,
bool is_requesting_processor) {
6818 if (access_state_ == MonitorAccess::Exclusive) {
6819 if (is_requesting_processor) {
6822 if (addr == tagged_addr_) {
6827 if (failure_counter_++ >= kMaxFailureCounter) {
6828 failure_counter_ = 0;
6834 }
else if ((addr & kExclusiveTaggedAddrMask) ==
6835 (tagged_addr_ & kExclusiveTaggedAddrMask)) {
6846void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(uintptr_t addr,
6847 Processor* processor) {
6848 processor->NotifyLoadExcl_Locked(addr);
6851void Simulator::GlobalMonitor::NotifyStore_Locked(Processor* processor) {
6853 for (Processor* iter = head_; iter; iter = iter->next_) {
6854 bool is_requesting_processor = iter == processor;
6855 iter->NotifyStore_Locked(is_requesting_processor);
6859bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(uintptr_t addr,
6860 Processor* processor) {
6861 if (processor->NotifyStoreExcl_Locked(addr,
true)) {
6863 for (Processor* iter = head_; iter; iter = iter->next_) {
6864 if (iter != processor) {
6865 iter->NotifyStoreExcl_Locked(addr,
false);
6874void Simulator::GlobalMonitor::PrependProcessor(Processor* processor) {
6875 base::MutexGuard lock_guard(&
mutex_);
6877 head_->prev_ = processor;
6879 processor->prev_ =
nullptr;
6880 processor->next_ = head_;
6885void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
6886 base::MutexGuard lock_guard(&
mutex_);
6887 if (processor->prev_) {
6888 processor->prev_->next_ = processor->next_;
6890 head_ = processor->next_;
6892 if (processor->next_) {
6893 processor->next_->prev_ = processor->prev_;
6895 processor->prev_ =
nullptr;
6896 processor->next_ =
nullptr;
6924 const char* command) {
6927 fprintf(stderr,
"No V8 Isolate found\n");
6930 i::Simulator* simulator = i::Simulator::current(isolate);
6932 fprintf(stderr,
"No Arm64 simulator found\n");
6936 size_t len = strlen(command);
6938 i::MemCopy(command_copy.get(), command, len + 1);
6939 return simulator->ExecDebugCommand(std::move(command_copy));
interpreter::OperandScale scale
virtual void VisitPointer(const void *address)=0
static int ActivationFrameAlignment()
static V8_NOINLINE StackSlot GetCurrentStackPosition()
static Instr ImmException(int imm16)
StackGuard * stack_guard()
constexpr int8_t code() const
#define ENABLE_CONTROL_FLOW_INTEGRITY_BOOL
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
#define MSAN_MEMORY_IS_INITIALIZED(start, size)
constexpr unsigned CountLeadingZeros(T value)
constexpr unsigned CountTrailingZeros(T value)
constexpr unsigned CountLeadingSignBits(T value)
constexpr Vector< T > VectorOf(T *start, size_t size)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD3_post
constexpr DataProcessing1SourceOp RBIT_w
constexpr NEONLoadStoreSingleOp NEONLoadStoreSingle2
constexpr NEONScalarPairwiseOp NEON_FMINNMP_scalar
constexpr NEON2RegMiscOp NEON_FNEG
constexpr FPDataProcessing1SourceOp FSQRT_d
constexpr FPDataProcessing2SourceOp FMUL_s
constexpr FPFixedPointConvertOp SCVTF_dw_fixed
constexpr NEONTableOp NEON_TBX_4v
constexpr NEON3SameOp NEON_FMULX
constexpr DataProcessing1SourceOp REV_x
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST4_s_post
constexpr FPConditionalCompareOp FCCMP_d
constexpr BitfieldOp BFM_x
constexpr LoadStoreAcquireReleaseOp LDAR_h
constexpr NEONShiftImmediateOp NEON_SSRA
constexpr NEONScalar3SameOp NEON_UQADD_scalar
constexpr NEONLoadStoreSingleOp NEONLoadStoreSingle4
constexpr NEONScalar2RegMiscOp NEON_FCVTNS_scalar
constexpr NEONScalar3SameOp NEON_CMGE_scalar
constexpr FPIntegerConvertOp FCVTNU_xd
constexpr UnconditionalBranchOp BL
constexpr NEONLoadStoreMultiStructOp NEON_LD3
constexpr NEONLoadStoreSingleStructOp NEON_LD3_h
constexpr FPIntegerConvertOp FCVTZS_wd
constexpr NEON3SameOp NEON_SMAX
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST3_b_post
constexpr NEONScalarPairwiseOp NEON_FMAXP_scalar
constexpr NEON3SameOp NEON_SABD
constexpr NEONLoadStoreSingleStructOp NEON_ST1_b
constexpr FPCompareOp FCMP_d_zero
constexpr NEON2RegMiscOp NEON_FCMLT_zero
constexpr FPIntegerConvertOp FCVTAS_ws
constexpr NEONScalar2RegMiscOp NEON_FRECPE_scalar
constexpr NEONScalar2RegMiscOp NEON_FCVTAU_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD1_s
constexpr NEON3SameOp NEON_FCMGE
constexpr BitfieldOp UBFM_w
constexpr ExceptionOp BRK
constexpr NEONLoadStoreMultiStructOp NEON_ST3
constexpr int64_t kByteMask
constexpr FPIntegerConvertOp FCVTZU_xd
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD4_s_post
constexpr NEON2RegMiscOp NEON_UADDLP
constexpr DataProcessing3SourceOp MSUB_x
constexpr NEONScalarByIndexedElementOp NEON_SQDMLSL_byelement_scalar
constexpr NEONScalarPairwiseOp NEON_FADDP_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD2_h
constexpr NEONSHA3Op NEON_EOR3
constexpr NEON3SameOp NEON_FADD
constexpr NEONScalar2RegMiscOp NEON_FCVTMS_scalar
constexpr FPFixedPointConvertOp SCVTF_sx_fixed
constexpr DataProcessing2SourceOp LSLV_w
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD1_s_post
constexpr DataProcessing3SourceOp SMSUBL_x
constexpr NEON2RegMiscOp NEON_CMGT_zero
constexpr FPDataProcessing3SourceOp FNMSUB_d
constexpr NEON3SameOp NEON_FRECPS
constexpr FPDataProcessing1SourceOp FRINTX_d
constexpr BitfieldOp SBFM_w
constexpr FPIntegerConvertOp UCVTF_sx
constexpr NEON3SameOp NEON_SQADD
constexpr FPDataProcessing3SourceOp FNMSUB_s
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD1_h_post
constexpr FPDataProcessing1SourceOp FMOV_s
constexpr NEON3DifferentOp NEON_SABAL
constexpr FPDataProcessing1SourceOp FRINTM_d
constexpr NEONScalar3SameOp NEON_SSHL_scalar
constexpr FPDataProcessing2SourceOp FMIN_s
constexpr NEONScalar3SameOp NEON_UQSUB_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD2_s
constexpr NEONScalar2RegMiscOp NEON_FCVTNU_scalar
constexpr NEONLoadStoreSingleStructOp NEON_ST3_h
int LowestSetBitPosition(uint64_t value)
constexpr NEONLoadStoreMultiStructOp NEON_ST1_4v
uint32_t NEONModifiedImmediateOp
constexpr NEONModifiedImmediateOp NEONModifiedImmediate_BIC
constexpr NEONShiftImmediateOp NEON_RSHRN
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD3_b_post
constexpr FPDataProcessing2SourceOp FSUB_d
constexpr NEON2RegMiscOp NEON_FCVTMU
constexpr NEONShiftImmediateOp NEON_URSHR
constexpr LoadStoreAcquireReleaseOp CASB
constexpr NEONScalar3SameOp NEON_UQSHL_scalar
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST3_s_post
const Instr kImmExceptionIsRedirectedCall
constexpr NEONScalar2RegMiscOp NEON_SUQADD_scalar
constexpr LoadStoreAcquireReleaseOp STLR_h
constexpr LoadStoreAcquireReleaseOp CASPA_w
constexpr NEONScalar2RegMiscOp NEON_FCVTPU_scalar
constexpr UnconditionalBranchToRegisterOp BLR
constexpr AtomicMemoryOp SWPALB
constexpr FPDataProcessing1SourceOp FCVT_hs
constexpr NEON2RegMiscOp NEON_ABS
constexpr NEONShiftImmediateOp NEON_FCVTZS_imm
constexpr NEON2RegMiscOp NEON_FCVTAS
constexpr NEONLoadStoreSingleStructOp NEON_LD4_b
constexpr NEONScalarShiftImmediateOp NEON_SQRSHRN_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD1_b
constexpr NEONScalarShiftImmediateOp NEON_SQSHLU_scalar
constexpr FPCompareOp FCMP_d
constexpr NEONScalarByIndexedElementOp NEON_FMUL_byelement_scalar
constexpr FPDataProcessing1SourceOp FRINTN_d
constexpr LoadStoreAcquireReleaseOp CAS_x
constexpr NEONScalarPairwiseOp NEON_ADDP_scalar
constexpr NEONShiftImmediateOp NEON_UQSHRN
constexpr FPDataProcessing1SourceOp FRINTX_s
constexpr NEON3SameOp NEON_UMAXP
constexpr NEONShiftImmediateOp NEON_SSHR
constexpr NEON3SameOp NEON_PMUL
constexpr FPIntegerConvertOp FCVTMU_ws
constexpr NEON3DifferentOp NEON_SMLSL2
constexpr NEON3SameOp NEON_CMGE
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD4_h_post
constexpr NEONScalar3SameOp NEON_SQADD_scalar
constexpr LoadStoreAcquireReleaseOp CASA_w
constexpr NEON3SameOp NEON_SUB
constexpr NEON3SameOp NEON_BSL
constexpr FPIntegerConvertOp FCVTZU_xs
constexpr NEON3SameOp NEON_UHADD
constexpr NEON3SameOp NEON_FABD
constexpr AtomicMemoryOp SWPLB
constexpr FPIntegerConvertOp FCVTMU_xs
constexpr LoadStoreAcquireReleaseOp CASALH
constexpr NEON3SameOp NEON_UHSUB
constexpr NEONTableOp NEON_TBL_2v
constexpr NEONScalarShiftImmediateOp NEON_FCVTZS_imm_scalar
constexpr FPCompareOp FCMP_s_zero
constexpr NEONLoadStoreMultiStructOp NEON_LD2
constexpr LoadStoreAcquireReleaseOp STLXR_x
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD3R_post
constexpr NEONAcrossLanesOp NEON_SMINV
constexpr NEONScalarShiftImmediateOp NEON_URSHR_scalar
constexpr int64_t kWRegMask
constexpr DataProcessing3SourceOp MSUB_w
constexpr NEONScalarShiftImmediateOp NEON_UCVTF_imm_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD1_h
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD4_post
constexpr LoadStoreAcquireReleaseOp CASH
constexpr FPDataProcessing3SourceOp FMADD_d
constexpr NEONShiftImmediateOp NEON_SRSHR
constexpr NEONScalar3SameOp NEON_ADD_scalar
constexpr NEON3SameOp NEON_FACGE
constexpr NEON3SameOp NEON_UMIN
constexpr NEON2RegMiscOp NEON_SADALP
constexpr LoadStoreAcquireReleaseOp LDAR_x
void PrintF(const char *format,...)
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD3_h_post
constexpr ConditionalSelectOp CSINC_w
char * ReadLine(const char *prompt)
constexpr NEON3SameOp NEON_FMLS
constexpr NEON3SameOp NEON_ORN
constexpr FPFixedPointConvertOp UCVTF_dx_fixed
constexpr BitfieldOp SBFM_x
constexpr FPDataProcessing1SourceOp FRINTZ_d
constexpr FPFixedPointConvertOp UCVTF_dw_fixed
constexpr DataProcessing2SourceOp LSLV_x
constexpr FPDataProcessing1SourceOp FNEG_d
constexpr NEONScalarShiftImmediateOp NEON_URSRA_scalar
constexpr NEON3DifferentOp NEON_SADDL2
constexpr ConditionalSelectOp CSEL_x
constexpr TestBranchOp TBZ
constexpr NEON2RegMiscOp NEON_CMLT_zero
constexpr LoadStoreAcquireReleaseOp CASPAL_x
constexpr FPIntegerConvertOp FCVTMS_xd
constexpr NEONScalar2RegMiscOp NEON_ABS_scalar
constexpr NEONLoadStoreMultiStructOp NEON_ST1_3v
constexpr NEON3SameOp NEON_CMGT
const RegList kCalleeSaved
constexpr NEONLoadStoreMultiStructOp NEON_LD1_3v
constexpr NEON2RegMiscOp NEON_FCVTZS
constexpr LoadStoreAcquireReleaseOp CASA_x
constexpr AtomicMemoryOp SWPAL_w
constexpr NEONScalar2RegMiscOp NEON_USQADD_scalar
constexpr PCRelAddressingOp ADRP
constexpr LoadStoreAcquireReleaseOp CASLH
constexpr NEON2RegMiscOp NEON_RBIT_NOT
constexpr LoadStoreAcquireReleaseOp LDAR_w
constexpr LoadStoreAcquireReleaseOp CASAH
constexpr int kNumberOfCalleeSavedVRegisters
constexpr FPIntegerConvertOp FCVTNS_xs
constexpr NEONAcrossLanesOp NEON_UMINV
constexpr NEON3DifferentOp NEON_SQDMULL2
constexpr FPDataProcessing3SourceOp FMADD_s
constexpr FPDataProcessing1SourceOp FCVT_dh
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST1_s_post
constexpr NEONTableOp NEON_TBL_1v
constexpr NEON2RegMiscOp NEON_FCVTN
constexpr NEONScalar3SameOp NEON_SQRDMULH_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD1R
constexpr NEONScalar2RegMiscOp NEON_FRECPX_scalar
constexpr NEON3SameOp NEON_URHADD
constexpr NEON3SameOp NEON_CMHI
constexpr NEON3DifferentOp NEON_SSUBW
constexpr NEON3SameOp NEON_URSHL
constexpr NEONByIndexedElementOp NEON_SQDMLSL_byelement
constexpr NEONScalar3SameOp NEON_FRECPS_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD4_h
constexpr FPIntegerConvertOp FCVTMU_wd
constexpr NEON3DifferentOp NEON_SMULL2
constexpr LoadStoreAcquireReleaseOp CASAL_x
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD2_s_post
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST2_post
constexpr FPDataProcessing2SourceOp FMAX_d
constexpr unsigned kShiftAmountXRegMask
constexpr NEONPermOp NEON_ZIP1
constexpr int kZeroRegCode
constexpr NEON3DifferentOp NEON_SSUBL
constexpr int kNumberOfRegisters
constexpr NEON3DifferentOp NEON_SADDW
constexpr NEONScalar3SameOp NEON_FACGT_scalar
constexpr NEON3SameOp NEON_UABD
constexpr FPDataProcessing3SourceOp FNMADD_d
constexpr NEON2RegMiscOp NEON_FCVTZU
constexpr NEON3SameOp NEON_FMAX
constexpr NEONLoadStoreSingleStructOp NEON_ST2_h
constexpr NEON3SameOp NEON_ADD
constexpr NEON2RegMiscOp NEON_FCVTMS
constexpr NEON2RegMiscOp NEON_FRINTM
constexpr NEONShiftImmediateOp NEON_URSRA
constexpr NEON3SameOp NEON_UMAX
constexpr FPDataProcessing1SourceOp FRINTM_s
constexpr NEONShiftImmediateOp NEON_SQSHRUN
constexpr FPDataProcessing1SourceOp FRINTA_s
uint64_t MaxUintFromFormat(VectorFormat vform)
constexpr NEON3SameOp NEON_UQADD
constexpr DataProcessing1SourceOp RBIT_x
constexpr NEONLoadStoreMultiStructOp NEON_ST2
constexpr NEONAcrossLanesOp NEON_UMAXV
constexpr NEONScalar2RegMiscOp NEON_CMEQ_zero_scalar
constexpr NEONScalar2RegMiscOp NEON_UQXTN_scalar
constexpr FPDataProcessing2SourceOp FMAXNM_s
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST2_b_post
constexpr FPDataProcessing2SourceOp FADD_s
constexpr NEON3SameOp NEON_SHSUB
constexpr NEON3DifferentOp NEON_SMLAL2
constexpr DataProcessing1SourceOp REV32_x
constexpr NEON2RegMiscOp NEON_XTN
constexpr FPConditionalSelectOp FCSEL_d
constexpr NEON3SameOp NEON_SSHL
constexpr NEONByIndexedElementOp NEON_SQDMULH_byelement
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
constexpr NEONScalar2RegMiscOp NEON_FCVTZS_scalar
constexpr NEON2RegMiscOp NEON_FCMGE_zero
constexpr BitfieldOp BFM_w
constexpr FPDataProcessing2SourceOp FNMUL_s
constexpr NEONScalar2RegMiscOp NEON_FRSQRTE_scalar
constexpr NEONScalarShiftImmediateOp NEON_SRSRA_scalar
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD4_b_post
constexpr NEONScalarShiftImmediateOp NEON_SHL_scalar
constexpr NEON3SameOp NEON_FMINNM
constexpr FPFixedPointConvertOp SCVTF_dx_fixed
constexpr NEON2RegMiscOp NEON_URECPE
constexpr LoadStoreAcquireReleaseOp CASP_x
constexpr NEON3DifferentOp NEON_SUBHN2
constexpr NEON3DifferentOp NEON_ADDHN
constexpr NEON3SameOp NEON_FRSQRTS
constexpr FPIntegerConvertOp FCVTAU_ws
constexpr AtomicMemoryOp SWPA_x
constexpr FPIntegerConvertOp FCVTMS_ws
int LaneSizeInBytesLog2FromFormat(VectorFormat vform)
constexpr NEON3SameOp NEON_UABA
constexpr NEON2RegMiscOp NEON_URSQRTE
constexpr NEON2RegMiscOp NEON_FCVTAU
constexpr FPConditionalCompareOp FCCMP_s
constexpr NEON3SameOp NEON_FADDP
constexpr NEONModifiedImmediateOp NEONModifiedImmediate_ORR
constexpr LoadStoreAcquireReleaseOp STLXR_b
constexpr NEONScalar2RegMiscOp NEON_SQNEG_scalar
constexpr FPIntegerConvertOp UCVTF_dx
constexpr LoadStoreAcquireReleaseOp LDAXR_h
constexpr NEONLoadStoreMultiStructOp NEON_LD1_2v
constexpr int64_t kWordMask
constexpr LoadStoreAcquireReleaseOp CASAL_w
constexpr NEON3SameOp NEON_FMIN
constexpr NEONScalarShiftImmediateOp NEON_SQSHRN_scalar
constexpr NEON3SameOp NEON_UQRSHL
constexpr NEON3DifferentOp NEON_UABAL
constexpr FPIntegerConvertOp FCVTAS_xd
constexpr NEONScalar2RegMiscOp NEON_UCVTF_scalar
constexpr NEON2RegMiscOp NEON_FCVTL
constexpr FPDataProcessing3SourceOp FMSUB_d
constexpr NEON2RegMiscOp NEON_FRINTI
constexpr NEON2RegMiscOp NEON_SQNEG
constexpr NEONByIndexedElementOp NEON_SQDMLAL_byelement
constexpr BitfieldOp UBFM_x
constexpr NEONTableOp NEON_TBX_1v
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST4_b_post
constexpr FPDataProcessing1SourceOp FCVT_sh
constexpr NEONScalar3SameOp NEON_FRSQRTS_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD3_s
constexpr NEON2RegMiscOp NEON_UCVTF
constexpr NEON3DifferentOp NEON_PMULL2
constexpr SystemSysRegOp MRS
constexpr FPIntegerConvertOp FCVTMS_xs
constexpr NEON2RegMiscOp NEON_REV16
std::unique_ptr< T, ArrayDeleter< T > > ArrayUniquePtr
const unsigned kPrintfMaxArgCount
constexpr NEONScalar3SameOp NEON_URSHL_scalar
constexpr NEON3DifferentOp NEON_SQDMULL
constexpr NEON2RegMiscOp NEON_NEG
constexpr NEONLoadStoreSingleStructOp NEON_ST4_h
constexpr NEON3SameOp NEON_BIF
constexpr DataProcessing1SourceOp CLZ_w
constexpr NEON2RegMiscOp NEON_REV64
constexpr FPIntegerConvertOp FCVTMS_wd
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD2_b_post
constexpr NEONShiftImmediateOp NEON_UQSHL_imm
constexpr NEON3SameOp NEON_CMHS
constexpr NEON3SameOp NEON_UQSUB
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST1_d_post
constexpr FPDataProcessing2SourceOp FDIV_d
constexpr NEONScalar3SameOp NEON_SQSUB_scalar
constexpr NEON3DifferentOp NEON_UADDL
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST1_3v_post
constexpr NEONLoadStoreSingleOp NEONLoadStoreSingle1
constexpr NEON3SameOp NEON_FDIV
constexpr SystemSysRegOp MSR
constexpr NEONScalar3SameOp NEON_SQRSHL_scalar
constexpr NEONLoadStoreSingleStructOp NEON_ST1_h
constexpr NEONTableOp NEON_TBX_3v
constexpr AtomicMemoryOp SWPA_w
constexpr NEONByIndexedElementOp NEON_UMULL_byelement
constexpr FPDataProcessing1SourceOp FCVT_hd
constexpr NEONScalarShiftImmediateOp NEON_SQSHRUN_scalar
constexpr LoadStoreAcquireReleaseOp STLR_x
constexpr NEONShiftImmediateOp NEON_SLI
constexpr NEONScalarByIndexedElementOp NEON_SQRDMULH_byelement_scalar
constexpr DataProcessing3SourceOp SMADDL_x
constexpr NEONLoadStoreSingleStructOp NEON_LD4_s
constexpr NEON2RegMiscOp NEON_FRINTA
constexpr NEON3SameOp NEON_SMAXP
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD1_1v_post
constexpr NEONScalarShiftImmediateOp NEON_SSRA_scalar
int HighestSetBitPosition(uint64_t value)
constexpr CompareBranchOp CBZ_w
constexpr int kSystemPointerSize
constexpr NEONAcrossLanesOp NEON_FMAXV
constexpr NEON3SameOp NEON_SHADD
const RegList kCallerSaved
constexpr unsigned kRegCodeMask
constexpr MoveWideImmediateOp MOVZ_x
constexpr NEON3SameOp NEON_ADDP
constexpr int kQRegSizeLog2
constexpr NEONScalar2RegMiscOp NEON_SQXTN_scalar
constexpr NEON2RegMiscOp NEON_SADDLP
constexpr int64_t kXRegMask
constexpr FPIntegerConvertOp SCVTF_dw
constexpr AtomicMemoryOp SWPL_w
constexpr FPIntegerConvertOp FCVTZS_xs
constexpr NEON3DifferentOp NEON_SADDL
constexpr DataProcessing1SourceOp REV_w
constexpr NEON3SameOp NEON_CMEQ
constexpr NEON3DifferentOp NEON_SABAL2
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST1_1v_post
constexpr NEONScalar3DiffOp NEON_SQDMLAL_scalar
constexpr NEONPermOp NEON_TRN1
constexpr NEONByIndexedElementOp NEON_MUL_byelement
constexpr NEONShiftImmediateOp NEON_SQSHLU
constexpr NEONAcrossLanesOp NEON_FMINNMV
constexpr NEONScalar3SameOp NEON_CMTST_scalar
constexpr NEONScalar3SameOp NEON_FACGE_scalar
constexpr NEON3SameOp NEON_MLA
constexpr AtomicMemoryOp SWPAH
constexpr NEONShiftImmediateOp NEON_USHLL
constexpr NEONScalar3SameOp NEON_SQSHL_scalar
constexpr NEON2RegMiscOp NEON_REV32
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD1R_post
constexpr DataProcessing3SourceOp MADD_w
constexpr FPIntegerConvertOp FCVTNU_wd
constexpr NEONScalarShiftImmediateOp NEON_USHR_scalar
constexpr DataProcessing2SourceOp LSRV_w
constexpr NEON2RegMiscOp NEON_FCMEQ_zero
constexpr DataProcessing3SourceOp UMADDL_x
constexpr NEON3DifferentOp NEON_SABDL2
constexpr NEONScalarShiftImmediateOp NEON_FCVTZU_imm_scalar
constexpr FPDataProcessing2SourceOp FMIN_d
constexpr NEONShiftImmediateOp NEON_SQRSHRUN
constexpr NEONLoadStoreMultiStructOp NEON_LD4
constexpr NEON3SameOp NEON_FSUB
constexpr DataProcessing2SourceOp SDIV_w
constexpr NEON3SameOp NEON_SQDMULH
constexpr NEON3DifferentOp NEON_SQDMLAL2
constexpr FPIntegerConvertOp FCVTMU_xd
constexpr NEONScalar2RegMiscOp NEON_SQXTUN_scalar
constexpr NEON2RegMiscOp NEON_CNT
constexpr NEONPermOp NEON_ZIP2
constexpr NEONScalar3SameOp NEON_CMHI_scalar
constexpr NEON3SameOp NEON_SMINP
constexpr NEONPermOp NEON_TRN2
constexpr UnconditionalBranchToRegisterOp BR
constexpr DataProcessing1SourceOp CLS_w
constexpr LoadLiteralOp LDR_d_lit
constexpr int kDRegSizeLog2
constexpr NEONScalar3SameOp NEON_UQRSHL_scalar
constexpr NEON2RegMiscOp NEON_FRSQRTE
constexpr FPDataProcessing2SourceOp FMINNM_d
constexpr FPIntegerConvertOp FCVTAS_wd
constexpr NEON3DifferentOp NEON_UMLSL2
constexpr FPIntegerConvertOp FCVTNU_ws
constexpr NEONShiftImmediateOp NEON_USRA
constexpr NEONScalar3SameOp NEON_FCMEQ_scalar
void ShortPrint(Tagged< Object > obj, FILE *out)
constexpr NEON3DifferentOp NEON_UMLSL
constexpr NEONScalar3DiffOp NEON_SQDMLSL_scalar
constexpr AtomicMemoryOp SWPB
constexpr NEON3SameOp NEON_FMUL
constexpr NEON3SameOp NEON_FMINNMP
constexpr NEON2RegMiscOp NEON_FCVTXN
constexpr FPIntegerConvertOp SCVTF_sx
constexpr FPDataProcessing1SourceOp FABS_d
constexpr ConditionalSelectOp CSINV_x
constexpr bool is_intn(int64_t x, unsigned n)
constexpr NEONScalarShiftImmediateOp NEON_SSHR_scalar
constexpr FPIntegerConvertOp FCVTAS_xs
constexpr NEON2RegMiscOp NEON_SUQADD
constexpr NEONScalarShiftImmediateOp NEON_SQSHL_imm_scalar
constexpr NEONScalarShiftImmediateOp NEON_SLI_scalar
constexpr DataProcessing1SourceOp REV16_x
constexpr NEONScalar3DiffOp NEON_SQDMULL_scalar
constexpr NEONScalarByIndexedElementOp NEON_FMULX_byelement_scalar
constexpr NEONScalarByIndexedElementOp NEON_SQDMLAL_byelement_scalar
constexpr FPIntegerConvertOp FJCVTZS
constexpr NEONShiftImmediateOp NEON_UCVTF_imm
constexpr NEONScalar3SameOp NEON_FCMGT_scalar
constexpr NEON2RegMiscOp NEON_FRINTZ
constexpr ConditionalSelectOp CSINC_x
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST3_h_post
constexpr NEONByIndexedElementOp NEON_FMULX_byelement
constexpr NEONScalarPairwiseOp NEON_FMAXNMP_scalar
constexpr CompareBranchOp CBZ_x
constexpr NEON3SameOp NEON_ORR
constexpr NEON3DifferentOp NEON_SADDW2
constexpr NEONScalar3SameOp NEON_FCMGE_scalar
constexpr NEON3SameOp NEON_FCMEQ
uint32_t LoadStoreAcquireReleaseOp
constexpr NEONLoadStoreSingleStructOp NEON_ST4_b
constexpr DataProcessing1SourceOp REV16_w
constexpr NEONScalarShiftImmediateOp NEON_SCVTF_imm_scalar
constexpr DataProcessing2SourceOp UDIV_x
constexpr NEONScalar2RegMiscOp NEON_SQABS_scalar
constexpr FPIntegerConvertOp FCVTAU_xd
constexpr DataProcessing2SourceOp LSRV_x
constexpr NEONAcrossLanesOp NEON_SADDLV
constexpr NEON2RegMiscOp NEON_CMLE_zero
constexpr FPDataProcessing1SourceOp FRINTI_s
constexpr FPIntegerConvertOp UCVTF_sw
constexpr NEON3DifferentOp NEON_UADDL2
constexpr AtomicMemoryOp SWP_x
constexpr NEONScalar2RegMiscOp NEON_FCMGT_zero_scalar
constexpr NEONScalar2RegMiscOp NEON_FCMLT_zero_scalar
constexpr NEONShiftImmediateOp NEON_SQRSHRN
constexpr NEONLoadStoreSingleStructOp NEON_ST1_d
constexpr NEON2RegMiscOp NEON_CMEQ_zero
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST1_2v_post
uint32_t MoveWideImmediateOp
constexpr NEON3SameOp NEON_UQSHL
constexpr FPIntegerConvertOp FCVTNS_wd
constexpr MoveWideImmediateOp MOVK_w
constexpr NEON2RegMiscOp NEON_CLS
constexpr NEONAcrossLanesOp NEON_UADDLV
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST1_h_post
constexpr NEON3SameOp NEON_SMIN
constexpr NEONScalar2RegMiscOp NEON_FCMLE_zero_scalar
constexpr NEONLoadStoreSingleStructOp NEON_LD3R
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD2_post
constexpr LoadStoreAcquireReleaseOp CASP_w
constexpr NEON3SameOp NEON_SQRDMULH
constexpr NEONLoadStoreSingleOp NEONLoadStoreSingle3
constexpr NEONScalar2RegMiscOp NEON_CMGT_zero_scalar
constexpr FPIntegerConvertOp FCVTNS_xd
constexpr NEON3SameOp NEON_AND
constexpr LoadStoreAcquireReleaseOp LDAXR_w
unsigned LaneSizeInBitsFromFormat(VectorFormat vform)
constexpr NEONSHA3Op NEON_BCAX
constexpr Register kWasmTrapHandlerFaultAddressRegister
constexpr NEONScalar2RegMiscOp NEON_CMGE_zero_scalar
constexpr LoadStoreAcquireReleaseOp CASPL_x
constexpr NEON3SameOp NEON_FMINP
constexpr NEONByIndexedElementOp NEON_SMLAL_byelement
constexpr NEONAcrossLanesOp NEON_SMAXV
constexpr NEON3SameOp NEON_FMAXNM
constexpr NEON3ExtensionOp NEON_SDOT
constexpr NEONScalar2RegMiscOp NEON_CMLE_zero_scalar
constexpr FPDataProcessing3SourceOp FNMADD_s
constexpr NEON3DifferentOp NEON_UABDL
constexpr FPDataProcessing2SourceOp FNMUL_d
constexpr LoadLiteralOp LDR_w_lit
constexpr NEON3SameOp NEON_USHL
constexpr DataProcessing3SourceOp MADD_x
constexpr NEONScalarShiftImmediateOp NEON_SQRSHRUN_scalar
constexpr NEON3DifferentOp NEON_UABDL2
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST1_4v_post
constexpr NEONPermOp NEON_UZP1
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr DataProcessing1SourceOp CLZ_x
constexpr NEONLoadStoreSingleStructOp NEON_LD1_d
constexpr NEONShiftImmediateOp NEON_SRSRA
constexpr NEON3SameOp NEON_SRSHL
constexpr LoadStoreAcquireReleaseOp CASPA_x
constexpr NEONAcrossLanesOp NEON_ADDV
constexpr FPDataProcessing1SourceOp FNEG_s
constexpr FPIntegerConvertOp FCVTAU_wd
constexpr NEONByIndexedElementOp NEON_FMLA_byelement
constexpr FPConditionalSelectOp FCSEL_s
constexpr NEON3SameOp NEON_SQSHL
constexpr NEONByIndexedElementOp NEON_SMLSL_byelement
constexpr NEONScalar3SameOp NEON_USHL_scalar
constexpr NEONShiftImmediateOp NEON_SSHLL
constexpr NEONScalarPairwiseOp NEON_FMINP_scalar
constexpr NEONShiftImmediateOp NEON_SQSHRN
constexpr DataProcessing3SourceOp SMULH_x
constexpr NEONScalarShiftImmediateOp NEON_USRA_scalar
constexpr FPIntegerConvertOp FMOV_dx
constexpr FPDataProcessing1SourceOp FRINTA_d
constexpr NEONScalarShiftImmediateOp NEON_UQSHRN_scalar
constexpr DataProcessing3SourceOp UMULH_x
constexpr NEONScalar2RegMiscOp NEON_CMLT_zero_scalar
constexpr NEONLoadStoreSingleStructOp NEON_ST2_s
constexpr NEONScalar2RegMiscOp NEON_FCMGE_zero_scalar
constexpr NEONShiftImmediateOp NEON_SRI
constexpr NEONByIndexedElementOp NEON_FMLS_byelement
constexpr NEON3DifferentOp NEON_SQDMLSL2
constexpr NEON3DifferentOp NEON_UMULL
constexpr NEON3DifferentOp NEON_SQDMLAL
constexpr DataProcessing2SourceOp ASRV_w
constexpr LoadStoreAcquireReleaseOp LDAXR_b
constexpr NEONLoadStoreSingleStructOp NEON_ST1_s
constexpr FPDataProcessing1SourceOp FMOV_d
constexpr NEON3DifferentOp NEON_USUBW2
constexpr NEON2RegMiscOp NEON_SQABS
constexpr NEON3DifferentOp NEON_USUBW
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD3_s_post
constexpr NEON2RegMiscOp NEON_UADALP
constexpr NEON3DifferentOp NEON_UADDW
constexpr NEON3SameOp NEON_FACGT
constexpr ConditionalSelectOp CSEL_w
constexpr NEONScalarShiftImmediateOp NEON_SRI_scalar
constexpr NEONShiftImmediateOp NEON_SHRN
constexpr AtomicMemoryOp SWP_w
constexpr NEONScalar2RegMiscOp NEON_FCVTXN_scalar
constexpr NEON3SameOp NEON_BIC
constexpr LoadStoreAcquireReleaseOp STLR_w
constexpr FPDataProcessing2SourceOp FADD_d
constexpr TestBranchOp TBNZ
constexpr NEONScalar3SameOp NEON_SQDMULH_scalar
constexpr unsigned kShiftAmountWRegMask
constexpr NEON3SameOp NEON_CMTST
constexpr NEON3SameOp NEON_FMAXNMP
constexpr FPCompareOp FCMP_s
constexpr DataProcessing1SourceOp CLS_x
constexpr NEON3DifferentOp NEON_RSUBHN
constexpr NEONAcrossLanesOp NEON_FMAXNMV
constexpr LoadStoreAcquireReleaseOp CASPL_w
constexpr NEONLoadStoreMultiStructOp NEON_LD1_4v
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST3_post
constexpr AtomicMemoryOp SWPL_x
constexpr FPIntegerConvertOp FCVTZS_xd
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST1_b_post
constexpr FPDataProcessing2SourceOp FMAXNM_d
constexpr NEON2RegMiscOp NEON_FABS
constexpr NEON2RegMiscOp NEON_FCVTPS
constexpr LoadStoreAcquireReleaseOp STLXR_w
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_ST4_post
constexpr ExceptionOp HLT
constexpr NEONScalarShiftImmediateOp NEON_UQSHL_imm_scalar
constexpr MoveWideImmediateOp MOVN_x
constexpr NEON3DifferentOp NEON_UMLAL
constexpr CompareBranchOp CBNZ_w
constexpr NEON2RegMiscOp NEON_SQXTUN
constexpr NEONLoadStoreSingleStructOp NEON_ST3_s
constexpr NEONByIndexedElementOp NEON_SQRDMULH_byelement
constexpr NEONScalar2RegMiscOp NEON_FCVTAS_scalar
constexpr NEON3SameOp NEON_MUL
constexpr NEON2RegMiscOp NEON_FCMGT_zero
constexpr NEONShiftImmediateOp NEON_SQSHL_imm
constexpr NEON3DifferentOp NEON_SSUBL2
constexpr NEONScalar3SameOp NEON_SRSHL_scalar
constexpr NEONByIndexedElementOp NEON_UMLAL_byelement
constexpr int kNumberOfVRegisters
constexpr NEONTableOp NEON_TBL_3v
constexpr FPDataProcessing1SourceOp FCVT_sd
constexpr NEON3SameOp NEON_BIT
constexpr NEON2RegMiscOp NEON_SHLL
constexpr NEON3SameOp NEON_SQSUB
constexpr FPIntegerConvertOp FCVTZS_ws
constexpr LoadStoreAcquireReleaseOp LDAR_b
constexpr NEON3DifferentOp NEON_SABDL
constexpr NEONScalar2RegMiscOp NEON_FCVTMU_scalar
constexpr NEON3DifferentOp NEON_SSUBW2
constexpr NEON3DifferentOp NEON_UMLAL2
constexpr NEONLoadStoreMultiStructOp NEON_ST4
constexpr NEON2RegMiscOp NEON_FCMLE_zero
constexpr NEON3DifferentOp NEON_PMULL
constexpr int kSPRegInternalCode
constexpr FPDataProcessing1SourceOp FRINTN_s
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD4R_post
constexpr FPDataProcessing1SourceOp FRINTP_d
constexpr NEON3SameOp NEON_SQRSHL
constexpr NEON2RegMiscOp NEON_CMGE_zero
constexpr NEONAcrossLanesOp NEON_FMINV
constexpr FPDataProcessing1SourceOp FRINTP_s
constexpr FPIntegerConvertOp SCVTF_dx
constexpr FPFixedPointConvertOp SCVTF_sw_fixed
constexpr LoadLiteralOp LDR_s_lit
constexpr NEON3SameOp NEON_FMLA
constexpr NEON3DifferentOp NEON_SUBHN
constexpr NEONShiftImmediateOp NEON_UQRSHRN
constexpr NEON3SameOp NEON_FMAXP
constexpr MoveWideImmediateOp MOVK_x
constexpr DataProcessing2SourceOp UDIV_w
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD1_b_post
constexpr NEONShiftImmediateOp NEON_FCVTZU_imm
constexpr NEONByIndexedElementOp NEON_FMUL_byelement
constexpr NEON2RegMiscOp NEON_FRINTP
constexpr NEON3SameOp NEON_MLS
constexpr NEONScalar3SameOp NEON_FABD_scalar
constexpr NEONByIndexedElementOp NEON_SQDMULL_byelement
constexpr NEONLoadStoreMultiStructOp NEON_ST1_2v
constexpr NEON3SameOp NEON_SABA
constexpr FPIntegerConvertOp FMOV_ws
constexpr NEON3DifferentOp NEON_RADDHN2
constexpr NEONLoadStoreSingleStructOp NEON_ST3_b
constexpr LoadStoreAcquireReleaseOp CASAB
constexpr NEON3DifferentOp NEON_USUBL2
constexpr NEONLoadStoreSingleStructOp NEON_ST2_b
constexpr MoveWideImmediateOp MOVN_w
constexpr LoadStoreAcquireReleaseOp CASL_w
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD2R_post
constexpr FPIntegerConvertOp FCVTNU_xs
constexpr NEON3DifferentOp NEON_SQDMLSL
constexpr NEONScalar3SameOp NEON_CMEQ_scalar
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST2_s_post
constexpr NEON3SameOp NEON_SRHADD
constexpr NEON3DifferentOp NEON_SMLSL
constexpr LoadLiteralOp LDR_x_lit
constexpr NEONLoadStoreSingleStructOp NEON_ST4_s
constexpr NEONScalar3SameOp NEON_SUB_scalar
constexpr NEON3DifferentOp NEON_RADDHN
constexpr NEONShiftImmediateOp NEON_SCVTF_imm
constexpr LoadStoreAcquireReleaseOp LDAXR_x
int LaneSizeInBytesFromFormat(VectorFormat vform)
constexpr NEON2RegMiscOp NEON_UQXTN
constexpr bool is_uintn(int64_t x, unsigned n)
constexpr NEONByIndexedElementOp NEON_MLA_byelement
constexpr NEONTableOp NEON_TBL_4v
constexpr NEONTableOp NEON_TBX_2v
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD1_d_post
constexpr NEON3DifferentOp NEON_UABAL2
constexpr DataProcessing2SourceOp RORV_x
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD1_2v_post
constexpr ConditionalSelectOp CSNEG_x
constexpr UnconditionalBranchToRegisterOp RET
constexpr NEONScalarByIndexedElementOp NEON_FMLA_byelement_scalar
void MemCopy(void *dest, const void *src, size_t size)
constexpr NEONScalarByIndexedElementOp NEON_SQDMULL_byelement_scalar
constexpr NEON3DifferentOp NEON_ADDHN2
constexpr NEON2RegMiscOp NEON_FRECPE
constexpr CompareBranchOp CBNZ_x
constexpr FPIntegerConvertOp UCVTF_dw
constexpr AtomicMemoryOp SWPAL_x
constexpr NEONScalar2RegMiscOp NEON_NEG_scalar
constexpr FPDataProcessing2SourceOp FMAX_s
constexpr NEONScalar3SameOp NEON_CMHS_scalar
constexpr LoadStoreAcquireReleaseOp CAS_w
constexpr NEON2RegMiscOp NEON_USQADD
constexpr int kNumberOfCalleeSavedRegisters
constexpr NEONShiftImmediateOp NEON_SHL
constexpr FPImmediateOp FMOV_s_imm
constexpr uint32_t kSlotsZapValue
constexpr NEONModifiedImmediateOp NEONModifiedImmediate_MVNI
constexpr NEONScalarShiftImmediateOp NEON_UQRSHRN_scalar
constexpr FPIntegerConvertOp FCVTZU_ws
constexpr AtomicMemoryOp SWPH
constexpr LoadStoreAcquireReleaseOp STLXR_h
constexpr NEONScalar3SameOp NEON_FMULX_scalar
constexpr NEONByIndexedElementOp NEON_MLS_byelement
constexpr NEONScalar2RegMiscOp NEON_FCMEQ_zero_scalar
constexpr FPDataProcessing1SourceOp FABS_s
constexpr int64_t kHalfWordMask
constexpr ConditionalSelectOp CSINV_w
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD1_4v_post
constexpr NEONScalar2RegMiscOp NEON_FCVTZU_scalar
constexpr NEON3SameOp NEON_UMINP
constexpr MoveWideImmediateOp MOVZ_w
constexpr NEONLoadStoreSingleStructOp NEON_LD4R
constexpr FPDataProcessing2SourceOp FSUB_s
constexpr DataProcessing3SourceOp UMSUBL_x
constexpr NEON2RegMiscOp NEON_FRINTN
constexpr NEON2RegMiscOp NEON_SCVTF
constexpr AtomicMemoryOp SWPLH
constexpr NEONPermOp NEON_UZP2
constexpr FPDataProcessing2SourceOp FMUL_d
constexpr NEONScalarByIndexedElementOp NEON_SQDMULH_byelement_scalar
T * NewArray(size_t size)
constexpr NEONShiftImmediateOp NEON_USHR
constexpr NEONLoadStoreMultiStructOp NEON_LD1_1v
constexpr DataProcessing2SourceOp RORV_w
constexpr NEONScalarShiftImmediateOp NEON_SRSHR_scalar
constexpr FPIntegerConvertOp SCVTF_sw
constexpr NEONModifiedImmediateOp NEONModifiedImmediate_MOVI
constexpr NEONScalarByIndexedElementOp NEON_FMLS_byelement_scalar
constexpr FPFixedPointConvertOp UCVTF_sx_fixed
constexpr NEONLoadStoreSingleStructOp NEON_LD3_b
constexpr NEON3DifferentOp NEON_USUBL
unsigned RegisterSizeInBytesFromFormat(VectorFormat vform)
constexpr FPFixedPointConvertOp UCVTF_sw_fixed
constexpr NEON3DifferentOp NEON_RSUBHN2
constexpr LoadStoreAcquireReleaseOp CASALB
constexpr NEON2RegMiscOp NEON_FSQRT
constexpr AtomicMemoryOp SWPAB
constexpr LoadStoreAcquireReleaseOp STLR_b
constexpr NEONScalar2RegMiscOp NEON_FCVTPS_scalar
constexpr AtomicMemoryOp SWPALH
constexpr NEON3DifferentOp NEON_SMULL
constexpr NEON3DifferentOp NEON_UADDW2
V8_WARN_UNUSED_RESULT bool IsValidHeapObject(Heap *heap, Tagged< HeapObject > object)
constexpr ConditionalSelectOp CSNEG_w
constexpr NEONByIndexedElementOp NEON_UMLSL_byelement
constexpr LoadStoreAcquireReleaseOp CASPAL_w
constexpr LoadStoreAcquireReleaseOp CASLB
constexpr FPIntegerConvertOp FMOV_sw
constexpr FPImmediateOp FMOV_d_imm
constexpr DataProcessing2SourceOp ASRV_x
constexpr FPIntegerConvertOp FMOV_xd
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST4_h_post
constexpr FPDataProcessing2SourceOp FDIV_s
constexpr NEONScalar2RegMiscOp NEON_SCVTF_scalar
constexpr FPDataProcessing1SourceOp FSQRT_s
constexpr FPDataProcessing1SourceOp FCVT_ds
constexpr NEON3SameOp NEON_EOR
constexpr FPDataProcessing2SourceOp FMINNM_s
constexpr FPDataProcessing1SourceOp FRINTI_d
constexpr NEONLoadStoreMultiStructOp NEON_ST1_1v
constexpr NEONLoadStoreSingleStructOp NEON_LD2R
constexpr PCRelAddressingOp ADR
constexpr FPIntegerConvertOp FCVTNS_ws
constexpr NEON2RegMiscOp NEON_FRINTX
constexpr NEON2RegMiscOp NEON_FCVTNS
constexpr NEONLoadStoreSingleStructOp NEON_LD2_b
constexpr NEONLoadStoreMultiStructPostIndexOp NEON_LD1_3v_post
constexpr NEON3SameOp NEON_FCMGT
constexpr FPDataProcessing1SourceOp FRINTZ_s
constexpr NEON3DifferentOp NEON_SMLAL
constexpr FPIntegerConvertOp FCVTAU_xs
const unsigned kDebugMessageOffset
constexpr FPIntegerConvertOp FCVTZU_wd
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_ST2_h_post
constexpr NEON2RegMiscOp NEON_SQXTN
constexpr NEONLoadStoreSingleStructPostIndexOp NEON_LD2_h_post
constexpr NEON2RegMiscOp NEON_FCVTPU
constexpr NEON2RegMiscOp NEON_CLZ
constexpr NEON2RegMiscOp NEON_FCVTNU
constexpr NEON3DifferentOp NEON_UMULL2
constexpr DataProcessing2SourceOp SDIV_x
constexpr LoadStoreAcquireReleaseOp CASL_x
constexpr NEONByIndexedElementOp NEON_SMULL_byelement
constexpr NEONScalar3SameOp NEON_CMGT_scalar
constexpr FPDataProcessing3SourceOp FMSUB_s
base::SmallVector< RegisterT, kStaticCapacity > registers_
const uintptr_t stack_limit_
#define V8_DEBUGGING_EXPORT
#define DCHECK_LE(v1, v2)
#define CHECK_LE(lhs, rhs)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
constexpr T RoundUp(T x, intptr_t m)
std::unique_ptr< ValueMirror > value