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);
67 sp_ =
static_cast<uword>(sim->get_register(R31, R31IsSP));
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);
102 bool GetValue(
char* desc, uint64_t* value);
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,
158 for (
unsigned i = 0; i <
ARRAY_SIZE(kNames); i++) {
159 if (strcmp(kNames[i],
name) == 0) {
160 return kRegisters[i];
168 bool ok = SScanF(
name,
"v%d", ®_nr);
175bool SimulatorDebugger::GetValue(
char* desc, uint64_t* value) {
176 Register reg = LookupCpuRegisterByName(desc);
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();
199 bool retval = SScanF(desc,
"0x%" Px64, value) == 1;
201 retval = SScanF(desc,
"%" Px64, value) == 1;
206bool SimulatorDebugger::GetSValue(
char* desc, uint32_t* value) {
207 VRegister vreg = LookupVRegisterByName(desc);
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) {
226 VRegister vreg = LookupVRegisterByName(desc);
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) {
245 VRegister vreg = LookupVRegisterByName(desc);
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();
404bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
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");
482 int args = SScanF(line,
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();
526 }
else if (
GetValue(arg1, &value)) {
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);
539 OS::PrintErr(
"%s: %d 0x%x %.8g\n", arg1, value, value, svalue);
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)) {
595 if (((arg1[0] ==
'*') &&
GetValue(arg1 + 1, &value)) ||
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,
951 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
952#if !defined(DART_TARGET_OS_FUCHSIA)
953 ASSERT(instr ==
nullptr || reg != R18);
956 if ((reg != R31) || (r31t != R31IsZR)) {
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);
985int64_t Simulator::get_register(Register reg, R31Type r31t)
const {
986 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
987 if ((reg == R31) && (r31t == R31IsZR)) {
990 return registers_[reg];
994void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) {
995 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
997 if ((reg != R31) || (r31t != R31IsZR)) {
998 registers_[reg] = Utils::LowHighTo64Bits(
static_cast<uint32_t
>(value), 0);
1003int32_t Simulator::get_wregister(Register reg, R31Type r31t)
const {
1004 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
1005 if ((reg == R31) && (r31t == R31IsZR)) {
1008 return static_cast<int32_t
>(registers_[reg]);
1012int32_t Simulator::get_vregisters(VRegister reg,
int idx)
const {
1013 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
1014 ASSERT((idx >= 0) && (idx <= 3));
1015 return vregisters_[reg].bits.i32[idx];
1018void Simulator::set_vregisters(VRegister reg,
int idx, int32_t value) {
1019 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
1020 ASSERT((idx >= 0) && (idx <= 3));
1021 vregisters_[reg].bits.i32[idx] =
value;
1024int64_t Simulator::get_vregisterd(VRegister reg,
int idx)
const {
1025 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
1026 ASSERT((idx == 0) || (idx == 1));
1027 return vregisters_[reg].bits.i64[idx];
1030void Simulator::set_vregisterd(VRegister reg,
int idx, int64_t value) {
1031 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
1032 ASSERT((idx == 0) || (idx == 1));
1033 vregisters_[reg].bits.i64[idx] =
value;
1036void Simulator::get_vregister(VRegister reg, simd_value_t* value)
const {
1037 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
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) {
1043 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
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;
1107intptr_t Simulator::ReadX(uword addr,
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) {
1113 return LoadUnaligned(
reinterpret_cast<intptr_t*
>(addr));
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) {
1121 StoreUnaligned(
reinterpret_cast<intptr_t*
>(addr), value);
1124 UnalignedAccess(
"write", addr, instr);
1127uint32_t Simulator::ReadWU(uword addr,
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) {
1133 return LoadUnaligned(
reinterpret_cast<uint32_t*
>(addr));
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) {
1141 return LoadUnaligned(
reinterpret_cast<int32_t*
>(addr));
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) {
1149 StoreUnaligned(
reinterpret_cast<uint32_t*
>(addr), value);
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) {
1157 return LoadUnaligned(
reinterpret_cast<uint16_t*
>(addr));
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) {
1165 return LoadUnaligned(
reinterpret_cast<int16_t*
>(addr));
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) {
1173 StoreUnaligned(
reinterpret_cast<uint16_t*
>(addr), value);
1176 UnalignedAccess(
"halfword write", addr, instr);
1179uint8_t Simulator::ReadBU(uword addr) {
1180 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(
addr);
1184int8_t Simulator::ReadB(uword addr) {
1185 int8_t* ptr =
reinterpret_cast<int8_t*
>(
addr);
1189void Simulator::WriteB(uword addr, uint8_t value) {
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 auto atomic_addr =
reinterpret_cast<RelaxedAtomic<int64_t>*
>(
addr);
1223 if (atomic_addr->compare_exchange_weak(old_value, value)) {
1229intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) {
1232 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr));
1233 if (exclusive_access_addr_ != addr) {
1237 int32_t old_value =
static_cast<uint32_t
>(exclusive_access_value_);
1240 auto atomic_addr =
reinterpret_cast<RelaxedAtomic<int32_t>*
>(
addr);
1241 if (atomic_addr->compare_exchange_weak(old_value, value)) {
1247intptr_t Simulator::ReadAcquire(uword addr, Instr* instr) {
1251 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1252 return reinterpret_cast<std::atomic<intptr_t>*
>(
addr)->
load(
1253 std::memory_order_acquire);
1256uint32_t Simulator::ReadAcquireW(uword addr, Instr* instr) {
1260 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1261 return reinterpret_cast<std::atomic<uint32_t>*
>(
addr)->
load(
1262 std::memory_order_acquire);
1265void Simulator::WriteRelease(uword addr, intptr_t value, Instr* instr) {
1269 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1270 reinterpret_cast<std::atomic<intptr_t>*
>(
addr)->
store(
1271 value, std::memory_order_release);
1274void Simulator::WriteReleaseW(uword addr, uint32_t value, Instr* instr) {
1278 COMPILE_ASSERT(
sizeof(std::atomic<intptr_t>) ==
sizeof(intptr_t));
1279 reinterpret_cast<std::atomic<uint32_t>*
>(
addr)->
store(
1280 value, std::memory_order_release);
1284void Simulator::Format(Instr* instr,
const char*
format) {
1285 OS::PrintErr(
"Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
1291void Simulator::SetNZFlagsW(int32_t val) {
1292 n_flag_ = (val < 0);
1293 z_flag_ = (val == 0);
1297bool Simulator::CarryFromW(int32_t
left, int32_t
right, int32_t carry) {
1298 uint64_t uleft =
static_cast<uint32_t
>(
left);
1299 uint64_t uright =
static_cast<uint32_t
>(
right);
1300 uint64_t ucarry =
static_cast<uint32_t
>(carry);
1301 return ((uleft + uright + ucarry) >> 32) != 0;
1305bool Simulator::OverflowFromW(int32_t
left, int32_t
right, int32_t carry) {
1311void Simulator::SetNZFlagsX(int64_t val) {
1312 n_flag_ = (val < 0);
1313 z_flag_ = (val == 0);
1317bool Simulator::CarryFromX(int64_t alu_out,
1329bool Simulator::OverflowFromX(int64_t alu_out,
1334 return (((alu_out ^
left) & (alu_out ^
right)) >> 63) != 0;
1341void Simulator::SetCFlag(
bool val) {
1346void Simulator::SetVFlag(
bool val) {
1350void Simulator::DecodeMoveWide(Instr* instr) {
1351 const Register rd = instr->RdField();
1352 const int hw = instr->HWField();
1353 const int64_t shift = hw << 4;
1354 const int64_t shifted_imm =
static_cast<int64_t
>(instr->Imm16Field())
1357 if (instr->SFField() != 0) {
1358 if (instr->Bits(29, 2) == 0) {
1360 set_register(instr, rd, ~shifted_imm, instr->RdMode());
1361 }
else if (instr->Bits(29, 2) == 2) {
1363 set_register(instr, rd, shifted_imm, instr->RdMode());
1364 }
else if (instr->Bits(29, 2) == 3) {
1366 const int64_t rd_val = get_register(rd, instr->RdMode());
1367 const int64_t
result = (rd_val & ~(0xffffL << shift)) | shifted_imm;
1368 set_register(instr, rd,
result, instr->RdMode());
1370 UnimplementedInstruction(instr);
1372 }
else if ((hw & 0x2) == 0) {
1373 if (instr->Bits(29, 2) == 0) {
1375 set_wregister(rd, ~shifted_imm & kWRegMask, instr->RdMode());
1376 }
else if (instr->Bits(29, 2) == 2) {
1378 set_wregister(rd, shifted_imm & kWRegMask, instr->RdMode());
1379 }
else if (instr->Bits(29, 2) == 3) {
1381 const int32_t rd_val = get_wregister(rd, instr->RdMode());
1382 const int32_t
result = (rd_val & ~(0xffffL << shift)) | shifted_imm;
1383 set_wregister(rd,
result, instr->RdMode());
1385 UnimplementedInstruction(instr);
1389 UnimplementedInstruction(instr);
1393void Simulator::DecodeAddSubImm(Instr* instr) {
1394 const bool addition = (instr->Bit(30) == 0);
1397 const Register rd = instr->RdField();
1398 const Register rn = instr->RnField();
1399 uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12)
1400 : (instr->Imm12Field());
1401 if (instr->SFField() != 0) {
1403 const uint64_t rn_val = get_register(rn, instr->RnMode());
1404 const uint64_t alu_out = addition ? (rn_val + imm) : (rn_val - imm);
1405 set_register(instr, rd, alu_out, instr->RdMode());
1406 if (instr->HasS()) {
1407 SetNZFlagsX(alu_out);
1408 SetCFlag(CarryFromX(alu_out, rn_val, imm, addition));
1409 SetVFlag(OverflowFromX(alu_out, rn_val, imm, addition));
1413 const uint32_t rn_val = get_wregister(rn, instr->RnMode());
1414 uint32_t carry_in = 0;
1419 const uint32_t alu_out = rn_val + imm + carry_in;
1420 set_wregister(rd, alu_out, instr->RdMode());
1421 if (instr->HasS()) {
1422 SetNZFlagsW(alu_out);
1423 SetCFlag(CarryFromW(rn_val, imm, carry_in));
1424 SetVFlag(OverflowFromW(rn_val, imm, carry_in));
1429void Simulator::DecodeBitfield(Instr* instr) {
1430 int bitwidth = instr->SFField() == 0 ? 32 : 64;
1431 unsigned op = instr->Bits(29, 2);
1434 bool zero_extend = op == 2;
1435 ASSERT(instr->NField() == instr->SFField());
1436 const Register rn = instr->RnField();
1437 const Register rd = instr->RdField();
1438 int64_t
result = get_register(rn, instr->RnMode());
1439 int r_bit = instr->ImmRField();
1440 int s_bit = instr->ImmSField();
1441 result &= Utils::NBitMask(bitwidth);
1442 ASSERT(s_bit < bitwidth && r_bit < bitwidth);
1446 uword mask = Utils::NBitMask(s_bit + 1);
1447 if (s_bit >= r_bit) {
1451 result =
static_cast<uint64_t
>(
result) << (bitwidth - r_bit);
1452 mask <<= bitwidth - r_bit;
1456 int highest_bit = (s_bit - r_bit) & (bitwidth - 1);
1457 int shift = 64 - highest_bit - 1;
1460 }
else if (!zero_extend) {
1461 const int64_t rd_val = get_register(rd, instr->RnMode());
1462 result |= rd_val & ~mask;
1464 if (bitwidth == 64) {
1465 set_register(instr, rd,
result, instr->RdMode());
1467 set_wregister(rd,
result, instr->RdMode());
1471void Simulator::DecodeLogicalImm(Instr* instr) {
1472 const int op = instr->Bits(29, 2);
1473 const bool set_flags = op == 3;
1474 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0))
1477 const Register rn = instr->RnField();
1478 const Register rd = instr->RdField();
1479 const int64_t rn_val = get_register(rn, instr->RnMode());
1480 const uint64_t imm = instr->ImmLogical();
1482 UnimplementedInstruction(instr);
1485 int64_t alu_out = 0;
1488 alu_out = rn_val & imm;
1491 alu_out = rn_val | imm;
1494 alu_out = rn_val ^ imm;
1497 alu_out = rn_val & imm;
1505 if (out_size == kXRegSizeInBits) {
1506 SetNZFlagsX(alu_out);
1508 SetNZFlagsW(alu_out);
1514 if (out_size == kXRegSizeInBits) {
1515 set_register(instr, rd, alu_out, instr->RdMode());
1517 set_wregister(rd, alu_out, instr->RdMode());
1521void Simulator::DecodePCRel(Instr* instr) {
1522 const int op = instr->Bit(31);
1525 const Register rd = instr->RdField();
1526 const uint64_t immhi = instr->SImm19Field();
1527 const uint64_t immlo = instr->Bits(29, 2);
1528 const uint64_t off = (immhi << 2) | immlo;
1529 const uint64_t
dest = get_pc() + off;
1530 set_register(instr, rd, dest, instr->RdMode());
1532 UnimplementedInstruction(instr);
1536void Simulator::DecodeDPImmediate(Instr* instr) {
1537 if (instr->IsMoveWideOp()) {
1538 DecodeMoveWide(instr);
1539 }
else if (instr->IsAddSubImmOp()) {
1540 DecodeAddSubImm(instr);
1541 }
else if (instr->IsBitfieldOp()) {
1542 DecodeBitfield(instr);
1543 }
else if (instr->IsLogicalImmOp()) {
1544 DecodeLogicalImm(instr);
1545 }
else if (instr->IsPCRelOp()) {
1548 UnimplementedInstruction(instr);
1552void Simulator::DecodeCompareAndBranch(Instr* instr) {
1553 const int op = instr->Bit(24);
1554 const Register rt = instr->RtField();
1555 const uint64_t imm19 = instr->SImm19Field();
1556 const uint64_t
dest = get_pc() + (imm19 << 2);
1558 const uint64_t rt_val = get_register(rt, R31IsZR) & mask;
1572bool Simulator::ConditionallyExecute(Instr* instr) {
1574 if (instr->IsConditionalSelectOp()) {
1575 cond = instr->SelectConditionField();
1577 cond = instr->ConditionField();
1597 return c_flag_ && !z_flag_;
1599 return !c_flag_ || z_flag_;
1601 return n_flag_ == v_flag_;
1603 return n_flag_ != v_flag_;
1605 return !z_flag_ && (n_flag_ == v_flag_);
1607 return z_flag_ || (n_flag_ != v_flag_);
1616void Simulator::DecodeConditionalBranch(Instr* instr) {
1618 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) {
1619 UnimplementedInstruction(instr);
1621 const uint64_t imm19 = instr->SImm19Field();
1622 const uint64_t
dest = get_pc() + (imm19 << 2);
1623 if (ConditionallyExecute(instr)) {
1629typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
1632typedef int64_t (*SimulatorLeafRuntimeCall)(int64_t r0,
1646static int64_t InvokeLeafRuntime(SimulatorLeafRuntimeCall
target,
1655 return target(r0, r1, r2, r3, r4, r5, r6, r7);
1659typedef double (*SimulatorLeafFloatRuntimeCall)(
double d0,
1673static
double InvokeFloatLeafRuntime(SimulatorLeafFloatRuntimeCall
target,
1682 return target(d0, d1, d2, d3, d4, d5, d6, d7);
1689void Simulator::DoRedirectedCall(Instr* instr) {
1690 SimulatorSetjmpBuffer
buffer(
this);
1691 if (!setjmp(
buffer.buffer_)) {
1692 int64_t saved_lr = get_register(
LR);
1693 Redirection* redirection = Redirection::FromHltInstruction(instr);
1694 uword external = redirection->external_function();
1695 if (IsTracingExecution()) {
1696 THR_Print(
"Call to host function at 0x%" Pd "\n", external);
1699 if (redirection->call_kind() == kRuntimeCall) {
1700 NativeArguments* arguments =
1701 reinterpret_cast<NativeArguments*
>(get_register(R0));
1702 SimulatorRuntimeCall
target =
1703 reinterpret_cast<SimulatorRuntimeCall
>(external);
1705 ClobberVolatileRegisters();
1706 }
else if (redirection->call_kind() == kLeafRuntimeCall) {
1707 ASSERT((0 <= redirection->argument_count()) &&
1708 (redirection->argument_count() <= 8));
1709 SimulatorLeafRuntimeCall
target =
1710 reinterpret_cast<SimulatorLeafRuntimeCall
>(external);
1711 const int64_t r0 = get_register(R0);
1712 const int64_t r1 = get_register(R1);
1713 const int64_t r2 = get_register(R2);
1714 const int64_t r3 = get_register(R3);
1715 const int64_t r4 = get_register(R4);
1716 const int64_t r5 = get_register(R5);
1717 const int64_t r6 = get_register(R6);
1718 const int64_t r7 = get_register(R7);
1720 InvokeLeafRuntime(
target, r0, r1, r2, r3, r4, r5, r6, r7);
1721 ClobberVolatileRegisters();
1722 set_register(instr, R0, res);
1723 }
else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
1724 ASSERT((0 <= redirection->argument_count()) &&
1725 (redirection->argument_count() <= 8));
1726 SimulatorLeafFloatRuntimeCall
target =
1727 reinterpret_cast<SimulatorLeafFloatRuntimeCall
>(external);
1728 const double d0 = bit_cast<double, int64_t>(get_vregisterd(V0, 0));
1729 const double d1 = bit_cast<double, int64_t>(get_vregisterd(V1, 0));
1730 const double d2 = bit_cast<double, int64_t>(get_vregisterd(V2, 0));
1731 const double d3 = bit_cast<double, int64_t>(get_vregisterd(V3, 0));
1732 const double d4 = bit_cast<double, int64_t>(get_vregisterd(V4, 0));
1733 const double d5 = bit_cast<double, int64_t>(get_vregisterd(V5, 0));
1734 const double d6 = bit_cast<double, int64_t>(get_vregisterd(V6, 0));
1735 const double d7 = bit_cast<double, int64_t>(get_vregisterd(V7, 0));
1737 InvokeFloatLeafRuntime(
target, d0, d1, d2, d3, d4, d5, d6, d7);
1738 ClobberVolatileRegisters();
1739 set_vregisterd(V0, 0, bit_cast<int64_t, double>(res));
1740 set_vregisterd(V0, 1, 0);
1742 ASSERT(redirection->call_kind() == kNativeCallWrapper);
1743 SimulatorNativeCallWrapper wrapper =
1744 reinterpret_cast<SimulatorNativeCallWrapper
>(external);
1749 wrapper(arguments,
target);
1750 ClobberVolatileRegisters();
1760void Simulator::ClobberVolatileRegisters() {
1762 exclusive_access_addr_ = exclusive_access_value_ = 0;
1765 if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
1766 registers_[i] = icount_;
1771 if ((kAbiVolatileFpuRegs & (1 << i)) != 0) {
1772 vregisters_[i].bits.i64[0] = icount_;
1773 vregisters_[i].bits.i64[1] = icount_;
1778void Simulator::DecodeExceptionGen(Instr* instr) {
1779 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
1780 (instr->Bits(21, 3) == 0)) {
1782 UnimplementedInstruction(instr);
1783 }
else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
1784 (instr->Bits(21, 3) == 1)) {
1786 SimulatorDebugger dbg(
this);
1787 int32_t imm = instr->Imm16Field();
1790 set_pc(get_pc() + Instr::kInstrSize);
1792 }
else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
1793 (instr->Bits(21, 3) == 2)) {
1795 uint16_t imm =
static_cast<uint16_t
>(instr->Imm16Field());
1796 if (imm == Instr::kSimulatorBreakCode) {
1797 SimulatorDebugger dbg(
this);
1798 dbg.Stop(instr,
"breakpoint");
1799 }
else if (imm == Instr::kSimulatorRedirectCode) {
1800 DoRedirectedCall(instr);
1802 UnimplementedInstruction(instr);
1805 UnimplementedInstruction(instr);
1809void Simulator::DecodeSystem(Instr* instr) {
1810 if (instr->InstructionBits() == CLREX) {
1816 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) &&
1817 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
1818 (instr->Bit(21) == 0)) {
1819 if (instr->Bits(8, 4) == 0) {
1822 UnimplementedInstruction(instr);
1825 UnimplementedInstruction(instr);
1829void Simulator::DecodeTestAndBranch(Instr* instr) {
1830 const int op = instr->Bit(24);
1831 const int bitpos = instr->Bits(19, 5) | (instr->Bit(31) << 5);
1832 const uint64_t imm14 = instr->SImm14Field();
1833 const uint64_t
dest = get_pc() + (imm14 << 2);
1834 const Register rt = instr->RtField();
1835 const uint64_t rt_val = get_register(rt, R31IsZR);
1838 if ((rt_val & (1ull << bitpos)) == 0) {
1843 if ((rt_val & (1ull << bitpos)) != 0) {
1849void Simulator::DecodeUnconditionalBranch(Instr* instr) {
1850 const bool link = instr->Bit(31) == 1;
1851 const uint64_t imm26 = instr->SImm26Field();
1852 const uint64_t
dest = get_pc() + (imm26 << 2);
1853 const uint64_t ret = get_pc() + Instr::kInstrSize;
1856 set_register(instr,
LR, ret);
1860void Simulator::DecodeUnconditionalBranchReg(Instr* instr) {
1861 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) &&
1862 (instr->Bits(16, 5) == 0x1f)) {
1863 switch (instr->Bits(21, 4)) {
1866 const Register rn = instr->RnField();
1867 const int64_t
dest = get_register(rn, instr->RnMode());
1873 const Register rn = instr->RnField();
1874 const int64_t
dest = get_register(rn, instr->RnMode());
1875 const int64_t ret = get_pc() + Instr::kInstrSize;
1877 set_register(instr,
LR, ret);
1882 const Register rn = instr->RnField();
1883 const int64_t rn_val = get_register(rn, instr->RnMode());
1888 UnimplementedInstruction(instr);
1892 UnimplementedInstruction(instr);
1897void Simulator::DecodeCompareBranch(Instr* instr) {
1898 if (instr->IsCompareAndBranchOp()) {
1899 DecodeCompareAndBranch(instr);
1900 }
else if (instr->IsConditionalBranchOp()) {
1901 DecodeConditionalBranch(instr);
1902 }
else if (instr->IsExceptionGenOp()) {
1903 DecodeExceptionGen(instr);
1904 }
else if (instr->IsSystemOp()) {
1905 DecodeSystem(instr);
1906 }
else if (instr->IsTestAndBranchOp()) {
1907 DecodeTestAndBranch(instr);
1908 }
else if (instr->IsUnconditionalBranchOp()) {
1909 DecodeUnconditionalBranch(instr);
1910 }
else if (instr->IsUnconditionalBranchRegOp()) {
1911 DecodeUnconditionalBranchReg(instr);
1913 UnimplementedInstruction(instr);
1917void Simulator::DecodeLoadStoreReg(Instr* instr) {
1919 const Register rn = instr->RnField();
1920 const Register rt = instr->RtField();
1922 const int64_t rn_val = get_register(rn, R31IsSP);
1923 const uint32_t
size = (instr->Bit(26) == 1)
1924 ? ((instr->Bit(23) << 2) | instr->SzField())
1927 uword wb_address = 0;
1929 if (instr->Bit(24) == 1) {
1931 const uint32_t imm12 =
static_cast<uint32_t
>(instr->Imm12Field());
1933 address = rn_val +
offset;
1934 }
else if (instr->Bits(10, 2) == 0) {
1937 const int64_t
offset =
static_cast<int64_t
>(instr->SImm9Field());
1938 address = rn_val +
offset;
1939 wb_address = rn_val;
1940 }
else if (instr->Bit(10) == 1) {
1943 const int64_t
offset =
static_cast<int64_t
>(instr->SImm9Field());
1944 if (instr->Bit(11) == 1) {
1946 address = rn_val +
offset;
1947 wb_address = address;
1951 wb_address = rn_val +
offset;
1953 }
else if (instr->Bits(10, 2) == 2) {
1955 const Register rm = instr->RmField();
1956 const Extend ext = instr->ExtendTypeField();
1957 const uint8_t
scale = (
ext ==
UXTX) && (instr->Bit(12) == 1) ? size : 0;
1958 const int64_t rm_val = get_register(rm, R31IsZR);
1959 const int64_t
offset = ExtendOperand(kXRegSizeInBits, rm_val, ext,
scale);
1960 address = rn_val +
offset;
1962 UnimplementedInstruction(instr);
1967 if (IsIllegalAddress(address)) {
1968 HandleIllegalAccess(address, instr);
1973 if (instr->Bit(26) == 1) {
1974 if (instr->Bit(22) == 0) {
1976 const int64_t vt_val = get_vregisterd(vt, 0);
1979 WriteW(address, vt_val & kWRegMask, instr);
1982 WriteX(address, vt_val, instr);
1986 get_vregister(vt, &val);
1987 WriteX(address, val.bits.i64[0], instr);
1988 WriteX(address + kWordSize, val.bits.i64[1], instr);
1992 UnimplementedInstruction(instr);
1999 set_vregisterd(vt, 0,
static_cast<int64_t
>(ReadWU(address, instr)));
2000 set_vregisterd(vt, 1, 0);
2003 set_vregisterd(vt, 0, ReadX(address, instr));
2004 set_vregisterd(vt, 1, 0);
2008 val.bits.i64[0] = ReadX(address, instr);
2009 val.bits.i64[1] = ReadX(address + kWordSize, instr);
2010 set_vregister(vt, val);
2014 UnimplementedInstruction(instr);
2019 if (instr->Bits(22, 2) == 0) {
2021 const int32_t rt_val32 = get_wregister(rt, R31IsZR);
2024 const uint8_t val =
static_cast<uint8_t
>(rt_val32);
2025 WriteB(address, val);
2029 const uint16_t val =
static_cast<uint16_t
>(rt_val32);
2030 WriteH(address, val, instr);
2034 const uint32_t val =
static_cast<uint32_t
>(rt_val32);
2035 WriteW(address, val, instr);
2039 const int64_t val = get_register(rt, R31IsZR);
2040 WriteX(address, val, instr);
2050 if ((size == 3) && (instr->Bits(22, 2) == 3)) {
2051 UnimplementedInstruction(instr);
2056 const bool is_signed = instr->Bit(23) == 1;
2060 (is_signed && (instr->Bit(22) == 1)) || (!is_signed && (
size == 2));
2065 val =
static_cast<int64_t
>(ReadB(address));
2067 val =
static_cast<int64_t
>(ReadBU(address));
2073 val =
static_cast<int64_t
>(ReadH(address, instr));
2075 val =
static_cast<int64_t
>(ReadHU(address, instr));
2081 val =
static_cast<int64_t
>(ReadW(address, instr));
2083 val =
static_cast<int64_t
>(ReadWU(address, instr));
2088 val = ReadX(address, instr);
2097 set_wregister(rt,
static_cast<int32_t
>(val), R31IsZR);
2099 set_register(instr, rt, val, R31IsZR);
2106 set_register(instr, rn, wb_address, R31IsSP);
2110void Simulator::DecodeLoadStoreRegPair(Instr* instr) {
2111 const int32_t opc = instr->Bits(23, 3);
2112 const Register rn = instr->RnField();
2113 const int64_t rn_val = get_register(rn, R31IsSP);
2114 const intptr_t shift =
2115 (instr->Bit(26) == 1) ? 2 + instr->SzField() : 2 + instr->SFField();
2116 const intptr_t
size = 1 << shift;
2117 const int32_t
offset = (
static_cast<uint32_t
>(instr->SImm7Field()) << shift);
2119 uword wb_address = 0;
2122 if ((instr->Bits(30, 2) == 3)) {
2123 UnimplementedInstruction(instr);
2131 wb_address = rn_val +
offset;
2135 address = rn_val +
offset;
2138 address = rn_val +
offset;
2139 wb_address = address;
2143 UnimplementedInstruction(instr);
2148 if (IsIllegalAddress(address)) {
2149 HandleIllegalAccess(address, instr);
2154 if (instr->Bit(26) == 1) {
2157 const VRegister vt2 = instr->Vt2Field();
2158 if (instr->Bit(22) != 0) {
2162 set_vregisterd(vt, 0,
static_cast<int64_t
>(ReadWU(address, instr)));
2163 set_vregisterd(vt, 1, 0);
2164 set_vregisterd(vt2, 0,
2165 static_cast<int64_t
>(ReadWU(address + 4, instr)));
2166 set_vregisterd(vt2, 1, 0);
2169 set_vregisterd(vt, 0, ReadX(address, instr));
2170 set_vregisterd(vt, 1, 0);
2171 set_vregisterd(vt2, 0, ReadX(address + 8, instr));
2172 set_vregisterd(vt2, 1, 0);
2176 val.bits.i64[0] = ReadX(address, instr);
2177 val.bits.i64[1] = ReadX(address + 8, instr);
2178 set_vregister(vt, val);
2179 val.bits.i64[0] = ReadX(address + 16, instr);
2180 val.bits.i64[1] = ReadX(address + 24, instr);
2181 set_vregister(vt2, val);
2185 UnimplementedInstruction(instr);
2192 WriteW(address, get_vregisterd(vt, 0) & kWRegMask, instr);
2193 WriteW(address + 4, get_vregisterd(vt2, 0) & kWRegMask, instr);
2196 WriteX(address, get_vregisterd(vt, 0), instr);
2197 WriteX(address + 8, get_vregisterd(vt2, 0), instr);
2201 get_vregister(vt, &val);
2202 WriteX(address, val.bits.i64[0], instr);
2203 WriteX(address + 8, val.bits.i64[1], instr);
2204 get_vregister(vt2, &val);
2205 WriteX(address + 16, val.bits.i64[0], instr);
2206 WriteX(address + 24, val.bits.i64[1], instr);
2210 UnimplementedInstruction(instr);
2216 const Register rt = instr->RtField();
2217 const Register rt2 = instr->Rt2Field();
2218 if (instr->Bit(22) != 0) {
2220 const bool is_signed = instr->Bit(30) == 1;
2223 if (instr->Bit(31) == 1) {
2225 val1 = ReadX(address, instr);
2226 val2 = ReadX(address + size, instr);
2229 val1 =
static_cast<int64_t
>(ReadW(address, instr));
2230 val2 =
static_cast<int64_t
>(ReadW(address + size, instr));
2232 val1 =
static_cast<int64_t
>(ReadWU(address, instr));
2233 val2 =
static_cast<int64_t
>(ReadWU(address + size, instr));
2237 if (instr->Bit(31) == 1) {
2238 set_register(instr, rt, val1, R31IsZR);
2239 set_register(instr, rt2, val2, R31IsZR);
2241 set_wregister(rt,
static_cast<int32_t
>(val1), R31IsZR);
2242 set_wregister(rt2,
static_cast<int32_t
>(val2), R31IsZR);
2246 if (instr->Bit(31) == 1) {
2247 const int64_t val1 = get_register(rt, R31IsZR);
2248 const int64_t val2 = get_register(rt2, R31IsZR);
2249 WriteX(address, val1, instr);
2250 WriteX(address + size, val2, instr);
2252 const int32_t val1 = get_wregister(rt, R31IsZR);
2253 const int32_t val2 = get_wregister(rt2, R31IsZR);
2254 WriteW(address, val1, instr);
2255 WriteW(address + size, val2, instr);
2262 set_register(instr, rn, wb_address, R31IsSP);
2266void Simulator::DecodeLoadRegLiteral(Instr* instr) {
2267 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) ||
2268 (instr->Bits(24, 3) != 0)) {
2269 UnimplementedInstruction(instr);
2272 const Register rt = instr->RtField();
2273 const int64_t off = instr->SImm19Field() << 2;
2274 const int64_t pc =
reinterpret_cast<int64_t
>(instr);
2275 const int64_t address = pc + off;
2276 const int64_t val = ReadX(address, instr);
2277 if (instr->Bit(30) != 0) {
2279 set_register(instr, rt, val, R31IsZR);
2282 set_wregister(rt,
static_cast<int32_t
>(val), R31IsZR);
2286void Simulator::DecodeLoadStoreExclusive(Instr* instr) {
2287 if (instr->Bit(21) != 0 || instr->Bit(23) != instr->Bit(15)) {
2290 const int32_t
size = instr->Bits(30, 2);
2291 if (size != 3 && size != 2) {
2294 const Register rs = instr->RsField();
2295 const Register rn = instr->RnField();
2296 const Register rt = instr->RtField();
2297 ASSERT(instr->Rt2Field() == R31);
2298 const bool is_load = instr->Bit(22) == 1;
2299 const bool is_exclusive = instr->Bit(23) == 0;
2300 const bool is_ordered = instr->Bit(15) == 1;
2302 const bool is_load_acquire = !is_exclusive && is_ordered;
2303 if (is_load_acquire) {
2306 const int64_t
addr = get_register(rn, R31IsSP);
2307 const intptr_t
value =
2308 (
size == 3) ? ReadAcquire(addr, instr) : ReadAcquireW(addr, instr);
2309 set_register(instr, rt, value, R31IsZR);
2313 const int64_t
addr = get_register(rn, R31IsSP);
2314 const intptr_t
value = (
size == 3) ? ReadExclusiveX(addr, instr)
2315 : ReadExclusiveW(addr, instr);
2316 set_register(instr, rt, value, R31IsZR);
2319 const bool is_store_release = !is_exclusive && is_ordered;
2320 if (is_store_release) {
2323 const uword value = get_register(rt, R31IsZR);
2324 const uword addr = get_register(rn, R31IsSP);
2326 WriteRelease(addr, value, instr);
2328 WriteReleaseW(addr,
static_cast<uint32_t
>(value), instr);
2332 const uword value = get_register(rt, R31IsZR);
2333 const uword addr = get_register(rn, R31IsSP);
2334 const intptr_t status =
2336 ? WriteExclusiveX(addr, value, instr)
2337 : WriteExclusiveW(addr,
static_cast<uint32_t
>(value), instr);
2338 set_register(instr, rs, status, R31IsSP);
2343void Simulator::DecodeAtomicMemory(Instr* instr) {
2344 const int32_t
size = instr->Bits(30, 2);
2345 std::memory_order order;
2346 switch (instr->Bits(22, 2)) {
2348 order = std::memory_order_acq_rel;
2351 order = std::memory_order_acquire;
2354 order = std::memory_order_release;
2357 order = std::memory_order_relaxed;
2360 const Register rs = instr->RsField();
2361 const Register rn = instr->RnField();
2362 const Register rt = instr->RtField();
2363 const int32_t opc = instr->Bits(12, 3);
2366 uint64_t in = get_register(rs, R31IsZR);
2368 reinterpret_cast<std::atomic<uint64_t>*
>(get_register(rn, R31IsSP));
2372 out =
addr->fetch_and(~in, order);
2375 out =
addr->fetch_or(in, order);
2380 set_register(instr, rt, out, R31IsZR);
2381 }
else if (size == 2) {
2383 uint32_t in = get_wregister(rs, R31IsZR);
2385 reinterpret_cast<std::atomic<uint32_t>*
>(get_register(rn, R31IsSP));
2389 out =
addr->fetch_and(~in, order);
2392 out =
addr->fetch_or(in, order);
2397 set_wregister(rt, out, R31IsZR);
2404void Simulator::DecodeLoadStore(Instr* instr) {
2405 if (instr->IsAtomicMemoryOp()) {
2406 DecodeAtomicMemory(instr);
2407 }
else if (instr->IsLoadStoreRegOp()) {
2408 DecodeLoadStoreReg(instr);
2409 }
else if (instr->IsLoadStoreRegPairOp()) {
2410 DecodeLoadStoreRegPair(instr);
2411 }
else if (instr->IsLoadRegLiteralOp()) {
2412 DecodeLoadRegLiteral(instr);
2413 }
else if (instr->IsLoadStoreExclusiveOp()) {
2414 DecodeLoadStoreExclusive(instr);
2416 UnimplementedInstruction(instr);
2420int64_t Simulator::ShiftOperand(uint8_t reg_size,
2428 switch (shift_type) {
2430 return (
static_cast<uint64_t
>(value) << amount) & mask;
2432 return static_cast<uint64_t
>(
value) >> amount;
2437 int64_t s_value = (value << s_shift) >> s_shift;
2438 return (s_value >> amount) & mask;
2441 if (reg_size == kWRegSizeInBits) {
2444 return (
static_cast<uint64_t
>(value) >> amount) |
2445 ((
static_cast<uint64_t
>(value) & ((1ULL << amount) - 1ULL))
2446 << (reg_size - amount));
2454int64_t Simulator::ExtendOperand(uint8_t reg_size,
2458 switch (extend_type) {
2466 value &= 0xffffffff;
2469 value =
static_cast<int64_t
>(
static_cast<uint64_t
>(
value) << 56) >> 56;
2472 value =
static_cast<int64_t
>(
static_cast<uint64_t
>(
value) << 48) >> 48;
2475 value =
static_cast<int64_t
>(
static_cast<uint64_t
>(
value) << 32) >> 32;
2485 return (
static_cast<uint64_t
>(value) << amount) & mask;
2488int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) {
2489 const Register rm = instr->RmField();
2490 const int64_t rm_val = get_register(rm, R31IsZR);
2491 const uint8_t
size =
2493 if (instr->IsShift()) {
2494 const Shift shift_type = instr->ShiftTypeField();
2495 const uint8_t shift_amount = instr->Imm6Field();
2496 return ShiftOperand(size, rm_val, shift_type, shift_amount);
2498 ASSERT(instr->IsExtend());
2499 const Extend extend_type = instr->ExtendTypeField();
2500 const uint8_t shift_amount = instr->Imm3Field();
2501 return ExtendOperand(size, rm_val, extend_type, shift_amount);
2507void Simulator::DecodeAddSubShiftExt(Instr* instr) {
2510 const bool addition = (instr->Bit(30) == 0);
2511 const Register rd = instr->RdField();
2512 const Register rn = instr->RnField();
2513 const uint64_t rm_val = DecodeShiftExtendOperand(instr);
2514 if (instr->SFField() != 0) {
2516 const uint64_t rn_val = get_register(rn, instr->RnMode());
2517 const uint64_t alu_out = rn_val + (addition ? rm_val : -rm_val);
2518 set_register(instr, rd, alu_out, instr->RdMode());
2519 if (instr->HasS()) {
2520 SetNZFlagsX(alu_out);
2521 SetCFlag(CarryFromX(alu_out, rn_val, rm_val, addition));
2522 SetVFlag(OverflowFromX(alu_out, rn_val, rm_val, addition));
2526 const uint32_t rn_val = get_wregister(rn, instr->RnMode());
2527 uint32_t rm_val32 =
static_cast<uint32_t
>(rm_val &
kWRegMask);
2528 uint32_t carry_in = 0;
2531 rm_val32 = ~rm_val32;
2533 const uint32_t alu_out = rn_val + rm_val32 + carry_in;
2534 set_wregister(rd, alu_out, instr->RdMode());
2535 if (instr->HasS()) {
2536 SetNZFlagsW(alu_out);
2537 SetCFlag(CarryFromW(rn_val, rm_val32, carry_in));
2538 SetVFlag(OverflowFromW(rn_val, rm_val32, carry_in));
2543void Simulator::DecodeAddSubWithCarry(Instr* instr) {
2546 const bool addition = (instr->Bit(30) == 0);
2547 const Register rd = instr->RdField();
2548 const Register rn = instr->RnField();
2549 const Register rm = instr->RmField();
2550 const uint64_t rn_val64 = get_register(rn, R31IsZR);
2551 const uint32_t rn_val32 = get_wregister(rn, R31IsZR);
2552 const uint64_t rm_val64 = get_register(rm, R31IsZR);
2553 uint32_t rm_val32 = get_wregister(rm, R31IsZR);
2554 const uint32_t carry_in = c_flag_ ? 1 : 0;
2555 if (instr->SFField() != 0) {
2557 const uint64_t alu_out =
2558 rn_val64 + (addition ? rm_val64 : ~rm_val64) + carry_in;
2559 set_register(instr, rd, alu_out, R31IsZR);
2560 if (instr->HasS()) {
2561 SetNZFlagsX(alu_out);
2562 SetCFlag(CarryFromX(alu_out, rn_val64, rm_val64, addition));
2563 SetVFlag(OverflowFromX(alu_out, rn_val64, rm_val64, addition));
2568 rm_val32 = ~rm_val32;
2570 const uint32_t alu_out = rn_val32 + rm_val32 + carry_in;
2571 set_wregister(rd, alu_out, R31IsZR);
2572 if (instr->HasS()) {
2573 SetNZFlagsW(alu_out);
2574 SetCFlag(CarryFromW(rn_val32, rm_val32, carry_in));
2575 SetVFlag(OverflowFromW(rn_val32, rm_val32, carry_in));
2580void Simulator::DecodeLogicalShift(Instr* instr) {
2581 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21);
2582 const Register rd = instr->RdField();
2583 const Register rn = instr->RnField();
2584 const int64_t rn_val = get_register(rn, instr->RnMode());
2585 const int64_t rm_val = DecodeShiftExtendOperand(instr);
2586 int64_t alu_out = 0;
2590 alu_out = rn_val & rm_val;
2594 alu_out = rn_val & (~rm_val);
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);
2626 if ((op == 6) || (op == 7)) {
2627 if (instr->SFField() == 1) {
2628 SetNZFlagsX(alu_out);
2630 SetNZFlagsW(alu_out);
2636 if (instr->SFField() == 1) {
2637 set_register(instr, rd, alu_out, instr->RdMode());
2639 set_wregister(rd, alu_out & kWRegMask, instr->RdMode());
2643static int64_t divide64(int64_t top, int64_t bottom,
bool is_signed) {
2652 if ((top ==
static_cast<int64_t
>(0x8000000000000000LL)) &&
2653 (bottom ==
static_cast<int64_t
>(0xffffffffffffffffLL))) {
2654 return static_cast<int64_t
>(0x8000000000000000LL);
2656 return top / bottom;
2659 const uint64_t utop =
static_cast<uint64_t
>(top);
2660 const uint64_t ubottom =
static_cast<uint64_t
>(bottom);
2661 return static_cast<int64_t
>(utop / ubottom);
2665static int32_t divide32(int32_t top, int32_t bottom,
bool is_signed) {
2674 if ((top ==
static_cast<int32_t
>(0x80000000)) &&
2675 (bottom ==
static_cast<int32_t
>(0xffffffff))) {
2676 return static_cast<int32_t
>(0x80000000);
2678 return top / bottom;
2681 const uint32_t utop =
static_cast<uint32_t
>(top);
2682 const uint32_t ubottom =
static_cast<uint32_t
>(bottom);
2683 return static_cast<int32_t
>(utop / ubottom);
2687void Simulator::DecodeMiscDP1Source(Instr* instr) {
2688 if (instr->Bit(29) != 0) {
2689 UnimplementedInstruction(instr);
2692 const Register rd = instr->RdField();
2693 const Register rn = instr->RnField();
2694 const int op = instr->Bits(10, 10);
2695 const int64_t rn_val64 = get_register(rn, R31IsZR);
2696 const int32_t rn_val32 = get_wregister(rn, R31IsZR);
2700 if (instr->SFField() == 1) {
2701 const uint64_t rd_val = Utils::CountLeadingZeros64(rn_val64);
2702 set_register(instr, rd, rd_val, R31IsZR);
2704 const uint32_t rd_val = Utils::CountLeadingZeros32(rn_val32);
2705 set_wregister(rd, rd_val, R31IsZR);
2711 if (instr->SFField() == 1) {
2712 const uint64_t rd_val = Utils::ReverseBits64(rn_val64);
2713 set_register(instr, rd, rd_val, R31IsZR);
2715 const uint32_t rd_val = Utils::ReverseBits32(rn_val32);
2716 set_wregister(rd, rd_val, R31IsZR);
2721 UnimplementedInstruction(instr);
2726void Simulator::DecodeMiscDP2Source(Instr* instr) {
2727 if (instr->Bit(29) != 0) {
2728 UnimplementedInstruction(instr);
2731 const Register rd = instr->RdField();
2732 const Register rn = instr->RnField();
2733 const Register rm = instr->RmField();
2734 const int op = instr->Bits(10, 5);
2735 const int64_t rn_val64 = get_register(rn, R31IsZR);
2736 const int64_t rm_val64 = get_register(rm, R31IsZR);
2737 const int32_t rn_val32 = get_wregister(rn, R31IsZR);
2738 const int32_t rm_val32 = get_wregister(rm, R31IsZR);
2744 const bool is_signed = instr->Bit(10) == 1;
2745 if (instr->SFField() == 1) {
2746 set_register(instr, rd, divide64(rn_val64, rm_val64, is_signed),
2749 set_wregister(rd, divide32(rn_val32, rm_val32, is_signed), R31IsZR);
2755 if (instr->SFField() == 1) {
2756 const uint64_t rn_u64 =
static_cast<uint64_t
>(rn_val64);
2758 set_register(instr, rd, alu_out, R31IsZR);
2760 const uint32_t rn_u32 =
static_cast<uint32_t
>(rn_val32);
2762 set_wregister(rd, alu_out, R31IsZR);
2768 if (instr->SFField() == 1) {
2769 const uint64_t rn_u64 =
static_cast<uint64_t
>(rn_val64);
2771 set_register(instr, rd, alu_out, R31IsZR);
2773 const uint32_t rn_u32 =
static_cast<uint32_t
>(rn_val32);
2775 set_wregister(rd, alu_out, R31IsZR);
2781 if (instr->SFField() == 1) {
2782 const int64_t alu_out = rn_val64 >> (rm_val64 & (
kXRegSizeInBits - 1));
2783 set_register(instr, rd, alu_out, R31IsZR);
2785 const int32_t alu_out = rn_val32 >> (rm_val32 & (
kXRegSizeInBits - 1));
2786 set_wregister(rd, alu_out, R31IsZR);
2791 UnimplementedInstruction(instr);
2796void Simulator::DecodeMiscDP3Source(Instr* instr) {
2797 const Register rd = instr->RdField();
2798 const Register rn = instr->RnField();
2799 const Register rm = instr->RmField();
2800 const Register ra = instr->RaField();
2801 if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) &&
2802 (instr->Bit(15) == 0)) {
2804 if (instr->SFField() == 1) {
2805 const uint64_t rn_val = get_register(rn, R31IsZR);
2806 const uint64_t rm_val = get_register(rm, R31IsZR);
2807 const uint64_t ra_val = get_register(ra, R31IsZR);
2808 const uint64_t alu_out = ra_val + (rn_val * rm_val);
2809 set_register(instr, rd, alu_out, R31IsZR);
2811 const uint32_t rn_val = get_wregister(rn, R31IsZR);
2812 const uint32_t rm_val = get_wregister(rm, R31IsZR);
2813 const uint32_t ra_val = get_wregister(ra, R31IsZR);
2814 const uint32_t alu_out = ra_val + (rn_val * rm_val);
2815 set_wregister(rd, alu_out, R31IsZR);
2817 }
else if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) &&
2818 (instr->Bit(15) == 1)) {
2820 if (instr->SFField() == 1) {
2821 const uint64_t rn_val = get_register(rn, R31IsZR);
2822 const uint64_t rm_val = get_register(rm, R31IsZR);
2823 const uint64_t ra_val = get_register(ra, R31IsZR);
2824 const uint64_t alu_out = ra_val - (rn_val * rm_val);
2825 set_register(instr, rd, alu_out, R31IsZR);
2827 const uint32_t rn_val = get_wregister(rn, R31IsZR);
2828 const uint32_t rm_val = get_wregister(rm, R31IsZR);
2829 const uint32_t ra_val = get_wregister(ra, R31IsZR);
2830 const uint32_t alu_out = ra_val - (rn_val * rm_val);
2831 set_wregister(rd, alu_out, R31IsZR);
2833 }
else if ((instr->Bits(29, 3) == 4) && (instr->Bits(21, 3) == 2) &&
2834 (instr->Bit(15) == 0)) {
2837 const int64_t rn_val = get_register(rn, R31IsZR);
2838 const int64_t rm_val = get_register(rm, R31IsZR);
2839#if defined(DART_HOST_OS_WINDOWS)
2842 Multiply128(rn_val, rm_val, &alu_out);
2844 const __int128 res =
2845 static_cast<__int128
>(rn_val) *
static_cast<__int128
>(rm_val);
2846 const int64_t alu_out =
static_cast<int64_t
>(res >> 64);
2848 set_register(instr, rd, alu_out, R31IsZR);
2849 }
else if ((instr->Bits(29, 3) == 4) && (instr->Bits(21, 3) == 6) &&
2850 (instr->Bit(15) == 0)) {
2853 const uint64_t rn_val = get_register(rn, R31IsZR);
2854 const uint64_t rm_val = get_register(rm, R31IsZR);
2855#if defined(DART_HOST_OS_WINDOWS)
2858 UnsignedMultiply128(rn_val, rm_val, &alu_out);
2860 const unsigned __int128 res =
static_cast<unsigned __int128
>(rn_val) *
2861 static_cast<unsigned __int128
>(rm_val);
2862 const uint64_t alu_out =
static_cast<uint64_t
>(res >> 64);
2864 set_register(instr, rd, alu_out, R31IsZR);
2865 }
else if ((instr->Bits(29, 3) == 4) && (instr->Bit(15) == 0)) {
2866 if (instr->Bits(21, 3) == 5) {
2868 const uint64_t rn_val =
static_cast<uint32_t
>(get_wregister(rn, R31IsZR));
2869 const uint64_t rm_val =
static_cast<uint32_t
>(get_wregister(rm, R31IsZR));
2870 const uint64_t ra_val = get_register(ra, R31IsZR);
2871 const uint64_t alu_out = ra_val + (rn_val * rm_val);
2872 set_register(instr, rd, alu_out, R31IsZR);
2875 const int64_t rn_val =
static_cast<int32_t
>(get_wregister(rn, R31IsZR));
2876 const int64_t rm_val =
static_cast<int32_t
>(get_wregister(rm, R31IsZR));
2877 const int64_t ra_val = get_register(ra, R31IsZR);
2878 const int64_t alu_out = ra_val + (rn_val * rm_val);
2879 set_register(instr, rd, alu_out, R31IsZR);
2882 UnimplementedInstruction(instr);
2886void Simulator::DecodeConditionalSelect(Instr* instr) {
2887 const Register rd = instr->RdField();
2888 const Register rn = instr->RnField();
2889 const Register rm = instr->RmField();
2890 const int64_t rm_val64 = get_register(rm, R31IsZR);
2891 const int32_t rm_val32 = get_wregister(rm, R31IsZR);
2892 const int64_t rn_val64 = get_register(rn, instr->RnMode());
2893 const int32_t rn_val32 = get_wregister(rn, instr->RnMode());
2894 int64_t result64 = 0;
2895 int32_t result32 = 0;
2897 if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 0)) {
2899 result64 = rm_val64;
2900 result32 = rm_val32;
2901 if (ConditionallyExecute(instr)) {
2902 result64 = rn_val64;
2903 result32 = rn_val32;
2905 }
else if ((instr->Bits(29, 2) == 0) && (instr->Bits(10, 2) == 1)) {
2907 result64 = rm_val64 + 1;
2908 result32 = rm_val32 + 1;
2909 if (ConditionallyExecute(instr)) {
2910 result64 = rn_val64;
2911 result32 = rn_val32;
2913 }
else if ((instr->Bits(29, 2) == 2) && (instr->Bits(10, 2) == 0)) {
2915 result64 = ~rm_val64;
2916 result32 = ~rm_val32;
2917 if (ConditionallyExecute(instr)) {
2918 result64 = rn_val64;
2919 result32 = rn_val32;
2921 }
else if ((instr->Bits(29, 2) == 2) && (instr->Bits(10, 2) == 1)) {
2923 result64 = -rm_val64;
2924 result32 = -rm_val32;
2925 if (ConditionallyExecute(instr)) {
2926 result64 = rn_val64;
2927 result32 = rn_val32;
2930 UnimplementedInstruction(instr);
2934 if (instr->SFField() == 1) {
2935 set_register(instr, rd, result64, instr->RdMode());
2937 set_wregister(rd, result32, instr->RdMode());
2941void Simulator::DecodeDPRegister(Instr* instr) {
2942 if (instr->IsAddSubShiftExtOp()) {
2943 DecodeAddSubShiftExt(instr);
2944 }
else if (instr->IsAddSubWithCarryOp()) {
2945 DecodeAddSubWithCarry(instr);
2946 }
else if (instr->IsLogicalShiftOp()) {
2947 DecodeLogicalShift(instr);
2948 }
else if (instr->IsMiscDP1SourceOp()) {
2949 DecodeMiscDP1Source(instr);
2950 }
else if (instr->IsMiscDP2SourceOp()) {
2951 DecodeMiscDP2Source(instr);
2952 }
else if (instr->IsMiscDP3SourceOp()) {
2953 DecodeMiscDP3Source(instr);
2954 }
else if (instr->IsConditionalSelectOp()) {
2955 DecodeConditionalSelect(instr);
2957 UnimplementedInstruction(instr);
2961void Simulator::DecodeSIMDCopy(Instr* instr) {
2962 const int32_t
Q = instr->Bit(30);
2963 const int32_t op = instr->Bit(29);
2964 const int32_t imm4 = instr->Bits(11, 4);
2965 const int32_t imm5 = instr->Bits(16, 5);
2969 int32_t element_bytes;
2970 if ((imm5 & 0x1) != 0) {
2974 }
else if ((imm5 & 0x2) != 0) {
2978 }
else if ((imm5 & 0x4) != 0) {
2982 }
else if ((imm5 & 0x8) != 0) {
2987 UnimplementedInstruction(instr);
2990 ASSERT((idx4 != -1) && (idx5 != -1));
2994 const Register rn = instr->RnField();
2995 const Register rd = instr->RdField();
2996 if ((op == 0) && (imm4 == 7)) {
2999 set_wregister(rd, get_vregisters(vn, idx5), R31IsZR);
3002 set_register(instr, rd, get_vregisterd(vn, idx5), R31IsZR);
3004 }
else if ((Q == 1) && (op == 0) && (imm4 == 0)) {
3006 if (element_bytes == 4) {
3007 for (
int i = 0; i < 4; i++) {
3008 set_vregisters(vd, i, get_vregisters(vn, idx5));
3010 }
else if (element_bytes == 8) {
3011 for (
int i = 0; i < 2; i++) {
3012 set_vregisterd(vd, i, get_vregisterd(vn, idx5));
3015 UnimplementedInstruction(instr);
3018 }
else if ((Q == 1) && (op == 0) && (imm4 == 3)) {
3020 if (element_bytes == 4) {
3021 set_vregisters(vd, idx5, get_wregister(rn, R31IsZR));
3022 }
else if (element_bytes == 8) {
3023 set_vregisterd(vd, idx5, get_register(rn, R31IsZR));
3025 UnimplementedInstruction(instr);
3027 }
else if ((Q == 1) && (op == 0) && (imm4 == 1)) {
3029 if (element_bytes == 4) {
3030 for (
int i = 0; i < 4; i++) {
3031 set_vregisters(vd, i, get_wregister(rn, R31IsZR));
3033 }
else if (element_bytes == 8) {
3034 for (
int i = 0; i < 2; i++) {
3035 set_vregisterd(vd, i, get_register(rn, R31IsZR));
3038 UnimplementedInstruction(instr);
3041 }
else if ((Q == 1) && (op == 1)) {
3043 if (element_bytes == 4) {
3044 set_vregisters(vd, idx5, get_vregisters(vn, idx4));
3045 }
else if (element_bytes == 8) {
3046 set_vregisterd(vd, idx5, get_vregisterd(vn, idx4));
3048 UnimplementedInstruction(instr);
3051 UnimplementedInstruction(instr);
3055static float vminf(
float f1,
float f2) {
3058 return signbit(f1) ? f1 : f2;
3060 return f1 > f2 ? f2 : f1;
3063static float vmaxf(
float f1,
float f2) {
3066 return signbit(f1) ? f2 : f1;
3068 return f1 < f2 ? f2 : f1;
3071static double vmind(
double f1,
double f2) {
3074 return signbit(f1) ? f1 : f2;
3076 return f1 > f2 ? f2 : f1;
3079static double vmaxd(
double f1,
double f2) {
3082 return signbit(f1) ? f2 : f1;
3084 return f1 < f2 ? f2 : f1;
3087void Simulator::DecodeSIMDThreeSame(Instr* instr) {
3088 const int Q = instr->Bit(30);
3089 const int U = instr->Bit(29);
3090 const int opcode = instr->Bits(11, 5);
3093 UnimplementedInstruction(instr);
3100 if (instr->Bit(22) == 0) {
3102 for (
int idx = 0; idx < 4; idx++) {
3103 const int32_t vn_val = get_vregisters(vn, idx);
3104 const int32_t vm_val = get_vregisters(vm, idx);
3105 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3106 const float vm_flt = bit_cast<float, int32_t>(vm_val);
3108 if ((U == 0) && (opcode == 0x3)) {
3109 if (instr->Bit(23) == 0) {
3111 res = vn_val & vm_val;
3114 res = vn_val | vm_val;
3116 }
else if ((U == 1) && (opcode == 0x3)) {
3118 res = vn_val ^ vm_val;
3119 }
else if ((U == 0) && (opcode == 0x10)) {
3121 res = vn_val + vm_val;
3122 }
else if ((U == 1) && (opcode == 0x10)) {
3124 res = vn_val - vm_val;
3125 }
else if ((U == 0) && (opcode == 0x1a)) {
3126 if (instr->Bit(23) == 0) {
3128 res = bit_cast<int32_t, float>(vn_flt + vm_flt);
3131 res = bit_cast<int32_t, float>(vn_flt - vm_flt);
3133 }
else if ((U == 1) && (opcode == 0x1b)) {
3135 res = bit_cast<int32_t, float>(vn_flt * vm_flt);
3136 }
else if ((U == 1) && (opcode == 0x1f)) {
3138 res = bit_cast<int32_t, float>(vn_flt / vm_flt);
3139 }
else if ((U == 0) && (opcode == 0x1c)) {
3141 res = (vn_flt == vm_flt) ? 0xffffffff : 0;
3142 }
else if ((U == 1) && (opcode == 0x1c)) {
3143 if (instr->Bit(23) == 1) {
3145 res = (vn_flt > vm_flt) ? 0xffffffff : 0;
3148 res = (vn_flt >= vm_flt) ? 0xffffffff : 0;
3150 }
else if ((U == 0) && (opcode == 0x1e)) {
3151 if (instr->Bit(23) == 1) {
3153 const float m = vminf(vn_flt, vm_flt);
3154 res = bit_cast<int32_t, float>(m);
3157 const float m = vmaxf(vn_flt, vm_flt);
3158 res = bit_cast<int32_t, float>(m);
3160 }
else if ((U == 0) && (opcode == 0x1f)) {
3161 if (instr->Bit(23) == 0) {
3163 res = bit_cast<int32_t, float>(2.0 - (vn_flt * vm_flt));
3166 res = bit_cast<int32_t, float>((3.0 - vn_flt * vm_flt) / 2.0);
3169 UnimplementedInstruction(instr);
3172 set_vregisters(vd, idx, res);
3176 for (
int idx = 0; idx < 2; idx++) {
3177 const int64_t vn_val = get_vregisterd(vn, idx);
3178 const int64_t vm_val = get_vregisterd(vm, idx);
3179 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3180 const double vm_dbl = bit_cast<double, int64_t>(vm_val);
3182 if ((U == 0) && (opcode == 0x3)) {
3183 if (instr->Bit(23) == 0) {
3185 res = vn_val & vm_val;
3188 res = vn_val | vm_val;
3190 }
else if ((U == 1) && (opcode == 0x3)) {
3192 res = vn_val ^ vm_val;
3193 }
else if ((U == 0) && (opcode == 0x10)) {
3195 res = vn_val + vm_val;
3196 }
else if ((U == 1) && (opcode == 0x10)) {
3198 res = vn_val - vm_val;
3199 }
else if ((U == 0) && (opcode == 0x1a)) {
3200 if (instr->Bit(23) == 0) {
3202 res = bit_cast<int64_t, double>(vn_dbl + vm_dbl);
3205 res = bit_cast<int64_t, double>(vn_dbl - vm_dbl);
3207 }
else if ((U == 1) && (opcode == 0x1b)) {
3209 res = bit_cast<int64_t, double>(vn_dbl * vm_dbl);
3210 }
else if ((U == 1) && (opcode == 0x1f)) {
3212 res = bit_cast<int64_t, double>(vn_dbl / vm_dbl);
3213 }
else if ((U == 0) && (opcode == 0x1c)) {
3215 res = (vn_dbl == vm_dbl) ? 0xffffffffffffffffLL : 0;
3216 }
else if ((U == 1) && (opcode == 0x1c)) {
3217 if (instr->Bit(23) == 1) {
3219 res = (vn_dbl > vm_dbl) ? 0xffffffffffffffffLL : 0;
3222 res = (vn_dbl >= vm_dbl) ? 0xffffffffffffffffLL : 0;
3224 }
else if ((U == 0) && (opcode == 0x1e)) {
3225 if (instr->Bit(23) == 1) {
3227 const double m = vmind(vn_dbl, vm_dbl);
3228 res = bit_cast<int64_t, double>(m);
3231 const double m = vmaxd(vn_dbl, vm_dbl);
3232 res = bit_cast<int64_t, double>(m);
3235 UnimplementedInstruction(instr);
3238 set_vregisterd(vd, idx, res);
3243static float arm_reciprocal_sqrt_estimate(
float a) {
3245 if (isinf(
a) || (fabs(
a) >= exp2f(126)))
3252 uint32_t a_bits = bit_cast<uint32_t, float>(
a);
3254 if (((a_bits >> 23) & 1) != 0) {
3256 scaled = (
static_cast<uint64_t
>(0x3fd) << 52) |
3257 ((
static_cast<uint64_t
>(a_bits) & 0x7fffff) << 29);
3260 scaled = (
static_cast<uint64_t
>(0x3fe) << 52) |
3261 ((
static_cast<uint64_t
>(a_bits) & 0x7fffff) << 29);
3264 int32_t result_exp = (380 - ((a_bits >> 23) & 0xff)) / 2;
3266 double scaled_d = bit_cast<double, uint64_t>(scaled);
3267 ASSERT((scaled_d >= 0.25) && (scaled_d < 1.0));
3270 if (scaled_d < 0.5) {
3274 int32_t q0 =
static_cast<int32_t
>(scaled_d * 512.0);
3276 r = 1.0 /
sqrt((
static_cast<double>(q0) + 0.5) / 512.0);
3281 int32_t q1 =
static_cast<int32_t
>(scaled_d * 256.0);
3283 r = 1.0 /
sqrt((
static_cast<double>(q1) + 0.5) / 256.0);
3286 int32_t
s =
static_cast<int>(256.0 * r + 0.5);
3287 double estimate =
static_cast<double>(
s) / 256.0;
3288 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0)));
3291 int32_t result_bits =
3292 ((result_exp & 0xff) << 23) |
3293 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
3294 return bit_cast<float, int32_t>(result_bits);
3297static float arm_recip_estimate(
float a) {
3299 if (isinf(
a) || (fabs(
a) >= exp2f(126)))
3306 uint32_t a_bits = bit_cast<uint32_t, float>(
a);
3308 uint64_t scaled = (
static_cast<uint64_t
>(0x3fe) << 52) |
3309 ((
static_cast<uint64_t
>(a_bits) & 0x7fffff) << 29);
3311 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff);
3312 ASSERT((result_exp >= 1) && (result_exp <= 252));
3314 double scaled_d = bit_cast<double, uint64_t>(scaled);
3315 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0));
3318 int32_t q =
static_cast<int32_t
>(scaled_d * 512.0);
3320 double r = 1.0 / ((
static_cast<double>(q) + 0.5) / 512.0);
3322 int32_t
s =
static_cast<int32_t
>(256.0 * r + 0.5);
3323 double estimate =
static_cast<double>(
s) / 256.0;
3324 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0)));
3327 int32_t result_bits =
3328 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) |
3329 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
3330 return bit_cast<float, int32_t>(result_bits);
3333void Simulator::DecodeSIMDTwoReg(Instr* instr) {
3334 const int32_t
Q = instr->Bit(30);
3335 const int32_t
U = instr->Bit(29);
3336 const int32_t op = instr->Bits(12, 5);
3337 const int32_t sz = instr->Bits(22, 2);
3342 UnimplementedInstruction(instr);
3346 if ((U == 1) && (op == 5)) {
3348 for (
int i = 0; i < 2; i++) {
3349 set_vregisterd(vd, i, ~get_vregisterd(vn, i));
3351 }
else if ((U == 0) && (op == 0xf)) {
3354 for (
int i = 0; i < 4; i++) {
3355 const int32_t vn_val = get_vregisters(vn, i);
3356 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3357 set_vregisters(vd, i, bit_cast<int32_t, float>(fabsf(vn_flt)));
3359 }
else if (sz == 3) {
3361 for (
int i = 0; i < 2; i++) {
3362 const int64_t vn_val = get_vregisterd(vn, i);
3363 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3364 set_vregisterd(vd, i, bit_cast<int64_t, double>(fabs(vn_dbl)));
3367 UnimplementedInstruction(instr);
3369 }
else if ((U == 1) && (op == 0xf)) {
3372 for (
int i = 0; i < 4; i++) {
3373 const int32_t vn_val = get_vregisters(vn, i);
3374 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3375 set_vregisters(vd, i, bit_cast<int32_t, float>(-vn_flt));
3377 }
else if (sz == 3) {
3379 for (
int i = 0; i < 2; i++) {
3380 const int64_t vn_val = get_vregisterd(vn, i);
3381 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3382 set_vregisterd(vd, i, bit_cast<int64_t, double>(-vn_dbl));
3385 UnimplementedInstruction(instr);
3387 }
else if ((U == 1) && (op == 0x1f)) {
3390 for (
int i = 0; i < 4; i++) {
3391 const int32_t vn_val = get_vregisters(vn, i);
3392 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3393 set_vregisters(vd, i, bit_cast<int32_t, float>(sqrtf(vn_flt)));
3395 }
else if (sz == 3) {
3397 for (
int i = 0; i < 2; i++) {
3398 const int64_t vn_val = get_vregisterd(vn, i);
3399 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3400 set_vregisterd(vd, i, bit_cast<int64_t, double>(
sqrt(vn_dbl)));
3403 UnimplementedInstruction(instr);
3405 }
else if ((U == 0) && (op == 0x1d)) {
3407 UnimplementedInstruction(instr);
3411 for (
int i = 0; i < 4; i++) {
3412 const int32_t vn_val = get_vregisters(vn, i);
3413 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3414 const float re = arm_recip_estimate(vn_flt);
3415 set_vregisters(vd, i, bit_cast<int32_t, float>(re));
3417 }
else if ((U == 1) && (op == 0x1d)) {
3419 UnimplementedInstruction(instr);
3423 for (
int i = 0; i < 4; i++) {
3424 const int32_t vn_val = get_vregisters(vn, i);
3425 const float vn_flt = bit_cast<float, int32_t>(vn_val);
3426 const float re = arm_reciprocal_sqrt_estimate(vn_flt);
3427 set_vregisters(vd, i, bit_cast<int32_t, float>(re));
3430 UnimplementedInstruction(instr);
3434void Simulator::DecodeDPSimd1(Instr* instr) {
3435 if (instr->IsSIMDCopyOp()) {
3436 DecodeSIMDCopy(instr);
3437 }
else if (instr->IsSIMDThreeSameOp()) {
3438 DecodeSIMDThreeSame(instr);
3439 }
else if (instr->IsSIMDTwoRegOp()) {
3440 DecodeSIMDTwoReg(instr);
3442 UnimplementedInstruction(instr);
3446void Simulator::DecodeFPImm(Instr* instr) {
3447 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) ||
3448 (instr->Bits(5, 5) != 0)) {
3449 UnimplementedInstruction(instr);
3452 if (instr->Bit(22) == 1) {
3456 const int64_t immd = Instr::VFPExpandImm(instr->Imm8Field());
3457 set_vregisterd(vd, 0, immd);
3458 set_vregisterd(vd, 1, 0);
3461 UnimplementedInstruction(instr);
3465void Simulator::DecodeFPIntCvt(Instr* instr) {
3468 const Register rd = instr->RdField();
3469 const Register rn = instr->RnField();
3471 if (instr->Bit(29) != 0) {
3472 UnimplementedInstruction(instr);
3476 if ((instr->SFField() == 0) && (instr->Bits(22, 2) == 0)) {
3477 if (instr->Bits(16, 5) == 6) {
3479 const int32_t vn_val = get_vregisters(vn, 0);
3480 set_wregister(rd, vn_val, R31IsZR);
3481 }
else if (instr->Bits(16, 5) == 7) {
3483 const int32_t rn_val = get_wregister(rn, R31IsZR);
3484 set_vregisters(vd, 0, rn_val);
3485 set_vregisters(vd, 1, 0);
3486 set_vregisters(vd, 2, 0);
3487 set_vregisters(vd, 3, 0);
3489 UnimplementedInstruction(instr);
3491 }
else if (instr->Bits(22, 2) == 1) {
3492 if (instr->Bits(16, 5) == 2) {
3494 const int64_t rn_val64 = get_register(rn, instr->RnMode());
3495 const int32_t rn_val32 = get_wregister(rn, instr->RnMode());
3496 const double vn_dbl = (instr->SFField() == 1)
3497 ?
static_cast<double>(rn_val64)
3498 :
static_cast<double>(rn_val32);
3499 set_vregisterd(vd, 0, bit_cast<int64_t, double>(vn_dbl));
3500 set_vregisterd(vd, 1, 0);
3501 }
else if (instr->Bits(16, 5) == 6) {
3503 const int64_t vn_val = get_vregisterd(vn, 0);
3504 set_register(instr, rd, vn_val, R31IsZR);
3505 }
else if (instr->Bits(16, 5) == 7) {
3507 const int64_t rn_val = get_register(rn, R31IsZR);
3508 set_vregisterd(vd, 0, rn_val);
3509 set_vregisterd(vd, 1, 0);
3510 }
else if ((instr->Bits(16, 5) == 8) || (instr->Bits(16, 5) == 16) ||
3511 (instr->Bits(16, 5) == 24)) {
3512 const intptr_t
max = instr->Bit(31) == 1 ? INT64_MAX : INT32_MAX;
3513 const intptr_t
min = instr->Bit(31) == 1 ? INT64_MIN : INT32_MIN;
3514 double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
3515 switch (instr->Bits(16, 5)) {
3518 vn_val =
ceil(vn_val);
3522 vn_val =
floor(vn_val);
3529 if (vn_val >=
static_cast<double>(
max)) {
3531 }
else if (vn_val <=
static_cast<double>(
min)) {
3534 result =
static_cast<int64_t
>(vn_val);
3536 if (instr->Bit(31) == 1) {
3537 set_register(instr, rd,
result, instr->RdMode());
3539 set_register(instr, rd,
result & 0xffffffffll, instr->RdMode());
3542 UnimplementedInstruction(instr);
3545 UnimplementedInstruction(instr);
3549void Simulator::DecodeFPOneSource(Instr* instr) {
3550 const int opc = instr->Bits(15, 6);
3553 const int64_t vn_val = get_vregisterd(vn, 0);
3554 const int32_t vn_val32 = vn_val &
kWRegMask;
3555 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
3556 const float vn_flt = bit_cast<float, int32_t>(vn_val32);
3558 if ((opc != 5) && (instr->Bit(22) != 1)) {
3561 UnimplementedInstruction(instr);
3565 int64_t res_val = 0;
3569 res_val = get_vregisterd(vn, 0);
3573 res_val = bit_cast<int64_t, double>(fabs(vn_dbl));
3577 res_val = bit_cast<int64_t, double>(-vn_dbl);
3581 res_val = bit_cast<int64_t, double>(
sqrt(vn_dbl));
3585 const uint32_t val =
3586 bit_cast<uint32_t, float>(
static_cast<float>(vn_dbl));
3587 res_val =
static_cast<int64_t
>(val);
3592 res_val = bit_cast<int64_t, double>(
static_cast<double>(vn_flt));
3595 UnimplementedInstruction(instr);
3599 set_vregisterd(vd, 0, res_val);
3600 set_vregisterd(vd, 1, 0);
3603void Simulator::DecodeFPTwoSource(Instr* instr) {
3604 if (instr->Bits(22, 2) != 1) {
3605 UnimplementedInstruction(instr);
3611 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
3612 const double vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0));
3613 const int opc = instr->Bits(12, 4);
3619 result = vn_val * vm_val;
3623 result = vn_val / vm_val;
3627 result = vn_val + vm_val;
3631 result = vn_val - vm_val;
3634 UnimplementedInstruction(instr);
3638 set_vregisterd(vd, 0, bit_cast<int64_t, double>(
result));
3639 set_vregisterd(vd, 1, 0);
3642void Simulator::DecodeFPCompare(Instr* instr) {
3645 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
3648 if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 0)) {
3650 vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0));
3651 }
else if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 1)) {
3652 if (instr->VmField() == V0) {
3656 UnimplementedInstruction(instr);
3660 UnimplementedInstruction(instr);
3669 if (isnan(vn_val) || isnan(vm_val)) {
3672 }
else if (vn_val == vm_val) {
3675 }
else if (vn_val < vm_val) {
3682void Simulator::DecodeFP(Instr* instr) {
3683 if (instr->IsFPImmOp()) {
3685 }
else if (instr->IsFPIntCvtOp()) {
3686 DecodeFPIntCvt(instr);
3687 }
else if (instr->IsFPOneSourceOp()) {
3688 DecodeFPOneSource(instr);
3689 }
else if (instr->IsFPTwoSourceOp()) {
3690 DecodeFPTwoSource(instr);
3691 }
else if (instr->IsFPCompareOp()) {
3692 DecodeFPCompare(instr);
3694 UnimplementedInstruction(instr);
3698void Simulator::DecodeDPSimd2(Instr* instr) {
3699 if (instr->IsFPOp()) {
3702 UnimplementedInstruction(instr);
3708void Simulator::InstructionDecodeImpl(Instr* instr) {
3709 pc_modified_ =
false;
3711 if (instr->IsLoadStoreOp()) {
3712 DecodeLoadStore(instr);
3713 }
else if (instr->IsDPImmediateOp()) {
3714 DecodeDPImmediate(instr);
3715 }
else if (instr->IsCompareBranchOp()) {
3716 DecodeCompareBranch(instr);
3717 }
else if (instr->IsDPRegisterOp()) {
3718 DecodeDPRegister(instr);
3719 }
else if (instr->IsDPSimd1Op()) {
3720 DecodeDPSimd1(instr);
3721 }
else if (instr->IsDPSimd2Op()) {
3722 DecodeDPSimd2(instr);
3724 UnimplementedInstruction(instr);
3727 if (!pc_modified_) {
3728 set_pc(
reinterpret_cast<int64_t
>(instr) + Instr::kInstrSize);
3732void Simulator::InstructionDecode(Instr* instr) {
3733 if (IsTracingExecution()) {
3737 if (FLAG_support_disassembler) {
3738 Disassembler::Disassemble(
start,
end);
3740 THR_Print(
"Disassembler not supported in this mode.\n");
3743 InstructionDecodeImpl(instr);
3746void Simulator::Execute() {
3747 if (
LIKELY(FLAG_stop_sim_at == ULLONG_MAX &&
3748 FLAG_trace_sim_after == ULLONG_MAX)) {
3755void Simulator::ExecuteNoTrace() {
3758 uword program_counter = get_pc();
3762 while (program_counter != kEndSimulatingPC) {
3763 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3765 InstructionDecodeImpl(instr);
3766 program_counter = get_pc();
3770void Simulator::ExecuteTrace() {
3773 uword program_counter = get_pc();
3777 while (program_counter != kEndSimulatingPC) {
3778 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3780 if (icount_ == FLAG_stop_sim_at) {
3781 SimulatorDebugger dbg(
this);
3782 dbg.Stop(instr,
"Instruction count reached");
3783 }
else if (
reinterpret_cast<uint64_t
>(instr) == FLAG_stop_sim_at) {
3784 SimulatorDebugger dbg(
this);
3785 dbg.Stop(instr,
"Instruction address reached");
3786 }
else if (IsIllegalAddress(program_counter)) {
3787 HandleIllegalAccess(program_counter, instr);
3789 InstructionDecode(instr);
3791 program_counter = get_pc();
3795int64_t Simulator::Call(int64_t entry,
3803 const intptr_t sp_before_call = get_register(R31, R31IsSP);
3807 set_vregisterd(V0, 0, parameter0);
3808 set_vregisterd(V0, 1, 0);
3809 set_vregisterd(V1, 0, parameter1);
3810 set_vregisterd(V1, 1, 0);
3811 set_vregisterd(V2, 0, parameter2);
3812 set_vregisterd(V2, 1, 0);
3813 set_vregisterd(V3, 0, parameter3);
3814 set_vregisterd(V3, 1, 0);
3816 set_register(
nullptr, R0, parameter0);
3817 set_register(
nullptr, R1, parameter1);
3818 set_register(
nullptr, R2, parameter2);
3819 set_register(
nullptr, R3, parameter3);
3823 intptr_t stack_pointer = sp_before_call;
3824 if (OS::ActivationFrameAlignment() > 1) {
3826 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
3828 set_register(
nullptr, R31, stack_pointer, R31IsSP);
3835 set_register(
nullptr,
LR, kEndSimulatingPC);
3841 const double dicount =
static_cast<double>(icount_);
3842 const int64_t callee_saved_value = bit_cast<int64_t, double>(dicount);
3846 set_register(
nullptr, r, callee_saved_value);
3854 set_vregisterd(r, 0, callee_saved_value);
3855 set_vregisterd(r, 1, 0);
3865 ASSERT(callee_saved_value == get_register(r));
3866 set_register(
nullptr, r, preserved_vals[i - kAbiFirstPreservedCpuReg]);
3871 ASSERT(callee_saved_value == get_vregisterd(r, 0));
3872 set_vregisterd(r, 0, preserved_dvals[i - kAbiFirstPreservedFpuReg]);
3873 set_vregisterd(r, 1, 0);
3877 set_register(
nullptr, R31, sp_before_call, R31IsSP);
3878 int64_t return_value;
3880 return_value = get_vregisterd(V0, 0);
3882 return_value = get_register(R0);
3884 return return_value;
3887void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
3890 SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
3891 while (buf->link() !=
nullptr && buf->link()->sp() <= sp) {
3899 StackResource::Unwind(thread);
3904 set_pc(
static_cast<int64_t
>(pc));
3905 set_register(
nullptr, SP,
static_cast<int64_t
>(sp));
3906 set_register(
nullptr, FP,
static_cast<int64_t
>(fp));
3907 set_register(
nullptr, THR,
reinterpret_cast<int64_t
>(thread));
3908 set_register(
nullptr, R31, thread->saved_stack_limit() - 4096);
3909#if defined(DART_TARGET_OS_FUCHSIA)
3910 set_register(
nullptr, R18, thread->saved_shadow_call_stack());
3913 thread->set_vm_tag(VMTag::kDartTagId);
3915 thread->set_top_exit_frame_info(0);
3918 *
reinterpret_cast<int64_t*
>(
fp + kPcMarkerSlotFromFp *
kWordSize);
3919 int64_t pp = FLAG_precompiled_mode
3920 ?
static_cast<int64_t
>(thread->global_object_pool())
3921 : *reinterpret_cast<int64_t*>(
3924 set_register(
nullptr, CODE_REG, code);
3925 set_register(
nullptr, PP, pp);
3928 (thread->write_barrier_mask() << 32) | (thread->heap_base() >> 32));
3929 set_register(
nullptr, NULL_REG,
static_cast<int64_t
>(Object::null()));
3930 if (FLAG_precompiled_mode) {
3931 set_register(
nullptr, DISPATCH_TABLE_REG,
3932 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
static const uint8_t buffer[]
uint32_t uint32_t * format
#define DEFINE_FLAG(type, name, default_value, comment)
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)
bool Contains(const Container &container, const Value &value)
const QRegister kAbiLastPreservedFpuReg
const int kXRegSizeInBits
static int64_t GetValue(Dart_Handle arg)
void SetBreakpoint(Dart_NativeArguments args)
const int kNumberOfFpuRegisters
intx_t sign_extend(int32_t x)
const Register kAbiLastPreservedCpuReg
const int kAbiPreservedCpuRegCount
const Register kAbiFirstPreservedCpuReg
const int kAbiPreservedFpuRegCount
const int kWRegSizeInBits
constexpr intptr_t kWordSize
const QRegister kAbiFirstPreservedFpuReg
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
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)