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);
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"};
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);
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;
197bool SimulatorDebugger::GetFValue(
char*
desc,
float*
value) {
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) {
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();
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");
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();
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);
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)) {
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;
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) {
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) {
919 sregisters_[reg] = bit_cast<int32_t, float>(
value);
922DART_FORCE_INLINE
float Simulator::get_sregister(
SRegister reg)
const {
924 return bit_cast<float, int32_t>(sregisters_[reg]);
927DART_FORCE_INLINE
void Simulator::set_dregister(
DRegister reg,
double value) {
929 dregisters_[reg] = bit_cast<int64_t, double>(
value);
932DART_FORCE_INLINE
double Simulator::get_dregister(
DRegister reg)
const {
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());
940 memcpy(&qregisters_[reg], &
value,
sizeof(
value));
943void Simulator::get_qregister(
QRegister reg, simd_value_t*
value)
const {
944 ASSERT(TargetCPUFeatures::neon_supported());
948 *
value = qregisters_[reg];
954 sregisters_[reg] =
value;
957int32_t Simulator::get_sregister_bits(
SRegister reg)
const {
959 return sregisters_[reg];
964 dregisters_[reg] =
value;
967int64_t Simulator::get_dregister_bits(
DRegister reg)
const {
969 return dregisters_[reg];
972void Simulator::HandleIllegalAccess(
uword addr, Instr* instr) {
973 uword fault_pc = get_pc();
978 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n",
addr,
980 SimulatorDebugger dbg(
this);
983 FATAL(
"Cannot continue execution after illegal memory access.");
986void Simulator::UnimplementedInstruction(Instr* instr) {
988 snprintf(
buffer,
sizeof(
buffer),
"Unimplemented instruction: pc=%p\n", instr);
989 SimulatorDebugger dbg(
this);
991 FATAL(
"Cannot continue execution after unimplemented instruction.");
994DART_FORCE_INLINE intptr_t Simulator::ReadW(
uword addr, Instr* instr) {
995 return *
reinterpret_cast<intptr_t*
>(
addr);
998DART_FORCE_INLINE
void Simulator::WriteW(
uword addr,
1001 *
reinterpret_cast<intptr_t*
>(
addr) =
value;
1004DART_FORCE_INLINE uint16_t Simulator::ReadHU(
uword addr, Instr* instr) {
1005 return *
reinterpret_cast<uint16_t*
>(
addr);
1008DART_FORCE_INLINE int16_t Simulator::ReadH(
uword addr, Instr* instr) {
1009 return *
reinterpret_cast<int16_t*
>(
addr);
1012DART_FORCE_INLINE
void Simulator::WriteH(
uword addr,
1015 *
reinterpret_cast<uint16_t*
>(
addr) =
value;
1018DART_FORCE_INLINE uint8_t Simulator::ReadBU(
uword addr) {
1019 return *
reinterpret_cast<uint8_t*
>(
addr);
1022DART_FORCE_INLINE int8_t Simulator::ReadB(
uword addr) {
1023 return *
reinterpret_cast<int8_t*
>(
addr);
1026DART_FORCE_INLINE
void Simulator::WriteB(
uword addr, uint8_t
value) {
1027 *
reinterpret_cast<uint8_t*
>(
addr) =
value;
1030void Simulator::ClearExclusive() {
1031 exclusive_access_addr_ = 0;
1032 exclusive_access_value_ = 0;
1035intptr_t Simulator::ReadExclusiveW(
uword addr, Instr* instr) {
1036 exclusive_access_addr_ =
addr;
1037 exclusive_access_value_ = ReadW(
addr, instr);
1038 return exclusive_access_value_;
1041intptr_t Simulator::WriteExclusiveW(
uword addr, intptr_t
value, Instr* instr) {
1044 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ ==
addr));
1045 if (exclusive_access_addr_ !=
addr) {
1049 int32_t old_value =
static_cast<uint32_t
>(exclusive_access_value_);
1052 if ((random_.NextUInt32() % 16) == 0) {
1056 auto atomic_addr =
reinterpret_cast<RelaxedAtomic<int32_t>*
>(
addr);
1057 if (atomic_addr->compare_exchange_weak(old_value,
value)) {
1063bool Simulator::IsTracingExecution()
const {
1064 return icount_ > FLAG_trace_sim_after;
1069 OS::PrintErr(
"Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
1076DART_FORCE_INLINE
bool Simulator::ConditionallyExecute(Instr* instr) {
1077 switch (instr->ConditionField()) {
1095 return c_flag_ && !z_flag_;
1097 return !c_flag_ || z_flag_;
1099 return n_flag_ == v_flag_;
1101 return n_flag_ != v_flag_;
1103 return !z_flag_ && (n_flag_ == v_flag_);
1105 return z_flag_ || (n_flag_ != v_flag_);
1115DART_FORCE_INLINE
void Simulator::SetNZFlags(int32_t val) {
1116 n_flag_ = (val < 0);
1117 z_flag_ = (val == 0);
1121DART_FORCE_INLINE
void Simulator::SetCFlag(
bool val) {
1126DART_FORCE_INLINE
void Simulator::SetVFlag(
bool val) {
1131DART_FORCE_INLINE
bool Simulator::CarryFrom(int32_t
left,
1134 uint64_t uleft =
static_cast<uint32_t
>(
left);
1135 uint64_t uright =
static_cast<uint32_t
>(
right);
1136 uint64_t ucarry =
static_cast<uint32_t
>(carry);
1137 return ((uleft + uright + ucarry) >> 32) != 0;
1141DART_FORCE_INLINE
bool Simulator::OverflowFrom(int32_t
left,
1150int32_t Simulator::GetShiftRm(Instr* instr,
bool* carry_out) {
1151 Shift shift = instr->ShiftField();
1152 int shift_amount = instr->ShiftAmountField();
1153 int32_t
result = get_register(instr->RmField());
1154 if (instr->Bit(4) == 0) {
1156 if ((shift ==
ROR) && (shift_amount == 0)) {
1157 UnimplementedInstruction(instr);
1158 }
else if (((shift ==
LSR) || (shift ==
ASR)) && (shift_amount == 0)) {
1163 if (shift_amount == 0) {
1172 result >>= (shift_amount - 1);
1173 *carry_out = (
result & 1) == 1;
1180 if (shift_amount == 0) {
1181 *carry_out = c_flag_;
1183 result =
static_cast<uint32_t
>(
result) << (shift_amount - 1);
1184 *carry_out = (
result < 0);
1191 if (shift_amount == 0) {
1193 *carry_out = c_flag_;
1195 uint32_t uresult =
static_cast<uint32_t
>(
result);
1196 uresult >>= (shift_amount - 1);
1197 *carry_out = (uresult & 1) == 1;
1199 result =
static_cast<int32_t
>(uresult);
1205 UnimplementedInstruction(instr);
1217 shift_amount = get_register(rs) & 0xff;
1220 if (shift_amount == 0) {
1221 *carry_out = c_flag_;
1222 }
else if (shift_amount < 32) {
1223 result >>= (shift_amount - 1);
1224 *carry_out = (
result & 1) == 1;
1227 ASSERT(shift_amount >= 32);
1240 if (shift_amount == 0) {
1241 *carry_out = c_flag_;
1242 }
else if (shift_amount < 32) {
1243 result =
static_cast<uint32_t
>(
result) << (shift_amount - 1);
1244 *carry_out = (
result < 0);
1246 }
else if (shift_amount == 32) {
1247 *carry_out = (
result & 1) == 1;
1250 ASSERT(shift_amount > 32);
1258 if (shift_amount == 0) {
1259 *carry_out = c_flag_;
1260 }
else if (shift_amount < 32) {
1261 uint32_t uresult =
static_cast<uint32_t
>(
result);
1262 uresult >>= (shift_amount - 1);
1263 *carry_out = (uresult & 1) == 1;
1265 result =
static_cast<int32_t
>(uresult);
1266 }
else if (shift_amount == 32) {
1267 *carry_out = (
result < 0);
1277 UnimplementedInstruction(instr);
1292DART_FORCE_INLINE int32_t Simulator::GetImm(Instr* instr,
bool* carry_out) {
1293 uint8_t
rotate = instr->RotateField() * 2;
1294 int32_t immed8 = instr->Immed8Field();
1296 *carry_out = (
rotate == 0) ? c_flag_ : (imm < 0);
1301void Simulator::HandleRList(Instr* instr,
bool load) {
1303 int32_t rn_val = get_register(rn);
1304 int rlist = instr->RlistField();
1305 int num_regs = Utils::CountOneBits32(
static_cast<uint32_t
>(rlist));
1308 uword end_address = 0;
1309 switch (instr->PUField()) {
1312 address = rn_val - (num_regs * 4) + 4;
1313 end_address = rn_val + 4;
1314 rn_val = rn_val - (num_regs * 4);
1320 end_address = rn_val + (num_regs * 4);
1321 rn_val = rn_val + (num_regs * 4);
1326 address = rn_val - (num_regs * 4);
1327 end_address = rn_val;
1333 address = rn_val + 4;
1334 end_address = rn_val + (num_regs * 4) + 4;
1335 rn_val = rn_val + (num_regs * 4);
1343 if (IsIllegalAddress(address)) {
1344 HandleIllegalAccess(address, instr);
1346 if (instr->HasW()) {
1347 set_register(rn, rn_val);
1350 while (rlist != 0) {
1351 if ((rlist & 1) != 0) {
1353 set_register(
static_cast<Register>(reg), ReadW(address, instr));
1355 WriteW(address, get_register(
static_cast<Register>(reg)), instr);
1362 ASSERT(end_address == address);
1367typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
1370typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0,
1381static int32_t InvokeLeafRuntime(SimulatorLeafRuntimeCall
target,
1387 return target(r0, r1, r2, r3, r4);
1391typedef double (*SimulatorLeafFloatRuntimeCall)(
double d0,
double d1);
1398static
double InvokeFloatLeafRuntime(SimulatorLeafFloatRuntimeCall
target,
1408void Simulator::SupervisorCall(Instr* instr) {
1409 int svc = instr->SvcField();
1411 case Instr::kSimulatorRedirectCode: {
1412 SimulatorSetjmpBuffer
buffer(
this);
1414 if (!setjmp(
buffer.buffer_)) {
1415 int32_t saved_lr = get_register(
LR);
1416 Redirection* redirection = Redirection::FromSvcInstruction(instr);
1417 uword external = redirection->external_function();
1418 if (IsTracingExecution()) {
1419 THR_Print(
"Call to host function at 0x%" Pd "\n", external);
1421 if (redirection->call_kind() == kRuntimeCall) {
1422 NativeArguments arguments;
1424 arguments.thread_ =
reinterpret_cast<Thread*
>(get_register(
R0));
1425 arguments.argc_tag_ = get_register(
R1);
1426 arguments.argv_ =
reinterpret_cast<ObjectPtr*
>(get_register(
R2));
1427 arguments.retval_ =
reinterpret_cast<ObjectPtr*
>(get_register(
R3));
1428 SimulatorRuntimeCall
target =
1429 reinterpret_cast<SimulatorRuntimeCall
>(external);
1431 ClobberVolatileRegisters();
1432 }
else if (redirection->call_kind() == kLeafRuntimeCall) {
1433 ASSERT((0 <= redirection->argument_count()) &&
1434 (redirection->argument_count() <= 5));
1435 int32_t r0 = get_register(
R0);
1436 int32_t r1 = get_register(
R1);
1437 int32_t r2 = get_register(
R2);
1438 int32_t r3 = get_register(
R3);
1439 int32_t r4 = *
reinterpret_cast<int32_t*
>(get_register(
SP));
1440 SimulatorLeafRuntimeCall
target =
1441 reinterpret_cast<SimulatorLeafRuntimeCall
>(external);
1442 r0 = InvokeLeafRuntime(
target, r0, r1, r2, r3, r4);
1443 ClobberVolatileRegisters();
1444 set_register(
R0, r0);
1445 }
else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
1446 ASSERT((0 <= redirection->argument_count()) &&
1447 (redirection->argument_count() <= 2));
1448 SimulatorLeafFloatRuntimeCall
target =
1449 reinterpret_cast<SimulatorLeafFloatRuntimeCall
>(external);
1450 if (TargetCPUFeatures::hardfp_supported()) {
1453 double d0 = get_dregister(
D0);
1454 double d1 = get_dregister(
D1);
1455 d0 = InvokeFloatLeafRuntime(
target, d0, d1);
1456 ClobberVolatileRegisters();
1457 set_dregister(
D0, d0);
1461 uint32_t r0 = get_register(
R0);
1462 int32_t r1 = get_register(
R1);
1463 uint32_t r2 = get_register(
R2);
1464 int32_t r3 = get_register(
R3);
1465 int64_t a0 = Utils::LowHighTo64Bits(r0, r1);
1466 int64_t a1 = Utils::LowHighTo64Bits(r2, r3);
1467 double d0 = bit_cast<double, int64_t>(a0);
1468 double d1 = bit_cast<double, int64_t>(a1);
1469 d0 = InvokeFloatLeafRuntime(
target, d0, d1);
1470 ClobberVolatileRegisters();
1471 a0 = bit_cast<int64_t, double>(d0);
1472 r0 = Utils::Low32Bits(a0);
1473 r1 = Utils::High32Bits(a0);
1474 set_register(
R0, r0);
1475 set_register(
R1, r1);
1478 ASSERT(redirection->call_kind() == kNativeCallWrapper);
1479 SimulatorNativeCallWrapper wrapper =
1480 reinterpret_cast<SimulatorNativeCallWrapper
>(external);
1485 wrapper(arguments, target_func);
1486 ClobberVolatileRegisters();
1497 case Instr::kSimulatorBreakCode: {
1498 SimulatorDebugger dbg(
this);
1499 dbg.Stop(instr,
"breakpoint");
1509void Simulator::ClobberVolatileRegisters() {
1511 exclusive_access_addr_ = exclusive_access_value_ = 0;
1515 registers_[
i] = random_.NextUInt32();
1519 double zap_dvalue =
static_cast<double>(icount_);
1520 for (
int i =
D0;
i <=
D7;
i++) {
1521 set_dregister(
static_cast<DRegister>(
i), zap_dvalue);
1525#if defined(VFPv3_D32)
1527 set_dregister(
static_cast<DRegister>(
i), zap_dvalue);
1536DART_FORCE_INLINE
void Simulator::DecodeType01(Instr* instr) {
1537 if (!instr->IsDataProcessing()) {
1539 if (instr->IsMiscellaneous()) {
1540 switch (instr->Bits(4, 3)) {
1542 if (instr->Bits(21, 2) == 0x3) {
1546 int32_t rm_val = get_register(rm);
1549 while (rm_val > 0) {
1556 set_register(rd, rd_val);
1558 ASSERT(instr->Bits(21, 2) == 0x1);
1561 int32_t rm_val = get_register(rm);
1567 ASSERT(instr->Bits(21, 2) == 0x1);
1570 int32_t rm_val = get_register(rm);
1571 intptr_t pc = get_pc();
1572 set_register(
LR, pc + Instr::kInstrSize);
1577 if ((instr->Bits(21, 2) == 0x1) && (instr->ConditionField() ==
AL)) {
1579 SimulatorDebugger dbg(
this);
1580 int32_t imm = instr->BkptField();
1583 set_pc(get_pc() + Instr::kInstrSize);
1587 UnimplementedInstruction(instr);
1592 UnimplementedInstruction(instr);
1596 }
else if (instr->IsMultiplyOrSyncPrimitive()) {
1597 if (instr->Bit(24) == 0) {
1603 uint32_t rm_val = get_register(rm);
1604 uint32_t rs_val = get_register(rs);
1605 uint32_t rd_val = 0;
1606 switch (instr->Bits(21, 3)) {
1613 rd_val = get_register(rd);
1619 uint32_t alu_out = rm_val * rs_val;
1620 if (instr->Bits(21, 3) == 3) {
1624 set_register(rn, alu_out);
1625 if (instr->HasS()) {
1626 SetNZFlags(alu_out);
1637 if (instr->Bits(21, 3) == 4) {
1638 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1639 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1640 result = left_op * right_op;
1642 int64_t left_op =
static_cast<int32_t
>(rm_val);
1643 int64_t right_op =
static_cast<int32_t
>(rs_val);
1644 result = left_op * right_op;
1646 int32_t hi_res = Utils::High32Bits(
result);
1647 int32_t lo_res = Utils::Low32Bits(
result);
1648 set_register(rd, lo_res);
1649 set_register(rn, hi_res);
1650 if (instr->HasS()) {
1672 int32_t rd_lo_val = get_register(rd);
1673 int32_t rd_hi_val = get_register(rn);
1674 uint32_t accum_lo =
static_cast<uint32_t
>(rd_lo_val);
1675 int32_t accum_hi =
static_cast<int32_t
>(rd_hi_val);
1676 int64_t accum = Utils::LowHighTo64Bits(accum_lo, accum_hi);
1678 if (instr->Bits(21, 3) == 5) {
1679 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1680 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1681 result = accum + left_op * right_op;
1682 }
else if (instr->Bits(21, 3) == 7) {
1683 int64_t left_op =
static_cast<int32_t
>(rm_val);
1684 int64_t right_op =
static_cast<int32_t
>(rs_val);
1685 result = accum + left_op * right_op;
1687 ASSERT(instr->Bits(21, 3) == 2);
1689 uint64_t left_op =
static_cast<uint32_t
>(rm_val);
1690 uint64_t right_op =
static_cast<uint32_t
>(rs_val);
1691 result = left_op * right_op +
1692 static_cast<uint32_t
>(rd_lo_val) +
1693 static_cast<uint32_t
>(rd_hi_val);
1695 int32_t hi_res = Utils::High32Bits(
result);
1696 int32_t lo_res = Utils::Low32Bits(
result);
1697 set_register(rd, lo_res);
1698 set_register(rn, hi_res);
1699 if (instr->HasS()) {
1711 UnimplementedInstruction(instr);
1720 switch (instr->Bits(20, 4)) {
1723 if (IsIllegalAddress(
addr)) {
1724 HandleIllegalAccess(
addr, instr);
1727 set_register(rd, WriteExclusiveW(
addr, get_register(rm), instr));
1733 if (IsIllegalAddress(
addr)) {
1734 HandleIllegalAccess(
addr, instr);
1736 set_register(rd, ReadExclusiveW(
addr, instr));
1741 UnimplementedInstruction(instr);
1746 }
else if (instr->Bit(25) == 1) {
1748 switch (instr->Bits(20, 5)) {
1751 uint16_t imm16 = instr->MovwField();
1753 if (instr->Bit(22) == 0) {
1755 set_register(rd, imm16);
1758 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16));
1763 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) {
1766 UnimplementedInstruction(instr);
1771 UnimplementedInstruction(instr);
1779 int32_t rn_val = get_register(rn);
1781 bool write_back =
false;
1782 if (instr->Bit(22) == 0) {
1784 int32_t rm_val = get_register(rm);
1785 switch (instr->PUField()) {
1806 write_back = instr->HasW();
1813 write_back = instr->HasW();
1823 int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField();
1824 switch (instr->PUField()) {
1845 write_back = instr->HasW();
1852 write_back = instr->HasW();
1862 if (IsIllegalAddress(
addr)) {
1863 HandleIllegalAccess(
addr, instr);
1867 set_register(rn, rn_val);
1869 if (!instr->HasSign()) {
1870 if (instr->HasL()) {
1871 uint16_t val = ReadHU(
addr, instr);
1872 set_register(rd, val);
1874 uint16_t val = get_register(rd);
1875 WriteH(
addr, val, instr);
1877 }
else if (instr->HasL()) {
1878 if (instr->HasH()) {
1879 int16_t val = ReadH(
addr, instr);
1880 set_register(rd, val);
1882 int8_t val = ReadB(
addr);
1883 set_register(rd, val);
1885 }
else if ((rd & 1) == 0) {
1888 if (instr->HasH()) {
1889 int32_t val_low = get_register(rd);
1890 int32_t val_high = get_register(rd1);
1891 WriteW(
addr, val_low, instr);
1892 WriteW(
addr + 4, val_high, instr);
1894 int32_t val_low = ReadW(
addr, instr);
1895 int32_t val_high = ReadW(
addr + 4, instr);
1896 set_register(rd, val_low);
1897 set_register(rd1, val_high);
1900 UnimplementedInstruction(instr);
1907 uint32_t rn_val = get_register(rn);
1908 uint32_t shifter_operand = 0;
1909 bool shifter_carry_out = 0;
1910 if (instr->TypeField() == 0) {
1911 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1913 ASSERT(instr->TypeField() == 1);
1914 shifter_operand = GetImm(instr, &shifter_carry_out);
1919 switch (instr->OpcodeField()) {
1923 alu_out = rn_val & shifter_operand;
1924 set_register(rd, alu_out);
1925 if (instr->HasS()) {
1926 SetNZFlags(alu_out);
1927 SetCFlag(shifter_carry_out);
1935 alu_out = rn_val ^ shifter_operand;
1936 set_register(rd, alu_out);
1937 if (instr->HasS()) {
1938 SetNZFlags(alu_out);
1939 SetCFlag(shifter_carry_out);
1947 alu_out = rn_val - shifter_operand;
1948 set_register(rd, alu_out);
1949 if (instr->HasS()) {
1950 SetNZFlags(alu_out);
1951 SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1));
1952 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1));
1960 alu_out = shifter_operand - rn_val;
1961 set_register(rd, alu_out);
1962 if (instr->HasS()) {
1963 SetNZFlags(alu_out);
1964 SetCFlag(CarryFrom(shifter_operand, ~rn_val, 1));
1965 SetVFlag(OverflowFrom(shifter_operand, ~rn_val, 1));
1973 alu_out = rn_val + shifter_operand;
1974 set_register(rd, alu_out);
1975 if (instr->HasS()) {
1976 SetNZFlags(alu_out);
1977 SetCFlag(CarryFrom(rn_val, shifter_operand, 0));
1978 SetVFlag(OverflowFrom(rn_val, shifter_operand, 0));
1986 carry_in = c_flag_ ? 1 : 0;
1987 alu_out = rn_val + shifter_operand + carry_in;
1988 set_register(rd, alu_out);
1989 if (instr->HasS()) {
1990 SetNZFlags(alu_out);
1991 SetCFlag(CarryFrom(rn_val, shifter_operand, carry_in));
1992 SetVFlag(OverflowFrom(rn_val, shifter_operand, carry_in));
2000 carry_in = c_flag_ ? 1 : 0;
2001 alu_out = rn_val + ~shifter_operand + carry_in;
2002 set_register(rd, alu_out);
2003 if (instr->HasS()) {
2004 SetNZFlags(alu_out);
2005 SetCFlag(CarryFrom(rn_val, ~shifter_operand, carry_in));
2006 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, carry_in));
2014 carry_in = c_flag_ ? 1 : 0;
2015 alu_out = shifter_operand + ~rn_val + carry_in;
2016 set_register(rd, alu_out);
2017 if (instr->HasS()) {
2018 SetNZFlags(alu_out);
2019 SetCFlag(CarryFrom(shifter_operand, ~rn_val, carry_in));
2020 SetVFlag(OverflowFrom(shifter_operand, ~rn_val, carry_in));
2026 if (instr->HasS()) {
2029 alu_out = rn_val & shifter_operand;
2030 SetNZFlags(alu_out);
2031 SetCFlag(shifter_carry_out);
2033 UnimplementedInstruction(instr);
2039 if (instr->HasS()) {
2042 alu_out = rn_val ^ shifter_operand;
2043 SetNZFlags(alu_out);
2044 SetCFlag(shifter_carry_out);
2046 UnimplementedInstruction(instr);
2052 if (instr->HasS()) {
2055 alu_out = rn_val - shifter_operand;
2056 SetNZFlags(alu_out);
2057 SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1));
2058 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1));
2060 UnimplementedInstruction(instr);
2066 if (instr->HasS()) {
2069 alu_out = rn_val + shifter_operand;
2070 SetNZFlags(alu_out);
2071 SetCFlag(CarryFrom(rn_val, shifter_operand, 0));
2072 SetVFlag(OverflowFrom(rn_val, shifter_operand, 0));
2074 UnimplementedInstruction(instr);
2082 alu_out = rn_val | shifter_operand;
2083 set_register(rd, alu_out);
2084 if (instr->HasS()) {
2085 SetNZFlags(alu_out);
2086 SetCFlag(shifter_carry_out);
2094 alu_out = shifter_operand;
2095 set_register(rd, alu_out);
2096 if (instr->HasS()) {
2097 SetNZFlags(alu_out);
2098 SetCFlag(shifter_carry_out);
2106 alu_out = rn_val & ~shifter_operand;
2107 set_register(rd, alu_out);
2108 if (instr->HasS()) {
2109 SetNZFlags(alu_out);
2110 SetCFlag(shifter_carry_out);
2118 alu_out = ~shifter_operand;
2119 set_register(rd, alu_out);
2120 if (instr->HasS()) {
2121 SetNZFlags(alu_out);
2122 SetCFlag(shifter_carry_out);
2135DART_FORCE_INLINE
void Simulator::DecodeType2(Instr* instr) {
2138 int32_t rn_val = get_register(rn);
2139 int32_t im_val = instr->Offset12Field();
2141 bool write_back =
false;
2142 switch (instr->PUField()) {
2163 write_back = instr->HasW();
2170 write_back = instr->HasW();
2178 if (IsIllegalAddress(
addr)) {
2179 HandleIllegalAccess(
addr, instr);
2183 set_register(rn, rn_val);
2185 if (instr->HasB()) {
2186 if (instr->HasL()) {
2187 unsigned char val = ReadBU(
addr);
2188 set_register(rd, val);
2190 unsigned char val = get_register(rd);
2194 if (instr->HasL()) {
2195 set_register(rd, ReadW(
addr, instr));
2197 WriteW(
addr, get_register(rd), instr);
2203void Simulator::DoDivision(Instr* instr) {
2204 const Register rd = instr->DivRdField();
2205 const Register rn = instr->DivRnField();
2206 const Register rm = instr->DivRmField();
2208 if (!TargetCPUFeatures::integer_division_supported()) {
2209 UnimplementedInstruction(instr);
2215 if (get_register(rm) == 0) {
2216 set_register(rd, 0);
2220 if (instr->IsDivUnsigned()) {
2222 uint32_t rn_val =
static_cast<uint32_t
>(get_register(rn));
2223 uint32_t rm_val =
static_cast<uint32_t
>(get_register(rm));
2224 uint32_t
result = rn_val / rm_val;
2225 set_register(rd,
static_cast<int32_t
>(
result));
2228 int32_t rn_val = get_register(rn);
2229 int32_t rm_val = get_register(rm);
2231 if ((rn_val ==
static_cast<int32_t
>(0x80000000)) &&
2232 (rm_val ==
static_cast<int32_t
>(0xffffffff))) {
2235 result = rn_val / rm_val;
2237 set_register(rd,
result);
2241void Simulator::DecodeType3(Instr* instr) {
2242 if (instr->IsMedia()) {
2243 if (instr->IsDivision()) {
2246 }
else if (instr->IsRbit()) {
2250 set_register(rd, Utils::ReverseBits32(get_register(rm)));
2252 }
else if (instr->IsBitFieldExtract()) {
2254 const Register rd = instr->RdField();
2255 const Register rn = instr->BitFieldExtractRnField();
2256 const uint8_t
width = instr->BitFieldExtractWidthField() + 1;
2257 const uint8_t lsb = instr->BitFieldExtractLSBField();
2258 const int32_t rn_val = get_register(rn);
2259 const uint32_t extracted_bitfield =
2260 ((rn_val >> lsb) & Utils::NBitMask(
width));
2261 const uint32_t sign_extension =
2262 (instr->IsBitFieldExtractSignExtended() &&
2263 Utils::TestBit(extracted_bitfield,
width - 1))
2264 ? ~Utils::NBitMask(
width)
2266 set_register(rd, sign_extension | extracted_bitfield);
2274 int32_t rn_val = get_register(rn);
2275 bool shifter_carry_out = 0;
2276 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2278 bool write_back =
false;
2279 switch (instr->PUField()) {
2284 rn_val -= shifter_operand;
2292 rn_val += shifter_operand;
2298 rn_val -= shifter_operand;
2300 write_back = instr->HasW();
2305 rn_val += shifter_operand;
2307 write_back = instr->HasW();
2315 if (IsIllegalAddress(
addr)) {
2316 HandleIllegalAccess(
addr, instr);
2320 set_register(rn, rn_val);
2322 if (instr->HasB()) {
2323 if (instr->HasL()) {
2324 unsigned char val = ReadBU(
addr);
2325 set_register(rd, val);
2327 unsigned char val = get_register(rd);
2331 if (instr->HasL()) {
2332 set_register(rd, ReadW(
addr, instr));
2334 WriteW(
addr, get_register(rd), instr);
2340void Simulator::DecodeType4(Instr* instr) {
2341 ASSERT(instr->Bit(22) == 0);
2342 if (instr->HasL()) {
2344 HandleRList(instr,
true);
2347 HandleRList(instr,
false);
2351void Simulator::DecodeType5(Instr* instr) {
2353 uint32_t off = (
static_cast<uint32_t
>(instr->SImmed24Field()) << 2) + 8;
2354 uint32_t pc = get_pc();
2355 if (instr->HasLink()) {
2356 set_register(
LR, pc + Instr::kInstrSize);
2361void Simulator::DecodeType6(Instr* instr) {
2362 if (instr->IsVFPDoubleTransfer()) {
2365 if (instr->Bit(8) == 0) {
2369 if (instr->Bit(20) == 1) {
2371 set_register(rd, get_sregister_bits(sm));
2372 set_register(rn, get_sregister_bits(sm1));
2375 set_sregister_bits(sm, get_register(rd));
2376 set_sregister_bits(sm1, get_register(rn));
2380 if (instr->Bit(20) == 1) {
2382 int64_t dm_val = get_dregister_bits(dm);
2383 set_register(rd, Utils::Low32Bits(dm_val));
2384 set_register(rn, Utils::High32Bits(dm_val));
2388 Utils::LowHighTo64Bits(get_register(rd), get_register(rn));
2389 set_dregister_bits(dm, dm_val);
2392 }
else if (instr->IsVFPLoadStore()) {
2394 int32_t
addr = get_register(rn);
2395 int32_t imm_val = instr->Bits(0, 8) << 2;
2396 if (instr->Bit(23) == 1) {
2401 if (IsIllegalAddress(
addr)) {
2402 HandleIllegalAccess(
addr, instr);
2404 if (instr->Bit(8) == 0) {
2406 if (instr->Bit(20) == 1) {
2409 set_sregister_bits(sd, ReadW(
addr, instr));
2413 WriteW(
addr, get_sregister_bits(sd), instr);
2417 if (instr->Bit(20) == 1) {
2420 int64_t dd_val = Utils::LowHighTo64Bits(ReadW(
addr, instr),
2421 ReadW(
addr + 4, instr));
2422 set_dregister_bits(dd, dd_val);
2426 int64_t dd_val = get_dregister_bits(dd);
2427 WriteW(
addr, Utils::Low32Bits(dd_val), instr);
2428 WriteW(
addr + 4, Utils::High32Bits(dd_val), instr);
2432 }
else if (instr->IsVFPMultipleLoadStore()) {
2434 int32_t
addr = get_register(rn);
2435 int32_t imm_val = instr->Bits(0, 8);
2436 if (instr->Bit(23) == 0) {
2437 addr -= (imm_val << 2);
2439 if (instr->HasW()) {
2440 if (instr->Bit(23) == 1) {
2441 set_register(rn,
addr + (imm_val << 2));
2443 set_register(rn,
addr);
2446 if (IsIllegalAddress(
addr)) {
2447 HandleIllegalAccess(
addr, instr);
2449 if (instr->Bit(8) == 0) {
2450 int32_t regs_cnt = imm_val;
2451 int32_t
start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
2454 if (instr->Bit(20) == 1) {
2456 set_sregister_bits(sd, ReadW(
addr, instr));
2459 WriteW(
addr, get_sregister_bits(sd), instr);
2464 int32_t regs_cnt = imm_val >> 1;
2465 int32_t
start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
2469 if (instr->Bit(20) == 1) {
2471 int64_t dd_val = Utils::LowHighTo64Bits(ReadW(
addr, instr),
2472 ReadW(
addr + 4, instr));
2473 set_dregister_bits(dd, dd_val);
2476 int64_t dd_val = get_dregister_bits(dd);
2477 WriteW(
addr, Utils::Low32Bits(dd_val), instr);
2478 WriteW(
addr + 4, Utils::High32Bits(dd_val), instr);
2483 UnimplementedInstruction(instr);
2488 UnimplementedInstruction(instr);
2492void Simulator::DecodeType7(Instr* instr) {
2493 if (instr->Bit(24) == 1) {
2495 SupervisorCall(instr);
2496 }
else if (instr->IsVFPDataProcessingOrSingleTransfer()) {
2497 if (instr->Bit(4) == 0) {
2505 if (instr->Bit(8) == 0) {
2506 sd = instr->SdField();
2507 sn = instr->SnField();
2508 sm = instr->SmField();
2516 dd = instr->DdField();
2517 dn = instr->DnField();
2518 dm = instr->DmField();
2520 switch (instr->Bits(20, 4) & 0xb) {
2523 UnimplementedInstruction(instr);
2527 if (instr->Bit(8) == 0) {
2528 float addend = get_sregister(sn) * get_sregister(sm);
2529 float sd_val = get_sregister(sd);
2530 if (instr->Bit(6) == 0) {
2536 set_sregister(sd, sd_val + addend);
2538 double addend = get_dregister(dn) * get_dregister(dm);
2539 double dd_val = get_dregister(dd);
2540 if (instr->Bit(6) == 0) {
2546 set_dregister(dd, dd_val + addend);
2551 if (instr->Bit(8) == 0) {
2553 set_sregister(sd, get_sregister(sn) * get_sregister(sm));
2556 set_dregister(dd, get_dregister(dn) * get_dregister(dm));
2561 if (instr->Bit(8) == 0) {
2563 set_sregister(sd, get_sregister(sn) / get_sregister(sm));
2566 set_dregister(dd, get_dregister(dn) / get_dregister(dm));
2571 if (instr->Bit(8) == 0) {
2572 if (instr->Bit(6) == 0) {
2574 set_sregister(sd, get_sregister(sn) + get_sregister(sm));
2577 set_sregister(sd, get_sregister(sn) - get_sregister(sm));
2580 if (instr->Bit(6) == 0) {
2582 set_dregister(dd, get_dregister(dn) + get_dregister(dm));
2585 set_dregister(dd, get_dregister(dn) - get_dregister(dm));
2591 if (instr->Bit(6) == 0) {
2592 if (instr->Bit(8) == 0) {
2594 set_sregister(sd, instr->ImmFloatField());
2597 set_dregister(dd, instr->ImmDoubleField());
2601 switch (instr->Bits(16, 4)) {
2603 switch (instr->Bits(6, 2)) {
2605 if (instr->Bit(8) == 0) {
2607 set_sregister(sd, get_sregister(sm));
2610 set_dregister(dd, get_dregister(dm));
2615 if (instr->Bit(8) == 0) {
2617 set_sregister(sd, fabsf(get_sregister(sm)));
2620 set_dregister(dd, fabs(get_dregister(dm)));
2625 UnimplementedInstruction(instr);
2632 switch (instr->Bits(6, 2)) {
2634 if (instr->Bit(8) == 0) {
2636 set_sregister(sd, -get_sregister(sm));
2639 set_dregister(dd, -get_dregister(dm));
2644 if (instr->Bit(8) == 0) {
2646 set_sregister(sd, sqrtf(get_sregister(sm)));
2649 set_dregister(dd,
sqrt(get_dregister(dm)));
2654 UnimplementedInstruction(instr);
2662 if (instr->Bit(7) == 1) {
2663 UnimplementedInstruction(instr);
2669 if (instr->Bit(8) == 0) {
2670 float sd_val = get_sregister(sd);
2672 if (instr->Bit(16) == 0) {
2674 sm_val = get_sregister(sm);
2679 if (isnan(sd_val) || isnan(sm_val)) {
2682 }
else if (sd_val == sm_val) {
2685 }
else if (sd_val < sm_val) {
2691 double dd_val = get_dregister(dd);
2693 if (instr->Bit(16) == 0) {
2695 dm_val = get_dregister(dm);
2700 if (isnan(dd_val) || isnan(dm_val)) {
2703 }
else if (dd_val == dm_val) {
2706 }
else if (dd_val < dm_val) {
2716 if (instr->Bit(8) == 0) {
2718 dd = instr->DdField();
2719 set_dregister(dd,
static_cast<double>(get_sregister(sm)));
2722 sd = instr->SdField();
2723 set_sregister(sd,
static_cast<float>(get_dregister(dm)));
2728 sm = instr->SmField();
2729 int32_t sm_int = get_sregister_bits(sm);
2730 uint32_t ud_val = 0;
2732 if (instr->Bit(7) == 0) {
2733 ud_val =
static_cast<uint32_t
>(sm_int);
2737 if (instr->Bit(8) == 0) {
2739 if (instr->Bit(7) == 0) {
2741 sd_val =
static_cast<float>(ud_val);
2744 sd_val =
static_cast<float>(id_val);
2746 set_sregister(sd, sd_val);
2749 if (instr->Bit(7) == 0) {
2751 dd_val =
static_cast<double>(ud_val);
2754 dd_val =
static_cast<double>(id_val);
2756 set_dregister(dd, dd_val);
2764 if (instr->Bit(7) == 0) {
2766 UnimplementedInstruction(instr);
2770 uint32_t ud_val = 0;
2771 if (instr->Bit(8) == 0) {
2772 float sm_val = get_sregister(sm);
2773 if (instr->Bit(16) == 0) {
2775 if (sm_val >=
static_cast<float>(INT32_MAX)) {
2777 }
else if (sm_val > 0.0) {
2778 ud_val =
static_cast<uint32_t
>(sm_val);
2782 if (sm_val <=
static_cast<float>(INT32_MIN)) {
2784 }
else if (sm_val >=
static_cast<float>(INT32_MAX)) {
2787 id_val =
static_cast<int32_t
>(sm_val);
2789 ASSERT((id_val >= 0) || !(sm_val >= 0.0));
2792 sd = instr->SdField();
2793 double dm_val = get_dregister(dm);
2794 if (instr->Bit(16) == 0) {
2796 if (dm_val >=
static_cast<double>(INT32_MAX)) {
2798 }
else if (dm_val > 0.0) {
2799 ud_val =
static_cast<uint32_t
>(dm_val);
2803 if (dm_val <=
static_cast<double>(INT32_MIN)) {
2805 }
else if (dm_val >=
static_cast<double>(INT32_MAX)) {
2807 }
else if (isnan(dm_val)) {
2810 id_val =
static_cast<int32_t
>(dm_val);
2812 ASSERT((id_val >= 0) || !(dm_val >= 0.0));
2816 if (instr->Bit(16) == 0) {
2817 sd_val =
static_cast<int32_t
>(ud_val);
2821 set_sregister_bits(sd, sd_val);
2832 UnimplementedInstruction(instr);
2840 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) {
2843 if (instr->Bit(20) == 0) {
2845 set_sregister_bits(sn, get_register(rd));
2848 set_register(rd, get_sregister_bits(sn));
2850 }
else if ((instr->Bits(22, 3) == 0) && (instr->Bit(20) == 0) &&
2851 (instr->Bit(8) == 1) && (instr->Bits(5, 2) == 0)) {
2854 const int32_t src_value = get_register(rd);
2855 const int64_t dst_value = get_dregister_bits(dn);
2856 int32_t dst_lo = Utils::Low32Bits(dst_value);
2857 int32_t dst_hi = Utils::High32Bits(dst_value);
2858 if (instr->Bit(21) == 0) {
2865 set_dregister_bits(dn, Utils::LowHighTo64Bits(dst_lo, dst_hi));
2866 }
else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0)) {
2867 if (instr->Bits(12, 4) == 0xf) {
2869 n_flag_ = fp_n_flag_;
2870 z_flag_ = fp_z_flag_;
2871 c_flag_ = fp_c_flag_;
2872 v_flag_ = fp_v_flag_;
2875 const int32_t n_flag = fp_n_flag_ ? (1 << 31) : 0;
2876 const int32_t z_flag = fp_z_flag_ ? (1 << 30) : 0;
2877 const int32_t c_flag = fp_c_flag_ ? (1 << 29) : 0;
2878 const int32_t v_flag = fp_v_flag_ ? (1 << 28) : 0;
2879 set_register(instr->RdField(), n_flag | z_flag | c_flag | v_flag);
2882 UnimplementedInstruction(instr);
2886 UnimplementedInstruction(instr);
2890static void simd_value_swap(simd_value_t* s1,
2896 s1->u32[i1] = s2->u32[i2];
2900static float vminf(
float f1,
float f2) {
2903 return signbit(f1) ? f1 : f2;
2905 return f1 > f2 ? f2 : f1;
2908static float vmaxf(
float f1,
float f2) {
2911 return signbit(f1) ? f2 : f1;
2913 return f1 < f2 ? f2 : f1;
2916void Simulator::DecodeSIMDDataProcessing(Instr* instr) {
2919 if (instr->Bit(6) == 1) {
2928 get_qregister(qn, &s8n);
2929 get_qregister(qm, &s8m);
2931 if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
2932 (instr->Bits(23, 2) == 0)) {
2935 const int size = instr->Bits(20, 2);
2937 for (
int i = 0;
i < 16;
i++) {
2938 s8d.u8[
i] = s8n.u8[
i] + s8m.u8[
i];
2940 }
else if (
size == 1) {
2941 for (
int i = 0;
i < 8;
i++) {
2942 s8d.u16[
i] = s8n.u16[
i] + s8m.u16[
i];
2944 }
else if (
size == 2) {
2945 for (
int i = 0;
i < 4;
i++) {
2946 s8d.u32[
i] = s8n.u32[
i] + s8m.u32[
i];
2948 }
else if (
size == 3) {
2949 for (
int i = 0;
i < 2;
i++) {
2950 s8d.u64[
i] = s8n.u64[
i] + s8m.u64[
i];
2955 }
else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
2956 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 0)) {
2958 for (
int i = 0;
i < 4;
i++) {
2959 s8d.f32[
i] = s8n.f32[
i] + s8m.f32[
i];
2961 }
else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
2962 (instr->Bits(23, 2) == 2)) {
2964 const int size = instr->Bits(20, 2);
2966 for (
int i = 0;
i < 16;
i++) {
2967 s8d.u8[
i] = s8n.u8[
i] - s8m.u8[
i];
2969 }
else if (
size == 1) {
2970 for (
int i = 0;
i < 8;
i++) {
2971 s8d.u16[
i] = s8n.u16[
i] - s8m.u16[
i];
2973 }
else if (
size == 2) {
2974 for (
int i = 0;
i < 4;
i++) {
2975 s8d.u32[
i] = s8n.u32[
i] - s8m.u32[
i];
2977 }
else if (
size == 3) {
2978 for (
int i = 0;
i < 2;
i++) {
2979 s8d.u64[
i] = s8n.u64[
i] - s8m.u64[
i];
2984 }
else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
2985 (instr->Bits(23, 2) == 0) && (instr->Bit(21) == 1)) {
2987 for (
int i = 0;
i < 4;
i++) {
2988 s8d.f32[
i] = s8n.f32[
i] - s8m.f32[
i];
2990 }
else if ((instr->Bits(8, 4) == 9) && (instr->Bit(4) == 1) &&
2991 (instr->Bits(23, 2) == 0)) {
2993 const int size = instr->Bits(20, 2);
2995 for (
int i = 0;
i < 16;
i++) {
2996 s8d.i8[
i] = s8n.i8[
i] * s8m.i8[
i];
2998 }
else if (
size == 1) {
2999 for (
int i = 0;
i < 8;
i++) {
3000 s8d.i16[
i] = s8n.i16[
i] * s8m.i16[
i];
3002 }
else if (
size == 2) {
3003 for (
int i = 0;
i < 4;
i++) {
3004 s8d.u32[
i] = s8n.u32[
i] * s8m.u32[
i];
3006 }
else if (
size == 3) {
3007 UnimplementedInstruction(instr);
3011 }
else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
3012 (instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
3014 for (
int i = 0;
i < 4;
i++) {
3015 s8d.f32[
i] = s8n.f32[
i] * s8m.f32[
i];
3017 }
else if ((instr->Bits(8, 4) == 4) && (instr->Bit(4) == 0) &&
3018 (instr->Bit(23) == 0) && (instr->Bits(25, 3) == 1)) {
3021 const bool is_signed = instr->Bit(24) == 0;
3022 const int size = instr->Bits(20, 2);
3024 for (
int i = 0;
i < 16;
i++) {
3025 int8_t shift = s8n.i8[
i];
3027 s8d.u8[
i] = s8m.u8[
i] << shift;
3028 }
else if (shift < 0) {
3030 s8d.i8[
i] = s8m.i8[
i] >> (-shift);
3032 s8d.u8[
i] = s8m.u8[
i] >> (-shift);
3036 }
else if (
size == 1) {
3037 for (
int i = 0;
i < 8;
i++) {
3038 int8_t shift = s8n.i8[
i * 2];
3040 s8d.u16[
i] = s8m.u16[
i] << shift;
3041 }
else if (shift < 0) {
3043 s8d.i16[
i] = s8m.i16[
i] >> (-shift);
3045 s8d.u16[
i] = s8m.u16[
i] >> (-shift);
3049 }
else if (
size == 2) {
3050 for (
int i = 0;
i < 4;
i++) {
3051 int8_t shift = s8n.i8[
i * 4];
3053 s8d.u32[
i] = s8m.u32[
i] << shift;
3054 }
else if (shift < 0) {
3056 s8d.i32[
i] = s8m.i32[
i] >> (-shift);
3058 s8d.u32[
i] = s8m.u32[
i] >> (-shift);
3064 for (
int i = 0;
i < 2;
i++) {
3065 int8_t shift = s8n.i8[
i * 8];
3067 s8d.u64[
i] = s8m.u64[
i] << shift;
3068 }
else if (shift < 0) {
3070 s8d.i64[
i] = s8m.i64[
i] >> (-shift);
3072 s8d.u64[
i] = s8m.u64[
i] >> (-shift);
3077 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3078 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
3080 for (
int i = 0;
i < 4;
i++) {
3081 s8d.u32[
i] = s8n.u32[
i] ^ s8m.u32[
i];
3083 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3084 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
3086 for (
int i = 0;
i < 4;
i++) {
3087 s8d.u32[
i] = s8n.u32[
i] | ~s8m.u32[
i];
3089 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3090 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
3093 for (
int i = 0;
i < 4;
i++) {
3094 s8d.u32[
i] = s8m.u32[
i];
3098 for (
int i = 0;
i < 4;
i++) {
3099 s8d.u32[
i] = s8n.u32[
i] | s8m.u32[
i];
3102 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
3103 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3105 for (
int i = 0;
i < 4;
i++) {
3106 s8d.u32[
i] = s8n.u32[
i] & s8m.u32[
i];
3108 }
else if ((instr->Bits(7, 5) == 11) && (instr->Bit(4) == 0) &&
3109 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 5) == 7) &&
3110 (instr->Bits(16, 4) == 0)) {
3112 for (
int i = 0;
i < 4;
i++) {
3113 s8d.u32[
i] = ~s8m.u32[
i];
3115 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) &&
3116 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
3118 for (
int i = 0;
i < 4;
i++) {
3119 s8d.f32[
i] = vminf(s8n.f32[
i], s8m.f32[
i]);
3121 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 0) &&
3122 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3124 for (
int i = 0;
i < 4;
i++) {
3125 s8d.f32[
i] = vmaxf(s8n.f32[
i], s8m.f32[
i]);
3127 }
else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) &&
3128 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3129 (instr->Bit(7) == 0) && (instr->Bits(16, 4) == 9)) {
3131 for (
int i = 0;
i < 4;
i++) {
3132 s8d.f32[
i] = fabsf(s8m.f32[
i]);
3134 }
else if ((instr->Bits(8, 4) == 7) && (instr->Bit(4) == 0) &&
3135 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3136 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 9)) {
3138 for (
int i = 0;
i < 4;
i++) {
3139 s8d.f32[
i] = -s8m.f32[
i];
3141 }
else if ((instr->Bits(7, 5) == 10) && (instr->Bit(4) == 0) &&
3142 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3143 (instr->Bits(16, 4) == 11)) {
3145 for (
int i = 0;
i < 4;
i++) {
3148 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 1) &&
3149 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3151 for (
int i = 0;
i < 4;
i++) {
3154 }
else if ((instr->Bits(8, 4) == 5) && (instr->Bit(4) == 0) &&
3155 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3156 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 11)) {
3158 for (
int i = 0;
i < 4;
i++) {
3161 }
else if ((instr->Bits(8, 4) == 15) && (instr->Bit(4) == 1) &&
3162 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
3164 for (
int i = 0;
i < 4;
i++) {
3167 }
else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
3168 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3169 (instr->Bit(7) == 0)) {
3171 int64_t dm_value = get_dregister_bits(dm);
3172 int32_t imm4 = instr->Bits(16, 4);
3174 if ((imm4 & 1) != 0) {
3177 memcpy(dm_b, &dm_value,
sizeof(dm_b));
3179 int8_t val = dm_b[idx];
3180 for (
int i = 0;
i < 16;
i++) {
3183 }
else if ((imm4 & 2) != 0) {
3186 memcpy(dm_h, &dm_value,
sizeof(dm_h));
3188 int16_t val = dm_h[idx];
3189 for (
int i = 0;
i < 8;
i++) {
3192 }
else if ((imm4 & 4) != 0) {
3195 memcpy(dm_w, &dm_value,
sizeof(dm_w));
3197 int32_t val = dm_w[idx];
3198 for (
int i = 0;
i < 4;
i++) {
3202 UnimplementedInstruction(instr);
3204 }
else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 0) &&
3205 (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
3206 (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 10)) {
3208 get_qregister(qd, &s8d);
3212 simd_value_swap(&s8d, 3, &s8m, 2);
3213 simd_value_swap(&s8d, 3, &s8m, 1);
3214 simd_value_swap(&s8d, 2, &s8m, 0);
3215 simd_value_swap(&s8d, 2, &s8d, 1);
3217 set_qregister(qm, s8m);
3218 }
else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
3219 (instr->Bits(23, 2) == 2)) {
3221 const int size = instr->Bits(20, 2);
3223 for (
int i = 0;
i < 16;
i++) {
3224 s8d.i8[
i] = s8n.i8[
i] == s8m.i8[
i] ? 0xff : 0;
3226 }
else if (
size == 1) {
3227 for (
int i = 0;
i < 8;
i++) {
3228 s8d.i16[
i] = s8n.i16[
i] == s8m.i16[
i] ? 0xffff : 0;
3230 }
else if (
size == 2) {
3231 for (
int i = 0;
i < 4;
i++) {
3232 s8d.u32[
i] = s8n.u32[
i] == s8m.u32[
i] ? 0xffffffff : 0;
3234 }
else if (
size == 3) {
3235 UnimplementedInstruction(instr);
3239 }
else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
3240 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
3242 for (
int i = 0;
i < 4;
i++) {
3243 s8d.u32[
i] = s8n.f32[
i] == s8m.f32[
i] ? 0xffffffff : 0;
3245 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
3246 (instr->Bits(23, 2) == 0)) {
3248 const int size = instr->Bits(20, 2);
3250 for (
int i = 0;
i < 16;
i++) {
3251 s8d.i8[
i] = s8n.i8[
i] >= s8m.i8[
i] ? 0xff : 0;
3253 }
else if (
size == 1) {
3254 for (
int i = 0;
i < 8;
i++) {
3255 s8d.i16[
i] = s8n.i16[
i] >= s8m.i16[
i] ? 0xffff : 0;
3257 }
else if (
size == 2) {
3258 for (
int i = 0;
i < 4;
i++) {
3259 s8d.u32[
i] = s8n.i32[
i] >= s8m.i32[
i] ? 0xffffffff : 0;
3261 }
else if (
size == 3) {
3262 UnimplementedInstruction(instr);
3266 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
3267 (instr->Bits(23, 2) == 2)) {
3269 const int size = instr->Bits(20, 2);
3271 for (
int i = 0;
i < 16;
i++) {
3272 s8d.i8[
i] = s8n.u8[
i] >= s8m.u8[
i] ? 0xff : 0;
3274 }
else if (
size == 1) {
3275 for (
int i = 0;
i < 8;
i++) {
3276 s8d.i16[
i] = s8n.u16[
i] >= s8m.u16[
i] ? 0xffff : 0;
3278 }
else if (
size == 2) {
3279 for (
int i = 0;
i < 4;
i++) {
3280 s8d.u32[
i] = s8n.u32[
i] >= s8m.u32[
i] ? 0xffffffff : 0;
3282 }
else if (
size == 3) {
3283 UnimplementedInstruction(instr);
3287 }
else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
3288 (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
3290 for (
int i = 0;
i < 4;
i++) {
3291 s8d.u32[
i] = s8n.f32[
i] >= s8m.f32[
i] ? 0xffffffff : 0;
3293 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
3294 (instr->Bits(23, 2) == 0)) {
3296 const int size = instr->Bits(20, 2);
3298 for (
int i = 0;
i < 16;
i++) {
3299 s8d.i8[
i] = s8n.i8[
i] > s8m.i8[
i] ? 0xff : 0;
3301 }
else if (
size == 1) {
3302 for (
int i = 0;
i < 8;
i++) {
3303 s8d.i16[
i] = s8n.i16[
i] > s8m.i16[
i] ? 0xffff : 0;
3305 }
else if (
size == 2) {
3306 for (
int i = 0;
i < 4;
i++) {
3307 s8d.u32[
i] = s8n.i32[
i] > s8m.i32[
i] ? 0xffffffff : 0;
3309 }
else if (
size == 3) {
3310 UnimplementedInstruction(instr);
3314 }
else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
3315 (instr->Bits(23, 2) == 2)) {
3317 const int size = instr->Bits(20, 2);
3319 for (
int i = 0;
i < 16;
i++) {
3320 s8d.i8[
i] = s8n.u8[
i] > s8m.u8[
i] ? 0xff : 0;
3322 }
else if (
size == 1) {
3323 for (
int i = 0;
i < 8;
i++) {
3324 s8d.i16[
i] = s8n.u16[
i] > s8m.u16[
i] ? 0xffff : 0;
3326 }
else if (
size == 2) {
3327 for (
int i = 0;
i < 4;
i++) {
3328 s8d.u32[
i] = s8n.u32[
i] > s8m.u32[
i] ? 0xffffffff : 0;
3330 }
else if (
size == 3) {
3331 UnimplementedInstruction(instr);
3335 }
else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
3336 (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
3338 for (
int i = 0;
i < 4;
i++) {
3339 s8d.u32[
i] = s8n.f32[
i] > s8m.f32[
i] ? 0xffffffff : 0;
3342 UnimplementedInstruction(instr);
3345 set_qregister(qd, s8d);
3348 if ((instr->Bits(23, 2) == 3) && (instr->Bits(20, 2) == 3) &&
3349 (instr->Bits(10, 2) == 2) && (instr->Bit(4) == 0)) {
3353 int reg_count = instr->Bits(8, 2) + 1;
3354 int start = (instr->Bit(7) << 4) | instr->Bits(16, 4);
3357 for (
int i = 0;
i < reg_count;
i++) {
3359 table[
i] = get_dregister_bits(
d);
3361 for (
int i = reg_count;
i < 4;
i++) {
3365 int64_t dm_value = get_dregister_bits(dm);
3367 int8_t* dm_bytes =
reinterpret_cast<int8_t*
>(&dm_value);
3368 int8_t* result_bytes =
reinterpret_cast<int8_t*
>(&
result);
3369 int8_t* table_bytes =
reinterpret_cast<int8_t*
>(&
table[0]);
3370 for (
int i = 0;
i < 8;
i++) {
3371 int idx = dm_bytes[
i];
3372 if ((idx >= 0) && (idx < 256)) {
3373 result_bytes[
i] = table_bytes[idx];
3375 result_bytes[
i] = 0;
3379 set_dregister_bits(dd,
result);
3381 UnimplementedInstruction(instr);
3387DART_FORCE_INLINE
void Simulator::InstructionDecodeImpl(Instr* instr) {
3388 pc_modified_ =
false;
3390 if (instr->InstructionBits() ==
static_cast<int32_t
>(0xf57ff01f)) {
3393 }
else if (instr->InstructionBits() ==
3396 std::atomic_thread_fence(std::memory_order_seq_cst);
3398 if (instr->IsSIMDDataProcessing()) {
3399 DecodeSIMDDataProcessing(instr);
3401 UnimplementedInstruction(instr);
3404 }
else if (ConditionallyExecute(instr)) {
3405 switch (instr->TypeField()) {
3408 DecodeType01(instr);
3442 if (!pc_modified_) {
3443 set_register(
PC,
reinterpret_cast<int32_t
>(instr) + Instr::kInstrSize);
3447void Simulator::InstructionDecode(Instr* instr) {
3448 if (IsTracingExecution()) {
3452 if (FLAG_support_disassembler) {
3453 Disassembler::Disassemble(
start,
end);
3455 THR_Print(
"Disassembler not supported in this mode.\n");
3458 InstructionDecodeImpl(instr);
3462 if (
LIKELY(FLAG_stop_sim_at == ULLONG_MAX &&
3463 FLAG_trace_sim_after == ULLONG_MAX)) {
3470void Simulator::ExecuteNoTrace() {
3473 uword program_counter = get_pc();
3477 while (program_counter != kEndSimulatingPC) {
3478 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3480 InstructionDecodeImpl(instr);
3481 program_counter = get_pc();
3485void Simulator::ExecuteTrace() {
3488 uword program_counter = get_pc();
3492 while (program_counter != kEndSimulatingPC) {
3493 Instr* instr =
reinterpret_cast<Instr*
>(program_counter);
3495 if (icount_ == FLAG_stop_sim_at) {
3496 SimulatorDebugger dbg(
this);
3497 dbg.Stop(instr,
"Instruction count reached");
3498 }
else if (
reinterpret_cast<uint64_t
>(instr) == FLAG_stop_sim_at) {
3499 SimulatorDebugger dbg(
this);
3500 dbg.Stop(instr,
"Instruction address reached");
3501 }
else if (IsIllegalAddress(program_counter)) {
3502 HandleIllegalAccess(program_counter, instr);
3504 InstructionDecode(instr);
3506 program_counter = get_pc();
3510int64_t Simulator::Call(int32_t entry,
3518 int32_t sp_before_call = get_register(
SP);
3522 set_sregister(
S0, bit_cast<float, int32_t>(parameter0));
3523 set_sregister(
S1, bit_cast<float, int32_t>(parameter1));
3524 set_sregister(
S2, bit_cast<float, int32_t>(parameter2));
3525 set_sregister(
S3, bit_cast<float, int32_t>(parameter3));
3527 set_register(
R0, parameter0);
3528 set_register(
R1, parameter1);
3529 set_register(
R2, parameter2);
3530 set_register(
R3, parameter3);
3534 int32_t stack_pointer = sp_before_call;
3535 if (OS::ActivationFrameAlignment() > 1) {
3537 Utils::RoundDown(stack_pointer, OS::ActivationFrameAlignment());
3539 set_register(
SP, stack_pointer);
3542 set_register(
PC, entry);
3546 set_register(
LR, kEndSimulatingPC);
3551 int32_t r4_val = get_register(
R4);
3552 int32_t r5_val = get_register(
R5);
3553 int32_t r6_val = get_register(
R6);
3554 int32_t r7_val = get_register(
R7);
3555 int32_t r8_val = get_register(
R8);
3556#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3557 int32_t r9_val = get_register(
R9);
3559 int32_t r10_val = get_register(
R10);
3560 int32_t r11_val = get_register(
R11);
3562 double d8_val = 0.0;
3563 double d9_val = 0.0;
3564 double d10_val = 0.0;
3565 double d11_val = 0.0;
3566 double d12_val = 0.0;
3567 double d13_val = 0.0;
3568 double d14_val = 0.0;
3569 double d15_val = 0.0;
3571 d8_val = get_dregister(
D8);
3572 d9_val = get_dregister(
D9);
3573 d10_val = get_dregister(
D10);
3574 d11_val = get_dregister(
D11);
3575 d12_val = get_dregister(
D12);
3576 d13_val = get_dregister(
D13);
3577 d14_val = get_dregister(
D14);
3578 d15_val = get_dregister(
D15);
3582 int32_t callee_saved_value = icount_;
3583 set_register(
R4, callee_saved_value);
3584 set_register(
R5, callee_saved_value);
3585 set_register(
R6, callee_saved_value);
3586 set_register(
R7, callee_saved_value);
3587 set_register(
R8, callee_saved_value);
3588#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3589 set_register(
R9, callee_saved_value);
3591 set_register(
R10, callee_saved_value);
3592 set_register(
R11, callee_saved_value);
3594 double callee_saved_dvalue = 0.0;
3595 callee_saved_dvalue =
static_cast<double>(icount_);
3596 set_dregister(
D8, callee_saved_dvalue);
3597 set_dregister(
D9, callee_saved_dvalue);
3598 set_dregister(
D10, callee_saved_dvalue);
3599 set_dregister(
D11, callee_saved_dvalue);
3600 set_dregister(
D12, callee_saved_dvalue);
3601 set_dregister(
D13, callee_saved_dvalue);
3602 set_dregister(
D14, callee_saved_dvalue);
3603 set_dregister(
D15, callee_saved_dvalue);
3609 ASSERT(callee_saved_value == get_register(
R4));
3610 ASSERT(callee_saved_value == get_register(
R5));
3611 ASSERT(callee_saved_value == get_register(
R6));
3612 ASSERT(callee_saved_value == get_register(
R7));
3613 ASSERT(callee_saved_value == get_register(
R8));
3614#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3615 ASSERT(callee_saved_value == get_register(
R9));
3617 ASSERT(callee_saved_value == get_register(
R10));
3618 ASSERT(callee_saved_value == get_register(
R11));
3620 ASSERT(callee_saved_dvalue == get_dregister(
D8));
3621 ASSERT(callee_saved_dvalue == get_dregister(
D9));
3622 ASSERT(callee_saved_dvalue == get_dregister(
D10));
3623 ASSERT(callee_saved_dvalue == get_dregister(
D11));
3624 ASSERT(callee_saved_dvalue == get_dregister(
D12));
3625 ASSERT(callee_saved_dvalue == get_dregister(
D13));
3626 ASSERT(callee_saved_dvalue == get_dregister(
D14));
3627 ASSERT(callee_saved_dvalue == get_dregister(
D15));
3630 set_register(
R4, r4_val);
3631 set_register(
R5, r5_val);
3632 set_register(
R6, r6_val);
3633 set_register(
R7, r7_val);
3634 set_register(
R8, r8_val);
3635#if !defined(DART_TARGET_OS_MACOS) && !defined(DART_TARGET_OS_MACOS_IOS)
3636 set_register(
R9, r9_val);
3638 set_register(
R10, r10_val);
3639 set_register(
R11, r11_val);
3641 set_dregister(
D8, d8_val);
3642 set_dregister(
D9, d9_val);
3643 set_dregister(
D10, d10_val);
3644 set_dregister(
D11, d11_val);
3645 set_dregister(
D12, d12_val);
3646 set_dregister(
D13, d13_val);
3647 set_dregister(
D14, d14_val);
3648 set_dregister(
D15, d15_val);
3651 set_register(
SP, sp_before_call);
3652 int64_t return_value;
3654 return_value = bit_cast<int64_t, double>(get_dregister(
D0));
3656 return_value = Utils::LowHighTo64Bits(get_register(
R0), get_register(
R1));
3658 return return_value;
3664 SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
3665 while (buf->link() !=
nullptr && buf->link()->sp() <= sp) {
3673 StackResource::Unwind(thread);
3678 set_register(
PC,
static_cast<int32_t
>(pc));
3679 set_register(
SP,
static_cast<int32_t
>(sp));
3680 set_register(
FP,
static_cast<int32_t
>(
fp));
3681 set_register(
THR,
reinterpret_cast<uword>(thread));
3683 thread->set_vm_tag(VMTag::kDartTagId);
3685 thread->set_top_exit_frame_info(0);
3689 int32_t pp = FLAG_precompiled_mode
3690 ?
static_cast<int32_t
>(thread->global_object_pool())
3691 : *
reinterpret_cast<int32_t*
>(
3695 set_register(
PP, pp);
3696 if (FLAG_precompiled_mode) {
3698 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
uint32_t uint32_t * format
Dart_NativeFunction function
const GrXPFactory * Get(SkBlendMode mode)
static bool is_signed(const Type &type)
bool Contains(const Container &container, const Value &value)
def link(from_root, to_root)
static int64_t GetValue(Dart_Handle arg)
float ReciprocalSqrtEstimate(float op)
void SetBreakpoint(Dart_NativeArguments args)
const RegList kAbiVolatileCpuRegs
static uint64_t RotateRight(uint64_t value, uint8_t rotate, uint8_t width)
float ReciprocalStep(float op1, float op2)
const Register DISPATCH_TABLE_REG
constexpr uword kDataMemoryBarrier
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
static constexpr int kPcMarkerSlotFromFp
float ReciprocalSqrtStep(float op1, float op2)
constexpr intptr_t kWordSize
float ReciprocalEstimate(float op)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
def Format(template, **parameters)
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
#define NO_SANITIZE_UNDEFINED(check)
#define ARRAY_SIZE(array)
#define OFFSET_OF(type, field)