9#if defined(TARGET_ARCH_ARM)
12#if defined(USING_SIMULATOR)
34 "Trace simulator execution after instruction count reached.");
38 "Instruction address or instruction count to stop simulator at.");
51class SimulatorSetjmpBuffer {
55 simulator_->set_last_setjmp_buffer(
this);
59 explicit SimulatorSetjmpBuffer(Simulator* sim) {
61 link_ = sim->last_setjmp_buffer();
62 sim->set_last_setjmp_buffer(
this);
63 sp_ =
static_cast<uword>(sim->get_register(SP));
66 ~SimulatorSetjmpBuffer() {
67 ASSERT(simulator_->last_setjmp_buffer() ==
this);
68 simulator_->set_last_setjmp_buffer(link_);
71 SimulatorSetjmpBuffer*
link() {
return link_; }
73 uword sp() {
return sp_; }
77 Simulator* simulator_;
78 SimulatorSetjmpBuffer* link_;
81 friend class Simulator;
86class SimulatorDebugger {
88 explicit SimulatorDebugger(Simulator* sim);
91 void Stop(Instr* instr,
const char*
message);
93 char* ReadLine(
const char* prompt);
98 bool GetValue(
char* desc, uint32_t* value);
99 bool GetFValue(
char* desc,
float* value);
100 bool GetDValue(
char* desc,
double* value);
102 static TokenPosition GetApproximateTokenIndex(
const Code& code, uword pc);
104 static void PrintDartFrame(uword vm_instructions,
105 uword isolate_instructions,
110 TokenPosition token_pos,
113 void PrintBacktrace();
117 bool DeleteBreakpoint(Instr* breakpc);
121 void UndoBreakpoints();
122 void RedoBreakpoints();
125SimulatorDebugger::SimulatorDebugger(Simulator* sim) {
129SimulatorDebugger::~SimulatorDebugger() {}
131void SimulatorDebugger::Stop(Instr* instr,
const char*
message) {
136static Register LookupCpuRegisterByName(
const char*
name) {
137 static const char*
const kNames[] = {
138 "r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
"r8",
"r9",
"r10",
139 "r11",
"r12",
"r13",
"r14",
"r15",
"pc",
"lr",
"sp",
"ip",
"fp",
"pp"};
144 for (
unsigned i = 0; i <
ARRAY_SIZE(kNames); i++) {
145 if (strcmp(kNames[i],
name) == 0) {
146 return kRegisters[i];
154 bool ok = SScanF(
name,
"s%d", ®_nr);
163 bool ok = SScanF(
name,
"d%d", ®_nr);
170bool SimulatorDebugger::GetValue(
char* desc, uint32_t* value) {
171 Register reg = LookupCpuRegisterByName(desc);
174 *
value = sim_->get_pc();
176 *
value = sim_->get_register(reg);
180 if (desc[0] ==
'*') {
183 if (Simulator::IsIllegalAddress(addr)) {
186 *
value = *(
reinterpret_cast<uint32_t*
>(
addr));
190 bool retval = SScanF(desc,
"0x%x", value) == 1;
192 retval = SScanF(desc,
"%x", value) == 1;
197bool SimulatorDebugger::GetFValue(
char* desc,
float* value) {
198 SRegister sreg = LookupSRegisterByName(desc);
200 *
value = sim_->get_sregister(sreg);
203 if (desc[0] ==
'*') {
206 if (Simulator::IsIllegalAddress(addr)) {
209 *
value = *(
reinterpret_cast<float*
>(
addr));
216bool SimulatorDebugger::GetDValue(
char* desc,
double* value) {
217 DRegister dreg = LookupDRegisterByName(desc);
219 *
value = sim_->get_dregister(dreg);
222 if (desc[0] ==
'*') {
225 if (Simulator::IsIllegalAddress(addr)) {
228 *
value = *(
reinterpret_cast<double*
>(
addr));
235TokenPosition SimulatorDebugger::GetApproximateTokenIndex(
const Code& code,
237 TokenPosition token_pos = TokenPosition::kNoSource;
238 uword pc_offset = pc -
code.PayloadStart();
239 const PcDescriptors& descriptors =
241 PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
242 while (iter.MoveNext()) {
243 if (iter.PcOffset() == pc_offset) {
244 return iter.TokenPos();
245 }
else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) {
246 token_pos = iter.TokenPos();
252#if defined(DART_PRECOMPILED_RUNTIME)
253static const char* ImageName(
uword vm_instructions,
254 uword isolate_instructions,
257 const Image vm_image(vm_instructions);
258 const Image isolate_image(isolate_instructions);
259 if (vm_image.contains(pc)) {
260 *
offset = pc - vm_instructions;
262 }
else if (isolate_image.contains(pc)) {
263 *
offset = pc - isolate_instructions;
272void SimulatorDebugger::PrintDartFrame(
uword vm_instructions,
273 uword isolate_instructions,
278 TokenPosition token_pos,
284 intptr_t
line, column;
285 if (
script.GetTokenLocation(token_pos, &line, &column)) {
287 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
288 fp, sp, is_optimized ? (is_inlined ?
"inlined " :
"optimized ") :
"",
289 func_name.ToCString(), url.ToCString(),
line, column);
293 is_optimized ? (is_inlined ?
"inlined " :
"optimized ") :
"",
294 func_name.ToCString(), url.ToCString());
296#if defined(DART_PRECOMPILED_RUNTIME)
298 auto const symbol_name =
299 ImageName(vm_instructions, isolate_instructions, pc, &
offset);
305void SimulatorDebugger::PrintBacktrace() {
307 auto const Z =
T->zone();
308#if defined(DART_PRECOMPILED_RUNTIME)
309 auto const vm_instructions =
reinterpret_cast<uword>(
311 auto const isolate_instructions =
reinterpret_cast<uword>(
312 T->isolate_group()->source()->snapshot_instructions);
314 vm_instructions, isolate_instructions);
316 const uword vm_instructions = 0;
317 const uword isolate_instructions = 0;
319 StackFrameIterator frames(sim_->get_register(
FP), sim_->get_register(
SP),
323 StackFrame*
frame = frames.NextFrame();
329 while (
frame !=
nullptr) {
330 if (
frame->IsDartFrame()) {
333 if (
code.is_optimized()) {
336 InlinedFunctionsIterator it(code,
frame->pc());
340 inlined_function = it.function();
341 unoptimized_code = it.code();
342 uword unoptimized_pc = it.pc();
346 vm_instructions, isolate_instructions, unoptimized_pc,
348 GetApproximateTokenIndex(unoptimized_code, unoptimized_pc),
354 PrintDartFrame(vm_instructions, isolate_instructions,
frame->pc(),
356 GetApproximateTokenIndex(code,
frame->pc()),
357 code.is_optimized(),
false);
361 frame->IsEntryFrame() ?
"entry"
362 :
frame->IsExitFrame() ?
"exit"
363 :
frame->IsStubFrame() ?
"stub"
365#if defined(DART_PRECOMPILED_RUNTIME)
367 auto const symbol_name = ImageName(vm_instructions, isolate_instructions,
373 frame = frames.NextFrame();
377bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
379 if (sim_->break_pc_ !=
nullptr) {
384 sim_->break_pc_ = breakpc;
385 sim_->break_instr_ = breakpc->InstructionBits();
391bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) {
392 if (sim_->break_pc_ !=
nullptr) {
393 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
396 sim_->break_pc_ =
nullptr;
397 sim_->break_instr_ = 0;
401void SimulatorDebugger::UndoBreakpoints() {
402 if (sim_->break_pc_ !=
nullptr) {
403 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
407void SimulatorDebugger::RedoBreakpoints() {
408 if (sim_->break_pc_ !=
nullptr) {
413void SimulatorDebugger::Debug() {
414 intptr_t last_pc = -1;
417#define COMMAND_SIZE 63
421#define XSTR(a) STR(a)
423 char cmd[COMMAND_SIZE + 1];
424 char arg1[ARG_SIZE + 1];
425 char arg2[ARG_SIZE + 1];
428 cmd[COMMAND_SIZE] = 0;
437 if (last_pc != sim_->get_pc()) {
438 last_pc = sim_->get_pc();
439 if (Simulator::IsIllegalAddress(last_pc)) {
442 if (FLAG_support_disassembler) {
445 OS::PrintErr(
"Disassembler not supported in this mode.\n");
449 char*
line = ReadLine(
"sim> ");
450 if (line ==
nullptr) {
451 FATAL(
"ReadLine failed");
455 int args = SScanF(line,
456 "%" XSTR(COMMAND_SIZE)
"s "
457 "%" XSTR(ARG_SIZE)
"s "
458 "%" XSTR(ARG_SIZE)
"s",
460 if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
462 "c/cont -- continue execution\n"
463 "disasm -- disassemble instrs at current pc location\n"
464 " other variants are:\n"
465 " disasm <address>\n"
466 " disasm <address> <number_of_instructions>\n"
467 " by default 10 instrs are disassembled\n"
468 "del -- delete breakpoints\n"
469 "flags -- print flag values\n"
470 "gdb -- transfer control to gdb\n"
471 "h/help -- print this help string\n"
472 "break <address> -- set break point at specified address\n"
473 "p/print <reg or icount or value or *addr> -- print integer\n"
474 "ps/printsingle <sreg or *addr> -- print float value\n"
475 "pd/printdouble <dreg or *addr> -- print double value\n"
476 "po/printobject <*reg or *addr> -- print object\n"
477 "si/stepi -- single step an instruction\n"
478 "trace -- toggle execution tracing mode\n"
479 "bt -- print backtrace\n"
480 "unstop -- if current pc is a stop instr make it a nop\n"
481 "q/quit -- Quit the debugger and exit the program\n");
482 }
else if ((strcmp(cmd,
"quit") == 0) || (strcmp(cmd,
"q") == 0)) {
485 }
else if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
486 sim_->InstructionDecode(
reinterpret_cast<Instr*
>(sim_->get_pc()));
487 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
489 sim_->InstructionDecode(
reinterpret_cast<Instr*
>(sim_->get_pc()));
492 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
495 if (strcmp(arg1,
"icount") == 0) {
496 const uint64_t icount = sim_->get_icount();
498 }
else if (
GetValue(arg1, &value)) {
504 OS::PrintErr(
"print <reg or icount or value or *addr>\n");
506 }
else if ((strcmp(cmd,
"ps") == 0) ||
507 (strcmp(cmd,
"printsingle") == 0)) {
510 if (GetFValue(arg1, &fvalue)) {
511 uint32_t
value = bit_cast<uint32_t, float>(fvalue);
512 OS::PrintErr(
"%s: 0%u 0x%x %.8g\n", arg1, value, value, fvalue);
519 }
else if ((strcmp(cmd,
"pd") == 0) ||
520 (strcmp(cmd,
"printdouble") == 0)) {
523 if (GetDValue(arg1, &dvalue)) {
524 uint64_t long_value = bit_cast<uint64_t, double>(dvalue);
525 OS::PrintErr(
"%s: %llu 0x%llx %.8g\n", arg1, long_value, long_value,
533 }
else if ((strcmp(cmd,
"po") == 0) ||
534 (strcmp(cmd,
"printobject") == 0)) {
538 if (((arg1[0] ==
'*') &&
GetValue(arg1 + 1, &value)) ||
543 const Object& obj =
Object::Handle(
static_cast<ObjectPtr
>(value));
547 OS::PrintErr(
"0x%x is not an object reference\n", value);
555 }
else if (strcmp(cmd,
"disasm") == 0) {
559 start = sim_->get_pc();
561 }
else if (
args == 2) {
564 if (Simulator::IsIllegalAddress(
start)) {
566 OS::PrintErr(
"First argument yields invalid address: 0x%x\n",
569 start = sim_->get_pc();
576 if (Simulator::IsIllegalAddress(
start)) {
578 OS::PrintErr(
"First argument yields invalid address: 0x%x\n",
581 start = sim_->get_pc();
587 if (FLAG_support_disassembler) {
590 OS::PrintErr(
"Disassembler not supported in this mode.\n");
593 OS::PrintErr(
"disasm [<address> [<number_of_instructions>]]\n");
595 }
else if (strcmp(cmd,
"gdb") == 0) {
599 }
else if (strcmp(cmd,
"break") == 0) {
612 }
else if (strcmp(cmd,
"del") == 0) {
613 if (!DeleteBreakpoint(
nullptr)) {
616 }
else if (strcmp(cmd,
"flags") == 0) {
627 }
else if (strcmp(cmd,
"unstop") == 0) {
629 Instr* stop_instr =
reinterpret_cast<Instr*
>(stop_pc);
630 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) {
635 }
else if (strcmp(cmd,
"trace") == 0) {
636 if (FLAG_trace_sim_after == ULLONG_MAX) {
637 FLAG_trace_sim_after = sim_->get_icount();
640 FLAG_trace_sim_after = ULLONG_MAX;
643 }
else if (strcmp(cmd,
"bt") == 0) {
644 Thread* thread =
reinterpret_cast<Thread*
>(sim_->get_register(
THR));
666char* SimulatorDebugger::ReadLine(
const char* prompt) {
670 bool keep_going =
true;
673 if (fgets(line_buf,
sizeof(line_buf), stdin) ==
nullptr) {
680 intptr_t
len = strlen(line_buf);
681 if (len > 1 && line_buf[len - 2] ==
'\\' && line_buf[len - 1] ==
'\n') {
684 line_buf[
len - 2] =
'\n';
685 line_buf[
len - 1] = 0;
687 }
else if ((len > 0) && (line_buf[len - 1] ==
'\n')) {
702 char* new_result =
new char[new_len];
703 if (new_result ==
nullptr) {
734 new char[(OSThread::GetSpecifiedStackSize() +
735 OSThread::kStackSizeBufferMax + kSimulatorStackUnderflowSize)];
737 stack_limit_ =
reinterpret_cast<uword>(stack_);
739 overflow_stack_limit_ = stack_limit_ + OSThread::kStackSizeBufferMax;
741 stack_base_ = overflow_stack_limit_ + OSThread::GetSpecifiedStackSize();
743 pc_modified_ =
false;
747 last_setjmp_buffer_ =
nullptr;
761 registers_[
SP] = stack_base();
764 registers_[
PC] = kBadLR;
765 registers_[
LR] = kBadLR;
773 ASSERT(2 * kNumberOfDRegisters >= kNumberOfSRegisters);
775 ASSERT(sregisters_[i] == 0.0);
783Simulator::~Simulator() {
785 Isolate* isolate = Isolate::Current();
786 if (isolate !=
nullptr) {
787 isolate->set_simulator(
nullptr);
800 uword address_of_svc_instruction() {
801 return reinterpret_cast<uword>(&svc_instruction_);
804 uword external_function()
const {
return external_function_; }
806 Simulator::CallKind call_kind()
const {
return call_kind_; }
810 static Redirection*
Get(uword external_function,
811 Simulator::CallKind call_kind,
813 MutexLocker ml(mutex_);
815 Redirection* old_head = list_.load(std::memory_order_relaxed);
816 for (Redirection* current = old_head; current !=
nullptr;
817 current = current->next_) {
818 if (current->external_function_ == external_function)
return current;
821 Redirection* redirection =
823 redirection->next_ = old_head;
828 list_.store(redirection, std::memory_order_release);
833 static Redirection* FromSvcInstruction(Instr* svc_instruction) {
834 char* addr_of_svc =
reinterpret_cast<char*
>(svc_instruction);
835 char* addr_of_redirection =
836 addr_of_svc -
OFFSET_OF(Redirection, svc_instruction_);
837 return reinterpret_cast<Redirection*
>(addr_of_redirection);
844 static uword FunctionForRedirect(uword address_of_svc) {
845 for (Redirection* current = list_.load(std::memory_order_acquire);
846 current !=
nullptr; current = current->next_) {
847 if (current->address_of_svc_instruction() == address_of_svc) {
848 return current->external_function_;
855 Redirection(uword external_function,
856 Simulator::CallKind call_kind,
858 : external_function_(external_function),
859 call_kind_(call_kind),
861 svc_instruction_(Instr::kSimulatorRedirectInstruction),
864 uword external_function_;
865 Simulator::CallKind call_kind_;
867 uint32_t svc_instruction_;
869 static std::atomic<Redirection*> list_;
870 static Mutex* mutex_;
873std::atomic<Redirection*> Redirection::list_ = {
nullptr};
874Mutex* Redirection::mutex_ =
new Mutex();
879 Redirection* redirection =
881 return redirection->address_of_svc_instruction();
884uword Simulator::FunctionForRedirect(uword redirect) {
885 return Redirection::FunctionForRedirect(redirect);
889Simulator* Simulator::Current() {
890 Isolate* isolate = Isolate::Current();
891 Simulator* simulator = isolate->simulator();
892 if (simulator ==
nullptr) {
893 NoSafepointScope no_safepoint;
894 simulator =
new Simulator();
895 isolate->set_simulator(simulator);
902DART_FORCE_INLINE
void Simulator::set_register(Register reg, int32_t value) {
903 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
907 registers_[reg] =
value;
911DART_FORCE_INLINE
void Simulator::set_pc(int32_t value) {
917DART_FORCE_INLINE
void Simulator::set_sregister(SRegister reg,
float value) {
918 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
919 sregisters_[reg] = bit_cast<int32_t, float>(value);
922DART_FORCE_INLINE
float Simulator::get_sregister(SRegister reg)
const {
923 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
924 return bit_cast<float, int32_t>(sregisters_[reg]);
927DART_FORCE_INLINE
void Simulator::set_dregister(DRegister reg,
double value) {
928 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
929 dregisters_[reg] = bit_cast<int64_t, double>(value);
932DART_FORCE_INLINE
double Simulator::get_dregister(DRegister reg)
const {
933 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
934 return bit_cast<double, int64_t>(dregisters_[reg]);
937void Simulator::set_qregister(QRegister reg,
const simd_value_t& value) {
938 ASSERT(TargetCPUFeatures::neon_supported());
939 ASSERT((reg >= 0) && (reg < kNumberOfQRegisters));
940 qregisters_[reg].data_[0] =
value.data_[0];
941 qregisters_[reg].data_[1] =
value.data_[1];
942 qregisters_[reg].data_[2] =
value.data_[2];
943 qregisters_[reg].data_[3] =
value.data_[3];
946void Simulator::get_qregister(QRegister reg, simd_value_t* value)
const {
947 ASSERT(TargetCPUFeatures::neon_supported());
950 if ((reg >= 0) && (reg < kNumberOfQRegisters)) {
951 *
value = qregisters_[reg];
955void Simulator::set_sregister_bits(SRegister reg, int32_t value) {
956 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
957 sregisters_[reg] =
value;
960int32_t Simulator::get_sregister_bits(SRegister reg)
const {
961 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
962 return sregisters_[reg];
965void Simulator::set_dregister_bits(DRegister reg, int64_t value) {
966 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
967 dregisters_[reg] =
value;
970int64_t Simulator::get_dregister_bits(DRegister reg)
const {
971 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
972 return dregisters_[reg];
975void Simulator::HandleIllegalAccess(uword addr, Instr* instr) {
976 uword fault_pc = get_pc();
981 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", addr,
983 SimulatorDebugger dbg(
this);
986 FATAL(
"Cannot continue execution after illegal memory access.");
989void Simulator::UnimplementedInstruction(Instr* instr) {
991 snprintf(
buffer,
sizeof(
buffer),
"Unimplemented instruction: pc=%p\n", instr);
992 SimulatorDebugger dbg(
this);
994 FATAL(
"Cannot continue execution after unimplemented instruction.");
997DART_FORCE_INLINE intptr_t Simulator::ReadW(uword addr, Instr* instr) {
998 return *
reinterpret_cast<intptr_t*
>(
addr);
1001DART_FORCE_INLINE
void Simulator::WriteW(uword addr,
1004 *
reinterpret_cast<intptr_t*
>(
addr) = value;
1007DART_FORCE_INLINE uint16_t Simulator::ReadHU(uword addr, Instr* instr) {
1008 return *
reinterpret_cast<uint16_t*
>(
addr);
1011DART_FORCE_INLINE int16_t Simulator::ReadH(uword addr, Instr* instr) {
1012 return *
reinterpret_cast<int16_t*
>(
addr);
1015DART_FORCE_INLINE
void Simulator::WriteH(uword addr,
1018 *
reinterpret_cast<uint16_t*
>(
addr) = value;
1021DART_FORCE_INLINE uint8_t Simulator::ReadBU(uword addr) {
1022 return *
reinterpret_cast<uint8_t*
>(
addr);
1025DART_FORCE_INLINE int8_t Simulator::ReadB(uword addr) {
1026 return *
reinterpret_cast<int8_t*
>(
addr);
1029DART_FORCE_INLINE
void Simulator::WriteB(uword addr, uint8_t value) {
1030 *
reinterpret_cast<uint8_t*
>(
addr) = value;
1033void Simulator::ClearExclusive() {
1034 exclusive_access_addr_ = 0;
1035 exclusive_access_value_ = 0;
1038intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) {
1039 exclusive_access_addr_ =
addr;
1040 exclusive_access_value_ = ReadW(addr, instr);
1041 return exclusive_access_value_;
1044intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) {
1047 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr));
1048 if (exclusive_access_addr_ != addr) {
1052 int32_t old_value =
static_cast<uint32_t
>(exclusive_access_value_);
1055 auto atomic_addr =
reinterpret_cast<RelaxedAtomic<int32_t>*
>(
addr);
1056 if (atomic_addr->compare_exchange_weak(old_value, value)) {
1062bool Simulator::IsTracingExecution()
const {
1063 return icount_ > FLAG_trace_sim_after;
1067void Simulator::Format(Instr* instr,
const char*
format) {
1068 OS::PrintErr(
"Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
1075DART_FORCE_INLINE
bool Simulator::ConditionallyExecute(Instr* instr) {
1076 switch (instr->ConditionField()) {
1094 return c_flag_ && !z_flag_;
1096 return !c_flag_ || z_flag_;
1098 return n_flag_ == v_flag_;
1100 return n_flag_ != v_flag_;
1102 return !z_flag_ && (n_flag_ == v_flag_);
1104 return z_flag_ || (n_flag_ != v_flag_);
1114DART_FORCE_INLINE
void Simulator::SetNZFlags(int32_t val) {
1115 n_flag_ = (val < 0);
1116 z_flag_ = (val == 0);
1120DART_FORCE_INLINE
void Simulator::SetCFlag(
bool val) {
1125DART_FORCE_INLINE
void Simulator::SetVFlag(
bool val) {
1130DART_FORCE_INLINE
bool Simulator::CarryFrom(int32_t
left,
1133 uint64_t uleft =
static_cast<uint32_t
>(
left);
1134 uint64_t uright =
static_cast<uint32_t
>(
right);
1135 uint64_t ucarry =
static_cast<uint32_t
>(carry);
1136 return ((uleft + uright + ucarry) >> 32) != 0;
1140DART_FORCE_INLINE
bool Simulator::OverflowFrom(int32_t
left,
1149int32_t Simulator::GetShiftRm(Instr* instr,
bool* carry_out) {
1150 Shift shift = instr->ShiftField();
1151 int shift_amount = instr->ShiftAmountField();
1152 int32_t
result = get_register(instr->RmField());
1153 if (instr->Bit(4) == 0) {
1155 if ((shift == ROR) && (shift_amount == 0)) {
1156 UnimplementedInstruction(instr);
1157 }
else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1162 if (shift_amount == 0) {
1171 result >>= (shift_amount - 1);
1172 *carry_out = (
result & 1) == 1;
1179 if (shift_amount == 0) {
1180 *carry_out = c_flag_;
1182 result =
static_cast<uint32_t
>(
result) << (shift_amount - 1);
1183 *carry_out = (
result < 0);
1190 if (shift_amount == 0) {
1192 *carry_out = c_flag_;
1194 uint32_t uresult =
static_cast<uint32_t
>(
result);
1195 uresult >>= (shift_amount - 1);
1196 *carry_out = (uresult & 1) == 1;
1198 result =
static_cast<int32_t
>(uresult);
1204 UnimplementedInstruction(instr);
1216 shift_amount = get_register(rs) & 0xff;
1219 if (shift_amount == 0) {
1220 *carry_out = c_flag_;
1221 }
else if (shift_amount < 32) {
1222 result >>= (shift_amount - 1);
1223 *carry_out = (
result & 1) == 1;
1226 ASSERT(shift_amount >= 32);
1239 if (shift_amount == 0) {
1240 *carry_out = c_flag_;
1241 }
else if (shift_amount < 32) {
1242 result =
static_cast<uint32_t
>(
result) << (shift_amount - 1);
1243 *carry_out = (
result < 0);
1245 }
else if (shift_amount == 32) {
1246 *carry_out = (
result & 1) == 1;
1249 ASSERT(shift_amount > 32);
1257 if (shift_amount == 0) {
1258 *carry_out = c_flag_;
1259 }
else if (shift_amount < 32) {
1260 uint32_t uresult =
static_cast<uint32_t
>(
result);
1261 uresult >>= (shift_amount - 1);
1262 *carry_out = (uresult & 1) == 1;
1264 result =
static_cast<int32_t
>(uresult);
1265 }
else if (shift_amount == 32) {
1266 *carry_out = (
result < 0);
1276 UnimplementedInstruction(instr);
1291DART_FORCE_INLINE int32_t Simulator::GetImm(Instr* instr,
bool* carry_out) {
1292 uint8_t
rotate = instr->RotateField() * 2;
1293 int32_t immed8 = instr->Immed8Field();
1294 int32_t imm = Utils::RotateRight(immed8,
rotate);
1295 *carry_out = (
rotate == 0) ? c_flag_ : (imm < 0);
1300void Simulator::HandleRList(Instr* instr,
bool load) {
1302 int32_t rn_val = get_register(rn);
1303 int rlist = instr->RlistField();
1304 int num_regs = Utils::CountOneBits32(
static_cast<uint32_t
>(rlist));
1307 uword end_address = 0;
1308 switch (instr->PUField()) {
1311 address = rn_val - (num_regs * 4) + 4;
1312 end_address = rn_val + 4;
1313 rn_val = rn_val - (num_regs * 4);
1319 end_address = rn_val + (num_regs * 4);
1320 rn_val = rn_val + (num_regs * 4);
1325 address = rn_val - (num_regs * 4);
1326 end_address = rn_val;
1332 address = rn_val + 4;
1333 end_address = rn_val + (num_regs * 4) + 4;
1334 rn_val = rn_val + (num_regs * 4);
1342 if (IsIllegalAddress(address)) {
1343 HandleIllegalAccess(address, instr);
1345 if (instr->HasW()) {
1346 set_register(rn, rn_val);
1349 while (rlist != 0) {
1350 if ((rlist & 1) != 0) {
1352 set_register(
static_cast<Register>(reg), ReadW(address, instr));
1354 WriteW(address, get_register(
static_cast<Register>(reg)), instr);
1361 ASSERT(end_address == address);
1366typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
1369typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0,
1380static int32_t InvokeLeafRuntime(SimulatorLeafRuntimeCall
target,
1386 return target(r0, r1, r2, r3, r4);
1390typedef double (*SimulatorLeafFloatRuntimeCall)(
double d0,
double d1);
1397static
double InvokeFloatLeafRuntime(SimulatorLeafFloatRuntimeCall
target,
1407void Simulator::SupervisorCall(Instr* instr) {
1408 int svc = instr->SvcField();
1410 case Instr::kSimulatorRedirectCode: {
1411 SimulatorSetjmpBuffer
buffer(
this);
1413 if (!setjmp(
buffer.buffer_)) {
1414 int32_t saved_lr = get_register(
LR);
1415 Redirection* redirection = Redirection::FromSvcInstruction(instr);
1416 uword external = redirection->external_function();
1417 if (IsTracingExecution()) {
1418 THR_Print(
"Call to host function at 0x%" Pd "\n", external);
1420 if (redirection->call_kind() == kRuntimeCall) {
1421 NativeArguments arguments;
1422 ASSERT(
sizeof(NativeArguments) == 4 * kWordSize);
1423 arguments.thread_ =
reinterpret_cast<Thread*
>(get_register(R0));
1424 arguments.argc_tag_ = get_register(R1);
1425 arguments.argv_ =
reinterpret_cast<ObjectPtr*
>(get_register(R2));
1426 arguments.retval_ =
reinterpret_cast<ObjectPtr*
>(get_register(R3));
1427 SimulatorRuntimeCall
target =
1428 reinterpret_cast<SimulatorRuntimeCall
>(external);
1430 ClobberVolatileRegisters();
1431 }
else if (redirection->call_kind() == kLeafRuntimeCall) {
1432 ASSERT((0 <= redirection->argument_count()) &&
1433 (redirection->argument_count() <= 5));
1434 int32_t r0 = get_register(R0);
1435 int32_t r1 = get_register(R1);
1436 int32_t r2 = get_register(R2);
1437 int32_t r3 = get_register(R3);
1438 int32_t r4 = *
reinterpret_cast<int32_t*
>(get_register(SP));
1439 SimulatorLeafRuntimeCall
target =
1440 reinterpret_cast<SimulatorLeafRuntimeCall
>(external);
1441 r0 = InvokeLeafRuntime(
target, r0, r1, r2, r3, r4);
1442 ClobberVolatileRegisters();
1443 set_register(R0, r0);
1444 }
else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
1445 ASSERT((0 <= redirection->argument_count()) &&
1446 (redirection->argument_count() <= 2));
1447 SimulatorLeafFloatRuntimeCall
target =
1448 reinterpret_cast<SimulatorLeafFloatRuntimeCall
>(external);
1449 if (TargetCPUFeatures::hardfp_supported()) {
1452 double d0 = get_dregister(D0);
1453 double d1 = get_dregister(D1);
1454 d0 = InvokeFloatLeafRuntime(
target, d0, d1);
1455 ClobberVolatileRegisters();
1456 set_dregister(D0, d0);
1460 uint32_t r0 = get_register(R0);
1461 int32_t r1 = get_register(R1);
1462 uint32_t r2 = get_register(R2);
1463 int32_t r3 = get_register(R3);
1464 int64_t a0 = Utils::LowHighTo64Bits(r0, r1);
1465 int64_t a1 = Utils::LowHighTo64Bits(r2, r3);
1466 double d0 = bit_cast<double, int64_t>(a0);
1467 double d1 = bit_cast<double, int64_t>(a1);
1468 d0 = InvokeFloatLeafRuntime(
target, d0, d1);
1469 ClobberVolatileRegisters();
1470 a0 = bit_cast<int64_t, double>(d0);
1471 r0 = Utils::Low32Bits(a0);
1472 r1 = Utils::High32Bits(a0);
1473 set_register(R0, r0);
1474 set_register(R1, r1);
1477 ASSERT(redirection->call_kind() == kNativeCallWrapper);
1478 SimulatorNativeCallWrapper wrapper =
1479 reinterpret_cast<SimulatorNativeCallWrapper
>(external);
1484 wrapper(arguments, target_func);
1485 ClobberVolatileRegisters();
1496 case Instr::kSimulatorBreakCode: {
1497 SimulatorDebugger dbg(
this);
1498 dbg.Stop(instr,
"breakpoint");
1508void Simulator::ClobberVolatileRegisters() {
1510 exclusive_access_addr_ = exclusive_access_value_ = 0;
1513 if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
1514 registers_[i] = icount_;
1518 double zap_dvalue =
static_cast<double>(icount_);
1519 for (
int i = D0; i <=
D7; i++) {
1520 set_dregister(
static_cast<DRegister>(i), zap_dvalue);
1524#if defined(VFPv3_D32)
1525 for (
int i = D16; i <=
D31; i++) {
1526 set_dregister(
static_cast<DRegister>(i), zap_dvalue);
1535DART_FORCE_INLINE
void Simulator::DecodeType01(Instr* instr) {
1536 if (!instr->IsDataProcessing()) {
1538 if (instr->IsMiscellaneous()) {
1539 switch (instr->Bits(4, 3)) {
1541 if (instr->Bits(21, 2) == 0x3) {
1545 int32_t rm_val = get_register(rm);
1548 while (rm_val > 0) {
1555 set_register(rd, rd_val);
1557 ASSERT(instr->Bits(21, 2) == 0x1);
1560 int32_t rm_val = get_register(rm);
1566 ASSERT(instr->Bits(21, 2) == 0x1);
1569 int32_t rm_val = get_register(rm);
1570 intptr_t pc = get_pc();
1571 set_register(
LR, pc + Instr::kInstrSize);
1576 if ((instr->Bits(21, 2) == 0x1) && (instr->ConditionField() == AL)) {
1578 SimulatorDebugger dbg(
this);
1579 int32_t imm = instr->BkptField();
1582 set_pc(get_pc() + Instr::kInstrSize);
1586 UnimplementedInstruction(instr);
1591 UnimplementedInstruction(instr);
1595 }
else if (instr->IsMultiplyOrSyncPrimitive()) {
1596 if (instr->Bit(24) == 0) {
1602 uint32_t rm_val = get_register(rm);
1603 uint32_t rs_val = get_register(rs);
1604 uint32_t rd_val = 0;
1605 switch (instr->Bits(21, 3)) {
1612 rd_val = get_register(rd);
1618 uint32_t alu_out = rm_val * rs_val;
1619 if (instr->Bits(21, 3) == 3) {
1623 set_register(rn, alu_out);
1624 if (instr->HasS()) {
1625 SetNZFlags(alu_out);
1636 if (instr->Bits(21, 3) == 4) {
1637 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1638 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1639 result = left_op * right_op;
1641 int64_t left_op =
static_cast<int32_t
>(rm_val);
1642 int64_t right_op =
static_cast<int32_t
>(rs_val);
1643 result = left_op * right_op;
1645 int32_t hi_res = Utils::High32Bits(
result);
1646 int32_t lo_res = Utils::Low32Bits(
result);
1647 set_register(rd, lo_res);
1648 set_register(rn, hi_res);
1649 if (instr->HasS()) {
1671 int32_t rd_lo_val = get_register(rd);
1672 int32_t rd_hi_val = get_register(rn);
1673 uint32_t accum_lo =
static_cast<uint32_t
>(rd_lo_val);
1674 int32_t accum_hi =
static_cast<int32_t
>(rd_hi_val);
1675 int64_t accum = Utils::LowHighTo64Bits(accum_lo, accum_hi);
1677 if (instr->Bits(21, 3) == 5) {
1678 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1679 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1680 result = accum + left_op * right_op;
1681 }
else if (instr->Bits(21, 3) == 7) {
1682 int64_t left_op =
static_cast<int32_t
>(rm_val);
1683 int64_t right_op =
static_cast<int32_t
>(rs_val);
1684 result = accum + left_op * right_op;
1686 ASSERT(instr->Bits(21, 3) == 2);
1688 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1689 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1690 result = left_op * right_op +
1691 static_cast<uint32_t
>(rd_lo_val) +
1692 static_cast<uint32_t
>(rd_hi_val);
1694 int32_t hi_res = Utils::High32Bits(
result);
1695 int32_t lo_res = Utils::Low32Bits(
result);
1696 set_register(rd, lo_res);
1697 set_register(rn, hi_res);
1698 if (instr->HasS()) {
1710 UnimplementedInstruction(instr);
1719 switch (instr->Bits(20, 4)) {
1722 if (IsIllegalAddress(addr)) {
1723 HandleIllegalAccess(addr, instr);
1726 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr));
1732 if (IsIllegalAddress(addr)) {
1733 HandleIllegalAccess(addr, instr);
1735 set_register(rd, ReadExclusiveW(addr, instr));
1740 UnimplementedInstruction(instr);
1745 }
else if (instr->Bit(25) == 1) {
1747 switch (instr->Bits(20, 5)) {
1750 uint16_t imm16 = instr->MovwField();
1752 if (instr->Bit(22) == 0) {
1754 set_register(rd, imm16);
1757 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16));
1762 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) {
1765 UnimplementedInstruction(instr);
1770 UnimplementedInstruction(instr);
1778 int32_t rn_val = get_register(rn);
1780 bool write_back =
false;
1781 if (instr->Bit(22) == 0) {
1783 int32_t rm_val = get_register(rm);
1784 switch (instr->PUField()) {
1805 write_back = instr->HasW();
1812 write_back = instr->HasW();
1822 int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField();
1823 switch (instr->PUField()) {
1844 write_back = instr->HasW();
1851 write_back = instr->HasW();
1861 if (IsIllegalAddress(addr)) {
1862 HandleIllegalAccess(addr, instr);
1866 set_register(rn, rn_val);
1868 if (!instr->HasSign()) {
1869 if (instr->HasL()) {
1870 uint16_t val = ReadHU(addr, instr);
1871 set_register(rd, val);
1873 uint16_t val = get_register(rd);
1874 WriteH(addr, val, instr);
1876 }
else if (instr->HasL()) {
1877 if (instr->HasH()) {
1878 int16_t val = ReadH(addr, instr);
1879 set_register(rd, val);
1881 int8_t val = ReadB(addr);
1882 set_register(rd, val);
1884 }
else if ((rd & 1) == 0) {
1886 ASSERT(rd1 < kNumberOfCpuRegisters);
1887 if (instr->HasH()) {
1888 int32_t val_low = get_register(rd);
1889 int32_t val_high = get_register(rd1);
1890 WriteW(addr, val_low, instr);
1891 WriteW(addr + 4, val_high, instr);
1893 int32_t val_low = ReadW(addr, instr);
1894 int32_t val_high = ReadW(addr + 4, instr);
1895 set_register(rd, val_low);
1896 set_register(rd1, val_high);
1899 UnimplementedInstruction(instr);
1906 uint32_t rn_val = get_register(rn);
1907 uint32_t shifter_operand = 0;
1908 bool shifter_carry_out = 0;
1909 if (instr->TypeField() == 0) {
1910 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1912 ASSERT(instr->TypeField() == 1);
1913 shifter_operand = GetImm(instr, &shifter_carry_out);
1918 switch (instr->OpcodeField()) {
1922 alu_out = rn_val & shifter_operand;
1923 set_register(rd, alu_out);
1924 if (instr->HasS()) {
1925 SetNZFlags(alu_out);
1926 SetCFlag(shifter_carry_out);
1934 alu_out = rn_val ^ shifter_operand;
1935 set_register(rd, alu_out);
1936 if (instr->HasS()) {
1937 SetNZFlags(alu_out);
1938 SetCFlag(shifter_carry_out);
1946 alu_out = rn_val - shifter_operand;
1947 set_register(rd, alu_out);
1948 if (instr->HasS()) {
1949 SetNZFlags(alu_out);
1950 SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1));
1951 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1));
1959 alu_out = shifter_operand - rn_val;
1960 set_register(rd, alu_out);
1961 if (instr->HasS()) {
1962 SetNZFlags(alu_out);
1963 SetCFlag(CarryFrom(shifter_operand, ~rn_val, 1));
1964 SetVFlag(OverflowFrom(shifter_operand, ~rn_val, 1));
1972 alu_out = rn_val + shifter_operand;
1973 set_register(rd, alu_out);
1974 if (instr->HasS()) {
1975 SetNZFlags(alu_out);
1976 SetCFlag(CarryFrom(rn_val, shifter_operand, 0));
1977 SetVFlag(OverflowFrom(rn_val, shifter_operand, 0));
1985 carry_in = c_flag_ ? 1 : 0;
1986 alu_out = rn_val + shifter_operand + carry_in;
1987 set_register(rd, alu_out);
1988 if (instr->HasS()) {
1989 SetNZFlags(alu_out);
1990 SetCFlag(CarryFrom(rn_val, shifter_operand, carry_in));
1991 SetVFlag(OverflowFrom(rn_val, shifter_operand, carry_in));
1999 carry_in = c_flag_ ? 1 : 0;
2000 alu_out = rn_val + ~shifter_operand + carry_in;
2001 set_register(rd, alu_out);
2002 if (instr->HasS()) {
2003 SetNZFlags(alu_out);
2004 SetCFlag(CarryFrom(rn_val, ~shifter_operand, carry_in));
2005 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, carry_in));
2013 carry_in = c_flag_ ? 1 : 0;
2014 alu_out = shifter_operand + ~rn_val + carry_in;
2015 set_register(rd, alu_out);
2016 if (instr->HasS()) {
2017 SetNZFlags(alu_out);
2018 SetCFlag(CarryFrom(shifter_operand, ~rn_val, carry_in));
2019 SetVFlag(OverflowFrom(shifter_operand, ~rn_val, carry_in));
2025 if (instr->HasS()) {
2028 alu_out = rn_val & shifter_operand;
2029 SetNZFlags(alu_out);
2030 SetCFlag(shifter_carry_out);
2032 UnimplementedInstruction(instr);
2038 if (instr->HasS()) {
2041 alu_out = rn_val ^ shifter_operand;
2042 SetNZFlags(alu_out);
2043 SetCFlag(shifter_carry_out);
2045 UnimplementedInstruction(instr);
2051 if (instr->HasS()) {
2054 alu_out = rn_val - shifter_operand;
2055 SetNZFlags(alu_out);
2056 SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1));
2057 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1));
2059 UnimplementedInstruction(instr);
2065 if (instr->HasS()) {
2068 alu_out = rn_val + shifter_operand;
2069 SetNZFlags(alu_out);
2070 SetCFlag(CarryFrom(rn_val, shifter_operand, 0));
2071 SetVFlag(OverflowFrom(rn_val, shifter_operand, 0));
2073 UnimplementedInstruction(instr);
2081 alu_out = rn_val | shifter_operand;
2082 set_register(rd, alu_out);
2083 if (instr->HasS()) {
2084 SetNZFlags(alu_out);
2085 SetCFlag(shifter_carry_out);
2093 alu_out = shifter_operand;
2094 set_register(rd, alu_out);
2095 if (instr->HasS()) {
2096 SetNZFlags(alu_out);
2097 SetCFlag(shifter_carry_out);
2105 alu_out = rn_val & ~shifter_operand;
2106 set_register(rd, alu_out);
2107 if (instr->HasS()) {
2108 SetNZFlags(alu_out);
2109 SetCFlag(shifter_carry_out);
2117 alu_out = ~shifter_operand;
2118 set_register(rd, alu_out);
2119 if (instr->HasS()) {
2120 SetNZFlags(alu_out);
2121 SetCFlag(shifter_carry_out);
2134DART_FORCE_INLINE
void Simulator::DecodeType2(Instr* instr) {
2137 int32_t rn_val = get_register(rn);
2138 int32_t im_val = instr->Offset12Field();
2140 bool write_back =
false;
2141 switch (instr->PUField()) {
2162 write_back = instr->HasW();
2169 write_back = instr->HasW();
2177 if (IsIllegalAddress(addr)) {
2178 HandleIllegalAccess(addr, instr);
2182 set_register(rn, rn_val);
2184 if (instr->HasB()) {
2185 if (instr->HasL()) {
2186 unsigned char val = ReadBU(addr);
2187 set_register(rd, val);
2189 unsigned char val = get_register(rd);
2193 if (instr->HasL()) {
2194 set_register(rd, ReadW(addr, instr));
2196 WriteW(addr, get_register(rd), instr);
2202void Simulator::DoDivision(Instr* instr) {
2203 const Register rd = instr->DivRdField();
2204 const Register rn = instr->DivRnField();
2205 const Register rm = instr->DivRmField();
2207 if (!TargetCPUFeatures::integer_division_supported()) {
2208 UnimplementedInstruction(instr);
2214 if (get_register(rm) == 0) {
2215 set_register(rd, 0);
2219 if (instr->IsDivUnsigned()) {
2221 uint32_t rn_val =
static_cast<uint32_t
>(get_register(rn));
2222 uint32_t rm_val =
static_cast<uint32_t
>(get_register(rm));
2223 uint32_t
result = rn_val / rm_val;
2224 set_register(rd,
static_cast<int32_t
>(
result));
2227 int32_t rn_val = get_register(rn);
2228 int32_t rm_val = get_register(rm);
2230 if ((rn_val ==
static_cast<int32_t
>(0x80000000)) &&
2231 (rm_val ==
static_cast<int32_t
>(0xffffffff))) {
2234 result = rn_val / rm_val;
2236 set_register(rd,
result);
2240void Simulator::DecodeType3(Instr* instr) {
2241 if (instr->IsMedia()) {
2242 if (instr->IsDivision()) {
2245 }
else if (instr->IsRbit()) {
2249 set_register(rd, Utils::ReverseBits32(get_register(rm)));
2251 }
else if (instr->IsBitFieldExtract()) {
2253 const Register rd = instr->RdField();
2254 const Register rn = instr->BitFieldExtractRnField();
2255 const uint8_t
width = instr->BitFieldExtractWidthField() + 1;
2256 const uint8_t lsb = instr->BitFieldExtractLSBField();
2257 const int32_t rn_val = get_register(rn);
2258 const uint32_t extracted_bitfield =
2259 ((rn_val >> lsb) & Utils::NBitMask(
width));
2260 const uint32_t sign_extension =
2261 (instr->IsBitFieldExtractSignExtended() &&
2262 Utils::TestBit(extracted_bitfield,
width - 1))
2263 ? ~Utils::NBitMask(
width)
2265 set_register(rd, sign_extension | extracted_bitfield);
2273 int32_t rn_val = get_register(rn);
2274 bool shifter_carry_out = 0;
2275 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2277 bool write_back =
false;
2278 switch (instr->PUField()) {
2283 rn_val -= shifter_operand;
2291 rn_val += shifter_operand;
2297 rn_val -= shifter_operand;
2299 write_back = instr->HasW();
2304 rn_val += shifter_operand;
2306 write_back = instr->HasW();
2314 if (IsIllegalAddress(addr)) {
2315 HandleIllegalAccess(addr, instr);
2319 set_register(rn, rn_val);
2321 if (instr->HasB()) {
2322 if (instr->HasL()) {
2323 unsigned char val = ReadBU(addr);
2324 set_register(rd, val);
2326 unsigned char val = get_register(rd);
2330 if (instr->HasL()) {
2331 set_register(rd, ReadW(addr, instr));
2333 WriteW(addr, get_register(rd), instr);
2339void Simulator::DecodeType4(Instr* instr) {
2340 ASSERT(instr->Bit(22) == 0);
2341 if (instr->HasL()) {
2343 HandleRList(instr,
true);
2346 HandleRList(instr,
false);
2350void Simulator::DecodeType5(Instr* instr) {
2352 uint32_t off = (
static_cast<uint32_t
>(instr->SImmed24Field()) << 2) + 8;
2353 uint32_t pc = get_pc();
2354 if (instr->HasLink()) {
2355 set_register(
LR, pc + Instr::kInstrSize);
2360void Simulator::DecodeType6(Instr* instr) {
2361 if (instr->IsVFPDoubleTransfer()) {
2364 if (instr->Bit(8) == 0) {
2367 ASSERT(sm1 < kNumberOfSRegisters);
2368 if (instr->Bit(20) == 1) {
2370 set_register(rd, get_sregister_bits(sm));
2371 set_register(rn, get_sregister_bits(sm1));
2374 set_sregister_bits(sm, get_register(rd));
2375 set_sregister_bits(sm1, get_register(rn));
2379 if (instr->Bit(20) == 1) {
2381 int64_t dm_val = get_dregister_bits(dm);
2382 set_register(rd, Utils::Low32Bits(dm_val));
2383 set_register(rn, Utils::High32Bits(dm_val));
2387 Utils::LowHighTo64Bits(get_register(rd), get_register(rn));
2388 set_dregister_bits(dm, dm_val);
2391 }
else if (instr->IsVFPLoadStore()) {
2393 int32_t
addr = get_register(rn);
2394 int32_t imm_val = instr->Bits(0, 8) << 2;
2395 if (instr->Bit(23) == 1) {
2400 if (IsIllegalAddress(addr)) {
2401 HandleIllegalAccess(addr, instr);
2403 if (instr->Bit(8) == 0) {
2405 if (instr->Bit(20) == 1) {
2408 set_sregister_bits(sd, ReadW(addr, instr));
2412 WriteW(addr, get_sregister_bits(sd), instr);
2416 if (instr->Bit(20) == 1) {
2419 int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr),
2420 ReadW(addr + 4, instr));
2421 set_dregister_bits(dd, dd_val);
2425 int64_t dd_val = get_dregister_bits(dd);
2426 WriteW(addr, Utils::Low32Bits(dd_val), instr);
2427 WriteW(addr + 4, Utils::High32Bits(dd_val), instr);
2431 }
else if (instr->IsVFPMultipleLoadStore()) {
2433 int32_t
addr = get_register(rn);
2434 int32_t imm_val = instr->Bits(0, 8);
2435 if (instr->Bit(23) == 0) {
2436 addr -= (imm_val << 2);
2438 if (instr->HasW()) {
2439 if (instr->Bit(23) == 1) {
2440 set_register(rn, addr + (imm_val << 2));
2442 set_register(rn, addr);
2445 if (IsIllegalAddress(addr)) {
2446 HandleIllegalAccess(addr, instr);
2448 if (instr->Bit(8) == 0) {
2449 int32_t regs_cnt = imm_val;
2450 int32_t
start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
2451 for (
int i =
start; i <
start + regs_cnt; i++) {
2453 if (instr->Bit(20) == 1) {
2455 set_sregister_bits(sd, ReadW(addr, instr));
2458 WriteW(addr, get_sregister_bits(sd), instr);
2463 int32_t regs_cnt = imm_val >> 1;
2464 int32_t
start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
2466 for (
int i =
start; i <
start + regs_cnt; i++) {
2468 if (instr->Bit(20) == 1) {
2470 int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr),
2471 ReadW(addr + 4, instr));
2472 set_dregister_bits(dd, dd_val);
2475 int64_t dd_val = get_dregister_bits(dd);
2476 WriteW(addr, Utils::Low32Bits(dd_val), instr);
2477 WriteW(addr + 4, Utils::High32Bits(dd_val), instr);
2482 UnimplementedInstruction(instr);
2487 UnimplementedInstruction(instr);
2491void Simulator::DecodeType7(Instr* instr) {
2492 if (instr->Bit(24) == 1) {
2494 SupervisorCall(instr);
2495 }
else if (instr->IsVFPDataProcessingOrSingleTransfer()) {
2496 if (instr->Bit(4) == 0) {
2504 if (instr->Bit(8) == 0) {
2505 sd = instr->SdField();
2506 sn = instr->SnField();
2507 sm = instr->SmField();
2515 dd = instr->DdField();
2516 dn = instr->DnField();
2517 dm = instr->DmField();
2519 switch (instr->Bits(20, 4) & 0xb) {
2522 UnimplementedInstruction(instr);
2526 if (instr->Bit(8) == 0) {
2527 float addend = get_sregister(sn) * get_sregister(sm);
2528 float sd_val = get_sregister(sd);
2529 if (instr->Bit(6) == 0) {
2535 set_sregister(sd, sd_val + addend);
2537 double addend = get_dregister(dn) * get_dregister(dm);
2538 double dd_val = get_dregister(dd);
2539 if (instr->Bit(6) == 0) {
2545 set_dregister(dd, dd_val + addend);
2550 if (instr->Bit(8) == 0) {
2552 set_sregister(sd, get_sregister(sn) * get_sregister(sm));
2555 set_dregister(dd, get_dregister(dn) * get_dregister(dm));
2560 if (instr->Bit(8) == 0) {
2562 set_sregister(sd, get_sregister(sn) / get_sregister(sm));
2565 set_dregister(dd, get_dregister(dn) / get_dregister(dm));
2570 if (instr->Bit(8) == 0) {
2571 if (instr->Bit(6) == 0) {
2573 set_sregister(sd, get_sregister(sn) + get_sregister(sm));
2576 set_sregister(sd, get_sregister(sn) - get_sregister(sm));
2579 if (instr->Bit(6) == 0) {
2581 set_dregister(dd, get_dregister(dn) + get_dregister(dm));
2584 set_dregister(dd, get_dregister(dn) - get_dregister(dm));
2590 if (instr->Bit(6) == 0) {
2591 if (instr->Bit(8) == 0) {
2593 set_sregister(sd, instr->ImmFloatField());
2596 set_dregister(dd, instr->ImmDoubleField());
2600 switch (instr->Bits(16, 4)) {
2602 switch (instr->Bits(6, 2)) {
2604 if (instr->Bit(8) == 0) {
2606 set_sregister(sd, get_sregister(sm));
2609 set_dregister(dd, get_dregister(dm));
2614 if (instr->Bit(8) == 0) {
2616 set_sregister(sd, fabsf(get_sregister(sm)));
2619 set_dregister(dd, fabs(get_dregister(dm)));
2624 UnimplementedInstruction(instr);
2631 switch (instr->Bits(6, 2)) {
2633 if (instr->Bit(8) == 0) {
2635 set_sregister(sd, -get_sregister(sm));
2638 set_dregister(dd, -get_dregister(dm));
2643 if (instr->Bit(8) == 0) {
2645 set_sregister(sd, sqrtf(get_sregister(sm)));
2648 set_dregister(dd,
sqrt(get_dregister(dm)));
2653 UnimplementedInstruction(instr);
2661 if (instr->Bit(7) == 1) {
2662 UnimplementedInstruction(instr);
2668 if (instr->Bit(8) == 0) {
2669 float sd_val = get_sregister(sd);
2671 if (instr->Bit(16) == 0) {
2673 sm_val = get_sregister(sm);
2678 if (isnan(sd_val) || isnan(sm_val)) {
2681 }
else if (sd_val == sm_val) {
2684 }
else if (sd_val < sm_val) {
2690 double dd_val = get_dregister(dd);
2692 if (instr->Bit(16) == 0) {
2694 dm_val = get_dregister(dm);
2699 if (isnan(dd_val) || isnan(dm_val)) {
2702 }
else if (dd_val == dm_val) {
2705 }
else if (dd_val < dm_val) {
2715 if (instr->Bit(8) == 0) {
2717 dd = instr->DdField();
2718 set_dregister(dd,
static_cast<double>(get_sregister(sm)));
2721 sd = instr->SdField();
2722 set_sregister(sd,
static_cast<float>(get_dregister(dm)));
2727 sm = instr->SmField();
2728 int32_t sm_int = get_sregister_bits(sm);
2729 uint32_t ud_val = 0;
2731 if (instr->Bit(7) == 0) {
2732 ud_val =
static_cast<uint32_t
>(sm_int);
2736 if (instr->Bit(8) == 0) {
2738 if (instr->Bit(7) == 0) {
2740 sd_val =
static_cast<float>(ud_val);
2743 sd_val =
static_cast<float>(id_val);
2745 set_sregister(sd, sd_val);
2748 if (instr->Bit(7) == 0) {
2750 dd_val =
static_cast<double>(ud_val);
2753 dd_val =
static_cast<double>(id_val);
2755 set_dregister(dd, dd_val);
2763 if (instr->Bit(7) == 0) {
2765 UnimplementedInstruction(instr);
2769 uint32_t ud_val = 0;
2770 if (instr->Bit(8) == 0) {
2771 float sm_val = get_sregister(sm);
2772 if (instr->Bit(16) == 0) {
2774 if (sm_val >=
static_cast<float>(INT32_MAX)) {
2776 }
else if (sm_val > 0.0) {
2777 ud_val =
static_cast<uint32_t
>(sm_val);
2781 if (sm_val <=
static_cast<float>(INT32_MIN)) {
2783 }
else if (sm_val >=
static_cast<float>(INT32_MAX)) {
2786 id_val =
static_cast<int32_t
>(sm_val);
2788 ASSERT((id_val >= 0) || !(sm_val >= 0.0));
2791 sd = instr->SdField();
2792 double dm_val = get_dregister(dm);
2793 if (instr->Bit(16) == 0) {
2795 if (dm_val >=
static_cast<double>(INT32_MAX)) {
2797 }
else if (dm_val > 0.0) {
2798 ud_val =
static_cast<uint32_t
>(dm_val);
2802 if (dm_val <=
static_cast<double>(INT32_MIN)) {
2804 }
else if (dm_val >=
static_cast<double>(INT32_MAX)) {
2806 }
else if (isnan(dm_val)) {
2809 id_val =
static_cast<int32_t
>(dm_val);
2811 ASSERT((id_val >= 0) || !(dm_val >= 0.0));
2815 if (instr->Bit(16) == 0) {
2816 sd_val =
static_cast<int32_t
>(ud_val);
2820 set_sregister_bits(sd, sd_val);
2831 UnimplementedInstruction(instr);
2839 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) {
2842 if (instr->Bit(20) == 0) {
2844 set_sregister_bits(sn, get_register(rd));
2847 set_register(rd, get_sregister_bits(sn));
2849 }
else if ((instr->Bits(22, 3) == 0) && (instr->Bit(20) == 0) &&
2850 (instr->Bit(8) == 1) && (instr->Bits(5, 2) == 0)) {
2853 const int32_t src_value = get_register(rd);
2854 const int64_t dst_value = get_dregister_bits(dn);
2855 int32_t dst_lo = Utils::Low32Bits(dst_value);
2856 int32_t dst_hi = Utils::High32Bits(dst_value);
2857 if (instr->Bit(21) == 0) {
2864 set_dregister_bits(dn, Utils::LowHighTo64Bits(dst_lo, dst_hi));
2865 }
else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0)) {
2866 if (instr->Bits(12, 4) == 0xf) {
2868 n_flag_ = fp_n_flag_;
2869 z_flag_ = fp_z_flag_;
2870 c_flag_ = fp_c_flag_;
2871 v_flag_ = fp_v_flag_;
2874 const int32_t n_flag = fp_n_flag_ ? (1 << 31) : 0;
2875 const int32_t z_flag = fp_z_flag_ ? (1 << 30) : 0;
2876 const int32_t c_flag = fp_c_flag_ ? (1 << 29) : 0;
2877 const int32_t v_flag = fp_v_flag_ ? (1 << 28) : 0;
2878 set_register(instr->RdField(), n_flag | z_flag | c_flag | v_flag);
2881 UnimplementedInstruction(instr);
2885 UnimplementedInstruction(instr);
2889static void simd_value_swap(simd_value_t* s1,
2894 tmp = s1->data_[i1].u;
2895 s1->data_[i1].u = s2->data_[i2].u;
2896 s2->data_[i2].u = tmp;
2899static float vminf(
float f1,
float f2) {
2902 return signbit(f1) ? f1 : f2;
2904 return f1 > f2 ? f2 : f1;
2907static float vmaxf(
float f1,
float f2) {
2910 return signbit(f1) ? f2 : f1;
2912 return f1 < f2 ? f2 : f1;
2915void Simulator::DecodeSIMDDataProcessing(Instr* instr) {
2916 ASSERT(instr->ConditionField() == kSpecialCondition);
2918 if (instr->Bit(6) == 1) {
2927 get_qregister(qn, &s8n);
2928 get_qregister(qm, &s8m);
2929 int8_t* s8d_8 =
reinterpret_cast<int8_t*
>(&s8d);
2930 int8_t* s8n_8 =
reinterpret_cast<int8_t*
>(&s8n);
2931 int8_t* s8m_8 =
reinterpret_cast<int8_t*
>(&s8m);
2932 uint8_t* s8d_u8 =
reinterpret_cast<uint8_t*
>(&s8d);
2933 uint8_t* s8n_u8 =
reinterpret_cast<uint8_t*
>(&s8n);
2934 uint8_t* s8m_u8 =
reinterpret_cast<uint8_t*
>(&s8m);
2935 int16_t* s8d_16 =
reinterpret_cast<int16_t*
>(&s8d);
2936 int16_t* s8n_16 =
reinterpret_cast<int16_t*
>(&s8n);
2937 int16_t* s8m_16 =
reinterpret_cast<int16_t*
>(&s8m);
2938 uint16_t* s8d_u16 =
reinterpret_cast<uint16_t*
>(&s8d);
2939 uint16_t* s8n_u16 =
reinterpret_cast<uint16_t*
>(&s8n);
2940 uint16_t* s8m_u16 =
reinterpret_cast<uint16_t*
>(&s8m);
2941 int32_t* s8d_32 =
reinterpret_cast<int32_t*
>(&s8d);
2942 int32_t* s8n_32 =
reinterpret_cast<int32_t*
>(&s8n);
2943 int32_t* s8m_32 =
reinterpret_cast<int32_t*
>(&s8m);
2944 uint32_t* s8d_u32 =
reinterpret_cast<uint32_t*
>(&s8d);
2945 uint32_t* s8m_u32 =
reinterpret_cast<uint32_t*
>(&s8m);
2946 int64_t* s8d_64 =
reinterpret_cast<int64_t*
>(&s8d);
2947 int64_t* s8n_64 =
reinterpret_cast<int64_t*
>(&s8n);
2948 int64_t* s8m_64 =
reinterpret_cast<int64_t*
>(&s8m);
2949 uint64_t* s8d_u64 =
reinterpret_cast<uint64_t*
>(&s8d);
2950 uint64_t* s8m_u64 =
reinterpret_cast<uint64_t*
>(&s8m);
2952 if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
2953 (instr->Bits(23, 2) == 0)) {
2956 const int size = instr->Bits(20, 2);
2958 for (
int i = 0; i < 16; i++) {
2959 s8d_8[i] = s8n_8[i] + s8m_8[i];
2961 }
else if (size == 1) {
2962 for (
int i = 0; i < 8; i++) {
2963 s8d_16[i] = s8n_16[i] + s8m_16[i];
2965 }
else if (size == 2) {
2966 for (
int i = 0; i < 4; i++) {
2967 s8d.data_[i].u = s8n.data_[i].u + s8m.data_[i].u;
2969 }
else if (size == 3) {
2970 for (
int i = 0; i < 2; i++) {
2971 s8d_64[i] = s8n_64[i] + s8m_64[i];
2976 }
else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
2977 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) {
2979 for (
int i = 0; i < 4; i++) {
2980 s8d.data_[i].f = s8n.data_[i].f + s8m.data_[i].f;
2982 }
else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
2983 (instr->Bits(23, 2) == 2)) {
2985 const int size = instr->Bits(20, 2);
2987 for (
int i = 0; i < 16; i++) {
2988 s8d_8[i] = s8n_8[i] - s8m_8[i];
2990 }
else if (size == 1) {
2991 for (
int i = 0; i < 8; i++) {
2992 s8d_16[i] = s8n_16[i] - s8m_16[i];
2994 }
else if (size == 2) {
2995 for (
int i = 0; i < 4; i++) {
2996 s8d.data_[i].u = s8n.data_[i].u - s8m.data_[i].u;
2998 }
else if (size == 3) {
2999 for (
int i = 0; i < 2; i++) {
3000 s8d_64[i] = s8n_64[i] - s8m_64[i];
3005 }
else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
3006 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 1)) {
3008 for (
int i = 0; i < 4; i++) {
3009 s8d.data_[i].f = s8n.data_[i].f - s8m.data_[i].f;
3011 }
else if ((instr->Bits(8, 4) == 9) && (instr->Bit(4) == 1) &&
3012 (instr->Bits(23, 2) == 0)) {
3014 const int size = instr->Bits(20, 2);
3016 for (
int i = 0; i < 16; i++) {
3017 s8d_8[i] = s8n_8[i] * s8m_8[i];
3019 }
else if (size == 1) {
3020 for (
int i = 0; i < 8; i++) {
3021 s8d_16[i] = s8n_16[i] * s8m_16[i];
3023 }
else if (size == 2) {
3024 for (
int i = 0; i < 4; i++) {
3025 s8d.data_[i].u = s8n.data_[i].u * s8m.data_[i].u;
3027 }
else if (size == 3) {
3028 UnimplementedInstruction(instr);
3032 }
else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
3033 (instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
3035 for (
int i = 0; i < 4; i++) {
3036 s8d.data_[i].f = s8n.data_[i].f * s8m.data_[i].f;
3038 }
else if ((instr->Bits(8, 4) == 4) && (instr->Bit(4) == 0) &&
3039 (instr->Bit(23) == 0) && (instr->Bits(25, 3) == 1)) {
3042 const bool is_signed = instr->Bit(24) == 0;
3043 const int size = instr->Bits(20, 2);
3045 for (
int i = 0; i < 16; i++) {
3046 int8_t shift = s8n_8[i];
3048 s8d_u8[i] = s8m_u8[i] << shift;
3049 }
else if (shift < 0) {
3051 s8d_8[i] = s8m_8[i] >> (-shift);
3053 s8d_u8[i] = s8m_u8[i] >> (-shift);
3057 }
else if (size == 1) {
3058 for (
int i = 0; i < 8; i++) {
3059 int8_t shift = s8n_8[i * 2];
3061 s8d_u16[i] = s8m_u16[i] << shift;
3062 }
else if (shift < 0) {
3064 s8d_16[i] = s8m_16[i] >> (-shift);
3066 s8d_u16[i] = s8m_u16[i] >> (-shift);
3070 }
else if (size == 2) {
3071 for (
int i = 0; i < 4; i++) {
3072 int8_t shift = s8n_8[i * 4];
3074 s8d_u32[i] = s8m_u32[i] << shift;
3075 }
else if (shift < 0) {
3077 s8d_32[i] = s8m_32[i] >> (-shift);
3079 s8d_u32[i] = s8m_u32[i] >> (-shift);
3085 for (
int i = 0; i < 2; i++) {
3086 int8_t shift = s8n_8[i * 8];
3088 s8d_u64[i] = s8m_u64[i] << shift;
3089 }
else if (shift < 0) {
3091 s8d_64[i] = s8m_64[i] >> (-shift);
3093 s8d_u64[i] = s8m_u64[i] >> (-shift);
3098 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3099 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
3101 for (
int i = 0; i < 4; i++) {
3102 s8d.data_[i].u = s8n.data_[i].u ^ s8m.data_[i].u;
3104 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3105 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
3107 for (
int i = 0; i < 4; i++) {
3108 s8d.data_[i].u = s8n.data_[i].u | ~s8m.data_[i].u;
3110 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3111 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
3114 for (
int i = 0; i < 4; i++) {
3115 s8d.data_[i].u = s8m.data_[i].u;
3119 for (
int i = 0; i < 4; i++) {
3120 s8d.data_[i].u = s8n.data_[i].u | s8m.data_[i].u;
3123 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3124 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3126 for (
int i = 0; i < 4; i++) {
3127 s8d.data_[i].u = s8n.data_[i].u & s8m.data_[i].u;
3129 }
else if ((instr->Bits(7, 5) == 11) && (instr->Bit(4) == 0) &&
3130 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 5) == 7) &&
3131 (instr->Bits(16, 4) == 0)) {
3133 for (
int i = 0; i < 4; i++) {
3134 s8d.data_[i].u = ~s8m.data_[i].u;
3136 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) &&
3137 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
3139 for (
int i = 0; i < 4; i++) {
3140 s8d.data_[i].f = vminf(s8n.data_[i].f, s8m.data_[i].f);
3142 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) &&
3143 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3145 for (
int i = 0; i < 4; i++) {
3146 s8d.data_[i].f = vmaxf(s8n.data_[i].f, s8m.data_[i].f);
3148 }
else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) &&
3149 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3150 (instr->Bit(7) == 0) && (instr->Bits(16, 4) == 9)) {
3152 for (
int i = 0; i < 4; i++) {
3153 s8d.data_[i].f = fabsf(s8m.data_[i].f);
3155 }
else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) &&
3156 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3157 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 9)) {
3159 for (
int i = 0; i < 4; i++) {
3160 s8d.data_[i].f = -s8m.data_[i].f;
3162 }
else if ((instr->Bits(7, 5) == 10) && (instr->Bit(4) == 0) &&
3163 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3164 (instr->Bits(16, 4) == 11)) {
3166 for (
int i = 0; i < 4; i++) {
3169 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 1) &&
3170 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3172 for (
int i = 0; i < 4; i++) {
3175 }
else if ((instr->Bits(8, 4) == 5) && (instr->Bit(4) == 0) &&
3176 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3177 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 11)) {
3179 for (
int i = 0; i < 4; i++) {
3182 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 1) &&
3183 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
3185 for (
int i = 0; i < 4; i++) {
3188 }
else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
3189 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3190 (instr->Bit(7) == 0)) {
3192 int64_t dm_value = get_dregister_bits(dm);
3193 int32_t imm4 = instr->Bits(16, 4);
3195 if ((imm4 & 1) != 0) {
3197 int8_t* dm_b =
reinterpret_cast<int8_t*
>(&dm_value);
3199 int8_t val = dm_b[idx];
3200 for (
int i = 0; i < 16; i++) {
3203 }
else if ((imm4 & 2) != 0) {
3205 int16_t* dm_h =
reinterpret_cast<int16_t*
>(&dm_value);
3207 int16_t val = dm_h[idx];
3208 for (
int i = 0; i < 8; i++) {
3211 }
else if ((imm4 & 4) != 0) {
3213 int32_t* dm_w =
reinterpret_cast<int32_t*
>(&dm_value);
3215 int32_t val = dm_w[idx];
3216 for (
int i = 0; i < 4; i++) {
3217 s8d.data_[i].u = val;
3220 UnimplementedInstruction(instr);
3222 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 0) &&
3223 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3224 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 10)) {
3226 get_qregister(qd, &s8d);
3230 simd_value_swap(&s8d, 3, &s8m, 2);
3231 simd_value_swap(&s8d, 3, &s8m, 1);
3232 simd_value_swap(&s8d, 2, &s8m, 0);
3233 simd_value_swap(&s8d, 2, &s8d, 1);
3235 set_qregister(qm, s8m);
3236 }
else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
3237 (instr->Bits(23, 2) == 2)) {
3239 const int size = instr->Bits(20, 2);
3241 for (
int i = 0; i < 16; i++) {
3242 s8d_8[i] = s8n_8[i] == s8m_8[i] ? 0xff : 0;
3244 }
else if (size == 1) {
3245 for (
int i = 0; i < 8; i++) {
3246 s8d_16[i] = s8n_16[i] == s8m_16[i] ? 0xffff : 0;
3248 }
else if (size == 2) {
3249 for (
int i = 0; i < 4; i++) {
3250 s8d.data_[i].u = s8n.data_[i].u == s8m.data_[i].u ? 0xffffffff : 0;
3252 }
else if (size == 3) {
3253 UnimplementedInstruction(instr);
3257 }
else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
3258 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3260 for (
int i = 0; i < 4; i++) {
3261 s8d.data_[i].u = s8n.data_[i].f == s8m.data_[i].f ? 0xffffffff : 0;
3263 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
3264 (instr->Bits(23, 2) == 0)) {
3266 const int size = instr->Bits(20, 2);
3268 for (
int i = 0; i < 16; i++) {
3269 s8d_8[i] = s8n_8[i] >= s8m_8[i] ? 0xff : 0;
3271 }
else if (size == 1) {
3272 for (
int i = 0; i < 8; i++) {
3273 s8d_16[i] = s8n_16[i] >= s8m_16[i] ? 0xffff : 0;
3275 }
else if (size == 2) {
3276 for (
int i = 0; i < 4; i++) {
3277 s8d.data_[i].u = s8n_32[i] >= s8m_32[i] ? 0xffffffff : 0;
3279 }
else if (size == 3) {
3280 UnimplementedInstruction(instr);
3284 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
3285 (instr->Bits(23, 2) == 2)) {
3287 const int size = instr->Bits(20, 2);
3289 for (
int i = 0; i < 16; i++) {
3290 s8d_8[i] = s8n_u8[i] >= s8m_u8[i] ? 0xff : 0;
3292 }
else if (size == 1) {
3293 for (
int i = 0; i < 8; i++) {
3294 s8d_16[i] = s8n_u16[i] >= s8m_u16[i] ? 0xffff : 0;
3296 }
else if (size == 2) {
3297 for (
int i = 0; i < 4; i++) {
3298 s8d.data_[i].u = s8n.data_[i].u >= s8m.data_[i].u ? 0xffffffff : 0;
3300 }
else if (size == 3) {
3301 UnimplementedInstruction(instr);
3305 }
else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
3306 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
3308 for (
int i = 0; i < 4; i++) {
3309 s8d.data_[i].u = s8n.data_[i].f >= s8m.data_[i].f ? 0xffffffff : 0;
3311 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
3312 (instr->Bits(23, 2) == 0)) {
3314 const int size = instr->Bits(20, 2);
3316 for (
int i = 0; i < 16; i++) {
3317 s8d_8[i] = s8n_8[i] > s8m_8[i] ? 0xff : 0;
3319 }
else if (size == 1) {
3320 for (
int i = 0; i < 8; i++) {
3321 s8d_16[i] = s8n_16[i] > s8m_16[i] ? 0xffff : 0;
3323 }
else if (size == 2) {
3324 for (
int i = 0; i < 4; i++) {
3325 s8d.data_[i].u = s8n_32[i] > s8m_32[i] ? 0xffffffff : 0;
3327 }
else if (size == 3) {
3328 UnimplementedInstruction(instr);
3332 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
3333 (instr->Bits(23, 2) == 2)) {
3335 const int size = instr->Bits(20, 2);
3337 for (
int i = 0; i < 16; i++) {
3338 s8d_8[i] = s8n_u8[i] > s8m_u8[i] ? 0xff : 0;
3340 }
else if (size == 1) {
3341 for (
int i = 0; i < 8; i++) {
3342 s8d_16[i] = s8n_u16[i] > s8m_u16[i] ? 0xffff : 0;
3344 }
else if (size == 2) {
3345 for (
int i = 0; i < 4; i++) {
3346 s8d.data_[i].u = s8n.data_[i].u > s8m.data_[i].u ? 0xffffffff : 0;
3348 }
else if (size == 3) {
3349 UnimplementedInstruction(instr);
3353 }
else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
3354 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
3356 for (
int i = 0; i < 4; i++) {
3357 s8d.data_[i].u = s8n.data_[i].f > s8m.data_[i].f ? 0xffffffff : 0;
3360 UnimplementedInstruction(instr);
3363 set_qregister(qd, s8d);
3366 if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) &&
3367 (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) {
3371 int reg_count = instr->Bits(8, 2) + 1;
3372 int start = (instr->Bit(7) << 4) | instr->Bits(16, 4);
3375 for (
int i = 0; i < reg_count; i++) {
3377 table[i] = get_dregister_bits(
d);
3379 for (
int i = reg_count; i < 4; i++) {
3383 int64_t dm_value = get_dregister_bits(dm);
3385 int8_t* dm_bytes =
reinterpret_cast<int8_t*
>(&dm_value);
3386 int8_t* result_bytes =
reinterpret_cast<int8_t*
>(&
result);
3387 int8_t* table_bytes =
reinterpret_cast<int8_t*
>(&
table[0]);
3388 for (
int i = 0; i < 8; i++) {
3389 int idx = dm_bytes[i];
3390 if ((idx >= 0) && (idx < 256)) {
3391 result_bytes[i] = table_bytes[idx];
3393 result_bytes[i] = 0;
3397 set_dregister_bits(dd,
result);
3399 UnimplementedInstruction(instr);
3405DART_FORCE_INLINE
void Simulator::InstructionDecodeImpl(Instr* instr) {
3406 pc_modified_ =
false;
3407 if (instr->ConditionField() == kSpecialCondition) {
3408 if (instr->InstructionBits() ==
static_cast<int32_t
>(0xf57ff01f)) {
3411 }
else if (instr->InstructionBits() ==
3412 static_cast<int32_t
>(kDataMemoryBarrier)) {
3414 std::atomic_thread_fence(std::memory_order_seq_cst);
3416 if (instr->IsSIMDDataProcessing()) {
3417 DecodeSIMDDataProcessing(instr);
3419 UnimplementedInstruction(instr);
3422 }
else if (ConditionallyExecute(instr)) {
3423 switch (instr->TypeField()) {
3426 DecodeType01(instr);
3460 if (!pc_modified_) {
3461 set_register(PC,
reinterpret_cast<int32_t
>(instr) + Instr::kInstrSize);
3465void Simulator::InstructionDecode(Instr* instr) {
3466 if (IsTracingExecution()) {
3470 if (FLAG_support_disassembler) {
3471 Disassembler::Disassemble(
start,
end);
3473 THR_Print(
"Disassembler not supported in this mode.\n");
3476 InstructionDecodeImpl(instr);
3479void Simulator::Execute() {
3480 if (
LIKELY(FLAG_stop_sim_at == ULLONG_MAX &&
3481 FLAG_trace_sim_after == ULLONG_MAX)) {
3488void Simulator::ExecuteNoTrace() {
3491 uword program_counter = get_pc();
3495 while (program_counter != kEndSimulatingPC) {
3496 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3498 InstructionDecodeImpl(instr);
3499 program_counter = get_pc();
3503void Simulator::ExecuteTrace() {
3506 uword program_counter = get_pc();
3510 while (program_counter != kEndSimulatingPC) {
3511 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3513 if (icount_ == FLAG_stop_sim_at) {
3514 SimulatorDebugger dbg(
this);
3515 dbg.Stop(instr,
"Instruction count reached");
3516 }
else if (
reinterpret_cast<uint64_t
>(instr) == FLAG_stop_sim_at) {
3517 SimulatorDebugger dbg(
this);
3518 dbg.Stop(instr,
"Instruction address reached");
3519 }
else if (IsIllegalAddress(program_counter)) {
3520 HandleIllegalAccess(program_counter, instr);
3522 InstructionDecode(instr);
3524 program_counter = get_pc();
3528int64_t Simulator::Call(int32_t entry,
3536 int32_t sp_before_call = get_register(SP);
3540 set_sregister(S0, bit_cast<float, int32_t>(parameter0));
3541 set_sregister(S1, bit_cast<float, int32_t>(parameter1));
3542 set_sregister(S2, bit_cast<float, int32_t>(parameter2));
3543 set_sregister(S3, bit_cast<float, int32_t>(parameter3));
3545 set_register(R0, parameter0);
3546 set_register(R1, parameter1);
3547 set_register(R2, parameter2);
3548 set_register(R3, parameter3);
3552 int32_t stack_pointer = sp_before_call;
3553 if (OS::ActivationFrameAlignment() > 1) {
3555 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
3557 set_register(SP, stack_pointer);
3560 set_register(PC, entry);
3564 set_register(
LR, kEndSimulatingPC);
3569 int32_t r4_val = get_register(R4);
3570 int32_t r5_val = get_register(R5);
3571 int32_t r6_val = get_register(R6);
3572 int32_t r7_val = get_register(R7);
3573 int32_t r8_val = get_register(R8);
3574#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3575 int32_t r9_val = get_register(R9);
3577 int32_t r10_val = get_register(R10);
3578 int32_t r11_val = get_register(R11);
3580 double d8_val = 0.0;
3581 double d9_val = 0.0;
3582 double d10_val = 0.0;
3583 double d11_val = 0.0;
3584 double d12_val = 0.0;
3585 double d13_val = 0.0;
3586 double d14_val = 0.0;
3587 double d15_val = 0.0;
3589 d8_val = get_dregister(D8);
3590 d9_val = get_dregister(D9);
3591 d10_val = get_dregister(D10);
3592 d11_val = get_dregister(D11);
3593 d12_val = get_dregister(D12);
3594 d13_val = get_dregister(D13);
3595 d14_val = get_dregister(D14);
3596 d15_val = get_dregister(D15);
3600 int32_t callee_saved_value = icount_;
3601 set_register(R4, callee_saved_value);
3602 set_register(R5, callee_saved_value);
3603 set_register(R6, callee_saved_value);
3604 set_register(R7, callee_saved_value);
3605 set_register(R8, callee_saved_value);
3606#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3607 set_register(R9, callee_saved_value);
3609 set_register(R10, callee_saved_value);
3610 set_register(R11, callee_saved_value);
3612 double callee_saved_dvalue = 0.0;
3613 callee_saved_dvalue =
static_cast<double>(icount_);
3614 set_dregister(D8, callee_saved_dvalue);
3615 set_dregister(D9, callee_saved_dvalue);
3616 set_dregister(D10, callee_saved_dvalue);
3617 set_dregister(D11, callee_saved_dvalue);
3618 set_dregister(D12, callee_saved_dvalue);
3619 set_dregister(D13, callee_saved_dvalue);
3620 set_dregister(D14, callee_saved_dvalue);
3621 set_dregister(D15, callee_saved_dvalue);
3627 ASSERT(callee_saved_value == get_register(R4));
3628 ASSERT(callee_saved_value == get_register(R5));
3629 ASSERT(callee_saved_value == get_register(R6));
3630 ASSERT(callee_saved_value == get_register(R7));
3631 ASSERT(callee_saved_value == get_register(R8));
3632#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3633 ASSERT(callee_saved_value == get_register(R9));
3635 ASSERT(callee_saved_value == get_register(R10));
3636 ASSERT(callee_saved_value == get_register(R11));
3638 ASSERT(callee_saved_dvalue == get_dregister(D8));
3639 ASSERT(callee_saved_dvalue == get_dregister(D9));
3640 ASSERT(callee_saved_dvalue == get_dregister(D10));
3641 ASSERT(callee_saved_dvalue == get_dregister(D11));
3642 ASSERT(callee_saved_dvalue == get_dregister(D12));
3643 ASSERT(callee_saved_dvalue == get_dregister(D13));
3644 ASSERT(callee_saved_dvalue == get_dregister(D14));
3645 ASSERT(callee_saved_dvalue == get_dregister(D15));
3648 set_register(R4, r4_val);
3649 set_register(R5, r5_val);
3650 set_register(R6, r6_val);
3651 set_register(R7, r7_val);
3652 set_register(R8, r8_val);
3653#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3654 set_register(R9, r9_val);
3656 set_register(R10, r10_val);
3657 set_register(R11, r11_val);
3659 set_dregister(D8, d8_val);
3660 set_dregister(D9, d9_val);
3661 set_dregister(D10, d10_val);
3662 set_dregister(D11, d11_val);
3663 set_dregister(D12, d12_val);
3664 set_dregister(D13, d13_val);
3665 set_dregister(D14, d14_val);
3666 set_dregister(D15, d15_val);
3669 set_register(SP, sp_before_call);
3670 int64_t return_value;
3672 return_value = bit_cast<int64_t, double>(get_dregister(D0));
3674 return_value = Utils::LowHighTo64Bits(get_register(R0), get_register(R1));
3676 return return_value;
3679void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
3682 SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
3683 while (buf->link() !=
nullptr && buf->link()->sp() <= sp) {
3691 StackResource::Unwind(thread);
3696 set_register(PC,
static_cast<int32_t
>(pc));
3697 set_register(SP,
static_cast<int32_t
>(sp));
3698 set_register(FP,
static_cast<int32_t
>(fp));
3699 set_register(THR,
reinterpret_cast<uword>(thread));
3701 thread->set_vm_tag(VMTag::kDartTagId);
3703 thread->set_top_exit_frame_info(0);
3706 *
reinterpret_cast<int32_t*
>(
fp + kPcMarkerSlotFromFp *
kWordSize);
3707 int32_t pp = FLAG_precompiled_mode
3708 ?
static_cast<int32_t
>(thread->global_object_pool())
3709 : *reinterpret_cast<int32_t*>(
3712 set_register(CODE_REG, code);
3713 set_register(PP, pp);
3714 if (FLAG_precompiled_mode) {
3715 set_register(DISPATCH_TABLE_REG,
3716 reinterpret_cast<int32_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 rotate(const SkDCubic &cubic, int zero, int index, SkDCubic &rotPath)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
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)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
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
const GrXPFactory * Get(SkBlendMode mode)
bool Contains(const Container &container, const Value &value)
static int64_t GetValue(Dart_Handle arg)
float ReciprocalSqrtEstimate(float op)
void SetBreakpoint(Dart_NativeArguments args)
float ReciprocalStep(float op1, float op2)
float ReciprocalSqrtStep(float op1, float op2)
constexpr intptr_t kWordSize
float ReciprocalEstimate(float op)
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)
#define NO_SANITIZE_UNDEFINED(check)
#define ARRAY_SIZE(array)
#define OFFSET_OF(type, field)