8#if defined(USE_SIMULATOR)
33 Simulator::GlobalMonitor::Get)
36inline bool HaveSameSign(int64_t a, int64_t b) {
return ((a ^ b) >= 0); }
41bool isMipsSupportUnalignedAccess =
true;
43uint32_t get_fcsr_condition_bit(uint32_t
cc) {
61 explicit MipsDebugger(Simulator* sim) : sim_(sim) {}
63 void Stop(Instruction*
instr);
67 void PrintAllRegsIncludingFPU();
72 static const Instr kNopInstr = 0x0;
76 int64_t GetRegisterValue(
int regnum);
77 int64_t GetFPURegisterValue(
int regnum);
78 float GetFPURegisterValueFloat(
int regnum);
79 double GetFPURegisterValueDouble(
int regnum);
80 bool GetValue(
const char* desc, int64_t* value);
83 bool SetBreakpoint(Instruction* breakpc);
84 bool DeleteBreakpoint(Instruction* breakpc);
88 void UndoBreakpoints();
89 void RedoBreakpoints();
92inline void UNSUPPORTED() { printf(
"Sim: Unsupported instruction.\n"); }
94void MipsDebugger::Stop(Instruction*
instr) {
97 PrintF(
"Simulator hit (%u)\n", code);
101int64_t MipsDebugger::GetRegisterValue(
int regnum) {
103 return sim_->get_pc();
105 return sim_->get_register(regnum);
109int64_t MipsDebugger::GetFPURegisterValue(
int regnum) {
111 return sim_->get_pc();
113 return sim_->get_fpu_register(regnum);
117float MipsDebugger::GetFPURegisterValueFloat(
int regnum) {
119 return sim_->get_pc();
121 return sim_->get_fpu_register_float(regnum);
125double MipsDebugger::GetFPURegisterValueDouble(
int regnum) {
127 return sim_->get_pc();
129 return sim_->get_fpu_register_double(regnum);
133bool MipsDebugger::GetValue(
const char* desc, int64_t* value) {
138 *value = GetRegisterValue(regnum);
141 *value = GetFPURegisterValue(fpuregnum);
143 }
else if (strncmp(desc,
"0x", 2) == 0) {
144 return SScanF(desc + 2,
"%" SCNx64,
reinterpret_cast<uint64_t*
>(value)) ==
147 return SScanF(desc,
"%" SCNu64,
reinterpret_cast<uint64_t*
>(value)) == 1;
151bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
153 if (sim_->break_pc_ !=
nullptr) {
158 sim_->break_pc_ = breakpc;
159 sim_->break_instr_ = breakpc->InstructionBits();
165bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
166 if (sim_->break_pc_ !=
nullptr) {
167 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
170 sim_->break_pc_ =
nullptr;
171 sim_->break_instr_ = 0;
175void MipsDebugger::UndoBreakpoints() {
176 if (sim_->break_pc_ !=
nullptr) {
177 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
181void MipsDebugger::RedoBreakpoints() {
182 if (sim_->break_pc_ !=
nullptr) {
183 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
187void MipsDebugger::PrintAllRegs() {
188#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
192 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
"\t%3s: 0x%016" PRIx64
" %14" PRId64
193 "\t%3s: 0x%016" PRIx64
" %14" PRId64
"\n",
194 REG_INFO(1), REG_INFO(2), REG_INFO(4));
196 PrintF(
"%34s\t%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
198 "", REG_INFO(3), REG_INFO(5));
200 PrintF(
"%34s\t%34s\t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
"",
"",
203 PrintF(
"%34s\t%34s\t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
"",
"",
207 for (
int i = 0;
i < 8;
i++) {
208 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
210 REG_INFO(8 +
i), REG_INFO(16 +
i));
214 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
215 " %14" PRId64
" \t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
216 REG_INFO(24), REG_INFO(26), REG_INFO(32));
218 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
219 " %14" PRId64
" \t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
220 REG_INFO(25), REG_INFO(27), REG_INFO(33));
222 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
223 " %14" PRId64
" \t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
224 REG_INFO(29), REG_INFO(30), REG_INFO(28));
226 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
228 REG_INFO(31), REG_INFO(34));
233void MipsDebugger::PrintAllRegsIncludingFPU() {
234#define FPU_REG_INFO(n) \
235 FPURegisters::Name(n), GetFPURegisterValue(n), GetFPURegisterValueDouble(n)
242 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(0));
243 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(1));
244 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(2));
245 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(3));
246 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(4));
247 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(5));
248 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(6));
249 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(7));
250 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(8));
251 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(9));
252 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(10));
253 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(11));
254 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(12));
255 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(13));
256 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(14));
257 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(15));
258 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(16));
259 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(17));
260 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(18));
261 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(19));
262 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(20));
263 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(21));
264 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(22));
265 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(23));
266 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(24));
267 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(25));
268 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(26));
269 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(27));
270 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(28));
271 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(29));
272 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(30));
273 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(31));
278void MipsDebugger::Debug() {
279 if (
v8_flags.correctness_fuzzer_suppressions) {
280 PrintF(
"Debugger disabled for differential fuzzing.\n");
283 intptr_t last_pc = -1;
286#define COMMAND_SIZE 63
290#define XSTR(a) STR(a)
292 char cmd[COMMAND_SIZE + 1];
293 char arg1[ARG_SIZE + 1];
294 char arg2[ARG_SIZE + 1];
295 char* argv[3] = {cmd, arg1, arg2};
298 cmd[COMMAND_SIZE] = 0;
306 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
307 if (last_pc != sim_->get_pc()) {
312 dasm.InstructionDecode(buffer,
313 reinterpret_cast<uint8_t*
>(sim_->get_pc()));
314 PrintF(
" 0x%016" PRIx64
" %s\n", sim_->get_pc(), buffer.
begin());
315 last_pc = sim_->get_pc();
318 if (line ==
nullptr) {
321 char* last_input = sim_->last_debugger_input();
322 if (strcmp(line,
"\n") == 0 && last_input !=
nullptr) {
326 sim_->set_last_debugger_input(line);
330 int argc = SScanF(line,
331 "%" XSTR(COMMAND_SIZE)
"s "
332 "%" XSTR(ARG_SIZE)
"s "
333 "%" XSTR(ARG_SIZE)
"s",
335 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
336 Instruction*
instr =
reinterpret_cast<Instruction*
>(sim_->get_pc());
339 sim_->InstructionDecode(
340 reinterpret_cast<Instruction*
>(sim_->get_pc()));
343 PrintF(
"/!\\ Jumping over generated breakpoint.\n");
346 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
348 sim_->InstructionDecode(
reinterpret_cast<Instruction*
>(sim_->get_pc()));
351 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
355 if (strcmp(arg1,
"all") == 0) {
357 }
else if (strcmp(arg1,
"allf") == 0) {
358 PrintAllRegsIncludingFPU();
364 value = GetRegisterValue(regnum);
365 PrintF(
"%s: 0x%08" PRIx64
" %" PRId64
" \n", arg1, value,
368 value = GetFPURegisterValue(fpuregnum);
369 dvalue = GetFPURegisterValueDouble(fpuregnum);
370 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n",
373 PrintF(
"%s unrecognized\n", arg1);
378 if (strcmp(arg2,
"single") == 0) {
384 value = GetFPURegisterValue(fpuregnum);
385 value &= 0xFFFFFFFFUL;
386 fvalue = GetFPURegisterValueFloat(fpuregnum);
387 PrintF(
"%s: 0x%08" PRIx64
" %11.4e\n", arg1, value, fvalue);
389 PrintF(
"%s unrecognized\n", arg1);
392 PrintF(
"print <fpu register> single\n");
395 PrintF(
"print <register> or print <fpu register> single\n");
398 }
else if ((strcmp(cmd,
"po") == 0) ||
399 (strcmp(cmd,
"printobject") == 0)) {
403 if (GetValue(arg1, &value)) {
405 os << arg1 <<
": \n";
410 os << Brief(obj) <<
"\n";
413 os << arg1 <<
" unrecognized\n";
416 PrintF(
"printobject <value>\n");
418 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0 ||
419 strcmp(cmd,
"dump") == 0) {
420 int64_t* cur =
nullptr;
421 int64_t*
end =
nullptr;
424 if (strcmp(cmd,
"stack") == 0) {
425 cur =
reinterpret_cast<int64_t*
>(sim_->get_register(Simulator::sp));
428 if (!GetValue(arg1, &value)) {
429 PrintF(
"%s unrecognized\n", arg1);
432 cur =
reinterpret_cast<int64_t*
>(
value);
437 if (argc == next_arg) {
440 if (!GetValue(argv[next_arg], &words)) {
446 bool skip_obj_print = (strcmp(cmd,
"dump") == 0);
448 PrintF(
" 0x%012" PRIxPTR
" : 0x%016" PRIx64
" %14" PRId64
" ",
449 reinterpret_cast<intptr_t
>(cur), *cur, *cur);
451 Heap* current_heap = sim_->isolate_->heap();
452 if (!skip_obj_print) {
468 }
else if ((strcmp(cmd,
"disasm") == 0) || (strcmp(cmd,
"dpc") == 0) ||
469 (strcmp(cmd,
"di") == 0)) {
475 uint8_t* cur =
nullptr;
476 uint8_t*
end =
nullptr;
479 cur =
reinterpret_cast<uint8_t*
>(sim_->get_pc());
481 }
else if (argc == 2) {
486 if (GetValue(arg1, &value)) {
487 cur =
reinterpret_cast<uint8_t*
>(
value);
494 if (GetValue(arg1, &value)) {
495 cur =
reinterpret_cast<uint8_t*
>(sim_->get_pc());
503 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
504 cur =
reinterpret_cast<uint8_t*
>(value1);
510 dasm.InstructionDecode(buffer, cur);
511 PrintF(
" 0x%08" PRIxPTR
" %s\n",
reinterpret_cast<intptr_t
>(cur),
515 }
else if (strcmp(cmd,
"gdb") == 0) {
516 PrintF(
"relinquishing control to gdb\n");
518 PrintF(
"regaining control from gdb\n");
519 }
else if (strcmp(cmd,
"break") == 0) {
522 if (GetValue(arg1, &value)) {
523 if (!SetBreakpoint(
reinterpret_cast<Instruction*
>(value))) {
524 PrintF(
"setting breakpoint failed\n");
527 PrintF(
"%s unrecognized\n", arg1);
530 PrintF(
"break <address>\n");
532 }
else if (strcmp(cmd,
"del") == 0) {
533 if (!DeleteBreakpoint(
nullptr)) {
534 PrintF(
"deleting breakpoint failed\n");
536 }
else if (strcmp(cmd,
"flags") == 0) {
537 PrintF(
"No flags on MIPS !\n");
538 }
else if (strcmp(cmd,
"stop") == 0) {
540 intptr_t stop_pc = sim_->get_pc() - 2 *
kInstrSize;
541 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
542 Instruction* msg_address =
543 reinterpret_cast<Instruction*
>(stop_pc +
kInstrSize);
544 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
546 if (sim_->IsStopInstruction(stop_instr)) {
547 stop_instr->SetInstructionBits(kNopInstr);
548 msg_address->SetInstructionBits(kNopInstr);
550 PrintF(
"Not at debugger stop.\n");
552 }
else if (argc == 3) {
554 if (strcmp(arg1,
"info") == 0) {
555 if (strcmp(arg2,
"all") == 0) {
556 PrintF(
"Stop information:\n");
559 sim_->PrintStopInfo(
i);
561 }
else if (GetValue(arg2, &value)) {
562 sim_->PrintStopInfo(value);
564 PrintF(
"Unrecognized argument.\n");
566 }
else if (strcmp(arg1,
"enable") == 0) {
568 if (strcmp(arg2,
"all") == 0) {
573 }
else if (GetValue(arg2, &value)) {
574 sim_->EnableStop(value);
576 PrintF(
"Unrecognized argument.\n");
578 }
else if (strcmp(arg1,
"disable") == 0) {
580 if (strcmp(arg2,
"all") == 0) {
583 sim_->DisableStop(
i);
585 }
else if (GetValue(arg2, &value)) {
586 sim_->DisableStop(value);
588 PrintF(
"Unrecognized argument.\n");
592 PrintF(
"Wrong usage. Use help command for more information.\n");
594 }
else if ((strcmp(cmd,
"stat") == 0) || (strcmp(cmd,
"st") == 0)) {
604 uint8_t* cur =
nullptr;
605 uint8_t*
end =
nullptr;
608 cur =
reinterpret_cast<uint8_t*
>(sim_->get_pc());
610 }
else if (argc == 2) {
612 if (GetValue(arg1, &value)) {
613 cur =
reinterpret_cast<uint8_t*
>(
value);
620 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
621 cur =
reinterpret_cast<uint8_t*
>(value1);
627 dasm.InstructionDecode(buffer, cur);
628 PrintF(
" 0x%08" PRIxPTR
" %s\n",
reinterpret_cast<intptr_t
>(cur),
632 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
634 PrintF(
" continue execution (alias 'c')\n");
636 PrintF(
" step one instruction (alias 'si')\n");
637 PrintF(
"print <register>\n");
638 PrintF(
" print register content (alias 'p')\n");
639 PrintF(
" use register name 'all' to print all registers\n");
640 PrintF(
"printobject <register>\n");
641 PrintF(
" print an object from a register (alias 'po')\n");
642 PrintF(
"stack [<words>]\n");
643 PrintF(
" dump stack content, default dump 10 words)\n");
644 PrintF(
"mem <address> [<words>]\n");
645 PrintF(
" dump memory content, default dump 10 words)\n");
646 PrintF(
"dump [<words>]\n");
648 " dump memory content without pretty printing JS objects, default "
652 PrintF(
"disasm [<instructions>]\n");
653 PrintF(
"disasm [<address/register>]\n");
654 PrintF(
"disasm [[<address/register>] <instructions>]\n");
655 PrintF(
" disassemble code, default is 10 instructions\n");
656 PrintF(
" from pc (alias 'di')\n");
659 PrintF(
"break <address>\n");
660 PrintF(
" set a break point on the address\n");
662 PrintF(
" delete the breakpoint\n");
663 PrintF(
"stop feature:\n");
664 PrintF(
" Description:\n");
665 PrintF(
" Stops are debug instructions inserted by\n");
666 PrintF(
" the Assembler::stop() function.\n");
667 PrintF(
" When hitting a stop, the Simulator will\n");
668 PrintF(
" stop and give control to the Debugger.\n");
669 PrintF(
" All stop codes are watched:\n");
670 PrintF(
" - They can be enabled / disabled: the Simulator\n");
671 PrintF(
" will / won't stop when hitting them.\n");
672 PrintF(
" - The Simulator keeps track of how many times they \n");
673 PrintF(
" are met. (See the info command.) Going over a\n");
674 PrintF(
" disabled stop still increases its counter. \n");
676 PrintF(
" stop info all/<code> : print infos about number <code>\n");
677 PrintF(
" or all stop(s).\n");
678 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
679 PrintF(
" all or number <code> stop(s)\n");
681 PrintF(
" ignore the stop instruction at the current location\n");
684 PrintF(
"Unknown command: %s\n", cmd);
700bool Simulator::ICacheMatch(
void*
one,
void* two) {
701 DCHECK_EQ(
reinterpret_cast<intptr_t
>(
one) & CachePage::kPageMask, 0);
702 DCHECK_EQ(
reinterpret_cast<intptr_t
>(two) & CachePage::kPageMask, 0);
706static uint32_t ICacheHash(
void*
key) {
707 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(
key)) >> 2;
710static bool AllOnOnePage(uintptr_t
start,
size_t size) {
711 intptr_t start_page = (
start & ~CachePage::kPageMask);
712 intptr_t end_page = ((
start +
size) & ~CachePage::kPageMask);
713 return start_page == end_page;
716void Simulator::set_last_debugger_input(
char* input) {
718 last_debugger_input_ = input;
721void Simulator::SetRedirectInstruction(Instruction* instruction) {
726 void* start_addr,
size_t size) {
727 int64_t
start =
reinterpret_cast<int64_t
>(start_addr);
728 int64_t intra_line = (
start & CachePage::kLineMask);
731 size = ((size - 1) | CachePage::kLineMask) + 1;
733 while (!AllOnOnePage(
start, size - 1)) {
734 int bytes_to_flush = CachePage::kPageSize -
offset;
735 FlushOnePage(i_cache,
start, bytes_to_flush);
736 start += bytes_to_flush;
737 size -= bytes_to_flush;
742 FlushOnePage(i_cache,
start, size);
749 if (entry->value ==
nullptr) {
750 CachePage* new_page =
new CachePage();
751 entry->value = new_page;
753 return reinterpret_cast<CachePage*
>(entry->value);
758 intptr_t
start,
size_t size) {
762 DCHECK_EQ(size & CachePage::kLineMask, 0);
763 void* page =
reinterpret_cast<void*
>(
start & (~CachePage::kPageMask));
765 CachePage* cache_page = GetCachePage(i_cache, page);
766 char* valid_bytemap = cache_page->ValidityByte(
offset);
767 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
771 Instruction*
instr) {
772 int64_t address =
reinterpret_cast<int64_t
>(
instr);
773 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
774 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
775 int offset = (address & CachePage::kPageMask);
776 CachePage* cache_page = GetCachePage(i_cache, page);
777 char* cache_valid_byte = cache_page->ValidityByte(
offset);
778 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
779 char* cached_line = cache_page->CachedData(
offset & ~CachePage::kLineMask);
786 memcpy(cached_line, line, CachePage::kLineLength);
787 *cache_valid_byte = CachePage::LINE_VALID;
791Simulator::Simulator(Isolate* isolate) :
isolate_(isolate) {
794 size_t stack_size = AllocatedStackSize();
795 stack_ =
reinterpret_cast<uintptr_t
>(
new uint8_t[stack_size]);
797 pc_modified_ =
false;
809 FPUregisters_[2 *
i] = 0;
810 FPUregisters_[2 *
i + 1] = 0;
829 last_debugger_input_ =
nullptr;
832Simulator::~Simulator() {
833 GlobalMonitor::Get()->RemoveLinkedAddress(&global_monitor_thread_);
834 delete[]
reinterpret_cast<uint8_t*
>(stack_);
838Simulator* Simulator::current(Isolate* isolate) {
840 isolate->FindOrAllocatePerThreadDataForThisThread();
843 Simulator* sim = isolate_data->simulator();
844 if (sim ==
nullptr) {
846 sim =
new Simulator(isolate);
847 isolate_data->set_simulator(sim);
854void Simulator::set_register(
int reg, int64_t value) {
864void Simulator::set_dw_register(
int reg,
const int* dbl) {
871void Simulator::set_fpu_register(
int fpureg, int64_t value) {
872 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
873 FPUregisters_[fpureg * 2] =
value;
876void Simulator::set_fpu_register_word(
int fpureg, int32_t value) {
878 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
881 pword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]);
883 pword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]) + 1;
888void Simulator::set_fpu_register_hi_word(
int fpureg, int32_t value) {
890 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
893 phiword = (
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2])) + 1;
895 phiword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]);
900void Simulator::set_fpu_register_float(
int fpureg,
float value) {
901 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
902 memcpy(&FPUregisters_[fpureg * 2], &value,
sizeof(value));
905void Simulator::set_fpu_register_double(
int fpureg,
double value) {
906 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
907 memcpy(&FPUregisters_[fpureg * 2], &value,
sizeof(value));
912int64_t Simulator::get_register(
int reg)
const {
920double Simulator::get_double_from_register_pair(
int reg) {
929 memcpy(&dm_val, buffer,
sizeof(
registers_[0]));
933int64_t Simulator::get_fpu_register(
int fpureg)
const {
934 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
935 return FPUregisters_[fpureg * 2];
938int32_t Simulator::get_fpu_register_word(
int fpureg)
const {
939 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
940 return static_cast<int32_t>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
943int32_t Simulator::get_fpu_register_signed_word(
int fpureg)
const {
944 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
945 return static_cast<int32_t>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
948int32_t Simulator::get_fpu_register_hi_word(
int fpureg)
const {
949 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
950 return static_cast<int32_t>((FPUregisters_[fpureg * 2] >> 32) & 0xFFFFFFFF);
953float Simulator::get_fpu_register_float(
int fpureg)
const {
954 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
955 return base::bit_cast<float>(get_fpu_register_word(fpureg));
958double Simulator::get_fpu_register_double(
int fpureg)
const {
959 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
960 return base::bit_cast<double>(FPUregisters_[fpureg * 2]);
964void Simulator::get_msa_register(
int wreg, T* value) {
965 DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
966 memcpy(value, FPUregisters_ + wreg * 2, kSimd128Size);
970void Simulator::set_msa_register(
int wreg,
const T* value) {
971 DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
972 memcpy(FPUregisters_ + wreg * 2, value, kSimd128Size);
978void Simulator::GetFpArgs(
double*
x,
double*
y, int32_t*
z) {
980 const int fparg2 = 13;
981 *
x = get_fpu_register_double(12);
982 *
y = get_fpu_register_double(fparg2);
983 *
z =
static_cast<int32_t>(get_register(a2));
988 char buffer[
sizeof(*x)];
992 reg_buffer[0] = get_register(a0);
993 reg_buffer[1] = get_register(a1);
994 memcpy(
x, buffer,
sizeof(buffer));
996 reg_buffer[0] = get_register(a2);
997 reg_buffer[1] = get_register(a3);
998 memcpy(
y, buffer,
sizeof(buffer));
1000 reg_buffer[0] = get_register(a2);
1001 memcpy(
z, buffer,
sizeof(*
z));
1006void Simulator::SetFpResult(
const double&
result) {
1008 set_fpu_register_double(0,
result);
1011 int64_t* reg_buffer =
reinterpret_cast<int64_t*
>(buffer);
1012 memcpy(buffer, &
result,
sizeof(buffer));
1014 set_register(v0, reg_buffer[0]);
1015 set_register(v1, reg_buffer[1]);
1020void Simulator::set_fcsr_bit(uint32_t cc,
bool value) {
1024 FCSR_ &= ~(1 <<
cc);
1028bool Simulator::test_fcsr_bit(uint32_t cc) {
return FCSR_ & (1 <<
cc); }
1030void Simulator::clear_fcsr_cause() {
1031 FCSR_ &= ~kFCSRCauseMask;
1034void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1038void Simulator::set_msacsr_rounding_mode(FPURoundingMode mode) {
1042unsigned int Simulator::get_fcsr_rounding_mode() {
1046unsigned int Simulator::get_msacsr_rounding_mode() {
1052bool Simulator::set_fcsr_round_error(
double original,
double rounded) {
1054 double max_int32 = std::numeric_limits<int32_t>::max();
1055 double min_int32 = std::numeric_limits<int32_t>::min();
1059 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1060 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1061 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1065 if (original != rounded) {
1066 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1067 set_fcsr_bit(kFCSRInexactCauseBit,
true);
1070 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1071 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1072 set_fcsr_bit(kFCSRUnderflowCauseBit,
true);
1076 if (rounded > max_int32 || rounded < min_int32) {
1077 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1078 set_fcsr_bit(kFCSROverflowCauseBit,
true);
1080 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1081 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1090bool Simulator::set_fcsr_round64_error(
double original,
double rounded) {
1094 double max_int64 =
static_cast<double>(std::numeric_limits<int64_t>::max());
1095 double min_int64 = std::numeric_limits<int64_t>::min();
1099 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1100 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1101 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1105 if (original != rounded) {
1106 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1107 set_fcsr_bit(kFCSRInexactCauseBit,
true);
1110 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1111 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1112 set_fcsr_bit(kFCSRUnderflowCauseBit,
true);
1116 if (rounded >= max_int64 || rounded < min_int64) {
1117 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1118 set_fcsr_bit(kFCSROverflowCauseBit,
true);
1120 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1121 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1130bool Simulator::set_fcsr_round_error(
float original,
float rounded) {
1132 double max_int32 = std::numeric_limits<int32_t>::max();
1133 double min_int32 = std::numeric_limits<int32_t>::min();
1137 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1138 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1139 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1143 if (original != rounded) {
1144 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1145 set_fcsr_bit(kFCSRInexactCauseBit,
true);
1148 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1149 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1150 set_fcsr_bit(kFCSRUnderflowCauseBit,
true);
1154 if (rounded > max_int32 || rounded < min_int32) {
1155 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1156 set_fcsr_bit(kFCSROverflowCauseBit,
true);
1158 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1159 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1166void Simulator::set_fpu_register_word_invalid_result(
float original,
1168 if (FCSR_ & kFCSRNaN2008FlagMask) {
1169 double max_int32 = std::numeric_limits<int32_t>::max();
1170 double min_int32 = std::numeric_limits<int32_t>::min();
1171 if (std::isnan(original)) {
1172 set_fpu_register_word(fd_reg(), 0);
1173 }
else if (rounded > max_int32) {
1174 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1175 }
else if (rounded < min_int32) {
1176 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1181 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1185void Simulator::set_fpu_register_invalid_result(
float original,
float rounded) {
1186 if (FCSR_ & kFCSRNaN2008FlagMask) {
1187 double max_int32 = std::numeric_limits<int32_t>::max();
1188 double min_int32 = std::numeric_limits<int32_t>::min();
1189 if (std::isnan(original)) {
1190 set_fpu_register(fd_reg(), 0);
1191 }
else if (rounded > max_int32) {
1192 set_fpu_register(fd_reg(), kFPUInvalidResult);
1193 }
else if (rounded < min_int32) {
1194 set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1199 set_fpu_register(fd_reg(), kFPUInvalidResult);
1203void Simulator::set_fpu_register_invalid_result64(
float original,
1205 if (FCSR_ & kFCSRNaN2008FlagMask) {
1208 double max_int64 =
static_cast<double>(std::numeric_limits<int64_t>::max());
1209 double min_int64 = std::numeric_limits<int64_t>::min();
1210 if (std::isnan(original)) {
1211 set_fpu_register(fd_reg(), 0);
1212 }
else if (rounded >= max_int64) {
1213 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1214 }
else if (rounded < min_int64) {
1215 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1220 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1224void Simulator::set_fpu_register_word_invalid_result(
double original,
1226 if (FCSR_ & kFCSRNaN2008FlagMask) {
1227 double max_int32 = std::numeric_limits<int32_t>::max();
1228 double min_int32 = std::numeric_limits<int32_t>::min();
1229 if (std::isnan(original)) {
1230 set_fpu_register_word(fd_reg(), 0);
1231 }
else if (rounded > max_int32) {
1232 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1233 }
else if (rounded < min_int32) {
1234 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1239 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1243void Simulator::set_fpu_register_invalid_result(
double original,
1245 if (FCSR_ & kFCSRNaN2008FlagMask) {
1246 double max_int32 = std::numeric_limits<int32_t>::max();
1247 double min_int32 = std::numeric_limits<int32_t>::min();
1248 if (std::isnan(original)) {
1249 set_fpu_register(fd_reg(), 0);
1250 }
else if (rounded > max_int32) {
1251 set_fpu_register(fd_reg(), kFPUInvalidResult);
1252 }
else if (rounded < min_int32) {
1253 set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1258 set_fpu_register(fd_reg(), kFPUInvalidResult);
1262void Simulator::set_fpu_register_invalid_result64(
double original,
1264 if (FCSR_ & kFCSRNaN2008FlagMask) {
1267 double max_int64 =
static_cast<double>(std::numeric_limits<int64_t>::max());
1268 double min_int64 = std::numeric_limits<int64_t>::min();
1269 if (std::isnan(original)) {
1270 set_fpu_register(fd_reg(), 0);
1271 }
else if (rounded >= max_int64) {
1272 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1273 }
else if (rounded < min_int64) {
1274 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1279 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1285bool Simulator::set_fcsr_round64_error(
float original,
float rounded) {
1289 double max_int64 =
static_cast<double>(std::numeric_limits<int64_t>::max());
1290 double min_int64 = std::numeric_limits<int64_t>::min();
1294 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1295 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1296 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1300 if (original != rounded) {
1301 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1302 set_fcsr_bit(kFCSRInexactCauseBit,
true);
1305 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1306 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1307 set_fcsr_bit(kFCSRUnderflowCauseBit,
true);
1311 if (rounded >= max_int64 || rounded < min_int64) {
1312 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1313 set_fcsr_bit(kFCSROverflowCauseBit,
true);
1315 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1316 set_fcsr_bit(kFCSRInvalidOpCauseBit,
true);
1324void Simulator::round_according_to_fcsr(
double toRound,
double* rounded,
1325 int32_t* rounded_int,
double fs) {
1339 switch (FCSR_ & 3) {
1341 *rounded = std::floor(fs + 0.5);
1342 *rounded_int =
static_cast<int32_t>(*rounded);
1343 if ((*rounded_int & 1) != 0 && *rounded_int - fs == 0.5) {
1351 *rounded = trunc(fs);
1352 *rounded_int =
static_cast<int32_t>(*rounded);
1355 *rounded = std::ceil(fs);
1356 *rounded_int =
static_cast<int32_t>(*rounded);
1359 *rounded = std::floor(fs);
1360 *rounded_int =
static_cast<int32_t>(*rounded);
1365void Simulator::round64_according_to_fcsr(
double toRound,
double* rounded,
1366 int64_t* rounded_int,
double fs) {
1380 switch (FCSR_ & 3) {
1382 *rounded = std::floor(fs + 0.5);
1383 *rounded_int =
static_cast<int64_t
>(*rounded);
1384 if ((*rounded_int & 1) != 0 && *rounded_int - fs == 0.5) {
1392 *rounded = trunc(fs);
1393 *rounded_int =
static_cast<int64_t
>(*rounded);
1396 *rounded = std::ceil(fs);
1397 *rounded_int =
static_cast<int64_t
>(*rounded);
1400 *rounded = std::floor(fs);
1401 *rounded_int =
static_cast<int64_t
>(*rounded);
1407void Simulator::round_according_to_fcsr(
float toRound,
float* rounded,
1408 int32_t* rounded_int,
float fs) {
1422 switch (FCSR_ & 3) {
1424 *rounded = std::floor(fs + 0.5);
1425 *rounded_int =
static_cast<int32_t>(*rounded);
1426 if ((*rounded_int & 1) != 0 && *rounded_int - fs == 0.5) {
1434 *rounded = trunc(fs);
1435 *rounded_int =
static_cast<int32_t>(*rounded);
1438 *rounded = std::ceil(fs);
1439 *rounded_int =
static_cast<int32_t>(*rounded);
1442 *rounded = std::floor(fs);
1443 *rounded_int =
static_cast<int32_t>(*rounded);
1448void Simulator::round64_according_to_fcsr(
float toRound,
float* rounded,
1449 int64_t* rounded_int,
float fs) {
1463 switch (FCSR_ & 3) {
1465 *rounded = std::floor(fs + 0.5);
1466 *rounded_int =
static_cast<int64_t
>(*rounded);
1467 if ((*rounded_int & 1) != 0 && *rounded_int - fs == 0.5) {
1475 *rounded = trunc(fs);
1476 *rounded_int =
static_cast<int64_t
>(*rounded);
1479 *rounded = std::ceil(fs);
1480 *rounded_int =
static_cast<int64_t
>(*rounded);
1483 *rounded = std::floor(fs);
1484 *rounded_int =
static_cast<int64_t
>(*rounded);
1489template <
typename T_fp,
typename T_
int>
1490void Simulator::round_according_to_msacsr(T_fp toRound, T_fp* rounded,
1491 T_int* rounded_int) {
1505 switch (get_msacsr_rounding_mode()) {
1507 *rounded = std::floor(toRound + 0.5);
1508 *rounded_int =
static_cast<T_int
>(*rounded);
1509 if ((*rounded_int & 1) != 0 && *rounded_int - toRound == 0.5) {
1517 *rounded = trunc(toRound);
1518 *rounded_int =
static_cast<T_int
>(*rounded);
1521 *rounded = std::ceil(toRound);
1522 *rounded_int =
static_cast<T_int
>(*rounded);
1525 *rounded = std::floor(toRound);
1526 *rounded_int =
static_cast<T_int
>(*rounded);
1532void Simulator::set_pc(int64_t value) {
1533 pc_modified_ =
true;
1537bool Simulator::has_bad_pc()
const {
1542int64_t Simulator::get_pc()
const {
return registers_[
pc]; }
1553void Simulator::DieOrDebug() {
1555 MipsDebugger dbg(
this);
1562void Simulator::TraceRegWr(int64_t value, TraceType t) {
1570 v.fmt_int64 =
value;
1574 base::SNPrintF(trace_buf_,
1575 "%016" PRIx64
" (%" PRId64
") int32:%" PRId32
1577 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0]);
1580 base::SNPrintF(trace_buf_,
1581 "%016" PRIx64
" (%" PRId64
") int64:%" PRId64
1583 value, icount_, value, value);
1586 base::SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") flt:%e",
1587 v.fmt_int64, icount_, v.fmt_float[0]);
1590 base::SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") dbl:%e",
1591 v.fmt_int64, icount_, v.fmt_double);
1594 base::SNPrintF(trace_buf_,
1595 "%016" PRIx64
" (%" PRId64
") flt:%e dbl:%e",
1596 v.fmt_int64, icount_, v.fmt_float[0], v.fmt_double);
1599 base::SNPrintF(trace_buf_,
1600 "%016" PRIx64
" (%" PRId64
") int32:%" PRId32
1601 " uint32:%" PRIu32
" int64:%" PRId64
" uint64:%" PRIu64,
1602 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0],
1603 v.fmt_int64, v.fmt_int64);
1611template <
typename T>
1612void Simulator::TraceMSARegWr(T* value, TraceType t) {
1622 memcpy(v.b, value, kSimd128Size);
1625 base::SNPrintF(trace_buf_,
1626 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1628 v.d[0], v.d[1], icount_);
1631 base::SNPrintF(trace_buf_,
1632 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1634 v.d[0], v.d[1], icount_);
1637 base::SNPrintF(trace_buf_,
1638 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1639 ") int32[0..3]:%" PRId32
" %" PRId32
" %" PRId32
1641 v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1644 base::SNPrintF(trace_buf_,
1645 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1647 v.d[0], v.d[1], icount_);
1650 base::SNPrintF(trace_buf_,
1651 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1652 ") flt[0..3]:%e %e %e %e",
1653 v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1656 base::SNPrintF(trace_buf_,
1657 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1658 ") dbl[0..1]:%e %e",
1659 v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1667template <
typename T>
1668void Simulator::TraceMSARegWr(T* value) {
1678 memcpy(v.b, value, kMSALanesByte);
1680 if (std::is_same<T, int32_t>::value) {
1681 base::SNPrintF(trace_buf_,
1682 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1683 ") int32[0..3]:%" PRId32
" %" PRId32
" %" PRId32
1685 v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1686 }
else if (std::is_same<T, float>::value) {
1687 base::SNPrintF(trace_buf_,
1688 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1689 ") flt[0..3]:%e %e %e %e",
1690 v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1691 }
else if (std::is_same<T, double>::value) {
1692 base::SNPrintF(trace_buf_,
1693 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1694 ") dbl[0..1]:%e %e",
1695 v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1697 base::SNPrintF(trace_buf_,
1698 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1699 v.d[0], v.d[1], icount_);
1705void Simulator::TraceMemRd(int64_t addr, int64_t value, TraceType t) {
1713 v.fmt_int64 =
value;
1717 base::SNPrintF(trace_buf_,
1718 "%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1719 ") int32:%" PRId32
" uint32:%" PRIu32,
1720 v.fmt_int64, addr, icount_, v.fmt_int32[0],
1724 base::SNPrintF(trace_buf_,
1725 "%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1726 ") int64:%" PRId64
" uint64:%" PRIu64,
1727 value, addr, icount_, value, value);
1730 base::SNPrintF(trace_buf_,
1731 "%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1733 v.fmt_int64, addr, icount_, v.fmt_float[0]);
1736 base::SNPrintF(trace_buf_,
1737 "%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1739 v.fmt_int64, addr, icount_, v.fmt_double);
1742 base::SNPrintF(trace_buf_,
1743 "%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1745 v.fmt_int64, addr, icount_, v.fmt_float[0],
1754void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) {
1758 base::SNPrintF(trace_buf_,
1759 " %02" PRIx8
" --> [%016" PRIx64
1761 static_cast<uint8_t
>(value), addr, icount_);
1764 base::SNPrintF(trace_buf_,
1765 " %04" PRIx16
" --> [%016" PRIx64
1767 static_cast<uint16_t>(value), addr, icount_);
1770 base::SNPrintF(trace_buf_,
1771 " %08" PRIx32
" --> [%016" PRIx64
"] (%" PRId64
1773 static_cast<uint32_t
>(value), addr, icount_);
1776 base::SNPrintF(trace_buf_,
1777 "%016" PRIx64
" --> [%016" PRIx64
"] (%" PRId64
" )",
1778 value, addr, icount_);
1786template <
typename T>
1787void Simulator::TraceMemRd(int64_t addr, T value) {
1789 switch (
sizeof(T)) {
1791 base::SNPrintF(trace_buf_,
1792 "%08" PRIx8
" <-- [%08" PRIx64
"] (%" PRIu64
1793 ") int8:%" PRId8
" uint8:%" PRIu8,
1794 static_cast<uint8_t
>(value), addr, icount_,
1795 static_cast<int8_t
>(value),
static_cast<uint8_t
>(value));
1798 base::SNPrintF(trace_buf_,
1799 "%08" PRIx16
" <-- [%08" PRIx64
"] (%" PRIu64
1800 ") int16:%" PRId16
" uint16:%" PRIu16,
1801 static_cast<uint16_t>(value), addr, icount_,
1806 base::SNPrintF(trace_buf_,
1807 "%08" PRIx32
" <-- [%08" PRIx64
"] (%" PRIu64
1808 ") int32:%" PRId32
" uint32:%" PRIu32,
1809 static_cast<uint32_t
>(value), addr, icount_,
1811 static_cast<uint32_t
>(value));
1814 base::SNPrintF(trace_buf_,
1815 "%08" PRIx64
" <-- [%08" PRIx64
"] (%" PRIu64
1816 ") int64:%" PRId64
" uint64:%" PRIu64,
1817 static_cast<uint64_t
>(value), addr, icount_,
1818 static_cast<int64_t
>(value),
1819 static_cast<uint64_t
>(value));
1827template <
typename T>
1828void Simulator::TraceMemWr(int64_t addr, T value) {
1830 switch (
sizeof(T)) {
1832 base::SNPrintF(trace_buf_,
1833 " %02" PRIx8
" --> [%08" PRIx64
"] (%" PRIu64
1835 static_cast<uint8_t
>(value), addr, icount_);
1838 base::SNPrintF(trace_buf_,
1839 " %04" PRIx16
" --> [%08" PRIx64
"] (%" PRIu64
")",
1840 static_cast<uint16_t>(value), addr, icount_);
1843 base::SNPrintF(trace_buf_,
1844 "%08" PRIx32
" --> [%08" PRIx64
"] (%" PRIu64
")",
1845 static_cast<uint32_t
>(value), addr, icount_);
1848 base::SNPrintF(trace_buf_,
1849 "%16" PRIx64
" --> [%08" PRIx64
"] (%" PRIu64
")",
1850 static_cast<uint64_t
>(value), addr, icount_);
1860int32_t Simulator::ReadW(int64_t addr, Instruction*
instr, TraceType t) {
1861 if (addr >= 0 && addr < 0x400) {
1863 PrintF(
"Memory read from bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1865 addr,
reinterpret_cast<intptr_t
>(
instr));
1869 isMipsSupportUnalignedAccess) {
1870 local_monitor_.NotifyLoad();
1872 TraceMemRd(addr,
static_cast<int64_t
>(*ptr), t);
1875 PrintF(
"Unaligned read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
1876 reinterpret_cast<intptr_t
>(
instr));
1881uint32_t Simulator::ReadWU(int64_t addr, Instruction*
instr) {
1882 if (addr >= 0 && addr < 0x400) {
1884 PrintF(
"Memory read from bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1886 addr,
reinterpret_cast<intptr_t
>(
instr));
1890 local_monitor_.NotifyLoad();
1891 uint32_t* ptr =
reinterpret_cast<uint32_t*
>(addr);
1892 TraceMemRd(addr,
static_cast<int64_t
>(*ptr), WORD);
1895 PrintF(
"Unaligned read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
1896 reinterpret_cast<intptr_t
>(
instr));
1901void Simulator::WriteW(int64_t addr, int32_t value, Instruction*
instr) {
1902 if (addr >= 0 && addr < 0x400) {
1904 PrintF(
"Memory write to bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1906 addr,
reinterpret_cast<intptr_t
>(
instr));
1910 local_monitor_.NotifyStore();
1911 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
1912 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
1913 TraceMemWr(addr, value, WORD);
1914 int* ptr =
reinterpret_cast<int*
>(addr);
1918 PrintF(
"Unaligned write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
1919 reinterpret_cast<intptr_t
>(
instr));
1923void Simulator::WriteConditionalW(int64_t addr, int32_t value,
1924 Instruction*
instr, int32_t rt_reg) {
1925 if (addr >= 0 && addr < 0x400) {
1927 PrintF(
"Memory write to bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1929 addr,
reinterpret_cast<intptr_t
>(
instr));
1933 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
1934 if (local_monitor_.NotifyStoreConditional(addr, TransactionSize::Word) &&
1935 GlobalMonitor::Get()->NotifyStoreConditional_Locked(
1936 addr, &global_monitor_thread_)) {
1937 local_monitor_.NotifyStore();
1938 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
1939 TraceMemWr(addr, value, WORD);
1940 int* ptr =
reinterpret_cast<int*
>(addr);
1942 set_register(rt_reg, 1);
1944 set_register(rt_reg, 0);
1948 PrintF(
"Unaligned write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
1949 reinterpret_cast<intptr_t
>(
instr));
1953int64_t Simulator::Read2W(int64_t addr, Instruction*
instr) {
1954 if (addr >= 0 && addr < 0x400) {
1956 PrintF(
"Memory read from bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1958 addr,
reinterpret_cast<intptr_t
>(
instr));
1962 isMipsSupportUnalignedAccess) {
1963 local_monitor_.NotifyLoad();
1964 int64_t* ptr =
reinterpret_cast<int64_t*
>(addr);
1965 TraceMemRd(addr, *ptr);
1968 PrintF(
"Unaligned read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
1969 reinterpret_cast<intptr_t
>(
instr));
1974void Simulator::Write2W(int64_t addr, int64_t value, Instruction*
instr) {
1975 if (addr >= 0 && addr < 0x400) {
1977 PrintF(
"Memory write to bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1979 addr,
reinterpret_cast<intptr_t
>(
instr));
1983 local_monitor_.NotifyStore();
1984 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
1985 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
1986 TraceMemWr(addr, value,
DWORD);
1987 int64_t* ptr =
reinterpret_cast<int64_t*
>(addr);
1991 PrintF(
"Unaligned write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
1992 reinterpret_cast<intptr_t
>(
instr));
1996void Simulator::WriteConditional2W(int64_t addr, int64_t value,
1997 Instruction*
instr, int32_t rt_reg) {
1998 if (addr >= 0 && addr < 0x400) {
2000 PrintF(
"Memory write to bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
2002 addr,
reinterpret_cast<intptr_t
>(
instr));
2006 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2007 if (local_monitor_.NotifyStoreConditional(addr,
2008 TransactionSize::DoubleWord) &&
2009 GlobalMonitor::Get()->NotifyStoreConditional_Locked(
2010 addr, &global_monitor_thread_)) {
2011 local_monitor_.NotifyStore();
2012 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2013 TraceMemWr(addr, value,
DWORD);
2014 int64_t* ptr =
reinterpret_cast<int64_t*
>(addr);
2016 set_register(rt_reg, 1);
2018 set_register(rt_reg, 0);
2022 PrintF(
"Unaligned write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n", addr,
2023 reinterpret_cast<intptr_t
>(
instr));
2027double Simulator::ReadD(int64_t addr, Instruction*
instr) {
2029 local_monitor_.NotifyLoad();
2030 double* ptr =
reinterpret_cast<double*
>(addr);
2033 PrintF(
"Unaligned (double) read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR "\n",
2034 addr,
reinterpret_cast<intptr_t
>(
instr));
2038void Simulator::WriteD(int64_t addr,
double value, Instruction*
instr) {
2040 local_monitor_.NotifyStore();
2041 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2042 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2043 double* ptr =
reinterpret_cast<double*
>(addr);
2047 PrintF(
"Unaligned (double) write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
2049 addr,
reinterpret_cast<intptr_t
>(
instr));
2053uint16_t Simulator::ReadHU(int64_t addr, Instruction*
instr) {
2055 local_monitor_.NotifyLoad();
2057 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
2060 PrintF(
"Unaligned unsigned halfword read at 0x%08" PRIx64
2062 addr,
reinterpret_cast<intptr_t
>(
instr));
2067int16_t Simulator::ReadH(int64_t addr, Instruction*
instr) {
2069 local_monitor_.NotifyLoad();
2071 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
2074 PrintF(
"Unaligned signed halfword read at 0x%08" PRIx64
2076 addr,
reinterpret_cast<intptr_t
>(
instr));
2081void Simulator::WriteH(int64_t addr, uint16_t value, Instruction*
instr) {
2083 local_monitor_.NotifyStore();
2084 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2085 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2086 TraceMemWr(addr, value, HALF);
2091 PrintF(
"Unaligned unsigned halfword write at 0x%08" PRIx64
2093 addr,
reinterpret_cast<intptr_t
>(
instr));
2097void Simulator::WriteH(int64_t addr, int16_t value, Instruction*
instr) {
2099 local_monitor_.NotifyStore();
2100 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2101 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2102 TraceMemWr(addr, value, HALF);
2107 PrintF(
"Unaligned halfword write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
2109 addr,
reinterpret_cast<intptr_t
>(
instr));
2113uint32_t Simulator::ReadBU(int64_t addr) {
2114 local_monitor_.NotifyLoad();
2115 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
2116 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
2120int32_t Simulator::ReadB(int64_t addr) {
2121 local_monitor_.NotifyLoad();
2122 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
2123 TraceMemRd(addr,
static_cast<int64_t
>(*ptr));
2127void Simulator::WriteB(int64_t addr, uint8_t value) {
2128 local_monitor_.NotifyStore();
2129 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2130 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2131 TraceMemWr(addr, value, BYTE);
2132 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
2136void Simulator::WriteB(int64_t addr, int8_t value) {
2137 local_monitor_.NotifyStore();
2138 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2139 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2140 TraceMemWr(addr, value, BYTE);
2141 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
2145template <
typename T>
2146T Simulator::ReadMem(int64_t addr, Instruction*
instr) {
2147 int alignment_mask = (1 <<
sizeof(
T)) - 1;
2149 local_monitor_.NotifyLoad();
2150 T* ptr =
reinterpret_cast<T*
>(addr);
2151 TraceMemRd(addr, *ptr);
2154 PrintF(
"Unaligned read of type sizeof(%ld) at 0x%08lx, pc=0x%08" V8PRIxPTR
2156 sizeof(T), addr,
reinterpret_cast<intptr_t
>(
instr));
2161template <
typename T>
2162void Simulator::WriteMem(int64_t addr, T value, Instruction*
instr) {
2163 int alignment_mask = (1 <<
sizeof(
T)) - 1;
2165 local_monitor_.NotifyStore();
2166 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
2167 GlobalMonitor::Get()->NotifyStore_Locked(&global_monitor_thread_);
2168 T* ptr =
reinterpret_cast<T*
>(addr);
2170 TraceMemWr(addr, value);
2173 PrintF(
"Unaligned write of type sizeof(%ld) at 0x%08lx, pc=0x%08" V8PRIxPTR
2175 sizeof(T), addr,
reinterpret_cast<intptr_t
>(
instr));
2180uintptr_t Simulator::StackLimit(uintptr_t c_limit)
const {
2183 if (base::Stack::GetCurrentStackPosition() < c_limit) {
2192uintptr_t Simulator::StackBase()
const {
2193 return reinterpret_cast<uintptr_t
>(stack_) + UsableStackSize();
2196base::Vector<uint8_t> Simulator::GetCentralStackView()
const {
2200 return base::VectorOf(
2201 reinterpret_cast<uint8_t*
>(stack_) + kStackProtectionSize,
2210 visitor->
VisitPointer(
reinterpret_cast<const void*
>(get_register(
i)));
2212 for (
const void*
const* current =
2213 reinterpret_cast<const void* const*
>(get_sp());
2215 const void* address = *
current;
2216 if (address ==
nullptr) {
2224void Simulator::Format(Instruction*
instr,
const char* format) {
2225 PrintF(
"Simulator found unsupported instruction:\n 0x%08" PRIxPTR
" : %s\n",
2226 reinterpret_cast<intptr_t
>(
instr), format);
2237 int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4,
2238 int64_t arg5, int64_t arg6, int64_t arg7, int64_t arg8, int64_t arg9,
2239 int64_t arg10, int64_t arg11, int64_t arg12, int64_t arg13, int64_t arg14,
2240 int64_t arg15, int64_t arg16, int64_t arg17, int64_t arg18, int64_t arg19);
2243using SimulatorRuntimeCompareCall = int64_t (*)(
double darg0,
double darg1);
2244using SimulatorRuntimeFPFPCall = double (*)(
double darg0,
double darg1);
2245using SimulatorRuntimeFPCall = double (*)(
double darg0);
2246using SimulatorRuntimeFPIntCall = double (*)(
double darg0,
int32_t arg0);
2247using SimulatorRuntimeIntFPCall =
int32_t (*)(
double darg0);
2250using SimulatorRuntimeFPTaggedCall = double (*)(int64_t arg0, int64_t arg1,
2251 int64_t arg2, int64_t arg3);
2255using SimulatorRuntimeDirectApiCall = void (*)(int64_t arg0);
2258using SimulatorRuntimeDirectGetterCall = void (*)(int64_t arg0, int64_t arg1);
2260using MixedRuntimeCall_0 = AnyCType (*)();
2262#define BRACKETS(ident, N) ident[N]
2264#define REP_0(expr, FMT)
2265#define REP_1(expr, FMT) FMT(expr, 0)
2266#define REP_2(expr, FMT) REP_1(expr, FMT), FMT(expr, 1)
2267#define REP_3(expr, FMT) REP_2(expr, FMT), FMT(expr, 2)
2268#define REP_4(expr, FMT) REP_3(expr, FMT), FMT(expr, 3)
2269#define REP_5(expr, FMT) REP_4(expr, FMT), FMT(expr, 4)
2270#define REP_6(expr, FMT) REP_5(expr, FMT), FMT(expr, 5)
2271#define REP_7(expr, FMT) REP_6(expr, FMT), FMT(expr, 6)
2272#define REP_8(expr, FMT) REP_7(expr, FMT), FMT(expr, 7)
2273#define REP_9(expr, FMT) REP_8(expr, FMT), FMT(expr, 8)
2274#define REP_10(expr, FMT) REP_9(expr, FMT), FMT(expr, 9)
2275#define REP_11(expr, FMT) REP_10(expr, FMT), FMT(expr, 10)
2276#define REP_12(expr, FMT) REP_11(expr, FMT), FMT(expr, 11)
2277#define REP_13(expr, FMT) REP_12(expr, FMT), FMT(expr, 12)
2278#define REP_14(expr, FMT) REP_13(expr, FMT), FMT(expr, 13)
2279#define REP_15(expr, FMT) REP_14(expr, FMT), FMT(expr, 14)
2280#define REP_16(expr, FMT) REP_15(expr, FMT), FMT(expr, 15)
2281#define REP_17(expr, FMT) REP_16(expr, FMT), FMT(expr, 16)
2282#define REP_18(expr, FMT) REP_17(expr, FMT), FMT(expr, 17)
2283#define REP_19(expr, FMT) REP_18(expr, FMT), FMT(expr, 18)
2284#define REP_20(expr, FMT) REP_19(expr, FMT), FMT(expr, 19)
2286#define GEN_MAX_PARAM_COUNT(V) \
2309#define MIXED_RUNTIME_CALL(N) \
2310 using MixedRuntimeCall_##N = AnyCType (*)(REP_##N(AnyCType arg, CONCAT));
2312GEN_MAX_PARAM_COUNT(MIXED_RUNTIME_CALL)
2313#undef MIXED_RUNTIME_CALL
2315#define CALL_ARGS(N) REP_##N(args, BRACKETS)
2316#define CALL_TARGET_VARARG(N) \
2317 if (signature.ParameterCount() == N) { \
2318 MixedRuntimeCall_##N target = \
2319 reinterpret_cast<MixedRuntimeCall_##N>(target_address); \
2320 result = target(CALL_ARGS(N)); \
2323#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
2324#define RETURN_REGISTER v0
2325#define FP_PARAM_REGISTERS f12, f13, f14, f15, f16, f17, f18, f19
2326#define FP_RETURN_REGISTER f0
2328void Simulator::CallAnyCTypeFunction(Address target_address,
2329 const EncodedCSignature& signature) {
2330 const int64_t* stack_pointer =
reinterpret_cast<int64_t*
>(get_register(sp));
2331 const double* double_stack_pointer =
2332 reinterpret_cast<double*
>(get_register(sp));
2334 const Register kParamRegisters[] = {PARAM_REGISTERS};
2335 const FPURegister kFPParamRegisters[] = {FP_PARAM_REGISTERS};
2337 int num_reg_params = 0, num_stack_params = 0;
2339 CHECK_LE(signature.ParameterCount(), kMaxCParameters);
2340 static_assert(
sizeof(AnyCType) == 8,
"AnyCType is assumed to be 64-bit.");
2341 AnyCType
args[kMaxCParameters];
2342 for (
int i = 0;
i < signature.ParameterCount(); ++
i) {
2343 if (num_reg_params < 8) {
2344 if (signature.IsFloat(
i)) {
2345 args[
i].double_value =
2346 get_fpu_register_double(kFPParamRegisters[num_reg_params++]);
2348 args[
i].int64_value = get_register(kParamRegisters[num_reg_params++]);
2351 if (signature.IsFloat(
i)) {
2352 args[
i].double_value = double_stack_pointer[num_stack_params++];
2354 args[
i].int64_value = stack_pointer[num_stack_params++];
2359 GEN_MAX_PARAM_COUNT(CALL_TARGET_VARARG)
2363 static_assert(20 == kMaxCParameters,
2364 "If you've changed kMaxCParameters, please change the "
2365 "GEN_MAX_PARAM_COUNT macro.");
2366 printf(
"CallAnyCTypeFunction end result \n");
2368#undef CALL_TARGET_VARARG
2370#undef GEN_MAX_PARAM_COUNT
2372 if (signature.IsReturnFloat()) {
2373 set_fpu_register_double(FP_RETURN_REGISTER,
result.double_value);
2375 set_register(RETURN_REGISTER,
result.int64_value);
2379#undef PARAM_REGISTERS
2380#undef RETURN_REGISTER
2381#undef FP_PARAM_REGISTERS
2382#undef FP_RETURN_REGISTER
2386void Simulator::SoftwareInterrupt() {
2390 int32_t func = instr_.FunctionFieldRaw();
2391 uint32_t code = (func ==
BREAK) ? instr_.Bits(25, 6) : -1;
2393 if (instr_.InstructionBits() == rtCallRedirInstr) {
2394 Redirection* redirection = Redirection::FromInstruction(instr_.instr());
2397 int64_t saved_ra = get_register(ra);
2400 reinterpret_cast<intptr_t
>(redirection->external_function());
2403 reinterpret_cast<Address>(redirection->external_function());
2404 SimulatorData* simulator_data =
isolate_->simulator_data();
2406 const EncodedCSignature& signature =
2407 simulator_data->GetSignatureForTarget(func_addr);
2408 if (signature.IsValid()) {
2409 CHECK_EQ(redirection->type(), ExternalReference::FAST_C_CALL);
2410 CallAnyCTypeFunction(external, signature);
2411 set_register(ra, saved_ra);
2412 set_pc(get_register(ra));
2416 int64_t* stack_pointer =
reinterpret_cast<int64_t*
>(get_register(sp));
2418 int64_t arg0 = get_register(a0);
2419 int64_t arg1 = get_register(a1);
2420 int64_t arg2 = get_register(a2);
2421 int64_t arg3 = get_register(a3);
2422 int64_t arg4 = get_register(a4);
2423 int64_t arg5 = get_register(a5);
2424 int64_t arg6 = get_register(a6);
2425 int64_t arg7 = get_register(a7);
2426 int64_t arg8 = stack_pointer[0];
2427 int64_t arg9 = stack_pointer[1];
2428 int64_t arg10 = stack_pointer[2];
2429 int64_t arg11 = stack_pointer[3];
2430 int64_t arg12 = stack_pointer[4];
2431 int64_t arg13 = stack_pointer[5];
2432 int64_t arg14 = stack_pointer[6];
2433 int64_t arg15 = stack_pointer[7];
2434 int64_t arg16 = stack_pointer[8];
2435 int64_t arg17 = stack_pointer[9];
2436 int64_t arg18 = stack_pointer[10];
2437 int64_t arg19 = stack_pointer[11];
2438 static_assert(kMaxCParameters == 20);
2441 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
2442 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
2443 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
2444 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL) ||
2445 (redirection->type() == ExternalReference::BUILTIN_INT_FP_CALL);
2452 switch (redirection->type()) {
2453 case ExternalReference::BUILTIN_FP_FP_CALL:
2454 case ExternalReference::BUILTIN_COMPARE_CALL:
2455 arg0 = get_fpu_register(f12);
2456 arg1 = get_fpu_register(f13);
2457 arg2 = get_fpu_register(f14);
2458 arg3 = get_fpu_register(f15);
2460 case ExternalReference::BUILTIN_FP_CALL:
2461 arg0 = get_fpu_register(f12);
2462 arg1 = get_fpu_register(f13);
2464 case ExternalReference::BUILTIN_FP_INT_CALL:
2465 arg0 = get_fpu_register(f12);
2466 arg1 = get_fpu_register(f13);
2467 arg2 = get_register(a2);
2479 double dval0, dval1;
2481 int64_t iresult = 0;
2483 GetFpArgs(&dval0, &dval1, &ival);
2484 SimulatorRuntimeCall generic_target =
2485 reinterpret_cast<SimulatorRuntimeCall
>(external);
2487 switch (redirection->type()) {
2488 case ExternalReference::BUILTIN_FP_FP_CALL:
2489 case ExternalReference::BUILTIN_COMPARE_CALL:
2490 PrintF(
"Call to host function at %p with args %f, %f",
2494 case ExternalReference::BUILTIN_FP_CALL:
2495 PrintF(
"Call to host function at %p with arg %f",
2499 case ExternalReference::BUILTIN_FP_INT_CALL:
2500 PrintF(
"Call to host function at %p with args %f, %d",
2504 case ExternalReference::BUILTIN_INT_FP_CALL:
2505 PrintF(
"Call to host function at %p with args %f",
2513 switch (redirection->type()) {
2514 case ExternalReference::BUILTIN_COMPARE_CALL: {
2515 SimulatorRuntimeCompareCall target =
2516 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
2517 iresult =
target(dval0, dval1);
2518 set_register(v0,
static_cast<int64_t
>(iresult));
2522 case ExternalReference::BUILTIN_FP_FP_CALL: {
2523 SimulatorRuntimeFPFPCall target =
2524 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
2525 dresult =
target(dval0, dval1);
2526 SetFpResult(dresult);
2529 case ExternalReference::BUILTIN_FP_CALL: {
2530 SimulatorRuntimeFPCall target =
2531 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
2533 SetFpResult(dresult);
2536 case ExternalReference::BUILTIN_FP_INT_CALL: {
2537 SimulatorRuntimeFPIntCall target =
2538 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
2539 dresult =
target(dval0, ival);
2540 SetFpResult(dresult);
2543 case ExternalReference::BUILTIN_INT_FP_CALL: {
2544 SimulatorRuntimeIntFPCall target =
2545 reinterpret_cast<SimulatorRuntimeIntFPCall
>(external);
2547 set_register(v0, iresult);
2554 switch (redirection->type()) {
2555 case ExternalReference::BUILTIN_COMPARE_CALL:
2556 case ExternalReference::BUILTIN_INT_FP_CALL:
2559 case ExternalReference::BUILTIN_FP_FP_CALL:
2560 case ExternalReference::BUILTIN_FP_CALL:
2561 case ExternalReference::BUILTIN_FP_INT_CALL:
2562 PrintF(
"Returned %f\n", dresult);
2568 }
else if (redirection->type() ==
2569 ExternalReference::BUILTIN_FP_POINTER_CALL) {
2571 PrintF(
"Call to host function at %p args %08" PRIx64
" \n",
2572 reinterpret_cast<void*
>(external), arg0);
2574 SimulatorRuntimeFPTaggedCall target =
2575 reinterpret_cast<SimulatorRuntimeFPTaggedCall
>(external);
2576 double dresult =
target(arg0, arg1, arg2, arg3);
2577 SetFpResult(dresult);
2579 PrintF(
"Returned %f\n", dresult);
2581 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
2583 PrintF(
"Call to host function at %p args %08" PRIx64
" \n",
2584 reinterpret_cast<void*
>(external), arg0);
2586 SimulatorRuntimeDirectApiCall target =
2587 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
2589 }
else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
2591 PrintF(
"Call to host function at %p args %08" PRIx64
" %08" PRIx64
2593 reinterpret_cast<void*
>(external), arg0, arg1);
2595 SimulatorRuntimeDirectGetterCall target =
2596 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
2599 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
2600 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
2601 SimulatorRuntimeCall target =
2602 reinterpret_cast<SimulatorRuntimeCall
>(external);
2605 "Call to host function at %p "
2606 "args %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2607 " , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2608 " , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2609 " , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2610 " , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2612 reinterpret_cast<void*
>(
FUNCTION_ADDR(target)), arg0, arg1, arg2,
2613 arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
2614 arg13, arg14, arg15, arg16, arg17, arg18, arg19);
2617 arg8, arg9, arg10, arg11, arg12, arg13, arg14,
2618 arg15, arg16, arg17, arg18, arg19);
2619 set_register(v0, (int64_t)(
result.x));
2620 set_register(v1, (int64_t)(
result.y));
2623 PrintF(
"Returned %08" PRIx64
" : %08" PRIx64
" \n", get_register(v1),
2626 set_register(ra, saved_ra);
2627 set_pc(get_register(ra));
2629 }
else if (func ==
BREAK && code <= kMaxStopCode) {
2630 if (IsWatchpoint(code)) {
2631 PrintWatchpoint(code);
2633 IncreaseStopCounter(code);
2634 HandleStop(code, instr_.instr());
2638 MipsDebugger dbg(
this);
2644bool Simulator::IsWatchpoint(uint64_t code) {
2645 return (code <= kMaxWatchpointCode);
2648void Simulator::PrintWatchpoint(uint64_t code) {
2649 MipsDebugger dbg(
this);
2651 PrintF(
"\n---- break %" PRId64
" marker: %3d (instr count: %8" PRId64
2653 "----------------------------------",
2654 code, break_count_, icount_);
2658void Simulator::HandleStop(uint64_t code, Instruction*
instr) {
2661 if (IsEnabledStop(code)) {
2662 MipsDebugger dbg(
this);
2667bool Simulator::IsStopInstruction(Instruction*
instr) {
2669 uint32_t code =
static_cast<uint32_t
>(
instr->Bits(25, 6));
2673bool Simulator::IsEnabledStop(uint64_t code) {
2676 return !(watched_stops_[
code].count & kStopDisabledBit);
2679void Simulator::EnableStop(uint64_t code) {
2680 if (!IsEnabledStop(code)) {
2681 watched_stops_[
code].count &= ~kStopDisabledBit;
2685void Simulator::DisableStop(uint64_t code) {
2686 if (IsEnabledStop(code)) {
2687 watched_stops_[
code].count |= kStopDisabledBit;
2691void Simulator::IncreaseStopCounter(uint64_t code) {
2693 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
2694 PrintF(
"Stop counter for code %" PRId64
2695 " has overflowed.\n"
2696 "Enabling this code and reseting the counter to 0.\n",
2698 watched_stops_[
code].count = 0;
2701 watched_stops_[
code].count++;
2706void Simulator::PrintStopInfo(uint64_t code) {
2707 if (code <= kMaxWatchpointCode) {
2708 PrintF(
"That is a watchpoint, not a stop.\n");
2710 }
else if (code > kMaxStopCode) {
2711 PrintF(
"Code too large, only %u stops can be used\n", kMaxStopCode + 1);
2714 const char* state = IsEnabledStop(code) ?
"Enabled" :
"Disabled";
2715 int32_t count = watched_stops_[
code].count & ~kStopDisabledBit;
2718 if (watched_stops_[code].desc) {
2719 PrintF(
"stop %" PRId64
" - 0x%" PRIx64
" : \t%s, \tcounter = %i, \t%s\n",
2720 code, code, state, count, watched_stops_[code].desc);
2722 PrintF(
"stop %" PRId64
" - 0x%" PRIx64
" : \t%s, \tcounter = %i\n", code,
2723 code, state, count);
2728void Simulator::SignalException(Exception e) {
2729 FATAL(
"Error: Exception %i raised.",
static_cast<int>(e));
2734template <
typename T>
2738double FPAbs<double>(
double a) {
2743float FPAbs<float>(
float a) {
2747template <
typename T>
2748static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind
kind, T*
result) {
2749 if (std::isnan(a) && std::isnan(b)) {
2751 }
else if (std::isnan(a)) {
2753 }
else if (std::isnan(b)) {
2755 }
else if (b == a) {
2759 *
result = std::signbit(b) -
static_cast<int>(
kind) ? b : a;
2766template <
typename T>
2767static T FPUMin(T a, T b) {
2769 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, &
result)) {
2772 return b < a ? b :
a;
2776template <
typename T>
2777static T FPUMax(T a, T b) {
2779 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, &
result)) {
2782 return b > a ? b :
a;
2786template <
typename T>
2787static T FPUMinA(T a, T b) {
2789 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, &
result)) {
2790 if (FPAbs(a) < FPAbs(b)) {
2792 }
else if (FPAbs(b) < FPAbs(a)) {
2801template <
typename T>
2802static T FPUMaxA(T a, T b) {
2804 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, &
result)) {
2805 if (FPAbs(a) > FPAbs(b)) {
2807 }
else if (FPAbs(b) > FPAbs(a)) {
2816enum class KeepSign :
bool { no =
false, yes };
2818template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
2820T FPUCanonalizeNaNArg(T
result, T arg, KeepSign keepSign = KeepSign::no) {
2822 T qNaN = std::numeric_limits<T>::quiet_NaN();
2823 if (keepSign == KeepSign::yes) {
2824 return std::copysign(qNaN,
result);
2829template <
typename T>
2830T FPUCanonalizeNaNArgs(T
result, KeepSign keepSign, T first) {
2831 if (std::isnan(first)) {
2832 return FPUCanonalizeNaNArg(
result, first, keepSign);
2837template <
typename T,
typename... Args>
2838T FPUCanonalizeNaNArgs(T
result, KeepSign keepSign, T first, Args...
args) {
2839 if (std::isnan(first)) {
2840 return FPUCanonalizeNaNArg(
result, first, keepSign);
2842 return FPUCanonalizeNaNArgs(
result, keepSign,
args...);
2845template <
typename Func,
typename T,
typename... Args>
2846T FPUCanonalizeOperation(Func f, T first, Args...
args) {
2847 return FPUCanonalizeOperation(f, KeepSign::no, first,
args...);
2850template <
typename Func,
typename T,
typename... Args>
2851T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args...
args) {
2853 if (std::isnan(
result)) {
2861void Simulator::DecodeTypeRegisterSRsType() {
2863 fs = get_fpu_register_float(fs_reg());
2864 ft = get_fpu_register_float(ft_reg());
2865 fd = get_fpu_register_float(fd_reg());
2866 int32_t ft_int = base::bit_cast<int32_t>(ft);
2867 int32_t fd_int = base::bit_cast<int32_t>(fd);
2868 uint32_t
cc, fcsr_cc;
2869 cc = instr_.FCccValue();
2870 fcsr_cc = get_fcsr_condition_bit(cc);
2871 switch (instr_.FunctionFieldRaw()) {
2874 float result, temp_result;
2876 float upper = std::ceil(fs);
2877 float lower = std::floor(fs);
2878 switch (get_fcsr_rounding_mode()) {
2880 if (upper - fs < fs - lower) {
2882 }
else if (upper - fs > fs - lower) {
2885 temp_result = upper / 2;
2886 float reminder = modf(temp_result, &temp);
2887 if (reminder == 0) {
2895 result = (fs > 0 ? lower : upper);
2904 SetFPUFloatResult(fd_reg(),
result);
2906 set_fcsr_bit(kFCSRInexactFlagBit,
true);
2913 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs + rhs; },
2919 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs - rhs; },
2924 SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd));
2928 SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd));
2933 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs * rhs; },
2939 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs / rhs; },
2943 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
2944 [](
float fs) {
return FPAbs(fs); }, fs));
2947 SetFPUFloatResult(fd_reg(), fs);
2950 SetFPUFloatResult(fd_reg(),
2951 FPUCanonalizeOperation([](
float src) {
return -src; },
2952 KeepSign::yes, fs));
2957 FPUCanonalizeOperation([](
float src) {
return std::sqrt(src); }, fs));
2961 fd_reg(), FPUCanonalizeOperation(
2962 [](
float src) {
return 1.0 / std::sqrt(src); }, fs));
2965 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
2966 [](
float src) {
return 1.0 / src; }, fs));
2969 set_fcsr_bit(fcsr_cc,
false);
2970 TraceRegWr(test_fcsr_bit(fcsr_cc));
2973 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2974 TraceRegWr(test_fcsr_bit(fcsr_cc));
2977 set_fcsr_bit(fcsr_cc, (fs == ft));
2978 TraceRegWr(test_fcsr_bit(fcsr_cc));
2981 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2982 TraceRegWr(test_fcsr_bit(fcsr_cc));
2985 set_fcsr_bit(fcsr_cc, (fs < ft));
2986 TraceRegWr(test_fcsr_bit(fcsr_cc));
2989 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2990 TraceRegWr(test_fcsr_bit(fcsr_cc));
2993 set_fcsr_bit(fcsr_cc, (fs <= ft));
2994 TraceRegWr(test_fcsr_bit(fcsr_cc));
2997 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2998 TraceRegWr(test_fcsr_bit(fcsr_cc));
3001 SetFPUDoubleResult(fd_reg(),
static_cast<double>(fs));
3005 uint32_t classed = base::bit_cast<uint32_t>(fs);
3008 uint32_t
sign = (classed >> 31) & 1;
3009 uint32_t exponent = (classed >> 23) & 0x000000FF;
3010 uint32_t mantissa = classed & 0x007FFFFF;
3016 bool negInf = (classed == 0xFF800000);
3017 bool posInf = (classed == 0x7F800000);
3018 bool negZero = (classed == 0x80000000);
3019 bool posZero = (classed == 0x00000000);
3029 signalingNan =
false;
3031 if (!negInf && !posInf && (exponent == 0xFF)) {
3032 quietNan = ((mantissa & 0x00200000) == 0) &&
3033 ((mantissa & (0x00200000 - 1)) == 0);
3034 signalingNan = !quietNan;
3040 if ((exponent == 0) && (mantissa != 0)) {
3041 DCHECK(sign == 0 || sign == 1);
3042 posSubnorm = (
sign == 0);
3043 negSubnorm = (
sign == 1);
3049 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3050 !quietNan && !negZero && !posZero) {
3051 DCHECK(sign == 0 || sign == 1);
3052 posNorm = (
sign == 0);
3053 negNorm = (
sign == 1);
3057 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3058 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3059 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3063 fResult = base::bit_cast<float>(
result);
3064 SetFPUFloatResult(fd_reg(), fResult);
3070 round64_according_to_fcsr(fs, &rounded, &
result, fs);
3071 SetFPUResult(fd_reg(),
result);
3072 if (set_fcsr_round64_error(fs, rounded)) {
3073 set_fpu_register_invalid_result64(fs, rounded);
3080 round_according_to_fcsr(fs, &rounded, &
result, fs);
3081 SetFPUWordResult(fd_reg(),
result);
3082 if (set_fcsr_round_error(fs, rounded)) {
3083 set_fpu_register_word_invalid_result(fs, rounded);
3088 float rounded = trunc(fs);
3090 SetFPUWordResult(fd_reg(),
result);
3091 if (set_fcsr_round_error(fs, rounded)) {
3092 set_fpu_register_word_invalid_result(fs, rounded);
3096 float rounded = trunc(fs);
3097 int64_t
result =
static_cast<int64_t
>(rounded);
3098 SetFPUResult(fd_reg(),
result);
3099 if (set_fcsr_round64_error(fs, rounded)) {
3100 set_fpu_register_invalid_result64(fs, rounded);
3105 float rounded = std::floor(fs + 0.5);
3112 SetFPUWordResult(fd_reg(),
result);
3113 if (set_fcsr_round_error(fs, rounded)) {
3114 set_fpu_register_word_invalid_result(fs, rounded);
3119 float rounded = std::floor(fs + 0.5);
3120 int64_t
result =
static_cast<int64_t
>(rounded);
3126 int64_t i64 =
static_cast<int64_t
>(
result);
3127 SetFPUResult(fd_reg(), i64);
3128 if (set_fcsr_round64_error(fs, rounded)) {
3129 set_fpu_register_invalid_result64(fs, rounded);
3134 float rounded = floor(fs);
3135 int64_t
result =
static_cast<int64_t
>(rounded);
3136 SetFPUResult(fd_reg(),
result);
3137 if (set_fcsr_round64_error(fs, rounded)) {
3138 set_fpu_register_invalid_result64(fs, rounded);
3144 float rounded = std::floor(fs);
3146 SetFPUWordResult(fd_reg(),
result);
3147 if (set_fcsr_round_error(fs, rounded)) {
3148 set_fpu_register_word_invalid_result(fs, rounded);
3153 float rounded = std::ceil(fs);
3155 SetFPUWordResult(fd_reg(),
result);
3156 if (set_fcsr_round_error(fs, rounded)) {
3157 set_fpu_register_invalid_result(fs, rounded);
3161 float rounded = ceil(fs);
3162 int64_t
result =
static_cast<int64_t
>(rounded);
3163 SetFPUResult(fd_reg(),
result);
3164 if (set_fcsr_round64_error(fs, rounded)) {
3165 set_fpu_register_invalid_result64(fs, rounded);
3171 SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs));
3175 SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs));
3179 SetFPUFloatResult(fd_reg(), FPUMin(ft, fs));
3183 SetFPUFloatResult(fd_reg(), FPUMax(ft, fs));
3187 SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
3191 SetFPUFloatResult(fd_reg(), (ft_int & 0x1) == 0
3192 ? get_fpu_register_float(fs_reg())
3197 SetFPUFloatResult(fd_reg(), (ft_int & 0x1) != 0
3198 ? get_fpu_register_float(fs_reg())
3204 SetFPUFloatResult(fd_reg(), fs);
3211 SetFPUFloatResult(fd_reg(), fs);
3217 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
3218 ft_cc = get_fcsr_condition_bit(ft_cc);
3220 if (instr_.Bit(16)) {
3222 if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
3225 if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
3236void Simulator::DecodeTypeRegisterDRsType() {
3238 uint32_t
cc, fcsr_cc;
3239 fs = get_fpu_register_double(fs_reg());
3240 ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg())
3242 fd = get_fpu_register_double(fd_reg());
3243 cc = instr_.FCccValue();
3244 fcsr_cc = get_fcsr_condition_bit(cc);
3245 int64_t ft_int = base::bit_cast<int64_t>(ft);
3246 int64_t fd_int = base::bit_cast<int64_t>(fd);
3247 switch (instr_.FunctionFieldRaw()) {
3250 double result, temp, temp_result;
3251 double upper = std::ceil(fs);
3252 double lower = std::floor(fs);
3253 switch (get_fcsr_rounding_mode()) {
3255 if (upper - fs < fs - lower) {
3257 }
else if (upper - fs > fs - lower) {
3260 temp_result = upper / 2;
3261 double reminder = modf(temp_result, &temp);
3262 if (reminder == 0) {
3270 result = (fs > 0 ? lower : upper);
3279 SetFPUDoubleResult(fd_reg(),
result);
3281 set_fcsr_bit(kFCSRInexactFlagBit,
true);
3287 SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
3291 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
3295 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
3300 SetFPUDoubleResult(fd_reg(), fs);
3307 SetFPUDoubleResult(fd_reg(), fs);
3313 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
3314 ft_cc = get_fcsr_condition_bit(ft_cc);
3315 if (instr_.Bit(16)) {
3317 if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
3320 if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
3326 SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs));
3330 SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs));
3334 SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs));
3338 SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs));
3343 FPUCanonalizeOperation(
3344 [](
double lhs,
double rhs) {
return lhs + rhs; }, fs, ft));
3349 FPUCanonalizeOperation(
3350 [](
double lhs,
double rhs) {
return lhs - rhs; }, fs, ft));
3354 SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd));
3358 SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd));
3363 FPUCanonalizeOperation(
3364 [](
double lhs,
double rhs) {
return lhs * rhs; }, fs, ft));
3369 FPUCanonalizeOperation(
3370 [](
double lhs,
double rhs) {
return lhs / rhs; }, fs, ft));
3375 FPUCanonalizeOperation([](
double fs) {
return FPAbs(fs); }, fs));
3378 SetFPUDoubleResult(fd_reg(), fs);
3381 SetFPUDoubleResult(fd_reg(),
3382 FPUCanonalizeOperation([](
double src) {
return -src; },
3383 KeepSign::yes, fs));
3388 FPUCanonalizeOperation([](
double fs) {
return std::sqrt(fs); }, fs));
3392 fd_reg(), FPUCanonalizeOperation(
3393 [](
double fs) {
return 1.0 / std::sqrt(fs); }, fs));
3396 SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation(
3397 [](
double fs) {
return 1.0 / fs; }, fs));
3400 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
3401 TraceRegWr(test_fcsr_bit(fcsr_cc));
3404 set_fcsr_bit(fcsr_cc, (fs == ft));
3405 TraceRegWr(test_fcsr_bit(fcsr_cc));
3408 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
3409 TraceRegWr(test_fcsr_bit(fcsr_cc));
3412 set_fcsr_bit(fcsr_cc, (fs < ft));
3413 TraceRegWr(test_fcsr_bit(fcsr_cc));
3416 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
3417 TraceRegWr(test_fcsr_bit(fcsr_cc));
3420 set_fcsr_bit(fcsr_cc, (fs <= ft));
3421 TraceRegWr(test_fcsr_bit(fcsr_cc));
3424 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
3425 TraceRegWr(test_fcsr_bit(fcsr_cc));
3430 round_according_to_fcsr(fs, &rounded, &
result, fs);
3431 SetFPUWordResult(fd_reg(),
result);
3432 if (set_fcsr_round_error(fs, rounded)) {
3433 set_fpu_register_word_invalid_result(fs, rounded);
3439 double rounded = std::floor(fs + 0.5);
3446 SetFPUWordResult(fd_reg(),
result);
3447 if (set_fcsr_round_error(fs, rounded)) {
3448 set_fpu_register_invalid_result(fs, rounded);
3453 double rounded = trunc(fs);
3455 SetFPUWordResult(fd_reg(),
result);
3456 if (set_fcsr_round_error(fs, rounded)) {
3457 set_fpu_register_invalid_result(fs, rounded);
3462 double rounded = std::floor(fs);
3464 SetFPUWordResult(fd_reg(),
result);
3465 if (set_fcsr_round_error(fs, rounded)) {
3466 set_fpu_register_invalid_result(fs, rounded);
3471 double rounded = std::ceil(fs);
3473 SetFPUWordResult2(fd_reg(),
result);
3474 if (set_fcsr_round_error(fs, rounded)) {
3475 set_fpu_register_invalid_result(fs, rounded);
3479 SetFPUFloatResult(fd_reg(),
static_cast<float>(fs));
3484 round64_according_to_fcsr(fs, &rounded, &
result, fs);
3485 SetFPUResult(fd_reg(),
result);
3486 if (set_fcsr_round64_error(fs, rounded)) {
3487 set_fpu_register_invalid_result64(fs, rounded);
3492 double rounded = std::floor(fs + 0.5);
3493 int64_t
result =
static_cast<int64_t
>(rounded);
3499 int64_t i64 =
static_cast<int64_t
>(
result);
3500 SetFPUResult(fd_reg(), i64);
3501 if (set_fcsr_round64_error(fs, rounded)) {
3502 set_fpu_register_invalid_result64(fs, rounded);
3507 double rounded = trunc(fs);
3508 int64_t
result =
static_cast<int64_t
>(rounded);
3509 SetFPUResult(fd_reg(),
result);
3510 if (set_fcsr_round64_error(fs, rounded)) {
3511 set_fpu_register_invalid_result64(fs, rounded);
3516 double rounded = floor(fs);
3517 int64_t
result =
static_cast<int64_t
>(rounded);
3518 SetFPUResult(fd_reg(),
result);
3519 if (set_fcsr_round64_error(fs, rounded)) {
3520 set_fpu_register_invalid_result64(fs, rounded);
3525 double rounded = ceil(fs);
3526 int64_t
result =
static_cast<int64_t
>(rounded);
3527 SetFPUResult(fd_reg(),
result);
3528 if (set_fcsr_round64_error(fs, rounded)) {
3529 set_fpu_register_invalid_result64(fs, rounded);
3535 uint64_t classed = base::bit_cast<uint64_t>(fs);
3538 uint32_t
sign = (classed >> 63) & 1;
3539 uint32_t exponent = (classed >> 52) & 0x00000000000007FF;
3540 uint64_t mantissa = classed & 0x000FFFFFFFFFFFFF;
3546 bool negInf = (classed == 0xFFF0000000000000);
3547 bool posInf = (classed == 0x7FF0000000000000);
3548 bool negZero = (classed == 0x8000000000000000);
3549 bool posZero = (classed == 0x0000000000000000);
3559 signalingNan =
false;
3561 if (!negInf && !posInf && exponent == 0x7FF) {
3562 quietNan = ((mantissa & 0x0008000000000000) != 0) &&
3563 ((mantissa & (0x0008000000000000 - 1)) == 0);
3564 signalingNan = !quietNan;
3570 if ((exponent == 0) && (mantissa != 0)) {
3571 DCHECK(sign == 0 || sign == 1);
3572 posSubnorm = (
sign == 0);
3573 negSubnorm = (
sign == 1);
3579 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3580 !quietNan && !negZero && !posZero) {
3581 DCHECK(sign == 0 || sign == 1);
3582 posNorm = (
sign == 0);
3583 negNorm = (
sign == 1);
3587 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3588 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3589 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3593 dResult = base::bit_cast<double>(
result);
3594 SetFPUDoubleResult(fd_reg(), dResult);
3598 set_fcsr_bit(fcsr_cc,
false);
3599 TraceRegWr(test_fcsr_bit(fcsr_cc));
3607void Simulator::DecodeTypeRegisterWRsType() {
3608 float fs = get_fpu_register_float(fs_reg());
3609 float ft = get_fpu_register_float(ft_reg());
3610 int64_t alu_out = 0x12345678;
3611 switch (instr_.FunctionFieldRaw()) {
3613 alu_out = get_fpu_register_signed_word(fs_reg());
3614 SetFPUFloatResult(fd_reg(),
static_cast<float>(alu_out));
3617 alu_out = get_fpu_register_signed_word(fs_reg());
3618 SetFPUDoubleResult(fd_reg(),
static_cast<double>(alu_out));
3621 SetFPUWordResult2(fd_reg(), 0);
3624 if (std::isnan(fs) || std::isnan(ft)) {
3625 SetFPUWordResult2(fd_reg(), -1);
3627 SetFPUWordResult2(fd_reg(), 0);
3632 SetFPUWordResult2(fd_reg(), -1);
3634 SetFPUWordResult2(fd_reg(), 0);
3638 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3639 SetFPUWordResult2(fd_reg(), -1);
3641 SetFPUWordResult2(fd_reg(), 0);
3646 SetFPUWordResult2(fd_reg(), -1);
3648 SetFPUWordResult2(fd_reg(), 0);
3652 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3653 SetFPUWordResult2(fd_reg(), -1);
3655 SetFPUWordResult2(fd_reg(), 0);
3660 SetFPUWordResult2(fd_reg(), -1);
3662 SetFPUWordResult2(fd_reg(), 0);
3666 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3667 SetFPUWordResult2(fd_reg(), -1);
3669 SetFPUWordResult2(fd_reg(), 0);
3673 if (!std::isnan(fs) && !std::isnan(ft)) {
3674 SetFPUWordResult2(fd_reg(), -1);
3676 SetFPUWordResult2(fd_reg(), 0);
3680 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3681 SetFPUWordResult2(fd_reg(), -1);
3683 SetFPUWordResult2(fd_reg(), 0);
3688 SetFPUWordResult2(fd_reg(), -1);
3690 SetFPUWordResult2(fd_reg(), 0);
3698void Simulator::DecodeTypeRegisterLRsType() {
3699 double fs = get_fpu_register_double(fs_reg());
3700 double ft = get_fpu_register_double(ft_reg());
3702 switch (instr_.FunctionFieldRaw()) {
3704 i64 = get_fpu_register(fs_reg());
3705 SetFPUDoubleResult(fd_reg(),
static_cast<double>(i64));
3708 i64 = get_fpu_register(fs_reg());
3709 SetFPUFloatResult(fd_reg(),
static_cast<float>(i64));
3712 SetFPUResult(fd_reg(), 0);
3715 if (std::isnan(fs) || std::isnan(ft)) {
3716 SetFPUResult(fd_reg(), -1);
3718 SetFPUResult(fd_reg(), 0);
3723 SetFPUResult(fd_reg(), -1);
3725 SetFPUResult(fd_reg(), 0);
3729 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3730 SetFPUResult(fd_reg(), -1);
3732 SetFPUResult(fd_reg(), 0);
3737 SetFPUResult(fd_reg(), -1);
3739 SetFPUResult(fd_reg(), 0);
3743 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3744 SetFPUResult(fd_reg(), -1);
3746 SetFPUResult(fd_reg(), 0);
3751 SetFPUResult(fd_reg(), -1);
3753 SetFPUResult(fd_reg(), 0);
3757 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3758 SetFPUResult(fd_reg(), -1);
3760 SetFPUResult(fd_reg(), 0);
3764 if (!std::isnan(fs) && !std::isnan(ft)) {
3765 SetFPUResult(fd_reg(), -1);
3767 SetFPUResult(fd_reg(), 0);
3771 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3772 SetFPUResult(fd_reg(), -1);
3774 SetFPUResult(fd_reg(), 0);
3778 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3779 SetFPUResult(fd_reg(), -1);
3781 SetFPUResult(fd_reg(), 0);
3789void Simulator::DecodeTypeRegisterCOP1() {
3790 switch (instr_.RsFieldRaw()) {
3798 SetResult(rt_reg(), FCSR_);
3801 set_register(rt_reg(),
3802 static_cast<int64_t
>(get_fpu_register_word(fs_reg())));
3803 TraceRegWr(get_register(rt_reg()), WORD_DWORD);
3806 SetResult(rt_reg(), get_fpu_register(fs_reg()));
3809 SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg()));
3814 uint32_t
reg =
static_cast<uint32_t
>(rt());
3819 FCSR_ =
reg & ~kFCSRNaN2008FlagMask;
3826 set_fpu_register_hi_word(fs_reg(), 0);
3827 set_fpu_register_word(fs_reg(),
static_cast<int32_t>(rt()));
3828 TraceRegWr(get_fpu_register(fs_reg()), FLOAT_DOUBLE);
3831 SetFPUResult2(fs_reg(), rt());
3834 set_fpu_register_hi_word(fs_reg(),
static_cast<int32_t>(rt()));
3835 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
3838 DecodeTypeRegisterSRsType();
3841 DecodeTypeRegisterDRsType();
3844 DecodeTypeRegisterWRsType();
3847 DecodeTypeRegisterLRsType();
3854void Simulator::DecodeTypeRegisterCOP1X() {
3855 switch (instr_.FunctionFieldRaw()) {
3859 fr = get_fpu_register_float(fr_reg());
3860 fs = get_fpu_register_float(fs_reg());
3861 ft = get_fpu_register_float(ft_reg());
3862 SetFPUFloatResult(fd_reg(), fs * ft + fr);
3868 fr = get_fpu_register_float(fr_reg());
3869 fs = get_fpu_register_float(fs_reg());
3870 ft = get_fpu_register_float(ft_reg());
3871 SetFPUFloatResult(fd_reg(), fs * ft - fr);
3877 fr = get_fpu_register_double(fr_reg());
3878 fs = get_fpu_register_double(fs_reg());
3879 ft = get_fpu_register_double(ft_reg());
3880 SetFPUDoubleResult(fd_reg(), fs * ft + fr);
3886 fr = get_fpu_register_double(fr_reg());
3887 fs = get_fpu_register_double(fs_reg());
3888 ft = get_fpu_register_double(ft_reg());
3889 SetFPUDoubleResult(fd_reg(), fs * ft - fr);
3897void Simulator::DecodeTypeRegisterSPECIAL() {
3901 bool do_interrupt =
false;
3903 switch (instr_.FunctionFieldRaw()) {
3906 SetResult(rd_reg(), rt() == 0 ? rs() : 0);
3910 SetResult(rd_reg(), rt() != 0 ? rs() : 0);
3913 int64_t next_pc = rs();
3914 int64_t current_pc = get_pc();
3915 Instruction* branch_delay_instr =
3916 reinterpret_cast<Instruction*
>(current_pc +
kInstrSize);
3917 BranchDelayInstructionDecode(branch_delay_instr);
3919 pc_modified_ =
true;
3923 int64_t next_pc = rs();
3924 int64_t current_pc = get_pc();
3925 int32_t return_addr_reg = rd_reg();
3926 Instruction* branch_delay_instr =
3927 reinterpret_cast<Instruction*
>(current_pc +
kInstrSize);
3928 BranchDelayInstructionDecode(branch_delay_instr);
3929 set_register(return_addr_reg, current_pc + 2 * kInstrSize);
3931 pc_modified_ =
true;
3935 SetResult(rd_reg(),
static_cast<int32_t>(rt()) << sa());
3938 SetResult(rd_reg(), rt() << sa());
3941 SetResult(rd_reg(), rt() << sa() << 32);
3944 if (rs_reg() == 0) {
3948 alu_out =
static_cast<int32_t>(
static_cast<uint32_t
>(rt_u()) >> sa());
3949 }
else if (rs_reg() == 1) {
3953 alu_out =
static_cast<int32_t>(
3954 base::bits::RotateRight32(
static_cast<const uint32_t
>(rt_u()),
3955 static_cast<const uint32_t
>(sa())));
3959 SetResult(rd_reg(), alu_out);
3962 if (rs_reg() == 0) {
3966 alu_out =
static_cast<int64_t
>(rt_u() >> sa());
3967 }
else if (rs_reg() == 1) {
3971 alu_out =
static_cast<int64_t
>(base::bits::RotateRight64(rt_u(), sa()));
3975 SetResult(rd_reg(), alu_out);
3978 if (rs_reg() == 0) {
3982 alu_out =
static_cast<int64_t
>(rt_u() >> sa() >> 32);
3983 }
else if (rs_reg() == 1) {
3988 static_cast<int64_t
>(base::bits::RotateRight64(rt_u(), sa() + 32));
3992 SetResult(rd_reg(), alu_out);
3995 SetResult(rd_reg(), (int32_t)rt() >> sa());
3998 SetResult(rd_reg(), rt() >> sa());
4001 SetResult(rd_reg(), rt() >> sa() >> 32);
4004 SetResult(rd_reg(), (int32_t)rt() << rs());
4007 SetResult(rd_reg(), rt() << rs());
4013 alu_out =
static_cast<int32_t>((uint32_t)rt_u() >> rs());
4018 alu_out =
static_cast<int32_t>(
4019 base::bits::RotateRight32(
static_cast<const uint32_t
>(rt_u()),
4020 static_cast<const uint32_t
>(rs_u())));
4022 SetResult(rd_reg(), alu_out);
4028 alu_out =
static_cast<int64_t
>(rt_u() >> rs());
4034 static_cast<int64_t
>(base::bits::RotateRight64(rt_u(), rs_u()));
4036 SetResult(rd_reg(), alu_out);
4039 SetResult(rd_reg(), (int32_t)rt() >> rs());
4042 SetResult(rd_reg(), rt() >> rs());
4046 int8_t sa = lsa_sa() + 1;
4051 SetResult(rd_reg(),
static_cast<int64_t
>(res));
4056 SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt());
4061 alu_out = get_register(HI);
4066 alu_out = base::bits::CountLeadingZeros32(
static_cast<int32_t>(rs_u()));
4068 SetResult(rd_reg(), alu_out);
4073 alu_out = get_register(LO);
4078 alu_out = base::bits::CountLeadingZeros64(
static_cast<int64_t
>(rs_u()));
4080 SetResult(rd_reg(), alu_out);
4086 i64hilo =
static_cast<int64_t
>(rs_lo) *
static_cast<int64_t
>(rt_lo);
4088 set_register(LO,
static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
4089 set_register(HI,
static_cast<int32_t>(i64hilo >> 32));
4093 SetResult(rd_reg(),
static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
4096 SetResult(rd_reg(),
static_cast<int32_t>(i64hilo >> 32));
4106 u64hilo =
static_cast<uint64_t
>(rs_u() & 0xFFFFFFFF) *
4107 static_cast<uint64_t
>(rt_u() & 0xFFFFFFFF);
4109 set_register(LO,
static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
4110 set_register(HI,
static_cast<int32_t>(u64hilo >> 32));
4114 SetResult(rd_reg(),
static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
4117 SetResult(rd_reg(),
static_cast<int32_t>(u64hilo >> 32));
4127 set_register(LO, rs() * rt());
4128 set_register(HI, base::bits::SignedMulHigh64(rs(), rt()));
4132 SetResult(rd_reg(), rs() * rt());
4135 SetResult(rd_reg(), base::bits::SignedMulHigh64(rs(), rt()));
4145 set_register(LO, rs_u() * rt_u());
4146 set_register(HI, base::bits::UnsignedMulHigh64(rs_u(), rt_u()));
4153 const int64_t int_min_value =
4154 instr_.FunctionFieldRaw() ==
DIV ? INT_MIN : LONG_MIN;
4161 if (rs() == int_min_value && rt() == -1) {
4162 set_register(LO, int_min_value);
4163 set_register(HI, 0);
4164 }
else if (rt() != 0) {
4165 set_register(LO, rs() / rt());
4166 set_register(HI, rs() % rt());
4172 if (rs() == int_min_value && rt() == -1) {
4173 SetResult(rd_reg(), int_min_value);
4174 }
else if (rt() != 0) {
4175 SetResult(rd_reg(), rs() / rt());
4179 if (rs() == int_min_value && rt() == -1) {
4180 SetResult(rd_reg(), 0);
4181 }
else if (rt() != 0) {
4182 SetResult(rd_reg(), rs() % rt());
4198 uint32_t rt_u_32 =
static_cast<uint32_t
>(rt_u());
4199 uint32_t rs_u_32 =
static_cast<uint32_t
>(rs_u());
4203 SetResult(rd_reg(),
static_cast<int32_t>(rs_u_32 / rt_u_32));
4208 SetResult(rd_reg(),
static_cast<int32_t>(rs_u_32 % rt_u_32));
4218 uint32_t rt_u_32 =
static_cast<uint32_t
>(rt_u());
4219 uint32_t rs_u_32 =
static_cast<uint32_t
>(rs_u());
4220 set_register(LO,
static_cast<int32_t>(rs_u_32 / rt_u_32));
4221 set_register(HI,
static_cast<int32_t>(rs_u_32 % rt_u_32));
4229 switch (instr_.SaValue()) {
4232 SetResult(rd_reg(), rs_u() / rt_u());
4237 SetResult(rd_reg(), rs_u() % rt_u());
4247 set_register(LO, rs_u() / rt_u());
4248 set_register(HI, rs_u() % rt_u());
4255 if (HaveSameSign(rs(), rt())) {
4257 if (rs() > (Registers::kMaxValue - rt())) {
4258 SignalException(kIntegerOverflow);
4260 }
else if (rs() < 0) {
4261 if (rs() < (Registers::kMinValue - rt())) {
4262 SignalException(kIntegerUnderflow);
4266 SetResult(rd_reg(), rs() + rt());
4271 SetResult(rd_reg(),
static_cast<int64_t
>(alu32_out));
4275 SetResult(rd_reg(), rs() + rt());
4279 if (!HaveSameSign(rs(), rt())) {
4281 if (rs() > (Registers::kMaxValue + rt())) {
4282 SignalException(kIntegerOverflow);
4284 }
else if (rs() < 0) {
4285 if (rs() < (Registers::kMinValue + rt())) {
4286 SignalException(kIntegerUnderflow);
4290 SetResult(rd_reg(), rs() - rt());
4295 SetResult(rd_reg(),
static_cast<int64_t
>(alu32_out));
4299 SetResult(rd_reg(), rs() - rt());
4302 SetResult(rd_reg(), rs() & rt());
4305 SetResult(rd_reg(), rs() | rt());
4308 SetResult(rd_reg(), rs() ^ rt());
4311 SetResult(rd_reg(), ~(rs() | rt()));
4314 SetResult(rd_reg(), rs() < rt() ? 1 : 0);
4317 SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
4321 do_interrupt =
true;
4324 do_interrupt = rs() >= rt();
4327 do_interrupt = rs_u() >= rt_u();
4330 do_interrupt = rs() < rt();
4333 do_interrupt = rs_u() < rt_u();
4336 do_interrupt = rs() == rt();
4339 do_interrupt = rs() != rt();
4347 SetResult(rd_reg(), rs());
4351 uint32_t
cc = instr_.FBccValue();
4352 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
4353 if (instr_.Bit(16)) {
4354 if (test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs());
4356 if (!test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs());
4362 SetResult(rd_reg(), rs());
4369 SoftwareInterrupt();
4373void Simulator::DecodeTypeRegisterSPECIAL2() {
4375 switch (instr_.FunctionFieldRaw()) {
4377 alu_out =
static_cast<int32_t>(rs_u()) *
static_cast<int32_t>(rt_u());
4378 SetResult(rd_reg(), alu_out);
4380 set_register(LO, Unpredictable);
4381 set_register(HI, Unpredictable);
4386 alu_out = base::bits::CountLeadingZeros32(
static_cast<uint32_t
>(rs_u()));
4387 SetResult(rd_reg(), alu_out);
4392 alu_out = base::bits::CountLeadingZeros64(
static_cast<uint64_t
>(rs_u()));
4393 SetResult(rd_reg(), alu_out);
4396 alu_out = 0x12345678;
4401void Simulator::DecodeTypeRegisterSPECIAL3() {
4403 switch (instr_.FunctionFieldRaw()) {
4410 uint64_t
mask = (1ULL <<
size) - 1;
4412 SetResult(rt_reg(), alu_out);
4421 uint64_t
mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4423 SetResult(rt_reg(), alu_out);
4431 uint16_t size = msbdminus32 + 1 + 32;
4432 uint64_t
mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4434 SetResult(rt_reg(), alu_out);
4444 uint64_t
mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4446 SetResult(rt_reg(), alu_out);
4455 uint64_t
mask = (1ULL <<
size) - 1;
4456 alu_out =
static_cast<int32_t>((rt_u() & ~(
mask << lsb)) |
4457 ((rs_u() &
mask) << lsb));
4458 SetResult(rt_reg(), alu_out);
4467 uint64_t
mask = (1ULL <<
size) - 1;
4468 alu_out = (rt_u() & ~(
mask << lsb)) | ((rs_u() &
mask) << lsb);
4469 SetResult(rt_reg(), alu_out);
4477 uint16_t size = msbminus32 + 32 - lsb + 1;
4482 mask = std::numeric_limits<uint64_t>::max();
4483 alu_out = (rt_u() & ~(
mask << lsb)) | ((rs_u() &
mask) << lsb);
4484 SetResult(rt_reg(), alu_out);
4493 uint16_t size = msbminus32 + 32 - lsb + 1;
4494 uint64_t
mask = (1ULL <<
size) - 1;
4495 alu_out = (rt_u() & ~(
mask << lsb)) | ((rs_u() &
mask) << lsb);
4496 SetResult(rt_reg(), alu_out);
4503 uint32_t input =
static_cast<uint32_t
>(rt());
4504 uint32_t output = 0;
4505 uint8_t i_byte, o_byte;
4508 for (
int i = 0;
i < 4;
i++) {
4509 output = output >> 8;
4510 i_byte = input & 0xFF;
4514 o_byte =
static_cast<uint8_t
>(((i_byte * 0x0802LU & 0x22110LU) |
4515 (i_byte * 0x8020LU & 0x88440LU)) *
4519 output = output | (
static_cast<uint32_t
>(o_byte << 24));
4523 alu_out =
static_cast<int64_t
>(
static_cast<int32_t>(output));
4527 uint8_t input =
static_cast<uint8_t
>(rt());
4528 uint32_t output = input;
4529 uint32_t
mask = 0x00000080;
4533 output |= 0xFFFFFF00;
4536 alu_out =
static_cast<int32_t>(output);
4541 uint32_t output = input;
4542 uint32_t
mask = 0x00008000;
4546 output |= 0xFFFF0000;
4549 alu_out =
static_cast<int32_t>(output);
4553 uint32_t input =
static_cast<uint32_t
>(rt());
4554 uint64_t output = 0;
4556 uint32_t
mask = 0xFF000000;
4557 for (
int i = 0;
i < 4;
i++) {
4558 uint32_t tmp =
mask & input;
4564 output = output |
tmp;
4570 if (
mask & output) {
4571 output |= 0xFFFFFFFF00000000;
4574 alu_out =
static_cast<int64_t
>(output);
4578 const uint8_t bp2 = instr_.Bp2Value();
4583 alu_out =
static_cast<int32_t>(rt());
4585 uint64_t rt_hi = rt() << (8 * bp2);
4586 uint64_t rs_lo = rs() >> (8 * (4 - bp2));
4587 alu_out =
static_cast<int32_t>(rt_hi | rs_lo);
4592 alu_out = 0x12345678;
4598 SetResult(rd_reg(), alu_out);
4607 uint64_t input =
static_cast<uint64_t
>(rt());
4608 uint64_t output = 0;
4609 uint8_t i_byte, o_byte;
4612 for (
int i = 0;
i < 8;
i++) {
4613 output = output >> 8;
4614 i_byte = input & 0xFF;
4619 static_cast<uint8_t
>(((i_byte * 0x0802LU & 0x22110LU) |
4620 (i_byte * 0x8020LU & 0x88440LU)) *
4624 output = output | ((
static_cast<uint64_t
>(o_byte) << 56));
4628 alu_out =
static_cast<int64_t
>(output);
4635 uint64_t input =
static_cast<uint64_t
>(rt());
4636 uint64_t output = 0;
4638 uint64_t
mask = 0xFF00000000000000;
4639 for (
int i = 0;
i < 8;
i++) {
4640 uint64_t tmp =
mask & input;
4646 output = output |
tmp;
4650 alu_out =
static_cast<int64_t
>(output);
4654 uint64_t input =
static_cast<uint64_t
>(rt());
4655 uint64_t output = 0;
4657 uint64_t
mask = 0xFFFF000000000000;
4658 for (
int i = 0;
i < 4;
i++) {
4659 uint64_t tmp =
mask & input;
4668 output = output |
tmp;
4672 alu_out =
static_cast<int64_t
>(output);
4676 const uint8_t bp3 = instr_.Bp3Value();
4681 alu_out =
static_cast<int64_t
>(rt());
4683 uint64_t rt_hi = rt() << (8 * bp3);
4684 uint64_t rs_lo = rs() >> (8 * (8 - bp3));
4685 alu_out =
static_cast<int64_t
>(rt_hi | rs_lo);
4690 alu_out = 0x12345678;
4696 SetResult(rd_reg(), alu_out);
4704int Simulator::DecodeMsaDataFormat() {
4706 if (instr_.IsMSABranchInstr()) {
4707 switch (instr_.RsFieldRaw()) {
4732 int DF[] = {MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD};
4733 switch (instr_.MSAMinorOpcodeField()) {
4737 df = DF[instr_.Bits(22, 21)];
4740 df = DF[instr_.Bits(1, 0)];
4743 df = DF[instr_.MsaBitDf()];
4746 df = DF[instr_.MsaElmDf()];
4749 uint32_t opcode = instr_.InstructionBits() &
kMsa3RFMask;
4759 df = DF[1 + instr_.Bit(21)];
4762 df = DF[2 + instr_.Bit(21)];
4767 df = DF[instr_.Bits(17, 16)];
4770 df = DF[2 + instr_.Bit(16)];
4779void Simulator::DecodeTypeMsaI8() {
4781 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4782 uint32_t opcode = instr_.InstructionBits() &
kMsaI8Mask;
4783 int8_t i8 = instr_.MsaImm8Value();
4788 get_msa_register(instr_.WsValue(), ws.b);
4790 wd.b[
i] = ws.b[
i] & i8;
4792 set_msa_register(instr_.WdValue(), wd.b);
4793 TraceMSARegWr(wd.b);
4796 get_msa_register(instr_.WsValue(), ws.b);
4798 wd.b[
i] = ws.b[
i] | i8;
4800 set_msa_register(instr_.WdValue(), wd.b);
4801 TraceMSARegWr(wd.b);
4804 get_msa_register(instr_.WsValue(), ws.b);
4806 wd.b[
i] = ~(ws.b[
i] | i8);
4808 set_msa_register(instr_.WdValue(), wd.b);
4809 TraceMSARegWr(wd.b);
4812 get_msa_register(instr_.WsValue(), ws.b);
4814 wd.b[
i] = ws.b[
i] ^ i8;
4816 set_msa_register(instr_.WdValue(), wd.b);
4817 TraceMSARegWr(wd.b);
4820 get_msa_register(instr_.WsValue(), ws.b);
4821 get_msa_register(instr_.WdValue(), wd.b);
4823 wd.b[
i] = (ws.b[
i] & i8) | (wd.b[
i] & ~i8);
4825 set_msa_register(instr_.WdValue(), wd.b);
4826 TraceMSARegWr(wd.b);
4829 get_msa_register(instr_.WsValue(), ws.b);
4830 get_msa_register(instr_.WdValue(), wd.b);
4832 wd.b[
i] = (ws.b[
i] & ~i8) | (wd.b[
i] & i8);
4834 set_msa_register(instr_.WdValue(), wd.b);
4835 TraceMSARegWr(wd.b);
4838 get_msa_register(instr_.WsValue(), ws.b);
4839 get_msa_register(instr_.WdValue(), wd.b);
4841 wd.b[
i] = (ws.b[
i] & ~wd.b[
i]) | (wd.b[
i] & i8);
4843 set_msa_register(instr_.WdValue(), wd.b);
4844 TraceMSARegWr(wd.b);
4847 get_msa_register(instr_.WsValue(), ws.b);
4850 int k = (i8 >> (2 * j)) & 0x3;
4851 wd.b[
i] = ws.b[
i - j + k];
4853 set_msa_register(instr_.WdValue(), wd.b);
4854 TraceMSARegWr(wd.b);
4857 get_msa_register(instr_.WsValue(), ws.h);
4860 int k = (i8 >> (2 * j)) & 0x3;
4861 wd.h[
i] = ws.h[
i - j + k];
4863 set_msa_register(instr_.WdValue(), wd.h);
4864 TraceMSARegWr(wd.h);
4867 get_msa_register(instr_.WsValue(), ws.w);
4869 int j = (i8 >> (2 *
i)) & 0x3;
4872 set_msa_register(instr_.WdValue(), wd.w);
4873 TraceMSARegWr(wd.w);
4880template <
typename T>
4881T Simulator::MsaI5InstrHelper(uint32_t opcode, T ws, int32_t i5) {
4883 uint32_t ui5 = i5 & 0x1Fu;
4884 uint64_t ws_u64 =
static_cast<uint64_t
>(ws);
4885 uint64_t ui5_u64 =
static_cast<uint64_t
>(ui5);
4889 res =
static_cast<T
>(ws + ui5);
4892 res =
static_cast<T
>(ws - ui5);
4895 res =
static_cast<T
>(std::max(ws,
static_cast<T
>(i5)));
4898 res =
static_cast<T
>(std::min(ws,
static_cast<T
>(i5)));
4901 res =
static_cast<T
>(std::max(ws_u64, ui5_u64));
4904 res =
static_cast<T
>(std::min(ws_u64, ui5_u64));
4907 res =
static_cast<T
>(!
Compare(ws,
static_cast<T
>(i5)) ? -1ull : 0ull);
4910 res =
static_cast<T
>((
Compare(ws,
static_cast<T
>(i5)) == -1) ? -1ull
4914 res =
static_cast<T
>((
Compare(ws_u64, ui5_u64) == -1) ? -1ull : 0ull);
4918 static_cast<T
>((
Compare(ws,
static_cast<T
>(i5)) != 1) ? -1ull : 0ull);
4921 res =
static_cast<T
>((
Compare(ws_u64, ui5_u64) != 1) ? -1ull : 0ull);
4929void Simulator::DecodeTypeMsaI5() {
4931 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4932 uint32_t opcode = instr_.InstructionBits() &
kMsaI5Mask;
4936 int32_t i5 =
static_cast<int32_t>(instr_.MsaImm5Value() << 27) >> 27;
4938#define MSA_I5_DF(elem, num_of_lanes) \
4939 get_msa_register(instr_.WsValue(), ws.elem); \
4940 for (int i = 0; i < num_of_lanes; i++) { \
4941 wd.elem[i] = MsaI5InstrHelper(opcode, ws.elem[i], i5); \
4943 set_msa_register(instr_.WdValue(), wd.elem); \
4944 TraceMSARegWr(wd.elem)
4946 switch (DecodeMsaDataFormat()) {
4948 MSA_I5_DF(b, kMSALanesByte);
4951 MSA_I5_DF(h, kMSALanesHalf);
4954 MSA_I5_DF(w, kMSALanesWord);
4957 MSA_I5_DF(d, kMSALanesDword);
4965void Simulator::DecodeTypeMsaI10() {
4967 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4968 uint32_t opcode = instr_.InstructionBits() &
kMsaI5Mask;
4969 int64_t s10 = (
static_cast<int64_t
>(instr_.MsaImm10Value()) << 54) >> 54;
4972#define MSA_I10_DF(elem, num_of_lanes, T) \
4973 for (int i = 0; i < num_of_lanes; ++i) { \
4974 wd.elem[i] = static_cast<T>(s10); \
4976 set_msa_register(instr_.WdValue(), wd.elem); \
4977 TraceMSARegWr(wd.elem)
4979 if (opcode == LDI) {
4980 switch (DecodeMsaDataFormat()) {
4982 MSA_I10_DF(b, kMSALanesByte, int8_t);
4985 MSA_I10_DF(h, kMSALanesHalf, int16_t);
4988 MSA_I10_DF(w, kMSALanesWord, int32_t);
4991 MSA_I10_DF(d, kMSALanesDword, int64_t);
5002void Simulator::DecodeTypeMsaELM() {
5004 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5006 int32_t n = instr_.MsaElmNValue();
5011 MSACSR_ = base::bit_cast<uint32_t>(
5013 TraceRegWr(
static_cast<int32_t>(MSACSR_));
5017 SetResult(sa(),
static_cast<int64_t
>(base::bit_cast<int32_t>(MSACSR_)));
5021 get_msa_register(ws_reg(), &ws);
5022 set_msa_register(wd_reg(), &ws);
5031 switch (DecodeMsaDataFormat()) {
5034 get_msa_register(instr_.WsValue(), ws.b);
5035 alu_out =
static_cast<int32_t>(ws.b[
n]);
5037 (opcode == COPY_U) ? alu_out & 0xFFu : alu_out);
5041 get_msa_register(instr_.WsValue(), ws.h);
5042 alu_out =
static_cast<int32_t>(ws.h[
n]);
5044 (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out);
5048 get_msa_register(instr_.WsValue(), ws.w);
5049 alu_out =
static_cast<int32_t>(ws.w[
n]);
5051 (opcode == COPY_U) ? alu_out & 0xFFFFFFFFu : alu_out);
5055 get_msa_register(instr_.WsValue(), ws.d);
5056 alu_out =
static_cast<int64_t
>(ws.d[
n]);
5057 SetResult(wd_reg(), alu_out);
5065 switch (DecodeMsaDataFormat()) {
5068 int64_t rs = get_register(instr_.WsValue());
5069 get_msa_register(instr_.WdValue(), wd.b);
5070 wd.b[
n] = rs & 0xFFu;
5071 set_msa_register(instr_.WdValue(), wd.b);
5072 TraceMSARegWr(wd.b);
5077 int64_t rs = get_register(instr_.WsValue());
5078 get_msa_register(instr_.WdValue(), wd.h);
5079 wd.h[
n] = rs & 0xFFFFu;
5080 set_msa_register(instr_.WdValue(), wd.h);
5081 TraceMSARegWr(wd.h);
5086 int64_t rs = get_register(instr_.WsValue());
5087 get_msa_register(instr_.WdValue(), wd.w);
5088 wd.w[
n] = rs & 0xFFFFFFFFu;
5089 set_msa_register(instr_.WdValue(), wd.w);
5090 TraceMSARegWr(wd.w);
5095 int64_t rs = get_register(instr_.WsValue());
5096 get_msa_register(instr_.WdValue(), wd.d);
5098 set_msa_register(instr_.WdValue(), wd.d);
5099 TraceMSARegWr(wd.d);
5110 get_msa_register(ws_reg(), &ws);
5111 get_msa_register(wd_reg(), &wd);
5112#define SLDI_DF(s, k) \
5113 for (unsigned i = 0; i < s; i++) { \
5114 v[i] = ws.b[s * k + i]; \
5115 v[i + s] = wd.b[s * k + i]; \
5117 for (unsigned i = 0; i < s; i++) { \
5118 wd.b[s * k + i] = v[i + n]; \
5120 switch (DecodeMsaDataFormat()) {
5122 DCHECK(n < kMSALanesByte);
5123 SLDI_DF(kMSARegSize /
sizeof(int8_t) / kBitsPerByte, 0)
5126 DCHECK(n < kMSALanesHalf);
5127 for (
int k = 0; k < 2; ++k) {
5128 SLDI_DF(kMSARegSize /
sizeof(int16_t) / kBitsPerByte, k)
5132 DCHECK(n < kMSALanesWord);
5133 for (
int k = 0; k < 4; ++k) {
5134 SLDI_DF(kMSARegSize /
sizeof(int32_t) / kBitsPerByte, k)
5138 DCHECK(n < kMSALanesDword);
5139 for (
int k = 0; k < 8; ++k) {
5140 SLDI_DF(kMSARegSize /
sizeof(int64_t) / kBitsPerByte, k)
5146 set_msa_register(wd_reg(), &wd);
5160template <
typename T>
5161T Simulator::MsaBitInstrHelper(uint32_t opcode, T wd, T ws, int32_t
m) {
5162 using uT =
typename std::make_unsigned<T>::type;
5166 res =
static_cast<T
>(ws <<
m);
5169 res =
static_cast<T
>(ArithmeticShiftRight(ws,
m));
5172 res =
static_cast<T
>(
static_cast<uT
>(ws) >>
m);
5175 res =
static_cast<T
>(
static_cast<T
>(~(1ull <<
m)) & ws);
5178 res =
static_cast<T
>(
static_cast<T
>(1ull <<
m) | ws);
5181 res =
static_cast<T
>(
static_cast<T
>(1ull <<
m) ^ ws);
5184 int elem_size = 8 *
sizeof(
T);
5186 if (bits == elem_size) {
5187 res =
static_cast<T
>(ws);
5189 uint64_t
mask = ((1ull << bits) - 1) << (elem_size - bits);
5190 res =
static_cast<T
>((
static_cast<T
>(
mask) & ws) |
5191 (
static_cast<T
>(~mask) & wd));
5195 int elem_size = 8 *
sizeof(
T);
5197 if (bits == elem_size) {
5198 res =
static_cast<T
>(ws);
5200 uint64_t
mask = (1ull << bits) - 1;
5201 res =
static_cast<T
>((
static_cast<T
>(
mask) & ws) |
5202 (
static_cast<T
>(~mask) & wd));
5206#define M_MAX_INT(x) static_cast<int64_t>((1LL << ((x)-1)) - 1)
5207#define M_MIN_INT(x) static_cast<int64_t>(-(1LL << ((x)-1)))
5208 int shift = 64 - 8 *
sizeof(
T);
5209 int64_t ws_i64 = (
static_cast<int64_t
>(ws) << shift) >> shift;
5210 res =
static_cast<T
>(ws_i64 < M_MIN_INT(
m + 1)
5212 : ws_i64 > M_MAX_INT(
m + 1) ? M_MAX_INT(
m + 1)
5218#define M_MAX_UINT(x) static_cast<uint64_t>(-1ULL >> (64 - (x)))
5219 uint64_t
mask =
static_cast<uint64_t
>(-1ULL >> (64 - 8 *
sizeof(
T)));
5220 uint64_t ws_u64 =
static_cast<uint64_t
>(ws) &
mask;
5221 res =
static_cast<T
>(ws_u64 < M_MAX_UINT(
m + 1) ? ws_u64
5222 : M_MAX_UINT(
m + 1));
5227 res =
static_cast<T
>(ws);
5229 res =
static_cast<T
>(ArithmeticShiftRight(ws,
m)) +
5230 static_cast<T
>((ws >> (
m - 1)) & 0x1);
5235 res =
static_cast<T
>(ws);
5237 res =
static_cast<T
>(
static_cast<uT
>(ws) >>
m) +
5238 static_cast<T
>((ws >> (
m - 1)) & 0x1);
5247void Simulator::DecodeTypeMsaBIT() {
5249 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5250 uint32_t opcode = instr_.InstructionBits() &
kMsaBITMask;
5254#define MSA_BIT_DF(elem, num_of_lanes) \
5255 get_msa_register(instr_.WsValue(), ws.elem); \
5256 if (opcode == BINSLI || opcode == BINSRI) { \
5257 get_msa_register(instr_.WdValue(), wd.elem); \
5259 for (int i = 0; i < num_of_lanes; i++) { \
5260 wd.elem[i] = MsaBitInstrHelper(opcode, wd.elem[i], ws.elem[i], m); \
5262 set_msa_register(instr_.WdValue(), wd.elem); \
5263 TraceMSARegWr(wd.elem)
5265 switch (DecodeMsaDataFormat()) {
5267 DCHECK(
m < kMSARegSize / kMSALanesByte);
5268 MSA_BIT_DF(b, kMSALanesByte);
5271 DCHECK(
m < kMSARegSize / kMSALanesHalf);
5272 MSA_BIT_DF(h, kMSALanesHalf);
5275 DCHECK(
m < kMSARegSize / kMSALanesWord);
5276 MSA_BIT_DF(w, kMSALanesWord);
5279 DCHECK(
m < kMSARegSize / kMSALanesDword);
5280 MSA_BIT_DF(d, kMSALanesDword);
5288void Simulator::DecodeTypeMsaMI10() {
5290 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5291 uint32_t opcode = instr_.InstructionBits() &
kMsaMI10Mask;
5292 int64_t s10 = (
static_cast<int64_t
>(instr_.MsaImmMI10Value()) << 54) >> 54;
5293 int64_t rs = get_register(instr_.WsValue());
5297#define MSA_MI10_LOAD(elem, num_of_lanes, T) \
5298 for (int i = 0; i < num_of_lanes; ++i) { \
5299 addr = rs + (s10 + i) * sizeof(T); \
5300 wd.elem[i] = ReadMem<T>(addr, instr_.instr()); \
5302 set_msa_register(instr_.WdValue(), wd.elem);
5304#define MSA_MI10_STORE(elem, num_of_lanes, T) \
5305 get_msa_register(instr_.WdValue(), wd.elem); \
5306 for (int i = 0; i < num_of_lanes; ++i) { \
5307 addr = rs + (s10 + i) * sizeof(T); \
5308 WriteMem<T>(addr, wd.elem[i], instr_.instr()); \
5311 if (opcode == MSA_LD) {
5312 switch (DecodeMsaDataFormat()) {
5314 MSA_MI10_LOAD(b, kMSALanesByte, int8_t);
5317 MSA_MI10_LOAD(h, kMSALanesHalf, int16_t);
5320 MSA_MI10_LOAD(w, kMSALanesWord, int32_t);
5323 MSA_MI10_LOAD(d, kMSALanesDword, int64_t);
5328 }
else if (opcode == MSA_ST) {
5329 switch (DecodeMsaDataFormat()) {
5331 MSA_MI10_STORE(b, kMSALanesByte, int8_t);
5334 MSA_MI10_STORE(h, kMSALanesHalf, int16_t);
5337 MSA_MI10_STORE(w, kMSALanesWord, int32_t);
5340 MSA_MI10_STORE(d, kMSALanesDword, int64_t);
5350#undef MSA_MI10_STORE
5353template <
typename T>
5354T Simulator::Msa3RInstrHelper(uint32_t opcode, T wd, T ws, T wt) {
5355 using uT =
typename std::make_unsigned<T>::type;
5357 int wt_modulo = wt % (
sizeof(
T) * 8);
5360 res =
static_cast<T
>(ws << wt_modulo);
5363 res =
static_cast<T
>(ArithmeticShiftRight(ws, wt_modulo));
5366 res =
static_cast<T
>(
static_cast<uT
>(ws) >> wt_modulo);
5369 res =
static_cast<T
>(
static_cast<T
>(~(1ull << wt_modulo)) & ws);
5372 res =
static_cast<T
>(
static_cast<T
>(1ull << wt_modulo) | ws);
5375 res =
static_cast<T
>(
static_cast<T
>(1ull << wt_modulo) ^ ws);
5378 int elem_size = 8 *
sizeof(
T);
5379 int bits = wt_modulo + 1;
5380 if (bits == elem_size) {
5381 res =
static_cast<T
>(ws);
5383 uint64_t
mask = ((1ull << bits) - 1) << (elem_size - bits);
5384 res =
static_cast<T
>((
static_cast<T
>(
mask) & ws) |
5385 (
static_cast<T
>(~mask) & wd));
5389 int elem_size = 8 *
sizeof(
T);
5390 int bits = wt_modulo + 1;
5391 if (bits == elem_size) {
5392 res =
static_cast<T
>(ws);
5394 uint64_t
mask = (1ull << bits) - 1;
5395 res =
static_cast<T
>((
static_cast<T
>(
mask) & ws) |
5396 (
static_cast<T
>(~mask) & wd));
5406 res = std::max(ws, wt);
5409 res =
static_cast<T
>(std::max(
static_cast<uT
>(ws),
static_cast<uT
>(wt)));
5412 res = std::min(ws, wt);
5415 res =
static_cast<T
>(std::min(
static_cast<uT
>(ws),
static_cast<uT
>(wt)));
5420 res =
Nabs(ws) <
Nabs(wt) ? ws : wt;
5425 res =
Nabs(ws) >
Nabs(wt) ? ws : wt;
5428 res =
static_cast<T
>(!
Compare(ws, wt) ? -1ull : 0ull);
5431 res =
static_cast<T
>((
Compare(ws, wt) == -1) ? -1ull : 0ull);
5434 res =
static_cast<T
>(
5435 (
Compare(
static_cast<uT
>(ws),
static_cast<uT
>(wt)) == -1) ? -1ull
5439 res =
static_cast<T
>((
Compare(ws, wt) != 1) ? -1ull : 0ull);
5442 res =
static_cast<T
>(
5443 (
Compare(
static_cast<uT
>(ws),
static_cast<uT
>(wt)) != 1) ? -1ull
5447 res =
static_cast<T
>(
Abs(ws) +
Abs(wt));
5450 T ws_nabs =
Nabs(ws);
5451 T wt_nabs =
Nabs(wt);
5452 if (ws_nabs < -std::numeric_limits<T>::max() - wt_nabs) {
5453 res = std::numeric_limits<T>::max();
5455 res = -(ws_nabs + wt_nabs);
5462 uT ws_u =
static_cast<uT
>(ws);
5463 uT wt_u =
static_cast<uT
>(wt);
5467 res =
static_cast<T
>((wt & ws) + ((wt ^ ws) >> 1));
5470 uT ws_u =
static_cast<uT
>(ws);
5471 uT wt_u =
static_cast<uT
>(wt);
5472 res =
static_cast<T
>((wt_u & ws_u) + ((wt_u ^ ws_u) >> 1));
5475 res =
static_cast<T
>((wt | ws) - ((wt ^ ws) >> 1));
5478 uT ws_u =
static_cast<uT
>(ws);
5479 uT wt_u =
static_cast<uT
>(wt);
5480 res =
static_cast<T
>((wt_u | ws_u) - ((wt_u ^ ws_u) >> 1));
5486 uT ws_u =
static_cast<uT
>(ws);
5487 uT wt_u =
static_cast<uT
>(wt);
5491 uT wsu =
static_cast<uT
>(ws);
5493 uT wtu =
static_cast<uT
>(wt);
5497 res =
static_cast<T
>(wsu - wtu);
5500 if (wsu > std::numeric_limits<uT>::max() + wt) {
5501 res =
static_cast<T
>(std::numeric_limits<uT>::max());
5503 res =
static_cast<T
>(wsu - wt);
5508 uT wsu =
static_cast<uT
>(ws);
5509 uT wtu =
static_cast<uT
>(wt);
5513 if (wdu > std::numeric_limits<T>::max()) {
5514 res = std::numeric_limits<T>::max();
5516 res =
static_cast<T
>(wdu);
5520 CHECK(-std::numeric_limits<T>::max() ==
5521 std::numeric_limits<T>::min() + 1);
5522 if (wdu <= std::numeric_limits<T>::max()) {
5523 res = -
static_cast<T
>(wdu);
5525 res = std::numeric_limits<T>::min();
5530 res =
static_cast<T
>(
Abs(ws - wt));
5533 uT wsu =
static_cast<uT
>(ws);
5534 uT wtu =
static_cast<uT
>(wt);
5535 res =
static_cast<T
>(wsu > wtu ? wsu - wtu : wtu - wsu);
5547 res = wt != 0 ? ws / wt :
static_cast<T
>(Unpredictable);
5550 res = wt != 0 ?
static_cast<T
>(
static_cast<uT
>(ws) /
static_cast<uT
>(wt))
5551 : static_cast<T>(Unpredictable);
5554 res = wt != 0 ? ws % wt :
static_cast<T
>(Unpredictable);
5557 res = wt != 0 ?
static_cast<T
>(
static_cast<uT
>(ws) %
static_cast<uT
>(wt))
5558 :
static_cast<T
>(Unpredictable);
5571 int bit = wt_modulo == 0 ? 0 : (ws >> (wt_modulo - 1)) & 1;
5572 res =
static_cast<T
>(ArithmeticShiftRight(ws, wt_modulo) + bit);
5575 uT wsu =
static_cast<uT
>(ws);
5576 int bit = wt_modulo == 0 ? 0 : (wsu >> (wt_modulo - 1)) & 1;
5577 res =
static_cast<T
>((wsu >> wt_modulo) + bit);
5584template <
typename T_
int,
typename T_reg>
5585void Msa3RInstrHelper_shuffle(
const uint32_t opcode, T_reg ws, T_reg wt,
5586 T_reg wd,
const int i,
const int num_of_lanes) {
5587 T_int *ws_p, *wt_p, *wd_p;
5588 ws_p =
reinterpret_cast<T_int*
>(ws);
5589 wt_p =
reinterpret_cast<T_int*
>(wt);
5590 wd_p =
reinterpret_cast<T_int*
>(wd);
5593 wd_p[
i] = wt_p[2 *
i];
5594 wd_p[
i + num_of_lanes / 2] = ws_p[2 *
i];
5597 wd_p[
i] = wt_p[2 *
i + 1];
5598 wd_p[
i + num_of_lanes / 2] = ws_p[2 *
i + 1];
5601 wd_p[2 *
i] = wt_p[
i + num_of_lanes / 2];
5602 wd_p[2 *
i + 1] = ws_p[
i + num_of_lanes / 2];
5605 wd_p[2 *
i] = wt_p[
i];
5606 wd_p[2 *
i + 1] = ws_p[
i];
5609 wd_p[2 *
i] = wt_p[2 *
i];
5610 wd_p[2 *
i + 1] = ws_p[2 *
i];
5613 wd_p[2 *
i] = wt_p[2 *
i + 1];
5614 wd_p[2 *
i + 1] = ws_p[2 *
i + 1];
5617 const int mask_not_valid = 0xC0;
5618 const int mask_6_bits = 0x3F;
5619 if ((wd_p[
i] & mask_not_valid)) {
5622 int k = (wd_p[
i] & mask_6_bits) % (num_of_lanes * 2);
5623 wd_p[
i] = k >= num_of_lanes ? ws_p[k - num_of_lanes] : wt_p[k];
5631template <
typename T_
int,
typename T_smaller_
int,
typename T_reg>
5632void Msa3RInstrHelper_horizontal(
const uint32_t opcode, T_reg ws, T_reg wt,
5633 T_reg wd,
const int i,
5634 const int num_of_lanes) {
5635 using T_uint =
typename std::make_unsigned<T_int>::type;
5636 using T_smaller_uint =
typename std::make_unsigned<T_smaller_int>::type;
5638 T_smaller_int *ws_p, *wt_p;
5639 ws_p =
reinterpret_cast<T_smaller_int*
>(ws);
5640 wt_p =
reinterpret_cast<T_smaller_int*
>(wt);
5641 wd_p =
reinterpret_cast<T_int*
>(wd);
5643 T_smaller_uint *ws_pu, *wt_pu;
5644 ws_pu =
reinterpret_cast<T_smaller_uint*
>(ws);
5645 wt_pu =
reinterpret_cast<T_smaller_uint*
>(wt);
5646 wd_pu =
reinterpret_cast<T_uint*
>(wd);
5650 static_cast<T_int
>(ws_p[2 *
i + 1]) +
static_cast<T_int
>(wt_p[2 *
i]);
5653 wd_pu[
i] =
static_cast<T_uint
>(ws_pu[2 *
i + 1]) +
5654 static_cast<T_uint
>(wt_pu[2 *
i]);
5658 static_cast<T_int
>(ws_p[2 *
i + 1]) -
static_cast<T_int
>(wt_p[2 *
i]);
5661 wd_pu[
i] =
static_cast<T_uint
>(ws_pu[2 *
i + 1]) -
5662 static_cast<T_uint
>(wt_pu[2 *
i]);
5669void Simulator::DecodeTypeMsa3R() {
5671 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5672 uint32_t opcode = instr_.InstructionBits() &
kMsa3RMask;
5673 msa_reg_t ws, wd, wt;
5674 get_msa_register(ws_reg(), &ws);
5675 get_msa_register(wt_reg(), &wt);
5676 get_msa_register(wd_reg(), &wd);
5682#define HORIZONTAL_ARITHMETIC_DF(num_of_lanes, int_type, lesser_int_type) \
5683 for (int i = 0; i < num_of_lanes; ++i) { \
5684 Msa3RInstrHelper_horizontal<int_type, lesser_int_type>( \
5685 opcode, &ws, &wt, &wd, i, num_of_lanes); \
5687 switch (DecodeMsaDataFormat()) {
5689 HORIZONTAL_ARITHMETIC_DF(kMSALanesHalf, int16_t, int8_t);
5692 HORIZONTAL_ARITHMETIC_DF(kMSALanesWord, int32_t, int16_t);
5695 HORIZONTAL_ARITHMETIC_DF(kMSALanesDword, int64_t, int32_t);
5701#undef HORIZONTAL_ARITHMETIC_DF
5703#define VSHF_DF(num_of_lanes, int_type) \
5704 for (int i = 0; i < num_of_lanes; ++i) { \
5705 Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \
5708 switch (DecodeMsaDataFormat()) {
5710 VSHF_DF(kMSALanesByte, int8_t);
5713 VSHF_DF(kMSALanesHalf, int16_t);
5716 VSHF_DF(kMSALanesWord, int32_t);
5719 VSHF_DF(kMSALanesDword, int64_t);
5732#define INTERLEAVE_PACK_DF(num_of_lanes, int_type) \
5733 for (int i = 0; i < num_of_lanes / 2; ++i) { \
5734 Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \
5737 switch (DecodeMsaDataFormat()) {
5739 INTERLEAVE_PACK_DF(kMSALanesByte, int8_t);
5742 INTERLEAVE_PACK_DF(kMSALanesHalf, int16_t);
5745 INTERLEAVE_PACK_DF(kMSALanesWord, int32_t);
5748 INTERLEAVE_PACK_DF(kMSALanesDword, int64_t);
5754#undef INTERLEAVE_PACK_DF
5756#define MSA_3R_DF(elem, num_of_lanes) \
5757 for (int i = 0; i < num_of_lanes; i++) { \
5758 wd.elem[i] = Msa3RInstrHelper(opcode, wd.elem[i], ws.elem[i], wt.elem[i]); \
5761 switch (DecodeMsaDataFormat()) {
5763 MSA_3R_DF(b, kMSALanesByte);
5766 MSA_3R_DF(h, kMSALanesHalf);
5769 MSA_3R_DF(w, kMSALanesWord);
5772 MSA_3R_DF(d, kMSALanesDword);
5780 set_msa_register(wd_reg(), &wd);
5784template <
typename T_
int,
typename T_fp,
typename T_reg>
5785void Msa3RFInstrHelper(uint32_t opcode, T_reg ws, T_reg wt, T_reg* wd) {
5786 const T_int all_ones =
static_cast<T_int
>(-1);
5787 const T_fp s_element = *
reinterpret_cast<T_fp*
>(&ws);
5788 const T_fp t_element = *
reinterpret_cast<T_fp*
>(&wt);
5791 if (std::isnan(s_element) || std::isnan(t_element)) {
5798 if (s_element != t_element || std::isnan(s_element) ||
5799 std::isnan(t_element)) {
5806 if (s_element == t_element || std::isnan(s_element) ||
5807 std::isnan(t_element)) {
5814 if (s_element >= t_element || std::isnan(s_element) ||
5815 std::isnan(t_element)) {
5822 if (s_element < t_element || std::isnan(s_element) ||
5823 std::isnan(t_element)) {
5830 if (s_element > t_element || std::isnan(s_element) ||
5831 std::isnan(t_element)) {
5838 if (s_element <= t_element || std::isnan(s_element) ||
5839 std::isnan(t_element)) {
5846 if (std::isnan(s_element) || std::isnan(t_element)) {
5853 if (s_element != t_element || std::isnan(s_element) ||
5854 std::isnan(t_element)) {
5861 if (s_element == t_element || std::isnan(s_element) ||
5862 std::isnan(t_element)) {
5869 *wd = base::bit_cast<T_int>(s_element + t_element);
5872 *wd = base::bit_cast<T_int>(s_element - t_element);
5875 *wd = base::bit_cast<T_int>(s_element * t_element);
5878 if (t_element == 0) {
5879 *wd = base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
5881 *wd = base::bit_cast<T_int>(s_element / t_element);
5885 *wd = base::bit_cast<T_int>(
5886 std::fma(s_element, t_element, *
reinterpret_cast<T_fp*
>(wd)));
5889 *wd = base::bit_cast<T_int>(
5890 std::fma(-s_element, t_element, *
reinterpret_cast<T_fp*
>(wd)));
5893 *wd = base::bit_cast<T_int>(std::ldexp(s_element,
static_cast<int>(wt)));
5896 *wd = base::bit_cast<T_int>(std::min(s_element, t_element));
5899 *wd = base::bit_cast<T_int>(std::max(s_element, t_element));
5902 *wd = base::bit_cast<T_int>(
5903 std::fabs(s_element) < std::fabs(t_element) ? s_element : t_element);
5906 *wd = base::bit_cast<T_int>(
5907 std::fabs(s_element) > std::fabs(t_element) ? s_element : t_element);
5927template <
typename T_
int,
typename T_
int_dbl,
typename T_reg>
5928void Msa3RFInstrHelper2(uint32_t opcode, T_reg ws, T_reg wt, T_reg* wd) {
5930 using T_uint_dbl =
typename std::make_unsigned<T_int_dbl>::type;
5931 const T_int max_int = std::numeric_limits<T_int>::max();
5932 const T_int min_int = std::numeric_limits<T_int>::min();
5934 const T_int_dbl reg_s = ws;
5935 const T_int_dbl reg_t = wt;
5936 T_int_dbl product,
result;
5937 product = reg_s * reg_t;
5940 const T_int_dbl min_fix_dbl =
5941 base::bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >>
5943 const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5944 if (product == min_fix_dbl) {
5945 product = max_fix_dbl;
5947 *wd =
static_cast<T_int
>(product >> shift);
5950 result = (product + (
static_cast<T_int_dbl
>(*wd) << shift)) >> shift;
5951 *wd =
static_cast<T_int
>(
5955 result = (-product + (
static_cast<T_int_dbl
>(*wd) << shift)) >> shift;
5956 *wd =
static_cast<T_int
>(
5960 const T_int_dbl min_fix_dbl =
5961 base::bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >>
5963 const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5964 if (product == min_fix_dbl) {
5965 *wd =
static_cast<T_int
>(max_fix_dbl >> shift);
5968 *wd =
static_cast<T_int
>((product + (1 << (shift - 1))) >> shift);
5971 result = (product + (
static_cast<T_int_dbl
>(*wd) << shift) +
5972 (1 << (shift - 1))) >>
5974 *wd =
static_cast<T_int
>(
5978 result = (-product + (
static_cast<T_int_dbl
>(*wd) << shift) +
5979 (1 << (shift - 1))) >>
5981 *wd =
static_cast<T_int
>(
5989void Simulator::DecodeTypeMsa3RF() {
5991 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5992 uint32_t opcode = instr_.InstructionBits() &
kMsa3RFMask;
5993 msa_reg_t wd, ws, wt;
5994 if (opcode != FCAF) {
5995 get_msa_register(ws_reg(), &ws);
5996 get_msa_register(wt_reg(), &wt);
6004#define PACK_FLOAT16(sign, exp, frac) \
6005 static_cast<uint16_t>(((sign) << 15) + ((exp) << 10) + (frac))
6006#define FEXDO_DF(source, dst) \
6009 aSign = element >> 31; \
6010 aExp = element >> 23 & 0xFF; \
6011 aFrac = element & 0x007FFFFF; \
6012 if (aExp == 0xFF) { \
6019 dst = PACK_FLOAT16(aSign, 0x1F, 0); \
6021 } else if (aExp == 0 && aFrac == 0) { \
6022 dst = PACK_FLOAT16(aSign, 0, 0); \
6027 uint32_t increment; \
6028 bool rounding_bumps_exp; \
6029 aFrac |= 0x00800000; \
6033 mask = 0x00FFFFFF; \
6034 if (aExp >= -11) { \
6035 mask >>= 11 + aExp; \
6039 mask = 0x00001FFF; \
6041 switch (MSACSR_ & 3) { \
6042 case kRoundToNearest: \
6043 increment = (mask + 1) >> 1; \
6044 if ((aFrac & mask) == increment) { \
6045 increment = aFrac & (increment << 1); \
6048 case kRoundToPlusInf: \
6049 increment = aSign ? 0 : mask; \
6051 case kRoundToMinusInf: \
6052 increment = aSign ? mask : 0; \
6054 case kRoundToZero: \
6058 rounding_bumps_exp = (aFrac + increment >= 0x01000000); \
6059 if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) { \
6060 dst = PACK_FLOAT16(aSign, 0x1F, 0); \
6063 aFrac += increment; \
6064 if (rounding_bumps_exp) { \
6069 dst = PACK_FLOAT16(aSign, 0, 0); \
6076 dst = PACK_FLOAT16(aSign, aExp, aFrac >> 13); \
6079 switch (DecodeMsaDataFormat()) {
6082 uint_fast32_t element;
6083 uint_fast32_t aSign, aFrac;
6085 FEXDO_DF(ws.uw[
i], wd.uh[
i + kMSALanesHalf / 2])
6086 FEXDO_DF(wt.uw[
i], wd.uh[
i])
6090 for (
int i = 0;
i < kMSALanesDword;
i++) {
6092 static_cast<float>(base::bit_cast<double>(ws.d[
i])));
6093 wd.w[
i] = base::bit_cast<int32_t>(
6094 static_cast<float>(base::bit_cast<double>(wt.d[
i])));
6104#define FTQ_DF(source, dst, fp_type, int_type) \
6105 element = base::bit_cast<fp_type>(source) * \
6106 (1U << (sizeof(int_type) * kBitsPerByte - 1)); \
6107 if (element > std::numeric_limits<int_type>::max()) { \
6108 dst = std::numeric_limits<int_type>::max(); \
6109 } else if (element < std::numeric_limits<int_type>::min()) { \
6110 dst = std::numeric_limits<int_type>::min(); \
6111 } else if (std::isnan(element)) { \
6114 int_type fixed_point; \
6115 round_according_to_msacsr(element, &element, &fixed_point); \
6116 dst = fixed_point; \
6119 switch (DecodeMsaDataFormat()) {
6123 FTQ_DF(ws.w[
i], wd.h[
i + kMSALanesHalf / 2],
float, int16_t)
6124 FTQ_DF(wt.w[
i], wd.h[
i],
float, int16_t)
6130 FTQ_DF(ws.d[
i], wd.w[
i + kMSALanesWord / 2],
double, int32_t)
6131 FTQ_DF(wt.d[
i], wd.w[
i],
double, int32_t)
6139#define MSA_3RF_DF(T1, T2, Lanes, ws, wt, wd) \
6140 for (int i = 0; i < Lanes; i++) { \
6141 Msa3RFInstrHelper<T1, T2>(opcode, ws, wt, &(wd)); \
6143#define MSA_3RF_DF2(T1, T2, Lanes, ws, wt, wd) \
6144 for (int i = 0; i < Lanes; i++) { \
6145 Msa3RFInstrHelper2<T1, T2>(opcode, ws, wt, &(wd)); \
6151 get_msa_register(wd_reg(), &wd);
6155 switch (DecodeMsaDataFormat()) {
6157 MSA_3RF_DF2(int16_t, int32_t, kMSALanesHalf, ws.h[
i], wt.h[
i],
6161 MSA_3RF_DF2(int32_t, int64_t, kMSALanesWord, ws.w[
i], wt.w[
i],
6169 if (opcode == FMADD || opcode == FMSUB) {
6170 get_msa_register(wd_reg(), &wd);
6172 switch (DecodeMsaDataFormat()) {
6174 MSA_3RF_DF(int32_t,
float, kMSALanesWord, ws.w[
i], wt.w[
i], wd.w[
i])
6177 MSA_3RF_DF(int64_t,
double, kMSALanesDword, ws.d[
i], wt.d[
i], wd.d[
i])
6186 set_msa_register(wd_reg(), &wd);
6190void Simulator::DecodeTypeMsaVec() {
6192 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
6193 uint32_t opcode = instr_.InstructionBits() &
kMsaVECMask;
6194 msa_reg_t wd, ws, wt;
6196 get_msa_register(instr_.WsValue(), ws.d);
6197 get_msa_register(instr_.WtValue(), wt.d);
6198 if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
6199 get_msa_register(instr_.WdValue(), wd.d);
6205 wd.d[
i] = ws.d[
i] & wt.d[
i];
6208 wd.d[
i] = ws.d[
i] | wt.d[
i];
6211 wd.d[
i] = ~(ws.d[
i] | wt.d[
i]);
6214 wd.d[
i] = ws.d[
i] ^ wt.d[
i];
6217 wd.d[
i] = (wt.d[
i] & ws.d[
i]) | (~wt.d[
i] & wd.d[
i]);
6220 wd.d[
i] = (~wt.d[
i] & ws.d[
i]) | (wt.d[
i] & wd.d[
i]);
6223 wd.d[
i] = (~wd.d[
i] & ws.d[
i]) | (wd.d[
i] & wt.d[
i]);
6229 set_msa_register(instr_.WdValue(), wd.d);
6230 TraceMSARegWr(wd.d);
6233void Simulator::DecodeTypeMsa2R() {
6235 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
6236 uint32_t opcode = instr_.InstructionBits() &
kMsa2RMask;
6240 switch (DecodeMsaDataFormat()) {
6242 int64_t rs = get_register(instr_.WsValue());
6244 wd.b[
i] = rs & 0xFFu;
6246 set_msa_register(instr_.WdValue(), wd.b);
6247 TraceMSARegWr(wd.b);
6251 int64_t rs = get_register(instr_.WsValue());
6253 wd.h[
i] = rs & 0xFFFFu;
6255 set_msa_register(instr_.WdValue(), wd.h);
6256 TraceMSARegWr(wd.h);
6260 int64_t rs = get_register(instr_.WsValue());
6262 wd.w[
i] = rs & 0xFFFFFFFFu;
6264 set_msa_register(instr_.WdValue(), wd.w);
6265 TraceMSARegWr(wd.w);
6269 int64_t rs = get_register(instr_.WsValue());
6270 wd.d[0] = wd.d[1] = rs;
6271 set_msa_register(instr_.WdValue(), wd.d);
6272 TraceMSARegWr(wd.d);
6280#define PCNT_DF(elem, num_of_lanes) \
6281 get_msa_register(instr_.WsValue(), ws.elem); \
6282 for (int i = 0; i < num_of_lanes; i++) { \
6283 uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
6284 wd.elem[i] = base::bits::CountPopulation(u64elem); \
6286 set_msa_register(instr_.WdValue(), wd.elem); \
6287 TraceMSARegWr(wd.elem)
6289 switch (DecodeMsaDataFormat()) {
6291 PCNT_DF(ub, kMSALanesByte);
6294 PCNT_DF(uh, kMSALanesHalf);
6297 PCNT_DF(uw, kMSALanesWord);
6300 PCNT_DF(ud, kMSALanesDword);
6308#define NLOC_DF(elem, num_of_lanes) \
6309 get_msa_register(instr_.WsValue(), ws.elem); \
6310 for (int i = 0; i < num_of_lanes; i++) { \
6311 const uint64_t mask = (num_of_lanes == kMSALanesDword) \
6313 : (1ULL << (kMSARegSize / num_of_lanes)) - 1; \
6314 uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask; \
6315 wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
6316 (64 - kMSARegSize / num_of_lanes); \
6318 set_msa_register(instr_.WdValue(), wd.elem); \
6319 TraceMSARegWr(wd.elem)
6321 switch (DecodeMsaDataFormat()) {
6323 NLOC_DF(ub, kMSALanesByte);
6326 NLOC_DF(uh, kMSALanesHalf);
6329 NLOC_DF(uw, kMSALanesWord);
6332 NLOC_DF(ud, kMSALanesDword);
6340#define NLZC_DF(elem, num_of_lanes) \
6341 get_msa_register(instr_.WsValue(), ws.elem); \
6342 for (int i = 0; i < num_of_lanes; i++) { \
6343 uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
6344 wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
6345 (64 - kMSARegSize / num_of_lanes); \
6347 set_msa_register(instr_.WdValue(), wd.elem); \
6348 TraceMSARegWr(wd.elem)
6350 switch (DecodeMsaDataFormat()) {
6352 NLZC_DF(ub, kMSALanesByte);
6355 NLZC_DF(uh, kMSALanesHalf);
6358 NLZC_DF(uw, kMSALanesWord);
6361 NLZC_DF(ud, kMSALanesDword);
6373#define BIT(n) (0x1LL << n)
6374#define QUIET_BIT_S(nan) (base::bit_cast<int32_t>(nan) & BIT(22))
6375#define QUIET_BIT_D(nan) (base::bit_cast<int64_t>(nan) & BIT(51))
6376static inline bool isSnan(
float fp) {
return !QUIET_BIT_S(fp); }
6377static inline bool isSnan(
double fp) {
return !QUIET_BIT_D(fp); }
6381template <
typename T_
int,
typename T_fp,
typename T_src,
typename T_dst>
6382T_int Msa2RFInstrHelper(uint32_t opcode, T_src src, T_dst* dst,
6384 using T_uint =
typename std::make_unsigned<T_int>::type;
6387#define SNAN_BIT BIT(0)
6388#define QNAN_BIT BIT(1)
6389#define NEG_INFINITY_BIT BIT(2)
6390#define NEG_NORMAL_BIT BIT(3)
6391#define NEG_SUBNORMAL_BIT BIT(4)
6392#define NEG_ZERO_BIT BIT(5)
6393#define POS_INFINITY_BIT BIT(6)
6394#define POS_NORMAL_BIT BIT(7)
6395#define POS_SUBNORMAL_BIT BIT(8)
6396#define POS_ZERO_BIT BIT(9)
6397 T_fp element = *
reinterpret_cast<T_fp*
>(&src);
6398 switch (std::fpclassify(element)) {
6400 if (std::signbit(element)) {
6401 *dst = NEG_INFINITY_BIT;
6403 *dst = POS_INFINITY_BIT;
6407 if (isSnan(element)) {
6414 if (std::signbit(element)) {
6415 *dst = NEG_NORMAL_BIT;
6417 *dst = POS_NORMAL_BIT;
6421 if (std::signbit(element)) {
6422 *dst = NEG_SUBNORMAL_BIT;
6424 *dst = POS_SUBNORMAL_BIT;
6428 if (std::signbit(element)) {
6429 *dst = NEG_ZERO_BIT;
6431 *dst = POS_ZERO_BIT;
6442#undef NEG_INFINITY_BIT
6443#undef NEG_NORMAL_BIT
6444#undef NEG_SUBNORMAL_BIT
6446#undef POS_INFINITY_BIT
6447#undef POS_NORMAL_BIT
6448#undef POS_SUBNORMAL_BIT
6451 T_fp element = base::bit_cast<T_fp>(src);
6452 const T_int max_int = std::numeric_limits<T_int>::max();
6453 const T_int min_int = std::numeric_limits<T_int>::min();
6454 if (std::isnan(element)) {
6456 }
else if (element >=
static_cast<T_fp
>(max_int) || element <= min_int) {
6457 *dst = element >=
static_cast<T_fp
>(max_int) ? max_int : min_int;
6459 *dst =
static_cast<T_int
>(std::trunc(element));
6464 T_fp element = base::bit_cast<T_fp>(src);
6465 const T_uint max_int = std::numeric_limits<T_uint>::max();
6466 if (std::isnan(element)) {
6468 }
else if (element >=
static_cast<T_fp
>(max_int) || element <= 0) {
6469 *dst = element >=
static_cast<T_fp
>(max_int) ? max_int : 0;
6471 *dst =
static_cast<T_uint
>(std::trunc(element));
6476 T_fp element = base::bit_cast<T_fp>(src);
6477 if (element < 0 || std::isnan(element)) {
6478 *dst = base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6480 *dst = base::bit_cast<T_int>(std::sqrt(element));
6485 T_fp element = base::bit_cast<T_fp>(src);
6486 if (element < 0 || std::isnan(element)) {
6487 *dst = base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6489 *dst = base::bit_cast<T_int>(1 / std::sqrt(element));
6494 T_fp element = base::bit_cast<T_fp>(src);
6495 if (std::isnan(element)) {
6496 *dst = base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6498 *dst = base::bit_cast<T_int>(1 / element);
6503 T_fp element = base::bit_cast<T_fp>(src);
6504 if (std::isnan(element)) {
6505 *dst = base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6508 sim->round_according_to_msacsr<T_fp, T_int>(element, &element, &dummy);
6509 *dst = base::bit_cast<T_int>(element);
6514 T_fp element = base::bit_cast<T_fp>(src);
6515 switch (std::fpclassify(element)) {
6518 *dst = base::bit_cast<T_int>(std::logb(element));
6521 *dst = base::bit_cast<T_int>(-std::numeric_limits<T_fp>::infinity());
6524 *dst = base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6529 base::bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6531 *dst = base::bit_cast<T_int>(std::numeric_limits<T_fp>::infinity());
6540 T_fp element = base::bit_cast<T_fp>(src);
6541 const T_int max_int = std::numeric_limits<T_int>::max();
6542 const T_int min_int = std::numeric_limits<T_int>::min();
6543 if (std::isnan(element)) {
6545 }
else if (element < min_int || element >
static_cast<T_fp
>(max_int)) {
6546 *dst = element >
static_cast<T_fp
>(max_int) ? max_int : min_int;
6548 sim->round_according_to_msacsr<T_fp, T_int>(element, &element, dst);
6553 T_fp element = base::bit_cast<T_fp>(src);
6554 const T_uint max_uint = std::numeric_limits<T_uint>::max();
6555 if (std::isnan(element)) {
6557 }
else if (element < 0 || element >
static_cast<T_fp
>(max_uint)) {
6558 *dst = element >
static_cast<T_fp
>(max_uint) ? max_uint : 0;
6561 sim->round_according_to_msacsr<T_fp, T_uint>(element, &element, &res);
6562 *dst = *
reinterpret_cast<T_int*
>(&res);
6567 *dst = base::bit_cast<T_int>(
static_cast<T_fp
>(src));
6570 using uT_src =
typename std::make_unsigned<T_src>::type;
6572 base::bit_cast<T_int>(
static_cast<T_fp
>(base::bit_cast<uT_src>(src)));
6580template <
typename T_
int,
typename T_fp,
typename T_reg>
6581T_int Msa2RFInstrHelper2(uint32_t opcode, T_reg ws,
int i) {
6583#define EXTRACT_FLOAT16_SIGN(fp16) (fp16 >> 15)
6584#define EXTRACT_FLOAT16_EXP(fp16) (fp16 >> 10 & 0x1F)
6585#define EXTRACT_FLOAT16_FRAC(fp16) (fp16 & 0x3FF)
6586#define PACK_FLOAT32(sign, exp, frac) \
6587 static_cast<uint32_t>(((sign) << 31) + ((exp) << 23) + (frac))
6588#define FEXUP_DF(src_index) \
6589 uint_fast16_t element = ws.uh[src_index]; \
6590 uint_fast32_t aSign, aFrac; \
6591 int_fast32_t aExp; \
6592 aSign = EXTRACT_FLOAT16_SIGN(element); \
6593 aExp = EXTRACT_FLOAT16_EXP(element); \
6594 aFrac = EXTRACT_FLOAT16_FRAC(element); \
6595 if (V8_LIKELY(aExp && aExp != 0x1F)) { \
6596 return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \
6597 } else if (aExp == 0x1F) { \
6599 return base::bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN()); \
6601 return base::bit_cast<uint32_t>( \
6602 std::numeric_limits<float>::infinity()) | \
6603 static_cast<uint32_t>(aSign) << 31; \
6607 return PACK_FLOAT32(aSign, 0, 0); \
6609 int_fast16_t shiftCount = \
6610 base::bits::CountLeadingZeros32(static_cast<uint32_t>(aFrac)) - 21; \
6611 aFrac <<= shiftCount; \
6612 aExp = -shiftCount; \
6613 return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \
6617 if (std::is_same<int32_t, T_int>::value) {
6618 FEXUP_DF(
i + kMSALanesWord)
6620 return base::bit_cast<int64_t>(
static_cast<double>(
6621 base::bit_cast<float>(ws.w[
i + kMSALanesDword])));
6624 if (std::is_same<int32_t, T_int>::value) {
6627 return base::bit_cast<int64_t>(
6628 static_cast<double>(base::bit_cast<float>(ws.w[
i])));
6631 if (std::is_same<int32_t, T_int>::value) {
6632 return base::bit_cast<int32_t>(
6633 static_cast<float>(ws.h[
i + kMSALanesWord]) / (1U << 15));
6635 return base::bit_cast<int64_t>(
6636 static_cast<double>(ws.w[
i + kMSALanesDword]) / (1U << 31));
6641 if (std::is_same<int32_t, T_int>::value) {
6642 return base::bit_cast<int32_t>(
static_cast<float>(ws.h[
i]) /
6645 return base::bit_cast<int64_t>(
static_cast<double>(ws.w[
i]) /
6653#undef EXTRACT_FLOAT16_SIGN
6654#undef EXTRACT_FLOAT16_EXP
6655#undef EXTRACT_FLOAT16_FRAC
6660void Simulator::DecodeTypeMsa2RF() {
6662 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
6663 uint32_t opcode = instr_.InstructionBits() &
kMsa2RFMask;
6665 get_msa_register(ws_reg(), &ws);
6666 if (opcode == FEXUPL || opcode == FEXUPR || opcode == FFQL ||
6668 switch (DecodeMsaDataFormat()) {
6671 wd.w[
i] = Msa2RFInstrHelper2<int32_t, float>(opcode, ws,
i);
6676 wd.d[
i] = Msa2RFInstrHelper2<int64_t, double>(opcode, ws,
i);
6683 switch (DecodeMsaDataFormat()) {
6686 Msa2RFInstrHelper<int32_t, float>(opcode, ws.w[
i], &wd.w[
i],
this);
6691 Msa2RFInstrHelper<int64_t, double>(opcode, ws.d[
i], &wd.d[
i],
this);
6698 set_msa_register(wd_reg(), &wd);
6702void Simulator::DecodeTypeRegister() {
6704 switch (instr_.OpcodeFieldRaw()) {
6706 DecodeTypeRegisterCOP1();
6709 DecodeTypeRegisterCOP1X();
6712 DecodeTypeRegisterSPECIAL();
6715 DecodeTypeRegisterSPECIAL2();
6718 DecodeTypeRegisterSPECIAL3();
6721 switch (instr_.MSAMinorOpcodeField()) {
6753void Simulator::DecodeTypeImmediate() {
6755 Opcode op = instr_.OpcodeFieldRaw();
6756 int32_t rs_reg = instr_.RsValue();
6757 int64_t rs = get_register(instr_.RsValue());
6758 uint64_t rs_u =
static_cast<uint64_t
>(rs);
6759 int32_t rt_reg = instr_.RtValue();
6760 int64_t rt = get_register(rt_reg);
6761 int16_t imm16 = instr_.Imm16Value();
6762 int32_t imm18 = instr_.Imm18Value();
6764 int32_t ft_reg = instr_.FtValue();
6767 uint64_t oe_imm16 = 0xFFFF & imm16;
6769 int64_t se_imm16 = imm16;
6770 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xFFFFFFFFFFFC0000 : 0);
6773 int64_t next_pc = bad_ra;
6776 bool execute_branch_delay_instruction =
false;
6779 int64_t alu_out = 0;
6784 const int kInt32AlignmentMask =
sizeof(uint32_t) - 1;
6786 const int kInt64AlignmentMask =
sizeof(uint64_t) - 1;
6789 auto BranchAndLinkHelper =
6790 [
this, &next_pc, &execute_branch_delay_instruction](
bool do_branch) {
6791 execute_branch_delay_instruction =
true;
6792 int64_t current_pc = get_pc();
6793 set_register(31, current_pc + 2 * kInstrSize);
6795 int16_t imm16 = instr_.Imm16Value();
6796 next_pc = current_pc + (imm16 << 2) + kInstrSize;
6802 auto BranchHelper = [
this, &next_pc,
6803 &execute_branch_delay_instruction](
bool do_branch) {
6804 execute_branch_delay_instruction =
true;
6805 int64_t current_pc = get_pc();
6807 int16_t imm16 = instr_.Imm16Value();
6808 next_pc = current_pc + (imm16 << 2) + kInstrSize;
6814 auto BranchHelper_MSA = [
this, &next_pc, imm16,
6815 &execute_branch_delay_instruction](
bool do_branch) {
6816 execute_branch_delay_instruction =
true;
6817 int64_t current_pc = get_pc();
6838 auto BranchAndLinkCompactHelper = [
this, &next_pc](
bool do_branch,
int bits) {
6839 int64_t current_pc = get_pc();
6840 CheckForbiddenSlot(current_pc);
6842 int32_t imm = instr_.ImmValue(bits);
6845 next_pc = current_pc + (imm << 2) + kInstrSize;
6846 set_register(31, current_pc + kInstrSize);
6850 auto BranchCompactHelper = [
this, &next_pc](
bool do_branch,
int bits) {
6851 int64_t current_pc = get_pc();
6852 CheckForbiddenSlot(current_pc);
6854 int32_t imm = instr_.ImmValue(bits);
6857 next_pc = get_pc() + (imm << 2) + kInstrSize;
6864 switch (instr_.RsFieldRaw()) {
6866 uint32_t
cc = instr_.FBccValue();
6867 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
6868 uint32_t cc_value = test_fcsr_bit(fcsr_cc);
6869 bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value;
6870 BranchHelper(do_branch);
6874 BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
6877 BranchHelper(get_fpu_register(ft_reg) & 0x1);
6881 get_msa_register(wt_reg(), &wt);
6882 BranchHelper_MSA(wt.d[0] == 0 && wt.d[1] == 0);
6884#define BZ_DF(witdh, lanes) \
6887 get_msa_register(wt_reg(), &wt); \
6889 for (i = 0; i < lanes; ++i) { \
6890 if (wt.witdh[i] == 0) { \
6894 BranchHelper_MSA(i != lanes); \
6897 BZ_DF(b, kMSALanesByte)
6900 BZ_DF(h, kMSALanesHalf)
6903 BZ_DF(w, kMSALanesWord)
6906 BZ_DF(d, kMSALanesDword)
6911 get_msa_register(wt_reg(), &wt);
6912 BranchHelper_MSA(wt.d[0] != 0 || wt.d[1] != 0);
6914#define BNZ_DF(witdh, lanes) \
6917 get_msa_register(wt_reg(), &wt); \
6919 for (i = 0; i < lanes; ++i) { \
6920 if (wt.witdh[i] == 0) { \
6924 BranchHelper_MSA(i == lanes); \
6927 BNZ_DF(b, kMSALanesByte)
6930 BNZ_DF(h, kMSALanesHalf)
6933 BNZ_DF(w, kMSALanesWord)
6936 BNZ_DF(d, kMSALanesDword)
6945 switch (instr_.RtFieldRaw()) {
6947 BranchHelper(rs < 0);
6950 BranchHelper(rs >= 0);
6953 BranchAndLinkHelper(rs < 0);
6956 BranchAndLinkHelper(rs >= 0);
6959 SetResult(rs_reg, rs + (se_imm16 << 32));
6962 SetResult(rs_reg, rs + (se_imm16 << 48));
6972 BranchHelper(rs == rt);
6975 BranchHelper(rs != rt);
6981 BranchAndLinkCompactHelper(rt <= 0, 16);
6983 if (rs_reg == rt_reg) {
6984 BranchAndLinkCompactHelper(rt >= 0, 16);
6986 BranchCompactHelper(
6987 static_cast<uint64_t
>(rs) >=
static_cast<uint64_t
>(rt), 16);
6991 BranchHelper(rs <= 0);
6994 BranchHelper(rs <= 0);
7001 BranchAndLinkCompactHelper(rt > 0, 16);
7003 if (rt_reg == rs_reg) {
7004 BranchAndLinkCompactHelper(rt < 0, 16);
7006 BranchCompactHelper(
7007 static_cast<uint64_t
>(rs) <
static_cast<uint64_t
>(rt), 16);
7011 BranchHelper(rs > 0);
7014 BranchHelper(rs > 0);
7021 BranchCompactHelper(rt <= 0, 16);
7023 if (rs_reg == rt_reg) {
7024 BranchCompactHelper(rt >= 0, 16);
7026 BranchCompactHelper(rs >= rt, 16);
7031 BranchAndLinkHelper(rs <= 0);
7038 BranchCompactHelper(rt > 0, 16);
7040 if (rs_reg == rt_reg) {
7041 BranchCompactHelper(rt < 0, 16);
7043 BranchCompactHelper(rs < rt, 16);
7048 BranchAndLinkHelper(rs > 0);
7053 BranchCompactHelper(rs == 0, 21);
7055 next_pc = rt + imm16;
7060 BranchCompactHelper(rs != 0, 21);
7062 int64_t current_pc = get_pc();
7063 set_register(31, current_pc + kInstrSize);
7064 next_pc = rt + imm16;
7068 BranchCompactHelper(
true, 26);
7071 BranchAndLinkCompactHelper(
true, 26);
7075 if (rs_reg >= rt_reg) {
7076 bool condition = !is_int32(rs) || !is_int32(rt) || !is_int32(rs + rt);
7080 BranchAndLinkCompactHelper(rt == 0, 16);
7082 BranchCompactHelper(rt == rs, 16);
7086 if (HaveSameSign(rs, se_imm16)) {
7088 if (rs <= Registers::kMaxValue - se_imm16) {
7089 SignalException(kIntegerOverflow);
7091 }
else if (rs < 0) {
7092 if (rs >= Registers::kMinValue - se_imm16) {
7093 SignalException(kIntegerUnderflow);
7097 SetResult(rt_reg, rs + se_imm16);
7102 if (rs_reg >= rt_reg) {
7103 bool condition = is_int32(rs) && is_int32(rt) && is_int32(rs + rt);
7107 BranchAndLinkCompactHelper(rt != 0, 16);
7109 BranchCompactHelper(rt != rs, 16);
7118 SetResult(rt_reg,
static_cast<int64_t
>(alu32_out));
7122 SetResult(rt_reg, rs + se_imm16);
7125 SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
7128 SetResult(rt_reg, rs_u <
static_cast<uint64_t
>(se_imm16) ? 1 : 0);
7131 SetResult(rt_reg, rs & oe_imm16);
7134 SetResult(rt_reg, rs | oe_imm16);
7137 SetResult(rt_reg, rs ^ oe_imm16);
7144 SetResult(rt_reg,
static_cast<int64_t
>(alu32_out));
7149 SetResult(rt_reg,
static_cast<int64_t
>(alu32_out));
7155 SetResult(rt_reg, rs + (se_imm16 << 16));
7159 set_register(rt_reg, ReadB(rs + se_imm16));
7162 set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr()));
7165 local_monitor_.NotifyLoad();
7167 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
7168 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
7169 uint32_t
mask = (1 << byte_shift * 8) - 1;
7170 addr = rs + se_imm16 - al_offset;
7171 int32_t val = ReadW(addr, instr_.instr());
7172 val <<= byte_shift * 8;
7174 set_register(rt_reg,
static_cast<int64_t
>(val));
7178 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
7181 set_register(rt_reg, ReadWU(rs + se_imm16, instr_.instr()));
7184 set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr()));
7187 set_register(rt_reg, ReadBU(rs + se_imm16));
7190 set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr()));
7194 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
7195 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
7196 uint32_t
mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
7197 addr = rs + se_imm16 - al_offset;
7198 alu_out = ReadW(addr, instr_.instr());
7199 alu_out =
static_cast<uint32_t
>(alu_out) >> al_offset * 8;
7200 alu_out |= rt &
mask;
7201 set_register(rt_reg, alu_out);
7206 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7207 uint8_t byte_shift = kInt64AlignmentMask - al_offset;
7208 uint64_t
mask = (1UL << byte_shift * 8) - 1;
7209 addr = rs + se_imm16 - al_offset;
7210 alu_out = Read2W(addr, instr_.instr());
7211 alu_out <<= byte_shift * 8;
7212 alu_out |= rt &
mask;
7213 set_register(rt_reg, alu_out);
7218 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7219 uint8_t byte_shift = kInt64AlignmentMask - al_offset;
7220 uint64_t
mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL;
7221 addr = rs + se_imm16 - al_offset;
7222 alu_out = Read2W(addr, instr_.instr());
7223 alu_out = alu_out >> al_offset * 8;
7224 alu_out |= rt &
mask;
7225 set_register(rt_reg, alu_out);
7229 WriteB(rs + se_imm16,
static_cast<int8_t
>(rt));
7232 WriteH(rs + se_imm16,
static_cast<uint16_t>(rt), instr_.instr());
7235 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
7236 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
7237 uint32_t
mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
7238 addr = rs + se_imm16 - al_offset;
7239 uint64_t mem_value = ReadW(addr, instr_.instr()) &
mask;
7240 mem_value |=
static_cast<uint32_t
>(rt) >> byte_shift * 8;
7241 WriteW(addr,
static_cast<int32_t>(mem_value), instr_.instr());
7245 WriteW(rs + se_imm16,
static_cast<int32_t>(rt), instr_.instr());
7248 Write2W(rs + se_imm16, rt, instr_.instr());
7251 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
7252 uint32_t
mask = (1 << al_offset * 8) - 1;
7253 addr = rs + se_imm16 - al_offset;
7254 uint64_t mem_value = ReadW(addr, instr_.instr());
7255 mem_value = (rt << al_offset * 8) | (mem_value &
mask);
7256 WriteW(addr,
static_cast<int32_t>(mem_value), instr_.instr());
7260 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7261 uint8_t byte_shift = kInt64AlignmentMask - al_offset;
7262 uint64_t
mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0;
7263 addr = rs + se_imm16 - al_offset;
7264 uint64_t mem_value = Read2W(addr, instr_.instr()) &
mask;
7265 mem_value |=
static_cast<uint64_t
>(rt) >> byte_shift * 8;
7266 Write2W(addr, mem_value, instr_.instr());
7270 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7271 uint64_t
mask = (1UL << al_offset * 8) - 1;
7272 addr = rs + se_imm16 - al_offset;
7273 uint64_t mem_value = Read2W(addr, instr_.instr());
7274 mem_value = (rt << al_offset * 8) | (mem_value &
mask);
7275 Write2W(addr, mem_value, instr_.instr());
7280 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
7281 addr = rs + se_imm16;
7282 set_register(rt_reg, ReadW(addr, instr_.instr()));
7283 local_monitor_.NotifyLoadLinked(addr, TransactionSize::Word);
7284 GlobalMonitor::Get()->NotifyLoadLinked_Locked(addr,
7285 &global_monitor_thread_);
7290 addr = rs + se_imm16;
7291 WriteConditionalW(addr,
static_cast<int32_t>(rt), instr_.instr(), rt_reg);
7296 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
7297 addr = rs + se_imm16;
7298 set_register(rt_reg, Read2W(addr, instr_.instr()));
7299 local_monitor_.NotifyLoadLinked(addr, TransactionSize::DoubleWord);
7300 GlobalMonitor::Get()->NotifyLoadLinked_Locked(addr,
7301 &global_monitor_thread_);
7306 addr = rs + se_imm16;
7307 WriteConditional2W(addr, rt, instr_.instr(), rt_reg);
7311 set_fpu_register(ft_reg, kFPUInvalidResult);
7312 set_fpu_register_word(ft_reg,
7313 ReadW(rs + se_imm16, instr_.instr(), FLOAT_DOUBLE));
7316 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr()));
7317 TraceMemRd(addr, get_fpu_register(ft_reg), DOUBLE);
7320 int32_t alu_out_32 =
static_cast<int32_t>(get_fpu_register(ft_reg));
7321 WriteW(rs + se_imm16, alu_out_32, instr_.instr());
7325 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr());
7326 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg),
DWORD);
7331 int32_t imm21 = instr_.Imm21Value();
7332 int64_t current_pc = get_pc();
7336 addr = current_pc + (se_imm16 << 16);
7337 alu_out =
static_cast<int64_t
>(~0x0FFFF) & addr;
7340 alu_out = current_pc + (se_imm16 << 16);
7343 int32_t imm19 = instr_.Imm19Value();
7349 (current_pc &
static_cast<int64_t
>(~0x7)) + (se_imm18 << 3);
7350 alu_out = Read2W(addr, instr_.instr());
7360 addr = current_pc + (imm19 << 2);
7361 alu_out = ReadWU(addr, instr_.instr());
7368 addr = current_pc + (imm19 << 2);
7369 alu_out = ReadW(addr, instr_.instr());
7374 imm19 | ((imm19 & 0x40000) ? 0xFFFFFFFFFFF80000 : 0);
7375 alu_out = current_pc + (se_imm19 << 2);
7387 SetResult(rs_reg, alu_out);
7391 switch (instr_.FunctionFieldRaw()) {
7394 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
7395 int64_t
base = get_register(instr_.BaseValue());
7396 int32_t offset9 = instr_.Imm9Value();
7397 addr =
base + offset9;
7399 set_register(rt_reg, ReadW(addr, instr_.instr()));
7400 local_monitor_.NotifyLoadLinked(addr, TransactionSize::Word);
7401 GlobalMonitor::Get()->NotifyLoadLinked_Locked(
7402 addr, &global_monitor_thread_);
7407 base::MutexGuard lock_guard(&GlobalMonitor::Get()->
mutex);
7408 int64_t
base = get_register(instr_.BaseValue());
7409 int32_t offset9 = instr_.Imm9Value();
7410 addr =
base + offset9;
7411 DCHECK_EQ(addr & kPointerAlignmentMask, 0);
7412 set_register(rt_reg, Read2W(addr, instr_.instr()));
7413 local_monitor_.NotifyLoadLinked(addr, TransactionSize::DoubleWord);
7414 GlobalMonitor::Get()->NotifyLoadLinked_Locked(
7415 addr, &global_monitor_thread_);
7420 int64_t
base = get_register(instr_.BaseValue());
7421 int32_t offset9 = instr_.Imm9Value();
7422 addr =
base + offset9;
7424 WriteConditionalW(addr,
static_cast<int32_t>(rt), instr_.instr(),
7430 int64_t
base = get_register(instr_.BaseValue());
7431 int32_t offset9 = instr_.Imm9Value();
7432 addr =
base + offset9;
7433 DCHECK_EQ(addr & kPointerAlignmentMask, 0);
7434 WriteConditional2W(addr, rt, instr_.instr(), rt_reg);
7444 switch (instr_.MSAMinorOpcodeField()) {
7461 DecodeTypeMsaMI10();
7471 if (execute_branch_delay_instruction) {
7475 Instruction* branch_delay_instr =
7476 reinterpret_cast<Instruction*
>(get_pc() +
kInstrSize);
7477 BranchDelayInstructionDecode(branch_delay_instr);
7481 if (next_pc != bad_ra) {
7487void Simulator::DecodeTypeJump() {
7490 bool isLinkingInstr = instr_.IsLinkingInstruction();
7492 int64_t current_pc = get_pc();
7494 int64_t pc_high_bits = current_pc & 0xFFFFFFFFF0000000;
7496 int64_t next_pc = pc_high_bits | (instr_.Imm26Value() << 2);
7501 Instruction* branch_delay_instr =
7502 reinterpret_cast<Instruction*
>(current_pc +
kInstrSize);
7503 BranchDelayInstructionDecode(branch_delay_instr);
7507 if (isLinkingInstr) {
7508 set_register(31, current_pc + 2 * kInstrSize);
7511 pc_modified_ =
true;
7515void Simulator::InstructionDecode(Instruction*
instr) {
7517 CheckICache(i_cache(),
instr);
7519 pc_modified_ =
false;
7524 base::SNPrintF(trace_buf_,
" ");
7528 dasm.InstructionDecode(buffer,
reinterpret_cast<uint8_t*
>(
instr));
7532 switch (instr_.InstructionType()) {
7533 case Instruction::kRegisterType:
7534 DecodeTypeRegister();
7536 case Instruction::kImmediateType:
7537 DecodeTypeImmediate();
7539 case Instruction::kJumpType:
7547 PrintF(
" 0x%08" PRIxPTR
" %-44s %s\n",
7548 reinterpret_cast<intptr_t
>(
instr), buffer.
begin(),
7549 trace_buf_.begin());
7552 if (!pc_modified_) {
7553 set_register(
pc,
reinterpret_cast<int64_t
>(
instr) + kInstrSize);
7557void Simulator::Execute() {
7560 int64_t program_counter = get_pc();
7564 while (program_counter != end_sim_pc) {
7565 Instruction*
instr =
reinterpret_cast<Instruction*
>(program_counter);
7567 InstructionDecode(
instr);
7568 program_counter = get_pc();
7573 while (program_counter != end_sim_pc) {
7574 Instruction*
instr =
reinterpret_cast<Instruction*
>(program_counter);
7576 if (icount_ ==
static_cast<int64_t
>(
v8_flags.stop_sim_at)) {
7577 MipsDebugger dbg(
this);
7580 InstructionDecode(
instr);
7582 program_counter = get_pc();
7587void Simulator::CallInternal(Address entry) {
7589 isolate_->stack_guard()->AdjustStackLimitForSimulator();
7592 set_register(
pc,
static_cast<int64_t
>(entry));
7596 set_register(ra, end_sim_pc);
7601 int64_t s0_val = get_register(s0);
7602 int64_t s1_val = get_register(s1);
7603 int64_t s2_val = get_register(s2);
7604 int64_t s3_val = get_register(s3);
7605 int64_t s4_val = get_register(s4);
7606 int64_t s5_val = get_register(s5);
7607 int64_t s6_val = get_register(s6);
7608 int64_t s7_val = get_register(s7);
7609 int64_t gp_val = get_register(gp);
7610 int64_t sp_val = get_register(sp);
7611 int64_t fp_val = get_register(fp);
7615 int64_t callee_saved_value = icount_;
7616 set_register(s0, callee_saved_value);
7617 set_register(s1, callee_saved_value);
7618 set_register(s2, callee_saved_value);
7619 set_register(s3, callee_saved_value);
7620 set_register(s4, callee_saved_value);
7621 set_register(s5, callee_saved_value);
7622 set_register(s6, callee_saved_value);
7623 set_register(s7, callee_saved_value);
7624 set_register(gp, callee_saved_value);
7625 set_register(fp, callee_saved_value);
7631 CHECK_EQ(callee_saved_value, get_register(s0));
7632 CHECK_EQ(callee_saved_value, get_register(s1));
7633 CHECK_EQ(callee_saved_value, get_register(s2));
7634 CHECK_EQ(callee_saved_value, get_register(s3));
7635 CHECK_EQ(callee_saved_value, get_register(s4));
7636 CHECK_EQ(callee_saved_value, get_register(s5));
7637 CHECK_EQ(callee_saved_value, get_register(s6));
7638 CHECK_EQ(callee_saved_value, get_register(s7));
7639 CHECK_EQ(callee_saved_value, get_register(gp));
7640 CHECK_EQ(callee_saved_value, get_register(fp));
7643 set_register(s0, s0_val);
7644 set_register(s1, s1_val);
7645 set_register(s2, s2_val);
7646 set_register(s3, s3_val);
7647 set_register(s4, s4_val);
7648 set_register(s5, s5_val);
7649 set_register(s6, s6_val);
7650 set_register(s7, s7_val);
7651 set_register(gp, gp_val);
7652 set_register(sp, sp_val);
7653 set_register(fp, fp_val);
7656void Simulator::CallImpl(Address entry, CallArgument*
args) {
7657 std::vector<int64_t> stack_args(0);
7658 for (
int i = 0; !
args[
i].IsEnd();
i++) {
7659 CallArgument arg =
args[
i];
7662 set_register(
i + 4, arg.
bits());
7665 set_fpu_register(
i + 12, arg.
bits());
7668 DCHECK(arg.IsFP() || arg.IsGP());
7669 stack_args.push_back(arg.bits());
7674 int64_t original_stack = get_register(sp);
7676 int64_t stack_args_size =
7677 stack_args.size() *
sizeof(stack_args[0]) + kCArgsSlotsSize;
7678 int64_t entry_stack = original_stack - stack_args_size;
7680 if (base::OS::ActivationFrameAlignment() != 0) {
7681 entry_stack &= -base::OS::ActivationFrameAlignment();
7684 char* stack_argument =
reinterpret_cast<char*
>(entry_stack);
7685 memcpy(stack_argument + kCArgSlotCount, stack_args.data(),
7686 stack_args.size() *
sizeof(int64_t));
7687 set_register(sp, entry_stack);
7689 CallInternal(entry);
7692 CHECK_EQ(entry_stack, get_register(sp));
7693 set_register(sp, original_stack);
7696double Simulator::CallFP(Address entry,
double d0,
double d1) {
7698 const FPURegister fparg2 = f13;
7699 set_fpu_register_double(f12, d0);
7700 set_fpu_register_double(fparg2, d1);
7703 DCHECK(
sizeof(buffer[0]) * 2 ==
sizeof(d0));
7704 memcpy(buffer, &d0,
sizeof(d0));
7705 set_dw_register(a0, buffer);
7706 memcpy(buffer, &d1,
sizeof(d1));
7707 set_dw_register(a2, buffer);
7709 CallInternal(entry);
7711 return get_fpu_register_double(f0);
7713 return get_double_from_register_pair(v0);
7717uintptr_t Simulator::PushAddress(uintptr_t address) {
7718 int64_t new_sp = get_register(sp) -
sizeof(uintptr_t);
7719 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(new_sp);
7720 *stack_slot = address;
7721 set_register(sp, new_sp);
7725uintptr_t Simulator::PopAddress() {
7726 int64_t current_sp = get_register(sp);
7727 uintptr_t* stack_slot =
reinterpret_cast<uintptr_t*
>(current_sp);
7728 uintptr_t address = *stack_slot;
7729 set_register(sp, current_sp +
sizeof(uintptr_t));
7733Simulator::LocalMonitor::LocalMonitor()
7734 : access_state_(MonitorAccess::Open),
7738void Simulator::LocalMonitor::Clear() {
7739 access_state_ = MonitorAccess::Open;
7741 size_ = TransactionSize::None;
7744void Simulator::LocalMonitor::NotifyLoad() {
7745 if (access_state_ == MonitorAccess::RMW) {
7752void Simulator::LocalMonitor::NotifyLoadLinked(uintptr_t addr,
7753 TransactionSize size) {
7754 access_state_ = MonitorAccess::RMW;
7755 tagged_addr_ = addr;
7759void Simulator::LocalMonitor::NotifyStore() {
7760 if (access_state_ == MonitorAccess::RMW) {
7767bool Simulator::LocalMonitor::NotifyStoreConditional(uintptr_t addr,
7768 TransactionSize size) {
7769 if (access_state_ == MonitorAccess::RMW) {
7770 if (addr == tagged_addr_ &&
size_ == size) {
7777 DCHECK(access_state_ == MonitorAccess::Open);
7782Simulator::GlobalMonitor::LinkedAddress::LinkedAddress()
7783 : access_state_(MonitorAccess::Open),
7787 failure_counter_(0) {}
7789void Simulator::GlobalMonitor::LinkedAddress::Clear_Locked() {
7790 access_state_ = MonitorAccess::Open;
7794void Simulator::GlobalMonitor::LinkedAddress::NotifyLoadLinked_Locked(
7796 access_state_ = MonitorAccess::RMW;
7797 tagged_addr_ = addr;
7800void Simulator::GlobalMonitor::LinkedAddress::NotifyStore_Locked() {
7801 if (access_state_ == MonitorAccess::RMW) {
7808bool Simulator::GlobalMonitor::LinkedAddress::NotifyStoreConditional_Locked(
7809 uintptr_t addr,
bool is_requesting_thread) {
7810 if (access_state_ == MonitorAccess::RMW) {
7811 if (is_requesting_thread) {
7812 if (addr == tagged_addr_) {
7817 if (failure_counter_++ >= kMaxFailureCounter) {
7818 failure_counter_ = 0;
7824 }
else if ((addr & kExclusiveTaggedAddrMask) ==
7825 (tagged_addr_ & kExclusiveTaggedAddrMask)) {
7836void Simulator::GlobalMonitor::NotifyLoadLinked_Locked(
7837 uintptr_t addr, LinkedAddress* linked_address) {
7838 linked_address->NotifyLoadLinked_Locked(addr);
7839 PrependProcessor_Locked(linked_address);
7842void Simulator::GlobalMonitor::NotifyStore_Locked(
7843 LinkedAddress* linked_address) {
7845 for (LinkedAddress* iter = head_; iter; iter = iter->next_) {
7846 iter->NotifyStore_Locked();
7850bool Simulator::GlobalMonitor::NotifyStoreConditional_Locked(
7851 uintptr_t addr, LinkedAddress* linked_address) {
7852 DCHECK(IsProcessorInLinkedList_Locked(linked_address));
7853 if (linked_address->NotifyStoreConditional_Locked(addr,
true)) {
7855 for (LinkedAddress* iter = head_; iter; iter = iter->next_) {
7856 if (iter != linked_address) {
7857 iter->NotifyStoreConditional_Locked(addr,
false);
7866bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
7867 LinkedAddress* linked_address)
const {
7868 return head_ == linked_address || linked_address->next_ ||
7869 linked_address->prev_;
7872void Simulator::GlobalMonitor::PrependProcessor_Locked(
7873 LinkedAddress* linked_address) {
7874 if (IsProcessorInLinkedList_Locked(linked_address)) {
7879 head_->prev_ = linked_address;
7881 linked_address->prev_ =
nullptr;
7882 linked_address->next_ = head_;
7883 head_ = linked_address;
7886void Simulator::GlobalMonitor::RemoveLinkedAddress(
7887 LinkedAddress* linked_address) {
7888 base::MutexGuard lock_guard(&
mutex);
7889 if (!IsProcessorInLinkedList_Locked(linked_address)) {
7893 if (linked_address->prev_) {
7894 linked_address->prev_->next_ = linked_address->next_;
7896 head_ = linked_address->next_;
7898 if (linked_address->next_) {
7899 linked_address->next_->prev_ = linked_address->prev_;
7901 linked_address->prev_ =
nullptr;
7902 linked_address->next_ =
nullptr;
virtual void VisitPointer(const void *address)=0
TemplateHashMapEntry< void *, void * > Entry
constexpr T * begin() const
static const char * Name(int reg)
static int Number(const char *name)
Instr InstructionBits() const
int Bits(int hi, int lo) const
static int Number(const char *name)
static constexpr int ToInt(const Tagged< Object > object)
const bool IsMipsSoftFloatABI
#define UNIMPLEMENTED_MIPS()
static const ArchVariants kArchVariant
base::Vector< const DirectHandle< Object > > args
#define SC(name, caption)
std::optional< TNode< JSArray > > a
ZoneVector< RpoNumber > & result
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
CustomMatcherTemplateHashMapImpl< DefaultAllocationPolicy > CustomMatcherHashMap
void DeleteArray(T *array)
constexpr MiscInstructionsBits74 CLZ
constexpr VFPRoundingMode kRoundToNearest
constexpr VFPRoundingMode kRoundToMinusInf
constexpr MoveWideImmediateOp MOVZ
constexpr MoveWideImmediateOp MOVN
std::make_unsigned< T >::type Abs(T a)
constexpr int kBitsPerByte
constexpr BarrierOption LD
const uint32_t kFCSRNaN2008FlagMask
void PrintF(const char *format,...)
char * ReadLine(const char *prompt)
const Instr rtCallRedirInstr
constexpr uint32_t kMaxStopCode
const uint32_t kMaxWatchpointCode
constexpr FPDataProcessing2SourceOp FSUB
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
const int kNumFPURegisters
const int kInvalidFPURegister
constexpr FPDataProcessing2SourceOp FMAX
void Print(Tagged< Object > obj)
const int kMsaLongerELMMask
const int kNumSimuRegisters
constexpr VFPRoundingMode kRoundToPlusInf
constexpr Opcode SPECIAL2
const int kInvalidRegister
constexpr FPDataProcessing2SourceOp FDIV
void ShortPrint(Tagged< Object > obj, FILE *out)
constexpr FPDataProcessing2SourceOp FADD
V8_EXPORT_PRIVATE FlagValues v8_flags
const uint32_t kFPURoundingModeMask
constexpr VFPRoundingMode kRoundToZero
constexpr FPDataProcessing2SourceOp FMIN
constexpr uint8_t kInstrSize
constexpr Opcode SPECIAL3
constexpr FPDataProcessing2SourceOp FMUL
constexpr FPDataProcessing1SourceOp FSQRT
V8_WARN_UNUSED_RESULT bool IsValidHeapObject(Heap *heap, Tagged< HeapObject > object)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
base::SmallVector< RegisterT, kStaticCapacity > registers_
const uintptr_t stack_limit_
int Compare(const T &a, const T &b)
#define DCHECK_LE(v1, v2)
#define CHECK_LE(lhs, rhs)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
std::unique_ptr< ValueMirror > value