9#if defined(TARGET_ARCH_ARM64)
12#if defined(USING_SIMULATOR)
33 "Trace simulator execution after instruction count reached.");
37 "Instruction address or instruction count to stop simulator at.");
40 sim_allow_unaligned_accesses,
42 "Allow unaligned accesses to Normal memory.");
55class SimulatorSetjmpBuffer {
59 simulator_->set_last_setjmp_buffer(
this);
63 explicit SimulatorSetjmpBuffer(Simulator* sim) {
65 link_ = sim->last_setjmp_buffer();
66 sim->set_last_setjmp_buffer(
this);
70 ~SimulatorSetjmpBuffer() {
71 ASSERT(simulator_->last_setjmp_buffer() ==
this);
72 simulator_->set_last_setjmp_buffer(link_);
75 SimulatorSetjmpBuffer*
link() {
return link_; }
77 uword sp() {
return sp_; }
81 Simulator* simulator_;
82 SimulatorSetjmpBuffer* link_;
85 friend class Simulator;
90class SimulatorDebugger {
92 explicit SimulatorDebugger(Simulator* sim);
95 void Stop(Instr* instr,
const char*
message);
97 char* ReadLine(
const char* prompt);
103 bool GetSValue(
char*
desc, uint32_t*
value);
104 bool GetDValue(
char*
desc, uint64_t*
value);
105 bool GetQValue(
char*
desc, simd_value_t*
value);
107 static TokenPosition GetApproximateTokenIndex(
const Code&
code,
uword pc);
109 static void PrintDartFrame(
uword vm_instructions,
110 uword isolate_instructions,
115 TokenPosition token_pos,
118 void PrintBacktrace();
122 bool DeleteBreakpoint(Instr* breakpc);
126 void UndoBreakpoints();
127 void RedoBreakpoints();
130SimulatorDebugger::SimulatorDebugger(Simulator* sim) {
134SimulatorDebugger::~SimulatorDebugger() {}
136void SimulatorDebugger::Stop(Instr* instr,
const char*
message) {
141static Register LookupCpuRegisterByName(
const char*
name) {
142 static const char*
const kNames[] = {
143 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
144 "r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
145 "r16",
"r17",
"r18",
"r19",
"r20",
"r21",
"r22",
"r23",
146 "r24",
"r25",
"r26",
"r27",
"r28",
"r29",
"r30",
148 "ip0",
"ip1",
"pp",
"fp",
"lr",
"sp",
"zr",
150 static const Register kRegisters[] = {
151 R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
152 R11,
R12,
R13,
R14,
R15,
R16,
R17,
R18,
R19,
R20,
R21,
159 if (strcmp(kNames[
i],
name) == 0) {
160 return kRegisters[
i];
168 bool ok = SScanF(
name,
"v%d", ®_nr);
182 *
value = sim_->get_register(reg);
185 if (
desc[0] ==
'*') {
188 if (Simulator::IsIllegalAddress(
addr)) {
191 *
value = *(
reinterpret_cast<int64_t*
>(
addr));
195 if (strcmp(
"pc",
desc) == 0) {
196 *
value = sim_->get_pc();
206bool SimulatorDebugger::GetSValue(
char*
desc, uint32_t*
value) {
209 *
value = sim_->get_vregisters(vreg, 0);
212 if (
desc[0] ==
'*') {
215 if (Simulator::IsIllegalAddress(
addr)) {
218 *
value = *(
reinterpret_cast<uint32_t*
>(
addr));
225bool SimulatorDebugger::GetDValue(
char*
desc, uint64_t*
value) {
228 *
value = sim_->get_vregisterd(vreg, 0);
231 if (
desc[0] ==
'*') {
234 if (Simulator::IsIllegalAddress(
addr)) {
237 *
value = *(
reinterpret_cast<uint64_t*
>(
addr));
244bool SimulatorDebugger::GetQValue(
char*
desc, simd_value_t*
value) {
247 sim_->get_vregister(vreg,
value);
250 if (
desc[0] ==
'*') {
253 if (Simulator::IsIllegalAddress(
addr)) {
256 *
value = *(
reinterpret_cast<simd_value_t*
>(
addr));
263TokenPosition SimulatorDebugger::GetApproximateTokenIndex(
const Code&
code,
265 TokenPosition token_pos = TokenPosition::kNoSource;
266 uword pc_offset = pc -
code.PayloadStart();
267 const PcDescriptors& descriptors =
269 PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
270 while (iter.MoveNext()) {
271 if (iter.PcOffset() == pc_offset) {
272 return iter.TokenPos();
273 }
else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) {
274 token_pos = iter.TokenPos();
280#if defined(DART_PRECOMPILED_RUNTIME)
281static const char* ImageName(
uword vm_instructions,
282 uword isolate_instructions,
285 const Image vm_image(vm_instructions);
286 const Image isolate_image(isolate_instructions);
287 if (vm_image.contains(pc)) {
288 *
offset = pc - vm_instructions;
290 }
else if (isolate_image.contains(pc)) {
291 *
offset = pc - isolate_instructions;
300void SimulatorDebugger::PrintDartFrame(
uword vm_instructions,
301 uword isolate_instructions,
306 TokenPosition token_pos,
312 intptr_t
line, column;
313 if (
script.GetTokenLocation(token_pos, &
line, &column)) {
315 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
316 fp, sp, is_optimized ? (is_inlined ?
"inlined " :
"optimized ") :
"",
317 func_name.ToCString(), url.ToCString(),
line, column);
320 is_optimized ? (is_inlined ?
"inlined " :
"optimized ") :
"",
321 func_name.ToCString(), url.ToCString());
323#if defined(DART_PRECOMPILED_RUNTIME)
325 auto const symbol_name =
326 ImageName(vm_instructions, isolate_instructions, pc, &
offset);
332void SimulatorDebugger::PrintBacktrace() {
334 auto const Z =
T->zone();
335#if defined(DART_PRECOMPILED_RUNTIME)
336 auto const vm_instructions =
reinterpret_cast<uword>(
338 auto const isolate_instructions =
reinterpret_cast<uword>(
339 T->isolate_group()->source()->snapshot_instructions);
341 vm_instructions, isolate_instructions);
343 const uword vm_instructions = 0;
344 const uword isolate_instructions = 0;
346 StackFrameIterator frames(sim_->get_register(
FP), sim_->get_register(
SP),
350 StackFrame*
frame = frames.NextFrame();
356 while (
frame !=
nullptr) {
357 if (
frame->IsDartFrame()) {
360 if (
code.is_optimized()) {
363 InlinedFunctionsIterator it(
code,
frame->pc());
367 inlined_function = it.function();
368 unoptimized_code = it.code();
369 uword unoptimized_pc = it.pc();
373 vm_instructions, isolate_instructions, unoptimized_pc,
375 GetApproximateTokenIndex(unoptimized_code, unoptimized_pc),
381 PrintDartFrame(vm_instructions, isolate_instructions,
frame->pc(),
383 GetApproximateTokenIndex(
code,
frame->pc()),
384 code.is_optimized(),
false);
388 frame->IsEntryFrame() ?
"entry"
389 :
frame->IsExitFrame() ?
"exit"
390 :
frame->IsStubFrame() ?
"stub"
392#if defined(DART_PRECOMPILED_RUNTIME)
394 auto const symbol_name = ImageName(vm_instructions, isolate_instructions,
400 frame = frames.NextFrame();
406 if (sim_->break_pc_ !=
nullptr) {
411 sim_->break_pc_ = breakpc;
412 sim_->break_instr_ = breakpc->InstructionBits();
418bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) {
419 if (sim_->break_pc_ !=
nullptr) {
420 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
423 sim_->break_pc_ =
nullptr;
424 sim_->break_instr_ = 0;
428void SimulatorDebugger::UndoBreakpoints() {
429 if (sim_->break_pc_ !=
nullptr) {
430 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
434void SimulatorDebugger::RedoBreakpoints() {
435 if (sim_->break_pc_ !=
nullptr) {
440void SimulatorDebugger::Debug() {
441 uintptr_t last_pc = -1;
444#define COMMAND_SIZE 63
448#define XSTR(a) STR(a)
450 char cmd[COMMAND_SIZE + 1];
451 char arg1[ARG_SIZE + 1];
452 char arg2[ARG_SIZE + 1];
455 cmd[COMMAND_SIZE] = 0;
464 if (last_pc != sim_->get_pc()) {
465 last_pc = sim_->get_pc();
466 if (Simulator::IsIllegalAddress(last_pc)) {
469 if (FLAG_support_disassembler) {
472 OS::PrintErr(
"Disassembler not supported in this mode.\n");
476 char*
line = ReadLine(
"sim> ");
477 if (
line ==
nullptr) {
478 FATAL(
"ReadLine failed");
483 "%" XSTR(COMMAND_SIZE)
"s "
484 "%" XSTR(ARG_SIZE)
"s "
485 "%" XSTR(ARG_SIZE)
"s",
487 if ((strcmp(
cmd,
"h") == 0) || (strcmp(
cmd,
"help") == 0)) {
489 "c/cont -- continue execution\n"
490 "disasm -- disassemble instrs at current pc location\n"
491 " other variants are:\n"
492 " disasm <address>\n"
493 " disasm <address> <number_of_instructions>\n"
494 " by default 10 instrs are disassembled\n"
495 "del -- delete breakpoints\n"
496 "flags -- print flag values\n"
497 "gdb -- transfer control to gdb\n"
498 "h/help -- print this help string\n"
499 "break <address> -- set break point at specified address\n"
500 "p/print <reg or icount or value or *addr> -- print integer\n"
501 "pf/printfloat <vreg or *addr> --print float value\n"
502 "pd/printdouble <vreg or *addr> -- print double value\n"
503 "pq/printquad <vreg or *addr> -- print vector register\n"
504 "po/printobject <*reg or *addr> -- print object\n"
505 "si/stepi -- single step an instruction\n"
506 "trace -- toggle execution tracing mode\n"
507 "bt -- print backtrace\n"
508 "unstop -- if current pc is a stop instr make it a nop\n"
509 "q/quit -- Quit the debugger and exit the program\n");
510 }
else if ((strcmp(
cmd,
"quit") == 0) || (strcmp(
cmd,
"q") == 0)) {
513 }
else if ((strcmp(
cmd,
"si") == 0) || (strcmp(
cmd,
"stepi") == 0)) {
514 sim_->InstructionDecode(
reinterpret_cast<Instr*
>(sim_->get_pc()));
515 }
else if ((strcmp(
cmd,
"c") == 0) || (strcmp(
cmd,
"cont") == 0)) {
517 sim_->InstructionDecode(
reinterpret_cast<Instr*
>(sim_->get_pc()));
520 }
else if ((strcmp(
cmd,
"p") == 0) || (strcmp(
cmd,
"print") == 0)) {
523 if (strcmp(arg1,
"icount") == 0) {
524 value = sim_->get_icount();
532 OS::PrintErr(
"print <reg or icount or value or *addr>\n");
534 }
else if ((strcmp(
cmd,
"pf") == 0) || (strcmp(
cmd,
"printfloat") == 0)) {
537 if (GetSValue(arg1, &
value)) {
538 float svalue = bit_cast<float, uint32_t>(
value);
546 }
else if ((strcmp(
cmd,
"pd") == 0) ||
547 (strcmp(
cmd,
"printdouble") == 0)) {
550 if (GetDValue(arg1, &long_value)) {
551 double dvalue = bit_cast<double, uint64_t>(long_value);
560 }
else if ((strcmp(
cmd,
"pq") == 0) || (strcmp(
cmd,
"printquad") == 0)) {
562 simd_value_t quad_value;
563 if (GetQValue(arg1, &quad_value)) {
564 const int64_t d0 = quad_value.bits.i64[0];
565 const int64_t d1 = quad_value.bits.i64[1];
566 const double dval0 = bit_cast<double, int64_t>(d0);
567 const double dval1 = bit_cast<double, int64_t>(d1);
568 const int32_t s0 = quad_value.bits.i32[0];
569 const int32_t s1 = quad_value.bits.i32[1];
570 const int32_t s2 = quad_value.bits.i32[2];
571 const int32_t s3 = quad_value.bits.i32[3];
572 const float sval0 = bit_cast<float, int32_t>(s0);
573 const float sval1 = bit_cast<float, int32_t>(s1);
574 const float sval2 = bit_cast<float, int32_t>(s2);
575 const float sval3 = bit_cast<float, int32_t>(s3);
580 OS::PrintErr(
"%s: %d 0x%x %.8g\n", arg1, s0, s0, sval0);
581 OS::PrintErr(
"%s: %d 0x%x %.8g\n", arg1, s1, s1, sval1);
582 OS::PrintErr(
"%s: %d 0x%x %.8g\n", arg1, s2, s2, sval2);
583 OS::PrintErr(
"%s: %d 0x%x %.8g\n", arg1, s3, s3, sval3);
590 }
else if ((strcmp(
cmd,
"po") == 0) ||
591 (strcmp(
cmd,
"printobject") == 0)) {
601 static_cast<ObjectPtr
>(
static_cast<uword>(
value)));
613 }
else if (strcmp(
cmd,
"disasm") == 0) {
617 start = sim_->get_pc();
619 }
else if (
args == 2) {
622 if (Simulator::IsIllegalAddress(start)) {
628 start = sim_->get_pc();
635 if (Simulator::IsIllegalAddress(start)) {
641 start = sim_->get_pc();
647 if (FLAG_support_disassembler) {
650 OS::PrintErr(
"Disassembler not supported in this mode.\n");
653 OS::PrintErr(
"disasm [<address> [<number_of_instructions>]]\n");
655 }
else if (strcmp(
cmd,
"gdb") == 0) {
659 }
else if (strcmp(
cmd,
"break") == 0) {
672 }
else if (strcmp(
cmd,
"del") == 0) {
673 if (!DeleteBreakpoint(
nullptr)) {
676 }
else if (strcmp(
cmd,
"flags") == 0) {
678 OS::PrintErr(
"N flag: %d; ",
static_cast<int>(sim_->n_flag_));
679 OS::PrintErr(
"Z flag: %d; ",
static_cast<int>(sim_->z_flag_));
680 OS::PrintErr(
"C flag: %d; ",
static_cast<int>(sim_->c_flag_));
681 OS::PrintErr(
"V flag: %d\n",
static_cast<int>(sim_->v_flag_));
682 }
else if (strcmp(
cmd,
"unstop") == 0) {
684 Instr* stop_instr =
reinterpret_cast<Instr*
>(stop_pc);
685 if (stop_instr->IsExceptionGenOp()) {
690 }
else if (strcmp(
cmd,
"trace") == 0) {
691 if (FLAG_trace_sim_after == ULLONG_MAX) {
692 FLAG_trace_sim_after = sim_->get_icount();
695 FLAG_trace_sim_after = ULLONG_MAX;
698 }
else if (strcmp(
cmd,
"bt") == 0) {
699 Thread* thread =
reinterpret_cast<Thread*
>(sim_->get_register(
THR));
721char* SimulatorDebugger::ReadLine(
const char* prompt) {
725 bool keep_going =
true;
728 if (fgets(line_buf,
sizeof(line_buf), stdin) ==
nullptr) {
735 intptr_t
len = strlen(line_buf);
736 if (
len > 1 && line_buf[
len - 2] ==
'\\' && line_buf[
len - 1] ==
'\n') {
739 line_buf[
len - 2] =
'\n';
740 line_buf[
len - 1] = 0;
742 }
else if ((
len > 0) && (line_buf[
len - 1] ==
'\n')) {
757 char* new_result =
new char[new_len];
758 if (new_result ==
nullptr) {
789 new char[(OSThread::GetSpecifiedStackSize() +
790 OSThread::kStackSizeBufferMax + kSimulatorStackUnderflowSize)];
792 stack_limit_ =
reinterpret_cast<uword>(stack_);
794 overflow_stack_limit_ = stack_limit_ + OSThread::kStackSizeBufferMax;
796 stack_base_ = overflow_stack_limit_ + OSThread::GetSpecifiedStackSize();
798 pc_modified_ =
false;
802 last_setjmp_buffer_ =
nullptr;
815 vregisters_[
i].bits.i64[0] = 0;
816 vregisters_[
i].bits.i64[1] = 0;
821 registers_[
R31] = stack_base();
824 registers_[
LR] = kBadLR;
828Simulator::~Simulator() {
830 Isolate* isolate = Isolate::Current();
831 if (isolate !=
nullptr) {
832 isolate->set_simulator(
nullptr);
845 uword address_of_hlt_instruction() {
846 return reinterpret_cast<uword>(&hlt_instruction_);
849 uword external_function()
const {
return external_function_; }
851 Simulator::CallKind call_kind()
const {
return call_kind_; }
855 static Redirection*
Get(
uword external_function,
856 Simulator::CallKind call_kind,
858 MutexLocker ml(mutex_);
860 Redirection* old_head = list_.load(std::memory_order_relaxed);
861 for (Redirection* current = old_head; current !=
nullptr;
862 current = current->next_) {
863 if (current->external_function_ == external_function)
return current;
866 Redirection* redirection =
868 redirection->next_ = old_head;
873 list_.store(redirection, std::memory_order_release);
878 static Redirection* FromHltInstruction(Instr* hlt_instruction) {
879 char* addr_of_hlt =
reinterpret_cast<char*
>(hlt_instruction);
880 char* addr_of_redirection =
881 addr_of_hlt -
OFFSET_OF(Redirection, hlt_instruction_);
882 return reinterpret_cast<Redirection*
>(addr_of_redirection);
889 static uword FunctionForRedirect(
uword address_of_hlt) {
890 for (Redirection* current = list_.load(std::memory_order_acquire);
891 current !=
nullptr; current = current->next_) {
892 if (current->address_of_hlt_instruction() == address_of_hlt) {
893 return current->external_function_;
900 Redirection(
uword external_function,
901 Simulator::CallKind call_kind,
903 : external_function_(external_function),
904 call_kind_(call_kind),
906 hlt_instruction_(Instr::kSimulatorRedirectInstruction),
909 uword external_function_;
910 Simulator::CallKind call_kind_;
912 uint32_t hlt_instruction_;
914 static std::atomic<Redirection*> list_;
915 static Mutex* mutex_;
918std::atomic<Redirection*> Redirection::list_ = {
nullptr};
919Mutex* Redirection::mutex_ =
new Mutex();
924 Redirection* redirection =
926 return redirection->address_of_hlt_instruction();
929uword Simulator::FunctionForRedirect(
uword redirect) {
930 return Redirection::FunctionForRedirect(redirect);
934Simulator* Simulator::Current() {
935 Isolate* isolate = Isolate::Current();
936 Simulator* simulator = isolate->simulator();
937 if (simulator ==
nullptr) {
938 NoSafepointScope no_safepoint;
939 simulator =
new Simulator();
940 isolate->set_simulator(simulator);
946void Simulator::set_register(Instr* instr,
952#if !defined(DART_TARGET_OS_FUCHSIA)
957 registers_[reg] =
value;
965 if ((instr !=
nullptr) && (reg ==
R31) && !Utils::IsAligned(
value, 16)) {
966 UnalignedAccess(
"CSP set",
value, instr);
975 WriteX(csp - 1 *
kWordSize, icount_,
nullptr);
976 WriteX(csp - 2 *
kWordSize, icount_,
nullptr);
977 WriteX(csp - 3 *
kWordSize, icount_,
nullptr);
978 WriteX(csp - 4 *
kWordSize, icount_,
nullptr);
990 return registers_[reg];
998 registers_[reg] = Utils::LowHighTo64Bits(
static_cast<uint32_t
>(
value), 0);
1008 return static_cast<int32_t
>(registers_[reg]);
1012int32_t Simulator::get_vregisters(
VRegister reg,
int idx)
const {
1014 ASSERT((idx >= 0) && (idx <= 3));
1015 return vregisters_[reg].bits.i32[idx];
1018void Simulator::set_vregisters(
VRegister reg,
int idx, int32_t
value) {
1020 ASSERT((idx >= 0) && (idx <= 3));
1021 vregisters_[reg].bits.i32[idx] =
value;
1024int64_t Simulator::get_vregisterd(
VRegister reg,
int idx)
const {
1026 ASSERT((idx == 0) || (idx == 1));
1027 return vregisters_[reg].bits.i64[idx];
1030void Simulator::set_vregisterd(
VRegister reg,
int idx, int64_t
value) {
1032 ASSERT((idx == 0) || (idx == 1));
1033 vregisters_[reg].bits.i64[idx] =
value;
1036void Simulator::get_vregister(
VRegister reg, simd_value_t*
value)
const {
1038 value->bits.i64[0] = vregisters_[reg].bits.i64[0];
1039 value->bits.i64[1] = vregisters_[reg].bits.i64[1];
1042void Simulator::set_vregister(
VRegister reg,
const simd_value_t&
value) {
1044 vregisters_[reg].bits.i64[0] =
value.bits.i64[0];
1045 vregisters_[reg].bits.i64[1] =
value.bits.i64[1];
1049void Simulator::set_pc(uint64_t
value) {
1050 pc_modified_ =
true;
1056uint64_t Simulator::get_pc()
const {
1060uint64_t Simulator::get_last_pc()
const {
1064void Simulator::HandleIllegalAccess(
uword addr, Instr* instr) {
1065 uword fault_pc = get_pc();
1066 uword last_pc = get_last_pc();
1069 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px
1071 addr, fault_pc, last_pc);
1072 SimulatorDebugger dbg(
this);
1075 FATAL(
"Cannot continue execution after illegal memory access.");
1082void Simulator::UnalignedAccess(
const char* msg,
uword addr, Instr* instr) {
1084 snprintf(
buffer,
sizeof(
buffer),
"unaligned %s at 0x%" Px ", pc=%p\n", msg,
1086 SimulatorDebugger dbg(
this);
1090 FATAL(
"Cannot continue execution after unaligned access.");
1093void Simulator::UnimplementedInstruction(Instr* instr) {
1096 "Unimplemented instruction: at %p, last_pc=0x%" Px64 "\n", instr,
1098 SimulatorDebugger dbg(
this);
1100 FATAL(
"Cannot continue execution after unimplemented instruction.");
1103bool Simulator::IsTracingExecution()
const {
1104 return icount_ > FLAG_trace_sim_after;
1109 bool must_be_aligned ) {
1110 const bool allow_unaligned_access =
1111 FLAG_sim_allow_unaligned_accesses && !must_be_aligned;
1112 if (allow_unaligned_access || (
addr & 7) == 0) {
1115 UnalignedAccess(
"read",
addr, instr);
1119void Simulator::WriteX(
uword addr, intptr_t
value, Instr* instr) {
1120 if (FLAG_sim_allow_unaligned_accesses || (
addr & 7) == 0) {
1124 UnalignedAccess(
"write",
addr, instr);
1129 bool must_be_aligned ) {
1130 const bool allow_unaligned_access =
1131 FLAG_sim_allow_unaligned_accesses && !must_be_aligned;
1132 if (allow_unaligned_access || (
addr & 3) == 0) {
1135 UnalignedAccess(
"read unsigned single word",
addr, instr);
1139int32_t Simulator::ReadW(
uword addr, Instr* instr) {
1140 if (FLAG_sim_allow_unaligned_accesses || (
addr & 3) == 0) {
1143 UnalignedAccess(
"read single word",
addr, instr);
1147void Simulator::WriteW(
uword addr, uint32_t
value, Instr* instr) {
1148 if (FLAG_sim_allow_unaligned_accesses || (
addr & 3) == 0) {
1152 UnalignedAccess(
"write single word",
addr, instr);
1155uint16_t Simulator::ReadHU(
uword addr, Instr* instr) {
1156 if (FLAG_sim_allow_unaligned_accesses || (
addr & 1) == 0) {
1159 UnalignedAccess(
"unsigned halfword read",
addr, instr);
1163int16_t Simulator::ReadH(
uword addr, Instr* instr) {
1164 if (FLAG_sim_allow_unaligned_accesses || (
addr & 1) == 0) {
1167 UnalignedAccess(
"signed halfword read",
addr, instr);
1171void Simulator::WriteH(
uword addr, uint16_t
value, Instr* instr) {
1172 if (FLAG_sim_allow_unaligned_accesses || (
addr & 1) == 0) {
1176 UnalignedAccess(
"halfword write",
addr, instr);
1180 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(
addr);
1185 int8_t* ptr =
reinterpret_cast<int8_t*
>(
addr);
1190 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(
addr);
1194void Simulator::ClearExclusive() {
1195 exclusive_access_addr_ = 0;
1196 exclusive_access_value_ = 0;
1199intptr_t Simulator::ReadExclusiveX(
uword addr, Instr* instr) {
1200 exclusive_access_addr_ =
addr;
1201 exclusive_access_value_ = ReadX(
addr, instr,
true);
1202 return exclusive_access_value_;
1205intptr_t Simulator::ReadExclusiveW(
uword addr, Instr* instr) {
1206 exclusive_access_addr_ =
addr;
1207 exclusive_access_value_ = ReadWU(
addr, instr,
true);
1208 return exclusive_access_value_;
1211intptr_t Simulator::WriteExclusiveX(
uword addr, intptr_t
value, Instr* instr) {
1214 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ ==
addr));
1215 if (exclusive_access_addr_ !=
addr) {
1219 int64_t old_value = exclusive_access_value_;
1222 if ((random_.NextUInt32() % 16) == 0) {
1226 auto atomic_addr =
reinterpret_cast<RelaxedAtomic<int64_t>*
>(
addr);
1227 if (atomic_addr->compare_exchange_weak(old_value,
value)) {
1233intptr_t Simulator::WriteExclusiveW(
uword addr, intptr_t
value, Instr* instr) {
1236 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ ==
addr));
1237 if (exclusive_access_addr_ !=
addr) {
1241 int32_t old_value =
static_cast<uint32_t
>(exclusive_access_value_);
1244 if ((random_.NextUInt32() % 16) == 0) {
1248 auto atomic_addr =
reinterpret_cast<RelaxedAtomic<int32_t>*
>(
addr);
1249 if (atomic_addr->compare_exchange_weak(old_value,
value)) {
1255intptr_t Simulator::ReadAcquire(
uword addr, Instr* instr) {
1259 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1260 return reinterpret_cast<std::atomic<intptr_t>*
>(
addr)->
load(
1261 std::memory_order_acquire);
1264uint32_t Simulator::ReadAcquireW(
uword addr, Instr* instr) {
1268 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1269 return reinterpret_cast<std::atomic<uint32_t>*
>(
addr)->
load(
1270 std::memory_order_acquire);
1273void Simulator::WriteRelease(
uword addr, intptr_t
value, Instr* instr) {
1277 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1278 reinterpret_cast<std::atomic<intptr_t>*
>(
addr)->
store(
1279 value, std::memory_order_release);
1282void Simulator::WriteReleaseW(
uword addr, uint32_t
value, Instr* instr) {
1286 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1287 reinterpret_cast<std::atomic<uint32_t>*
>(
addr)->
store(
1288 value, std::memory_order_release);
1293 OS::PrintErr(
"Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
1299void Simulator::SetNZFlagsW(int32_t val) {
1300 n_flag_ = (val < 0);
1301 z_flag_ = (val == 0);
1305bool Simulator::CarryFromW(int32_t
left, int32_t
right, int32_t carry) {
1306 uint64_t uleft =
static_cast<uint32_t
>(
left);
1307 uint64_t uright =
static_cast<uint32_t
>(
right);
1308 uint64_t ucarry =
static_cast<uint32_t
>(carry);
1309 return ((uleft + uright + ucarry) >> 32) != 0;
1313bool Simulator::OverflowFromW(int32_t
left, int32_t
right, int32_t carry) {
1319void Simulator::SetNZFlagsX(int64_t val) {
1320 n_flag_ = (val < 0);
1321 z_flag_ = (val == 0);
1325bool Simulator::CarryFromX(int64_t alu_out,
1337bool Simulator::OverflowFromX(int64_t alu_out,
1342 return (((alu_out ^
left) & (alu_out ^
right)) >> 63) != 0;
1349void Simulator::SetCFlag(
bool val) {
1354void Simulator::SetVFlag(
bool val) {
1358void Simulator::DecodeMoveWide(Instr* instr) {
1359 const Register rd = instr->RdField();
1360 const int hw = instr->HWField();
1361 const int64_t shift = hw << 4;
1362 const int64_t shifted_imm =
static_cast<int64_t
>(instr->Imm16Field())
1365 if (instr->SFField() != 0) {
1366 if (instr->Bits(29, 2) == 0) {
1368 set_register(instr, rd, ~shifted_imm, instr->RdMode());
1369 }
else if (instr->Bits(29, 2) == 2) {
1371 set_register(instr, rd, shifted_imm, instr->RdMode());
1372 }
else if (instr->Bits(29, 2) == 3) {
1374 const int64_t rd_val = get_register(rd, instr->RdMode());
1375 const int64_t
result = (rd_val & ~(0xffffL << shift)) | shifted_imm;
1376 set_register(instr, rd,
result, instr->RdMode());
1378 UnimplementedInstruction(instr);
1380 }
else if ((hw & 0x2) == 0) {
1381 if (instr->Bits(29, 2) == 0) {
1383 set_wregister(rd, ~shifted_imm &
kWRegMask, instr->RdMode());
1384 }
else if (instr->Bits(29, 2) == 2) {
1386 set_wregister(rd, shifted_imm &
kWRegMask, instr->RdMode());
1387 }
else if (instr->Bits(29, 2) == 3) {
1389 const int32_t rd_val = get_wregister(rd, instr->RdMode());
1390 const int32_t
result = (rd_val & ~(0xffffL << shift)) | shifted_imm;
1391 set_wregister(rd,
result, instr->RdMode());
1393 UnimplementedInstruction(instr);
1397 UnimplementedInstruction(instr);
1401void Simulator::DecodeAddSubImm(Instr* instr) {
1402 const bool addition = (instr->Bit(30) == 0);
1405 const Register rd = instr->RdField();
1406 const Register rn = instr->RnField();
1407 uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12)
1408 : (instr->Imm12Field());
1409 if (instr->SFField() != 0) {
1411 const uint64_t rn_val = get_register(rn, instr->RnMode());
1412 const uint64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm);
1413 set_register(instr, rd, alu_out, instr->RdMode());
1414 if (instr->HasS()) {
1415 SetNZFlagsX(alu_out);
1416 SetCFlag(CarryFromX(alu_out, rn_val, imm, addition));
1417 SetVFlag(OverflowFromX(alu_out, rn_val, imm, addition));
1421 const uint32_t rn_val = get_wregister(rn, instr->RnMode());
1422 uint32_t carry_in = 0;
1427 const uint32_t alu_out = rn_val + imm + carry_in;
1428 set_wregister(rd, alu_out, instr->RdMode());
1429 if (instr->HasS()) {
1430 SetNZFlagsW(alu_out);
1431 SetCFlag(CarryFromW(rn_val, imm, carry_in));
1432 SetVFlag(OverflowFromW(rn_val, imm, carry_in));
1437void Simulator::DecodeBitfield(Instr* instr) {
1438 int bitwidth = instr->SFField() == 0 ? 32 : 64;
1439 unsigned op = instr->Bits(29, 2);
1442 bool zero_extend = op == 2;
1443 ASSERT(instr->NField() == instr->SFField());
1444 const Register rn = instr->RnField();
1445 const Register rd = instr->RdField();
1446 int64_t
result = get_register(rn, instr->RnMode());
1447 int r_bit = instr->ImmRField();
1448 int s_bit = instr->ImmSField();
1449 result &= Utils::NBitMask(bitwidth);
1450 ASSERT(s_bit < bitwidth && r_bit < bitwidth);
1454 uword mask = Utils::NBitMask(s_bit + 1);
1455 if (s_bit >= r_bit) {
1459 result =
static_cast<uint64_t
>(
result) << (bitwidth - r_bit);
1460 mask <<= bitwidth - r_bit;
1464 int highest_bit = (s_bit - r_bit) & (bitwidth - 1);
1465 int shift = 64 - highest_bit - 1;
1468 }
else if (!zero_extend) {
1469 const int64_t rd_val = get_register(rd, instr->RnMode());
1470 result |= rd_val & ~mask;
1472 if (bitwidth == 64) {
1473 set_register(instr, rd,
result, instr->RdMode());
1475 set_wregister(rd,
result, instr->RdMode());
1479void Simulator::DecodeLogicalImm(Instr* instr) {
1480 const int op = instr->Bits(29, 2);
1481 const bool set_flags = op == 3;
1482 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0))
1485 const Register rn = instr->RnField();
1486 const Register rd = instr->RdField();
1487 const int64_t rn_val = get_register(rn, instr->RnMode());
1488 const uint64_t imm = instr->ImmLogical();
1490 UnimplementedInstruction(instr);
1493 int64_t alu_out = 0;
1496 alu_out = rn_val & imm;
1499 alu_out = rn_val | imm;
1502 alu_out = rn_val ^ imm;
1505 alu_out = rn_val & imm;
1514 SetNZFlagsX(alu_out);
1516 SetNZFlagsW(alu_out);
1523 set_register(instr, rd, alu_out, instr->RdMode());
1525 set_wregister(rd, alu_out, instr->RdMode());
1529void Simulator::DecodePCRel(Instr* instr) {
1530 const int op = instr->Bit(31);
1533 const Register rd = instr->RdField();
1534 const uint64_t immhi = instr->SImm19Field();
1535 const uint64_t immlo = instr->Bits(29, 2);
1536 const uint64_t off = (immhi << 2) | immlo;
1537 const uint64_t
dest = get_pc() + off;
1538 set_register(instr, rd,
dest, instr->RdMode());
1540 UnimplementedInstruction(instr);
1544void Simulator::DecodeDPImmediate(Instr* instr) {
1545 if (instr->IsMoveWideOp()) {
1546 DecodeMoveWide(instr);
1547 }
else if (instr->IsAddSubImmOp()) {
1548 DecodeAddSubImm(instr);
1549 }
else if (instr->IsBitfieldOp()) {
1550 DecodeBitfield(instr);
1551 }
else if (instr->IsLogicalImmOp()) {
1552 DecodeLogicalImm(instr);
1553 }
else if (instr->IsPCRelOp()) {
1556 UnimplementedInstruction(instr);
1560void Simulator::DecodeCompareAndBranch(Instr* instr) {
1561 const int op = instr->Bit(24);
1562 const Register rt = instr->RtField();
1563 const uint64_t imm19 = instr->SImm19Field();
1564 const uint64_t
dest = get_pc() + (imm19 << 2);
1566 const uint64_t rt_val = get_register(rt,
R31IsZR) & mask;
1580bool Simulator::ConditionallyExecute(Instr* instr) {
1582 if (instr->IsConditionalSelectOp()) {
1583 cond = instr->SelectConditionField();
1585 cond = instr->ConditionField();
1605 return c_flag_ && !z_flag_;
1607 return !c_flag_ || z_flag_;
1609 return n_flag_ == v_flag_;
1611 return n_flag_ != v_flag_;
1613 return !z_flag_ && (n_flag_ == v_flag_);
1615 return z_flag_ || (n_flag_ != v_flag_);
1624void Simulator::DecodeConditionalBranch(Instr* instr) {
1626 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) {
1627 UnimplementedInstruction(instr);
1629 const uint64_t imm19 = instr->SImm19Field();
1630 const uint64_t
dest = get_pc() + (imm19 << 2);
1631 if (ConditionallyExecute(instr)) {
1637typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
1640typedef int64_t (*SimulatorLeafRuntimeCall)(int64_t r0,
1654static int64_t InvokeLeafRuntime(SimulatorLeafRuntimeCall
target,
1663 return target(r0, r1, r2, r3, r4, r5, r6, r7);
1667typedef double (*SimulatorLeafFloatRuntimeCall)(
double d0,
1681static
double InvokeFloatLeafRuntime(SimulatorLeafFloatRuntimeCall
target,
1690 return target(d0, d1, d2, d3, d4, d5, d6, d7);
1697void Simulator::DoRedirectedCall(Instr* instr) {
1698 SimulatorSetjmpBuffer
buffer(
this);
1699 if (!setjmp(
buffer.buffer_)) {
1700 int64_t saved_lr = get_register(
LR);
1701 Redirection* redirection = Redirection::FromHltInstruction(instr);
1702 uword external = redirection->external_function();
1703 if (IsTracingExecution()) {
1704 THR_Print(
"Call to host function at 0x%" Pd "\n", external);
1707 if (redirection->call_kind() == kRuntimeCall) {
1708 NativeArguments* arguments =
1709 reinterpret_cast<NativeArguments*
>(get_register(
R0));
1710 SimulatorRuntimeCall
target =
1711 reinterpret_cast<SimulatorRuntimeCall
>(external);
1713 ClobberVolatileRegisters();
1714 }
else if (redirection->call_kind() == kLeafRuntimeCall) {
1715 ASSERT((0 <= redirection->argument_count()) &&
1716 (redirection->argument_count() <= 8));
1717 SimulatorLeafRuntimeCall
target =
1718 reinterpret_cast<SimulatorLeafRuntimeCall
>(external);
1719 const int64_t r0 = get_register(
R0);
1720 const int64_t r1 = get_register(
R1);
1721 const int64_t r2 = get_register(
R2);
1722 const int64_t r3 = get_register(
R3);
1723 const int64_t r4 = get_register(
R4);
1724 const int64_t r5 = get_register(
R5);
1725 const int64_t r6 = get_register(
R6);
1726 const int64_t r7 = get_register(
R7);
1728 InvokeLeafRuntime(
target, r0, r1, r2, r3, r4, r5, r6, r7);
1729 ClobberVolatileRegisters();
1730 set_register(instr,
R0, res);
1731 }
else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
1732 ASSERT((0 <= redirection->argument_count()) &&
1733 (redirection->argument_count() <= 8));
1734 SimulatorLeafFloatRuntimeCall
target =
1735 reinterpret_cast<SimulatorLeafFloatRuntimeCall
>(external);
1736 const double d0 = bit_cast<double, int64_t>(get_vregisterd(
V0, 0));
1737 const double d1 = bit_cast<double, int64_t>(get_vregisterd(
V1, 0));
1738 const double d2 = bit_cast<double, int64_t>(get_vregisterd(
V2, 0));
1739 const double d3 = bit_cast<double, int64_t>(get_vregisterd(
V3, 0));
1740 const double d4 = bit_cast<double, int64_t>(get_vregisterd(
V4, 0));
1741 const double d5 = bit_cast<double, int64_t>(get_vregisterd(
V5, 0));
1742 const double d6 = bit_cast<double, int64_t>(get_vregisterd(
V6, 0));
1743 const double d7 = bit_cast<double, int64_t>(get_vregisterd(
V7, 0));
1745 InvokeFloatLeafRuntime(
target, d0, d1, d2, d3, d4, d5, d6, d7);
1746 ClobberVolatileRegisters();
1747 set_vregisterd(
V0, 0, bit_cast<int64_t, double>(res));
1748 set_vregisterd(
V0, 1, 0);
1750 ASSERT(redirection->call_kind() == kNativeCallWrapper);
1751 SimulatorNativeCallWrapper wrapper =
1752 reinterpret_cast<SimulatorNativeCallWrapper
>(external);
1757 wrapper(arguments,
target);
1758 ClobberVolatileRegisters();
1768void Simulator::ClobberVolatileRegisters() {
1770 exclusive_access_addr_ = exclusive_access_value_ = 0;
1774 registers_[
i] = random_.NextUInt64();
1780 vregisters_[
i].bits.i64[0] = icount_;
1781 vregisters_[
i].bits.i64[1] = icount_;
1786void Simulator::DecodeExceptionGen(Instr* instr) {
1787 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
1788 (instr->Bits(21, 3) == 0)) {
1790 UnimplementedInstruction(instr);
1791 }
else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
1792 (instr->Bits(21, 3) == 1)) {
1794 SimulatorDebugger dbg(
this);
1795 int32_t imm = instr->Imm16Field();
1798 set_pc(get_pc() + Instr::kInstrSize);
1800 }
else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
1801 (instr->Bits(21, 3) == 2)) {
1803 uint16_t imm =
static_cast<uint16_t
>(instr->Imm16Field());
1804 if (imm == Instr::kSimulatorBreakCode) {
1805 SimulatorDebugger dbg(
this);
1806 dbg.Stop(instr,
"breakpoint");
1807 }
else if (imm == Instr::kSimulatorRedirectCode) {
1808 DoRedirectedCall(instr);
1810 UnimplementedInstruction(instr);
1813 UnimplementedInstruction(instr);
1817void Simulator::DecodeSystem(Instr* instr) {
1818 if (instr->InstructionBits() ==
CLREX) {
1824 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) &&
1825 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
1826 (instr->Bit(21) == 0)) {
1827 if (instr->Bits(8, 4) == 0) {
1830 UnimplementedInstruction(instr);
1833 UnimplementedInstruction(instr);
1837void Simulator::DecodeTestAndBranch(Instr* instr) {
1838 const int op = instr->Bit(24);
1839 const int bitpos = instr->Bits(19, 5) | (instr->Bit(31) << 5);
1840 const uint64_t imm14 = instr->SImm14Field();
1841 const uint64_t
dest = get_pc() + (imm14 << 2);
1842 const Register rt = instr->RtField();
1843 const uint64_t rt_val = get_register(rt,
R31IsZR);
1846 if ((rt_val & (1ull << bitpos)) == 0) {
1851 if ((rt_val & (1ull << bitpos)) != 0) {
1857void Simulator::DecodeUnconditionalBranch(Instr* instr) {
1858 const bool link = instr->Bit(31) == 1;
1859 const uint64_t imm26 = instr->SImm26Field();
1860 const uint64_t
dest = get_pc() + (imm26 << 2);
1861 const uint64_t ret = get_pc() + Instr::kInstrSize;
1864 set_register(instr,
LR, ret);
1868void Simulator::DecodeUnconditionalBranchReg(Instr* instr) {
1869 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) &&
1870 (instr->Bits(16, 5) == 0x1f)) {
1871 switch (instr->Bits(21, 4)) {
1874 const Register rn = instr->RnField();
1875 const int64_t
dest = get_register(rn, instr->RnMode());
1881 const Register rn = instr->RnField();
1882 const int64_t
dest = get_register(rn, instr->RnMode());
1883 const int64_t ret = get_pc() + Instr::kInstrSize;
1885 set_register(instr,
LR, ret);
1890 const Register rn = instr->RnField();
1891 const int64_t rn_val = get_register(rn, instr->RnMode());
1896 UnimplementedInstruction(instr);
1900 UnimplementedInstruction(instr);
1905void Simulator::DecodeCompareBranch(Instr* instr) {
1906 if (instr->IsCompareAndBranchOp()) {
1907 DecodeCompareAndBranch(instr);
1908 }
else if (instr->IsConditionalBranchOp()) {
1909 DecodeConditionalBranch(instr);
1910 }
else if (instr->IsExceptionGenOp()) {
1911 DecodeExceptionGen(instr);
1912 }
else if (instr->IsSystemOp()) {
1913 DecodeSystem(instr);
1914 }
else if (instr->IsTestAndBranchOp()) {
1915 DecodeTestAndBranch(instr);
1916 }
else if (instr->IsUnconditionalBranchOp()) {
1917 DecodeUnconditionalBranch(instr);
1918 }
else if (instr->IsUnconditionalBranchRegOp()) {
1919 DecodeUnconditionalBranchReg(instr);
1921 UnimplementedInstruction(instr);
1925void Simulator::DecodeLoadStoreReg(Instr* instr) {
1927 const Register rn = instr->RnField();
1928 const Register rt = instr->RtField();
1930 const int64_t rn_val = get_register(rn,
R31IsSP);
1931 const uint32_t
size = (instr->Bit(26) == 1)
1932 ? ((instr->Bit(23) << 2) | instr->SzField())
1935 uword wb_address = 0;
1937 if (instr->Bit(24) == 1) {
1939 const uint32_t imm12 =
static_cast<uint32_t
>(instr->Imm12Field());
1941 address = rn_val +
offset;
1942 }
else if (instr->Bits(10, 2) == 0) {
1945 const int64_t
offset =
static_cast<int64_t
>(instr->SImm9Field());
1946 address = rn_val +
offset;
1947 wb_address = rn_val;
1948 }
else if (instr->Bit(10) == 1) {
1951 const int64_t
offset =
static_cast<int64_t
>(instr->SImm9Field());
1952 if (instr->Bit(11) == 1) {
1954 address = rn_val +
offset;
1955 wb_address = address;
1959 wb_address = rn_val +
offset;
1961 }
else if (instr->Bits(10, 2) == 2) {
1963 const Register rm = instr->RmField();
1964 const Extend ext = instr->ExtendTypeField();
1966 const int64_t rm_val = get_register(rm,
R31IsZR);
1968 address = rn_val +
offset;
1970 UnimplementedInstruction(instr);
1975 if (IsIllegalAddress(address)) {
1976 HandleIllegalAccess(address, instr);
1981 if (instr->Bit(26) == 1) {
1982 if (instr->Bit(22) == 0) {
1984 const int64_t vt_val = get_vregisterd(vt, 0);
1987 WriteW(address, vt_val &
kWRegMask, instr);
1990 WriteX(address, vt_val, instr);
1994 get_vregister(vt, &val);
1995 WriteX(address, val.bits.i64[0], instr);
1996 WriteX(address +
kWordSize, val.bits.i64[1], instr);
2000 UnimplementedInstruction(instr);
2007 set_vregisterd(vt, 0,
static_cast<int64_t
>(ReadWU(address, instr)));
2008 set_vregisterd(vt, 1, 0);
2011 set_vregisterd(vt, 0, ReadX(address, instr));
2012 set_vregisterd(vt, 1, 0);
2016 val.bits.i64[0] = ReadX(address, instr);
2017 val.bits.i64[1] = ReadX(address +
kWordSize, instr);
2018 set_vregister(vt, val);
2022 UnimplementedInstruction(instr);
2027 if (instr->Bits(22, 2) == 0) {
2029 const int32_t rt_val32 = get_wregister(rt,
R31IsZR);
2032 const uint8_t val =
static_cast<uint8_t
>(rt_val32);
2033 WriteB(address, val);
2037 const uint16_t val =
static_cast<uint16_t
>(rt_val32);
2038 WriteH(address, val, instr);
2042 const uint32_t val =
static_cast<uint32_t
>(rt_val32);
2043 WriteW(address, val, instr);
2047 const int64_t val = get_register(rt,
R31IsZR);
2048 WriteX(address, val, instr);
2058 if ((
size == 3) && (instr->Bits(22, 2) == 3)) {
2059 UnimplementedInstruction(instr);
2064 const bool is_signed = instr->Bit(23) == 1;
2073 val =
static_cast<int64_t
>(ReadB(address));
2075 val =
static_cast<int64_t
>(ReadBU(address));
2081 val =
static_cast<int64_t
>(ReadH(address, instr));
2083 val =
static_cast<int64_t
>(ReadHU(address, instr));
2089 val =
static_cast<int64_t
>(ReadW(address, instr));
2091 val =
static_cast<int64_t
>(ReadWU(address, instr));
2096 val = ReadX(address, instr);
2105 set_wregister(rt,
static_cast<int32_t
>(val),
R31IsZR);
2107 set_register(instr, rt, val,
R31IsZR);
2114 set_register(instr, rn, wb_address,
R31IsSP);
2118void Simulator::DecodeLoadStoreRegPair(Instr* instr) {
2119 const int32_t opc = instr->Bits(23, 3);
2120 const Register rn = instr->RnField();
2121 const int64_t rn_val = get_register(rn,
R31IsSP);
2122 const intptr_t shift =
2123 (instr->Bit(26) == 1) ? 2 + instr->SzField() : 2 + instr->SFField();
2124 const intptr_t
size = 1 << shift;
2125 const int32_t
offset = (
static_cast<uint32_t
>(instr->SImm7Field()) << shift);
2127 uword wb_address = 0;
2130 if ((instr->Bits(30, 2) == 3)) {
2131 UnimplementedInstruction(instr);
2139 wb_address = rn_val +
offset;
2143 address = rn_val +
offset;
2146 address = rn_val +
offset;
2147 wb_address = address;
2151 UnimplementedInstruction(instr);
2156 if (IsIllegalAddress(address)) {
2157 HandleIllegalAccess(address, instr);
2162 if (instr->Bit(26) == 1) {
2165 const VRegister vt2 = instr->Vt2Field();
2166 if (instr->Bit(22) != 0) {
2170 set_vregisterd(vt, 0,
static_cast<int64_t
>(ReadWU(address, instr)));
2171 set_vregisterd(vt, 1, 0);
2172 set_vregisterd(vt2, 0,
2173 static_cast<int64_t
>(ReadWU(address + 4, instr)));
2174 set_vregisterd(vt2, 1, 0);
2177 set_vregisterd(vt, 0, ReadX(address, instr));
2178 set_vregisterd(vt, 1, 0);
2179 set_vregisterd(vt2, 0, ReadX(address + 8, instr));
2180 set_vregisterd(vt2, 1, 0);
2184 val.bits.i64[0] = ReadX(address, instr);
2185 val.bits.i64[1] = ReadX(address + 8, instr);
2186 set_vregister(vt, val);
2187 val.bits.i64[0] = ReadX(address + 16, instr);
2188 val.bits.i64[1] = ReadX(address + 24, instr);
2189 set_vregister(vt2, val);
2193 UnimplementedInstruction(instr);
2200 WriteW(address, get_vregisterd(vt, 0) &
kWRegMask, instr);
2201 WriteW(address + 4, get_vregisterd(vt2, 0) &
kWRegMask, instr);
2204 WriteX(address, get_vregisterd(vt, 0), instr);
2205 WriteX(address + 8, get_vregisterd(vt2, 0), instr);
2209 get_vregister(vt, &val);
2210 WriteX(address, val.bits.i64[0], instr);
2211 WriteX(address + 8, val.bits.i64[1], instr);
2212 get_vregister(vt2, &val);
2213 WriteX(address + 16, val.bits.i64[0], instr);
2214 WriteX(address + 24, val.bits.i64[1], instr);
2218 UnimplementedInstruction(instr);
2224 const Register rt = instr->RtField();
2225 const Register rt2 = instr->Rt2Field();
2226 if (instr->Bit(22) != 0) {
2228 const bool is_signed = instr->Bit(30) == 1;
2231 if (instr->Bit(31) == 1) {
2233 val1 = ReadX(address, instr);
2234 val2 = ReadX(address +
size, instr);
2237 val1 =
static_cast<int64_t
>(ReadW(address, instr));
2238 val2 =
static_cast<int64_t
>(ReadW(address +
size, instr));
2240 val1 =
static_cast<int64_t
>(ReadWU(address, instr));
2241 val2 =
static_cast<int64_t
>(ReadWU(address +
size, instr));
2245 if (instr->Bit(31) == 1) {
2246 set_register(instr, rt, val1,
R31IsZR);
2247 set_register(instr, rt2, val2,
R31IsZR);
2249 set_wregister(rt,
static_cast<int32_t
>(val1),
R31IsZR);
2250 set_wregister(rt2,
static_cast<int32_t
>(val2),
R31IsZR);
2254 if (instr->Bit(31) == 1) {
2255 const int64_t val1 = get_register(rt,
R31IsZR);
2256 const int64_t val2 = get_register(rt2,
R31IsZR);
2257 WriteX(address, val1, instr);
2258 WriteX(address +
size, val2, instr);
2260 const int32_t val1 = get_wregister(rt,
R31IsZR);
2261 const int32_t val2 = get_wregister(rt2,
R31IsZR);
2262 WriteW(address, val1, instr);
2263 WriteW(address +
size, val2, instr);
2270 set_register(instr, rn, wb_address,
R31IsSP);
2274void Simulator::DecodeLoadRegLiteral(Instr* instr) {
2275 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) ||
2276 (instr->Bits(24, 3) != 0)) {
2277 UnimplementedInstruction(instr);
2280 const Register rt = instr->RtField();
2281 const int64_t off = instr->SImm19Field() << 2;
2282 const int64_t pc =
reinterpret_cast<int64_t
>(instr);
2283 const int64_t address = pc + off;
2284 const int64_t val = ReadX(address, instr);
2285 if (instr->Bit(30) != 0) {
2287 set_register(instr, rt, val,
R31IsZR);
2290 set_wregister(rt,
static_cast<int32_t
>(val),
R31IsZR);
2294void Simulator::DecodeLoadStoreExclusive(Instr* instr) {
2295 if (instr->Bit(21) != 0 || instr->Bit(23) != instr->Bit(15)) {
2298 const int32_t
size = instr->Bits(30, 2);
2302 const Register rs = instr->RsField();
2303 const Register rn = instr->RnField();
2304 const Register rt = instr->RtField();
2306 const bool is_load = instr->Bit(22) == 1;
2307 const bool is_exclusive = instr->Bit(23) == 0;
2308 const bool is_ordered = instr->Bit(15) == 1;
2310 const bool is_load_acquire = !is_exclusive && is_ordered;
2311 if (is_load_acquire) {
2315 const intptr_t
value =
2316 (
size == 3) ? ReadAcquire(
addr, instr) : ReadAcquireW(
addr, instr);
2322 const intptr_t
value = (
size == 3) ? ReadExclusiveX(
addr, instr)
2323 : ReadExclusiveW(
addr, instr);
2327 const bool is_store_release = !is_exclusive && is_ordered;
2328 if (is_store_release) {
2336 WriteReleaseW(
addr,
static_cast<uint32_t
>(
value), instr);
2342 const intptr_t status =
2345 : WriteExclusiveW(
addr,
static_cast<uint32_t
>(
value), instr);
2346 set_register(instr, rs, status,
R31IsSP);
2351void Simulator::DecodeAtomicMemory(Instr* instr) {
2352 const int32_t
size = instr->Bits(30, 2);
2353 std::memory_order order;
2354 switch (instr->Bits(22, 2)) {
2356 order = std::memory_order_acq_rel;
2359 order = std::memory_order_acquire;
2362 order = std::memory_order_release;
2365 order = std::memory_order_relaxed;
2368 const Register rs = instr->RsField();
2369 const Register rn = instr->RnField();
2370 const Register rt = instr->RtField();
2371 const int32_t opc = instr->Bits(12, 3);
2374 uint64_t in = get_register(rs,
R31IsZR);
2376 reinterpret_cast<std::atomic<uint64_t>*
>(get_register(rn,
R31IsSP));
2380 out =
addr->fetch_and(~in, order);
2383 out =
addr->fetch_or(in, order);
2389 }
else if (
size == 2) {
2391 uint32_t in = get_wregister(rs,
R31IsZR);
2393 reinterpret_cast<std::atomic<uint32_t>*
>(get_register(rn,
R31IsSP));
2397 out =
addr->fetch_and(~in, order);
2400 out =
addr->fetch_or(in, order);
2412void Simulator::DecodeLoadStore(Instr* instr) {
2413 if (instr->IsAtomicMemoryOp()) {
2414 DecodeAtomicMemory(instr);
2415 }
else if (instr->IsLoadStoreRegOp()) {
2416 DecodeLoadStoreReg(instr);
2417 }
else if (instr->IsLoadStoreRegPairOp()) {
2418 DecodeLoadStoreRegPair(instr);
2419 }
else if (instr->IsLoadRegLiteralOp()) {
2420 DecodeLoadRegLiteral(instr);
2421 }
else if (instr->IsLoadStoreExclusiveOp()) {
2422 DecodeLoadStoreExclusive(instr);
2424 UnimplementedInstruction(instr);
2428int64_t Simulator::ShiftOperand(uint8_t reg_size,
2436 switch (shift_type) {
2438 return (
static_cast<uint64_t
>(
value) << amount) & mask;
2440 return static_cast<uint64_t
>(
value) >> amount;
2445 int64_t s_value = (value << s_shift) >> s_shift;
2446 return (s_value >> amount) & mask;
2452 return (
static_cast<uint64_t
>(
value) >> amount) |
2453 ((
static_cast<uint64_t
>(
value) & ((1ULL << amount) - 1ULL))
2454 << (reg_size - amount));
2462int64_t Simulator::ExtendOperand(uint8_t reg_size,
2466 switch (extend_type) {
2474 value &= 0xffffffff;
2477 value =
static_cast<int64_t
>(
static_cast<uint64_t
>(
value) << 56) >> 56;
2480 value =
static_cast<int64_t
>(
static_cast<uint64_t
>(
value) << 48) >> 48;
2483 value =
static_cast<int64_t
>(
static_cast<uint64_t
>(
value) << 32) >> 32;
2493 return (
static_cast<uint64_t
>(
value) << amount) & mask;
2496int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) {
2497 const Register rm = instr->RmField();
2498 const int64_t rm_val = get_register(rm,
R31IsZR);
2499 const uint8_t
size =
2501 if (instr->IsShift()) {
2502 const Shift shift_type = instr->ShiftTypeField();
2503 const uint8_t shift_amount = instr->Imm6Field();
2504 return ShiftOperand(
size, rm_val, shift_type, shift_amount);
2506 ASSERT(instr->IsExtend());
2507 const Extend extend_type = instr->ExtendTypeField();
2508 const uint8_t shift_amount = instr->Imm3Field();
2509 return ExtendOperand(
size, rm_val, extend_type, shift_amount);
2515void Simulator::DecodeAddSubShiftExt(Instr* instr) {
2518 const bool addition = (instr->Bit(30) == 0);
2519 const Register rd = instr->RdField();
2520 const Register rn = instr->RnField();
2521 const uint64_t rm_val = DecodeShiftExtendOperand(instr);
2522 if (instr->SFField() != 0) {
2524 const uint64_t rn_val = get_register(rn, instr->RnMode());
2525 const uint64_t alu_out = rn_val + (addition ? rm_val : -rm_val);
2526 set_register(instr, rd, alu_out, instr->RdMode());
2527 if (instr->HasS()) {
2528 SetNZFlagsX(alu_out);
2529 SetCFlag(CarryFromX(alu_out, rn_val, rm_val, addition));
2530 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, addition));
2534 const uint32_t rn_val = get_wregister(rn, instr->RnMode());
2535 uint32_t rm_val32 =
static_cast<uint32_t
>(rm_val &
kWRegMask);
2536 uint32_t carry_in = 0;
2539 rm_val32 = ~rm_val32;
2541 const uint32_t alu_out = rn_val + rm_val32 + carry_in;
2542 set_wregister(rd, alu_out, instr->RdMode());
2543 if (instr->HasS()) {
2544 SetNZFlagsW(alu_out);
2545 SetCFlag(CarryFromW(rn_val, rm_val32, carry_in));
2546 SetVFlag(OverflowFromW(rn_val, rm_val32, carry_in));
2551void Simulator::DecodeAddSubWithCarry(Instr* instr) {
2554 const bool addition = (instr->Bit(30) == 0);
2555 const Register rd = instr->RdField();
2556 const Register rn = instr->RnField();
2557 const Register rm = instr->RmField();
2558 const uint64_t rn_val64 = get_register(rn,
R31IsZR);
2559 const uint32_t rn_val32 = get_wregister(rn,
R31IsZR);
2560 const uint64_t rm_val64 = get_register(rm,
R31IsZR);
2561 uint32_t rm_val32 = get_wregister(rm,
R31IsZR);
2562 const uint32_t carry_in = c_flag_ ? 1 : 0;
2563 if (instr->SFField() != 0) {
2565 const uint64_t alu_out =
2566 rn_val64 + (addition ? rm_val64 : ~rm_val64) + carry_in;
2567 set_register(instr, rd, alu_out,
R31IsZR);
2568 if (instr->HasS()) {
2569 SetNZFlagsX(alu_out);
2570 SetCFlag(CarryFromX(alu_out, rn_val64, rm_val64, addition));
2571 SetVFlag(OverflowFromX(alu_out, rn_val64, rm_val64, addition));
2576 rm_val32 = ~rm_val32;
2578 const uint32_t alu_out = rn_val32 + rm_val32 + carry_in;
2579 set_wregister(rd, alu_out,
R31IsZR);
2580 if (instr->HasS()) {
2581 SetNZFlagsW(alu_out);
2582 SetCFlag(CarryFromW(rn_val32, rm_val32, carry_in));
2583 SetVFlag(OverflowFromW(rn_val32, rm_val32, carry_in));
2588void Simulator::DecodeLogicalShift(Instr* instr) {
2589 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21);
2590 const Register rd = instr->RdField();
2591 const Register rn = instr->RnField();
2592 const int64_t rn_val = get_register(rn, instr->RnMode());
2593 const int64_t rm_val = DecodeShiftExtendOperand(instr);
2594 int64_t alu_out = 0;
2598 alu_out = rn_val & rm_val;
2602 alu_out = rn_val & (~rm_val);
2606 alu_out = rn_val | rm_val;
2610 alu_out = rn_val | (~rm_val);
2614 alu_out = rn_val ^ rm_val;
2618 alu_out = rn_val ^ (~rm_val);
2622 alu_out = rn_val & rm_val;
2626 alu_out = rn_val & (~rm_val);
2634 if ((op == 6) || (op == 7)) {
2635 if (instr->SFField() == 1) {
2636 SetNZFlagsX(alu_out);
2638 SetNZFlagsW(alu_out);
2644 if (instr->SFField() == 1) {
2645 set_register(instr, rd, alu_out, instr->RdMode());
2647 set_wregister(rd, alu_out &
kWRegMask, instr->RdMode());
2651static int64_t divide64(int64_t top, int64_t bottom,
bool is_signed) {
2660 if ((top ==
static_cast<int64_t
>(0x8000000000000000LL)) &&
2661 (bottom ==
static_cast<int64_t
>(0xffffffffffffffffLL))) {
2662 return static_cast<int64_t
>(0x8000000000000000LL);
2664 return top / bottom;
2667 const uint64_t utop =
static_cast<uint64_t
>(top);
2668 const uint64_t ubottom =
static_cast<uint64_t
>(bottom);
2669 return static_cast<int64_t
>(utop / ubottom);
2673static int32_t divide32(int32_t top, int32_t bottom,
bool is_signed) {
2682 if ((top ==
static_cast<int32_t
>(0x80000000)) &&
2683 (bottom ==
static_cast<int32_t
>(0xffffffff))) {
2684 return static_cast<int32_t
>(0x80000000);
2686 return top / bottom;
2689 const uint32_t utop =
static_cast<uint32_t
>(top);
2690 const uint32_t ubottom =
static_cast<uint32_t
>(bottom);
2691 return static_cast<int32_t
>(utop / ubottom);
2695void Simulator::DecodeMiscDP1Source(Instr* instr) {
2696 if (instr->Bit(29) != 0) {
2697 UnimplementedInstruction(instr);
2700 const Register rd = instr->RdField();
2701 const Register rn = instr->RnField();
2702 const int op = instr->Bits(10, 10);
2703 const int64_t rn_val64 = get_register(rn,
R31IsZR);
2704 const int32_t rn_val32 = get_wregister(rn,
R31IsZR);
2708 if (instr->SFField() == 1) {
2709 const uint64_t rd_val = Utils::CountLeadingZeros64(rn_val64);
2710 set_register(instr, rd, rd_val,
R31IsZR);
2712 const uint32_t rd_val = Utils::CountLeadingZeros32(rn_val32);
2713 set_wregister(rd, rd_val,
R31IsZR);
2719 if (instr->SFField() == 1) {
2720 const uint64_t rd_val = Utils::ReverseBits64(rn_val64);
2721 set_register(instr, rd, rd_val,
R31IsZR);
2723 const uint32_t rd_val = Utils::ReverseBits32(rn_val32);
2724 set_wregister(rd, rd_val,
R31IsZR);
2729 UnimplementedInstruction(instr);
2734void Simulator::DecodeMiscDP2Source(Instr* instr) {
2735 if (instr->Bit(29) != 0) {
2736 UnimplementedInstruction(instr);
2739 const Register rd = instr->RdField();
2740 const Register rn = instr->RnField();
2741 const Register rm = instr->RmField();
2742 const int op = instr->Bits(10, 5);
2743 const int64_t rn_val64 = get_register(rn,
R31IsZR);
2744 const int64_t rm_val64 = get_register(rm,
R31IsZR);
2745 const int32_t rn_val32 = get_wregister(rn,
R31IsZR);
2746 const int32_t rm_val32 = get_wregister(rm,
R31IsZR);
2752 const bool is_signed = instr->Bit(10) == 1;
2753 if (instr->SFField() == 1) {
2754 set_register(instr, rd, divide64(rn_val64, rm_val64,
is_signed),
2763 if (instr->SFField() == 1) {
2764 const uint64_t rn_u64 =
static_cast<uint64_t
>(rn_val64);
2766 set_register(instr, rd, alu_out,
R31IsZR);
2768 const uint32_t rn_u32 =
static_cast<uint32_t
>(rn_val32);
2770 set_wregister(rd, alu_out,
R31IsZR);
2776 if (instr->SFField() == 1) {
2777 const uint64_t rn_u64 =
static_cast<uint64_t
>(rn_val64);
2779 set_register(instr, rd, alu_out,
R31IsZR);
2781 const uint32_t rn_u32 =
static_cast<uint32_t
>(rn_val32);
2783 set_wregister(rd, alu_out,
R31IsZR);
2789 if (instr->SFField() == 1) {
2790 const int64_t alu_out = rn_val64 >> (rm_val64 & (
kXRegSizeInBits - 1));
2791 set_register(instr, rd, alu_out,
R31IsZR);
2793 const int32_t alu_out = rn_val32 >> (rm_val32 & (
kXRegSizeInBits - 1));
2794 set_wregister(rd, alu_out,
R31IsZR);
2799 UnimplementedInstruction(instr);
2804void Simulator::DecodeMiscDP3Source(Instr* instr) {
2805 const Register rd = instr->RdField();
2806 const Register rn = instr->RnField();
2807 const Register rm = instr->RmField();
2808 const Register ra = instr->RaField();
2809 if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) &&
2810 (instr->Bit(15) == 0)) {
2812 if (instr->SFField() == 1) {
2813 const uint64_t rn_val = get_register(rn,
R31IsZR);
2814 const uint64_t rm_val = get_register(rm,
R31IsZR);
2815 const uint64_t ra_val = get_register(ra,
R31IsZR);
2816 const uint64_t alu_out = ra_val + (rn_val * rm_val);
2817 set_register(instr, rd, alu_out,
R31IsZR);
2819 const uint32_t rn_val = get_wregister(rn,
R31IsZR);
2820 const uint32_t rm_val = get_wregister(rm,
R31IsZR);
2821 const uint32_t ra_val = get_wregister(ra,
R31IsZR);
2822 const uint32_t alu_out = ra_val + (rn_val * rm_val);
2823 set_wregister(rd, alu_out,
R31IsZR);
2825 }
else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) &&
2826 (instr->Bit(15) == 1)) {
2828 if (instr->SFField() == 1) {
2829 const uint64_t rn_val = get_register(rn,
R31IsZR);
2830 const uint64_t rm_val = get_register(rm,
R31IsZR);
2831 const uint64_t ra_val = get_register(ra,
R31IsZR);
2832 const uint64_t alu_out = ra_val - (rn_val * rm_val);
2833 set_register(instr, rd, alu_out,
R31IsZR);
2835 const uint32_t rn_val = get_wregister(rn,
R31IsZR);
2836 const uint32_t rm_val = get_wregister(rm,
R31IsZR);
2837 const uint32_t ra_val = get_wregister(ra,
R31IsZR);
2838 const uint32_t alu_out = ra_val - (rn_val * rm_val);
2839 set_wregister(rd, alu_out,
R31IsZR);
2841 }
else if ((instr->Bits(29, 3) == 4) && (instr->Bits(21, 3) == 2) &&
2842 (instr->Bit(15) == 0)) {
2845 const int64_t rn_val = get_register(rn,
R31IsZR);
2846 const int64_t rm_val = get_register(rm,
R31IsZR);
2847#if defined(DART_HOST_OS_WINDOWS)
2850 Multiply128(rn_val, rm_val, &alu_out);
2852 const __int128 res =
2853 static_cast<__int128
>(rn_val) *
static_cast<__int128
>(rm_val);
2854 const int64_t alu_out =
static_cast<int64_t
>(res >> 64);
2856 set_register(instr, rd, alu_out,
R31IsZR);
2857 }
else if ((instr->Bits(29, 3) == 4) && (instr->Bits(21, 3) == 6) &&
2858 (instr->Bit(15) == 0)) {
2861 const uint64_t rn_val = get_register(rn,
R31IsZR);
2862 const uint64_t rm_val = get_register(rm,
R31IsZR);
2863#if defined(DART_HOST_OS_WINDOWS)
2866 UnsignedMultiply128(rn_val, rm_val, &alu_out);
2868 const unsigned __int128 res =
static_cast<unsigned __int128
>(rn_val) *
2869 static_cast<unsigned __int128
>(rm_val);
2870 const uint64_t alu_out =
static_cast<uint64_t
>(res >> 64);
2872 set_register(instr, rd, alu_out,
R31IsZR);
2873 }
else if ((instr->Bits(29, 3) == 4) && (instr->Bit(15) == 0)) {
2874 if (instr->Bits(21, 3) == 5) {
2876 const uint64_t rn_val =
static_cast<uint32_t
>(get_wregister(rn,
R31IsZR));
2877 const uint64_t rm_val =
static_cast<uint32_t
>(get_wregister(rm,
R31IsZR));
2878 const uint64_t ra_val = get_register(ra,
R31IsZR);
2879 const uint64_t alu_out = ra_val + (rn_val * rm_val);
2880 set_register(instr, rd, alu_out,
R31IsZR);
2883 const int64_t rn_val =
static_cast<int32_t
>(get_wregister(rn,
R31IsZR));
2884 const int64_t rm_val =
static_cast<int32_t
>(get_wregister(rm,
R31IsZR));
2885 const int64_t ra_val = get_register(ra,
R31IsZR);
2886 const int64_t alu_out = ra_val + (rn_val * rm_val);
2887 set_register(instr, rd, alu_out,
R31IsZR);
2890 UnimplementedInstruction(instr);
2894void Simulator::DecodeConditionalSelect(Instr* instr) {
2895 const Register rd = instr->RdField();
2896 const Register rn = instr->RnField();
2897 const Register rm = instr->RmField();
2898 const int64_t rm_val64 = get_register(rm,
R31IsZR);
2899 const int32_t rm_val32 = get_wregister(rm,
R31IsZR);
2900 const int64_t rn_val64 = get_register(rn, instr->RnMode());
2901 const int32_t rn_val32 = get_wregister(rn, instr->RnMode());
2902 int64_t result64 = 0;
2903 int32_t result32 = 0;
2905 if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 0)) {
2907 result64 = rm_val64;
2908 result32 = rm_val32;
2909 if (ConditionallyExecute(instr)) {
2910 result64 = rn_val64;
2911 result32 = rn_val32;
2913 }
else if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 1)) {
2915 result64 = rm_val64 + 1;
2916 result32 = rm_val32 + 1;
2917 if (ConditionallyExecute(instr)) {
2918 result64 = rn_val64;
2919 result32 = rn_val32;
2921 }
else if ((instr->Bits(29, 2) == 2) && (instr->Bits(10, 2) == 0)) {
2923 result64 = ~rm_val64;
2924 result32 = ~rm_val32;
2925 if (ConditionallyExecute(instr)) {
2926 result64 = rn_val64;
2927 result32 = rn_val32;
2929 }
else if ((instr->Bits(29, 2) == 2) && (instr->Bits(10, 2) == 1)) {
2931 result64 = -rm_val64;
2932 result32 = -rm_val32;
2933 if (ConditionallyExecute(instr)) {
2934 result64 = rn_val64;
2935 result32 = rn_val32;
2938 UnimplementedInstruction(instr);
2942 if (instr->SFField() == 1) {
2943 set_register(instr, rd, result64, instr->RdMode());
2945 set_wregister(rd, result32, instr->RdMode());
2949void Simulator::DecodeDPRegister(Instr* instr) {
2950 if (instr->IsAddSubShiftExtOp()) {
2951 DecodeAddSubShiftExt(instr);
2952 }
else if (instr->IsAddSubWithCarryOp()) {
2953 DecodeAddSubWithCarry(instr);
2954 }
else if (instr->IsLogicalShiftOp()) {
2955 DecodeLogicalShift(instr);
2956 }
else if (instr->IsMiscDP1SourceOp()) {
2957 DecodeMiscDP1Source(instr);
2958 }
else if (instr->IsMiscDP2SourceOp()) {
2959 DecodeMiscDP2Source(instr);
2960 }
else if (instr->IsMiscDP3SourceOp()) {
2961 DecodeMiscDP3Source(instr);
2962 }
else if (instr->IsConditionalSelectOp()) {
2963 DecodeConditionalSelect(instr);
2965 UnimplementedInstruction(instr);
2969void Simulator::DecodeSIMDCopy(Instr* instr) {
2970 const int32_t
Q = instr->Bit(30);
2971 const int32_t op = instr->Bit(29);
2972 const int32_t imm4 = instr->Bits(11, 4);
2973 const int32_t imm5 = instr->Bits(16, 5);
2977 int32_t element_bytes;
2978 if ((imm5 & 0x1) != 0) {
2982 }
else if ((imm5 & 0x2) != 0) {
2986 }
else if ((imm5 & 0x4) != 0) {
2990 }
else if ((imm5 & 0x8) != 0) {
2995 UnimplementedInstruction(instr);
2998 ASSERT((idx4 != -1) && (idx5 != -1));
3002 const Register rn = instr->RnField();
3003 const Register rd = instr->RdField();
3004 if ((op == 0) && (imm4 == 7)) {
3007 set_wregister(rd, get_vregisters(vn, idx5),
R31IsZR);
3010 set_register(instr, rd, get_vregisterd(vn, idx5),
R31IsZR);
3012 }
else if ((
Q == 1) && (op == 0) && (imm4 == 0)) {
3014 if (element_bytes == 4) {
3015 for (
int i = 0;
i < 4;
i++) {
3016 set_vregisters(vd,
i, get_vregisters(vn, idx5));
3018 }
else if (element_bytes == 8) {
3019 for (
int i = 0;
i < 2;
i++) {
3020 set_vregisterd(vd,
i, get_vregisterd(vn, idx5));
3023 UnimplementedInstruction(instr);
3026 }
else if ((
Q == 1) && (op == 0) && (imm4 == 3)) {
3028 if (element_bytes == 4) {
3029 set_vregisters(vd, idx5, get_wregister(rn,
R31IsZR));
3030 }
else if (element_bytes == 8) {
3031 set_vregisterd(vd, idx5, get_register(rn,
R31IsZR));
3033 UnimplementedInstruction(instr);
3035 }
else if ((
Q == 1) && (op == 0) && (imm4 == 1)) {
3037 if (element_bytes == 4) {
3038 for (
int i = 0;
i < 4;
i++) {
3039 set_vregisters(vd,
i, get_wregister(rn,
R31IsZR));
3041 }
else if (element_bytes == 8) {
3042 for (
int i = 0;
i < 2;
i++) {
3043 set_vregisterd(vd,
i, get_register(rn,
R31IsZR));
3046 UnimplementedInstruction(instr);
3049 }
else if ((
Q == 1) && (op == 1)) {
3051 if (element_bytes == 4) {
3052 set_vregisters(vd, idx5, get_vregisters(vn, idx4));
3053 }
else if (element_bytes == 8) {
3054 set_vregisterd(vd, idx5, get_vregisterd(vn, idx4));
3056 UnimplementedInstruction(instr);
3059 UnimplementedInstruction(instr);
3063static float vminf(
float f1,
float f2) {
3066 return signbit(f1) ? f1 : f2;
3068 return f1 > f2 ? f2 : f1;
3071static float vmaxf(
float f1,
float f2) {
3074 return signbit(f1) ? f2 : f1;
3076 return f1 < f2 ? f2 : f1;
3079static double vmind(
double f1,
double f2) {
3082 return signbit(f1) ? f1 : f2;
3084 return f1 > f2 ? f2 : f1;
3087static double vmaxd(
double f1,
double f2) {
3090 return signbit(f1) ? f2 : f1;
3092 return f1 < f2 ? f2 : f1;
3095void Simulator::DecodeSIMDThreeSame(Instr* instr) {
3096 const int Q = instr->Bit(30);
3097 const int U = instr->Bit(29);
3098 const int opcode = instr->Bits(11, 5);
3101 UnimplementedInstruction(instr);
3108 if (instr->Bit(22) == 0) {
3110 for (
int idx = 0; idx < 4; idx++) {
3111 const int32_t vn_val = get_vregisters(vn, idx);
3112 const int32_t vm_val = get_vregisters(vm, idx);
3113 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3114 const float vm_flt = bit_cast<float, int32_t>(vm_val);
3116 if ((
U == 0) && (opcode == 0x3)) {
3117 if (instr->Bit(23) == 0) {
3119 res = vn_val & vm_val;
3122 res = vn_val | vm_val;
3124 }
else if ((
U == 1) && (opcode == 0x3)) {
3126 res = vn_val ^ vm_val;
3127 }
else if ((
U == 0) && (opcode == 0x10)) {
3129 res = vn_val + vm_val;
3130 }
else if ((
U == 1) && (opcode == 0x10)) {
3132 res = vn_val - vm_val;
3133 }
else if ((
U == 0) && (opcode == 0x1a)) {
3134 if (instr->Bit(23) == 0) {
3136 res = bit_cast<int32_t, float>(vn_flt + vm_flt);
3139 res = bit_cast<int32_t, float>(vn_flt - vm_flt);
3141 }
else if ((
U == 1) && (opcode == 0x1b)) {
3143 res = bit_cast<int32_t, float>(vn_flt * vm_flt);
3144 }
else if ((
U == 1) && (opcode == 0x1f)) {
3146 res = bit_cast<int32_t, float>(vn_flt / vm_flt);
3147 }
else if ((
U == 0) && (opcode == 0x1c)) {
3149 res = (vn_flt == vm_flt) ? 0xffffffff : 0;
3150 }
else if ((
U == 1) && (opcode == 0x1c)) {
3151 if (instr->Bit(23) == 1) {
3153 res = (vn_flt > vm_flt) ? 0xffffffff : 0;
3156 res = (vn_flt >= vm_flt) ? 0xffffffff : 0;
3158 }
else if ((
U == 0) && (opcode == 0x1e)) {
3159 if (instr->Bit(23) == 1) {
3161 const float m = vminf(vn_flt, vm_flt);
3162 res = bit_cast<int32_t, float>(
m);
3165 const float m = vmaxf(vn_flt, vm_flt);
3166 res = bit_cast<int32_t, float>(
m);
3168 }
else if ((
U == 0) && (opcode == 0x1f)) {
3169 if (instr->Bit(23) == 0) {
3171 res = bit_cast<int32_t, float>(2.0 - (vn_flt * vm_flt));
3174 res = bit_cast<int32_t, float>((3.0 - vn_flt * vm_flt) / 2.0);
3177 UnimplementedInstruction(instr);
3180 set_vregisters(vd, idx, res);
3184 for (
int idx = 0; idx < 2; idx++) {
3185 const int64_t vn_val = get_vregisterd(vn, idx);
3186 const int64_t vm_val = get_vregisterd(vm, idx);
3187 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3188 const double vm_dbl = bit_cast<double, int64_t>(vm_val);
3190 if ((
U == 0) && (opcode == 0x3)) {
3191 if (instr->Bit(23) == 0) {
3193 res = vn_val & vm_val;
3196 res = vn_val | vm_val;
3198 }
else if ((
U == 1) && (opcode == 0x3)) {
3200 res = vn_val ^ vm_val;
3201 }
else if ((
U == 0) && (opcode == 0x10)) {
3203 res = vn_val + vm_val;
3204 }
else if ((
U == 1) && (opcode == 0x10)) {
3206 res = vn_val - vm_val;
3207 }
else if ((
U == 0) && (opcode == 0x1a)) {
3208 if (instr->Bit(23) == 0) {
3210 res = bit_cast<int64_t, double>(vn_dbl + vm_dbl);
3213 res = bit_cast<int64_t, double>(vn_dbl - vm_dbl);
3215 }
else if ((
U == 1) && (opcode == 0x1b)) {
3217 res = bit_cast<int64_t, double>(vn_dbl * vm_dbl);
3218 }
else if ((
U == 1) && (opcode == 0x1f)) {
3220 res = bit_cast<int64_t, double>(vn_dbl / vm_dbl);
3221 }
else if ((
U == 0) && (opcode == 0x1c)) {
3223 res = (vn_dbl == vm_dbl) ? 0xffffffffffffffffLL : 0;
3224 }
else if ((
U == 1) && (opcode == 0x1c)) {
3225 if (instr->Bit(23) == 1) {
3227 res = (vn_dbl > vm_dbl) ? 0xffffffffffffffffLL : 0;
3230 res = (vn_dbl >= vm_dbl) ? 0xffffffffffffffffLL : 0;
3232 }
else if ((
U == 0) && (opcode == 0x1e)) {
3233 if (instr->Bit(23) == 1) {
3235 const double m = vmind(vn_dbl, vm_dbl);
3236 res = bit_cast<int64_t, double>(
m);
3239 const double m = vmaxd(vn_dbl, vm_dbl);
3240 res = bit_cast<int64_t, double>(
m);
3243 UnimplementedInstruction(instr);
3246 set_vregisterd(vd, idx, res);
3251static float arm_reciprocal_sqrt_estimate(
float a) {
3253 if (isinf(
a) || (fabs(
a) >= exp2f(126)))
3260 uint32_t a_bits = bit_cast<uint32_t, float>(
a);
3262 if (((a_bits >> 23) & 1) != 0) {
3264 scaled = (
static_cast<uint64_t
>(0x3fd) << 52) |
3265 ((
static_cast<uint64_t
>(a_bits) & 0x7fffff) << 29);
3268 scaled = (
static_cast<uint64_t
>(0x3fe) << 52) |
3269 ((
static_cast<uint64_t
>(a_bits) & 0x7fffff) << 29);
3272 int32_t result_exp = (380 - ((a_bits >> 23) & 0xff)) / 2;
3274 double scaled_d = bit_cast<double, uint64_t>(scaled);
3275 ASSERT((scaled_d >= 0.25) && (scaled_d < 1.0));
3278 if (scaled_d < 0.5) {
3282 int32_t q0 =
static_cast<int32_t
>(scaled_d * 512.0);
3284 r = 1.0 /
sqrt((
static_cast<double>(q0) + 0.5) / 512.0);
3289 int32_t q1 =
static_cast<int32_t
>(scaled_d * 256.0);
3291 r = 1.0 /
sqrt((
static_cast<double>(q1) + 0.5) / 256.0);
3294 int32_t
s =
static_cast<int>(256.0 * r + 0.5);
3295 double estimate =
static_cast<double>(
s) / 256.0;
3296 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0)));
3299 int32_t result_bits =
3300 ((result_exp & 0xff) << 23) |
3301 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
3302 return bit_cast<float, int32_t>(result_bits);
3305static float arm_recip_estimate(
float a) {
3307 if (isinf(
a) || (fabs(
a) >= exp2f(126)))
3314 uint32_t a_bits = bit_cast<uint32_t, float>(
a);
3316 uint64_t scaled = (
static_cast<uint64_t
>(0x3fe) << 52) |
3317 ((
static_cast<uint64_t
>(a_bits) & 0x7fffff) << 29);
3319 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff);
3320 ASSERT((result_exp >= 1) && (result_exp <= 252));
3322 double scaled_d = bit_cast<double, uint64_t>(scaled);
3323 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0));
3326 int32_t q =
static_cast<int32_t
>(scaled_d * 512.0);
3328 double r = 1.0 / ((
static_cast<double>(q) + 0.5) / 512.0);
3330 int32_t
s =
static_cast<int32_t
>(256.0 * r + 0.5);
3331 double estimate =
static_cast<double>(
s) / 256.0;
3332 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0)));
3335 int32_t result_bits =
3336 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) |
3337 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
3338 return bit_cast<float, int32_t>(result_bits);
3341void Simulator::DecodeSIMDTwoReg(Instr* instr) {
3342 const int32_t
Q = instr->Bit(30);
3343 const int32_t
U = instr->Bit(29);
3344 const int32_t op = instr->Bits(12, 5);
3345 const int32_t sz = instr->Bits(22, 2);
3350 UnimplementedInstruction(instr);
3354 if ((
U == 1) && (op == 5)) {
3356 for (
int i = 0;
i < 2;
i++) {
3357 set_vregisterd(vd,
i, ~get_vregisterd(vn,
i));
3359 }
else if ((
U == 0) && (op == 0xf)) {
3362 for (
int i = 0;
i < 4;
i++) {
3363 const int32_t vn_val = get_vregisters(vn,
i);
3364 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3365 set_vregisters(vd,
i, bit_cast<int32_t, float>(fabsf(vn_flt)));
3367 }
else if (sz == 3) {
3369 for (
int i = 0;
i < 2;
i++) {
3370 const int64_t vn_val = get_vregisterd(vn,
i);
3371 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3372 set_vregisterd(vd,
i, bit_cast<int64_t, double>(fabs(vn_dbl)));
3375 UnimplementedInstruction(instr);
3377 }
else if ((
U == 1) && (op == 0xf)) {
3380 for (
int i = 0;
i < 4;
i++) {
3381 const int32_t vn_val = get_vregisters(vn,
i);
3382 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3383 set_vregisters(vd,
i, bit_cast<int32_t, float>(-vn_flt));
3385 }
else if (sz == 3) {
3387 for (
int i = 0;
i < 2;
i++) {
3388 const int64_t vn_val = get_vregisterd(vn,
i);
3389 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3390 set_vregisterd(vd,
i, bit_cast<int64_t, double>(-vn_dbl));
3393 UnimplementedInstruction(instr);
3395 }
else if ((
U == 1) && (op == 0x1f)) {
3398 for (
int i = 0;
i < 4;
i++) {
3399 const int32_t vn_val = get_vregisters(vn,
i);
3400 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3401 set_vregisters(vd,
i, bit_cast<int32_t, float>(sqrtf(vn_flt)));
3403 }
else if (sz == 3) {
3405 for (
int i = 0;
i < 2;
i++) {
3406 const int64_t vn_val = get_vregisterd(vn,
i);
3407 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3408 set_vregisterd(vd,
i, bit_cast<int64_t, double>(
sqrt(vn_dbl)));
3411 UnimplementedInstruction(instr);
3413 }
else if ((
U == 0) && (op == 0x1d)) {
3415 UnimplementedInstruction(instr);
3419 for (
int i = 0;
i < 4;
i++) {
3420 const int32_t vn_val = get_vregisters(vn,
i);
3421 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3422 const float re = arm_recip_estimate(vn_flt);
3423 set_vregisters(vd,
i, bit_cast<int32_t, float>(re));
3425 }
else if ((
U == 1) && (op == 0x1d)) {
3427 UnimplementedInstruction(instr);
3431 for (
int i = 0;
i < 4;
i++) {
3432 const int32_t vn_val = get_vregisters(vn,
i);
3433 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3434 const float re = arm_reciprocal_sqrt_estimate(vn_flt);
3435 set_vregisters(vd,
i, bit_cast<int32_t, float>(re));
3438 UnimplementedInstruction(instr);
3442void Simulator::DecodeDPSimd1(Instr* instr) {
3443 if (instr->IsSIMDCopyOp()) {
3444 DecodeSIMDCopy(instr);
3445 }
else if (instr->IsSIMDThreeSameOp()) {
3446 DecodeSIMDThreeSame(instr);
3447 }
else if (instr->IsSIMDTwoRegOp()) {
3448 DecodeSIMDTwoReg(instr);
3450 UnimplementedInstruction(instr);
3454void Simulator::DecodeFPImm(Instr* instr) {
3455 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) ||
3456 (instr->Bits(5, 5) != 0)) {
3457 UnimplementedInstruction(instr);
3460 if (instr->Bit(22) == 1) {
3464 const int64_t immd = Instr::VFPExpandImm(instr->Imm8Field());
3465 set_vregisterd(vd, 0, immd);
3466 set_vregisterd(vd, 1, 0);
3469 UnimplementedInstruction(instr);
3473void Simulator::DecodeFPIntCvt(Instr* instr) {
3476 const Register rd = instr->RdField();
3477 const Register rn = instr->RnField();
3479 if (instr->Bit(29) != 0) {
3480 UnimplementedInstruction(instr);
3484 if ((instr->SFField() == 0) && (instr->Bits(22, 2) == 0)) {
3485 if (instr->Bits(16, 5) == 6) {
3487 const int32_t vn_val = get_vregisters(vn, 0);
3488 set_wregister(rd, vn_val,
R31IsZR);
3489 }
else if (instr->Bits(16, 5) == 7) {
3491 const int32_t rn_val = get_wregister(rn,
R31IsZR);
3492 set_vregisters(vd, 0, rn_val);
3493 set_vregisters(vd, 1, 0);
3494 set_vregisters(vd, 2, 0);
3495 set_vregisters(vd, 3, 0);
3497 UnimplementedInstruction(instr);
3499 }
else if (instr->Bits(22, 2) == 1) {
3500 if (instr->Bits(16, 5) == 2) {
3502 const int64_t rn_val64 = get_register(rn, instr->RnMode());
3503 const int32_t rn_val32 = get_wregister(rn, instr->RnMode());
3504 const double vn_dbl = (instr->SFField() == 1)
3505 ?
static_cast<double>(rn_val64)
3506 :
static_cast<double>(rn_val32);
3507 set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl));
3508 set_vregisterd(vd, 1, 0);
3509 }
else if (instr->Bits(16, 5) == 6) {
3511 const int64_t vn_val = get_vregisterd(vn, 0);
3512 set_register(instr, rd, vn_val,
R31IsZR);
3513 }
else if (instr->Bits(16, 5) == 7) {
3515 const int64_t rn_val = get_register(rn,
R31IsZR);
3516 set_vregisterd(vd, 0, rn_val);
3517 set_vregisterd(vd, 1, 0);
3518 }
else if ((instr->Bits(16, 5) == 8) || (instr->Bits(16, 5) == 16) ||
3519 (instr->Bits(16, 5) == 24)) {
3520 const intptr_t
max = instr->Bit(31) == 1 ? INT64_MAX : INT32_MAX;
3521 const intptr_t
min = instr->Bit(31) == 1 ? INT64_MIN : INT32_MIN;
3522 double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
3523 switch (instr->Bits(16, 5)) {
3526 vn_val =
ceil(vn_val);
3530 vn_val =
floor(vn_val);
3537 if (vn_val >=
static_cast<double>(
max)) {
3539 }
else if (vn_val <=
static_cast<double>(
min)) {
3542 result =
static_cast<int64_t
>(vn_val);
3544 if (instr->Bit(31) == 1) {
3545 set_register(instr, rd,
result, instr->RdMode());
3547 set_register(instr, rd,
result & 0xffffffffll, instr->RdMode());
3550 UnimplementedInstruction(instr);
3553 UnimplementedInstruction(instr);
3557void Simulator::DecodeFPOneSource(Instr* instr) {
3558 const int opc = instr->Bits(15, 6);
3561 const int64_t vn_val = get_vregisterd(vn, 0);
3562 const int32_t vn_val32 = vn_val &
kWRegMask;
3563 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3564 const float vn_flt = bit_cast<float, int32_t>(vn_val32);
3566 if ((opc != 5) && (instr->Bit(22) != 1)) {
3569 UnimplementedInstruction(instr);
3573 int64_t res_val = 0;
3577 res_val = get_vregisterd(vn, 0);
3581 res_val = bit_cast<int64_t, double>(fabs(vn_dbl));
3585 res_val = bit_cast<int64_t, double>(-vn_dbl);
3589 res_val = bit_cast<int64_t, double>(
sqrt(vn_dbl));
3593 const uint32_t val =
3594 bit_cast<uint32_t, float>(
static_cast<float>(vn_dbl));
3595 res_val =
static_cast<int64_t
>(val);
3600 res_val = bit_cast<int64_t, double>(
static_cast<double>(vn_flt));
3603 UnimplementedInstruction(instr);
3607 set_vregisterd(vd, 0, res_val);
3608 set_vregisterd(vd, 1, 0);
3611void Simulator::DecodeFPTwoSource(Instr* instr) {
3612 if (instr->Bits(22, 2) != 1) {
3613 UnimplementedInstruction(instr);
3619 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
3620 const double vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0));
3621 const int opc = instr->Bits(12, 4);
3627 result = vn_val * vm_val;
3631 result = vn_val / vm_val;
3635 result = vn_val + vm_val;
3639 result = vn_val - vm_val;
3642 UnimplementedInstruction(instr);
3646 set_vregisterd(vd, 0, bit_cast<int64_t, double>(
result));
3647 set_vregisterd(vd, 1, 0);
3650void Simulator::DecodeFPCompare(Instr* instr) {
3653 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
3656 if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 0)) {
3658 vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0));
3659 }
else if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 1)) {
3660 if (instr->VmField() ==
V0) {
3664 UnimplementedInstruction(instr);
3668 UnimplementedInstruction(instr);
3677 if (isnan(vn_val) || isnan(vm_val)) {
3680 }
else if (vn_val == vm_val) {
3683 }
else if (vn_val < vm_val) {
3690void Simulator::DecodeFP(Instr* instr) {
3691 if (instr->IsFPImmOp()) {
3693 }
else if (instr->IsFPIntCvtOp()) {
3694 DecodeFPIntCvt(instr);
3695 }
else if (instr->IsFPOneSourceOp()) {
3696 DecodeFPOneSource(instr);
3697 }
else if (instr->IsFPTwoSourceOp()) {
3698 DecodeFPTwoSource(instr);
3699 }
else if (instr->IsFPCompareOp()) {
3700 DecodeFPCompare(instr);
3702 UnimplementedInstruction(instr);
3706void Simulator::DecodeDPSimd2(Instr* instr) {
3707 if (instr->IsFPOp()) {
3710 UnimplementedInstruction(instr);
3716void Simulator::InstructionDecodeImpl(Instr* instr) {
3717 pc_modified_ =
false;
3719 if (instr->IsLoadStoreOp()) {
3720 DecodeLoadStore(instr);
3721 }
else if (instr->IsDPImmediateOp()) {
3722 DecodeDPImmediate(instr);
3723 }
else if (instr->IsCompareBranchOp()) {
3724 DecodeCompareBranch(instr);
3725 }
else if (instr->IsDPRegisterOp()) {
3726 DecodeDPRegister(instr);
3727 }
else if (instr->IsDPSimd1Op()) {
3728 DecodeDPSimd1(instr);
3729 }
else if (instr->IsDPSimd2Op()) {
3730 DecodeDPSimd2(instr);
3732 UnimplementedInstruction(instr);
3735 if (!pc_modified_) {
3736 set_pc(
reinterpret_cast<int64_t
>(instr) + Instr::kInstrSize);
3740void Simulator::InstructionDecode(Instr* instr) {
3741 if (IsTracingExecution()) {
3745 if (FLAG_support_disassembler) {
3746 Disassembler::Disassemble(
start,
end);
3748 THR_Print(
"Disassembler not supported in this mode.\n");
3751 InstructionDecodeImpl(instr);
3755 if (
LIKELY(FLAG_stop_sim_at == ULLONG_MAX &&
3756 FLAG_trace_sim_after == ULLONG_MAX)) {
3763void Simulator::ExecuteNoTrace() {
3766 uword program_counter = get_pc();
3770 while (program_counter != kEndSimulatingPC) {
3771 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3773 InstructionDecodeImpl(instr);
3774 program_counter = get_pc();
3778void Simulator::ExecuteTrace() {
3781 uword program_counter = get_pc();
3785 while (program_counter != kEndSimulatingPC) {
3786 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3788 if (icount_ == FLAG_stop_sim_at) {
3789 SimulatorDebugger dbg(
this);
3790 dbg.Stop(instr,
"Instruction count reached");
3791 }
else if (
reinterpret_cast<uint64_t
>(instr) == FLAG_stop_sim_at) {
3792 SimulatorDebugger dbg(
this);
3793 dbg.Stop(instr,
"Instruction address reached");
3794 }
else if (IsIllegalAddress(program_counter)) {
3795 HandleIllegalAccess(program_counter, instr);
3797 InstructionDecode(instr);
3799 program_counter = get_pc();
3803int64_t Simulator::Call(int64_t entry,
3811 const intptr_t sp_before_call = get_register(
R31,
R31IsSP);
3815 set_vregisterd(
V0, 0, parameter0);
3816 set_vregisterd(
V0, 1, 0);
3817 set_vregisterd(
V1, 0, parameter1);
3818 set_vregisterd(
V1, 1, 0);
3819 set_vregisterd(
V2, 0, parameter2);
3820 set_vregisterd(
V2, 1, 0);
3821 set_vregisterd(
V3, 0, parameter3);
3822 set_vregisterd(
V3, 1, 0);
3824 set_register(
nullptr,
R0, parameter0);
3825 set_register(
nullptr,
R1, parameter1);
3826 set_register(
nullptr,
R2, parameter2);
3827 set_register(
nullptr,
R3, parameter3);
3831 intptr_t stack_pointer = sp_before_call;
3832 if (OS::ActivationFrameAlignment() > 1) {
3834 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
3836 set_register(
nullptr,
R31, stack_pointer,
R31IsSP);
3843 set_register(
nullptr,
LR, kEndSimulatingPC);
3849 const double dicount =
static_cast<double>(icount_);
3850 const int64_t callee_saved_value = bit_cast<int64_t, double>(dicount);
3854 set_register(
nullptr, r, callee_saved_value);
3862 set_vregisterd(r, 0, callee_saved_value);
3863 set_vregisterd(r, 1, 0);
3873 ASSERT(callee_saved_value == get_register(r));
3879 ASSERT(callee_saved_value == get_vregisterd(r, 0));
3881 set_vregisterd(r, 1, 0);
3885 set_register(
nullptr,
R31, sp_before_call,
R31IsSP);
3886 int64_t return_value;
3888 return_value = get_vregisterd(
V0, 0);
3890 return_value = get_register(
R0);
3892 return return_value;
3898 SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
3899 while (buf->link() !=
nullptr && buf->link()->sp() <= sp) {
3907 StackResource::Unwind(thread);
3912 set_pc(
static_cast<int64_t
>(pc));
3913 set_register(
nullptr,
SP,
static_cast<int64_t
>(sp));
3914 set_register(
nullptr,
FP,
static_cast<int64_t
>(
fp));
3915 set_register(
nullptr,
THR,
reinterpret_cast<int64_t
>(thread));
3916 set_register(
nullptr,
R31, thread->saved_stack_limit() - 4096);
3917#if defined(DART_TARGET_OS_FUCHSIA)
3918 set_register(
nullptr,
R18, thread->saved_shadow_call_stack());
3921 thread->set_vm_tag(VMTag::kDartTagId);
3923 thread->set_top_exit_frame_info(0);
3927 int64_t pp = FLAG_precompiled_mode
3928 ?
static_cast<int64_t
>(thread->global_object_pool())
3929 : *
reinterpret_cast<int64_t*
>(
3933 set_register(
nullptr,
PP, pp);
3936 (thread->write_barrier_mask() << 32) | (thread->heap_base() >> 32));
3937 set_register(
nullptr,
NULL_REG,
static_cast<int64_t
>(Object::null()));
3938 if (FLAG_precompiled_mode) {
3940 reinterpret_cast<int64_t
>(thread->dispatch_table_array()));
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static bool ok(int result)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define COMPILE_ASSERT(expr)
static IsolateGroup * vm_isolate_group()
static void Disassemble(uword start, uword end, DisassemblyFormatter *formatter, const Code &code, const CodeComments *comments=nullptr)
static constexpr int32_t kSimulatorBreakpointInstruction
static constexpr int32_t kNopInstruction
const uint8_t * snapshot_instructions
static IsolateGroup * Current()
IsolateGroupSource * source() const
static DART_NORETURN void Exit(int code)
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
@ kNoCrossThreadIteration
static Thread * Current()
#define THR_Print(format,...)
#define kIsolateSnapshotInstructionsAsmSymbol
#define kVmSnapshotInstructionsAsmSymbol
struct _Dart_NativeArguments * Dart_NativeArguments
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint32_t uint32_t * format
Dart_NativeFunction function
static float max(float r, float g, float b)
static float min(float r, float g, float b)
const GrXPFactory * Get(SkBlendMode mode)
static bool is_signed(const Type &type)
bool Contains(const Container &container, const Value &value)
def link(from_root, to_root)
const QRegister kAbiLastPreservedFpuReg
const int kXRegSizeInBits
static int64_t GetValue(Dart_Handle arg)
void SetBreakpoint(Dart_NativeArguments args)
const RegList kAbiVolatileCpuRegs
const Register DISPATCH_TABLE_REG
const int kNumberOfFpuRegisters
intx_t sign_extend(int32_t x)
const Register kAbiLastPreservedCpuReg
const int kAbiPreservedCpuRegCount
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
const Register kAbiFirstPreservedCpuReg
static T LoadUnaligned(const T *ptr)
const int kAbiPreservedFpuRegCount
static void StoreUnaligned(T *ptr, T value)
static constexpr int kPcMarkerSlotFromFp
const int kWRegSizeInBits
constexpr intptr_t kWordSize
const RegList kAbiVolatileFpuRegs
const QRegister kAbiFirstPreservedFpuReg
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
def Format(template, **parameters)
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
SIN Vec< N, float > floor(const Vec< N, float > &x)
SIN Vec< N, float > ceil(const Vec< N, float > &x)
#define NO_SANITIZE_UNDEFINED(check)
#define ARRAY_SIZE(array)
#define OFFSET_OF(type, field)