10 #if V8_TARGET_ARCH_MIPS64 12 #include "src/assembler-inl.h" 13 #include "src/base/bits.h" 14 #include "src/codegen.h" 15 #include "src/disasm.h" 16 #include "src/macro-assembler.h" 17 #include "src/mips64/constants-mips64.h" 18 #include "src/mips64/simulator-mips64.h" 19 #include "src/ostreams.h" 20 #include "src/runtime/runtime-utils.h" 23 #if defined(USE_SIMULATOR) 29 inline bool HaveSameSign(
int64_t a,
int64_t b) {
return ((a ^ b) >= 0); }
50 t = u1 * v0 + (w0 >> 32);
55 return u1 * v1 + w2 + (w1 >> 32);
63 #define SScanF sscanf // NOLINT 69 explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
71 void Stop(Instruction* instr);
75 void PrintAllRegsIncludingFPU();
79 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xFFFFF << 6;
80 static const Instr kNopInstr = 0x0;
84 int64_t GetRegisterValue(
int regnum);
85 int64_t GetFPURegisterValue(
int regnum);
86 float GetFPURegisterValueFloat(
int regnum);
87 double GetFPURegisterValueDouble(
int regnum);
88 bool GetValue(
const char* desc,
int64_t* value);
91 bool SetBreakpoint(Instruction* breakpc);
92 bool DeleteBreakpoint(Instruction* breakpc);
96 void UndoBreakpoints();
97 void RedoBreakpoints();
100 inline void UNSUPPORTED() { printf(
"Sim: Unsupported instruction.\n"); }
102 void MipsDebugger::Stop(Instruction* instr) {
105 PrintF(
"Simulator hit (%u)\n", code);
109 int64_t MipsDebugger::GetRegisterValue(
int regnum) {
110 if (regnum == kNumSimuRegisters) {
111 return sim_->get_pc();
113 return sim_->get_register(regnum);
118 int64_t MipsDebugger::GetFPURegisterValue(
int regnum) {
119 if (regnum == kNumFPURegisters) {
120 return sim_->get_pc();
122 return sim_->get_fpu_register(regnum);
127 float MipsDebugger::GetFPURegisterValueFloat(
int regnum) {
128 if (regnum == kNumFPURegisters) {
129 return sim_->get_pc();
131 return sim_->get_fpu_register_float(regnum);
136 double MipsDebugger::GetFPURegisterValueDouble(
int regnum) {
137 if (regnum == kNumFPURegisters) {
138 return sim_->get_pc();
140 return sim_->get_fpu_register_double(regnum);
145 bool MipsDebugger::GetValue(
const char* desc,
int64_t* value) {
146 int regnum = Registers::Number(desc);
147 int fpuregnum = FPURegisters::Number(desc);
149 if (regnum != kInvalidRegister) {
150 *value = GetRegisterValue(regnum);
152 }
else if (fpuregnum != kInvalidFPURegister) {
153 *value = GetFPURegisterValue(fpuregnum);
155 }
else if (strncmp(desc,
"0x", 2) == 0) {
156 return SScanF(desc + 2,
"%" SCNx64,
157 reinterpret_cast<uint64_t*>(value)) == 1;
159 return SScanF(desc,
"%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
165 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
167 if (sim_->break_pc_ !=
nullptr) {
172 sim_->break_pc_ = breakpc;
173 sim_->break_instr_ = breakpc->InstructionBits();
180 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
181 if (sim_->break_pc_ !=
nullptr) {
182 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
185 sim_->break_pc_ =
nullptr;
186 sim_->break_instr_ = 0;
191 void MipsDebugger::UndoBreakpoints() {
192 if (sim_->break_pc_ !=
nullptr) {
193 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
198 void MipsDebugger::RedoBreakpoints() {
199 if (sim_->break_pc_ !=
nullptr) {
200 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
205 void MipsDebugger::PrintAllRegs() {
206 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 210 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
"\t%3s: 0x%016" PRIx64
" %14" PRId64
211 "\t%3s: 0x%016" PRIx64
" %14" PRId64
"\n",
212 REG_INFO(1), REG_INFO(2), REG_INFO(4));
214 PrintF(
"%34s\t%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
216 "", REG_INFO(3), REG_INFO(5));
218 PrintF(
"%34s\t%34s\t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
"",
"",
221 PrintF(
"%34s\t%34s\t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
"",
"",
225 for (
int i = 0;
i < 8;
i++) {
226 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
228 REG_INFO(8 +
i), REG_INFO(16 +
i));
232 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
233 " %14" PRId64
" \t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
234 REG_INFO(24), REG_INFO(26), REG_INFO(32));
236 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
237 " %14" PRId64
" \t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
238 REG_INFO(25), REG_INFO(27), REG_INFO(33));
240 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
241 " %14" PRId64
" \t%3s: 0x%016" PRIx64
" %14" PRId64
" \n",
242 REG_INFO(29), REG_INFO(30), REG_INFO(28));
244 PrintF(
"%3s: 0x%016" PRIx64
" %14" PRId64
" \t%3s: 0x%016" PRIx64
246 REG_INFO(31), REG_INFO(34));
253 void MipsDebugger::PrintAllRegsIncludingFPU() {
254 #define FPU_REG_INFO(n) FPURegisters::Name(n), \ 255 GetFPURegisterValue(n), \ 256 GetFPURegisterValueDouble(n) 263 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(0));
264 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(1));
265 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(2));
266 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(3));
267 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(4));
268 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(5));
269 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(6));
270 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(7));
271 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(8));
272 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(9));
273 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(10));
274 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(11));
275 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(12));
276 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(13));
277 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(14));
278 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(15));
279 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(16));
280 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(17));
281 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(18));
282 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(19));
283 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(20));
284 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(21));
285 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(22));
286 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(23));
287 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(24));
288 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(25));
289 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(26));
290 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(27));
291 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(28));
292 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(29));
293 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(30));
294 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n", FPU_REG_INFO(31));
301 void MipsDebugger::Debug() {
302 intptr_t last_pc = -1;
305 #define COMMAND_SIZE 63 309 #define XSTR(a) STR(a) 311 char cmd[COMMAND_SIZE + 1];
312 char arg1[ARG_SIZE + 1];
313 char arg2[ARG_SIZE + 1];
314 char* argv[3] = { cmd, arg1, arg2 };
317 cmd[COMMAND_SIZE] = 0;
325 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
326 if (last_pc != sim_->get_pc()) {
331 dasm.InstructionDecode(buffer,
332 reinterpret_cast<byte*>(sim_->get_pc()));
333 PrintF(
" 0x%016" PRIx64
" %s\n", sim_->get_pc(), buffer.start());
334 last_pc = sim_->get_pc();
336 char* line = ReadLine(
"sim> ");
337 if (line ==
nullptr) {
340 char* last_input = sim_->last_debugger_input();
341 if (strcmp(line,
"\n") == 0 && last_input !=
nullptr) {
345 sim_->set_last_debugger_input(line);
349 int argc = SScanF(line,
350 "%" XSTR(COMMAND_SIZE)
"s " 351 "%" XSTR(ARG_SIZE)
"s " 352 "%" XSTR(ARG_SIZE)
"s",
354 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
355 Instruction* instr =
reinterpret_cast<Instruction*
>(sim_->get_pc());
356 if (!(instr->IsTrap()) ||
357 instr->InstructionBits() == rtCallRedirInstr) {
358 sim_->InstructionDecode(
359 reinterpret_cast<Instruction*>(sim_->get_pc()));
362 PrintF(
"/!\\ Jumping over generated breakpoint.\n");
363 sim_->set_pc(sim_->get_pc() + kInstrSize);
365 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
367 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
370 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
374 if (strcmp(arg1,
"all") == 0) {
376 }
else if (strcmp(arg1,
"allf") == 0) {
377 PrintAllRegsIncludingFPU();
379 int regnum = Registers::Number(arg1);
380 int fpuregnum = FPURegisters::Number(arg1);
382 if (regnum != kInvalidRegister) {
383 value = GetRegisterValue(regnum);
384 PrintF(
"%s: 0x%08" PRIx64
" %" PRId64
" \n", arg1, value,
386 }
else if (fpuregnum != kInvalidFPURegister) {
387 value = GetFPURegisterValue(fpuregnum);
388 dvalue = GetFPURegisterValueDouble(fpuregnum);
389 PrintF(
"%3s: 0x%016" PRIx64
" %16.4e\n",
390 FPURegisters::Name(fpuregnum), value, dvalue);
392 PrintF(
"%s unrecognized\n", arg1);
397 if (strcmp(arg2,
"single") == 0) {
400 int fpuregnum = FPURegisters::Number(arg1);
402 if (fpuregnum != kInvalidFPURegister) {
403 value = GetFPURegisterValue(fpuregnum);
404 value &= 0xFFFFFFFFUL;
405 fvalue = GetFPURegisterValueFloat(fpuregnum);
406 PrintF(
"%s: 0x%08" PRIx64
" %11.4e\n", arg1, value, fvalue);
408 PrintF(
"%s unrecognized\n", arg1);
411 PrintF(
"print <fpu register> single\n");
414 PrintF(
"print <register> or print <fpu register> single\n");
417 }
else if ((strcmp(cmd,
"po") == 0)
418 || (strcmp(cmd,
"printobject") == 0)) {
422 if (GetValue(arg1, &value)) {
423 Object* obj =
reinterpret_cast<Object*
>(value);
424 os << arg1 <<
": \n";
429 os << Brief(obj) <<
"\n";
432 os << arg1 <<
" unrecognized\n";
435 PrintF(
"printobject <value>\n");
437 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
442 if (strcmp(cmd,
"stack") == 0) {
443 cur =
reinterpret_cast<int64_t*
>(sim_->get_register(Simulator::sp));
446 if (!GetValue(arg1, &value)) {
447 PrintF(
"%s unrecognized\n", arg1);
450 cur =
reinterpret_cast<int64_t*
>(value);
455 if (argc == next_arg) {
458 if (!GetValue(argv[next_arg], &words)) {
465 PrintF(
" 0x%012" PRIxPTR
" : 0x%016" PRIx64
" %14" PRId64
" ",
466 reinterpret_cast<intptr_t>(cur), *cur, *cur);
467 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
469 Heap* current_heap = sim_->isolate_->heap();
470 if (((value & 1) == 0) || current_heap->Contains(obj)) {
472 if ((value & 1) == 0) {
473 PrintF(
"smi %d", static_cast<int>(value >> 32));
483 }
else if ((strcmp(cmd,
"disasm") == 0) ||
484 (strcmp(cmd,
"dpc") == 0) ||
485 (strcmp(cmd,
"di") == 0)) {
495 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
496 end = cur + (10 * kInstrSize);
497 }
else if (argc == 2) {
498 int regnum = Registers::Number(arg1);
499 if (regnum != kInvalidRegister || strncmp(arg1,
"0x", 2) == 0) {
502 if (GetValue(arg1, &value)) {
503 cur =
reinterpret_cast<byte*
>(value);
505 end = cur + (10 * kInstrSize);
510 if (GetValue(arg1, &value)) {
511 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
513 end = cur + (value * kInstrSize);
519 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
520 cur =
reinterpret_cast<byte*
>(value1);
521 end = cur + (value2 * kInstrSize);
526 dasm.InstructionDecode(buffer, cur);
527 PrintF(
" 0x%08" PRIxPTR
" %s\n", reinterpret_cast<intptr_t>(cur),
531 }
else if (strcmp(cmd,
"gdb") == 0) {
532 PrintF(
"relinquishing control to gdb\n");
533 v8::base::OS::DebugBreak();
534 PrintF(
"regaining control from gdb\n");
535 }
else if (strcmp(cmd,
"break") == 0) {
538 if (GetValue(arg1, &value)) {
539 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
540 PrintF(
"setting breakpoint failed\n");
543 PrintF(
"%s unrecognized\n", arg1);
546 PrintF(
"break <address>\n");
548 }
else if (strcmp(cmd,
"del") == 0) {
549 if (!DeleteBreakpoint(
nullptr)) {
550 PrintF(
"deleting breakpoint failed\n");
552 }
else if (strcmp(cmd,
"flags") == 0) {
553 PrintF(
"No flags on MIPS !\n");
554 }
else if (strcmp(cmd,
"stop") == 0) {
556 intptr_t stop_pc = sim_->get_pc() - 2 * kInstrSize;
557 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
558 Instruction* msg_address =
559 reinterpret_cast<Instruction*
>(stop_pc + kInstrSize);
560 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
562 if (sim_->IsStopInstruction(stop_instr)) {
563 stop_instr->SetInstructionBits(kNopInstr);
564 msg_address->SetInstructionBits(kNopInstr);
566 PrintF(
"Not at debugger stop.\n");
568 }
else if (argc == 3) {
570 if (strcmp(arg1,
"info") == 0) {
571 if (strcmp(arg2,
"all") == 0) {
572 PrintF(
"Stop information:\n");
573 for (
uint32_t i = kMaxWatchpointCode + 1;
576 sim_->PrintStopInfo(
i);
578 }
else if (GetValue(arg2, &value)) {
579 sim_->PrintStopInfo(value);
581 PrintF(
"Unrecognized argument.\n");
583 }
else if (strcmp(arg1,
"enable") == 0) {
585 if (strcmp(arg2,
"all") == 0) {
586 for (
uint32_t i = kMaxWatchpointCode + 1;
591 }
else if (GetValue(arg2, &value)) {
592 sim_->EnableStop(value);
594 PrintF(
"Unrecognized argument.\n");
596 }
else if (strcmp(arg1,
"disable") == 0) {
598 if (strcmp(arg2,
"all") == 0) {
599 for (
uint32_t i = kMaxWatchpointCode + 1;
602 sim_->DisableStop(
i);
604 }
else if (GetValue(arg2, &value)) {
605 sim_->DisableStop(value);
607 PrintF(
"Unrecognized argument.\n");
611 PrintF(
"Wrong usage. Use help command for more information.\n");
613 }
else if ((strcmp(cmd,
"stat") == 0) || (strcmp(cmd,
"st") == 0)) {
627 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
628 end = cur + (10 * kInstrSize);
629 }
else if (argc == 2) {
631 if (GetValue(arg1, &value)) {
632 cur =
reinterpret_cast<byte*
>(value);
634 end = cur + (10 * kInstrSize);
639 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
640 cur =
reinterpret_cast<byte*
>(value1);
641 end = cur + (value2 * kInstrSize);
646 dasm.InstructionDecode(buffer, cur);
647 PrintF(
" 0x%08" PRIxPTR
" %s\n", reinterpret_cast<intptr_t>(cur),
651 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
653 PrintF(
" continue execution (alias 'c')\n");
655 PrintF(
" step one instruction (alias 'si')\n");
656 PrintF(
"print <register>\n");
657 PrintF(
" print register content (alias 'p')\n");
658 PrintF(
" use register name 'all' to print all registers\n");
659 PrintF(
"printobject <register>\n");
660 PrintF(
" print an object from a register (alias 'po')\n");
661 PrintF(
"stack [<words>]\n");
662 PrintF(
" dump stack content, default dump 10 words)\n");
663 PrintF(
"mem <address> [<words>]\n");
664 PrintF(
" dump memory content, default dump 10 words)\n");
666 PrintF(
" print flags\n");
667 PrintF(
"disasm [<instructions>]\n");
668 PrintF(
"disasm [<address/register>]\n");
669 PrintF(
"disasm [[<address/register>] <instructions>]\n");
670 PrintF(
" disassemble code, default is 10 instructions\n");
671 PrintF(
" from pc (alias 'di')\n");
673 PrintF(
" enter gdb\n");
674 PrintF(
"break <address>\n");
675 PrintF(
" set a break point on the address\n");
677 PrintF(
" delete the breakpoint\n");
678 PrintF(
"stop feature:\n");
679 PrintF(
" Description:\n");
680 PrintF(
" Stops are debug instructions inserted by\n");
681 PrintF(
" the Assembler::stop() function.\n");
682 PrintF(
" When hitting a stop, the Simulator will\n");
683 PrintF(
" stop and give control to the Debugger.\n");
684 PrintF(
" All stop codes are watched:\n");
685 PrintF(
" - They can be enabled / disabled: the Simulator\n");
686 PrintF(
" will / won't stop when hitting them.\n");
687 PrintF(
" - The Simulator keeps track of how many times they \n");
688 PrintF(
" are met. (See the info command.) Going over a\n");
689 PrintF(
" disabled stop still increases its counter. \n");
690 PrintF(
" Commands:\n");
691 PrintF(
" stop info all/<code> : print infos about number <code>\n");
692 PrintF(
" or all stop(s).\n");
693 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
694 PrintF(
" all or number <code> stop(s)\n");
695 PrintF(
" stop unstop\n");
696 PrintF(
" ignore the stop instruction at the current location\n");
697 PrintF(
" from now on\n");
699 PrintF(
"Unknown command: %s\n", cmd);
715 bool Simulator::ICacheMatch(
void* one,
void* two) {
716 DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
717 DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
722 static uint32_t ICacheHash(
void* key) {
727 static bool AllOnOnePage(
uintptr_t start,
size_t size) {
728 intptr_t start_page = (start & ~CachePage::kPageMask);
729 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
730 return start_page == end_page;
734 void Simulator::set_last_debugger_input(
char* input) {
735 DeleteArray(last_debugger_input_);
736 last_debugger_input_ = input;
739 void Simulator::SetRedirectInstruction(Instruction* instruction) {
740 instruction->SetInstructionBits(rtCallRedirInstr);
743 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
744 void* start_addr,
size_t size) {
746 int64_t intra_line = (start & CachePage::kLineMask);
749 size = ((size - 1) | CachePage::kLineMask) + 1;
750 int offset = (start & CachePage::kPageMask);
751 while (!AllOnOnePage(start, size - 1)) {
752 int bytes_to_flush = CachePage::kPageSize - offset;
753 FlushOnePage(i_cache, start, bytes_to_flush);
754 start += bytes_to_flush;
755 size -= bytes_to_flush;
756 DCHECK_EQ((
int64_t)0, start & CachePage::kPageMask);
760 FlushOnePage(i_cache, start, size);
764 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
766 base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
767 if (entry->value ==
nullptr) {
768 CachePage* new_page =
new CachePage();
769 entry->value = new_page;
771 return reinterpret_cast<CachePage*
>(entry->value);
776 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
777 intptr_t start,
size_t size) {
778 DCHECK_LE(size, CachePage::kPageSize);
779 DCHECK(AllOnOnePage(start, size - 1));
780 DCHECK_EQ(start & CachePage::kLineMask, 0);
781 DCHECK_EQ(size & CachePage::kLineMask, 0);
782 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
783 int offset = (start & CachePage::kPageMask);
784 CachePage* cache_page = GetCachePage(i_cache, page);
785 char* valid_bytemap = cache_page->ValidityByte(offset);
786 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
789 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
790 Instruction* instr) {
792 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
793 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
794 int offset = (address & CachePage::kPageMask);
795 CachePage* cache_page = GetCachePage(i_cache, page);
796 char* cache_valid_byte = cache_page->ValidityByte(offset);
797 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
798 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
801 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
802 cache_page->CachedData(offset), kInstrSize));
805 memcpy(cached_line, line, CachePage::kLineLength);
806 *cache_valid_byte = CachePage::LINE_VALID;
811 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
814 stack_size_ = FLAG_sim_stack_size * KB;
815 stack_ =
reinterpret_cast<char*
>(malloc(stack_size_));
816 pc_modified_ =
false;
824 for (
int i = 0;
i < kNumSimuRegisters;
i++) {
827 for (
int i = 0;
i < kNumFPURegisters;
i++) {
828 FPUregisters_[2 *
i] = 0;
829 FPUregisters_[2 *
i + 1] = 0;
832 if (kArchVariant == kMips64r6) {
833 FCSR_ = kFCSRNaN2008FlagMask;
842 registers_[sp] =
reinterpret_cast<int64_t>(stack_) + stack_size_ - 64;
845 registers_[pc] = bad_ra;
846 registers_[ra] = bad_ra;
848 last_debugger_input_ =
nullptr;
852 Simulator::~Simulator() { free(stack_); }
856 Simulator* Simulator::current(Isolate* isolate) {
858 isolate->FindOrAllocatePerThreadDataForThisThread();
859 DCHECK_NOT_NULL(isolate_data);
861 Simulator* sim = isolate_data->simulator();
862 if (sim ==
nullptr) {
864 sim =
new Simulator(isolate);
865 isolate_data->set_simulator(sim);
873 void Simulator::set_register(
int reg,
int64_t value) {
874 DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
880 registers_[reg] = (reg == 0) ? 0 : value;
884 void Simulator::set_dw_register(
int reg,
const int* dbl) {
885 DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
886 registers_[reg] = dbl[1];
887 registers_[reg] = registers_[reg] << 32;
888 registers_[reg] += dbl[0];
892 void Simulator::set_fpu_register(
int fpureg,
int64_t value) {
893 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
894 FPUregisters_[fpureg * 2] = value;
898 void Simulator::set_fpu_register_word(
int fpureg, int32_t value) {
900 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
902 if (kArchEndian == kLittle) {
903 pword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]);
905 pword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]) + 1;
911 void Simulator::set_fpu_register_hi_word(
int fpureg, int32_t value) {
913 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
915 if (kArchEndian == kLittle) {
916 phiword = (
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2])) + 1;
918 phiword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]);
924 void Simulator::set_fpu_register_float(
int fpureg,
float value) {
925 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
926 *bit_cast<
float*>(&FPUregisters_[fpureg * 2]) = value;
930 void Simulator::set_fpu_register_double(
int fpureg,
double value) {
931 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
932 *bit_cast<
double*>(&FPUregisters_[fpureg * 2]) = value;
938 int64_t Simulator::get_register(
int reg)
const {
939 DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
943 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
947 double Simulator::get_double_from_register_pair(
int reg) {
949 DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
954 char buffer[
sizeof(registers_[0])];
955 memcpy(buffer, ®isters_[reg],
sizeof(registers_[0]));
956 memcpy(&dm_val, buffer,
sizeof(registers_[0]));
961 int64_t Simulator::get_fpu_register(
int fpureg)
const {
962 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
963 return FPUregisters_[fpureg * 2];
967 int32_t Simulator::get_fpu_register_word(
int fpureg)
const {
968 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
969 return static_cast<int32_t
>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
973 int32_t Simulator::get_fpu_register_signed_word(
int fpureg)
const {
974 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
975 return static_cast<int32_t
>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
979 int32_t Simulator::get_fpu_register_hi_word(
int fpureg)
const {
980 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
981 return static_cast<int32_t
>((FPUregisters_[fpureg * 2] >> 32) & 0xFFFFFFFF);
985 float Simulator::get_fpu_register_float(
int fpureg)
const {
986 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
987 return *bit_cast<
float*>(
const_cast<int64_t*
>(&FPUregisters_[fpureg * 2]));
991 double Simulator::get_fpu_register_double(
int fpureg)
const {
992 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
993 return *bit_cast<
double*>(&FPUregisters_[fpureg * 2]);
996 template <
typename T>
997 void Simulator::get_msa_register(
int wreg, T* value) {
998 DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
999 memcpy(value, FPUregisters_ + wreg * 2, kSimd128Size);
1002 template <
typename T>
1003 void Simulator::set_msa_register(
int wreg,
const T* value) {
1004 DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
1005 memcpy(FPUregisters_ + wreg * 2, value, kSimd128Size);
1011 void Simulator::GetFpArgs(
double* x,
double* y, int32_t* z) {
1012 if (!IsMipsSoftFloatABI) {
1013 const int fparg2 = 13;
1014 *x = get_fpu_register_double(12);
1015 *y = get_fpu_register_double(fparg2);
1016 *z =
static_cast<int32_t
>(get_register(a2));
1021 char buffer[
sizeof(*x)];
1022 int32_t* reg_buffer =
reinterpret_cast<int32_t*
>(buffer);
1025 reg_buffer[0] = get_register(a0);
1026 reg_buffer[1] = get_register(a1);
1027 memcpy(x, buffer,
sizeof(buffer));
1029 reg_buffer[0] = get_register(a2);
1030 reg_buffer[1] = get_register(a3);
1031 memcpy(y, buffer,
sizeof(buffer));
1033 reg_buffer[0] = get_register(a2);
1034 memcpy(z, buffer,
sizeof(*z));
1040 void Simulator::SetFpResult(
const double& result) {
1041 if (!IsMipsSoftFloatABI) {
1042 set_fpu_register_double(0, result);
1044 char buffer[2 *
sizeof(registers_[0])];
1046 memcpy(buffer, &result,
sizeof(buffer));
1048 set_register(v0, reg_buffer[0]);
1049 set_register(v1, reg_buffer[1]);
1055 void Simulator::set_fcsr_bit(
uint32_t cc,
bool value) {
1059 FCSR_ &= ~(1 << cc);
1064 bool Simulator::test_fcsr_bit(
uint32_t cc) {
1065 return FCSR_ & (1 << cc);
1069 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1070 FCSR_ |= mode & kFPURoundingModeMask;
1073 void Simulator::set_msacsr_rounding_mode(FPURoundingMode mode) {
1074 MSACSR_ |= mode & kFPURoundingModeMask;
1077 unsigned int Simulator::get_fcsr_rounding_mode() {
1078 return FCSR_ & kFPURoundingModeMask;
1081 unsigned int Simulator::get_msacsr_rounding_mode() {
1082 return MSACSR_ & kFPURoundingModeMask;
1087 bool Simulator::set_fcsr_round_error(
double original,
double rounded) {
1089 double max_int32 = std::numeric_limits<int32_t>::max();
1090 double min_int32 = std::numeric_limits<int32_t>::min();
1092 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1093 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1097 if (original != rounded) {
1098 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1101 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1102 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1106 if (rounded > max_int32 || rounded < min_int32) {
1107 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1109 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1119 bool Simulator::set_fcsr_round64_error(
double original,
double rounded) {
1123 double max_int64 = std::numeric_limits<int64_t>::max();
1124 double min_int64 = std::numeric_limits<int64_t>::min();
1126 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1127 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1131 if (original != rounded) {
1132 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1135 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1136 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1140 if (rounded >= max_int64 || rounded < min_int64) {
1141 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1143 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1153 bool Simulator::set_fcsr_round_error(
float original,
float rounded) {
1155 double max_int32 = std::numeric_limits<int32_t>::max();
1156 double min_int32 = std::numeric_limits<int32_t>::min();
1158 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1159 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1163 if (original != rounded) {
1164 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1167 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1168 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1172 if (rounded > max_int32 || rounded < min_int32) {
1173 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1175 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1182 void Simulator::set_fpu_register_word_invalid_result(
float original,
1184 if (FCSR_ & kFCSRNaN2008FlagMask) {
1185 double max_int32 = std::numeric_limits<int32_t>::max();
1186 double min_int32 = std::numeric_limits<int32_t>::min();
1187 if (std::isnan(original)) {
1188 set_fpu_register_word(fd_reg(), 0);
1189 }
else if (rounded > max_int32) {
1190 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1191 }
else if (rounded < min_int32) {
1192 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1197 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1202 void Simulator::set_fpu_register_invalid_result(
float original,
float rounded) {
1203 if (FCSR_ & kFCSRNaN2008FlagMask) {
1204 double max_int32 = std::numeric_limits<int32_t>::max();
1205 double min_int32 = std::numeric_limits<int32_t>::min();
1206 if (std::isnan(original)) {
1207 set_fpu_register(fd_reg(), 0);
1208 }
else if (rounded > max_int32) {
1209 set_fpu_register(fd_reg(), kFPUInvalidResult);
1210 }
else if (rounded < min_int32) {
1211 set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1216 set_fpu_register(fd_reg(), kFPUInvalidResult);
1221 void Simulator::set_fpu_register_invalid_result64(
float original,
1223 if (FCSR_ & kFCSRNaN2008FlagMask) {
1226 double max_int64 = std::numeric_limits<int64_t>::max();
1227 double min_int64 = std::numeric_limits<int64_t>::min();
1228 if (std::isnan(original)) {
1229 set_fpu_register(fd_reg(), 0);
1230 }
else if (rounded >= max_int64) {
1231 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1232 }
else if (rounded < min_int64) {
1233 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1238 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1243 void Simulator::set_fpu_register_word_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_word(fd_reg(), 0);
1250 }
else if (rounded > max_int32) {
1251 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1252 }
else if (rounded < min_int32) {
1253 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1258 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1263 void Simulator::set_fpu_register_invalid_result(
double original,
1265 if (FCSR_ & kFCSRNaN2008FlagMask) {
1266 double max_int32 = std::numeric_limits<int32_t>::max();
1267 double min_int32 = std::numeric_limits<int32_t>::min();
1268 if (std::isnan(original)) {
1269 set_fpu_register(fd_reg(), 0);
1270 }
else if (rounded > max_int32) {
1271 set_fpu_register(fd_reg(), kFPUInvalidResult);
1272 }
else if (rounded < min_int32) {
1273 set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1278 set_fpu_register(fd_reg(), kFPUInvalidResult);
1283 void Simulator::set_fpu_register_invalid_result64(
double original,
1285 if (FCSR_ & kFCSRNaN2008FlagMask) {
1288 double max_int64 = std::numeric_limits<int64_t>::max();
1289 double min_int64 = std::numeric_limits<int64_t>::min();
1290 if (std::isnan(original)) {
1291 set_fpu_register(fd_reg(), 0);
1292 }
else if (rounded >= max_int64) {
1293 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1294 }
else if (rounded < min_int64) {
1295 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1300 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1307 bool Simulator::set_fcsr_round64_error(
float original,
float rounded) {
1311 double max_int64 = std::numeric_limits<int64_t>::max();
1312 double min_int64 = std::numeric_limits<int64_t>::min();
1314 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1315 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1319 if (original != rounded) {
1320 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1323 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1324 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1328 if (rounded >= max_int64 || rounded < min_int64) {
1329 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1331 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1340 void Simulator::round_according_to_fcsr(
double toRound,
double& rounded,
1341 int32_t& rounded_int,
double fs) {
1355 switch (FCSR_ & 3) {
1356 case kRoundToNearest:
1357 rounded = std::floor(fs + 0.5);
1358 rounded_int =
static_cast<int32_t
>(rounded);
1359 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1367 rounded = trunc(fs);
1368 rounded_int =
static_cast<int32_t
>(rounded);
1370 case kRoundToPlusInf:
1371 rounded = std::ceil(fs);
1372 rounded_int =
static_cast<int32_t
>(rounded);
1374 case kRoundToMinusInf:
1375 rounded = std::floor(fs);
1376 rounded_int =
static_cast<int32_t
>(rounded);
1382 void Simulator::round64_according_to_fcsr(
double toRound,
double& rounded,
1383 int64_t& rounded_int,
double fs) {
1397 switch (FCSR_ & 3) {
1398 case kRoundToNearest:
1399 rounded = std::floor(fs + 0.5);
1400 rounded_int =
static_cast<int64_t>(rounded);
1401 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1409 rounded = trunc(fs);
1410 rounded_int =
static_cast<int64_t>(rounded);
1412 case kRoundToPlusInf:
1413 rounded = std::ceil(fs);
1414 rounded_int =
static_cast<int64_t>(rounded);
1416 case kRoundToMinusInf:
1417 rounded = std::floor(fs);
1418 rounded_int =
static_cast<int64_t>(rounded);
1425 void Simulator::round_according_to_fcsr(
float toRound,
float& rounded,
1426 int32_t& rounded_int,
float fs) {
1440 switch (FCSR_ & 3) {
1441 case kRoundToNearest:
1442 rounded = std::floor(fs + 0.5);
1443 rounded_int =
static_cast<int32_t
>(rounded);
1444 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1452 rounded = trunc(fs);
1453 rounded_int =
static_cast<int32_t
>(rounded);
1455 case kRoundToPlusInf:
1456 rounded = std::ceil(fs);
1457 rounded_int =
static_cast<int32_t
>(rounded);
1459 case kRoundToMinusInf:
1460 rounded = std::floor(fs);
1461 rounded_int =
static_cast<int32_t
>(rounded);
1467 void Simulator::round64_according_to_fcsr(
float toRound,
float& rounded,
1468 int64_t& rounded_int,
float fs) {
1482 switch (FCSR_ & 3) {
1483 case kRoundToNearest:
1484 rounded = std::floor(fs + 0.5);
1485 rounded_int =
static_cast<int64_t>(rounded);
1486 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1494 rounded = trunc(fs);
1495 rounded_int =
static_cast<int64_t>(rounded);
1497 case kRoundToPlusInf:
1498 rounded = std::ceil(fs);
1499 rounded_int =
static_cast<int64_t>(rounded);
1501 case kRoundToMinusInf:
1502 rounded = std::floor(fs);
1503 rounded_int =
static_cast<int64_t>(rounded);
1508 template <
typename T_fp,
typename T_
int>
1509 void Simulator::round_according_to_msacsr(T_fp toRound, T_fp& rounded,
1510 T_int& rounded_int) {
1524 switch (get_msacsr_rounding_mode()) {
1525 case kRoundToNearest:
1526 rounded = std::floor(toRound + 0.5);
1527 rounded_int =
static_cast<T_int
>(rounded);
1528 if ((rounded_int & 1) != 0 && rounded_int - toRound == 0.5) {
1536 rounded = trunc(toRound);
1537 rounded_int =
static_cast<T_int
>(rounded);
1539 case kRoundToPlusInf:
1540 rounded = std::ceil(toRound);
1541 rounded_int =
static_cast<T_int
>(rounded);
1543 case kRoundToMinusInf:
1544 rounded = std::floor(toRound);
1545 rounded_int =
static_cast<T_int
>(rounded);
1551 void Simulator::set_pc(
int64_t value) {
1552 pc_modified_ =
true;
1553 registers_[pc] = value;
1557 bool Simulator::has_bad_pc()
const {
1558 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1563 int64_t Simulator::get_pc()
const {
1564 return registers_[pc];
1577 void Simulator::DieOrDebug() {
1579 MipsDebugger dbg(
this);
1586 void Simulator::TraceRegWr(
int64_t value, TraceType t) {
1587 if (::v8::internal::FLAG_trace_sim) {
1590 int32_t fmt_int32[2];
1594 v.fmt_int64 = value;
1598 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") int32:%" PRId32
1600 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0]);
1603 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") int64:%" PRId64
1605 value, icount_, value, value);
1608 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") flt:%e",
1609 v.fmt_int64, icount_, v.fmt_float[0]);
1612 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") dbl:%e",
1613 v.fmt_int64, icount_, v.fmt_double);
1616 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRId64
") flt:%e dbl:%e",
1617 v.fmt_int64, icount_, v.fmt_float[0], v.fmt_double);
1620 SNPrintF(trace_buf_,
1621 "%016" PRIx64
" (%" PRId64
") int32:%" PRId32
1622 " uint32:%" PRIu32
" int64:%" PRId64
" uint64:%" PRIu64,
1623 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0],
1624 v.fmt_int64, v.fmt_int64);
1632 template <
typename T>
1633 void Simulator::TraceMSARegWr(T* value, TraceType t) {
1634 if (::v8::internal::FLAG_trace_sim) {
1643 memcpy(v.b, value, kSimd128Size);
1646 SNPrintF(trace_buf_,
1647 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1648 v.d[0], v.d[1], icount_);
1651 SNPrintF(trace_buf_,
1652 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1653 v.d[0], v.d[1], icount_);
1656 SNPrintF(trace_buf_,
1657 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1658 ") int32[0..3]:%" PRId32
" %" PRId32
" %" PRId32
1660 v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1663 SNPrintF(trace_buf_,
1664 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1665 v.d[0], v.d[1], icount_);
1668 SNPrintF(trace_buf_,
1669 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1670 ") flt[0..3]:%e %e %e %e",
1671 v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1674 SNPrintF(trace_buf_,
1675 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1676 ") dbl[0..1]:%e %e",
1677 v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1685 template <
typename T>
1686 void Simulator::TraceMSARegWr(T* value) {
1687 if (::v8::internal::FLAG_trace_sim) {
1689 uint8_t b[kMSALanesByte];
1690 uint16_t h[kMSALanesHalf];
1692 uint64_t d[kMSALanesDword];
1693 float f[kMSALanesWord];
1694 double df[kMSALanesDword];
1696 memcpy(v.b, value, kMSALanesByte);
1698 if (std::is_same<T, int32_t>::value) {
1699 SNPrintF(trace_buf_,
1700 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1701 ") int32[0..3]:%" PRId32
" %" PRId32
" %" PRId32
1703 v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1704 }
else if (std::is_same<T, float>::value) {
1705 SNPrintF(trace_buf_,
1706 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1707 ") flt[0..3]:%e %e %e %e",
1708 v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1709 }
else if (std::is_same<T, double>::value) {
1710 SNPrintF(trace_buf_,
1711 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1712 ") dbl[0..1]:%e %e",
1713 v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1715 SNPrintF(trace_buf_,
1716 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1717 v.d[0], v.d[1], icount_);
1723 void Simulator::TraceMemRd(
int64_t addr,
int64_t value, TraceType t) {
1724 if (::v8::internal::FLAG_trace_sim) {
1727 int32_t fmt_int32[2];
1731 v.fmt_int64 = value;
1735 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1736 ") int32:%" PRId32
" uint32:%" PRIu32,
1737 v.fmt_int64, addr, icount_, v.fmt_int32[0], v.fmt_int32[0]);
1740 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1741 ") int64:%" PRId64
" uint64:%" PRIu64,
1742 value, addr, icount_, value, value);
1745 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1747 v.fmt_int64, addr, icount_, v.fmt_float[0]);
1750 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1752 v.fmt_int64, addr, icount_, v.fmt_double);
1755 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%016" PRIx64
"] (%" PRId64
1757 v.fmt_int64, addr, icount_, v.fmt_float[0], v.fmt_double);
1766 void Simulator::TraceMemWr(
int64_t addr,
int64_t value, TraceType t) {
1767 if (::v8::internal::FLAG_trace_sim) {
1770 SNPrintF(trace_buf_,
" %02" PRIx8
" --> [%016" PRIx64
1772 static_cast<uint8_t>(value), addr, icount_);
1775 SNPrintF(trace_buf_,
" %04" PRIx16
" --> [%016" PRIx64
1777 static_cast<uint16_t>(value), addr, icount_);
1780 SNPrintF(trace_buf_,
1781 " %08" PRIx32
" --> [%016" PRIx64
"] (%" PRId64
")",
1782 static_cast<uint32_t>(value), addr, icount_);
1785 SNPrintF(trace_buf_,
1786 "%016" PRIx64
" --> [%016" PRIx64
"] (%" PRId64
" )",
1787 value, addr, icount_);
1795 template <
typename T>
1796 void Simulator::TraceMemRd(
int64_t addr, T value) {
1797 if (::v8::internal::FLAG_trace_sim) {
1798 switch (
sizeof(T)) {
1800 SNPrintF(trace_buf_,
1801 "%08" PRIx8
" <-- [%08" PRIx64
"] (%" PRIu64
1802 ") int8:%" PRId8
" uint8:%" PRIu8,
1803 static_cast<uint8_t>(value), addr, icount_,
1804 static_cast<int8_t>(value), static_cast<uint8_t>(value));
1807 SNPrintF(trace_buf_,
1808 "%08" PRIx16
" <-- [%08" PRIx64
"] (%" PRIu64
1809 ") int16:%" PRId16
" uint16:%" PRIu16,
1810 static_cast<uint16_t>(value), addr, icount_,
1811 static_cast<int16_t>(value), static_cast<uint16_t>(value));
1814 SNPrintF(trace_buf_,
1815 "%08" PRIx32
" <-- [%08" PRIx64
"] (%" PRIu64
1816 ") int32:%" PRId32
" uint32:%" PRIu32,
1817 static_cast<uint32_t>(value), addr, icount_,
1818 static_cast<int32_t>(value), static_cast<uint32_t>(value));
1821 SNPrintF(trace_buf_,
1822 "%08" PRIx64
" <-- [%08" PRIx64
"] (%" PRIu64
1823 ") int64:%" PRId64
" uint64:%" PRIu64,
1824 static_cast<uint64_t>(value), addr, icount_,
1825 static_cast<int64_t>(value), static_cast<uint64_t>(value));
1833 template <
typename T>
1834 void Simulator::TraceMemWr(
int64_t addr, T value) {
1835 if (::v8::internal::FLAG_trace_sim) {
1836 switch (
sizeof(T)) {
1838 SNPrintF(trace_buf_,
1839 " %02" PRIx8
" --> [%08" PRIx64
"] (%" PRIu64
")",
1840 static_cast<uint8_t>(value), addr, icount_);
1843 SNPrintF(trace_buf_,
1844 " %04" PRIx16
" --> [%08" PRIx64
"] (%" PRIu64
")",
1845 static_cast<uint16_t>(value), addr, icount_);
1848 SNPrintF(trace_buf_,
1849 "%08" PRIx32
" --> [%08" PRIx64
"] (%" PRIu64
")",
1850 static_cast<uint32_t>(value), addr, icount_);
1853 SNPrintF(trace_buf_,
1854 "%16" PRIx64
" --> [%08" PRIx64
"] (%" PRIu64
")",
1855 static_cast<uint64_t>(value), addr, icount_);
1865 int32_t Simulator::ReadW(
int64_t addr, Instruction* instr, TraceType t) {
1866 if (addr >=0 && addr < 0x400) {
1868 PrintF(
"Memory read from bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1870 addr, reinterpret_cast<intptr_t>(instr));
1873 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1874 int32_t* ptr =
reinterpret_cast<int32_t*
>(addr);
1875 TraceMemRd(addr, static_cast<int64_t>(*ptr), t);
1878 PrintF(
"Unaligned read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
"\n", addr,
1879 reinterpret_cast<intptr_t>(instr));
1886 if (addr >=0 && addr < 0x400) {
1888 PrintF(
"Memory read from bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1890 addr, reinterpret_cast<intptr_t>(instr));
1893 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1895 TraceMemRd(addr, static_cast<int64_t>(*ptr), WORD);
1898 PrintF(
"Unaligned read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
"\n", addr,
1899 reinterpret_cast<intptr_t>(instr));
1905 void Simulator::WriteW(
int64_t addr, int32_t value, Instruction* instr) {
1906 if (addr >= 0 && addr < 0x400) {
1908 PrintF(
"Memory write to bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1910 addr, reinterpret_cast<intptr_t>(instr));
1913 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
1914 TraceMemWr(addr, value, WORD);
1915 int* ptr =
reinterpret_cast<int*
>(addr);
1919 PrintF(
"Unaligned write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
"\n", addr,
1920 reinterpret_cast<intptr_t>(instr));
1926 if (addr >=0 && addr < 0x400) {
1928 PrintF(
"Memory read from bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1930 addr, reinterpret_cast<intptr_t>(instr));
1933 if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1935 TraceMemRd(addr, *ptr);
1938 PrintF(
"Unaligned read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
"\n", addr,
1939 reinterpret_cast<intptr_t>(instr));
1945 void Simulator::Write2W(
int64_t addr,
int64_t value, Instruction* instr) {
1946 if (addr >= 0 && addr < 0x400) {
1948 PrintF(
"Memory write to bad address: 0x%08" PRIx64
" , pc=0x%08" PRIxPTR
1950 addr, reinterpret_cast<intptr_t>(instr));
1953 if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1954 TraceMemWr(addr, value, DWORD);
1959 PrintF(
"Unaligned write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
"\n", addr,
1960 reinterpret_cast<intptr_t>(instr));
1965 double Simulator::ReadD(
int64_t addr, Instruction* instr) {
1966 if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1967 double* ptr =
reinterpret_cast<double*
>(addr);
1970 PrintF(
"Unaligned (double) read at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
"\n",
1971 addr, reinterpret_cast<intptr_t>(instr));
1977 void Simulator::WriteD(
int64_t addr,
double value, Instruction* instr) {
1978 if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
1979 double* ptr =
reinterpret_cast<double*
>(addr);
1983 PrintF(
"Unaligned (double) write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
1985 addr, reinterpret_cast<intptr_t>(instr));
1990 uint16_t Simulator::ReadHU(
int64_t addr, Instruction* instr) {
1991 if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
1992 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
1993 TraceMemRd(addr, static_cast<int64_t>(*ptr));
1996 PrintF(
"Unaligned unsigned halfword read at 0x%08" PRIx64
1997 " , pc=0x%08" V8PRIxPTR
"\n",
1998 addr, reinterpret_cast<intptr_t>(instr));
2004 int16_t Simulator::ReadH(
int64_t addr, Instruction* instr) {
2005 if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
2006 int16_t* ptr =
reinterpret_cast<int16_t*
>(addr);
2007 TraceMemRd(addr, static_cast<int64_t>(*ptr));
2010 PrintF(
"Unaligned signed halfword read at 0x%08" PRIx64
2011 " , pc=0x%08" V8PRIxPTR
"\n",
2012 addr, reinterpret_cast<intptr_t>(instr));
2018 void Simulator::WriteH(
int64_t addr, uint16_t value, Instruction* instr) {
2019 if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
2020 TraceMemWr(addr, value, HALF);
2021 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
2025 PrintF(
"Unaligned unsigned halfword write at 0x%08" PRIx64
2026 " , pc=0x%08" V8PRIxPTR
"\n",
2027 addr, reinterpret_cast<intptr_t>(instr));
2032 void Simulator::WriteH(
int64_t addr, int16_t value, Instruction* instr) {
2033 if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
2034 TraceMemWr(addr, value, HALF);
2035 int16_t* ptr =
reinterpret_cast<int16_t*
>(addr);
2039 PrintF(
"Unaligned halfword write at 0x%08" PRIx64
" , pc=0x%08" V8PRIxPTR
2041 addr, reinterpret_cast<intptr_t>(instr));
2047 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
2048 TraceMemRd(addr, static_cast<int64_t>(*ptr));
2053 int32_t Simulator::ReadB(
int64_t addr) {
2054 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
2055 TraceMemRd(addr, static_cast<int64_t>(*ptr));
2060 void Simulator::WriteB(
int64_t addr, uint8_t value) {
2061 TraceMemWr(addr, value, BYTE);
2062 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
2067 void Simulator::WriteB(
int64_t addr, int8_t value) {
2068 TraceMemWr(addr, value, BYTE);
2069 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
2073 template <
typename T>
2074 T Simulator::ReadMem(
int64_t addr, Instruction* instr) {
2075 int alignment_mask = (1 <<
sizeof(T)) - 1;
2076 if ((addr & alignment_mask) == 0 || kArchVariant == kMips64r6) {
2077 T* ptr =
reinterpret_cast<T*
>(addr);
2078 TraceMemRd(addr, *ptr);
2081 PrintF(
"Unaligned read of type sizeof(%ld) at 0x%08lx, pc=0x%08" V8PRIxPTR
2083 sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
2088 template <
typename T>
2089 void Simulator::WriteMem(
int64_t addr, T value, Instruction* instr) {
2090 int alignment_mask = (1 <<
sizeof(T)) - 1;
2091 if ((addr & alignment_mask) == 0 || kArchVariant == kMips64r6) {
2092 T* ptr =
reinterpret_cast<T*
>(addr);
2094 TraceMemWr(addr, value);
2097 PrintF(
"Unaligned write of type sizeof(%ld) at 0x%08lx, pc=0x%08" V8PRIxPTR
2099 sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
2107 if (GetCurrentStackPosition() < c_limit) {
2108 return reinterpret_cast<uintptr_t>(get_sp());
2113 return reinterpret_cast<uintptr_t>(stack_) + 1024;
2118 void Simulator::Format(Instruction* instr,
const char* format) {
2119 PrintF(
"Simulator found unsupported instruction:\n 0x%08" PRIxPTR
" : %s\n",
2120 reinterpret_cast<intptr_t>(instr), format);
2121 UNIMPLEMENTED_MIPS();
2132 typedef ObjectPair (*SimulatorRuntimeCall)(
int64_t arg0,
int64_t arg1,
2139 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
2140 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
2141 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
2142 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0, int32_t arg0);
2146 typedef void (*SimulatorRuntimeDirectApiCall)(
int64_t arg0);
2147 typedef void (*SimulatorRuntimeProfilingApiCall)(
int64_t arg0,
void* arg1);
2150 typedef void (*SimulatorRuntimeDirectGetterCall)(
int64_t arg0,
int64_t arg1);
2151 typedef void (*SimulatorRuntimeProfilingGetterCall)(
2156 void Simulator::SoftwareInterrupt() {
2160 int32_t func = instr_.FunctionFieldRaw();
2161 uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1;
2163 if (instr_.InstructionBits() == rtCallRedirInstr) {
2164 Redirection* redirection = Redirection::FromInstruction(instr_.instr());
2166 int64_t* stack_pointer =
reinterpret_cast<int64_t*
>(get_register(sp));
2168 int64_t arg0 = get_register(a0);
2169 int64_t arg1 = get_register(a1);
2170 int64_t arg2 = get_register(a2);
2171 int64_t arg3 = get_register(a3);
2172 int64_t arg4 = get_register(a4);
2173 int64_t arg5 = get_register(a5);
2174 int64_t arg6 = get_register(a6);
2175 int64_t arg7 = get_register(a7);
2176 int64_t arg8 = stack_pointer[0];
2177 STATIC_ASSERT(kMaxCParameters == 9);
2180 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
2181 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
2182 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
2183 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
2185 if (!IsMipsSoftFloatABI) {
2190 switch (redirection->type()) {
2191 case ExternalReference::BUILTIN_FP_FP_CALL:
2192 case ExternalReference::BUILTIN_COMPARE_CALL:
2193 arg0 = get_fpu_register(f12);
2194 arg1 = get_fpu_register(f13);
2195 arg2 = get_fpu_register(f14);
2196 arg3 = get_fpu_register(f15);
2198 case ExternalReference::BUILTIN_FP_CALL:
2199 arg0 = get_fpu_register(f12);
2200 arg1 = get_fpu_register(f13);
2202 case ExternalReference::BUILTIN_FP_INT_CALL:
2203 arg0 = get_fpu_register(f12);
2204 arg1 = get_fpu_register(f13);
2205 arg2 = get_register(a2);
2214 int64_t saved_ra = get_register(ra);
2217 reinterpret_cast<intptr_t
>(redirection->external_function());
2224 double dval0, dval1;
2228 GetFpArgs(&dval0, &dval1, &ival);
2229 SimulatorRuntimeCall generic_target =
2230 reinterpret_cast<SimulatorRuntimeCall
>(external);
2231 if (::v8::internal::FLAG_trace_sim) {
2232 switch (redirection->type()) {
2233 case ExternalReference::BUILTIN_FP_FP_CALL:
2234 case ExternalReference::BUILTIN_COMPARE_CALL:
2235 PrintF(
"Call to host function at %p with args %f, %f",
2236 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2239 case ExternalReference::BUILTIN_FP_CALL:
2240 PrintF(
"Call to host function at %p with arg %f",
2241 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2244 case ExternalReference::BUILTIN_FP_INT_CALL:
2245 PrintF(
"Call to host function at %p with args %f, %d",
2246 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2254 switch (redirection->type()) {
2255 case ExternalReference::BUILTIN_COMPARE_CALL: {
2256 SimulatorRuntimeCompareCall target =
2257 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
2258 iresult = target(dval0, dval1);
2259 set_register(v0, static_cast<int64_t>(iresult));
2263 case ExternalReference::BUILTIN_FP_FP_CALL: {
2264 SimulatorRuntimeFPFPCall target =
2265 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
2266 dresult = target(dval0, dval1);
2267 SetFpResult(dresult);
2270 case ExternalReference::BUILTIN_FP_CALL: {
2271 SimulatorRuntimeFPCall target =
2272 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
2273 dresult = target(dval0);
2274 SetFpResult(dresult);
2277 case ExternalReference::BUILTIN_FP_INT_CALL: {
2278 SimulatorRuntimeFPIntCall target =
2279 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
2280 dresult = target(dval0, ival);
2281 SetFpResult(dresult);
2288 if (::v8::internal::FLAG_trace_sim) {
2289 switch (redirection->type()) {
2290 case ExternalReference::BUILTIN_COMPARE_CALL:
2291 PrintF(
"Returned %08x\n", static_cast<int32_t>(iresult));
2293 case ExternalReference::BUILTIN_FP_FP_CALL:
2294 case ExternalReference::BUILTIN_FP_CALL:
2295 case ExternalReference::BUILTIN_FP_INT_CALL:
2296 PrintF(
"Returned %f\n", dresult);
2303 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
2304 if (::v8::internal::FLAG_trace_sim) {
2305 PrintF(
"Call to host function at %p args %08" PRIx64
" \n",
2306 reinterpret_cast<void*>(external), arg0);
2308 SimulatorRuntimeDirectApiCall target =
2309 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
2312 redirection->type() == ExternalReference::PROFILING_API_CALL) {
2313 if (::v8::internal::FLAG_trace_sim) {
2314 PrintF(
"Call to host function at %p args %08" PRIx64
" %08" PRIx64
2316 reinterpret_cast<void*>(external), arg0, arg1);
2318 SimulatorRuntimeProfilingApiCall target =
2319 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
2320 target(arg0, Redirection::ReverseRedirection(arg1));
2322 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
2323 if (::v8::internal::FLAG_trace_sim) {
2324 PrintF(
"Call to host function at %p args %08" PRIx64
" %08" PRIx64
2326 reinterpret_cast<void*>(external), arg0, arg1);
2328 SimulatorRuntimeDirectGetterCall target =
2329 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
2332 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
2333 if (::v8::internal::FLAG_trace_sim) {
2334 PrintF(
"Call to host function at %p args %08" PRIx64
" %08" PRIx64
2335 " %08" PRIx64
" \n",
2336 reinterpret_cast<void*>(external), arg0, arg1, arg2);
2338 SimulatorRuntimeProfilingGetterCall target =
2339 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(external);
2340 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
2342 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
2343 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
2344 SimulatorRuntimeCall target =
2345 reinterpret_cast<SimulatorRuntimeCall
>(external);
2346 if (::v8::internal::FLAG_trace_sim) {
2348 "Call to host function at %p " 2349 "args %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2350 " , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
" , %08" PRIx64
2351 " , %08" PRIx64
" \n",
2352 reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2,
2353 arg3, arg4, arg5, arg6, arg7, arg8);
2356 target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
2357 set_register(v0, (
int64_t)(result.x));
2358 set_register(v1, (
int64_t)(result.y));
2360 if (::v8::internal::FLAG_trace_sim) {
2361 PrintF(
"Returned %08" PRIx64
" : %08" PRIx64
" \n", get_register(v1),
2364 set_register(ra, saved_ra);
2365 set_pc(get_register(ra));
2367 }
else if (func == BREAK && code <= kMaxStopCode) {
2368 if (IsWatchpoint(code)) {
2369 PrintWatchpoint(code);
2371 IncreaseStopCounter(code);
2372 HandleStop(code, instr_.instr());
2376 MipsDebugger dbg(
this);
2383 bool Simulator::IsWatchpoint(uint64_t code) {
2384 return (code <= kMaxWatchpointCode);
2388 void Simulator::PrintWatchpoint(uint64_t code) {
2389 MipsDebugger dbg(
this);
2391 PrintF(
"\n---- break %" PRId64
" marker: %3d (instr count: %8" PRId64
2393 "----------------------------------",
2394 code, break_count_, icount_);
2399 void Simulator::HandleStop(uint64_t code, Instruction* instr) {
2402 if (IsEnabledStop(code)) {
2403 MipsDebugger dbg(
this);
2409 bool Simulator::IsStopInstruction(Instruction* instr) {
2410 int32_t func = instr->FunctionFieldRaw();
2412 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
2416 bool Simulator::IsEnabledStop(uint64_t code) {
2417 DCHECK_LE(code, kMaxStopCode);
2418 DCHECK_GT(code, kMaxWatchpointCode);
2419 return !(watched_stops_[code].count & kStopDisabledBit);
2423 void Simulator::EnableStop(uint64_t code) {
2424 if (!IsEnabledStop(code)) {
2425 watched_stops_[code].count &= ~kStopDisabledBit;
2430 void Simulator::DisableStop(uint64_t code) {
2431 if (IsEnabledStop(code)) {
2432 watched_stops_[code].count |= kStopDisabledBit;
2437 void Simulator::IncreaseStopCounter(uint64_t code) {
2438 DCHECK_LE(code, kMaxStopCode);
2439 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
2440 PrintF(
"Stop counter for code %" PRId64
2441 " has overflowed.\n" 2442 "Enabling this code and reseting the counter to 0.\n",
2444 watched_stops_[code].count = 0;
2447 watched_stops_[code].count++;
2453 void Simulator::PrintStopInfo(uint64_t code) {
2454 if (code <= kMaxWatchpointCode) {
2455 PrintF(
"That is a watchpoint, not a stop.\n");
2457 }
else if (code > kMaxStopCode) {
2458 PrintF(
"Code too large, only %u stops can be used\n", kMaxStopCode + 1);
2461 const char* state = IsEnabledStop(code) ?
"Enabled" :
"Disabled";
2462 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2465 if (watched_stops_[code].desc) {
2466 PrintF(
"stop %" PRId64
" - 0x%" PRIx64
" : \t%s, \tcounter = %i, \t%s\n",
2467 code, code, state, count, watched_stops_[code].desc);
2469 PrintF(
"stop %" PRId64
" - 0x%" PRIx64
" : \t%s, \tcounter = %i\n", code,
2470 code, state, count);
2476 void Simulator::SignalException(Exception e) {
2477 FATAL(
"Error: Exception %i raised.", static_cast<int>(e));
2482 template <
typename T>
2483 static T FPAbs(T a);
2486 double FPAbs<double>(
double a) {
2491 float FPAbs<float>(
float a) {
2495 template <
typename T>
2496 static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind kind, T& result) {
2497 if (std::isnan(a) && std::isnan(b)) {
2499 }
else if (std::isnan(a)) {
2501 }
else if (std::isnan(b)) {
2503 }
else if (b == a) {
2507 result = std::signbit(b) -
static_cast<int>(kind) ? b : a;
2514 template <
typename T>
2515 static T FPUMin(T a, T b) {
2517 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2520 return b < a ? b : a;
2524 template <
typename T>
2525 static T FPUMax(T a, T b) {
2527 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, result)) {
2530 return b > a ? b : a;
2534 template <
typename T>
2535 static T FPUMinA(T a, T b) {
2537 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2538 if (FPAbs(a) < FPAbs(b)) {
2540 }
else if (FPAbs(b) < FPAbs(a)) {
2543 result = a < b ? a : b;
2549 template <
typename T>
2550 static T FPUMaxA(T a, T b) {
2552 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2553 if (FPAbs(a) > FPAbs(b)) {
2555 }
else if (FPAbs(b) > FPAbs(a)) {
2558 result = a > b ? a : b;
2564 enum class KeepSign :
bool { no =
false, yes };
2566 template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
2568 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) {
2569 DCHECK(std::isnan(arg));
2570 T qNaN = std::numeric_limits<T>::quiet_NaN();
2571 if (keepSign == KeepSign::yes) {
2572 return std::copysign(qNaN, result);
2577 template <
typename T>
2578 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
2579 if (std::isnan(first)) {
2580 return FPUCanonalizeNaNArg(result, first, keepSign);
2585 template <
typename T,
typename... Args>
2586 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
2587 if (std::isnan(first)) {
2588 return FPUCanonalizeNaNArg(result, first, keepSign);
2590 return FPUCanonalizeNaNArgs(result, keepSign, args...);
2593 template <
typename Func,
typename T,
typename... Args>
2594 T FPUCanonalizeOperation(Func f, T first, Args... args) {
2595 return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
2598 template <
typename Func,
typename T,
typename... Args>
2599 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
2600 T result = f(first, args...);
2601 if (std::isnan(result)) {
2602 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
2609 void Simulator::DecodeTypeRegisterSRsType() {
2611 fs = get_fpu_register_float(fs_reg());
2612 ft = get_fpu_register_float(ft_reg());
2613 fd = get_fpu_register_float(fd_reg());
2614 int32_t ft_int = bit_cast<int32_t>(ft);
2615 int32_t fd_int = bit_cast<int32_t>(fd);
2617 cc = instr_.FCccValue();
2618 fcsr_cc = get_fcsr_condition_bit(cc);
2619 switch (instr_.FunctionFieldRaw()) {
2621 DCHECK_EQ(kArchVariant, kMips64r6);
2622 float result, temp_result;
2624 float upper = std::ceil(fs);
2625 float lower = std::floor(fs);
2626 switch (get_fcsr_rounding_mode()) {
2627 case kRoundToNearest:
2628 if (upper - fs < fs - lower) {
2630 }
else if (upper - fs > fs - lower) {
2633 temp_result = upper / 2;
2634 float reminder = modf(temp_result, &temp);
2635 if (reminder == 0) {
2643 result = (fs > 0 ? lower : upper);
2645 case kRoundToPlusInf:
2648 case kRoundToMinusInf:
2652 SetFPUFloatResult(fd_reg(), result);
2654 set_fcsr_bit(kFCSRInexactFlagBit,
true);
2661 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs + rhs; },
2667 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs - rhs; },
2671 DCHECK_EQ(kArchVariant, kMips64r6);
2672 SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd));
2675 DCHECK_EQ(kArchVariant, kMips64r6);
2676 SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd));
2681 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs * rhs; },
2687 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs / rhs; },
2691 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
2692 [](
float fs) {
return FPAbs(fs); }, fs));
2695 SetFPUFloatResult(fd_reg(), fs);
2698 SetFPUFloatResult(fd_reg(),
2699 FPUCanonalizeOperation([](
float src) {
return -src; },
2700 KeepSign::yes, fs));
2705 FPUCanonalizeOperation([](
float src) {
return std::sqrt(src); }, fs));
2709 fd_reg(), FPUCanonalizeOperation(
2710 [](
float src) {
return 1.0 / std::sqrt(src); }, fs));
2713 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
2714 [](
float src) {
return 1.0 / src; }, fs));
2717 set_fcsr_bit(fcsr_cc,
false);
2718 TraceRegWr(test_fcsr_bit(fcsr_cc));
2721 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2722 TraceRegWr(test_fcsr_bit(fcsr_cc));
2725 set_fcsr_bit(fcsr_cc, (fs == ft));
2726 TraceRegWr(test_fcsr_bit(fcsr_cc));
2729 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2730 TraceRegWr(test_fcsr_bit(fcsr_cc));
2733 set_fcsr_bit(fcsr_cc, (fs < ft));
2734 TraceRegWr(test_fcsr_bit(fcsr_cc));
2737 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2738 TraceRegWr(test_fcsr_bit(fcsr_cc));
2741 set_fcsr_bit(fcsr_cc, (fs <= ft));
2742 TraceRegWr(test_fcsr_bit(fcsr_cc));
2745 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2746 TraceRegWr(test_fcsr_bit(fcsr_cc));
2749 SetFPUDoubleResult(fd_reg(), static_cast<double>(fs));
2756 uint32_t sign = (classed >> 31) & 1;
2757 uint32_t exponent = (classed >> 23) & 0x000000FF;
2758 uint32_t mantissa = classed & 0x007FFFFF;
2764 bool negInf = (classed == 0xFF800000);
2765 bool posInf = (classed == 0x7F800000);
2766 bool negZero = (classed == 0x80000000);
2767 bool posZero = (classed == 0x00000000);
2777 signalingNan =
false;
2779 if (!negInf && !posInf && (exponent == 0xFF)) {
2780 quietNan = ((mantissa & 0x00200000) == 0) &&
2781 ((mantissa & (0x00200000 - 1)) == 0);
2782 signalingNan = !quietNan;
2788 if ((exponent == 0) && (mantissa != 0)) {
2789 DCHECK(sign == 0 || sign == 1);
2790 posSubnorm = (sign == 0);
2791 negSubnorm = (sign == 1);
2797 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
2798 !quietNan && !negZero && !posZero) {
2799 DCHECK(sign == 0 || sign == 1);
2800 posNorm = (sign == 0);
2801 negNorm = (sign == 1);
2805 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
2806 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
2807 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
2809 DCHECK_NE(result, 0);
2811 fResult = bit_cast<
float>(result);
2812 SetFPUFloatResult(fd_reg(), fResult);
2818 round64_according_to_fcsr(fs, rounded, result, fs);
2819 SetFPUResult(fd_reg(), result);
2820 if (set_fcsr_round64_error(fs, rounded)) {
2821 set_fpu_register_invalid_result64(fs, rounded);
2828 round_according_to_fcsr(fs, rounded, result, fs);
2829 SetFPUWordResult(fd_reg(), result);
2830 if (set_fcsr_round_error(fs, rounded)) {
2831 set_fpu_register_word_invalid_result(fs, rounded);
2836 float rounded = trunc(fs);
2837 int32_t result =
static_cast<int32_t
>(rounded);
2838 SetFPUWordResult(fd_reg(), result);
2839 if (set_fcsr_round_error(fs, rounded)) {
2840 set_fpu_register_word_invalid_result(fs, rounded);
2844 float rounded = trunc(fs);
2846 SetFPUResult(fd_reg(), result);
2847 if (set_fcsr_round64_error(fs, rounded)) {
2848 set_fpu_register_invalid_result64(fs, rounded);
2853 float rounded = std::floor(fs + 0.5);
2854 int32_t result =
static_cast<int32_t
>(rounded);
2855 if ((result & 1) != 0 && result - fs == 0.5) {
2860 SetFPUWordResult(fd_reg(), result);
2861 if (set_fcsr_round_error(fs, rounded)) {
2862 set_fpu_register_word_invalid_result(fs, rounded);
2867 float rounded = std::floor(fs + 0.5);
2869 if ((result & 1) != 0 && result - fs == 0.5) {
2875 SetFPUResult(fd_reg(), i64);
2876 if (set_fcsr_round64_error(fs, rounded)) {
2877 set_fpu_register_invalid_result64(fs, rounded);
2882 float rounded = floor(fs);
2884 SetFPUResult(fd_reg(), result);
2885 if (set_fcsr_round64_error(fs, rounded)) {
2886 set_fpu_register_invalid_result64(fs, rounded);
2892 float rounded = std::floor(fs);
2893 int32_t result =
static_cast<int32_t
>(rounded);
2894 SetFPUWordResult(fd_reg(), result);
2895 if (set_fcsr_round_error(fs, rounded)) {
2896 set_fpu_register_word_invalid_result(fs, rounded);
2901 float rounded = std::ceil(fs);
2902 int32_t result =
static_cast<int32_t
>(rounded);
2903 SetFPUWordResult(fd_reg(), result);
2904 if (set_fcsr_round_error(fs, rounded)) {
2905 set_fpu_register_invalid_result(fs, rounded);
2909 float rounded = ceil(fs);
2911 SetFPUResult(fd_reg(), result);
2912 if (set_fcsr_round64_error(fs, rounded)) {
2913 set_fpu_register_invalid_result64(fs, rounded);
2918 DCHECK_EQ(kArchVariant, kMips64r6);
2919 SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs));
2922 DCHECK_EQ(kArchVariant, kMips64r6);
2923 SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs));
2926 DCHECK_EQ(kArchVariant, kMips64r6);
2927 SetFPUFloatResult(fd_reg(), FPUMin(ft, fs));
2930 DCHECK_EQ(kArchVariant, kMips64r6);
2931 SetFPUFloatResult(fd_reg(), FPUMax(ft, fs));
2934 DCHECK_EQ(kArchVariant, kMips64r6);
2935 SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
2938 DCHECK_EQ(kArchVariant, kMips64r6);
2941 (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0);
2944 DCHECK_EQ(kArchVariant, kMips64r6);
2947 (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0);
2950 DCHECK_EQ(kArchVariant, kMips64r2);
2952 SetFPUFloatResult(fd_reg(), fs);
2957 DCHECK_EQ(kArchVariant, kMips64r2);
2959 SetFPUFloatResult(fd_reg(), fs);
2965 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
2966 ft_cc = get_fcsr_condition_bit(ft_cc);
2968 if (instr_.Bit(16)) {
2970 if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
2973 if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
2985 void Simulator::DecodeTypeRegisterDRsType() {
2988 fs = get_fpu_register_double(fs_reg());
2989 ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg())
2991 fd = get_fpu_register_double(fd_reg());
2992 cc = instr_.FCccValue();
2993 fcsr_cc = get_fcsr_condition_bit(cc);
2996 switch (instr_.FunctionFieldRaw()) {
2998 DCHECK_EQ(kArchVariant, kMips64r6);
2999 double result, temp, temp_result;
3000 double upper = std::ceil(fs);
3001 double lower = std::floor(fs);
3002 switch (get_fcsr_rounding_mode()) {
3003 case kRoundToNearest:
3004 if (upper - fs < fs - lower) {
3006 }
else if (upper - fs > fs - lower) {
3009 temp_result = upper / 2;
3010 double reminder = modf(temp_result, &temp);
3011 if (reminder == 0) {
3019 result = (fs > 0 ? lower : upper);
3021 case kRoundToPlusInf:
3024 case kRoundToMinusInf:
3028 SetFPUDoubleResult(fd_reg(), result);
3030 set_fcsr_bit(kFCSRInexactFlagBit,
true);
3035 DCHECK_EQ(kArchVariant, kMips64r6);
3036 SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
3039 DCHECK_EQ(kArchVariant, kMips64r6);
3040 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
3043 DCHECK_EQ(kArchVariant, kMips64r6);
3044 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
3047 DCHECK_EQ(kArchVariant, kMips64r2);
3049 SetFPUDoubleResult(fd_reg(), fs);
3054 DCHECK_EQ(kArchVariant, kMips64r2);
3056 SetFPUDoubleResult(fd_reg(), fs);
3062 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
3063 ft_cc = get_fcsr_condition_bit(ft_cc);
3064 if (instr_.Bit(16)) {
3066 if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
3069 if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
3074 DCHECK_EQ(kArchVariant, kMips64r6);
3075 SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs));
3078 DCHECK_EQ(kArchVariant, kMips64r6);
3079 SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs));
3082 DCHECK_EQ(kArchVariant, kMips64r6);
3083 SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs));
3086 DCHECK_EQ(kArchVariant, kMips64r6);
3087 SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs));
3092 FPUCanonalizeOperation(
3093 [](
double lhs,
double rhs) {
return lhs + rhs; }, fs, ft));
3098 FPUCanonalizeOperation(
3099 [](
double lhs,
double rhs) {
return lhs - rhs; }, fs, ft));
3102 DCHECK_EQ(kArchVariant, kMips64r6);
3103 SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd));
3106 DCHECK_EQ(kArchVariant, kMips64r6);
3107 SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd));
3112 FPUCanonalizeOperation(
3113 [](
double lhs,
double rhs) {
return lhs * rhs; }, fs, ft));
3118 FPUCanonalizeOperation(
3119 [](
double lhs,
double rhs) {
return lhs / rhs; }, fs, ft));
3124 FPUCanonalizeOperation([](
double fs) {
return FPAbs(fs); }, fs));
3127 SetFPUDoubleResult(fd_reg(), fs);
3130 SetFPUDoubleResult(fd_reg(),
3131 FPUCanonalizeOperation([](
double src) {
return -src; },
3132 KeepSign::yes, fs));
3137 FPUCanonalizeOperation([](
double fs) {
return std::sqrt(fs); }, fs));
3141 fd_reg(), FPUCanonalizeOperation(
3142 [](
double fs) {
return 1.0 / std::sqrt(fs); }, fs));
3145 SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation(
3146 [](
double fs) {
return 1.0 / fs; }, fs));
3149 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
3150 TraceRegWr(test_fcsr_bit(fcsr_cc));
3153 set_fcsr_bit(fcsr_cc, (fs == ft));
3154 TraceRegWr(test_fcsr_bit(fcsr_cc));
3157 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
3158 TraceRegWr(test_fcsr_bit(fcsr_cc));
3161 set_fcsr_bit(fcsr_cc, (fs < ft));
3162 TraceRegWr(test_fcsr_bit(fcsr_cc));
3165 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
3166 TraceRegWr(test_fcsr_bit(fcsr_cc));
3169 set_fcsr_bit(fcsr_cc, (fs <= ft));
3170 TraceRegWr(test_fcsr_bit(fcsr_cc));
3173 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
3174 TraceRegWr(test_fcsr_bit(fcsr_cc));
3179 round_according_to_fcsr(fs, rounded, result, fs);
3180 SetFPUWordResult(fd_reg(), result);
3181 if (set_fcsr_round_error(fs, rounded)) {
3182 set_fpu_register_word_invalid_result(fs, rounded);
3188 double rounded = std::floor(fs + 0.5);
3189 int32_t result =
static_cast<int32_t
>(rounded);
3190 if ((result & 1) != 0 && result - fs == 0.5) {
3195 SetFPUWordResult(fd_reg(), result);
3196 if (set_fcsr_round_error(fs, rounded)) {
3197 set_fpu_register_invalid_result(fs, rounded);
3202 double rounded = trunc(fs);
3203 int32_t result =
static_cast<int32_t
>(rounded);
3204 SetFPUWordResult(fd_reg(), result);
3205 if (set_fcsr_round_error(fs, rounded)) {
3206 set_fpu_register_invalid_result(fs, rounded);
3211 double rounded = std::floor(fs);
3212 int32_t result =
static_cast<int32_t
>(rounded);
3213 SetFPUWordResult(fd_reg(), result);
3214 if (set_fcsr_round_error(fs, rounded)) {
3215 set_fpu_register_invalid_result(fs, rounded);
3220 double rounded = std::ceil(fs);
3221 int32_t result =
static_cast<int32_t
>(rounded);
3222 SetFPUWordResult2(fd_reg(), result);
3223 if (set_fcsr_round_error(fs, rounded)) {
3224 set_fpu_register_invalid_result(fs, rounded);
3228 SetFPUFloatResult(fd_reg(), static_cast<float>(fs));
3233 round64_according_to_fcsr(fs, rounded, result, fs);
3234 SetFPUResult(fd_reg(), result);
3235 if (set_fcsr_round64_error(fs, rounded)) {
3236 set_fpu_register_invalid_result64(fs, rounded);
3241 double rounded = std::floor(fs + 0.5);
3243 if ((result & 1) != 0 && result - fs == 0.5) {
3249 SetFPUResult(fd_reg(), i64);
3250 if (set_fcsr_round64_error(fs, rounded)) {
3251 set_fpu_register_invalid_result64(fs, rounded);
3256 double rounded = trunc(fs);
3258 SetFPUResult(fd_reg(), result);
3259 if (set_fcsr_round64_error(fs, rounded)) {
3260 set_fpu_register_invalid_result64(fs, rounded);
3265 double rounded = floor(fs);
3267 SetFPUResult(fd_reg(), result);
3268 if (set_fcsr_round64_error(fs, rounded)) {
3269 set_fpu_register_invalid_result64(fs, rounded);
3274 double rounded = ceil(fs);
3276 SetFPUResult(fd_reg(), result);
3277 if (set_fcsr_round64_error(fs, rounded)) {
3278 set_fpu_register_invalid_result64(fs, rounded);
3284 uint64_t classed = bit_cast<uint64_t>(fs);
3287 uint32_t sign = (classed >> 63) & 1;
3288 uint32_t exponent = (classed >> 52) & 0x00000000000007FF;
3289 uint64_t mantissa = classed & 0x000FFFFFFFFFFFFF;
3295 bool negInf = (classed == 0xFFF0000000000000);
3296 bool posInf = (classed == 0x7FF0000000000000);
3297 bool negZero = (classed == 0x8000000000000000);
3298 bool posZero = (classed == 0x0000000000000000);
3308 signalingNan =
false;
3310 if (!negInf && !posInf && exponent == 0x7FF) {
3311 quietNan = ((mantissa & 0x0008000000000000) != 0) &&
3312 ((mantissa & (0x0008000000000000 - 1)) == 0);
3313 signalingNan = !quietNan;
3319 if ((exponent == 0) && (mantissa != 0)) {
3320 DCHECK(sign == 0 || sign == 1);
3321 posSubnorm = (sign == 0);
3322 negSubnorm = (sign == 1);
3328 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3329 !quietNan && !negZero && !posZero) {
3330 DCHECK(sign == 0 || sign == 1);
3331 posNorm = (sign == 0);
3332 negNorm = (sign == 1);
3336 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3337 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3338 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3340 DCHECK_NE(result, 0);
3342 dResult = bit_cast<
double>(result);
3343 SetFPUDoubleResult(fd_reg(), dResult);
3347 set_fcsr_bit(fcsr_cc,
false);
3348 TraceRegWr(test_fcsr_bit(fcsr_cc));
3357 void Simulator::DecodeTypeRegisterWRsType() {
3358 float fs = get_fpu_register_float(fs_reg());
3359 float ft = get_fpu_register_float(ft_reg());
3361 switch (instr_.FunctionFieldRaw()) {
3363 alu_out = get_fpu_register_signed_word(fs_reg());
3364 SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out));
3367 alu_out = get_fpu_register_signed_word(fs_reg());
3368 SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out));
3371 SetFPUWordResult2(fd_reg(), 0);
3374 if (std::isnan(fs) || std::isnan(ft)) {
3375 SetFPUWordResult2(fd_reg(), -1);
3377 SetFPUWordResult2(fd_reg(), 0);
3382 SetFPUWordResult2(fd_reg(), -1);
3384 SetFPUWordResult2(fd_reg(), 0);
3388 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3389 SetFPUWordResult2(fd_reg(), -1);
3391 SetFPUWordResult2(fd_reg(), 0);
3396 SetFPUWordResult2(fd_reg(), -1);
3398 SetFPUWordResult2(fd_reg(), 0);
3402 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3403 SetFPUWordResult2(fd_reg(), -1);
3405 SetFPUWordResult2(fd_reg(), 0);
3410 SetFPUWordResult2(fd_reg(), -1);
3412 SetFPUWordResult2(fd_reg(), 0);
3416 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3417 SetFPUWordResult2(fd_reg(), -1);
3419 SetFPUWordResult2(fd_reg(), 0);
3423 if (!std::isnan(fs) && !std::isnan(ft)) {
3424 SetFPUWordResult2(fd_reg(), -1);
3426 SetFPUWordResult2(fd_reg(), 0);
3430 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3431 SetFPUWordResult2(fd_reg(), -1);
3433 SetFPUWordResult2(fd_reg(), 0);
3438 SetFPUWordResult2(fd_reg(), -1);
3440 SetFPUWordResult2(fd_reg(), 0);
3449 void Simulator::DecodeTypeRegisterLRsType() {
3450 double fs = get_fpu_register_double(fs_reg());
3451 double ft = get_fpu_register_double(ft_reg());
3453 switch (instr_.FunctionFieldRaw()) {
3455 i64 = get_fpu_register(fs_reg());
3456 SetFPUDoubleResult(fd_reg(), static_cast<double>(i64));
3459 i64 = get_fpu_register(fs_reg());
3460 SetFPUFloatResult(fd_reg(), static_cast<float>(i64));
3463 SetFPUResult(fd_reg(), 0);
3466 if (std::isnan(fs) || std::isnan(ft)) {
3467 SetFPUResult(fd_reg(), -1);
3469 SetFPUResult(fd_reg(), 0);
3474 SetFPUResult(fd_reg(), -1);
3476 SetFPUResult(fd_reg(), 0);
3480 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3481 SetFPUResult(fd_reg(), -1);
3483 SetFPUResult(fd_reg(), 0);
3488 SetFPUResult(fd_reg(), -1);
3490 SetFPUResult(fd_reg(), 0);
3494 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3495 SetFPUResult(fd_reg(), -1);
3497 SetFPUResult(fd_reg(), 0);
3502 SetFPUResult(fd_reg(), -1);
3504 SetFPUResult(fd_reg(), 0);
3508 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3509 SetFPUResult(fd_reg(), -1);
3511 SetFPUResult(fd_reg(), 0);
3515 if (!std::isnan(fs) && !std::isnan(ft)) {
3516 SetFPUResult(fd_reg(), -1);
3518 SetFPUResult(fd_reg(), 0);
3522 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3523 SetFPUResult(fd_reg(), -1);
3525 SetFPUResult(fd_reg(), 0);
3529 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3530 SetFPUResult(fd_reg(), -1);
3532 SetFPUResult(fd_reg(), 0);
3541 void Simulator::DecodeTypeRegisterCOP1() {
3542 switch (instr_.RsFieldRaw()) {
3550 DCHECK_EQ(fs_reg(), kFCSRRegister);
3551 SetResult(rt_reg(), FCSR_);
3554 set_register(rt_reg(),
3555 static_cast<int64_t>(get_fpu_register_word(fs_reg())));
3556 TraceRegWr(get_register(rt_reg()), WORD_DWORD);
3559 SetResult(rt_reg(), get_fpu_register(fs_reg()));
3562 SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg()));
3566 DCHECK_EQ(fs_reg(), kFCSRRegister);
3568 if (kArchVariant == kMips64r6) {
3569 FCSR_ = reg | kFCSRNaN2008FlagMask;
3571 DCHECK_EQ(kArchVariant, kMips64r2);
3572 FCSR_ = reg & ~kFCSRNaN2008FlagMask;
3579 set_fpu_register_hi_word(fs_reg(), 0);
3580 set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt()));
3581 TraceRegWr(get_fpu_register(fs_reg()), FLOAT_DOUBLE);
3584 SetFPUResult2(fs_reg(), rt());
3587 set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt()));
3588 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
3591 DecodeTypeRegisterSRsType();
3594 DecodeTypeRegisterDRsType();
3597 DecodeTypeRegisterWRsType();
3600 DecodeTypeRegisterLRsType();
3608 void Simulator::DecodeTypeRegisterCOP1X() {
3609 switch (instr_.FunctionFieldRaw()) {
3611 DCHECK_EQ(kArchVariant, kMips64r2);
3613 fr = get_fpu_register_float(fr_reg());
3614 fs = get_fpu_register_float(fs_reg());
3615 ft = get_fpu_register_float(ft_reg());
3616 SetFPUFloatResult(fd_reg(), fs * ft + fr);
3620 DCHECK_EQ(kArchVariant, kMips64r2);
3622 fr = get_fpu_register_float(fr_reg());
3623 fs = get_fpu_register_float(fs_reg());
3624 ft = get_fpu_register_float(ft_reg());
3625 SetFPUFloatResult(fd_reg(), fs * ft - fr);
3629 DCHECK_EQ(kArchVariant, kMips64r2);
3631 fr = get_fpu_register_double(fr_reg());
3632 fs = get_fpu_register_double(fs_reg());
3633 ft = get_fpu_register_double(ft_reg());
3634 SetFPUDoubleResult(fd_reg(), fs * ft + fr);
3638 DCHECK_EQ(kArchVariant, kMips64r2);
3640 fr = get_fpu_register_double(fr_reg());
3641 fs = get_fpu_register_double(fs_reg());
3642 ft = get_fpu_register_double(ft_reg());
3643 SetFPUDoubleResult(fd_reg(), fs * ft - fr);
3652 void Simulator::DecodeTypeRegisterSPECIAL() {
3656 bool do_interrupt =
false;
3658 switch (instr_.FunctionFieldRaw()) {
3660 DCHECK_EQ(kArchVariant, kMips64r6);
3661 SetResult(rd_reg(), rt() == 0 ? rs() : 0);
3664 DCHECK_EQ(kArchVariant, kMips64r6);
3665 SetResult(rd_reg(), rt() != 0 ? rs() : 0);
3669 int64_t current_pc = get_pc();
3670 Instruction* branch_delay_instr =
3671 reinterpret_cast<Instruction*
>(current_pc + kInstrSize);
3672 BranchDelayInstructionDecode(branch_delay_instr);
3674 pc_modified_ =
true;
3679 int64_t current_pc = get_pc();
3680 int32_t return_addr_reg = rd_reg();
3681 Instruction* branch_delay_instr =
3682 reinterpret_cast<Instruction*
>(current_pc + kInstrSize);
3683 BranchDelayInstructionDecode(branch_delay_instr);
3684 set_register(return_addr_reg, current_pc + 2 * kInstrSize);
3686 pc_modified_ =
true;
3690 SetResult(rd_reg(), static_cast<int32_t>(rt()) << sa());
3693 SetResult(rd_reg(), rt() << sa());
3696 SetResult(rd_reg(), rt() << sa() << 32);
3699 if (rs_reg() == 0) {
3703 alu_out =
static_cast<int32_t
>(
static_cast<uint32_t>(rt_u()) >> sa());
3704 }
else if (rs_reg() == 1) {
3708 alu_out =
static_cast<int32_t
>(
3709 base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
3710 static_cast<const uint32_t>(sa())));
3714 SetResult(rd_reg(), alu_out);
3717 if (rs_reg() == 0) {
3721 alu_out =
static_cast<int64_t>(rt_u() >> sa());
3722 }
else if (rs_reg() == 1) {
3726 alu_out =
static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa()));
3730 SetResult(rd_reg(), alu_out);
3733 if (rs_reg() == 0) {
3737 alu_out =
static_cast<int64_t>(rt_u() >> sa() >> 32);
3738 }
else if (rs_reg() == 1) {
3743 static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa() + 32));
3747 SetResult(rd_reg(), alu_out);
3750 SetResult(rd_reg(), (int32_t)rt() >> sa());
3753 SetResult(rd_reg(), rt() >> sa());
3756 SetResult(rd_reg(), rt() >> sa() >> 32);
3759 SetResult(rd_reg(), (int32_t)rt() << rs());
3762 SetResult(rd_reg(), rt() << rs());
3768 alu_out =
static_cast<int32_t
>((
uint32_t)rt_u() >> rs());
3773 alu_out =
static_cast<int32_t
>(
3774 base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
3775 static_cast<const uint32_t>(rs_u())));
3777 SetResult(rd_reg(), alu_out);
3783 alu_out =
static_cast<int64_t>(rt_u() >> rs());
3789 static_cast<int64_t>(base::bits::RotateRight64(rt_u(), rs_u()));
3791 SetResult(rd_reg(), alu_out);
3794 SetResult(rd_reg(), (int32_t)rt() >> rs());
3797 SetResult(rd_reg(), rt() >> rs());
3800 DCHECK_EQ(kArchVariant, kMips64r6);
3801 int8_t sa = lsa_sa() + 1;
3802 int32_t _rt =
static_cast<int32_t
>(rt());
3803 int32_t _rs =
static_cast<int32_t
>(rs());
3804 int32_t res = _rs << sa;
3806 SetResult(rd_reg(), static_cast<int64_t>(res));
3810 DCHECK_EQ(kArchVariant, kMips64r6);
3811 SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt());
3814 if (kArchVariant != kMips64r6) {
3816 alu_out = get_register(HI);
3821 alu_out = base::bits::CountLeadingZeros32(static_cast<int32_t>(rs_u()));
3823 SetResult(rd_reg(), alu_out);
3826 if (kArchVariant != kMips64r6) {
3828 alu_out = get_register(LO);
3833 alu_out = base::bits::CountLeadingZeros64(static_cast<int64_t>(rs_u()));
3835 SetResult(rd_reg(), alu_out);
3839 int32_t rs_lo =
static_cast<int32_t
>(rs());
3840 int32_t rt_lo =
static_cast<int32_t
>(rt());
3841 i64hilo =
static_cast<int64_t>(rs_lo) * static_cast<int64_t>(rt_lo);
3842 if (kArchVariant != kMips64r6) {
3843 set_register(LO, static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
3844 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
3848 SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
3851 SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
3854 UNIMPLEMENTED_MIPS();
3861 u64hilo =
static_cast<uint64_t
>(rs_u() & 0xFFFFFFFF) *
3862 static_cast<uint64_t>(rt_u() & 0xFFFFFFFF);
3863 if (kArchVariant != kMips64r6) {
3864 set_register(LO, static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
3865 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
3869 SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
3872 SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
3875 UNIMPLEMENTED_MIPS();
3881 if (kArchVariant != kMips64r6) {
3882 set_register(LO, rs() * rt());
3883 set_register(HI, MultiplyHighSigned(rs(), rt()));
3887 SetResult(rd_reg(), rs() * rt());
3890 SetResult(rd_reg(), MultiplyHighSigned(rs(), rt()));
3893 UNIMPLEMENTED_MIPS();
3899 UNIMPLEMENTED_MIPS();
3904 instr_.FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN;
3905 switch (kArchVariant) {
3911 if (rs() == int_min_value && rt() == -1) {
3912 set_register(LO, int_min_value);
3913 set_register(HI, 0);
3914 }
else if (rt() != 0) {
3915 set_register(LO, rs() / rt());
3916 set_register(HI, rs() % rt());
3922 if (rs() == int_min_value && rt() == -1) {
3923 SetResult(rd_reg(), int_min_value);
3924 }
else if (rt() != 0) {
3925 SetResult(rd_reg(), rs() / rt());
3929 if (rs() == int_min_value && rt() == -1) {
3930 SetResult(rd_reg(), 0);
3931 }
else if (rt() != 0) {
3932 SetResult(rd_reg(), rs() % rt());
3936 UNIMPLEMENTED_MIPS();
3946 switch (kArchVariant) {
3953 SetResult(rd_reg(), rs_u_32 / rt_u_32);
3958 SetResult(rd_reg(), rs_u_32 % rt_u_32);
3962 UNIMPLEMENTED_MIPS();
3970 set_register(LO, rs_u_32 / rt_u_32);
3971 set_register(HI, rs_u_32 % rt_u_32);
3977 switch (kArchVariant) {
3979 switch (instr_.SaValue()) {
3982 SetResult(rd_reg(), rs_u() / rt_u());
3987 SetResult(rd_reg(), rs_u() % rt_u());
3991 UNIMPLEMENTED_MIPS();
3997 set_register(LO, rs_u() / rt_u());
3998 set_register(HI, rs_u() % rt_u());
4005 if (HaveSameSign(rs(), rt())) {
4007 if (rs() > (Registers::kMaxValue - rt())) {
4008 SignalException(kIntegerOverflow);
4010 }
else if (rs() < 0) {
4011 if (rs() < (Registers::kMinValue - rt())) {
4012 SignalException(kIntegerUnderflow);
4016 SetResult(rd_reg(), rs() + rt());
4019 int32_t alu32_out =
static_cast<int32_t
>(rs() + rt());
4021 SetResult(rd_reg(), static_cast<int64_t>(alu32_out));
4025 SetResult(rd_reg(), rs() + rt());
4029 if (!HaveSameSign(rs(), rt())) {
4031 if (rs() > (Registers::kMaxValue + rt())) {
4032 SignalException(kIntegerOverflow);
4034 }
else if (rs() < 0) {
4035 if (rs() < (Registers::kMinValue + rt())) {
4036 SignalException(kIntegerUnderflow);
4040 SetResult(rd_reg(), rs() - rt());
4043 int32_t alu32_out =
static_cast<int32_t
>(rs() - rt());
4045 SetResult(rd_reg(), static_cast<int64_t>(alu32_out));
4049 SetResult(rd_reg(), rs() - rt());
4052 SetResult(rd_reg(), rs() & rt());
4055 SetResult(rd_reg(), rs() | rt());
4058 SetResult(rd_reg(), rs() ^ rt());
4061 SetResult(rd_reg(), ~(rs() | rt()));
4064 SetResult(rd_reg(), rs() < rt() ? 1 : 0);
4067 SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
4071 do_interrupt =
true;
4074 do_interrupt = rs() >= rt();
4077 do_interrupt = rs_u() >= rt_u();
4080 do_interrupt = rs() < rt();
4083 do_interrupt = rs_u() < rt_u();
4086 do_interrupt = rs() == rt();
4089 do_interrupt = rs() != rt();
4097 SetResult(rd_reg(), rs());
4102 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
4103 if (instr_.Bit(16)) {
4104 if (test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs());
4106 if (!test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs());
4112 SetResult(rd_reg(), rs());
4119 SoftwareInterrupt();
4124 void Simulator::DecodeTypeRegisterSPECIAL2() {
4126 switch (instr_.FunctionFieldRaw()) {
4128 alu_out =
static_cast<int32_t
>(rs_u()) * static_cast<int32_t>(rt_u());
4129 SetResult(rd_reg(), alu_out);
4131 set_register(LO, Unpredictable);
4132 set_register(HI, Unpredictable);
4137 alu_out = base::bits::CountLeadingZeros32(static_cast<uint32_t>(rs_u()));
4138 SetResult(rd_reg(), alu_out);
4143 alu_out = base::bits::CountLeadingZeros64(static_cast<uint64_t>(rs_u()));
4144 SetResult(rd_reg(), alu_out);
4147 alu_out = 0x12345678;
4153 void Simulator::DecodeTypeRegisterSPECIAL3() {
4155 switch (instr_.FunctionFieldRaw()) {
4158 uint16_t msbd = rd_reg();
4160 uint16_t lsb = sa();
4161 uint16_t size = msbd + 1;
4162 uint64_t mask = (1ULL << size) - 1;
4163 alu_out =
static_cast<int32_t
>((rs_u() & (mask << lsb)) >> lsb);
4164 SetResult(rt_reg(), alu_out);
4169 uint16_t msbd = rd_reg();
4171 uint16_t lsb = sa();
4172 uint16_t size = msbd + 1;
4173 uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4174 alu_out =
static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
4175 SetResult(rt_reg(), alu_out);
4180 uint16_t msbdminus32 = rd_reg();
4182 uint16_t lsb = sa();
4183 uint16_t size = msbdminus32 + 1 + 32;
4184 uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4185 alu_out =
static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
4186 SetResult(rt_reg(), alu_out);
4191 uint16_t msbd = rd_reg();
4194 uint16_t lsb = sa() + 32;
4195 uint16_t size = msbd + 1;
4196 uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
4197 alu_out =
static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
4198 SetResult(rt_reg(), alu_out);
4203 uint16_t msb = rd_reg();
4205 uint16_t lsb = sa();
4206 uint16_t size = msb - lsb + 1;
4207 uint64_t mask = (1ULL << size) - 1;
4208 alu_out =
static_cast<int32_t
>((rt_u() & ~(mask << lsb)) |
4209 ((rs_u() & mask) << lsb));
4210 SetResult(rt_reg(), alu_out);
4215 uint16_t msb = rd_reg();
4217 uint16_t lsb = sa();
4218 uint16_t size = msb - lsb + 1;
4219 uint64_t mask = (1ULL << size) - 1;
4220 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4221 SetResult(rt_reg(), alu_out);
4226 uint16_t msbminus32 = rd_reg();
4228 uint16_t lsb = sa();
4229 uint16_t size = msbminus32 + 32 - lsb + 1;
4232 mask = (1ULL << size) - 1;
4234 mask = std::numeric_limits<uint64_t>::max();
4235 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4236 SetResult(rt_reg(), alu_out);
4241 uint16_t msbminus32 = rd_reg();
4243 uint16_t lsbminus32 = sa();
4244 uint16_t lsb = lsbminus32 + 32;
4245 uint16_t size = msbminus32 + 32 - lsb + 1;
4246 uint64_t mask = (1ULL << size) - 1;
4247 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4248 SetResult(rt_reg(), alu_out);
4252 int32_t sa = instr_.SaFieldRaw() >> kSaShift;
4257 uint8_t i_byte, o_byte;
4260 for (
int i = 0;
i < 4;
i++) {
4261 output = output >> 8;
4262 i_byte = input & 0xFF;
4266 o_byte =
static_cast<uint8_t
>(((i_byte * 0x0802LU & 0x22110LU) |
4267 (i_byte * 0x8020LU & 0x88440LU)) *
4271 output = output | (
static_cast<uint32_t>(o_byte << 24));
4275 alu_out =
static_cast<int64_t>(
static_cast<int32_t
>(output));
4279 uint8_t input =
static_cast<uint8_t
>(rt());
4285 output |= 0xFFFFFF00;
4288 alu_out =
static_cast<int32_t
>(output);
4292 uint16_t input =
static_cast<uint16_t
>(rt());
4298 output |= 0xFFFF0000;
4301 alu_out =
static_cast<int32_t
>(output);
4306 uint64_t output = 0;
4309 for (
int i = 0;
i < 4;
i++) {
4316 output = output | tmp;
4322 if (mask & output) {
4323 output |= 0xFFFFFFFF00000000;
4326 alu_out =
static_cast<int64_t>(output);
4330 const uint8_t bp2 = instr_.Bp2Value();
4335 alu_out =
static_cast<int32_t
>(rt());
4337 uint64_t rt_hi = rt() << (8 * bp2);
4338 uint64_t rs_lo = rs() >> (8 * (4 - bp2));
4339 alu_out =
static_cast<int32_t
>(rt_hi | rs_lo);
4344 alu_out = 0x12345678;
4351 SetResult(rd_reg(), alu_out);
4355 int32_t sa = instr_.SaFieldRaw() >> kSaShift;
4360 uint64_t input =
static_cast<uint64_t
>(rt());
4361 uint64_t output = 0;
4362 uint8_t i_byte, o_byte;
4365 for (
int i = 0;
i < 8;
i++) {
4366 output = output >> 8;
4367 i_byte = input & 0xFF;
4372 static_cast<uint8_t
>(((i_byte * 0x0802LU & 0x22110LU) |
4373 (i_byte * 0x8020LU & 0x88440LU)) *
4377 output = output | ((
static_cast<uint64_t
>(o_byte) << 56));
4381 alu_out =
static_cast<int64_t>(output);
4388 uint64_t input =
static_cast<uint64_t
>(rt());
4389 uint64_t output = 0;
4391 uint64_t mask = 0xFF00000000000000;
4392 for (
int i = 0;
i < 8;
i++) {
4393 uint64_t tmp = mask & input;
4399 output = output | tmp;
4403 alu_out =
static_cast<int64_t>(output);
4407 uint64_t input =
static_cast<uint64_t
>(rt());
4408 uint64_t output = 0;
4410 uint64_t mask = 0xFFFF000000000000;
4411 for (
int i = 0;
i < 4;
i++) {
4412 uint64_t tmp = mask & input;
4421 output = output | tmp;
4425 alu_out =
static_cast<int64_t>(output);
4429 const uint8_t bp3 = instr_.Bp3Value();
4434 alu_out =
static_cast<int64_t>(rt());
4436 uint64_t rt_hi = rt() << (8 * bp3);
4437 uint64_t rs_lo = rs() >> (8 * (8 - bp3));
4438 alu_out =
static_cast<int64_t>(rt_hi | rs_lo);
4443 alu_out = 0x12345678;
4450 SetResult(rd_reg(), alu_out);
4458 int Simulator::DecodeMsaDataFormat() {
4460 if (instr_.IsMSABranchInstr()) {
4461 switch (instr_.RsFieldRaw()) {
4487 int DF[] = {MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD};
4488 switch (instr_.MSAMinorOpcodeField()) {
4492 df = DF[instr_.Bits(22, 21)];
4495 df = DF[instr_.Bits(1, 0)];
4498 df = DF[instr_.MsaBitDf()];
4501 df = DF[instr_.MsaElmDf()];
4503 case kMsaMinor3RF: {
4504 uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
4514 df = DF[1 + instr_.Bit(21)];
4517 df = DF[2 + instr_.Bit(21)];
4522 df = DF[instr_.Bits(17, 16)];
4525 df = DF[2 + instr_.Bit(16)];
4535 void Simulator::DecodeTypeMsaI8() {
4536 DCHECK_EQ(kArchVariant, kMips64r6);
4537 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4538 uint32_t opcode = instr_.InstructionBits() & kMsaI8Mask;
4539 int8_t i8 = instr_.MsaImm8Value();
4544 get_msa_register(instr_.WsValue(), ws.b);
4545 for (
int i = 0;
i < kMSALanesByte;
i++) {
4546 wd.b[
i] = ws.b[
i] & i8;
4548 set_msa_register(instr_.WdValue(), wd.b);
4549 TraceMSARegWr(wd.b);
4552 get_msa_register(instr_.WsValue(), ws.b);
4553 for (
int i = 0;
i < kMSALanesByte;
i++) {
4554 wd.b[
i] = ws.b[
i] | i8;
4556 set_msa_register(instr_.WdValue(), wd.b);
4557 TraceMSARegWr(wd.b);
4560 get_msa_register(instr_.WsValue(), ws.b);
4561 for (
int i = 0;
i < kMSALanesByte;
i++) {
4562 wd.b[
i] = ~(ws.b[
i] | i8);
4564 set_msa_register(instr_.WdValue(), wd.b);
4565 TraceMSARegWr(wd.b);
4568 get_msa_register(instr_.WsValue(), ws.b);
4569 for (
int i = 0;
i < kMSALanesByte;
i++) {
4570 wd.b[
i] = ws.b[
i] ^ i8;
4572 set_msa_register(instr_.WdValue(), wd.b);
4573 TraceMSARegWr(wd.b);
4576 get_msa_register(instr_.WsValue(), ws.b);
4577 get_msa_register(instr_.WdValue(), wd.b);
4578 for (
int i = 0;
i < kMSALanesByte;
i++) {
4579 wd.b[
i] = (ws.b[
i] & i8) | (wd.b[
i] & ~i8);
4581 set_msa_register(instr_.WdValue(), wd.b);
4582 TraceMSARegWr(wd.b);
4585 get_msa_register(instr_.WsValue(), ws.b);
4586 get_msa_register(instr_.WdValue(), wd.b);
4587 for (
int i = 0;
i < kMSALanesByte;
i++) {
4588 wd.b[
i] = (ws.b[
i] & ~i8) | (wd.b[
i] & i8);
4590 set_msa_register(instr_.WdValue(), wd.b);
4591 TraceMSARegWr(wd.b);
4594 get_msa_register(instr_.WsValue(), ws.b);
4595 get_msa_register(instr_.WdValue(), wd.b);
4596 for (
int i = 0;
i < kMSALanesByte;
i++) {
4597 wd.b[
i] = (ws.b[
i] & ~wd.b[
i]) | (wd.b[
i] & i8);
4599 set_msa_register(instr_.WdValue(), wd.b);
4600 TraceMSARegWr(wd.b);
4603 get_msa_register(instr_.WsValue(), ws.b);
4604 for (
int i = 0;
i < kMSALanesByte;
i++) {
4606 int k = (i8 >> (2 * j)) & 0x3;
4607 wd.b[
i] = ws.b[
i - j + k];
4609 set_msa_register(instr_.WdValue(), wd.b);
4610 TraceMSARegWr(wd.b);
4613 get_msa_register(instr_.WsValue(), ws.h);
4614 for (
int i = 0;
i < kMSALanesHalf;
i++) {
4616 int k = (i8 >> (2 * j)) & 0x3;
4617 wd.h[
i] = ws.h[
i - j + k];
4619 set_msa_register(instr_.WdValue(), wd.h);
4620 TraceMSARegWr(wd.h);
4623 get_msa_register(instr_.WsValue(), ws.w);
4624 for (
int i = 0;
i < kMSALanesWord;
i++) {
4625 int j = (i8 >> (2 *
i)) & 0x3;
4628 set_msa_register(instr_.WdValue(), wd.w);
4629 TraceMSARegWr(wd.w);
4636 template <
typename T>
4637 T Simulator::MsaI5InstrHelper(
uint32_t opcode, T ws, int32_t i5) {
4640 uint64_t ws_u64 =
static_cast<uint64_t
>(ws);
4641 uint64_t ui5_u64 =
static_cast<uint64_t
>(ui5);
4645 res =
static_cast<T
>(ws + ui5);
4648 res =
static_cast<T
>(ws - ui5);
4651 res =
static_cast<T
>(Max(ws, static_cast<T>(i5)));
4654 res =
static_cast<T
>(Min(ws, static_cast<T>(i5)));
4657 res =
static_cast<T
>(Max(ws_u64, ui5_u64));
4660 res =
static_cast<T
>(Min(ws_u64, ui5_u64));
4663 res =
static_cast<T
>(!Compare(ws, static_cast<T>(i5)) ? -1ull : 0ull);
4666 res =
static_cast<T
>((Compare(ws, static_cast<T>(i5)) == -1) ? -1ull
4670 res =
static_cast<T
>((Compare(ws_u64, ui5_u64) == -1) ? -1ull : 0ull);
4674 static_cast<T
>((Compare(ws, static_cast<T>(i5)) != 1) ? -1ull : 0ull);
4677 res =
static_cast<T
>((Compare(ws_u64, ui5_u64) != 1) ? -1ull : 0ull);
4685 void Simulator::DecodeTypeMsaI5() {
4686 DCHECK_EQ(kArchVariant, kMips64r6);
4687 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4688 uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
4692 int32_t i5 =
static_cast<int32_t
>(instr_.MsaImm5Value() << 27) >> 27;
4694 #define MSA_I5_DF(elem, num_of_lanes) \ 4695 get_msa_register(instr_.WsValue(), ws.elem); \ 4696 for (int i = 0; i < num_of_lanes; i++) { \ 4697 wd.elem[i] = MsaI5InstrHelper(opcode, ws.elem[i], i5); \ 4699 set_msa_register(instr_.WdValue(), wd.elem); \ 4700 TraceMSARegWr(wd.elem) 4702 switch (DecodeMsaDataFormat()) {
4704 MSA_I5_DF(b, kMSALanesByte);
4707 MSA_I5_DF(h, kMSALanesHalf);
4710 MSA_I5_DF(w, kMSALanesWord);
4713 MSA_I5_DF(d, kMSALanesDword);
4721 void Simulator::DecodeTypeMsaI10() {
4722 DCHECK_EQ(kArchVariant, kMips64r6);
4723 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4724 uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
4725 int64_t s10 = (
static_cast<int64_t>(instr_.MsaImm10Value()) << 54) >> 54;
4728 #define MSA_I10_DF(elem, num_of_lanes, T) \ 4729 for (int i = 0; i < num_of_lanes; ++i) { \ 4730 wd.elem[i] = static_cast<T>(s10); \ 4732 set_msa_register(instr_.WdValue(), wd.elem); \ 4733 TraceMSARegWr(wd.elem) 4735 if (opcode == LDI) {
4736 switch (DecodeMsaDataFormat()) {
4738 MSA_I10_DF(b, kMSALanesByte, int8_t);
4741 MSA_I10_DF(h, kMSALanesHalf, int16_t);
4744 MSA_I10_DF(w, kMSALanesWord, int32_t);
4747 MSA_I10_DF(d, kMSALanesDword,
int64_t);
4758 void Simulator::DecodeTypeMsaELM() {
4759 DCHECK_EQ(kArchVariant, kMips64r6);
4760 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4761 uint32_t opcode = instr_.InstructionBits() & kMsaLongerELMMask;
4762 int32_t n = instr_.MsaElmNValue();
4766 DCHECK_EQ(sa(), kMSACSRRegister);
4768 static_cast<int32_t
>(registers_[rd_reg()] & kMaxUInt32));
4769 TraceRegWr(static_cast<int32_t>(MSACSR_));
4772 DCHECK_EQ(rd_reg(), kMSACSRRegister);
4773 SetResult(sa(), static_cast<int64_t>(bit_cast<int32_t>(MSACSR_)));
4777 get_msa_register(ws_reg(), &ws);
4778 set_msa_register(wd_reg(), &ws);
4782 opcode &= kMsaELMMask;
4787 switch (DecodeMsaDataFormat()) {
4789 DCHECK_LT(n, kMSALanesByte);
4790 get_msa_register(instr_.WsValue(), ws.b);
4791 alu_out =
static_cast<int32_t
>(ws.b[n]);
4793 (opcode == COPY_U) ? alu_out & 0xFFu : alu_out);
4796 DCHECK_LT(n, kMSALanesHalf);
4797 get_msa_register(instr_.WsValue(), ws.h);
4798 alu_out =
static_cast<int32_t
>(ws.h[n]);
4800 (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out);
4803 DCHECK_LT(n, kMSALanesWord);
4804 get_msa_register(instr_.WsValue(), ws.w);
4805 alu_out =
static_cast<int32_t
>(ws.w[n]);
4807 (opcode == COPY_U) ? alu_out & 0xFFFFFFFFu : alu_out);
4810 DCHECK_LT(n, kMSALanesDword);
4811 get_msa_register(instr_.WsValue(), ws.d);
4812 alu_out =
static_cast<int64_t>(ws.d[n]);
4813 SetResult(wd_reg(), alu_out);
4821 switch (DecodeMsaDataFormat()) {
4823 DCHECK_LT(n, kMSALanesByte);
4824 int64_t rs = get_register(instr_.WsValue());
4825 get_msa_register(instr_.WdValue(), wd.b);
4826 wd.b[n] = rs & 0xFFu;
4827 set_msa_register(instr_.WdValue(), wd.b);
4828 TraceMSARegWr(wd.b);
4832 DCHECK_LT(n, kMSALanesHalf);
4833 int64_t rs = get_register(instr_.WsValue());
4834 get_msa_register(instr_.WdValue(), wd.h);
4835 wd.h[n] = rs & 0xFFFFu;
4836 set_msa_register(instr_.WdValue(), wd.h);
4837 TraceMSARegWr(wd.h);
4841 DCHECK_LT(n, kMSALanesWord);
4842 int64_t rs = get_register(instr_.WsValue());
4843 get_msa_register(instr_.WdValue(), wd.w);
4844 wd.w[n] = rs & 0xFFFFFFFFu;
4845 set_msa_register(instr_.WdValue(), wd.w);
4846 TraceMSARegWr(wd.w);
4850 DCHECK_LT(n, kMSALanesDword);
4851 int64_t rs = get_register(instr_.WsValue());
4852 get_msa_register(instr_.WdValue(), wd.d);
4854 set_msa_register(instr_.WdValue(), wd.d);
4855 TraceMSARegWr(wd.d);
4866 get_msa_register(ws_reg(), &ws);
4867 get_msa_register(wd_reg(), &wd);
4868 #define SLDI_DF(s, k) \ 4869 for (unsigned i = 0; i < s; i++) { \ 4870 v[i] = ws.b[s * k + i]; \ 4871 v[i + s] = wd.b[s * k + i]; \ 4873 for (unsigned i = 0; i < s; i++) { \ 4874 wd.b[s * k + i] = v[i + n]; \ 4876 switch (DecodeMsaDataFormat()) {
4878 DCHECK(n < kMSALanesByte);
4879 SLDI_DF(kMSARegSize /
sizeof(int8_t) / kBitsPerByte, 0)
4882 DCHECK(n < kMSALanesHalf);
4883 for (
int k = 0; k < 2; ++k) {
4884 SLDI_DF(kMSARegSize /
sizeof(int16_t) / kBitsPerByte, k)
4888 DCHECK(n < kMSALanesWord);
4889 for (
int k = 0; k < 4; ++k) {
4890 SLDI_DF(kMSARegSize /
sizeof(int32_t) / kBitsPerByte, k)
4894 DCHECK(n < kMSALanesDword);
4895 for (
int k = 0; k < 8; ++k) {
4896 SLDI_DF(kMSARegSize /
sizeof(
int64_t) / kBitsPerByte, k)
4902 set_msa_register(wd_reg(), &wd);
4917 template <
typename T>
4918 T Simulator::MsaBitInstrHelper(
uint32_t opcode, T wd, T ws, int32_t m) {
4919 typedef typename std::make_unsigned<T>::type uT;
4923 res =
static_cast<T
>(ws << m);
4926 res =
static_cast<T
>(ArithmeticShiftRight(ws, m));
4929 res =
static_cast<T
>(
static_cast<uT
>(ws) >> m);
4932 res =
static_cast<T
>(
static_cast<T
>(~(1ull << m)) & ws);
4935 res =
static_cast<T
>(
static_cast<T
>(1ull << m) | ws);
4938 res =
static_cast<T
>(
static_cast<T
>(1ull << m) ^ ws);
4941 int elem_size = 8 *
sizeof(T);
4943 if (bits == elem_size) {
4944 res =
static_cast<T
>(ws);
4946 uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
4947 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
4948 (
static_cast<T
>(~mask) & wd));
4952 int elem_size = 8 *
sizeof(T);
4954 if (bits == elem_size) {
4955 res =
static_cast<T
>(ws);
4957 uint64_t mask = (1ull << bits) - 1;
4958 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
4959 (
static_cast<T
>(~mask) & wd));
4963 #define M_MAX_INT(x) static_cast<int64_t>((1LL << ((x)-1)) - 1) 4964 #define M_MIN_INT(x) static_cast<int64_t>(-(1LL << ((x)-1))) 4965 int shift = 64 - 8 *
sizeof(T);
4967 res =
static_cast<T
>(ws_i64 < M_MIN_INT(m + 1)
4969 : ws_i64 > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1)
4975 #define M_MAX_UINT(x) static_cast<uint64_t>(-1ULL >> (64 - (x))) 4976 uint64_t mask =
static_cast<uint64_t
>(-1ULL >> (64 - 8 *
sizeof(T)));
4977 uint64_t ws_u64 =
static_cast<uint64_t
>(ws) & mask;
4978 res =
static_cast<T
>(ws_u64 < M_MAX_UINT(m + 1) ? ws_u64
4979 : M_MAX_UINT(m + 1));
4984 res =
static_cast<T
>(ws);
4986 res =
static_cast<T
>(ArithmeticShiftRight(ws, m)) +
4987 static_cast<T>((ws >> (m - 1)) & 0x1);
4992 res =
static_cast<T
>(ws);
4994 res =
static_cast<T
>(
static_cast<uT
>(ws) >> m) +
4995 static_cast<T
>((ws >> (m - 1)) & 0x1);
5004 void Simulator::DecodeTypeMsaBIT() {
5005 DCHECK_EQ(kArchVariant, kMips64r6);
5006 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5007 uint32_t opcode = instr_.InstructionBits() & kMsaBITMask;
5008 int32_t m = instr_.MsaBitMValue();
5011 #define MSA_BIT_DF(elem, num_of_lanes) \ 5012 get_msa_register(instr_.WsValue(), ws.elem); \ 5013 if (opcode == BINSLI || opcode == BINSRI) { \ 5014 get_msa_register(instr_.WdValue(), wd.elem); \ 5016 for (int i = 0; i < num_of_lanes; i++) { \ 5017 wd.elem[i] = MsaBitInstrHelper(opcode, wd.elem[i], ws.elem[i], m); \ 5019 set_msa_register(instr_.WdValue(), wd.elem); \ 5020 TraceMSARegWr(wd.elem) 5022 switch (DecodeMsaDataFormat()) {
5024 DCHECK(m < kMSARegSize / kMSALanesByte);
5025 MSA_BIT_DF(b, kMSALanesByte);
5028 DCHECK(m < kMSARegSize / kMSALanesHalf);
5029 MSA_BIT_DF(h, kMSALanesHalf);
5032 DCHECK(m < kMSARegSize / kMSALanesWord);
5033 MSA_BIT_DF(w, kMSALanesWord);
5036 DCHECK(m < kMSARegSize / kMSALanesDword);
5037 MSA_BIT_DF(d, kMSALanesDword);
5045 void Simulator::DecodeTypeMsaMI10() {
5046 DCHECK_EQ(kArchVariant, kMips64r6);
5047 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5048 uint32_t opcode = instr_.InstructionBits() & kMsaMI10Mask;
5049 int64_t s10 = (
static_cast<int64_t>(instr_.MsaImmMI10Value()) << 54) >> 54;
5050 int64_t rs = get_register(instr_.WsValue());
5054 #define MSA_MI10_LOAD(elem, num_of_lanes, T) \ 5055 for (int i = 0; i < num_of_lanes; ++i) { \ 5056 addr = rs + (s10 + i) * sizeof(T); \ 5057 wd.elem[i] = ReadMem<T>(addr, instr_.instr()); \ 5059 set_msa_register(instr_.WdValue(), wd.elem); 5061 #define MSA_MI10_STORE(elem, num_of_lanes, T) \ 5062 get_msa_register(instr_.WdValue(), wd.elem); \ 5063 for (int i = 0; i < num_of_lanes; ++i) { \ 5064 addr = rs + (s10 + i) * sizeof(T); \ 5065 WriteMem<T>(addr, wd.elem[i], instr_.instr()); \ 5068 if (opcode == MSA_LD) {
5069 switch (DecodeMsaDataFormat()) {
5071 MSA_MI10_LOAD(b, kMSALanesByte, int8_t);
5074 MSA_MI10_LOAD(h, kMSALanesHalf, int16_t);
5077 MSA_MI10_LOAD(w, kMSALanesWord, int32_t);
5080 MSA_MI10_LOAD(d, kMSALanesDword,
int64_t);
5085 }
else if (opcode == MSA_ST) {
5086 switch (DecodeMsaDataFormat()) {
5088 MSA_MI10_STORE(b, kMSALanesByte, int8_t);
5091 MSA_MI10_STORE(h, kMSALanesHalf, int16_t);
5094 MSA_MI10_STORE(w, kMSALanesWord, int32_t);
5097 MSA_MI10_STORE(d, kMSALanesDword,
int64_t);
5106 #undef MSA_MI10_LOAD 5107 #undef MSA_MI10_STORE 5110 template <
typename T>
5111 T Simulator::Msa3RInstrHelper(
uint32_t opcode, T wd, T ws, T wt) {
5112 typedef typename std::make_unsigned<T>::type uT;
5114 int wt_modulo = wt % (
sizeof(T) * 8);
5117 res =
static_cast<T
>(ws << wt_modulo);
5120 res =
static_cast<T
>(ArithmeticShiftRight(ws, wt_modulo));
5123 res =
static_cast<T
>(
static_cast<uT
>(ws) >> wt_modulo);
5126 res =
static_cast<T
>(
static_cast<T
>(~(1ull << wt_modulo)) & ws);
5129 res =
static_cast<T
>(
static_cast<T
>(1ull << wt_modulo) | ws);
5132 res =
static_cast<T
>(
static_cast<T
>(1ull << wt_modulo) ^ ws);
5135 int elem_size = 8 *
sizeof(T);
5136 int bits = wt_modulo + 1;
5137 if (bits == elem_size) {
5138 res =
static_cast<T
>(ws);
5140 uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
5141 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
5142 (
static_cast<T
>(~mask) & wd));
5146 int elem_size = 8 *
sizeof(T);
5147 int bits = wt_modulo + 1;
5148 if (bits == elem_size) {
5149 res =
static_cast<T
>(ws);
5151 uint64_t mask = (1ull << bits) - 1;
5152 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
5153 (
static_cast<T
>(~mask) & wd));
5166 res =
static_cast<T
>(Max(static_cast<uT>(ws), static_cast<uT>(wt)));
5172 res =
static_cast<T
>(Min(static_cast<uT>(ws), static_cast<uT>(wt)));
5177 res = Nabs(ws) < Nabs(wt) ? ws : wt;
5182 res = Nabs(ws) > Nabs(wt) ? ws : wt;
5185 res =
static_cast<T
>(!Compare(ws, wt) ? -1ull : 0ull);
5188 res =
static_cast<T
>((Compare(ws, wt) == -1) ? -1ull : 0ull);
5191 res =
static_cast<T
>(
5192 (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) == -1) ? -1ull
5196 res =
static_cast<T
>((Compare(ws, wt) != 1) ? -1ull : 0ull);
5199 res =
static_cast<T
>(
5200 (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) != 1) ? -1ull
5204 res =
static_cast<T
>(Abs(ws) + Abs(wt));
5207 T ws_nabs = Nabs(ws);
5208 T wt_nabs = Nabs(wt);
5209 if (ws_nabs < -std::numeric_limits<T>::max() - wt_nabs) {
5210 res = std::numeric_limits<T>::max();
5212 res = -(ws_nabs + wt_nabs);
5216 res = SaturateAdd(ws, wt);
5219 uT ws_u =
static_cast<uT
>(ws);
5220 uT wt_u =
static_cast<uT
>(wt);
5221 res =
static_cast<T
>(SaturateAdd(ws_u, wt_u));
5224 res =
static_cast<T
>((wt & ws) + ((wt ^ ws) >> 1));
5227 uT ws_u =
static_cast<uT
>(ws);
5228 uT wt_u =
static_cast<uT
>(wt);
5229 res =
static_cast<T
>((wt_u & ws_u) + ((wt_u ^ ws_u) >> 1));
5232 res =
static_cast<T
>((wt | ws) - ((wt ^ ws) >> 1));
5235 uT ws_u =
static_cast<uT
>(ws);
5236 uT wt_u =
static_cast<uT
>(wt);
5237 res =
static_cast<T
>((wt_u | ws_u) - ((wt_u ^ ws_u) >> 1));
5240 res = SaturateSub(ws, wt);
5243 uT ws_u =
static_cast<uT
>(ws);
5244 uT wt_u =
static_cast<uT
>(wt);
5245 res =
static_cast<T
>(SaturateSub(ws_u, wt_u));
5248 uT wsu =
static_cast<uT
>(ws);
5250 uT wtu =
static_cast<uT
>(wt);
5254 res =
static_cast<T
>(wsu - wtu);
5257 if (wsu > std::numeric_limits<uT>::max() + wt) {
5258 res =
static_cast<T
>(std::numeric_limits<uT>::max());
5260 res =
static_cast<T
>(wsu - wt);
5265 uT wsu =
static_cast<uT
>(ws);
5266 uT wtu =
static_cast<uT
>(wt);
5270 if (wdu > std::numeric_limits<T>::max()) {
5271 res = std::numeric_limits<T>::max();
5273 res =
static_cast<T
>(wdu);
5277 CHECK(-std::numeric_limits<T>::max() ==
5278 std::numeric_limits<T>::min() + 1);
5279 if (wdu <= std::numeric_limits<T>::max()) {
5280 res = -
static_cast<T
>(wdu);
5282 res = std::numeric_limits<T>::min();
5287 res =
static_cast<T
>(Abs(ws - wt));
5290 uT wsu =
static_cast<uT
>(ws);
5291 uT wtu =
static_cast<uT
>(wt);
5292 res =
static_cast<T
>(wsu > wtu ? wsu - wtu : wtu - wsu);
5304 res = wt != 0 ? ws / wt :
static_cast<T
>(Unpredictable);
5307 res = wt != 0 ?
static_cast<T
>(
static_cast<uT
>(ws) / static_cast<uT>(wt))
5308 : static_cast<T>(Unpredictable);
5311 res = wt != 0 ? ws % wt :
static_cast<T
>(Unpredictable);
5314 res = wt != 0 ?
static_cast<T
>(
static_cast<uT
>(ws) % static_cast<uT>(wt))
5315 : static_cast<T>(Unpredictable);
5328 int bit = wt_modulo == 0 ? 0 : (ws >> (wt_modulo - 1)) & 1;
5329 res =
static_cast<T
>(ArithmeticShiftRight(ws, wt_modulo) + bit);
5332 uT wsu =
static_cast<uT
>(ws);
5333 int bit = wt_modulo == 0 ? 0 : (wsu >> (wt_modulo - 1)) & 1;
5334 res =
static_cast<T
>((wsu >> wt_modulo) + bit);
5341 template <
typename T_
int,
typename T_reg>
5342 void Msa3RInstrHelper_shuffle(
const uint32_t opcode, T_reg ws, T_reg wt,
5343 T_reg wd,
const int i,
const int num_of_lanes) {
5344 T_int *ws_p, *wt_p, *wd_p;
5345 ws_p =
reinterpret_cast<T_int*
>(ws);
5346 wt_p =
reinterpret_cast<T_int*
>(wt);
5347 wd_p =
reinterpret_cast<T_int*
>(wd);
5350 wd_p[
i] = wt_p[2 *
i];
5351 wd_p[
i + num_of_lanes / 2] = ws_p[2 *
i];
5354 wd_p[
i] = wt_p[2 *
i + 1];
5355 wd_p[
i + num_of_lanes / 2] = ws_p[2 *
i + 1];
5358 wd_p[2 *
i] = wt_p[
i + num_of_lanes / 2];
5359 wd_p[2 *
i + 1] = ws_p[
i + num_of_lanes / 2];
5362 wd_p[2 *
i] = wt_p[
i];
5363 wd_p[2 *
i + 1] = ws_p[
i];
5366 wd_p[2 *
i] = wt_p[2 *
i];
5367 wd_p[2 *
i + 1] = ws_p[2 *
i];
5370 wd_p[2 *
i] = wt_p[2 *
i + 1];
5371 wd_p[2 *
i + 1] = ws_p[2 *
i + 1];
5374 const int mask_not_valid = 0xC0;
5375 const int mask_6_bits = 0x3F;
5376 if ((wd_p[
i] & mask_not_valid)) {
5379 int k = (wd_p[
i] & mask_6_bits) % (num_of_lanes * 2);
5380 wd_p[
i] = k >= num_of_lanes ? ws_p[k - num_of_lanes] : wt_p[k];
5388 template <
typename T_
int,
typename T_smaller_
int,
typename T_reg>
5389 void Msa3RInstrHelper_horizontal(
const uint32_t opcode, T_reg ws, T_reg wt,
5390 T_reg wd,
const int i,
5391 const int num_of_lanes) {
5392 typedef typename std::make_unsigned<T_int>::type T_uint;
5393 typedef typename std::make_unsigned<T_smaller_int>::type T_smaller_uint;
5395 T_smaller_int *ws_p, *wt_p;
5396 ws_p =
reinterpret_cast<T_smaller_int*
>(ws);
5397 wt_p =
reinterpret_cast<T_smaller_int*
>(wt);
5398 wd_p =
reinterpret_cast<T_int*
>(wd);
5400 T_smaller_uint *ws_pu, *wt_pu;
5401 ws_pu =
reinterpret_cast<T_smaller_uint*
>(ws);
5402 wt_pu =
reinterpret_cast<T_smaller_uint*
>(wt);
5403 wd_pu =
reinterpret_cast<T_uint*
>(wd);
5407 static_cast<T_int
>(ws_p[2 *
i + 1]) + static_cast<T_int>(wt_p[2 *
i]);
5410 wd_pu[
i] =
static_cast<T_uint
>(ws_pu[2 *
i + 1]) +
5411 static_cast<T_uint>(wt_pu[2 *
i]);
5415 static_cast<T_int
>(ws_p[2 *
i + 1]) - static_cast<T_int>(wt_p[2 *
i]);
5418 wd_pu[
i] =
static_cast<T_uint
>(ws_pu[2 *
i + 1]) -
5419 static_cast<T_uint>(wt_pu[2 *
i]);
5426 void Simulator::DecodeTypeMsa3R() {
5427 DCHECK_EQ(kArchVariant, kMips64r6);
5428 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5429 uint32_t opcode = instr_.InstructionBits() & kMsa3RMask;
5430 msa_reg_t ws, wd, wt;
5431 get_msa_register(ws_reg(), &ws);
5432 get_msa_register(wt_reg(), &wt);
5433 get_msa_register(wd_reg(), &wd);
5439 #define HORIZONTAL_ARITHMETIC_DF(num_of_lanes, int_type, lesser_int_type) \ 5440 for (int i = 0; i < num_of_lanes; ++i) { \ 5441 Msa3RInstrHelper_horizontal<int_type, lesser_int_type>( \ 5442 opcode, &ws, &wt, &wd, i, num_of_lanes); \ 5444 switch (DecodeMsaDataFormat()) {
5446 HORIZONTAL_ARITHMETIC_DF(kMSALanesHalf, int16_t, int8_t);
5449 HORIZONTAL_ARITHMETIC_DF(kMSALanesWord, int32_t, int16_t);
5452 HORIZONTAL_ARITHMETIC_DF(kMSALanesDword,
int64_t, int32_t);
5458 #undef HORIZONTAL_ARITHMETIC_DF 5460 #define VSHF_DF(num_of_lanes, int_type) \ 5461 for (int i = 0; i < num_of_lanes; ++i) { \ 5462 Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \ 5465 switch (DecodeMsaDataFormat()) {
5467 VSHF_DF(kMSALanesByte, int8_t);
5470 VSHF_DF(kMSALanesHalf, int16_t);
5473 VSHF_DF(kMSALanesWord, int32_t);
5476 VSHF_DF(kMSALanesDword,
int64_t);
5489 #define INTERLEAVE_PACK_DF(num_of_lanes, int_type) \ 5490 for (int i = 0; i < num_of_lanes / 2; ++i) { \ 5491 Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \ 5494 switch (DecodeMsaDataFormat()) {
5496 INTERLEAVE_PACK_DF(kMSALanesByte, int8_t);
5499 INTERLEAVE_PACK_DF(kMSALanesHalf, int16_t);
5502 INTERLEAVE_PACK_DF(kMSALanesWord, int32_t);
5505 INTERLEAVE_PACK_DF(kMSALanesDword,
int64_t);
5511 #undef INTERLEAVE_PACK_DF 5513 #define MSA_3R_DF(elem, num_of_lanes) \ 5514 for (int i = 0; i < num_of_lanes; i++) { \ 5515 wd.elem[i] = Msa3RInstrHelper(opcode, wd.elem[i], ws.elem[i], wt.elem[i]); \ 5518 switch (DecodeMsaDataFormat()) {
5520 MSA_3R_DF(b, kMSALanesByte);
5523 MSA_3R_DF(h, kMSALanesHalf);
5526 MSA_3R_DF(w, kMSALanesWord);
5529 MSA_3R_DF(d, kMSALanesDword);
5537 set_msa_register(wd_reg(), &wd);
5541 template <
typename T_
int,
typename T_fp,
typename T_reg>
5542 void Msa3RFInstrHelper(
uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
5543 const T_int all_ones =
static_cast<T_int
>(-1);
5544 const T_fp s_element = *
reinterpret_cast<T_fp*
>(&ws);
5545 const T_fp t_element = *
reinterpret_cast<T_fp*
>(&wt);
5548 if (std::isnan(s_element) || std::isnan(t_element)) {
5555 if (s_element != t_element || std::isnan(s_element) ||
5556 std::isnan(t_element)) {
5563 if (s_element == t_element || std::isnan(s_element) ||
5564 std::isnan(t_element)) {
5571 if (s_element >= t_element || std::isnan(s_element) ||
5572 std::isnan(t_element)) {
5579 if (s_element < t_element || std::isnan(s_element) ||
5580 std::isnan(t_element)) {
5587 if (s_element > t_element || std::isnan(s_element) ||
5588 std::isnan(t_element)) {
5595 if (s_element <= t_element || std::isnan(s_element) ||
5596 std::isnan(t_element)) {
5603 if (std::isnan(s_element) || std::isnan(t_element)) {
5610 if (s_element != t_element || std::isnan(s_element) ||
5611 std::isnan(t_element)) {
5618 if (s_element == t_element || std::isnan(s_element) ||
5619 std::isnan(t_element)) {
5626 wd = bit_cast<T_int>(s_element + t_element);
5629 wd = bit_cast<T_int>(s_element - t_element);
5632 wd = bit_cast<T_int>(s_element * t_element);
5635 if (t_element == 0) {
5636 wd = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
5638 wd = bit_cast<T_int>(s_element / t_element);
5642 wd = bit_cast<T_int>(
5643 std::fma(s_element, t_element, *reinterpret_cast<T_fp*>(&wd)));
5646 wd = bit_cast<T_int>(
5647 std::fma(-s_element, t_element, *reinterpret_cast<T_fp*>(&wd)));
5650 wd = bit_cast<T_int>(std::ldexp(s_element, static_cast<int>(wt)));
5653 wd = bit_cast<T_int>(std::min(s_element, t_element));
5656 wd = bit_cast<T_int>(std::max(s_element, t_element));
5659 wd = bit_cast<T_int>(
5660 std::fabs(s_element) < std::fabs(t_element) ? s_element : t_element);
5663 wd = bit_cast<T_int>(
5664 std::fabs(s_element) > std::fabs(t_element) ? s_element : t_element);
5684 template <
typename T_
int,
typename T_
int_dbl,
typename T_reg>
5685 void Msa3RFInstrHelper2(
uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
5687 typedef typename std::make_unsigned<T_int_dbl>::type T_uint_dbl;
5688 const T_int max_int = std::numeric_limits<T_int>::max();
5689 const T_int min_int = std::numeric_limits<T_int>::min();
5690 const int shift = kBitsPerByte *
sizeof(T_int) - 1;
5691 const T_int_dbl reg_s = ws;
5692 const T_int_dbl reg_t = wt;
5693 T_int_dbl product, result;
5694 product = reg_s * reg_t;
5697 const T_int_dbl min_fix_dbl =
5698 bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
5699 const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5700 if (product == min_fix_dbl) {
5701 product = max_fix_dbl;
5703 wd =
static_cast<T_int
>(product >> shift);
5706 result = (product + (
static_cast<T_int_dbl
>(wd) << shift)) >> shift;
5707 wd =
static_cast<T_int
>(
5708 result > max_int ? max_int : result < min_int ? min_int : result);
5711 result = (-product + (
static_cast<T_int_dbl
>(wd) << shift)) >> shift;
5712 wd =
static_cast<T_int
>(
5713 result > max_int ? max_int : result < min_int ? min_int : result);
5716 const T_int_dbl min_fix_dbl =
5717 bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
5718 const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5719 if (product == min_fix_dbl) {
5720 wd =
static_cast<T_int
>(max_fix_dbl >> shift);
5723 wd =
static_cast<T_int
>((product + (1 << (shift - 1))) >> shift);
5726 result = (product + (
static_cast<T_int_dbl
>(wd) << shift) +
5727 (1 << (shift - 1))) >>
5729 wd =
static_cast<T_int
>(
5730 result > max_int ? max_int : result < min_int ? min_int : result);
5733 result = (-product + (
static_cast<T_int_dbl
>(wd) << shift) +
5734 (1 << (shift - 1))) >>
5736 wd =
static_cast<T_int
>(
5737 result > max_int ? max_int : result < min_int ? min_int : result);
5744 void Simulator::DecodeTypeMsa3RF() {
5745 DCHECK_EQ(kArchVariant, kMips64r6);
5746 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5747 uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
5748 msa_reg_t wd, ws, wt;
5749 if (opcode != FCAF) {
5750 get_msa_register(ws_reg(), &ws);
5751 get_msa_register(wt_reg(), &wt);
5759 #define PACK_FLOAT16(sign, exp, frac) \ 5760 static_cast<uint16_t>(((sign) << 15) + ((exp) << 10) + (frac)) 5761 #define FEXDO_DF(source, dst) \ 5764 aSign = element >> 31; \ 5765 aExp = element >> 23 & 0xFF; \ 5766 aFrac = element & 0x007FFFFF; \ 5767 if (aExp == 0xFF) { \ 5774 dst = PACK_FLOAT16(aSign, 0x1F, 0); \ 5776 } else if (aExp == 0 && aFrac == 0) { \ 5777 dst = PACK_FLOAT16(aSign, 0, 0); \ 5782 uint32_t increment; \ 5783 bool rounding_bumps_exp; \ 5784 aFrac |= 0x00800000; \ 5788 mask = 0x00FFFFFF; \ 5789 if (aExp >= -11) { \ 5790 mask >>= 11 + aExp; \ 5794 mask = 0x00001FFF; \ 5796 switch (MSACSR_ & 3) { \ 5797 case kRoundToNearest: \ 5798 increment = (mask + 1) >> 1; \ 5799 if ((aFrac & mask) == increment) { \ 5800 increment = aFrac & (increment << 1); \ 5803 case kRoundToPlusInf: \ 5804 increment = aSign ? 0 : mask; \ 5806 case kRoundToMinusInf: \ 5807 increment = aSign ? mask : 0; \ 5809 case kRoundToZero: \ 5813 rounding_bumps_exp = (aFrac + increment >= 0x01000000); \ 5814 if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) { \ 5815 dst = PACK_FLOAT16(aSign, 0x1F, 0); \ 5818 aFrac += increment; \ 5819 if (rounding_bumps_exp) { \ 5824 dst = PACK_FLOAT16(aSign, 0, 0); \ 5831 dst = PACK_FLOAT16(aSign, aExp, aFrac >> 13); \ 5834 switch (DecodeMsaDataFormat()) {
5836 for (
int i = 0;
i < kMSALanesWord;
i++) {
5837 uint_fast32_t element;
5838 uint_fast32_t aSign, aFrac;
5840 FEXDO_DF(ws.uw[
i], wd.uh[
i + kMSALanesHalf / 2])
5841 FEXDO_DF(wt.uw[
i], wd.uh[
i])
5845 for (
int i = 0;
i < kMSALanesDword;
i++) {
5846 wd.w[
i + kMSALanesWord / 2] = bit_cast<int32_t>(
5847 static_cast<float>(bit_cast<
double>(ws.d[
i])));
5848 wd.w[
i] = bit_cast<int32_t>(
5849 static_cast<float>(bit_cast<
double>(wt.d[
i])));
5859 #define FTQ_DF(source, dst, fp_type, int_type) \ 5860 element = bit_cast<fp_type>(source) * \ 5861 (1U << (sizeof(int_type) * kBitsPerByte - 1)); \ 5862 if (element > std::numeric_limits<int_type>::max()) { \ 5863 dst = std::numeric_limits<int_type>::max(); \ 5864 } else if (element < std::numeric_limits<int_type>::min()) { \ 5865 dst = std::numeric_limits<int_type>::min(); \ 5866 } else if (std::isnan(element)) { \ 5869 int_type fixed_point; \ 5870 round_according_to_msacsr(element, element, fixed_point); \ 5871 dst = fixed_point; \ 5874 switch (DecodeMsaDataFormat()) {
5876 for (
int i = 0;
i < kMSALanesWord;
i++) {
5878 FTQ_DF(ws.w[
i], wd.h[
i + kMSALanesHalf / 2],
float, int16_t)
5879 FTQ_DF(wt.w[
i], wd.h[
i],
float, int16_t)
5884 for (
int i = 0;
i < kMSALanesDword;
i++) {
5885 FTQ_DF(ws.d[
i], wd.w[
i + kMSALanesWord / 2],
double, int32_t)
5886 FTQ_DF(wt.d[
i], wd.w[
i],
double, int32_t)
5894 #define MSA_3RF_DF(T1, T2, Lanes, ws, wt, wd) \ 5895 for (int i = 0; i < Lanes; i++) { \ 5896 Msa3RFInstrHelper<T1, T2>(opcode, ws, wt, wd); \ 5898 #define MSA_3RF_DF2(T1, T2, Lanes, ws, wt, wd) \ 5899 for (int i = 0; i < Lanes; i++) { \ 5900 Msa3RFInstrHelper2<T1, T2>(opcode, ws, wt, wd); \ 5906 get_msa_register(wd_reg(), &wd);
5910 switch (DecodeMsaDataFormat()) {
5912 MSA_3RF_DF2(int16_t, int32_t, kMSALanesHalf, ws.h[
i], wt.h[
i],
5916 MSA_3RF_DF2(int32_t,
int64_t, kMSALanesWord, ws.w[
i], wt.w[
i],
5924 if (opcode == FMADD || opcode == FMSUB) {
5925 get_msa_register(wd_reg(), &wd);
5927 switch (DecodeMsaDataFormat()) {
5929 MSA_3RF_DF(int32_t,
float, kMSALanesWord, ws.w[
i], wt.w[
i], wd.w[
i])
5932 MSA_3RF_DF(
int64_t,
double, kMSALanesDword, ws.d[
i], wt.d[
i], wd.d[
i])
5941 set_msa_register(wd_reg(), &wd);
5945 void Simulator::DecodeTypeMsaVec() {
5946 DCHECK_EQ(kArchVariant, kMips64r6);
5947 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5948 uint32_t opcode = instr_.InstructionBits() & kMsaVECMask;
5949 msa_reg_t wd, ws, wt;
5951 get_msa_register(instr_.WsValue(), ws.d);
5952 get_msa_register(instr_.WtValue(), wt.d);
5953 if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
5954 get_msa_register(instr_.WdValue(), wd.d);
5957 for (
int i = 0;
i < kMSALanesDword;
i++) {
5960 wd.d[
i] = ws.d[
i] & wt.d[
i];
5963 wd.d[
i] = ws.d[
i] | wt.d[
i];
5966 wd.d[
i] = ~(ws.d[
i] | wt.d[
i]);
5969 wd.d[
i] = ws.d[
i] ^ wt.d[
i];
5972 wd.d[
i] = (wt.d[
i] & ws.d[
i]) | (~wt.d[
i] & wd.d[
i]);
5975 wd.d[
i] = (~wt.d[
i] & ws.d[
i]) | (wt.d[
i] & wd.d[
i]);
5978 wd.d[
i] = (~wd.d[
i] & ws.d[
i]) | (wd.d[
i] & wt.d[
i]);
5984 set_msa_register(instr_.WdValue(), wd.d);
5985 TraceMSARegWr(wd.d);
5988 void Simulator::DecodeTypeMsa2R() {
5989 DCHECK_EQ(kArchVariant, kMips64r6);
5990 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5991 uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
5995 switch (DecodeMsaDataFormat()) {
5997 int64_t rs = get_register(instr_.WsValue());
5998 for (
int i = 0;
i < kMSALanesByte;
i++) {
5999 wd.b[
i] = rs & 0xFFu;
6001 set_msa_register(instr_.WdValue(), wd.b);
6002 TraceMSARegWr(wd.b);
6006 int64_t rs = get_register(instr_.WsValue());
6007 for (
int i = 0;
i < kMSALanesHalf;
i++) {
6008 wd.h[
i] = rs & 0xFFFFu;
6010 set_msa_register(instr_.WdValue(), wd.h);
6011 TraceMSARegWr(wd.h);
6015 int64_t rs = get_register(instr_.WsValue());
6016 for (
int i = 0;
i < kMSALanesWord;
i++) {
6017 wd.w[
i] = rs & 0xFFFFFFFFu;
6019 set_msa_register(instr_.WdValue(), wd.w);
6020 TraceMSARegWr(wd.w);
6024 int64_t rs = get_register(instr_.WsValue());
6025 wd.d[0] = wd.d[1] = rs;
6026 set_msa_register(instr_.WdValue(), wd.d);
6027 TraceMSARegWr(wd.d);
6035 #define PCNT_DF(elem, num_of_lanes) \ 6036 get_msa_register(instr_.WsValue(), ws.elem); \ 6037 for (int i = 0; i < num_of_lanes; i++) { \ 6038 uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \ 6039 wd.elem[i] = base::bits::CountPopulation(u64elem); \ 6041 set_msa_register(instr_.WdValue(), wd.elem); \ 6042 TraceMSARegWr(wd.elem) 6044 switch (DecodeMsaDataFormat()) {
6046 PCNT_DF(ub, kMSALanesByte);
6049 PCNT_DF(uh, kMSALanesHalf);
6052 PCNT_DF(uw, kMSALanesWord);
6055 PCNT_DF(ud, kMSALanesDword);
6063 #define NLOC_DF(elem, num_of_lanes) \ 6064 get_msa_register(instr_.WsValue(), ws.elem); \ 6065 for (int i = 0; i < num_of_lanes; i++) { \ 6066 const uint64_t mask = (num_of_lanes == kMSALanesDword) \ 6068 : (1ULL << (kMSARegSize / num_of_lanes)) - 1; \ 6069 uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask; \ 6070 wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \ 6071 (64 - kMSARegSize / num_of_lanes); \ 6073 set_msa_register(instr_.WdValue(), wd.elem); \ 6074 TraceMSARegWr(wd.elem) 6076 switch (DecodeMsaDataFormat()) {
6078 NLOC_DF(ub, kMSALanesByte);
6081 NLOC_DF(uh, kMSALanesHalf);
6084 NLOC_DF(uw, kMSALanesWord);
6087 NLOC_DF(ud, kMSALanesDword);
6095 #define NLZC_DF(elem, num_of_lanes) \ 6096 get_msa_register(instr_.WsValue(), ws.elem); \ 6097 for (int i = 0; i < num_of_lanes; i++) { \ 6098 uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \ 6099 wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \ 6100 (64 - kMSARegSize / num_of_lanes); \ 6102 set_msa_register(instr_.WdValue(), wd.elem); \ 6103 TraceMSARegWr(wd.elem) 6105 switch (DecodeMsaDataFormat()) {
6107 NLZC_DF(ub, kMSALanesByte);
6110 NLZC_DF(uh, kMSALanesHalf);
6113 NLZC_DF(uw, kMSALanesWord);
6116 NLZC_DF(ud, kMSALanesDword);
6128 #define BIT(n) (0x1LL << n) 6129 #define QUIET_BIT_S(nan) (bit_cast<int32_t>(nan) & BIT(22)) 6130 #define QUIET_BIT_D(nan) (bit_cast<int64_t>(nan) & BIT(51)) 6131 static inline bool isSnan(
float fp) {
return !QUIET_BIT_S(fp); }
6132 static inline bool isSnan(
double fp) {
return !QUIET_BIT_D(fp); }
6136 template <
typename T_
int,
typename T_fp,
typename T_src,
typename T_dst>
6137 T_int Msa2RFInstrHelper(
uint32_t opcode, T_src src, T_dst& dst,
6139 typedef typename std::make_unsigned<T_int>::type T_uint;
6142 #define SNAN_BIT BIT(0) 6143 #define QNAN_BIT BIT(1) 6144 #define NEG_INFINITY_BIT BIT(2) 6145 #define NEG_NORMAL_BIT BIT(3) 6146 #define NEG_SUBNORMAL_BIT BIT(4) 6147 #define NEG_ZERO_BIT BIT(5) 6148 #define POS_INFINITY_BIT BIT(6) 6149 #define POS_NORMAL_BIT BIT(7) 6150 #define POS_SUBNORMAL_BIT BIT(8) 6151 #define POS_ZERO_BIT BIT(9) 6152 T_fp element = *
reinterpret_cast<T_fp*
>(&src);
6153 switch (std::fpclassify(element)) {
6155 if (std::signbit(element)) {
6156 dst = NEG_INFINITY_BIT;
6158 dst = POS_INFINITY_BIT;
6162 if (isSnan(element)) {
6169 if (std::signbit(element)) {
6170 dst = NEG_NORMAL_BIT;
6172 dst = POS_NORMAL_BIT;
6176 if (std::signbit(element)) {
6177 dst = NEG_SUBNORMAL_BIT;
6179 dst = POS_SUBNORMAL_BIT;
6183 if (std::signbit(element)) {
6197 #undef NEG_INFINITY_BIT 6198 #undef NEG_NORMAL_BIT 6199 #undef NEG_SUBNORMAL_BIT 6201 #undef POS_INFINITY_BIT 6202 #undef POS_NORMAL_BIT 6203 #undef POS_SUBNORMAL_BIT 6206 T_fp element = bit_cast<T_fp>(src);
6207 const T_int max_int = std::numeric_limits<T_int>::max();
6208 const T_int min_int = std::numeric_limits<T_int>::min();
6209 if (std::isnan(element)) {
6211 }
else if (element >= max_int || element <= min_int) {
6212 dst = element >= max_int ? max_int : min_int;
6214 dst =
static_cast<T_int
>(std::trunc(element));
6219 T_fp element = bit_cast<T_fp>(src);
6220 const T_uint max_int = std::numeric_limits<T_uint>::max();
6221 if (std::isnan(element)) {
6223 }
else if (element >= max_int || element <= 0) {
6224 dst = element >= max_int ? max_int : 0;
6226 dst =
static_cast<T_uint
>(std::trunc(element));
6231 T_fp element = bit_cast<T_fp>(src);
6232 if (element < 0 || std::isnan(element)) {
6233 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6235 dst = bit_cast<T_int>(std::sqrt(element));
6240 T_fp element = bit_cast<T_fp>(src);
6241 if (element < 0 || std::isnan(element)) {
6242 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6244 dst = bit_cast<T_int>(1 / std::sqrt(element));
6249 T_fp element = bit_cast<T_fp>(src);
6250 if (std::isnan(element)) {
6251 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6253 dst = bit_cast<T_int>(1 / element);
6258 T_fp element = bit_cast<T_fp>(src);
6259 if (std::isnan(element)) {
6260 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6263 sim->round_according_to_msacsr<T_fp, T_int>(element, element, dummy);
6264 dst = bit_cast<T_int>(element);
6269 T_fp element = bit_cast<T_fp>(src);
6270 switch (std::fpclassify(element)) {
6273 dst = bit_cast<T_int>(std::logb(element));
6276 dst = bit_cast<T_int>(-std::numeric_limits<T_fp>::infinity());
6279 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6283 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6285 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::infinity());
6294 T_fp element = bit_cast<T_fp>(src);
6295 const T_int max_int = std::numeric_limits<T_int>::max();
6296 const T_int min_int = std::numeric_limits<T_int>::min();
6297 if (std::isnan(element)) {
6299 }
else if (element < min_int || element > max_int) {
6300 dst = element > max_int ? max_int : min_int;
6302 sim->round_according_to_msacsr<T_fp, T_int>(element, element, dst);
6307 T_fp element = bit_cast<T_fp>(src);
6308 const T_uint max_uint = std::numeric_limits<T_uint>::max();
6309 if (std::isnan(element)) {
6311 }
else if (element < 0 || element > max_uint) {
6312 dst = element > max_uint ? max_uint : 0;
6315 sim->round_according_to_msacsr<T_fp, T_uint>(element, element, res);
6316 dst = *
reinterpret_cast<T_int*
>(&res);
6321 dst = bit_cast<T_int>(
static_cast<T_fp
>(src));
6324 typedef typename std::make_unsigned<T_src>::type uT_src;
6325 dst = bit_cast<T_int>(
static_cast<T_fp
>(bit_cast<uT_src>(src)));
6333 template <
typename T_
int,
typename T_fp,
typename T_reg>
6334 T_int Msa2RFInstrHelper2(
uint32_t opcode, T_reg ws,
int i) {
6336 #define EXTRACT_FLOAT16_SIGN(fp16) (fp16 >> 15) 6337 #define EXTRACT_FLOAT16_EXP(fp16) (fp16 >> 10 & 0x1F) 6338 #define EXTRACT_FLOAT16_FRAC(fp16) (fp16 & 0x3FF) 6339 #define PACK_FLOAT32(sign, exp, frac) \ 6340 static_cast<uint32_t>(((sign) << 31) + ((exp) << 23) + (frac)) 6341 #define FEXUP_DF(src_index) \ 6342 uint_fast16_t element = ws.uh[src_index]; \ 6343 uint_fast32_t aSign, aFrac; \ 6344 int_fast32_t aExp; \ 6345 aSign = EXTRACT_FLOAT16_SIGN(element); \ 6346 aExp = EXTRACT_FLOAT16_EXP(element); \ 6347 aFrac = EXTRACT_FLOAT16_FRAC(element); \ 6348 if (V8_LIKELY(aExp && aExp != 0x1F)) { \ 6349 return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \ 6350 } else if (aExp == 0x1F) { \ 6352 return bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN()); \ 6354 return bit_cast<uint32_t>(std::numeric_limits<float>::infinity()) | \ 6355 static_cast<uint32_t>(aSign) << 31; \ 6359 return PACK_FLOAT32(aSign, 0, 0); \ 6361 int_fast16_t shiftCount = \ 6362 base::bits::CountLeadingZeros32(static_cast<uint32_t>(aFrac)) - 21; \ 6363 aFrac <<= shiftCount; \ 6364 aExp = -shiftCount; \ 6365 return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \ 6369 if (std::is_same<int32_t, T_int>::value) {
6370 FEXUP_DF(
i + kMSALanesWord)
6373 static_cast<double>(bit_cast<
float>(ws.w[
i + kMSALanesDword])));
6376 if (std::is_same<int32_t, T_int>::value) {
6379 return bit_cast<
int64_t>(
static_cast<double>(bit_cast<
float>(ws.w[
i])));
6382 if (std::is_same<int32_t, T_int>::value) {
6383 return bit_cast<int32_t>(
static_cast<float>(ws.h[
i + kMSALanesWord]) /
6386 return bit_cast<
int64_t>(
static_cast<double>(ws.w[
i + kMSALanesDword]) /
6392 if (std::is_same<int32_t, T_int>::value) {
6393 return bit_cast<int32_t>(
static_cast<float>(ws.h[
i]) / (1U << 15));
6395 return bit_cast<
int64_t>(
static_cast<double>(ws.w[
i]) / (1U << 31));
6402 #undef EXTRACT_FLOAT16_SIGN 6403 #undef EXTRACT_FLOAT16_EXP 6404 #undef EXTRACT_FLOAT16_FRAC 6409 void Simulator::DecodeTypeMsa2RF() {
6410 DCHECK_EQ(kArchVariant, kMips64r6);
6411 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
6412 uint32_t opcode = instr_.InstructionBits() & kMsa2RFMask;
6414 get_msa_register(ws_reg(), &ws);
6415 if (opcode == FEXUPL || opcode == FEXUPR || opcode == FFQL ||
6417 switch (DecodeMsaDataFormat()) {
6419 for (
int i = 0;
i < kMSALanesWord;
i++) {
6420 wd.w[
i] = Msa2RFInstrHelper2<int32_t, float>(opcode, ws,
i);
6424 for (
int i = 0;
i < kMSALanesDword;
i++) {
6425 wd.d[
i] = Msa2RFInstrHelper2<int64_t, double>(opcode, ws,
i);
6432 switch (DecodeMsaDataFormat()) {
6434 for (
int i = 0;
i < kMSALanesWord;
i++) {
6435 Msa2RFInstrHelper<int32_t, float>(opcode, ws.w[
i], wd.w[
i],
this);
6439 for (
int i = 0;
i < kMSALanesDword;
i++) {
6440 Msa2RFInstrHelper<int64_t, double>(opcode, ws.d[
i], wd.d[
i],
this);
6447 set_msa_register(wd_reg(), &wd);
6451 void Simulator::DecodeTypeRegister() {
6453 switch (instr_.OpcodeFieldRaw()) {
6455 DecodeTypeRegisterCOP1();
6458 DecodeTypeRegisterCOP1X();
6461 DecodeTypeRegisterSPECIAL();
6464 DecodeTypeRegisterSPECIAL2();
6467 DecodeTypeRegisterSPECIAL3();
6470 switch (instr_.MSAMinorOpcodeField()) {
6503 void Simulator::DecodeTypeImmediate() {
6505 Opcode op = instr_.OpcodeFieldRaw();
6506 int32_t rs_reg = instr_.RsValue();
6507 int64_t rs = get_register(instr_.RsValue());
6508 uint64_t rs_u =
static_cast<uint64_t
>(rs);
6509 int32_t rt_reg = instr_.RtValue();
6510 int64_t rt = get_register(rt_reg);
6511 int16_t imm16 = instr_.Imm16Value();
6512 int32_t imm18 = instr_.Imm18Value();
6514 int32_t ft_reg = instr_.FtValue();
6517 uint64_t oe_imm16 = 0xFFFF & imm16;
6520 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xFFFFFFFFFFFC0000 : 0);
6526 bool execute_branch_delay_instruction =
false;
6534 const int kInt32AlignmentMask =
sizeof(
uint32_t) - 1;
6536 const int kInt64AlignmentMask =
sizeof(uint64_t) - 1;
6539 auto BranchAndLinkHelper =
6540 [
this, &next_pc, &execute_branch_delay_instruction](
bool do_branch) {
6541 execute_branch_delay_instruction =
true;
6542 int64_t current_pc = get_pc();
6543 set_register(31, current_pc + 2 * kInstrSize);
6545 int16_t imm16 = instr_.Imm16Value();
6546 next_pc = current_pc + (imm16 << 2) + kInstrSize;
6548 next_pc = current_pc + 2 * kInstrSize;
6552 auto BranchHelper = [
this, &next_pc,
6553 &execute_branch_delay_instruction](
bool do_branch) {
6554 execute_branch_delay_instruction =
true;
6555 int64_t current_pc = get_pc();
6557 int16_t imm16 = instr_.Imm16Value();
6558 next_pc = current_pc + (imm16 << 2) + kInstrSize;
6560 next_pc = current_pc + 2 * kInstrSize;
6564 auto BranchHelper_MSA = [
this, &next_pc, imm16,
6565 &execute_branch_delay_instruction](
bool do_branch) {
6566 execute_branch_delay_instruction =
true;
6567 int64_t current_pc = get_pc();
6568 const int32_t bitsIn16Int =
sizeof(int16_t) * kBitsPerByte;
6570 if (FLAG_debug_code) {
6571 int16_t bits = imm16 & 0xFC;
6575 CHECK_EQ(bits ^ 0xFC, 0);
6580 int16_t offset =
static_cast<int16_t
>(imm16 << (bitsIn16Int - 10)) >>
6582 next_pc = current_pc + offset + kInstrSize;
6584 next_pc = current_pc + 2 * kInstrSize;
6588 auto BranchAndLinkCompactHelper = [
this, &next_pc](
bool do_branch,
int bits) {
6589 int64_t current_pc = get_pc();
6590 CheckForbiddenSlot(current_pc);
6592 int32_t imm = instr_.ImmValue(bits);
6595 next_pc = current_pc + (imm << 2) + kInstrSize;
6596 set_register(31, current_pc + kInstrSize);
6600 auto BranchCompactHelper = [
this, &next_pc](
bool do_branch,
int bits) {
6601 int64_t current_pc = get_pc();
6602 CheckForbiddenSlot(current_pc);
6604 int32_t imm = instr_.ImmValue(bits);
6607 next_pc = get_pc() + (imm << 2) + kInstrSize;
6614 switch (instr_.RsFieldRaw()) {
6617 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
6618 uint32_t cc_value = test_fcsr_bit(fcsr_cc);
6619 bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value;
6620 BranchHelper(do_branch);
6624 BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
6627 BranchHelper(get_fpu_register(ft_reg) & 0x1);
6631 get_msa_register(wt_reg(), &wt);
6632 BranchHelper_MSA(wt.d[0] == 0 && wt.d[1] == 0);
6634 #define BZ_DF(witdh, lanes) \ 6637 get_msa_register(wt_reg(), &wt); \ 6639 for (i = 0; i < lanes; ++i) { \ 6640 if (wt.witdh[i] == 0) { \ 6644 BranchHelper_MSA(i != lanes); \ 6647 BZ_DF(b, kMSALanesByte)
6650 BZ_DF(h, kMSALanesHalf)
6653 BZ_DF(w, kMSALanesWord)
6656 BZ_DF(d, kMSALanesDword)
6661 get_msa_register(wt_reg(), &wt);
6662 BranchHelper_MSA(wt.d[0] != 0 || wt.d[1] != 0);
6664 #define BNZ_DF(witdh, lanes) \ 6667 get_msa_register(wt_reg(), &wt); \ 6669 for (i = 0; i < lanes; ++i) { \ 6670 if (wt.witdh[i] == 0) { \ 6674 BranchHelper_MSA(i == lanes); \ 6677 BNZ_DF(b, kMSALanesByte)
6680 BNZ_DF(h, kMSALanesHalf)
6683 BNZ_DF(w, kMSALanesWord)
6686 BNZ_DF(d, kMSALanesDword)
6695 switch (instr_.RtFieldRaw()) {
6697 BranchHelper(rs < 0);
6700 BranchHelper(rs >= 0);
6703 BranchAndLinkHelper(rs < 0);
6706 BranchAndLinkHelper(rs >= 0);
6709 SetResult(rs_reg, rs + (se_imm16 << 32));
6712 SetResult(rs_reg, rs + (se_imm16 << 48));
6722 BranchHelper(rs == rt);
6725 BranchHelper(rs != rt);
6728 if (kArchVariant == kMips64r6) {
6731 BranchAndLinkCompactHelper(rt <= 0, 16);
6733 if (rs_reg == rt_reg) {
6734 BranchAndLinkCompactHelper(rt >= 0, 16);
6736 BranchCompactHelper(
6737 static_cast<uint64_t>(rs) >= static_cast<uint64_t>(rt), 16);
6741 BranchHelper(rs <= 0);
6744 BranchHelper(rs <= 0);
6748 if (kArchVariant == kMips64r6) {
6751 BranchAndLinkCompactHelper(rt > 0, 16);
6753 if (rt_reg == rs_reg) {
6754 BranchAndLinkCompactHelper(rt < 0, 16);
6756 BranchCompactHelper(
6757 static_cast<uint64_t>(rs) < static_cast<uint64_t>(rt), 16);
6761 BranchHelper(rs > 0);
6764 BranchHelper(rs > 0);
6768 if (kArchVariant == kMips64r6) {
6771 BranchCompactHelper(rt <= 0, 16);
6773 if (rs_reg == rt_reg) {
6774 BranchCompactHelper(rt >= 0, 16);
6776 BranchCompactHelper(rs >= rt, 16);
6781 BranchAndLinkHelper(rs <= 0);
6785 if (kArchVariant == kMips64r6) {
6788 BranchCompactHelper(rt > 0, 16);
6790 if (rs_reg == rt_reg) {
6791 BranchCompactHelper(rt < 0, 16);
6793 BranchCompactHelper(rs < rt, 16);
6798 BranchAndLinkHelper(rs > 0);
6803 BranchCompactHelper(rs == 0, 21);
6805 next_pc = rt + imm16;
6810 BranchCompactHelper(rs != 0, 21);
6812 int64_t current_pc = get_pc();
6813 set_register(31, current_pc + kInstrSize);
6814 next_pc = rt + imm16;
6818 BranchCompactHelper(
true, 26);
6821 BranchAndLinkCompactHelper(
true, 26);
6824 if (kArchVariant == kMips64r6) {
6825 if (rs_reg >= rt_reg) {
6826 bool condition = !is_int32(rs) || !is_int32(rt) || !is_int32(rs + rt);
6827 BranchCompactHelper(condition, 16);
6830 BranchAndLinkCompactHelper(rt == 0, 16);
6832 BranchCompactHelper(rt == rs, 16);
6836 if (HaveSameSign(rs, se_imm16)) {
6838 if (rs <= Registers::kMaxValue - se_imm16) {
6839 SignalException(kIntegerOverflow);
6841 }
else if (rs < 0) {
6842 if (rs >= Registers::kMinValue - se_imm16) {
6843 SignalException(kIntegerUnderflow);
6847 SetResult(rt_reg, rs + se_imm16);
6851 if (kArchVariant == kMips64r6) {
6852 if (rs_reg >= rt_reg) {
6853 bool condition = is_int32(rs) && is_int32(rt) && is_int32(rs + rt);
6854 BranchCompactHelper(condition, 16);
6857 BranchAndLinkCompactHelper(rt != 0, 16);
6859 BranchCompactHelper(rt != rs, 16);
6866 int32_t alu32_out =
static_cast<int32_t
>(rs + se_imm16);
6868 SetResult(rt_reg, static_cast<int64_t>(alu32_out));
6872 SetResult(rt_reg, rs + se_imm16);
6875 SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
6878 SetResult(rt_reg, rs_u < static_cast<uint64_t>(se_imm16) ? 1 : 0);
6881 SetResult(rt_reg, rs & oe_imm16);
6884 SetResult(rt_reg, rs | oe_imm16);
6887 SetResult(rt_reg, rs ^ oe_imm16);
6892 DCHECK_EQ(kArchVariant, kMips64r6);
6893 int32_t alu32_out =
static_cast<int32_t
>(rs + (se_imm16 << 16));
6894 SetResult(rt_reg, static_cast<int64_t>(alu32_out));
6897 int32_t alu32_out =
static_cast<int32_t
>(oe_imm16 << 16);
6899 SetResult(rt_reg, static_cast<int64_t>(alu32_out));
6903 DCHECK_EQ(kArchVariant, kMips64r6);
6904 DCHECK_NE(rs_reg, 0);
6905 SetResult(rt_reg, rs + (se_imm16 << 16));
6909 set_register(rt_reg, ReadB(rs + se_imm16));
6912 set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr()));
6916 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
6917 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
6918 uint32_t mask = (1 << byte_shift * 8) - 1;
6919 addr = rs + se_imm16 - al_offset;
6920 int32_t val = ReadW(addr, instr_.instr());
6921 val <<= byte_shift * 8;
6923 set_register(rt_reg, static_cast<int64_t>(val));
6927 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
6930 set_register(rt_reg, ReadWU(rs + se_imm16, instr_.instr()));
6933 set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr()));
6936 set_register(rt_reg, ReadBU(rs + se_imm16));
6939 set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr()));
6943 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
6944 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
6945 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
6946 addr = rs + se_imm16 - al_offset;
6947 alu_out = ReadW(addr, instr_.instr());
6948 alu_out =
static_cast<uint32_t> (alu_out) >> al_offset * 8;
6949 alu_out |= rt & mask;
6950 set_register(rt_reg, alu_out);
6955 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
6956 uint8_t byte_shift = kInt64AlignmentMask - al_offset;
6957 uint64_t mask = (1UL << byte_shift * 8) - 1;
6958 addr = rs + se_imm16 - al_offset;
6959 alu_out = Read2W(addr, instr_.instr());
6960 alu_out <<= byte_shift * 8;
6961 alu_out |= rt & mask;
6962 set_register(rt_reg, alu_out);
6967 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
6968 uint8_t byte_shift = kInt64AlignmentMask - al_offset;
6969 uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL;
6970 addr = rs + se_imm16 - al_offset;
6971 alu_out = Read2W(addr, instr_.instr());
6972 alu_out = alu_out >> al_offset * 8;
6973 alu_out |= rt & mask;
6974 set_register(rt_reg, alu_out);
6978 WriteB(rs + se_imm16, static_cast<int8_t>(rt));
6981 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr());
6984 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
6985 uint8_t byte_shift = kInt32AlignmentMask - al_offset;
6986 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
6987 addr = rs + se_imm16 - al_offset;
6988 uint64_t mem_value = ReadW(addr, instr_.instr()) & mask;
6989 mem_value |=
static_cast<uint32_t>(rt) >> byte_shift * 8;
6990 WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr());
6994 WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr_.instr());
6997 Write2W(rs + se_imm16, rt, instr_.instr());
7000 uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
7001 uint32_t mask = (1 << al_offset * 8) - 1;
7002 addr = rs + se_imm16 - al_offset;
7003 uint64_t mem_value = ReadW(addr, instr_.instr());
7004 mem_value = (rt << al_offset * 8) | (mem_value & mask);
7005 WriteW(addr, static_cast<int32_t>(mem_value), instr_.instr());
7009 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7010 uint8_t byte_shift = kInt64AlignmentMask - al_offset;
7011 uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0;
7012 addr = rs + se_imm16 - al_offset;
7013 uint64_t mem_value = Read2W(addr, instr_.instr()) & mask;
7014 mem_value |=
static_cast<uint64_t
>(rt) >> byte_shift * 8;
7015 Write2W(addr, mem_value, instr_.instr());
7019 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
7020 uint64_t mask = (1UL << al_offset * 8) - 1;
7021 addr = rs + se_imm16 - al_offset;
7022 uint64_t mem_value = Read2W(addr, instr_.instr());
7023 mem_value = (rt << al_offset * 8) | (mem_value & mask);
7024 Write2W(addr, mem_value, instr_.instr());
7029 DCHECK_EQ(kArchVariant, kMips64r2);
7030 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
7035 DCHECK_EQ(kArchVariant, kMips64r2);
7036 WriteW(rs + se_imm16, static_cast<int32_t>(rt), instr_.instr());
7037 set_register(rt_reg, 1);
7042 DCHECK_EQ(kArchVariant, kMips64r2);
7043 set_register(rt_reg, Read2W(rs + se_imm16, instr_.instr()));
7048 DCHECK_EQ(kArchVariant, kMips64r2);
7049 Write2W(rs + se_imm16, rt, instr_.instr());
7050 set_register(rt_reg, 1);
7054 set_fpu_register(ft_reg, kFPUInvalidResult);
7055 set_fpu_register_word(ft_reg,
7056 ReadW(rs + se_imm16, instr_.instr(), FLOAT_DOUBLE));
7059 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr()));
7060 TraceMemRd(addr, get_fpu_register(ft_reg), DOUBLE);
7063 int32_t alu_out_32 =
static_cast<int32_t
>(get_fpu_register(ft_reg));
7064 WriteW(rs + se_imm16, alu_out_32, instr_.instr());
7068 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr());
7069 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg), DWORD);
7074 int32_t imm21 = instr_.Imm21Value();
7075 int64_t current_pc = get_pc();
7076 uint8_t rt = (imm21 >> kImm16Bits);
7079 addr = current_pc + (se_imm16 << 16);
7080 alu_out =
static_cast<int64_t>(~0x0FFFF) & addr;
7083 alu_out = current_pc + (se_imm16 << 16);
7086 int32_t imm19 = instr_.Imm19Value();
7088 rt = (imm21 >> kImm18Bits);
7092 (current_pc &
static_cast<int64_t>(~0x7)) + (se_imm18 << 3);
7093 alu_out = Read2W(addr, instr_.instr());
7097 rt = (imm21 >> kImm19Bits);
7101 imm19 <<= (kOpcodeBits + kRsBits + 2);
7102 imm19 >>= (kOpcodeBits + kRsBits + 2);
7103 addr = current_pc + (imm19 << 2);
7110 imm19 <<= (kOpcodeBits + kRsBits + 2);
7111 imm19 >>= (kOpcodeBits + kRsBits + 2);
7112 addr = current_pc + (imm19 << 2);
7113 int32_t* ptr =
reinterpret_cast<int32_t*
>(addr);
7119 imm19 | ((imm19 & 0x40000) ? 0xFFFFFFFFFFF80000 : 0);
7120 alu_out = current_pc + (se_imm19 << 2);
7133 SetResult(rs_reg, alu_out);
7137 switch (instr_.FunctionFieldRaw()) {
7140 DCHECK_EQ(kArchVariant, kMips64r6);
7141 int64_t base = get_register(instr_.BaseValue());
7142 int32_t offset9 = instr_.Imm9Value();
7143 set_register(rt_reg, ReadW(base + offset9, instr_.instr()));
7148 DCHECK_EQ(kArchVariant, kMips64r6);
7149 int64_t base = get_register(instr_.BaseValue());
7150 int32_t offset9 = instr_.Imm9Value();
7151 set_register(rt_reg, Read2W(base + offset9, instr_.instr()));
7156 DCHECK_EQ(kArchVariant, kMips64r6);
7157 int64_t base = get_register(instr_.BaseValue());
7158 int32_t offset9 = instr_.Imm9Value();
7159 WriteW(base + offset9, static_cast<int32_t>(rt), instr_.instr());
7160 set_register(rt_reg, 1);
7165 DCHECK_EQ(kArchVariant, kMips64r6);
7166 int64_t base = get_register(instr_.BaseValue());
7167 int32_t offset9 = instr_.Imm9Value();
7168 Write2W(base + offset9, rt, instr_.instr());
7169 set_register(rt_reg, 1);
7179 switch (instr_.MSAMinorOpcodeField()) {
7196 DecodeTypeMsaMI10();
7207 if (execute_branch_delay_instruction) {
7211 Instruction* branch_delay_instr =
7212 reinterpret_cast<Instruction*
>(get_pc() + kInstrSize);
7213 BranchDelayInstructionDecode(branch_delay_instr);
7217 if (next_pc != bad_ra) {
7224 void Simulator::DecodeTypeJump() {
7225 SimInstruction simInstr = instr_;
7227 int64_t current_pc = get_pc();
7229 int64_t pc_high_bits = current_pc & 0xFFFFFFFFF0000000;
7231 int64_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2);
7236 Instruction* branch_delay_instr =
7237 reinterpret_cast<Instruction*
>(current_pc + kInstrSize);
7238 BranchDelayInstructionDecode(branch_delay_instr);
7242 if (simInstr.IsLinkingInstruction()) {
7243 set_register(31, current_pc + 2 * kInstrSize);
7246 pc_modified_ =
true;
7251 void Simulator::InstructionDecode(Instruction* instr) {
7252 if (v8::internal::FLAG_check_icache) {
7253 CheckICache(i_cache(), instr);
7255 pc_modified_ =
false;
7259 if (::v8::internal::FLAG_trace_sim) {
7260 SNPrintF(trace_buf_,
" ");
7264 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
7268 switch (instr_.InstructionType()) {
7269 case Instruction::kRegisterType:
7270 DecodeTypeRegister();
7272 case Instruction::kImmediateType:
7273 DecodeTypeImmediate();
7275 case Instruction::kJumpType:
7282 if (::v8::internal::FLAG_trace_sim) {
7283 PrintF(
" 0x%08" PRIxPTR
" %-44s %s\n",
7284 reinterpret_cast<intptr_t>(instr), buffer.start(),
7285 trace_buf_.start());
7288 if (!pc_modified_) {
7289 set_register(pc, reinterpret_cast<int64_t>(instr) + kInstrSize);
7295 void Simulator::Execute() {
7298 int64_t program_counter = get_pc();
7299 if (::v8::internal::FLAG_stop_sim_at == 0) {
7302 while (program_counter != end_sim_pc) {
7303 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
7305 InstructionDecode(instr);
7306 program_counter = get_pc();
7311 while (program_counter != end_sim_pc) {
7312 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
7314 if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) {
7315 MipsDebugger dbg(
this);
7318 InstructionDecode(instr);
7320 program_counter = get_pc();
7325 void Simulator::CallInternal(Address entry) {
7327 isolate_->stack_guard()->AdjustStackLimitForSimulator();
7330 set_register(pc, static_cast<int64_t>(entry));
7334 set_register(ra, end_sim_pc);
7339 int64_t s0_val = get_register(s0);
7340 int64_t s1_val = get_register(s1);
7341 int64_t s2_val = get_register(s2);
7342 int64_t s3_val = get_register(s3);
7343 int64_t s4_val = get_register(s4);
7344 int64_t s5_val = get_register(s5);
7345 int64_t s6_val = get_register(s6);
7346 int64_t s7_val = get_register(s7);
7347 int64_t gp_val = get_register(gp);
7348 int64_t sp_val = get_register(sp);
7349 int64_t fp_val = get_register(fp);
7353 int64_t callee_saved_value = icount_;
7354 set_register(s0, callee_saved_value);
7355 set_register(s1, callee_saved_value);
7356 set_register(s2, callee_saved_value);
7357 set_register(s3, callee_saved_value);
7358 set_register(s4, callee_saved_value);
7359 set_register(s5, callee_saved_value);
7360 set_register(s6, callee_saved_value);
7361 set_register(s7, callee_saved_value);
7362 set_register(gp, callee_saved_value);
7363 set_register(fp, callee_saved_value);
7369 CHECK_EQ(callee_saved_value, get_register(s0));
7370 CHECK_EQ(callee_saved_value, get_register(s1));
7371 CHECK_EQ(callee_saved_value, get_register(s2));
7372 CHECK_EQ(callee_saved_value, get_register(s3));
7373 CHECK_EQ(callee_saved_value, get_register(s4));
7374 CHECK_EQ(callee_saved_value, get_register(s5));
7375 CHECK_EQ(callee_saved_value, get_register(s6));
7376 CHECK_EQ(callee_saved_value, get_register(s7));
7377 CHECK_EQ(callee_saved_value, get_register(gp));
7378 CHECK_EQ(callee_saved_value, get_register(fp));
7381 set_register(s0, s0_val);
7382 set_register(s1, s1_val);
7383 set_register(s2, s2_val);
7384 set_register(s3, s3_val);
7385 set_register(s4, s4_val);
7386 set_register(s5, s5_val);
7387 set_register(s6, s6_val);
7388 set_register(s7, s7_val);
7389 set_register(gp, gp_val);
7390 set_register(sp, sp_val);
7391 set_register(fp, fp_val);
7394 intptr_t Simulator::CallImpl(Address entry,
int argument_count,
7395 const intptr_t* arguments) {
7396 constexpr
int kRegisterPassedArguments = 8;
7400 int reg_arg_count = std::min(kRegisterPassedArguments, argument_count);
7401 if (reg_arg_count > 0) set_register(a0, arguments[0]);
7402 if (reg_arg_count > 1) set_register(a1, arguments[1]);
7403 if (reg_arg_count > 2) set_register(a2, arguments[2]);
7404 if (reg_arg_count > 2) set_register(a3, arguments[3]);
7408 if (reg_arg_count > 4) set_register(a4, arguments[4]);
7409 if (reg_arg_count > 5) set_register(a5, arguments[5]);
7410 if (reg_arg_count > 6) set_register(a6, arguments[6]);
7411 if (reg_arg_count > 7) set_register(a7, arguments[7]);
7414 int64_t original_stack = get_register(sp);
7416 int stack_args_count = argument_count - reg_arg_count;
7417 int stack_args_size = stack_args_count *
sizeof(*arguments) + kCArgsSlotsSize;
7418 int64_t entry_stack = original_stack - stack_args_size;
7420 if (base::OS::ActivationFrameAlignment() != 0) {
7421 entry_stack &= -base::OS::ActivationFrameAlignment();
7424 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
7425 memcpy(stack_argument + kCArgSlotCount, arguments + reg_arg_count,
7426 stack_args_count *
sizeof(*arguments));
7427 set_register(sp, entry_stack);
7429 CallInternal(entry);
7432 CHECK_EQ(entry_stack, get_register(sp));
7433 set_register(sp, original_stack);
7435 return get_register(v0);
7438 double Simulator::CallFP(Address entry,
double d0,
double d1) {
7439 if (!IsMipsSoftFloatABI) {
7440 const FPURegister fparg2 = f13;
7441 set_fpu_register_double(f12, d0);
7442 set_fpu_register_double(fparg2, d1);
7445 DCHECK(
sizeof(buffer[0]) * 2 ==
sizeof(d0));
7446 memcpy(buffer, &d0,
sizeof(d0));
7447 set_dw_register(a0, buffer);
7448 memcpy(buffer, &d1,
sizeof(d1));
7449 set_dw_register(a2, buffer);
7451 CallInternal(entry);
7452 if (!IsMipsSoftFloatABI) {
7453 return get_fpu_register_double(f0);
7455 return get_double_from_register_pair(v0);
7463 *stack_slot = address;
7464 set_register(sp, new_sp);
7470 int64_t current_sp = get_register(sp);
7473 set_register(sp, current_sp +
sizeof(
uintptr_t));
7482 #endif // USE_SIMULATOR 7484 #endif // V8_TARGET_ARCH_MIPS64