10 #if V8_TARGET_ARCH_MIPS 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/mips/constants-mips.h" 18 #include "src/mips/simulator-mips.h" 19 #include "src/ostreams.h" 20 #include "src/runtime/runtime-utils.h" 24 #if defined(USE_SIMULATOR) 30 bool HaveSameSign(int32_t a, int32_t b) {
31 return ((a ^ b) >= 0);
48 #define SScanF sscanf // NOLINT 54 explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
56 void Stop(Instruction* instr);
60 void PrintAllRegsIncludingFPU();
64 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xFFFFF << 6;
65 static const Instr kNopInstr = 0x0;
69 int32_t GetRegisterValue(
int regnum);
70 int32_t GetFPURegisterValue32(
int regnum);
71 int64_t GetFPURegisterValue64(
int regnum);
72 float GetFPURegisterValueFloat(
int regnum);
73 double GetFPURegisterValueDouble(
int regnum);
74 bool GetValue(
const char* desc, int32_t* value);
75 bool GetValue(
const char* desc,
int64_t* value);
78 bool SetBreakpoint(Instruction* breakpc);
79 bool DeleteBreakpoint(Instruction* breakpc);
83 void UndoBreakpoints();
84 void RedoBreakpoints();
88 #define UNSUPPORTED() printf("Sim: Unsupported instruction.\n"); 91 void MipsDebugger::Stop(Instruction* instr) {
94 PrintF(
"Simulator hit (%u)\n", code);
99 int32_t MipsDebugger::GetRegisterValue(
int regnum) {
100 if (regnum == kNumSimuRegisters) {
101 return sim_->get_pc();
103 return sim_->get_register(regnum);
108 int32_t MipsDebugger::GetFPURegisterValue32(
int regnum) {
109 if (regnum == kNumFPURegisters) {
110 return sim_->get_pc();
112 return sim_->get_fpu_register_word(regnum);
117 int64_t MipsDebugger::GetFPURegisterValue64(
int regnum) {
118 if (regnum == kNumFPURegisters) {
119 return sim_->get_pc();
121 return sim_->get_fpu_register(regnum);
126 float MipsDebugger::GetFPURegisterValueFloat(
int regnum) {
127 if (regnum == kNumFPURegisters) {
128 return sim_->get_pc();
130 return sim_->get_fpu_register_float(regnum);
135 double MipsDebugger::GetFPURegisterValueDouble(
int regnum) {
136 if (regnum == kNumFPURegisters) {
137 return sim_->get_pc();
139 return sim_->get_fpu_register_double(regnum);
144 bool MipsDebugger::GetValue(
const char* desc, int32_t* value) {
145 int regnum = Registers::Number(desc);
146 int fpuregnum = FPURegisters::Number(desc);
148 if (regnum != kInvalidRegister) {
149 *value = GetRegisterValue(regnum);
151 }
else if (fpuregnum != kInvalidFPURegister) {
152 *value = GetFPURegisterValue32(fpuregnum);
154 }
else if (strncmp(desc,
"0x", 2) == 0) {
155 return SScanF(desc,
"%x", reinterpret_cast<uint32_t*>(value)) == 1;
157 return SScanF(desc,
"%i", value) == 1;
163 bool MipsDebugger::GetValue(
const char* desc,
int64_t* value) {
164 int regnum = Registers::Number(desc);
165 int fpuregnum = FPURegisters::Number(desc);
167 if (regnum != kInvalidRegister) {
168 *value = GetRegisterValue(regnum);
170 }
else if (fpuregnum != kInvalidFPURegister) {
171 *value = GetFPURegisterValue64(fpuregnum);
173 }
else if (strncmp(desc,
"0x", 2) == 0) {
174 return SScanF(desc + 2,
"%" SCNx64,
175 reinterpret_cast<uint64_t*>(value)) == 1;
177 return SScanF(desc,
"%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
183 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
185 if (sim_->break_pc_ !=
nullptr) {
190 sim_->break_pc_ = breakpc;
191 sim_->break_instr_ = breakpc->InstructionBits();
198 bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
199 if (sim_->break_pc_ !=
nullptr) {
200 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
203 sim_->break_pc_ =
nullptr;
204 sim_->break_instr_ = 0;
209 void MipsDebugger::UndoBreakpoints() {
210 if (sim_->break_pc_ !=
nullptr) {
211 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
216 void MipsDebugger::RedoBreakpoints() {
217 if (sim_->break_pc_ !=
nullptr) {
218 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
223 void MipsDebugger::PrintAllRegs() {
224 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 228 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
229 REG_INFO(1), REG_INFO(2), REG_INFO(4));
231 PrintF(
"%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
232 "", REG_INFO(3), REG_INFO(5));
234 PrintF(
"%26s\t%26s\t%3s: 0x%08x %10d\n",
"",
"", REG_INFO(6));
236 PrintF(
"%26s\t%26s\t%3s: 0x%08x %10d\n",
"",
"", REG_INFO(7));
239 for (
int i = 0;
i < 8;
i++) {
240 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
241 REG_INFO(8+
i), REG_INFO(16+
i));
245 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
246 REG_INFO(24), REG_INFO(26), REG_INFO(32));
248 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
249 REG_INFO(25), REG_INFO(27), REG_INFO(33));
251 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
252 REG_INFO(29), REG_INFO(30), REG_INFO(28));
254 PrintF(
"%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
255 REG_INFO(31), REG_INFO(34));
262 void MipsDebugger::PrintAllRegsIncludingFPU() {
263 #define FPU_REG_INFO32(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \ 264 GetFPURegisterValue32(n+1), \ 265 GetFPURegisterValue32(n), \ 266 GetFPURegisterValueDouble(n) 268 #define FPU_REG_INFO64(n) FPURegisters::Name(n), \ 269 GetFPURegisterValue64(n), \ 270 GetFPURegisterValueDouble(n) 278 if (kFpuMode == kFP64) {
279 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(0) );
280 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(1) );
281 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(2) );
282 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(3) );
283 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(4) );
284 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(5) );
285 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(6) );
286 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(7) );
287 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(8) );
288 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(9) );
289 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(10));
290 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(11));
291 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(12));
292 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(13));
293 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(14));
294 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(15));
295 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(16));
296 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(17));
297 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(18));
298 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(19));
299 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(20));
300 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(21));
301 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(22));
302 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(23));
303 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(24));
304 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(25));
305 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(26));
306 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(27));
307 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(28));
308 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(29));
309 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(30));
310 PrintF(
"%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(31));
312 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(0) );
313 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(2) );
314 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(4) );
315 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(6) );
316 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(8) );
317 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(10));
318 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(12));
319 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(14));
320 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(16));
321 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(18));
322 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(20));
323 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(22));
324 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(24));
325 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(26));
326 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(28));
327 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(30));
331 #undef FPU_REG_INFO32 332 #undef FPU_REG_INFO64 336 void MipsDebugger::Debug() {
337 intptr_t last_pc = -1;
340 #define COMMAND_SIZE 63 344 #define XSTR(a) STR(a) 346 char cmd[COMMAND_SIZE + 1];
347 char arg1[ARG_SIZE + 1];
348 char arg2[ARG_SIZE + 1];
349 char* argv[3] = { cmd, arg1, arg2 };
352 cmd[COMMAND_SIZE] = 0;
360 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
361 if (last_pc != sim_->get_pc()) {
366 dasm.InstructionDecode(buffer,
367 reinterpret_cast<byte*>(sim_->get_pc()));
368 PrintF(
" 0x%08x %s\n", sim_->get_pc(), buffer.start());
369 last_pc = sim_->get_pc();
371 char* line = ReadLine(
"sim> ");
372 if (line ==
nullptr) {
375 char* last_input = sim_->last_debugger_input();
376 if (strcmp(line,
"\n") == 0 && last_input !=
nullptr) {
380 sim_->set_last_debugger_input(line);
384 int argc = SScanF(line,
385 "%" XSTR(COMMAND_SIZE)
"s " 386 "%" XSTR(ARG_SIZE)
"s " 387 "%" XSTR(ARG_SIZE)
"s",
389 if ((strcmp(cmd,
"si") == 0) || (strcmp(cmd,
"stepi") == 0)) {
390 Instruction* instr =
reinterpret_cast<Instruction*
>(sim_->get_pc());
391 if (!(instr->IsTrap()) ||
392 instr->InstructionBits() == rtCallRedirInstr) {
393 sim_->InstructionDecode(
394 reinterpret_cast<Instruction*>(sim_->get_pc()));
397 PrintF(
"/!\\ Jumping over generated breakpoint.\n");
398 sim_->set_pc(sim_->get_pc() + kInstrSize);
400 }
else if ((strcmp(cmd,
"c") == 0) || (strcmp(cmd,
"cont") == 0)) {
402 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
405 }
else if ((strcmp(cmd,
"p") == 0) || (strcmp(cmd,
"print") == 0)) {
407 if (strcmp(arg1,
"all") == 0) {
409 }
else if (strcmp(arg1,
"allf") == 0) {
410 PrintAllRegsIncludingFPU();
412 int regnum = Registers::Number(arg1);
413 int fpuregnum = FPURegisters::Number(arg1);
415 if (regnum != kInvalidRegister) {
417 value = GetRegisterValue(regnum);
418 PrintF(
"%s: 0x%08x %d \n", arg1, value, value);
419 }
else if (fpuregnum != kInvalidFPURegister) {
423 value = GetFPURegisterValue64(fpuregnum);
424 dvalue = GetFPURegisterValueDouble(fpuregnum);
425 PrintF(
"%3s: 0x%016llx %16.4e\n",
426 FPURegisters::Name(fpuregnum), value, dvalue);
428 if (fpuregnum % 2 == 1) {
431 value = GetFPURegisterValue32(fpuregnum);
432 fvalue = GetFPURegisterValueFloat(fpuregnum);
433 PrintF(
"%s: 0x%08x %11.4e\n", arg1, value, fvalue);
436 int32_t lvalue1 = GetFPURegisterValue32(fpuregnum);
437 int32_t lvalue2 = GetFPURegisterValue32(fpuregnum + 1);
438 dfvalue = GetFPURegisterValueDouble(fpuregnum);
439 PrintF(
"%3s,%3s: 0x%08x%08x %16.4e\n",
440 FPURegisters::Name(fpuregnum+1),
441 FPURegisters::Name(fpuregnum),
448 PrintF(
"%s unrecognized\n", arg1);
453 if (strcmp(arg2,
"single") == 0) {
456 int fpuregnum = FPURegisters::Number(arg1);
458 if (fpuregnum != kInvalidFPURegister) {
459 value = GetFPURegisterValue32(fpuregnum);
460 fvalue = GetFPURegisterValueFloat(fpuregnum);
461 PrintF(
"%s: 0x%08x %11.4e\n", arg1, value, fvalue);
463 PrintF(
"%s unrecognized\n", arg1);
466 PrintF(
"print <fpu register> single\n");
469 PrintF(
"print <register> or print <fpu register> single\n");
472 }
else if ((strcmp(cmd,
"po") == 0)
473 || (strcmp(cmd,
"printobject") == 0)) {
477 if (GetValue(arg1, &value)) {
478 Object* obj =
reinterpret_cast<Object*
>(value);
479 os << arg1 <<
": \n";
484 os << Brief(obj) <<
"\n";
487 os << arg1 <<
" unrecognized\n";
490 PrintF(
"printobject <value>\n");
492 }
else if (strcmp(cmd,
"stack") == 0 || strcmp(cmd,
"mem") == 0) {
493 int32_t* cur =
nullptr;
494 int32_t* end =
nullptr;
497 if (strcmp(cmd,
"stack") == 0) {
498 cur =
reinterpret_cast<int32_t*
>(sim_->get_register(Simulator::sp));
501 if (!GetValue(arg1, &value)) {
502 PrintF(
"%s unrecognized\n", arg1);
505 cur =
reinterpret_cast<int32_t*
>(value);
512 if (argc == next_arg) {
515 if (!GetValue(argv[next_arg], &words)) {
522 if (argc == next_arg) {
525 if (!GetValue(argv[next_arg], &words)) {
533 PrintF(
" 0x%08" PRIxPTR
": 0x%08x %10d",
534 reinterpret_cast<intptr_t>(cur), *cur, *cur);
535 HeapObject* obj =
reinterpret_cast<HeapObject*
>(*cur);
537 Heap* current_heap = sim_->isolate_->heap();
538 if (((value & 1) == 0) || current_heap->Contains(obj)) {
540 if ((value & 1) == 0) {
541 PrintF(
"smi %d", value / 2);
551 }
else if ((strcmp(cmd,
"disasm") == 0) ||
552 (strcmp(cmd,
"dpc") == 0) ||
553 (strcmp(cmd,
"di") == 0)) {
563 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
564 end = cur + (10 * kInstrSize);
565 }
else if (argc == 2) {
566 int regnum = Registers::Number(arg1);
567 if (regnum != kInvalidRegister || strncmp(arg1,
"0x", 2) == 0) {
570 if (GetValue(arg1, &value)) {
571 cur =
reinterpret_cast<byte*
>(value);
573 end = cur + (10 * kInstrSize);
578 if (GetValue(arg1, &value)) {
579 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
581 end = cur + (value * kInstrSize);
587 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
588 cur =
reinterpret_cast<byte*
>(value1);
589 end = cur + (value2 * kInstrSize);
594 dasm.InstructionDecode(buffer, cur);
595 PrintF(
" 0x%08" PRIxPTR
" %s\n", reinterpret_cast<intptr_t>(cur),
599 }
else if (strcmp(cmd,
"gdb") == 0) {
600 PrintF(
"relinquishing control to gdb\n");
601 v8::base::OS::DebugBreak();
602 PrintF(
"regaining control from gdb\n");
603 }
else if (strcmp(cmd,
"break") == 0) {
606 if (GetValue(arg1, &value)) {
607 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
608 PrintF(
"setting breakpoint failed\n");
611 PrintF(
"%s unrecognized\n", arg1);
614 PrintF(
"break <address>\n");
616 }
else if (strcmp(cmd,
"del") == 0) {
617 if (!DeleteBreakpoint(
nullptr)) {
618 PrintF(
"deleting breakpoint failed\n");
620 }
else if (strcmp(cmd,
"flags") == 0) {
621 PrintF(
"No flags on MIPS !\n");
622 }
else if (strcmp(cmd,
"stop") == 0) {
624 intptr_t stop_pc = sim_->get_pc() - 2 * kInstrSize;
625 Instruction* stop_instr =
reinterpret_cast<Instruction*
>(stop_pc);
626 Instruction* msg_address =
627 reinterpret_cast<Instruction*
>(stop_pc + kInstrSize);
628 if ((argc == 2) && (strcmp(arg1,
"unstop") == 0)) {
630 if (sim_->IsStopInstruction(stop_instr)) {
631 stop_instr->SetInstructionBits(kNopInstr);
632 msg_address->SetInstructionBits(kNopInstr);
634 PrintF(
"Not at debugger stop.\n");
636 }
else if (argc == 3) {
638 if (strcmp(arg1,
"info") == 0) {
639 if (strcmp(arg2,
"all") == 0) {
640 PrintF(
"Stop information:\n");
641 for (
uint32_t i = kMaxWatchpointCode + 1;
644 sim_->PrintStopInfo(
i);
646 }
else if (GetValue(arg2, &value)) {
647 sim_->PrintStopInfo(value);
649 PrintF(
"Unrecognized argument.\n");
651 }
else if (strcmp(arg1,
"enable") == 0) {
653 if (strcmp(arg2,
"all") == 0) {
654 for (
uint32_t i = kMaxWatchpointCode + 1;
659 }
else if (GetValue(arg2, &value)) {
660 sim_->EnableStop(value);
662 PrintF(
"Unrecognized argument.\n");
664 }
else if (strcmp(arg1,
"disable") == 0) {
666 if (strcmp(arg2,
"all") == 0) {
667 for (
uint32_t i = kMaxWatchpointCode + 1;
670 sim_->DisableStop(
i);
672 }
else if (GetValue(arg2, &value)) {
673 sim_->DisableStop(value);
675 PrintF(
"Unrecognized argument.\n");
679 PrintF(
"Wrong usage. Use help command for more information.\n");
681 }
else if ((strcmp(cmd,
"stat") == 0) || (strcmp(cmd,
"st") == 0)) {
695 cur =
reinterpret_cast<byte*
>(sim_->get_pc());
696 end = cur + (10 * kInstrSize);
697 }
else if (argc == 2) {
699 if (GetValue(arg1, &value)) {
700 cur =
reinterpret_cast<byte*
>(value);
702 end = cur + (10 * kInstrSize);
707 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
708 cur =
reinterpret_cast<byte*
>(value1);
709 end = cur + (value2 * kInstrSize);
714 dasm.InstructionDecode(buffer, cur);
715 PrintF(
" 0x%08" PRIxPTR
" %s\n", reinterpret_cast<intptr_t>(cur),
719 }
else if ((strcmp(cmd,
"h") == 0) || (strcmp(cmd,
"help") == 0)) {
721 PrintF(
" continue execution (alias 'c')\n");
723 PrintF(
" step one instruction (alias 'si')\n");
724 PrintF(
"print <register>\n");
725 PrintF(
" print register content (alias 'p')\n");
726 PrintF(
" use register name 'all' to print all registers\n");
727 PrintF(
"printobject <register>\n");
728 PrintF(
" print an object from a register (alias 'po')\n");
729 PrintF(
"stack [<words>]\n");
730 PrintF(
" dump stack content, default dump 10 words)\n");
731 PrintF(
"mem <address> [<words>]\n");
732 PrintF(
" dump memory content, default dump 10 words)\n");
734 PrintF(
" print flags\n");
735 PrintF(
"disasm [<instructions>]\n");
736 PrintF(
"disasm [<address/register>]\n");
737 PrintF(
"disasm [[<address/register>] <instructions>]\n");
738 PrintF(
" disassemble code, default is 10 instructions\n");
739 PrintF(
" from pc (alias 'di')\n");
741 PrintF(
" enter gdb\n");
742 PrintF(
"break <address>\n");
743 PrintF(
" set a break point on the address\n");
745 PrintF(
" delete the breakpoint\n");
746 PrintF(
"stop feature:\n");
747 PrintF(
" Description:\n");
748 PrintF(
" Stops are debug instructions inserted by\n");
749 PrintF(
" the Assembler::stop() function.\n");
750 PrintF(
" When hitting a stop, the Simulator will\n");
751 PrintF(
" stop and give control to the Debugger.\n");
752 PrintF(
" All stop codes are watched:\n");
753 PrintF(
" - They can be enabled / disabled: the Simulator\n");
754 PrintF(
" will / won't stop when hitting them.\n");
755 PrintF(
" - The Simulator keeps track of how many times they \n");
756 PrintF(
" are met. (See the info command.) Going over a\n");
757 PrintF(
" disabled stop still increases its counter. \n");
758 PrintF(
" Commands:\n");
759 PrintF(
" stop info all/<code> : print infos about number <code>\n");
760 PrintF(
" or all stop(s).\n");
761 PrintF(
" stop enable/disable all/<code> : enables / disables\n");
762 PrintF(
" all or number <code> stop(s)\n");
763 PrintF(
" stop unstop\n");
764 PrintF(
" ignore the stop instruction at the current location\n");
765 PrintF(
" from now on\n");
767 PrintF(
"Unknown command: %s\n", cmd);
783 bool Simulator::ICacheMatch(
void* one,
void* two) {
784 DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
785 DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
790 static uint32_t ICacheHash(
void* key) {
795 static bool AllOnOnePage(
uintptr_t start,
int size) {
796 intptr_t start_page = (start & ~CachePage::kPageMask);
797 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
798 return start_page == end_page;
802 void Simulator::set_last_debugger_input(
char* input) {
803 DeleteArray(last_debugger_input_);
804 last_debugger_input_ = input;
807 void Simulator::SetRedirectInstruction(Instruction* instruction) {
808 instruction->SetInstructionBits(rtCallRedirInstr);
811 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
812 void* start_addr,
size_t size) {
813 intptr_t start =
reinterpret_cast<intptr_t
>(start_addr);
814 int intra_line = (start & CachePage::kLineMask);
817 size = ((size - 1) | CachePage::kLineMask) + 1;
818 int offset = (start & CachePage::kPageMask);
819 while (!AllOnOnePage(start, size - 1)) {
820 int bytes_to_flush = CachePage::kPageSize - offset;
821 FlushOnePage(i_cache, start, bytes_to_flush);
822 start += bytes_to_flush;
823 size -= bytes_to_flush;
824 DCHECK_EQ(0, start & CachePage::kPageMask);
828 FlushOnePage(i_cache, start, size);
832 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
834 base::CustomMatcherHashMap::Entry* entry =
835 i_cache->LookupOrInsert(page, ICacheHash(page));
836 if (entry->value ==
nullptr) {
837 CachePage* new_page =
new CachePage();
838 entry->value = new_page;
840 return reinterpret_cast<CachePage*
>(entry->value);
845 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
846 intptr_t start,
int size) {
847 DCHECK_LE(size, CachePage::kPageSize);
848 DCHECK(AllOnOnePage(start, size - 1));
849 DCHECK_EQ(start & CachePage::kLineMask, 0);
850 DCHECK_EQ(size & CachePage::kLineMask, 0);
851 void* page =
reinterpret_cast<void*
>(start & (~CachePage::kPageMask));
852 int offset = (start & CachePage::kPageMask);
853 CachePage* cache_page = GetCachePage(i_cache, page);
854 char* valid_bytemap = cache_page->ValidityByte(offset);
855 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
858 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
859 Instruction* instr) {
860 intptr_t address =
reinterpret_cast<intptr_t
>(instr);
861 void* page =
reinterpret_cast<void*
>(address & (~CachePage::kPageMask));
862 void* line =
reinterpret_cast<void*
>(address & (~CachePage::kLineMask));
863 int offset = (address & CachePage::kPageMask);
864 CachePage* cache_page = GetCachePage(i_cache, page);
865 char* cache_valid_byte = cache_page->ValidityByte(offset);
866 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
867 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
870 CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
871 cache_page->CachedData(offset), kInstrSize));
874 memcpy(cached_line, line, CachePage::kLineLength);
875 *cache_valid_byte = CachePage::LINE_VALID;
880 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
883 stack_ =
reinterpret_cast<char*
>(malloc(stack_size_));
884 pc_modified_ =
false;
892 for (
int i = 0;
i < kNumSimuRegisters;
i++) {
895 for (
int i = 0;
i < kNumFPURegisters;
i++) {
896 FPUregisters_[2 *
i] = 0;
897 FPUregisters_[2 *
i + 1] = 0;
899 if (IsMipsArchVariant(kMips32r6)) {
900 FCSR_ = kFCSRNaN2008FlagMask;
903 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2));
910 registers_[sp] =
reinterpret_cast<int32_t
>(stack_) + stack_size_ - 64;
913 registers_[pc] = bad_ra;
914 registers_[ra] = bad_ra;
915 last_debugger_input_ =
nullptr;
919 Simulator::~Simulator() { free(stack_); }
923 Simulator* Simulator::current(Isolate* isolate) {
925 isolate->FindOrAllocatePerThreadDataForThisThread();
926 DCHECK_NOT_NULL(isolate_data);
928 Simulator* sim = isolate_data->simulator();
929 if (sim ==
nullptr) {
931 sim =
new Simulator(isolate);
932 isolate_data->set_simulator(sim);
940 void Simulator::set_register(
int reg, int32_t value) {
941 DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
947 registers_[reg] = (reg == 0) ? 0 : value;
951 void Simulator::set_dw_register(
int reg,
const int* dbl) {
952 DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
953 registers_[reg] = dbl[0];
954 registers_[reg + 1] = dbl[1];
958 void Simulator::set_fpu_register(
int fpureg,
int64_t value) {
959 DCHECK(IsFp64Mode());
960 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
961 FPUregisters_[fpureg * 2] = value;
965 void Simulator::set_fpu_register_word(
int fpureg, int32_t value) {
968 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
969 int32_t* pword =
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2]);
974 void Simulator::set_fpu_register_hi_word(
int fpureg, int32_t value) {
977 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
979 (
reinterpret_cast<int32_t*
>(&FPUregisters_[fpureg * 2])) + 1;
984 void Simulator::set_fpu_register_float(
int fpureg,
float value) {
985 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
986 *bit_cast<
float*>(&FPUregisters_[fpureg * 2]) = value;
990 void Simulator::set_fpu_register_double(
int fpureg,
double value) {
992 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
993 *bit_cast<
double*>(&FPUregisters_[fpureg * 2]) = value;
995 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
997 set_fpu_register_word(fpureg, i64 & 0xFFFFFFFF);
998 set_fpu_register_word(fpureg + 1, i64 >> 32);
1005 int32_t Simulator::get_register(
int reg)
const {
1006 DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
1010 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
1014 double Simulator::get_double_from_register_pair(
int reg) {
1016 DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1018 double dm_val = 0.0;
1021 char buffer[2 *
sizeof(registers_[0])];
1022 memcpy(buffer, ®isters_[reg], 2 *
sizeof(registers_[0]));
1023 memcpy(&dm_val, buffer, 2 *
sizeof(registers_[0]));
1028 int64_t Simulator::get_fpu_register(
int fpureg)
const {
1030 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1031 return FPUregisters_[fpureg * 2];
1033 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1035 i64 =
static_cast<uint32_t>(get_fpu_register_word(fpureg));
1036 i64 |=
static_cast<uint64_t
>(get_fpu_register_word(fpureg + 1)) << 32;
1037 return static_cast<int64_t>(i64);
1042 int32_t Simulator::get_fpu_register_word(
int fpureg)
const {
1043 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1044 return static_cast<int32_t
>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
1048 int32_t Simulator::get_fpu_register_signed_word(
int fpureg)
const {
1049 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1050 return static_cast<int32_t
>(FPUregisters_[fpureg * 2] & 0xFFFFFFFF);
1054 int32_t Simulator::get_fpu_register_hi_word(
int fpureg)
const {
1055 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1056 return static_cast<int32_t
>((FPUregisters_[fpureg * 2] >> 32) & 0xFFFFFFFF);
1060 float Simulator::get_fpu_register_float(
int fpureg)
const {
1061 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1062 return *bit_cast<
float*>(
const_cast<int64_t*
>(&FPUregisters_[fpureg * 2]));
1066 double Simulator::get_fpu_register_double(
int fpureg)
const {
1068 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1069 return *bit_cast<
double*>(&FPUregisters_[fpureg * 2]);
1071 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1073 i64 =
static_cast<uint32_t>(get_fpu_register_word(fpureg));
1074 i64 |=
static_cast<uint64_t
>(get_fpu_register_word(fpureg + 1)) << 32;
1075 return bit_cast<
double>(i64);
1079 template <
typename T>
1080 void Simulator::get_msa_register(
int wreg, T* value) {
1081 DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
1082 memcpy(value, FPUregisters_ + wreg * 2, kSimd128Size);
1085 template <
typename T>
1086 void Simulator::set_msa_register(
int wreg,
const T* value) {
1087 DCHECK((wreg >= 0) && (wreg < kNumMSARegisters));
1088 memcpy(FPUregisters_ + wreg * 2, value, kSimd128Size);
1094 void Simulator::GetFpArgs(
double* x,
double* y, int32_t* z) {
1095 if (!IsMipsSoftFloatABI) {
1096 *x = get_fpu_register_double(12);
1097 *y = get_fpu_register_double(14);
1098 *z = get_register(a2);
1103 char buffer[
sizeof(*x)];
1104 int32_t* reg_buffer =
reinterpret_cast<int32_t*
>(buffer);
1107 reg_buffer[0] = get_register(a0);
1108 reg_buffer[1] = get_register(a1);
1109 memcpy(x, buffer,
sizeof(buffer));
1111 reg_buffer[0] = get_register(a2);
1112 reg_buffer[1] = get_register(a3);
1113 memcpy(y, buffer,
sizeof(buffer));
1115 reg_buffer[0] = get_register(a2);
1116 memcpy(z, buffer,
sizeof(*z));
1122 void Simulator::SetFpResult(
const double& result) {
1123 if (!IsMipsSoftFloatABI) {
1124 set_fpu_register_double(0, result);
1126 char buffer[2 *
sizeof(registers_[0])];
1127 int32_t* reg_buffer =
reinterpret_cast<int32_t*
>(buffer);
1128 memcpy(buffer, &result,
sizeof(buffer));
1130 set_register(v0, reg_buffer[0]);
1131 set_register(v1, reg_buffer[1]);
1137 void Simulator::set_fcsr_bit(
uint32_t cc,
bool value) {
1141 FCSR_ &= ~(1 << cc);
1146 bool Simulator::test_fcsr_bit(
uint32_t cc) {
1147 return FCSR_ & (1 << cc);
1151 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) {
1152 FCSR_ |= mode & kFPURoundingModeMask;
1155 void Simulator::set_msacsr_rounding_mode(FPURoundingMode mode) {
1156 MSACSR_ |= mode & kFPURoundingModeMask;
1159 unsigned int Simulator::get_fcsr_rounding_mode() {
1160 return FCSR_ & kFPURoundingModeMask;
1163 unsigned int Simulator::get_msacsr_rounding_mode() {
1164 return MSACSR_ & kFPURoundingModeMask;
1167 void Simulator::set_fpu_register_word_invalid_result(
float original,
1169 if (FCSR_ & kFCSRNaN2008FlagMask) {
1170 double max_int32 = std::numeric_limits<int32_t>::max();
1171 double min_int32 = std::numeric_limits<int32_t>::min();
1172 if (std::isnan(original)) {
1173 set_fpu_register_word(fd_reg(), 0);
1174 }
else if (rounded > max_int32) {
1175 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1176 }
else if (rounded < min_int32) {
1177 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1182 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1187 void Simulator::set_fpu_register_invalid_result(
float original,
float rounded) {
1188 if (FCSR_ & kFCSRNaN2008FlagMask) {
1189 double max_int32 = std::numeric_limits<int32_t>::max();
1190 double min_int32 = std::numeric_limits<int32_t>::min();
1191 if (std::isnan(original)) {
1192 set_fpu_register(fd_reg(), 0);
1193 }
else if (rounded > max_int32) {
1194 set_fpu_register(fd_reg(), kFPUInvalidResult);
1195 }
else if (rounded < min_int32) {
1196 set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1201 set_fpu_register(fd_reg(), kFPUInvalidResult);
1206 void Simulator::set_fpu_register_invalid_result64(
float original,
1208 if (FCSR_ & kFCSRNaN2008FlagMask) {
1211 double max_int64 = std::numeric_limits<int64_t>::max();
1212 double min_int64 = std::numeric_limits<int64_t>::min();
1213 if (std::isnan(original)) {
1214 set_fpu_register(fd_reg(), 0);
1215 }
else if (rounded >= max_int64) {
1216 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1217 }
else if (rounded < min_int64) {
1218 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1223 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1228 void Simulator::set_fpu_register_word_invalid_result(
double original,
1230 if (FCSR_ & kFCSRNaN2008FlagMask) {
1231 double max_int32 = std::numeric_limits<int32_t>::max();
1232 double min_int32 = std::numeric_limits<int32_t>::min();
1233 if (std::isnan(original)) {
1234 set_fpu_register_word(fd_reg(), 0);
1235 }
else if (rounded > max_int32) {
1236 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1237 }
else if (rounded < min_int32) {
1238 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative);
1243 set_fpu_register_word(fd_reg(), kFPUInvalidResult);
1248 void Simulator::set_fpu_register_invalid_result(
double original,
1250 if (FCSR_ & kFCSRNaN2008FlagMask) {
1251 double max_int32 = std::numeric_limits<int32_t>::max();
1252 double min_int32 = std::numeric_limits<int32_t>::min();
1253 if (std::isnan(original)) {
1254 set_fpu_register(fd_reg(), 0);
1255 }
else if (rounded > max_int32) {
1256 set_fpu_register(fd_reg(), kFPUInvalidResult);
1257 }
else if (rounded < min_int32) {
1258 set_fpu_register(fd_reg(), kFPUInvalidResultNegative);
1263 set_fpu_register(fd_reg(), kFPUInvalidResult);
1268 void Simulator::set_fpu_register_invalid_result64(
double original,
1270 if (FCSR_ & kFCSRNaN2008FlagMask) {
1273 double max_int64 = std::numeric_limits<int64_t>::max();
1274 double min_int64 = std::numeric_limits<int64_t>::min();
1275 if (std::isnan(original)) {
1276 set_fpu_register(fd_reg(), 0);
1277 }
else if (rounded >= max_int64) {
1278 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1279 }
else if (rounded < min_int64) {
1280 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative);
1285 set_fpu_register(fd_reg(), kFPU64InvalidResult);
1292 bool Simulator::set_fcsr_round_error(
double original,
double rounded) {
1294 double max_int32 = std::numeric_limits<int32_t>::max();
1295 double min_int32 = std::numeric_limits<int32_t>::min();
1297 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1298 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1302 if (original != rounded) {
1303 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1306 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1307 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1311 if (rounded > max_int32 || rounded < min_int32) {
1312 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1314 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1324 bool Simulator::set_fcsr_round64_error(
double original,
double rounded) {
1328 double max_int64 = std::numeric_limits<int64_t>::max();
1329 double min_int64 = std::numeric_limits<int64_t>::min();
1331 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1332 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1336 if (original != rounded) {
1337 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1340 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1341 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1345 if (rounded >= max_int64 || rounded < min_int64) {
1346 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1348 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1358 bool Simulator::set_fcsr_round_error(
float original,
float rounded) {
1360 double max_int32 = std::numeric_limits<int32_t>::max();
1361 double min_int32 = std::numeric_limits<int32_t>::min();
1363 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1364 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1368 if (original != rounded) {
1369 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1372 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1373 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1377 if (rounded > max_int32 || rounded < min_int32) {
1378 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1380 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1390 bool Simulator::set_fcsr_round64_error(
float original,
float rounded) {
1394 double max_int64 = std::numeric_limits<int64_t>::max();
1395 double min_int64 = std::numeric_limits<int64_t>::min();
1397 if (!std::isfinite(original) || !std::isfinite(rounded)) {
1398 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1402 if (original != rounded) {
1403 set_fcsr_bit(kFCSRInexactFlagBit,
true);
1406 if (rounded < FLT_MIN && rounded > -FLT_MIN && rounded != 0) {
1407 set_fcsr_bit(kFCSRUnderflowFlagBit,
true);
1411 if (rounded >= max_int64 || rounded < min_int64) {
1412 set_fcsr_bit(kFCSROverflowFlagBit,
true);
1414 set_fcsr_bit(kFCSRInvalidOpFlagBit,
true);
1422 void Simulator::round_according_to_fcsr(
double toRound,
double& rounded,
1423 int32_t& rounded_int,
double fs) {
1437 switch (get_fcsr_rounding_mode()) {
1438 case kRoundToNearest:
1439 rounded = std::floor(fs + 0.5);
1440 rounded_int =
static_cast<int32_t
>(rounded);
1441 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1449 rounded = trunc(fs);
1450 rounded_int =
static_cast<int32_t
>(rounded);
1452 case kRoundToPlusInf:
1453 rounded = std::ceil(fs);
1454 rounded_int =
static_cast<int32_t
>(rounded);
1456 case kRoundToMinusInf:
1457 rounded = std::floor(fs);
1458 rounded_int =
static_cast<int32_t
>(rounded);
1464 void Simulator::round_according_to_fcsr(
float toRound,
float& rounded,
1465 int32_t& rounded_int,
float fs) {
1479 switch (get_fcsr_rounding_mode()) {
1480 case kRoundToNearest:
1481 rounded = std::floor(fs + 0.5);
1482 rounded_int =
static_cast<int32_t
>(rounded);
1483 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1491 rounded = trunc(fs);
1492 rounded_int =
static_cast<int32_t
>(rounded);
1494 case kRoundToPlusInf:
1495 rounded = std::ceil(fs);
1496 rounded_int =
static_cast<int32_t
>(rounded);
1498 case kRoundToMinusInf:
1499 rounded = std::floor(fs);
1500 rounded_int =
static_cast<int32_t
>(rounded);
1505 template <
typename T_fp,
typename T_
int>
1506 void Simulator::round_according_to_msacsr(T_fp toRound, T_fp& rounded,
1507 T_int& rounded_int) {
1521 switch (get_msacsr_rounding_mode()) {
1522 case kRoundToNearest:
1523 rounded = std::floor(toRound + 0.5);
1524 rounded_int =
static_cast<T_int
>(rounded);
1525 if ((rounded_int & 1) != 0 && rounded_int - toRound == 0.5) {
1533 rounded = trunc(toRound);
1534 rounded_int =
static_cast<T_int
>(rounded);
1536 case kRoundToPlusInf:
1537 rounded = std::ceil(toRound);
1538 rounded_int =
static_cast<T_int
>(rounded);
1540 case kRoundToMinusInf:
1541 rounded = std::floor(toRound);
1542 rounded_int =
static_cast<T_int
>(rounded);
1547 void Simulator::round64_according_to_fcsr(
double toRound,
double& rounded,
1548 int64_t& rounded_int,
double fs) {
1562 switch (FCSR_ & 3) {
1563 case kRoundToNearest:
1564 rounded = std::floor(fs + 0.5);
1565 rounded_int =
static_cast<int64_t>(rounded);
1566 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1574 rounded = trunc(fs);
1575 rounded_int =
static_cast<int64_t>(rounded);
1577 case kRoundToPlusInf:
1578 rounded = std::ceil(fs);
1579 rounded_int =
static_cast<int64_t>(rounded);
1581 case kRoundToMinusInf:
1582 rounded = std::floor(fs);
1583 rounded_int =
static_cast<int64_t>(rounded);
1589 void Simulator::round64_according_to_fcsr(
float toRound,
float& rounded,
1590 int64_t& rounded_int,
float fs) {
1604 switch (FCSR_ & 3) {
1605 case kRoundToNearest:
1606 rounded = std::floor(fs + 0.5);
1607 rounded_int =
static_cast<int64_t>(rounded);
1608 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) {
1616 rounded = trunc(fs);
1617 rounded_int =
static_cast<int64_t>(rounded);
1619 case kRoundToPlusInf:
1620 rounded = std::ceil(fs);
1621 rounded_int =
static_cast<int64_t>(rounded);
1623 case kRoundToMinusInf:
1624 rounded = std::floor(fs);
1625 rounded_int =
static_cast<int64_t>(rounded);
1632 void Simulator::set_pc(int32_t value) {
1633 pc_modified_ =
true;
1634 registers_[pc] = value;
1638 bool Simulator::has_bad_pc()
const {
1639 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1644 int32_t Simulator::get_pc()
const {
1645 return registers_[pc];
1657 void Simulator::TraceRegWr(int32_t value, TraceType t) {
1658 if (::v8::internal::FLAG_trace_sim) {
1663 v.fmt_int32 = value;
1667 SNPrintF(trace_buf_,
"%08" PRIx32
" (%" PRIu64
") int32:%" PRId32
1669 value, icount_, value, value);
1672 SNPrintF(trace_buf_,
"%08" PRIx32
" (%" PRIu64
") flt:%e",
1673 v.fmt_int32, icount_, v.fmt_float);
1681 void Simulator::TraceRegWr(
int64_t value, TraceType t) {
1682 if (::v8::internal::FLAG_trace_sim) {
1687 v.fmt_int64 = value;
1691 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRIu64
") int64:%" PRId64
1693 value, icount_, value, value);
1696 SNPrintF(trace_buf_,
"%016" PRIx64
" (%" PRIu64
") dbl:%e",
1697 v.fmt_int64, icount_, v.fmt_double);
1705 template <
typename T>
1706 void Simulator::TraceMSARegWr(T* value, TraceType t) {
1707 if (::v8::internal::FLAG_trace_sim) {
1716 memcpy(v.b, value, kSimd128Size);
1719 SNPrintF(trace_buf_,
1720 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1721 v.d[0], v.d[1], icount_);
1724 SNPrintF(trace_buf_,
1725 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1726 v.d[0], v.d[1], icount_);
1729 SNPrintF(trace_buf_,
1730 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1731 ") int32[0..3]:%" PRId32
" %" PRId32
" %" PRId32
1733 v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1736 SNPrintF(trace_buf_,
1737 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1738 v.d[0], v.d[1], icount_);
1741 SNPrintF(trace_buf_,
1742 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1743 ") flt[0..3]:%e %e %e %e",
1744 v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1747 SNPrintF(trace_buf_,
1748 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1749 ") dbl[0..1]:%e %e",
1750 v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1758 template <
typename T>
1759 void Simulator::TraceMSARegWr(T* value) {
1760 if (::v8::internal::FLAG_trace_sim) {
1762 uint8_t b[kMSALanesByte];
1763 uint16_t h[kMSALanesHalf];
1765 uint64_t d[kMSALanesDword];
1766 float f[kMSALanesWord];
1767 double df[kMSALanesDword];
1769 memcpy(v.b, value, kMSALanesByte);
1771 if (std::is_same<T, int32_t>::value) {
1772 SNPrintF(trace_buf_,
1773 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1774 ") int32[0..3]:%" PRId32
" %" PRId32
" %" PRId32
1776 v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
1777 }
else if (std::is_same<T, float>::value) {
1778 SNPrintF(trace_buf_,
1779 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1780 ") flt[0..3]:%e %e %e %e",
1781 v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
1782 }
else if (std::is_same<T, double>::value) {
1783 SNPrintF(trace_buf_,
1784 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
1785 ") dbl[0..1]:%e %e",
1786 v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
1788 SNPrintF(trace_buf_,
1789 "LO: %016" PRIx64
" HI: %016" PRIx64
" (%" PRIu64
")",
1790 v.d[0], v.d[1], icount_);
1796 void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) {
1797 if (::v8::internal::FLAG_trace_sim) {
1802 v.fmt_int32 = value;
1806 SNPrintF(trace_buf_,
"%08" PRIx32
" <-- [%08" PRIx32
"] (%" PRIu64
1807 ") int32:%" PRId32
" uint32:%" PRIu32,
1808 value, addr, icount_, value, value);
1811 SNPrintF(trace_buf_,
1812 "%08" PRIx32
" <-- [%08" PRIx32
"] (%" PRIu64
") flt:%e",
1813 v.fmt_int32, addr, icount_, v.fmt_float);
1822 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) {
1823 if (::v8::internal::FLAG_trace_sim) {
1826 SNPrintF(trace_buf_,
1827 " %02" PRIx8
" --> [%08" PRIx32
"] (%" PRIu64
")",
1828 static_cast<uint8_t>(value), addr, icount_);
1831 SNPrintF(trace_buf_,
1832 " %04" PRIx16
" --> [%08" PRIx32
"] (%" PRIu64
")",
1833 static_cast<uint16_t>(value), addr, icount_);
1836 SNPrintF(trace_buf_,
1837 "%08" PRIx32
" --> [%08" PRIx32
"] (%" PRIu64
")", value,
1846 template <
typename T>
1847 void Simulator::TraceMemRd(int32_t addr, T value) {
1848 if (::v8::internal::FLAG_trace_sim) {
1849 switch (
sizeof(T)) {
1851 SNPrintF(trace_buf_,
1852 "%08" PRIx8
" <-- [%08" PRIx32
"] (%" PRIu64
1853 ") int8:%" PRId8
" uint8:%" PRIu8,
1854 static_cast<uint8_t>(value), addr, icount_,
1855 static_cast<int8_t>(value), static_cast<uint8_t>(value));
1858 SNPrintF(trace_buf_,
1859 "%08" PRIx16
" <-- [%08" PRIx32
"] (%" PRIu64
1860 ") int16:%" PRId16
" uint16:%" PRIu16,
1861 static_cast<uint16_t>(value), addr, icount_,
1862 static_cast<int16_t>(value), static_cast<uint16_t>(value));
1865 SNPrintF(trace_buf_,
1866 "%08" PRIx32
" <-- [%08" PRIx32
"] (%" PRIu64
1867 ") int32:%" PRId32
" uint32:%" PRIu32,
1868 static_cast<uint32_t>(value), addr, icount_,
1869 static_cast<int32_t>(value), static_cast<uint32_t>(value));
1872 SNPrintF(trace_buf_,
1873 "%08" PRIx64
" <-- [%08" PRIx32
"] (%" PRIu64
1874 ") int64:%" PRId64
" uint64:%" PRIu64,
1875 static_cast<uint64_t>(value), addr, icount_,
1876 static_cast<int64_t>(value), static_cast<uint64_t>(value));
1884 template <
typename T>
1885 void Simulator::TraceMemWr(int32_t addr, T value) {
1886 if (::v8::internal::FLAG_trace_sim) {
1887 switch (
sizeof(T)) {
1889 SNPrintF(trace_buf_,
1890 " %02" PRIx8
" --> [%08" PRIx32
"] (%" PRIu64
")",
1891 static_cast<uint8_t>(value), addr, icount_);
1894 SNPrintF(trace_buf_,
1895 " %04" PRIx16
" --> [%08" PRIx32
"] (%" PRIu64
")",
1896 static_cast<uint16_t>(value), addr, icount_);
1899 SNPrintF(trace_buf_,
1900 "%08" PRIx32
" --> [%08" PRIx32
"] (%" PRIu64
")",
1901 static_cast<uint32_t>(value), addr, icount_);
1904 SNPrintF(trace_buf_,
1905 "%16" PRIx64
" --> [%08" PRIx32
"] (%" PRIu64
")",
1906 static_cast<uint64_t>(value), addr, icount_);
1914 void Simulator::TraceMemRd(int32_t addr,
int64_t value, TraceType t) {
1915 if (::v8::internal::FLAG_trace_sim) {
1918 int32_t fmt_int32[2];
1922 v.fmt_int64 = value;
1926 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%08" PRIx32
"] (%" PRIu64
1927 ") int64:%" PRId64
" uint64:%" PRIu64,
1928 v.fmt_int64, addr, icount_, v.fmt_int64, v.fmt_int64);
1931 SNPrintF(trace_buf_,
"%016" PRIx64
" <-- [%08" PRIx32
"] (%" PRIu64
1933 v.fmt_int64, addr, icount_, v.fmt_double);
1936 SNPrintF(trace_buf_,
"%08" PRIx32
" <-- [%08" PRIx32
"] (%" PRIu64
1938 v.fmt_int32[1], addr, icount_, v.fmt_float[1], v.fmt_double);
1946 void Simulator::TraceMemWr(int32_t addr,
int64_t value, TraceType t) {
1947 if (::v8::internal::FLAG_trace_sim) {
1950 SNPrintF(trace_buf_,
1951 "%016" PRIx64
" --> [%08" PRIx32
"] (%" PRIu64
")", value,
1960 int Simulator::ReadW(int32_t addr, Instruction* instr, TraceType t) {
1961 if (addr >=0 && addr < 0x400) {
1963 PrintF(
"Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR
"\n", addr,
1964 reinterpret_cast<intptr_t>(instr));
1965 MipsDebugger dbg(
this);
1968 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
1969 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
1972 TraceMemRd(addr, static_cast<int32_t>(*ptr), t);
1982 PrintF(
"Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
1984 reinterpret_cast<intptr_t>(instr));
1985 MipsDebugger dbg(
this);
1990 void Simulator::WriteW(int32_t addr,
int value, Instruction* instr) {
1991 if (addr >= 0 && addr < 0x400) {
1993 PrintF(
"Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR
"\n", addr,
1994 reinterpret_cast<intptr_t>(instr));
1995 MipsDebugger dbg(
this);
1998 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
1999 intptr_t* ptr =
reinterpret_cast<intptr_t*
>(addr);
2000 TraceMemWr(addr, value, WORD);
2004 PrintF(
"Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2006 reinterpret_cast<intptr_t>(instr));
2007 MipsDebugger dbg(
this);
2011 double Simulator::ReadD(int32_t addr, Instruction* instr) {
2012 if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
2013 double* ptr =
reinterpret_cast<double*
>(addr);
2016 PrintF(
"Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2018 reinterpret_cast<intptr_t>(instr));
2024 void Simulator::WriteD(int32_t addr,
double value, Instruction* instr) {
2025 if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
2026 double* ptr =
reinterpret_cast<double*
>(addr);
2030 PrintF(
"Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2032 reinterpret_cast<intptr_t>(instr));
2037 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
2038 if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
2039 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
2040 TraceMemRd(addr, static_cast<int32_t>(*ptr));
2043 PrintF(
"Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2045 reinterpret_cast<intptr_t>(instr));
2051 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
2052 if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
2053 int16_t* ptr =
reinterpret_cast<int16_t*
>(addr);
2054 TraceMemRd(addr, static_cast<int32_t>(*ptr));
2057 PrintF(
"Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2059 reinterpret_cast<intptr_t>(instr));
2065 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
2066 if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
2067 uint16_t* ptr =
reinterpret_cast<uint16_t*
>(addr);
2068 TraceMemWr(addr, value, HALF);
2072 PrintF(
"Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2074 reinterpret_cast<intptr_t>(instr));
2079 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
2080 if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
2081 int16_t* ptr =
reinterpret_cast<int16_t*
>(addr);
2082 TraceMemWr(addr, value, HALF);
2086 PrintF(
"Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2088 reinterpret_cast<intptr_t>(instr));
2093 uint32_t Simulator::ReadBU(int32_t addr) {
2094 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
2095 TraceMemRd(addr, static_cast<int32_t>(*ptr));
2100 int32_t Simulator::ReadB(int32_t addr) {
2101 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
2102 TraceMemRd(addr, static_cast<int32_t>(*ptr));
2107 void Simulator::WriteB(int32_t addr, uint8_t value) {
2108 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(addr);
2109 TraceMemWr(addr, value, BYTE);
2114 void Simulator::WriteB(int32_t addr, int8_t value) {
2115 int8_t* ptr =
reinterpret_cast<int8_t*
>(addr);
2116 TraceMemWr(addr, value, BYTE);
2120 template <
typename T>
2121 T Simulator::ReadMem(int32_t addr, Instruction* instr) {
2122 int alignment_mask = (1 <<
sizeof(T)) - 1;
2123 if ((addr & alignment_mask) == 0 || IsMipsArchVariant(kMips32r6)) {
2124 T* ptr =
reinterpret_cast<T*
>(addr);
2125 TraceMemRd(addr, *ptr);
2128 PrintF(
"Unaligned read of type sizeof(%d) at 0x%08x, pc=0x%08" V8PRIxPTR
"\n",
2129 sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
2134 template <
typename T>
2135 void Simulator::WriteMem(int32_t addr, T value, Instruction* instr) {
2136 int alignment_mask = (1 <<
sizeof(T)) - 1;
2137 if ((addr & alignment_mask) == 0 || IsMipsArchVariant(kMips32r6)) {
2138 T* ptr =
reinterpret_cast<T*
>(addr);
2140 TraceMemWr(addr, value);
2143 PrintF(
"Unaligned write of type sizeof(%d) at 0x%08x, pc=0x%08" V8PRIxPTR
2145 sizeof(T), addr, reinterpret_cast<intptr_t>(instr));
2153 if (GetCurrentStackPosition() < c_limit) {
2154 return reinterpret_cast<uintptr_t>(get_sp());
2159 return reinterpret_cast<uintptr_t>(stack_) + 1024;
2164 void Simulator::Format(Instruction* instr,
const char* format) {
2165 PrintF(
"Simulator found unsupported instruction:\n 0x%08" PRIxPTR
": %s\n",
2166 reinterpret_cast<intptr_t>(instr), format);
2167 UNIMPLEMENTED_MIPS();
2177 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, int32_t arg1,
2178 int32_t arg2, int32_t arg3,
2179 int32_t arg4, int32_t arg5,
2180 int32_t arg6, int32_t arg7,
2184 typedef int64_t (*SimulatorRuntimeCompareCall)(
double darg0,
double darg1);
2185 typedef double (*SimulatorRuntimeFPFPCall)(
double darg0,
double darg1);
2186 typedef double (*SimulatorRuntimeFPCall)(
double darg0);
2187 typedef double (*SimulatorRuntimeFPIntCall)(
double darg0, int32_t arg0);
2191 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
2192 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0,
void* arg1);
2195 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
2196 typedef void (*SimulatorRuntimeProfilingGetterCall)(
2197 int32_t arg0, int32_t arg1,
void* arg2);
2201 void Simulator::SoftwareInterrupt() {
2205 int32_t func = instr_.FunctionFieldRaw();
2206 uint32_t code = (func == BREAK) ? instr_.Bits(25, 6) : -1;
2209 if (instr_.InstructionBits() == rtCallRedirInstr) {
2210 Redirection* redirection = Redirection::FromInstruction(instr_.instr());
2211 int32_t arg0 = get_register(a0);
2212 int32_t arg1 = get_register(a1);
2213 int32_t arg2 = get_register(a2);
2214 int32_t arg3 = get_register(a3);
2216 int32_t* stack_pointer =
reinterpret_cast<int32_t*
>(get_register(sp));
2218 int32_t arg4 = stack_pointer[4];
2219 int32_t arg5 = stack_pointer[5];
2220 int32_t arg6 = stack_pointer[6];
2221 int32_t arg7 = stack_pointer[7];
2222 int32_t arg8 = stack_pointer[8];
2223 STATIC_ASSERT(kMaxCParameters == 9);
2226 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
2227 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
2228 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
2229 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
2231 if (!IsMipsSoftFloatABI) {
2236 switch (redirection->type()) {
2237 case ExternalReference::BUILTIN_FP_FP_CALL:
2238 case ExternalReference::BUILTIN_COMPARE_CALL:
2240 arg0 = get_fpu_register_word(f12);
2241 arg1 = get_fpu_register_hi_word(f12);
2242 arg2 = get_fpu_register_word(f14);
2243 arg3 = get_fpu_register_hi_word(f14);
2245 arg0 = get_fpu_register_word(f12);
2246 arg1 = get_fpu_register_word(f13);
2247 arg2 = get_fpu_register_word(f14);
2248 arg3 = get_fpu_register_word(f15);
2251 case ExternalReference::BUILTIN_FP_CALL:
2253 arg0 = get_fpu_register_word(f12);
2254 arg1 = get_fpu_register_hi_word(f12);
2256 arg0 = get_fpu_register_word(f12);
2257 arg1 = get_fpu_register_word(f13);
2260 case ExternalReference::BUILTIN_FP_INT_CALL:
2262 arg0 = get_fpu_register_word(f12);
2263 arg1 = get_fpu_register_hi_word(f12);
2265 arg0 = get_fpu_register_word(f12);
2266 arg1 = get_fpu_register_word(f13);
2268 arg2 = get_register(a2);
2277 int32_t saved_ra = get_register(ra);
2280 reinterpret_cast<intptr_t
>(redirection->external_function());
2287 double dval0, dval1;
2291 GetFpArgs(&dval0, &dval1, &ival);
2292 SimulatorRuntimeCall generic_target =
2293 reinterpret_cast<SimulatorRuntimeCall
>(external);
2294 if (::v8::internal::FLAG_trace_sim) {
2295 switch (redirection->type()) {
2296 case ExternalReference::BUILTIN_FP_FP_CALL:
2297 case ExternalReference::BUILTIN_COMPARE_CALL:
2298 PrintF(
"Call to host function at %p with args %f, %f",
2299 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2302 case ExternalReference::BUILTIN_FP_CALL:
2303 PrintF(
"Call to host function at %p with arg %f",
2304 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2307 case ExternalReference::BUILTIN_FP_INT_CALL:
2308 PrintF(
"Call to host function at %p with args %f, %d",
2309 reinterpret_cast<void*>(FUNCTION_ADDR(generic_target)),
2317 switch (redirection->type()) {
2318 case ExternalReference::BUILTIN_COMPARE_CALL: {
2319 SimulatorRuntimeCompareCall target =
2320 reinterpret_cast<SimulatorRuntimeCompareCall
>(external);
2321 iresult = target(dval0, dval1);
2322 set_register(v0, static_cast<int32_t>(iresult));
2323 set_register(v1, static_cast<int32_t>(iresult >> 32));
2326 case ExternalReference::BUILTIN_FP_FP_CALL: {
2327 SimulatorRuntimeFPFPCall target =
2328 reinterpret_cast<SimulatorRuntimeFPFPCall
>(external);
2329 dresult = target(dval0, dval1);
2330 SetFpResult(dresult);
2333 case ExternalReference::BUILTIN_FP_CALL: {
2334 SimulatorRuntimeFPCall target =
2335 reinterpret_cast<SimulatorRuntimeFPCall
>(external);
2336 dresult = target(dval0);
2337 SetFpResult(dresult);
2340 case ExternalReference::BUILTIN_FP_INT_CALL: {
2341 SimulatorRuntimeFPIntCall target =
2342 reinterpret_cast<SimulatorRuntimeFPIntCall
>(external);
2343 dresult = target(dval0, ival);
2344 SetFpResult(dresult);
2351 if (::v8::internal::FLAG_trace_sim) {
2352 switch (redirection->type()) {
2353 case ExternalReference::BUILTIN_COMPARE_CALL:
2354 PrintF(
"Returned %08x\n", static_cast<int32_t>(iresult));
2356 case ExternalReference::BUILTIN_FP_FP_CALL:
2357 case ExternalReference::BUILTIN_FP_CALL:
2358 case ExternalReference::BUILTIN_FP_INT_CALL:
2359 PrintF(
"Returned %f\n", dresult);
2366 }
else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
2367 if (::v8::internal::FLAG_trace_sim) {
2368 PrintF(
"Call to host function at %p args %08x\n",
2369 reinterpret_cast<void*>(external), arg0);
2371 SimulatorRuntimeDirectApiCall target =
2372 reinterpret_cast<SimulatorRuntimeDirectApiCall
>(external);
2375 redirection->type() == ExternalReference::PROFILING_API_CALL) {
2376 if (::v8::internal::FLAG_trace_sim) {
2377 PrintF(
"Call to host function at %p args %08x %08x\n",
2378 reinterpret_cast<void*>(external), arg0, arg1);
2380 SimulatorRuntimeProfilingApiCall target =
2381 reinterpret_cast<SimulatorRuntimeProfilingApiCall
>(external);
2382 target(arg0, Redirection::ReverseRedirection(arg1));
2384 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
2385 if (::v8::internal::FLAG_trace_sim) {
2386 PrintF(
"Call to host function at %p args %08x %08x\n",
2387 reinterpret_cast<void*>(external), arg0, arg1);
2389 SimulatorRuntimeDirectGetterCall target =
2390 reinterpret_cast<SimulatorRuntimeDirectGetterCall
>(external);
2393 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
2394 if (::v8::internal::FLAG_trace_sim) {
2395 PrintF(
"Call to host function at %p args %08x %08x %08x\n",
2396 reinterpret_cast<void*>(external), arg0, arg1, arg2);
2398 SimulatorRuntimeProfilingGetterCall target =
2399 reinterpret_cast<SimulatorRuntimeProfilingGetterCall
>(external);
2400 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
2402 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
2403 redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
2404 SimulatorRuntimeCall target =
2405 reinterpret_cast<SimulatorRuntimeCall
>(external);
2406 if (::v8::internal::FLAG_trace_sim) {
2408 "Call to host function at %p " 2409 "args %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x\n",
2410 reinterpret_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2,
2411 arg3, arg4, arg5, arg6, arg7, arg8);
2414 target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
2415 set_register(v0, static_cast<int32_t>(result));
2416 set_register(v1, static_cast<int32_t>(result >> 32));
2418 if (::v8::internal::FLAG_trace_sim) {
2419 PrintF(
"Returned %08x : %08x\n", get_register(v1), get_register(v0));
2421 set_register(ra, saved_ra);
2422 set_pc(get_register(ra));
2424 }
else if (func == BREAK && code <= kMaxStopCode) {
2425 if (IsWatchpoint(code)) {
2426 PrintWatchpoint(code);
2428 IncreaseStopCounter(code);
2429 HandleStop(code, instr_.instr());
2433 MipsDebugger dbg(
this);
2440 bool Simulator::IsWatchpoint(
uint32_t code) {
2441 return (code <= kMaxWatchpointCode);
2445 void Simulator::PrintWatchpoint(
uint32_t code) {
2446 MipsDebugger dbg(
this);
2448 PrintF(
"\n---- break %d marker: %3d (instr count: %" PRIu64
2450 "----------------------------------",
2451 code, break_count_, icount_);
2456 void Simulator::HandleStop(
uint32_t code, Instruction* instr) {
2459 if (IsEnabledStop(code)) {
2460 MipsDebugger dbg(
this);
2466 bool Simulator::IsStopInstruction(Instruction* instr) {
2467 int32_t func = instr->FunctionFieldRaw();
2469 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
2473 bool Simulator::IsEnabledStop(
uint32_t code) {
2474 DCHECK_LE(code, kMaxStopCode);
2475 DCHECK_GT(code, kMaxWatchpointCode);
2476 return !(watched_stops_[code].count & kStopDisabledBit);
2480 void Simulator::EnableStop(
uint32_t code) {
2481 if (!IsEnabledStop(code)) {
2482 watched_stops_[code].count &= ~kStopDisabledBit;
2487 void Simulator::DisableStop(
uint32_t code) {
2488 if (IsEnabledStop(code)) {
2489 watched_stops_[code].count |= kStopDisabledBit;
2494 void Simulator::IncreaseStopCounter(
uint32_t code) {
2495 DCHECK_LE(code, kMaxStopCode);
2496 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7FFFFFFF) {
2497 PrintF(
"Stop counter for code %i has overflowed.\n" 2498 "Enabling this code and reseting the counter to 0.\n", code);
2499 watched_stops_[code].count = 0;
2502 watched_stops_[code].count++;
2508 void Simulator::PrintStopInfo(
uint32_t code) {
2509 if (code <= kMaxWatchpointCode) {
2510 PrintF(
"That is a watchpoint, not a stop.\n");
2512 }
else if (code > kMaxStopCode) {
2513 PrintF(
"Code too large, only %u stops can be used\n", kMaxStopCode + 1);
2516 const char* state = IsEnabledStop(code) ?
"Enabled" :
"Disabled";
2517 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2520 if (watched_stops_[code].desc) {
2521 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
2522 code, code, state, count, watched_stops_[code].desc);
2524 PrintF(
"stop %i - 0x%x: \t%s, \tcounter = %i\n",
2525 code, code, state, count);
2531 void Simulator::SignalException(Exception e) {
2532 FATAL(
"Error: Exception %i raised.", static_cast<int>(e));
2537 template <
typename T>
2538 static T FPAbs(T a);
2541 double FPAbs<double>(
double a) {
2546 float FPAbs<float>(
float a) {
2550 template <
typename T>
2551 static bool FPUProcessNaNsAndZeros(T a, T b, MaxMinKind kind, T& result) {
2552 if (std::isnan(a) && std::isnan(b)) {
2554 }
else if (std::isnan(a)) {
2556 }
else if (std::isnan(b)) {
2558 }
else if (b == a) {
2562 result = std::signbit(b) -
static_cast<int>(kind) ? b : a;
2569 template <
typename T>
2570 static T FPUMin(T a, T b) {
2572 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2575 return b < a ? b : a;
2579 template <
typename T>
2580 static T FPUMax(T a, T b) {
2582 if (FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMax, result)) {
2585 return b > a ? b : a;
2589 template <
typename T>
2590 static T FPUMinA(T a, T b) {
2592 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2593 if (FPAbs(a) < FPAbs(b)) {
2595 }
else if (FPAbs(b) < FPAbs(a)) {
2598 result = a < b ? a : b;
2604 template <
typename T>
2605 static T FPUMaxA(T a, T b) {
2607 if (!FPUProcessNaNsAndZeros(a, b, MaxMinKind::kMin, result)) {
2608 if (FPAbs(a) > FPAbs(b)) {
2610 }
else if (FPAbs(b) > FPAbs(a)) {
2613 result = a > b ? a : b;
2619 enum class KeepSign :
bool { no =
false, yes };
2621 template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
2623 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) {
2624 DCHECK(std::isnan(arg));
2625 T qNaN = std::numeric_limits<T>::quiet_NaN();
2626 if (keepSign == KeepSign::yes) {
2627 return std::copysign(qNaN, result);
2632 template <
typename T>
2633 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
2634 if (std::isnan(first)) {
2635 return FPUCanonalizeNaNArg(result, first, keepSign);
2640 template <
typename T,
typename... Args>
2641 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
2642 if (std::isnan(first)) {
2643 return FPUCanonalizeNaNArg(result, first, keepSign);
2645 return FPUCanonalizeNaNArgs(result, keepSign, args...);
2648 template <
typename Func,
typename T,
typename... Args>
2649 T FPUCanonalizeOperation(Func f, T first, Args... args) {
2650 return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
2653 template <
typename Func,
typename T,
typename... Args>
2654 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
2655 T result = f(first, args...);
2656 if (std::isnan(result)) {
2657 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
2664 void Simulator::DecodeTypeRegisterDRsType() {
2668 fs = get_fpu_register_double(fs_reg());
2669 ft = (instr_.FunctionFieldRaw() != MOVF) ? get_fpu_register_double(ft_reg())
2671 fd = get_fpu_register_double(fd_reg());
2674 cc = instr_.FCccValue();
2675 fcsr_cc = get_fcsr_condition_bit(cc);
2676 switch (instr_.FunctionFieldRaw()) {
2678 DCHECK(IsMipsArchVariant(kMips32r6));
2679 double result, temp, temp_result;
2680 double upper = std::ceil(fs);
2681 double lower = std::floor(fs);
2682 switch (get_fcsr_rounding_mode()) {
2683 case kRoundToNearest:
2684 if (upper - fs < fs - lower) {
2686 }
else if (upper - fs > fs - lower) {
2689 temp_result = upper / 2;
2690 double reminder = modf(temp_result, &temp);
2691 if (reminder == 0) {
2699 result = (fs > 0 ? lower : upper);
2701 case kRoundToPlusInf:
2704 case kRoundToMinusInf:
2708 SetFPUDoubleResult(fd_reg(), result);
2710 set_fcsr_bit(kFCSRInexactFlagBit,
true);
2715 DCHECK(IsMipsArchVariant(kMips32r6));
2716 SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
2719 DCHECK(IsMipsArchVariant(kMips32r6));
2720 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0);
2723 DCHECK(IsMipsArchVariant(kMips32r6));
2724 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0);
2727 DCHECK(IsMipsArchVariant(kMips32r2));
2729 SetFPUDoubleResult(fd_reg(), fs);
2734 DCHECK(IsMipsArchVariant(kMips32r2));
2735 int32_t rt_reg = instr_.RtValue();
2736 int32_t rt = get_register(rt_reg);
2738 SetFPUDoubleResult(fd_reg(), fs);
2744 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
2745 ft_cc = get_fcsr_condition_bit(ft_cc);
2746 if (instr_.Bit(16)) {
2748 if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
2751 if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs);
2756 DCHECK(IsMipsArchVariant(kMips32r6));
2757 SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs));
2760 DCHECK(IsMipsArchVariant(kMips32r6));
2761 SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs));
2764 DCHECK(IsMipsArchVariant(kMips32r6));
2765 SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs));
2768 DCHECK(IsMipsArchVariant(kMips32r6));
2769 SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs));
2774 FPUCanonalizeOperation(
2775 [](
double lhs,
double rhs) {
return lhs + rhs; }, fs, ft));
2780 FPUCanonalizeOperation(
2781 [](
double lhs,
double rhs) {
return lhs - rhs; }, fs, ft));
2784 DCHECK(IsMipsArchVariant(kMips32r6));
2785 SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd));
2788 DCHECK(IsMipsArchVariant(kMips32r6));
2789 SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd));
2794 FPUCanonalizeOperation(
2795 [](
double lhs,
double rhs) {
return lhs * rhs; }, fs, ft));
2800 FPUCanonalizeOperation(
2801 [](
double lhs,
double rhs) {
return lhs / rhs; }, fs, ft));
2806 FPUCanonalizeOperation([](
double fs) {
return FPAbs(fs); }, fs));
2809 SetFPUDoubleResult(fd_reg(), fs);
2812 SetFPUDoubleResult(fd_reg(),
2813 FPUCanonalizeOperation([](
double src) {
return -src; },
2814 KeepSign::yes, fs));
2819 FPUCanonalizeOperation([](
double fs) {
return std::sqrt(fs); }, fs));
2823 fd_reg(), FPUCanonalizeOperation(
2824 [](
double fs) {
return 1.0 / std::sqrt(fs); }, fs));
2827 SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation(
2828 [](
double fs) {
return 1.0 / fs; }, fs));
2831 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2832 TraceRegWr(test_fcsr_bit(fcsr_cc));
2835 set_fcsr_bit(fcsr_cc, (fs == ft));
2836 TraceRegWr(test_fcsr_bit(fcsr_cc));
2839 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2840 TraceRegWr(test_fcsr_bit(fcsr_cc));
2843 set_fcsr_bit(fcsr_cc, (fs < ft));
2844 TraceRegWr(test_fcsr_bit(fcsr_cc));
2847 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2848 TraceRegWr(test_fcsr_bit(fcsr_cc));
2851 set_fcsr_bit(fcsr_cc, (fs <= ft));
2852 TraceRegWr(test_fcsr_bit(fcsr_cc));
2855 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2856 TraceRegWr(test_fcsr_bit(fcsr_cc));
2861 round_according_to_fcsr(fs, rounded, result, fs);
2862 SetFPUWordResult(fd_reg(), result);
2863 if (set_fcsr_round_error(fs, rounded)) {
2864 set_fpu_register_word_invalid_result(fs, rounded);
2869 double rounded = std::floor(fs + 0.5);
2870 int32_t result =
static_cast<int32_t
>(rounded);
2871 if ((result & 1) != 0 && result - fs == 0.5) {
2876 SetFPUWordResult(fd_reg(), result);
2877 if (set_fcsr_round_error(fs, rounded)) {
2878 set_fpu_register_word_invalid_result(fs, rounded);
2883 double rounded = trunc(fs);
2884 int32_t result =
static_cast<int32_t
>(rounded);
2885 SetFPUWordResult(fd_reg(), result);
2886 if (set_fcsr_round_error(fs, rounded)) {
2887 set_fpu_register_word_invalid_result(fs, rounded);
2892 double 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 double 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_word_invalid_result(fs, rounded);
2909 SetFPUFloatResult(fd_reg(), static_cast<float>(fs));
2915 round64_according_to_fcsr(fs, rounded, result, fs);
2916 SetFPUResult(fd_reg(), result);
2917 if (set_fcsr_round64_error(fs, rounded)) {
2918 set_fpu_register_invalid_result64(fs, rounded);
2927 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2928 double rounded = trunc(fs);
2929 i64 =
static_cast<int64_t>(rounded);
2931 SetFPUResult(fd_reg(), i64);
2932 if (set_fcsr_round64_error(fs, rounded)) {
2933 set_fpu_register_invalid_result64(fs, rounded);
2941 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2942 double rounded = std::floor(fs + 0.5);
2944 if ((result & 1) != 0 && result - fs == 0.5) {
2951 SetFPUResult(fd_reg(), i64);
2952 if (set_fcsr_round64_error(fs, rounded)) {
2953 set_fpu_register_invalid_result64(fs, rounded);
2961 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2962 double rounded = std::floor(fs);
2965 SetFPUResult(fd_reg(), i64);
2966 if (set_fcsr_round64_error(fs, rounded)) {
2967 set_fpu_register_invalid_result64(fs, rounded);
2975 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
2976 double rounded = std::ceil(fs);
2979 SetFPUResult(fd_reg(), i64);
2980 if (set_fcsr_round64_error(fs, rounded)) {
2981 set_fpu_register_invalid_result64(fs, rounded);
2990 uint64_t classed = bit_cast<uint64_t>(fs);
2993 uint32_t sign = (classed >> 63) & 1;
2994 uint32_t exponent = (classed >> 52) & 0x00000000000007FF;
2995 uint64_t mantissa = classed & 0x000FFFFFFFFFFFFF;
3001 bool negInf = (classed == 0xFFF0000000000000);
3002 bool posInf = (classed == 0x7FF0000000000000);
3003 bool negZero = (classed == 0x8000000000000000);
3004 bool posZero = (classed == 0x0000000000000000);
3014 signalingNan =
false;
3016 if (!negInf && !posInf && exponent == 0x7FF) {
3017 quietNan = ((mantissa & 0x0008000000000000) != 0) &&
3018 ((mantissa & (0x0008000000000000 - 1)) == 0);
3019 signalingNan = !quietNan;
3025 if ((exponent == 0) && (mantissa != 0)) {
3026 DCHECK(sign == 0 || sign == 1);
3027 posSubnorm = (sign == 0);
3028 negSubnorm = (sign == 1);
3034 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3035 !quietNan && !negZero && !posZero) {
3036 DCHECK(sign == 0 || sign == 1);
3037 posNorm = (sign == 0);
3038 negNorm = (sign == 1);
3042 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3043 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3044 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3046 DCHECK_NE(result, 0);
3048 dResult = bit_cast<
double>(result);
3049 SetFPUDoubleResult(fd_reg(), dResult);
3054 set_fcsr_bit(fcsr_cc,
false);
3055 TraceRegWr(test_fcsr_bit(fcsr_cc));
3064 void Simulator::DecodeTypeRegisterWRsType() {
3065 float fs = get_fpu_register_float(fs_reg());
3066 float ft = get_fpu_register_float(ft_reg());
3067 int32_t alu_out = 0x12345678;
3068 switch (instr_.FunctionFieldRaw()) {
3070 alu_out = get_fpu_register_signed_word(fs_reg());
3071 SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out));
3074 alu_out = get_fpu_register_signed_word(fs_reg());
3075 SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out));
3078 SetFPUWordResult(fd_reg(), 0);
3081 if (std::isnan(fs) || std::isnan(ft)) {
3082 SetFPUWordResult(fd_reg(), -1);
3084 SetFPUWordResult(fd_reg(), 0);
3089 SetFPUWordResult(fd_reg(), -1);
3091 SetFPUWordResult(fd_reg(), 0);
3095 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3096 SetFPUWordResult(fd_reg(), -1);
3098 SetFPUWordResult(fd_reg(), 0);
3103 SetFPUWordResult(fd_reg(), -1);
3105 SetFPUWordResult(fd_reg(), 0);
3109 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3110 SetFPUWordResult(fd_reg(), -1);
3112 SetFPUWordResult(fd_reg(), 0);
3117 SetFPUWordResult(fd_reg(), -1);
3119 SetFPUWordResult(fd_reg(), 0);
3123 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3124 SetFPUWordResult(fd_reg(), -1);
3126 SetFPUWordResult(fd_reg(), 0);
3130 if (!std::isnan(fs) && !std::isnan(ft)) {
3131 SetFPUWordResult(fd_reg(), -1);
3133 SetFPUWordResult(fd_reg(), 0);
3137 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3138 SetFPUWordResult(fd_reg(), -1);
3140 SetFPUWordResult(fd_reg(), 0);
3145 SetFPUWordResult(fd_reg(), -1);
3147 SetFPUWordResult(fd_reg(), 0);
3156 void Simulator::DecodeTypeRegisterSRsType() {
3158 fs = get_fpu_register_float(fs_reg());
3159 ft = get_fpu_register_float(ft_reg());
3160 fd = get_fpu_register_float(fd_reg());
3161 int32_t ft_int = bit_cast<int32_t>(ft);
3162 int32_t fd_int = bit_cast<int32_t>(fd);
3164 cc = instr_.FCccValue();
3165 fcsr_cc = get_fcsr_condition_bit(cc);
3166 switch (instr_.FunctionFieldRaw()) {
3168 DCHECK(IsMipsArchVariant(kMips32r6));
3169 float result, temp_result;
3171 float upper = std::ceil(fs);
3172 float lower = std::floor(fs);
3173 switch (get_fcsr_rounding_mode()) {
3174 case kRoundToNearest:
3175 if (upper - fs < fs - lower) {
3177 }
else if (upper - fs > fs - lower) {
3180 temp_result = upper / 2;
3181 float reminder = modf(temp_result, &temp);
3182 if (reminder == 0) {
3190 result = (fs > 0 ? lower : upper);
3192 case kRoundToPlusInf:
3195 case kRoundToMinusInf:
3199 SetFPUFloatResult(fd_reg(), result);
3201 set_fcsr_bit(kFCSRInexactFlagBit,
true);
3208 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs + rhs; },
3214 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs - rhs; },
3218 DCHECK(IsMipsArchVariant(kMips32r6));
3219 SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd));
3222 DCHECK(IsMipsArchVariant(kMips32r6));
3223 SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd));
3228 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs * rhs; },
3234 FPUCanonalizeOperation([](
float lhs,
float rhs) {
return lhs / rhs; },
3238 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
3239 [](
float fs) {
return FPAbs(fs); }, fs));
3242 SetFPUFloatResult(fd_reg(), fs);
3245 SetFPUFloatResult(fd_reg(),
3246 FPUCanonalizeOperation([](
float src) {
return -src; },
3247 KeepSign::yes, fs));
3252 FPUCanonalizeOperation([](
float src) {
return std::sqrt(src); }, fs));
3256 fd_reg(), FPUCanonalizeOperation(
3257 [](
float src) {
return 1.0 / std::sqrt(src); }, fs));
3260 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation(
3261 [](
float src) {
return 1.0 / src; }, fs));
3264 set_fcsr_bit(fcsr_cc,
false);
3265 TraceRegWr(test_fcsr_bit(fcsr_cc));
3268 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
3269 TraceRegWr(test_fcsr_bit(fcsr_cc));
3272 set_fcsr_bit(fcsr_cc, (fs == ft));
3273 TraceRegWr(test_fcsr_bit(fcsr_cc));
3276 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
3277 TraceRegWr(test_fcsr_bit(fcsr_cc));
3280 set_fcsr_bit(fcsr_cc, (fs < ft));
3281 TraceRegWr(test_fcsr_bit(fcsr_cc));
3284 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
3285 TraceRegWr(test_fcsr_bit(fcsr_cc));
3288 set_fcsr_bit(fcsr_cc, (fs <= ft));
3289 TraceRegWr(test_fcsr_bit(fcsr_cc));
3292 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
3293 TraceRegWr(test_fcsr_bit(fcsr_cc));
3296 SetFPUDoubleResult(fd_reg(), static_cast<double>(fs));
3299 DCHECK(IsMipsArchVariant(kMips32r6));
3300 SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft);
3304 float fs = get_fpu_register_float(fs_reg());
3308 uint32_t sign = (classed >> 31) & 1;
3309 uint32_t exponent = (classed >> 23) & 0x000000FF;
3310 uint32_t mantissa = classed & 0x007FFFFF;
3316 bool negInf = (classed == 0xFF800000);
3317 bool posInf = (classed == 0x7F800000);
3318 bool negZero = (classed == 0x80000000);
3319 bool posZero = (classed == 0x00000000);
3329 signalingNan =
false;
3331 if (!negInf && !posInf && (exponent == 0xFF)) {
3332 quietNan = ((mantissa & 0x00200000) == 0) &&
3333 ((mantissa & (0x00200000 - 1)) == 0);
3334 signalingNan = !quietNan;
3340 if ((exponent == 0) && (mantissa != 0)) {
3341 DCHECK(sign == 0 || sign == 1);
3342 posSubnorm = (sign == 0);
3343 negSubnorm = (sign == 1);
3349 if (!posSubnorm && !negSubnorm && !posInf && !negInf && !signalingNan &&
3350 !quietNan && !negZero && !posZero) {
3351 DCHECK(sign == 0 || sign == 1);
3352 posNorm = (sign == 0);
3353 negNorm = (sign == 1);
3357 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) |
3358 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) |
3359 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan;
3361 DCHECK_NE(result, 0);
3363 fResult = bit_cast<
float>(result);
3364 SetFPUFloatResult(fd_reg(), fResult);
3369 DCHECK(IsMipsArchVariant(kMips32r6));
3372 (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0);
3375 DCHECK(IsMipsArchVariant(kMips32r6));
3378 (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0);
3381 DCHECK(IsMipsArchVariant(kMips32r2));
3383 SetFPUFloatResult(fd_reg(), fs);
3388 DCHECK(IsMipsArchVariant(kMips32r2));
3390 SetFPUFloatResult(fd_reg(), fs);
3396 uint32_t ft_cc = (ft_reg() >> 2) & 0x7;
3397 ft_cc = get_fcsr_condition_bit(ft_cc);
3399 if (instr_.Bit(16)) {
3401 if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
3404 if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs);
3409 float rounded = trunc(fs);
3410 int32_t result =
static_cast<int32_t
>(rounded);
3411 SetFPUWordResult(fd_reg(), result);
3412 if (set_fcsr_round_error(fs, rounded)) {
3413 set_fpu_register_word_invalid_result(fs, rounded);
3417 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3418 float rounded = trunc(fs);
3421 SetFPUResult(fd_reg(), i64);
3422 if (set_fcsr_round64_error(fs, rounded)) {
3423 set_fpu_register_invalid_result64(fs, rounded);
3432 float rounded = std::floor(fs);
3433 int32_t result =
static_cast<int32_t
>(rounded);
3434 SetFPUWordResult(fd_reg(), result);
3435 if (set_fcsr_round_error(fs, rounded)) {
3436 set_fpu_register_word_invalid_result(fs, rounded);
3440 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3441 float rounded = std::floor(fs);
3444 SetFPUResult(fd_reg(), i64);
3445 if (set_fcsr_round64_error(fs, rounded)) {
3446 set_fpu_register_invalid_result64(fs, rounded);
3454 float rounded = std::floor(fs + 0.5);
3455 int32_t result =
static_cast<int32_t
>(rounded);
3456 if ((result & 1) != 0 && result - fs == 0.5) {
3461 SetFPUWordResult(fd_reg(), result);
3462 if (set_fcsr_round_error(fs, rounded)) {
3463 set_fpu_register_word_invalid_result(fs, rounded);
3468 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3469 float rounded = std::floor(fs + 0.5);
3471 if ((result & 1) != 0 && result - fs == 0.5) {
3478 SetFPUResult(fd_reg(), i64);
3479 if (set_fcsr_round64_error(fs, rounded)) {
3480 set_fpu_register_invalid_result64(fs, rounded);
3489 float rounded = std::ceil(fs);
3490 int32_t result =
static_cast<int32_t
>(rounded);
3491 SetFPUWordResult(fd_reg(), result);
3492 if (set_fcsr_round_error(fs, rounded)) {
3493 set_fpu_register_word_invalid_result(fs, rounded);
3497 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
3498 float rounded = std::ceil(fs);
3501 SetFPUResult(fd_reg(), i64);
3502 if (set_fcsr_round64_error(fs, rounded)) {
3503 set_fpu_register_invalid_result64(fs, rounded);
3511 DCHECK(IsMipsArchVariant(kMips32r6));
3512 SetFPUFloatResult(fd_reg(), FPUMin(ft, fs));
3515 DCHECK(IsMipsArchVariant(kMips32r6));
3516 SetFPUFloatResult(fd_reg(), FPUMax(ft, fs));
3519 DCHECK(IsMipsArchVariant(kMips32r6));
3520 SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs));
3523 DCHECK(IsMipsArchVariant(kMips32r6));
3524 SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs));
3530 round64_according_to_fcsr(fs, rounded, result, fs);
3531 SetFPUResult(fd_reg(), result);
3532 if (set_fcsr_round64_error(fs, rounded)) {
3533 set_fpu_register_invalid_result64(fs, rounded);
3543 round_according_to_fcsr(fs, rounded, result, fs);
3544 SetFPUWordResult(fd_reg(), result);
3545 if (set_fcsr_round_error(fs, rounded)) {
3546 set_fpu_register_word_invalid_result(fs, rounded);
3558 void Simulator::DecodeTypeRegisterLRsType() {
3559 double fs = get_fpu_register_double(fs_reg());
3560 double ft = get_fpu_register_double(ft_reg());
3561 switch (instr_.FunctionFieldRaw()) {
3567 i64 = get_fpu_register(fs_reg());
3569 i64 =
static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
3570 i64 |=
static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
3572 SetFPUDoubleResult(fd_reg(), static_cast<double>(i64));
3576 i64 = get_fpu_register(fs_reg());
3578 i64 =
static_cast<uint32_t>(get_fpu_register_word(fs_reg()));
3579 i64 |=
static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32;
3581 SetFPUFloatResult(fd_reg(), static_cast<float>(i64));
3584 SetFPUResult(fd_reg(), 0);
3587 if (std::isnan(fs) || std::isnan(ft)) {
3588 SetFPUResult(fd_reg(), -1);
3590 SetFPUResult(fd_reg(), 0);
3595 SetFPUResult(fd_reg(), -1);
3597 SetFPUResult(fd_reg(), 0);
3601 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
3602 SetFPUResult(fd_reg(), -1);
3604 SetFPUResult(fd_reg(), 0);
3609 SetFPUResult(fd_reg(), -1);
3611 SetFPUResult(fd_reg(), 0);
3615 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
3616 SetFPUResult(fd_reg(), -1);
3618 SetFPUResult(fd_reg(), 0);
3623 SetFPUResult(fd_reg(), -1);
3625 SetFPUResult(fd_reg(), 0);
3629 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
3630 SetFPUResult(fd_reg(), -1);
3632 SetFPUResult(fd_reg(), 0);
3636 if (!std::isnan(fs) && !std::isnan(ft)) {
3637 SetFPUResult(fd_reg(), -1);
3639 SetFPUResult(fd_reg(), 0);
3643 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) {
3644 SetFPUResult(fd_reg(), -1);
3646 SetFPUResult(fd_reg(), 0);
3650 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) {
3651 SetFPUResult(fd_reg(), -1);
3653 SetFPUResult(fd_reg(), 0);
3662 void Simulator::DecodeTypeRegisterCOP1() {
3663 switch (instr_.RsFieldRaw()) {
3666 DCHECK_EQ(fs_reg(), kFCSRRegister);
3667 SetResult(rt_reg(), FCSR_);
3670 SetResult(rt_reg(), get_fpu_register_word(fs_reg()));
3674 SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg()));
3676 SetResult(rt_reg(), get_fpu_register_word(fs_reg() + 1));
3681 DCHECK_EQ(fs_reg(), kFCSRRegister);
3682 int32_t reg = registers_[rt_reg()];
3683 if (IsMipsArchVariant(kMips32r6)) {
3684 FCSR_ = reg | kFCSRNaN2008FlagMask;
3686 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2));
3687 FCSR_ = reg & ~kFCSRNaN2008FlagMask;
3689 TraceRegWr(static_cast<int32_t>(FCSR_));
3694 set_fpu_register_hi_word(fs_reg(), 0);
3695 set_fpu_register_word(fs_reg(), registers_[rt_reg()]);
3696 TraceRegWr(get_fpu_register_word(fs_reg()), FLOAT);
3700 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]);
3701 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
3703 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]);
3705 TraceRegWr(get_fpu_register_word(fs_reg() + 1), FLOAT);
3707 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE);
3712 DecodeTypeRegisterSRsType();
3716 DecodeTypeRegisterDRsType();
3719 DecodeTypeRegisterWRsType();
3722 DecodeTypeRegisterLRsType();
3733 void Simulator::DecodeTypeRegisterCOP1X() {
3734 switch (instr_.FunctionFieldRaw()) {
3736 DCHECK(IsMipsArchVariant(kMips32r2));
3738 fr = get_fpu_register_float(fr_reg());
3739 fs = get_fpu_register_float(fs_reg());
3740 ft = get_fpu_register_float(ft_reg());
3741 SetFPUFloatResult(fd_reg(), fs * ft + fr);
3745 DCHECK(IsMipsArchVariant(kMips32r2));
3747 fr = get_fpu_register_float(fr_reg());
3748 fs = get_fpu_register_float(fs_reg());
3749 ft = get_fpu_register_float(ft_reg());
3750 SetFPUFloatResult(fd_reg(), fs * ft - fr);
3754 DCHECK(IsMipsArchVariant(kMips32r2));
3756 fr = get_fpu_register_double(fr_reg());
3757 fs = get_fpu_register_double(fs_reg());
3758 ft = get_fpu_register_double(ft_reg());
3759 SetFPUDoubleResult(fd_reg(), fs * ft + fr);
3763 DCHECK(IsMipsArchVariant(kMips32r2));
3765 fr = get_fpu_register_double(fr_reg());
3766 fs = get_fpu_register_double(fs_reg());
3767 ft = get_fpu_register_double(ft_reg());
3768 SetFPUDoubleResult(fd_reg(), fs * ft - fr);
3777 void Simulator::DecodeTypeRegisterSPECIAL() {
3780 uint64_t u64hilo = 0;
3781 bool do_interrupt =
false;
3783 switch (instr_.FunctionFieldRaw()) {
3785 DCHECK(IsMipsArchVariant(kMips32r6));
3786 SetResult(rd_reg(), rt() == 0 ? rs() : 0);
3789 DCHECK(IsMipsArchVariant(kMips32r6));
3790 SetResult(rd_reg(), rt() != 0 ? rs() : 0);
3793 int32_t next_pc = rs();
3794 int32_t current_pc = get_pc();
3795 Instruction* branch_delay_instr =
3796 reinterpret_cast<Instruction*
>(current_pc + kInstrSize);
3797 BranchDelayInstructionDecode(branch_delay_instr);
3799 pc_modified_ =
true;
3803 int32_t next_pc = rs();
3804 int32_t return_addr_reg = rd_reg();
3805 int32_t current_pc = get_pc();
3806 Instruction* branch_delay_instr =
3807 reinterpret_cast<Instruction*
>(current_pc + kInstrSize);
3808 BranchDelayInstructionDecode(branch_delay_instr);
3809 set_register(return_addr_reg, current_pc + 2 * kInstrSize);
3811 pc_modified_ =
true;
3815 alu_out = rt() << sa();
3816 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3819 if (rs_reg() == 0) {
3822 alu_out = rt_u() >> sa();
3827 alu_out = base::bits::RotateRight32(rt_u(), sa());
3829 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3832 alu_out = rt() >> sa();
3833 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3836 alu_out = rt() << rs();
3837 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3843 alu_out = rt_u() >> rs();
3848 alu_out = base::bits::RotateRight32(rt_u(), rs_u());
3850 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3853 SetResult(rd_reg(), rt() >> rs());
3856 DCHECK(IsMipsArchVariant(kMips32r6));
3857 int8_t sa = lsa_sa() + 1;
3860 int32_t res = _rs << sa;
3862 DCHECK_EQ(res, (rs() << (lsa_sa() + 1)) + rt());
3863 SetResult(rd_reg(), (rs() << (lsa_sa() + 1)) + rt());
3867 if (!IsMipsArchVariant(kMips32r6)) {
3869 alu_out = get_register(HI);
3874 alu_out = base::bits::CountLeadingZeros32(rs_u());
3876 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3879 alu_out = get_register(LO);
3880 SetResult(rd_reg(), static_cast<int32_t>(alu_out));
3884 i64hilo =
static_cast<int64_t>(rs()) * static_cast<int64_t>(rt());
3885 if (!IsMipsArchVariant(kMips32r6)) {
3886 set_register(LO, static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
3887 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
3891 SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xFFFFFFFF));
3894 SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32));
3897 UNIMPLEMENTED_MIPS();
3903 u64hilo =
static_cast<uint64_t
>(rs_u()) * static_cast<uint64_t>(rt_u());
3904 if (!IsMipsArchVariant(kMips32r6)) {
3905 set_register(LO, static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
3906 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
3910 SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xFFFFFFFF));
3913 SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32));
3916 UNIMPLEMENTED_MIPS();
3922 if (IsMipsArchVariant(kMips32r6)) {
3925 if (rs() == INT_MIN && rt() == -1) {
3926 SetResult(rd_reg(), INT_MIN);
3927 }
else if (rt() != 0) {
3928 SetResult(rd_reg(), rs() / rt());
3932 if (rs() == INT_MIN && rt() == -1) {
3933 SetResult(rd_reg(), 0);
3934 }
else if (rt() != 0) {
3935 SetResult(rd_reg(), rs() % rt());
3939 UNIMPLEMENTED_MIPS();
3947 if (rs() == INT_MIN && rt() == -1) {
3948 set_register(LO, INT_MIN);
3949 set_register(HI, 0);
3950 }
else if (rt() != 0) {
3951 set_register(LO, rs() / rt());
3952 set_register(HI, rs() % rt());
3957 if (IsMipsArchVariant(kMips32r6)) {
3961 SetResult(rd_reg(), rs_u() / rt_u());
3966 SetResult(rd_reg(), rs_u() % rt_u());
3970 UNIMPLEMENTED_MIPS();
3975 set_register(LO, rs_u() / rt_u());
3976 set_register(HI, rs_u() % rt_u());
3981 if (HaveSameSign(rs(), rt())) {
3983 if (rs() <= (Registers::kMaxValue - rt())) {
3984 SignalException(kIntegerOverflow);
3986 }
else if (rs() < 0) {
3987 if (rs() >= (Registers::kMinValue - rt())) {
3988 SignalException(kIntegerUnderflow);
3992 SetResult(rd_reg(), rs() + rt());
3995 SetResult(rd_reg(), rs() + rt());
3998 if (!HaveSameSign(rs(), rt())) {
4000 if (rs() <= (Registers::kMaxValue + rt())) {
4001 SignalException(kIntegerOverflow);
4003 }
else if (rs() < 0) {
4004 if (rs() >= (Registers::kMinValue + rt())) {
4005 SignalException(kIntegerUnderflow);
4009 SetResult(rd_reg(), rs() - rt());
4012 SetResult(rd_reg(), rs() - rt());
4015 SetResult(rd_reg(), rs() & rt());
4018 SetResult(rd_reg(), rs() | rt());
4021 SetResult(rd_reg(), rs() ^ rt());
4024 SetResult(rd_reg(), ~(rs() | rt()));
4027 SetResult(rd_reg(), rs() < rt() ? 1 : 0);
4030 SetResult(rd_reg(), rs_u() < rt_u() ? 1 : 0);
4034 do_interrupt =
true;
4037 do_interrupt = rs() >= rt();
4040 do_interrupt = rs_u() >= rt_u();
4043 do_interrupt = rs() < rt();
4046 do_interrupt = rs_u() < rt_u();
4049 do_interrupt = rs() == rt();
4052 do_interrupt = rs() != rt();
4060 SetResult(rd_reg(), rs());
4065 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
4066 if (instr_.Bit(16)) {
4067 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
4069 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs());
4075 SetResult(rd_reg(), rs());
4082 SoftwareInterrupt();
4087 void Simulator::DecodeTypeRegisterSPECIAL2() {
4089 switch (instr_.FunctionFieldRaw()) {
4092 alu_out = rs_u() * rt_u();
4094 set_register(LO, Unpredictable);
4095 set_register(HI, Unpredictable);
4100 alu_out = base::bits::CountLeadingZeros32(rs_u());
4103 alu_out = 0x12345678;
4106 SetResult(rd_reg(), alu_out);
4110 void Simulator::DecodeTypeRegisterSPECIAL3() {
4112 switch (instr_.FunctionFieldRaw()) {
4115 uint16_t msb = rd_reg();
4117 uint16_t lsb = sa();
4118 uint16_t size = msb - lsb + 1;
4121 mask = (1 << size) - 1;
4123 mask = std::numeric_limits<uint32_t>::max();
4125 alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
4127 SetResult(rt_reg(), alu_out);
4132 uint16_t msb = rd_reg();
4134 uint16_t lsb = sa();
4135 uint16_t size = msb + 1;
4138 mask = (1 << size) - 1;
4140 mask = std::numeric_limits<uint32_t>::max();
4142 alu_out = (rs_u() & (mask << lsb)) >> lsb;
4143 SetResult(rt_reg(), alu_out);
4147 int sa = instr_.SaFieldRaw() >> kSaShift;
4152 uint8_t i_byte, o_byte;
4155 for (
int i = 0;
i < 4;
i++) {
4156 output = output >> 8;
4157 i_byte = input & 0xFF;
4161 o_byte =
static_cast<uint8_t
>(((i_byte * 0x0802LU & 0x22110LU) |
4162 (i_byte * 0x8020LU & 0x88440LU)) *
4166 output = output | (
static_cast<uint32_t>(o_byte << 24));
4170 alu_out =
static_cast<int32_t
>(output);
4174 uint8_t input =
static_cast<uint8_t
>(rt());
4180 output |= 0xFFFFFF00;
4183 alu_out =
static_cast<int32_t
>(output);
4187 uint16_t input =
static_cast<uint16_t
>(rt());
4193 output |= 0xFFFF0000;
4196 alu_out =
static_cast<int32_t
>(output);
4204 for (
int i = 0;
i < 4;
i++) {
4211 output = output | tmp;
4215 alu_out =
static_cast<int32_t
>(output);
4219 const uint8_t bp = instr_.Bp2Value();
4224 alu_out =
static_cast<int32_t
>(rt());
4227 uint32_t rs_lo = rs() >> (8 * (4 - bp));
4228 alu_out =
static_cast<int32_t
>(rt_hi | rs_lo);
4233 alu_out = 0x12345678;
4239 SetResult(rd_reg(), alu_out);
4247 int Simulator::DecodeMsaDataFormat() {
4249 if (instr_.IsMSABranchInstr()) {
4250 switch (instr_.RsFieldRaw()) {
4276 int DF[] = {MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD};
4277 switch (instr_.MSAMinorOpcodeField()) {
4281 df = DF[instr_.Bits(22, 21)];
4284 df = DF[instr_.Bits(1, 0)];
4287 df = DF[instr_.MsaBitDf()];
4290 df = DF[instr_.MsaElmDf()];
4292 case kMsaMinor3RF: {
4293 uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
4303 df = DF[1 + instr_.Bit(21)];
4306 df = DF[2 + instr_.Bit(21)];
4311 df = DF[instr_.Bits(17, 16)];
4314 df = DF[2 + instr_.Bit(16)];
4324 void Simulator::DecodeTypeMsaI8() {
4325 DCHECK(IsMipsArchVariant(kMips32r6));
4326 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4327 uint32_t opcode = instr_.InstructionBits() & kMsaI8Mask;
4328 int8_t i8 = instr_.MsaImm8Value();
4333 get_msa_register(instr_.WsValue(), ws.b);
4334 for (
int i = 0;
i < kMSALanesByte;
i++) {
4335 wd.b[
i] = ws.b[
i] & i8;
4337 set_msa_register(instr_.WdValue(), wd.b);
4338 TraceMSARegWr(wd.b);
4341 get_msa_register(instr_.WsValue(), ws.b);
4342 for (
int i = 0;
i < kMSALanesByte;
i++) {
4343 wd.b[
i] = ws.b[
i] | i8;
4345 set_msa_register(instr_.WdValue(), wd.b);
4346 TraceMSARegWr(wd.b);
4349 get_msa_register(instr_.WsValue(), ws.b);
4350 for (
int i = 0;
i < kMSALanesByte;
i++) {
4351 wd.b[
i] = ~(ws.b[
i] | i8);
4353 set_msa_register(instr_.WdValue(), wd.b);
4354 TraceMSARegWr(wd.b);
4357 get_msa_register(instr_.WsValue(), ws.b);
4358 for (
int i = 0;
i < kMSALanesByte;
i++) {
4359 wd.b[
i] = ws.b[
i] ^ i8;
4361 set_msa_register(instr_.WdValue(), wd.b);
4362 TraceMSARegWr(wd.b);
4365 get_msa_register(instr_.WsValue(), ws.b);
4366 get_msa_register(instr_.WdValue(), wd.b);
4367 for (
int i = 0;
i < kMSALanesByte;
i++) {
4368 wd.b[
i] = (ws.b[
i] & i8) | (wd.b[
i] & ~i8);
4370 set_msa_register(instr_.WdValue(), wd.b);
4371 TraceMSARegWr(wd.b);
4374 get_msa_register(instr_.WsValue(), ws.b);
4375 get_msa_register(instr_.WdValue(), wd.b);
4376 for (
int i = 0;
i < kMSALanesByte;
i++) {
4377 wd.b[
i] = (ws.b[
i] & ~i8) | (wd.b[
i] & i8);
4379 set_msa_register(instr_.WdValue(), wd.b);
4380 TraceMSARegWr(wd.b);
4383 get_msa_register(instr_.WsValue(), ws.b);
4384 get_msa_register(instr_.WdValue(), wd.b);
4385 for (
int i = 0;
i < kMSALanesByte;
i++) {
4386 wd.b[
i] = (ws.b[
i] & ~wd.b[
i]) | (wd.b[
i] & i8);
4388 set_msa_register(instr_.WdValue(), wd.b);
4389 TraceMSARegWr(wd.b);
4392 get_msa_register(instr_.WsValue(), ws.b);
4393 for (
int i = 0;
i < kMSALanesByte;
i++) {
4395 int k = (i8 >> (2 * j)) & 0x3;
4396 wd.b[
i] = ws.b[
i - j + k];
4398 set_msa_register(instr_.WdValue(), wd.b);
4399 TraceMSARegWr(wd.b);
4402 get_msa_register(instr_.WsValue(), ws.h);
4403 for (
int i = 0;
i < kMSALanesHalf;
i++) {
4405 int k = (i8 >> (2 * j)) & 0x3;
4406 wd.h[
i] = ws.h[
i - j + k];
4408 set_msa_register(instr_.WdValue(), wd.h);
4409 TraceMSARegWr(wd.h);
4412 get_msa_register(instr_.WsValue(), ws.w);
4413 for (
int i = 0;
i < kMSALanesWord;
i++) {
4414 int j = (i8 >> (2 *
i)) & 0x3;
4417 set_msa_register(instr_.WdValue(), wd.w);
4418 TraceMSARegWr(wd.w);
4425 template <
typename T>
4426 T Simulator::MsaI5InstrHelper(
uint32_t opcode, T ws, int32_t i5) {
4429 uint64_t ws_u64 =
static_cast<uint64_t
>(ws);
4430 uint64_t ui5_u64 =
static_cast<uint64_t
>(ui5);
4434 res =
static_cast<T
>(ws + ui5);
4437 res =
static_cast<T
>(ws - ui5);
4440 res =
static_cast<T
>(Max(ws, static_cast<T>(i5)));
4443 res =
static_cast<T
>(Min(ws, static_cast<T>(i5)));
4446 res =
static_cast<T
>(Max(ws_u64, ui5_u64));
4449 res =
static_cast<T
>(Min(ws_u64, ui5_u64));
4452 res =
static_cast<T
>(!Compare(ws, static_cast<T>(i5)) ? -1ull : 0ull);
4455 res =
static_cast<T
>((Compare(ws, static_cast<T>(i5)) == -1) ? -1ull
4459 res =
static_cast<T
>((Compare(ws_u64, ui5_u64) == -1) ? -1ull : 0ull);
4463 static_cast<T
>((Compare(ws, static_cast<T>(i5)) != 1) ? -1ull : 0ull);
4466 res =
static_cast<T
>((Compare(ws_u64, ui5_u64) != 1) ? -1ull : 0ull);
4474 void Simulator::DecodeTypeMsaI5() {
4475 DCHECK(IsMipsArchVariant(kMips32r6));
4476 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4477 uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
4481 int32_t i5 =
static_cast<int32_t
>(instr_.MsaImm5Value() << 27) >> 27;
4483 #define MSA_I5_DF(elem, num_of_lanes) \ 4484 get_msa_register(instr_.WsValue(), ws.elem); \ 4485 for (int i = 0; i < num_of_lanes; i++) { \ 4486 wd.elem[i] = MsaI5InstrHelper(opcode, ws.elem[i], i5); \ 4488 set_msa_register(instr_.WdValue(), wd.elem); \ 4489 TraceMSARegWr(wd.elem) 4491 switch (DecodeMsaDataFormat()) {
4493 MSA_I5_DF(b, kMSALanesByte);
4496 MSA_I5_DF(h, kMSALanesHalf);
4499 MSA_I5_DF(w, kMSALanesWord);
4502 MSA_I5_DF(d, kMSALanesDword);
4510 void Simulator::DecodeTypeMsaI10() {
4511 DCHECK(IsMipsArchVariant(kMips32r6));
4512 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4513 uint32_t opcode = instr_.InstructionBits() & kMsaI5Mask;
4514 int64_t s10 = (
static_cast<int64_t>(instr_.MsaImm10Value()) << 54) >> 54;
4517 #define MSA_I10_DF(elem, num_of_lanes, T) \ 4518 for (int i = 0; i < num_of_lanes; ++i) { \ 4519 wd.elem[i] = static_cast<T>(s10); \ 4521 set_msa_register(instr_.WdValue(), wd.elem); \ 4522 TraceMSARegWr(wd.elem) 4524 if (opcode == LDI) {
4525 switch (DecodeMsaDataFormat()) {
4527 MSA_I10_DF(b, kMSALanesByte, int8_t);
4530 MSA_I10_DF(h, kMSALanesHalf, int16_t);
4533 MSA_I10_DF(w, kMSALanesWord, int32_t);
4536 MSA_I10_DF(d, kMSALanesDword,
int64_t);
4547 void Simulator::DecodeTypeMsaELM() {
4548 DCHECK(IsMipsArchVariant(kMips32r6));
4549 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4550 uint32_t opcode = instr_.InstructionBits() & kMsaLongerELMMask;
4551 int32_t n = instr_.MsaElmNValue();
4555 DCHECK_EQ(sa(), kMSACSRRegister);
4556 MSACSR_ = bit_cast<
uint32_t>(registers_[rd_reg()]);
4557 TraceRegWr(static_cast<int32_t>(MSACSR_));
4560 DCHECK_EQ(rd_reg(), kMSACSRRegister);
4561 SetResult(sa(), bit_cast<int32_t>(MSACSR_));
4565 get_msa_register(ws_reg(), &ws);
4566 set_msa_register(wd_reg(), &ws);
4570 opcode &= kMsaELMMask;
4575 switch (DecodeMsaDataFormat()) {
4577 DCHECK_LT(n, kMSALanesByte);
4578 get_msa_register(instr_.WsValue(), ws.b);
4579 alu_out =
static_cast<int32_t
>(ws.b[n]);
4581 (opcode == COPY_U) ? alu_out & 0xFFu : alu_out);
4585 DCHECK_LT(n, kMSALanesHalf);
4586 get_msa_register(instr_.WsValue(), ws.h);
4587 alu_out =
static_cast<int32_t
>(ws.h[n]);
4589 (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out);
4593 DCHECK_LT(n, kMSALanesWord);
4594 get_msa_register(instr_.WsValue(), ws.w);
4595 alu_out =
static_cast<int32_t
>(ws.w[n]);
4596 SetResult(wd_reg(), alu_out);
4605 switch (DecodeMsaDataFormat()) {
4607 DCHECK_LT(n, kMSALanesByte);
4608 int32_t rs = get_register(instr_.WsValue());
4609 get_msa_register(instr_.WdValue(), wd.b);
4610 wd.b[n] = rs & 0xFFu;
4611 set_msa_register(instr_.WdValue(), wd.b);
4612 TraceMSARegWr(wd.b);
4616 DCHECK_LT(n, kMSALanesHalf);
4617 int32_t rs = get_register(instr_.WsValue());
4618 get_msa_register(instr_.WdValue(), wd.h);
4619 wd.h[n] = rs & 0xFFFFu;
4620 set_msa_register(instr_.WdValue(), wd.h);
4621 TraceMSARegWr(wd.h);
4625 DCHECK_LT(n, kMSALanesWord);
4626 int32_t rs = get_register(instr_.WsValue());
4627 get_msa_register(instr_.WdValue(), wd.w);
4629 set_msa_register(instr_.WdValue(), wd.w);
4630 TraceMSARegWr(wd.w);
4641 get_msa_register(ws_reg(), &ws);
4642 get_msa_register(wd_reg(), &wd);
4643 #define SLDI_DF(s, k) \ 4644 for (unsigned i = 0; i < s; i++) { \ 4645 v[i] = ws.b[s * k + i]; \ 4646 v[i + s] = wd.b[s * k + i]; \ 4648 for (unsigned i = 0; i < s; i++) { \ 4649 wd.b[s * k + i] = v[i + n]; \ 4651 switch (DecodeMsaDataFormat()) {
4653 DCHECK(n < kMSALanesByte);
4654 SLDI_DF(kMSARegSize /
sizeof(int8_t) / kBitsPerByte, 0)
4657 DCHECK(n < kMSALanesHalf);
4658 for (
int k = 0; k < 2; ++k) {
4659 SLDI_DF(kMSARegSize /
sizeof(int16_t) / kBitsPerByte, k)
4663 DCHECK(n < kMSALanesWord);
4664 for (
int k = 0; k < 4; ++k) {
4665 SLDI_DF(kMSARegSize /
sizeof(int32_t) / kBitsPerByte, k)
4669 DCHECK(n < kMSALanesDword);
4670 for (
int k = 0; k < 8; ++k) {
4671 SLDI_DF(kMSARegSize /
sizeof(
int64_t) / kBitsPerByte, k)
4677 set_msa_register(wd_reg(), &wd);
4692 template <
typename T>
4693 T Simulator::MsaBitInstrHelper(
uint32_t opcode, T wd, T ws, int32_t m) {
4694 typedef typename std::make_unsigned<T>::type uT;
4698 res =
static_cast<T
>(ws << m);
4701 res =
static_cast<T
>(ArithmeticShiftRight(ws, m));
4704 res =
static_cast<T
>(
static_cast<uT
>(ws) >> m);
4707 res =
static_cast<T
>(
static_cast<T
>(~(1ull << m)) & ws);
4710 res =
static_cast<T
>(
static_cast<T
>(1ull << m) | ws);
4713 res =
static_cast<T
>(
static_cast<T
>(1ull << m) ^ ws);
4716 int elem_size = 8 *
sizeof(T);
4718 if (bits == elem_size) {
4719 res =
static_cast<T
>(ws);
4721 uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
4722 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
4723 (
static_cast<T
>(~mask) & wd));
4727 int elem_size = 8 *
sizeof(T);
4729 if (bits == elem_size) {
4730 res =
static_cast<T
>(ws);
4732 uint64_t mask = (1ull << bits) - 1;
4733 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
4734 (
static_cast<T
>(~mask) & wd));
4738 #define M_MAX_INT(x) static_cast<int64_t>((1LL << ((x)-1)) - 1) 4739 #define M_MIN_INT(x) static_cast<int64_t>(-(1LL << ((x)-1))) 4740 int shift = 64 - 8 *
sizeof(T);
4742 res =
static_cast<T
>(ws_i64 < M_MIN_INT(m + 1)
4744 : ws_i64 > M_MAX_INT(m + 1) ? M_MAX_INT(m + 1)
4750 #define M_MAX_UINT(x) static_cast<uint64_t>(-1ULL >> (64 - (x))) 4751 uint64_t mask =
static_cast<uint64_t
>(-1ULL >> (64 - 8 *
sizeof(T)));
4752 uint64_t ws_u64 =
static_cast<uint64_t
>(ws) & mask;
4753 res =
static_cast<T
>(ws_u64 < M_MAX_UINT(m + 1) ? ws_u64
4754 : M_MAX_UINT(m + 1));
4759 res =
static_cast<T
>(ws);
4761 res =
static_cast<T
>(ArithmeticShiftRight(ws, m)) +
4762 static_cast<T>((ws >> (m - 1)) & 0x1);
4767 res =
static_cast<T
>(ws);
4769 res =
static_cast<T
>(
static_cast<uT
>(ws) >> m) +
4770 static_cast<T
>((ws >> (m - 1)) & 0x1);
4779 void Simulator::DecodeTypeMsaBIT() {
4780 DCHECK(IsMipsArchVariant(kMips32r6));
4781 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4782 uint32_t opcode = instr_.InstructionBits() & kMsaBITMask;
4783 int32_t m = instr_.MsaBitMValue();
4786 #define MSA_BIT_DF(elem, num_of_lanes) \ 4787 get_msa_register(instr_.WsValue(), ws.elem); \ 4788 if (opcode == BINSLI || opcode == BINSRI) { \ 4789 get_msa_register(instr_.WdValue(), wd.elem); \ 4791 for (int i = 0; i < num_of_lanes; i++) { \ 4792 wd.elem[i] = MsaBitInstrHelper(opcode, wd.elem[i], ws.elem[i], m); \ 4794 set_msa_register(instr_.WdValue(), wd.elem); \ 4795 TraceMSARegWr(wd.elem) 4797 switch (DecodeMsaDataFormat()) {
4799 DCHECK(m < kMSARegSize / kMSALanesByte);
4800 MSA_BIT_DF(b, kMSALanesByte);
4803 DCHECK(m < kMSARegSize / kMSALanesHalf);
4804 MSA_BIT_DF(h, kMSALanesHalf);
4807 DCHECK(m < kMSARegSize / kMSALanesWord);
4808 MSA_BIT_DF(w, kMSALanesWord);
4811 DCHECK(m < kMSARegSize / kMSALanesDword);
4812 MSA_BIT_DF(d, kMSALanesDword);
4820 void Simulator::DecodeTypeMsaMI10() {
4821 DCHECK(IsMipsArchVariant(kMips32r6));
4822 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
4823 uint32_t opcode = instr_.InstructionBits() & kMsaMI10Mask;
4824 int32_t s10 = (
static_cast<int32_t
>(instr_.MsaImmMI10Value()) << 22) >> 22;
4825 int32_t rs = get_register(instr_.WsValue());
4829 #define MSA_MI10_LOAD(elem, num_of_lanes, T) \ 4830 for (int i = 0; i < num_of_lanes; ++i) { \ 4831 addr = rs + (s10 + i) * sizeof(T); \ 4832 wd.elem[i] = ReadMem<T>(addr, instr_.instr()); \ 4834 set_msa_register(instr_.WdValue(), wd.elem); 4836 #define MSA_MI10_STORE(elem, num_of_lanes, T) \ 4837 get_msa_register(instr_.WdValue(), wd.elem); \ 4838 for (int i = 0; i < num_of_lanes; ++i) { \ 4839 addr = rs + (s10 + i) * sizeof(T); \ 4840 WriteMem<T>(addr, wd.elem[i], instr_.instr()); \ 4843 if (opcode == MSA_LD) {
4844 switch (DecodeMsaDataFormat()) {
4846 MSA_MI10_LOAD(b, kMSALanesByte, int8_t);
4849 MSA_MI10_LOAD(h, kMSALanesHalf, int16_t);
4852 MSA_MI10_LOAD(w, kMSALanesWord, int32_t);
4855 MSA_MI10_LOAD(d, kMSALanesDword,
int64_t);
4860 }
else if (opcode == MSA_ST) {
4861 switch (DecodeMsaDataFormat()) {
4863 MSA_MI10_STORE(b, kMSALanesByte, int8_t);
4866 MSA_MI10_STORE(h, kMSALanesHalf, int16_t);
4869 MSA_MI10_STORE(w, kMSALanesWord, int32_t);
4872 MSA_MI10_STORE(d, kMSALanesDword,
int64_t);
4881 #undef MSA_MI10_LOAD 4882 #undef MSA_MI10_STORE 4885 template <
typename T>
4886 T Simulator::Msa3RInstrHelper(
uint32_t opcode, T wd, T ws, T wt) {
4887 typedef typename std::make_unsigned<T>::type uT;
4889 T wt_modulo = wt % (
sizeof(T) * 8);
4892 res =
static_cast<T
>(ws << wt_modulo);
4895 res =
static_cast<T
>(ArithmeticShiftRight(ws, wt_modulo));
4898 res =
static_cast<T
>(
static_cast<uT
>(ws) >> wt_modulo);
4901 res =
static_cast<T
>(
static_cast<T
>(~(1ull << wt_modulo)) & ws);
4904 res =
static_cast<T
>(
static_cast<T
>(1ull << wt_modulo) | ws);
4907 res =
static_cast<T
>(
static_cast<T
>(1ull << wt_modulo) ^ ws);
4910 int elem_size = 8 *
sizeof(T);
4911 int bits = wt_modulo + 1;
4912 if (bits == elem_size) {
4913 res =
static_cast<T
>(ws);
4915 uint64_t mask = ((1ull << bits) - 1) << (elem_size - bits);
4916 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
4917 (
static_cast<T
>(~mask) & wd));
4921 int elem_size = 8 *
sizeof(T);
4922 int bits = wt_modulo + 1;
4923 if (bits == elem_size) {
4924 res =
static_cast<T
>(ws);
4926 uint64_t mask = (1ull << bits) - 1;
4927 res =
static_cast<T
>((
static_cast<T
>(mask) & ws) |
4928 (
static_cast<T
>(~mask) & wd));
4941 res =
static_cast<T
>(Max(static_cast<uT>(ws), static_cast<uT>(wt)));
4947 res =
static_cast<T
>(Min(static_cast<uT>(ws), static_cast<uT>(wt)));
4952 res = Nabs(ws) < Nabs(wt) ? ws : wt;
4957 res = Nabs(ws) > Nabs(wt) ? ws : wt;
4960 res =
static_cast<T
>(!Compare(ws, wt) ? -1ull : 0ull);
4963 res =
static_cast<T
>((Compare(ws, wt) == -1) ? -1ull : 0ull);
4966 res =
static_cast<T
>(
4967 (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) == -1) ? -1ull
4971 res =
static_cast<T
>((Compare(ws, wt) != 1) ? -1ull : 0ull);
4974 res =
static_cast<T
>(
4975 (Compare(static_cast<uT>(ws), static_cast<uT>(wt)) != 1) ? -1ull
4979 res =
static_cast<T
>(Abs(ws) + Abs(wt));
4982 T ws_nabs = Nabs(ws);
4983 T wt_nabs = Nabs(wt);
4984 if (ws_nabs < -std::numeric_limits<T>::max() - wt_nabs) {
4985 res = std::numeric_limits<T>::max();
4987 res = -(ws_nabs + wt_nabs);
4991 res = SaturateAdd(ws, wt);
4994 uT ws_u =
static_cast<uT
>(ws);
4995 uT wt_u =
static_cast<uT
>(wt);
4996 res =
static_cast<T
>(SaturateAdd(ws_u, wt_u));
4999 res =
static_cast<T
>((wt & ws) + ((wt ^ ws) >> 1));
5002 uT ws_u =
static_cast<uT
>(ws);
5003 uT wt_u =
static_cast<uT
>(wt);
5004 res =
static_cast<T
>((wt_u & ws_u) + ((wt_u ^ ws_u) >> 1));
5007 res =
static_cast<T
>((wt | ws) - ((wt ^ ws) >> 1));
5010 uT ws_u =
static_cast<uT
>(ws);
5011 uT wt_u =
static_cast<uT
>(wt);
5012 res =
static_cast<T
>((wt_u | ws_u) - ((wt_u ^ ws_u) >> 1));
5015 res = SaturateSub(ws, wt);
5018 uT ws_u =
static_cast<uT
>(ws);
5019 uT wt_u =
static_cast<uT
>(wt);
5020 res =
static_cast<T
>(SaturateSub(ws_u, wt_u));
5023 uT wsu =
static_cast<uT
>(ws);
5025 uT wtu =
static_cast<uT
>(wt);
5029 res =
static_cast<T
>(wsu - wtu);
5032 if (wsu > std::numeric_limits<uT>::max() + wt) {
5033 res =
static_cast<T
>(std::numeric_limits<uT>::max());
5035 res =
static_cast<T
>(wsu - wt);
5040 uT wsu =
static_cast<uT
>(ws);
5041 uT wtu =
static_cast<uT
>(wt);
5045 if (wdu > std::numeric_limits<T>::max()) {
5046 res = std::numeric_limits<T>::max();
5048 res =
static_cast<T
>(wdu);
5052 CHECK(-std::numeric_limits<T>::max() ==
5053 std::numeric_limits<T>::min() + 1);
5054 if (wdu <= std::numeric_limits<T>::max()) {
5055 res = -
static_cast<T
>(wdu);
5057 res = std::numeric_limits<T>::min();
5062 res =
static_cast<T
>(Abs(ws - wt));
5065 uT wsu =
static_cast<uT
>(ws);
5066 uT wtu =
static_cast<uT
>(wt);
5067 res =
static_cast<T
>(wsu > wtu ? wsu - wtu : wtu - wsu);
5079 res = wt != 0 ? ws / wt :
static_cast<T
>(Unpredictable);
5082 res = wt != 0 ?
static_cast<T
>(
static_cast<uT
>(ws) / static_cast<uT>(wt))
5083 : static_cast<T>(Unpredictable);
5086 res = wt != 0 ? ws % wt :
static_cast<T
>(Unpredictable);
5089 res = wt != 0 ?
static_cast<T
>(
static_cast<uT
>(ws) % static_cast<uT>(wt))
5090 : static_cast<T>(Unpredictable);
5103 int bit = wt_modulo == 0 ? 0 : (ws >> (wt_modulo - 1)) & 1;
5104 res =
static_cast<T
>(ArithmeticShiftRight(ws, wt_modulo) + bit);
5107 uT wsu =
static_cast<uT
>(ws);
5108 int bit = wt_modulo == 0 ? 0 : (wsu >> (wt_modulo - 1)) & 1;
5109 res =
static_cast<T
>((wsu >> wt_modulo) + bit);
5117 template <
typename T_
int,
typename T_reg>
5118 void Msa3RInstrHelper_shuffle(
const uint32_t opcode, T_reg ws, T_reg wt,
5119 T_reg wd,
const int i,
const int num_of_lanes) {
5120 T_int *ws_p, *wt_p, *wd_p;
5121 ws_p =
reinterpret_cast<T_int*
>(ws);
5122 wt_p =
reinterpret_cast<T_int*
>(wt);
5123 wd_p =
reinterpret_cast<T_int*
>(wd);
5126 wd_p[
i] = wt_p[2 *
i];
5127 wd_p[
i + num_of_lanes / 2] = ws_p[2 *
i];
5130 wd_p[
i] = wt_p[2 *
i + 1];
5131 wd_p[
i + num_of_lanes / 2] = ws_p[2 *
i + 1];
5134 wd_p[2 *
i] = wt_p[
i + num_of_lanes / 2];
5135 wd_p[2 *
i + 1] = ws_p[
i + num_of_lanes / 2];
5138 wd_p[2 *
i] = wt_p[
i];
5139 wd_p[2 *
i + 1] = ws_p[
i];
5142 wd_p[2 *
i] = wt_p[2 *
i];
5143 wd_p[2 *
i + 1] = ws_p[2 *
i];
5146 wd_p[2 *
i] = wt_p[2 *
i + 1];
5147 wd_p[2 *
i + 1] = ws_p[2 *
i + 1];
5150 const int mask_not_valid = 0xC0;
5151 const int mask_6_bits = 0x3F;
5152 if ((wd_p[
i] & mask_not_valid)) {
5155 int k = (wd_p[
i] & mask_6_bits) % (num_of_lanes * 2);
5156 wd_p[
i] = k >= num_of_lanes ? ws_p[k - num_of_lanes] : wt_p[k];
5164 template <
typename T_
int,
typename T_smaller_
int,
typename T_reg>
5165 void Msa3RInstrHelper_horizontal(
const uint32_t opcode, T_reg ws, T_reg wt,
5166 T_reg wd,
const int i,
5167 const int num_of_lanes) {
5168 typedef typename std::make_unsigned<T_int>::type T_uint;
5169 typedef typename std::make_unsigned<T_smaller_int>::type T_smaller_uint;
5171 T_smaller_int *ws_p, *wt_p;
5172 ws_p =
reinterpret_cast<T_smaller_int*
>(ws);
5173 wt_p =
reinterpret_cast<T_smaller_int*
>(wt);
5174 wd_p =
reinterpret_cast<T_int*
>(wd);
5176 T_smaller_uint *ws_pu, *wt_pu;
5177 ws_pu =
reinterpret_cast<T_smaller_uint*
>(ws);
5178 wt_pu =
reinterpret_cast<T_smaller_uint*
>(wt);
5179 wd_pu =
reinterpret_cast<T_uint*
>(wd);
5183 static_cast<T_int
>(ws_p[2 *
i + 1]) + static_cast<T_int>(wt_p[2 *
i]);
5186 wd_pu[
i] =
static_cast<T_uint
>(ws_pu[2 *
i + 1]) +
5187 static_cast<T_uint>(wt_pu[2 *
i]);
5191 static_cast<T_int
>(ws_p[2 *
i + 1]) - static_cast<T_int>(wt_p[2 *
i]);
5194 wd_pu[
i] =
static_cast<T_uint
>(ws_pu[2 *
i + 1]) -
5195 static_cast<T_uint>(wt_pu[2 *
i]);
5202 void Simulator::DecodeTypeMsa3R() {
5203 DCHECK(IsMipsArchVariant(kMips32r6));
5204 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5205 uint32_t opcode = instr_.InstructionBits() & kMsa3RMask;
5206 msa_reg_t ws, wd, wt;
5207 get_msa_register(ws_reg(), &ws);
5208 get_msa_register(wt_reg(), &wt);
5209 get_msa_register(wd_reg(), &wd);
5215 #define HORIZONTAL_ARITHMETIC_DF(num_of_lanes, int_type, lesser_int_type) \ 5216 for (int i = 0; i < num_of_lanes; ++i) { \ 5217 Msa3RInstrHelper_horizontal<int_type, lesser_int_type>( \ 5218 opcode, &ws, &wt, &wd, i, num_of_lanes); \ 5220 switch (DecodeMsaDataFormat()) {
5222 HORIZONTAL_ARITHMETIC_DF(kMSALanesHalf, int16_t, int8_t);
5225 HORIZONTAL_ARITHMETIC_DF(kMSALanesWord, int32_t, int16_t);
5228 HORIZONTAL_ARITHMETIC_DF(kMSALanesDword,
int64_t, int32_t);
5234 #undef HORIZONTAL_ARITHMETIC_DF 5236 #define VSHF_DF(num_of_lanes, int_type) \ 5237 for (int i = 0; i < num_of_lanes; ++i) { \ 5238 Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \ 5241 switch (DecodeMsaDataFormat()) {
5243 VSHF_DF(kMSALanesByte, int8_t);
5246 VSHF_DF(kMSALanesHalf, int16_t);
5249 VSHF_DF(kMSALanesWord, int32_t);
5252 VSHF_DF(kMSALanesDword,
int64_t);
5265 #define INTERLEAVE_PACK_DF(num_of_lanes, int_type) \ 5266 for (int i = 0; i < num_of_lanes / 2; ++i) { \ 5267 Msa3RInstrHelper_shuffle<int_type>(opcode, &ws, &wt, &wd, i, \ 5270 switch (DecodeMsaDataFormat()) {
5272 INTERLEAVE_PACK_DF(kMSALanesByte, int8_t);
5275 INTERLEAVE_PACK_DF(kMSALanesHalf, int16_t);
5278 INTERLEAVE_PACK_DF(kMSALanesWord, int32_t);
5281 INTERLEAVE_PACK_DF(kMSALanesDword,
int64_t);
5287 #undef INTERLEAVE_PACK_DF 5289 #define MSA_3R_DF(elem, num_of_lanes) \ 5290 for (int i = 0; i < num_of_lanes; i++) { \ 5291 wd.elem[i] = Msa3RInstrHelper(opcode, wd.elem[i], ws.elem[i], wt.elem[i]); \ 5294 switch (DecodeMsaDataFormat()) {
5296 MSA_3R_DF(b, kMSALanesByte);
5299 MSA_3R_DF(h, kMSALanesHalf);
5302 MSA_3R_DF(w, kMSALanesWord);
5305 MSA_3R_DF(d, kMSALanesDword);
5313 set_msa_register(wd_reg(), &wd);
5317 template <
typename T_
int,
typename T_fp,
typename T_reg>
5318 void Msa3RFInstrHelper(
uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
5319 const T_int all_ones =
static_cast<T_int
>(-1);
5320 const T_fp s_element = *
reinterpret_cast<T_fp*
>(&ws);
5321 const T_fp t_element = *
reinterpret_cast<T_fp*
>(&wt);
5324 if (std::isnan(s_element) || std::isnan(t_element)) {
5331 if (s_element != t_element || std::isnan(s_element) ||
5332 std::isnan(t_element)) {
5339 if (s_element == t_element || std::isnan(s_element) ||
5340 std::isnan(t_element)) {
5347 if (s_element >= t_element || std::isnan(s_element) ||
5348 std::isnan(t_element)) {
5355 if (s_element < t_element || std::isnan(s_element) ||
5356 std::isnan(t_element)) {
5363 if (s_element > t_element || std::isnan(s_element) ||
5364 std::isnan(t_element)) {
5371 if (s_element <= t_element || std::isnan(s_element) ||
5372 std::isnan(t_element)) {
5379 if (std::isnan(s_element) || std::isnan(t_element)) {
5386 if (s_element != t_element || std::isnan(s_element) ||
5387 std::isnan(t_element)) {
5394 if (s_element == t_element || std::isnan(s_element) ||
5395 std::isnan(t_element)) {
5402 wd = bit_cast<T_int>(s_element + t_element);
5405 wd = bit_cast<T_int>(s_element - t_element);
5408 wd = bit_cast<T_int>(s_element * t_element);
5411 if (t_element == 0) {
5412 wd = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
5414 wd = bit_cast<T_int>(s_element / t_element);
5418 wd = bit_cast<T_int>(
5419 std::fma(s_element, t_element, *reinterpret_cast<T_fp*>(&wd)));
5422 wd = bit_cast<T_int>(
5423 std::fma(s_element, -t_element, *reinterpret_cast<T_fp*>(&wd)));
5426 wd = bit_cast<T_int>(std::ldexp(s_element, static_cast<int>(wt)));
5429 wd = bit_cast<T_int>(std::min(s_element, t_element));
5432 wd = bit_cast<T_int>(std::max(s_element, t_element));
5435 wd = bit_cast<T_int>(
5436 std::fabs(s_element) < std::fabs(t_element) ? s_element : t_element);
5439 wd = bit_cast<T_int>(
5440 std::fabs(s_element) > std::fabs(t_element) ? s_element : t_element);
5460 template <
typename T_
int,
typename T_
int_dbl,
typename T_reg>
5461 void Msa3RFInstrHelper2(
uint32_t opcode, T_reg ws, T_reg wt, T_reg& wd) {
5463 typedef typename std::make_unsigned<T_int_dbl>::type T_uint_dbl;
5464 const T_int max_int = std::numeric_limits<T_int>::max();
5465 const T_int min_int = std::numeric_limits<T_int>::min();
5466 const int shift = kBitsPerByte *
sizeof(T_int) - 1;
5467 const T_int_dbl reg_s = ws;
5468 const T_int_dbl reg_t = wt;
5469 T_int_dbl product, result;
5470 product = reg_s * reg_t;
5473 const T_int_dbl min_fix_dbl =
5474 bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
5475 const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5476 if (product == min_fix_dbl) {
5477 product = max_fix_dbl;
5479 wd =
static_cast<T_int
>(product >> shift);
5482 result = (product + (
static_cast<T_int_dbl
>(wd) << shift)) >> shift;
5483 wd =
static_cast<T_int
>(
5484 result > max_int ? max_int : result < min_int ? min_int : result);
5487 result = (-product + (
static_cast<T_int_dbl
>(wd) << shift)) >> shift;
5488 wd =
static_cast<T_int
>(
5489 result > max_int ? max_int : result < min_int ? min_int : result);
5492 const T_int_dbl min_fix_dbl =
5493 bit_cast<T_uint_dbl>(std::numeric_limits<T_int_dbl>::min()) >> 1U;
5494 const T_int_dbl max_fix_dbl = std::numeric_limits<T_int_dbl>::max() >> 1U;
5495 if (product == min_fix_dbl) {
5496 wd =
static_cast<T_int
>(max_fix_dbl >> shift);
5499 wd =
static_cast<T_int
>((product + (1 << (shift - 1))) >> shift);
5502 result = (product + (
static_cast<T_int_dbl
>(wd) << shift) +
5503 (1 << (shift - 1))) >>
5505 wd =
static_cast<T_int
>(
5506 result > max_int ? max_int : result < min_int ? min_int : result);
5509 result = (-product + (
static_cast<T_int_dbl
>(wd) << shift) +
5510 (1 << (shift - 1))) >>
5512 wd =
static_cast<T_int
>(
5513 result > max_int ? max_int : result < min_int ? min_int : result);
5520 void Simulator::DecodeTypeMsa3RF() {
5521 DCHECK(IsMipsArchVariant(kMips32r6));
5522 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5523 uint32_t opcode = instr_.InstructionBits() & kMsa3RFMask;
5524 msa_reg_t wd, ws, wt;
5525 if (opcode != FCAF) {
5526 get_msa_register(ws_reg(), &ws);
5527 get_msa_register(wt_reg(), &wt);
5535 #define PACK_FLOAT16(sign, exp, frac) \ 5536 static_cast<uint16_t>(((sign) << 15) + ((exp) << 10) + (frac)) 5537 #define FEXDO_DF(source, dst) \ 5540 aSign = element >> 31; \ 5541 aExp = element >> 23 & 0xFF; \ 5542 aFrac = element & 0x007FFFFF; \ 5543 if (aExp == 0xFF) { \ 5550 dst = PACK_FLOAT16(aSign, 0x1F, 0); \ 5552 } else if (aExp == 0 && aFrac == 0) { \ 5553 dst = PACK_FLOAT16(aSign, 0, 0); \ 5558 uint32_t increment; \ 5559 bool rounding_bumps_exp; \ 5560 aFrac |= 0x00800000; \ 5564 mask = 0x00FFFFFF; \ 5565 if (aExp >= -11) { \ 5566 mask >>= 11 + aExp; \ 5570 mask = 0x00001FFF; \ 5572 switch (MSACSR_ & 3) { \ 5573 case kRoundToNearest: \ 5574 increment = (mask + 1) >> 1; \ 5575 if ((aFrac & mask) == increment) { \ 5576 increment = aFrac & (increment << 1); \ 5579 case kRoundToPlusInf: \ 5580 increment = aSign ? 0 : mask; \ 5582 case kRoundToMinusInf: \ 5583 increment = aSign ? mask : 0; \ 5585 case kRoundToZero: \ 5589 rounding_bumps_exp = (aFrac + increment >= 0x01000000); \ 5590 if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) { \ 5591 dst = PACK_FLOAT16(aSign, 0x1F, 0); \ 5594 aFrac += increment; \ 5595 if (rounding_bumps_exp) { \ 5600 dst = PACK_FLOAT16(aSign, 0, 0); \ 5607 dst = PACK_FLOAT16(aSign, aExp, aFrac >> 13); \ 5610 switch (DecodeMsaDataFormat()) {
5612 for (
int i = 0;
i < kMSALanesWord;
i++) {
5613 uint_fast32_t element;
5614 uint_fast32_t aSign, aFrac;
5616 FEXDO_DF(ws.uw[
i], wd.uh[
i + kMSALanesHalf / 2])
5617 FEXDO_DF(wt.uw[
i], wd.uh[
i])
5621 for (
int i = 0;
i < kMSALanesDword;
i++) {
5622 wd.w[
i + kMSALanesWord / 2] = bit_cast<int32_t>(
5623 static_cast<float>(bit_cast<
double>(ws.d[
i])));
5624 wd.w[
i] = bit_cast<int32_t>(
5625 static_cast<float>(bit_cast<
double>(wt.d[
i])));
5635 #define FTQ_DF(source, dst, fp_type, int_type) \ 5636 element = bit_cast<fp_type>(source) * \ 5637 (1U << (sizeof(int_type) * kBitsPerByte - 1)); \ 5638 if (element > std::numeric_limits<int_type>::max()) { \ 5639 dst = std::numeric_limits<int_type>::max(); \ 5640 } else if (element < std::numeric_limits<int_type>::min()) { \ 5641 dst = std::numeric_limits<int_type>::min(); \ 5642 } else if (std::isnan(element)) { \ 5645 int_type fixed_point; \ 5646 round_according_to_msacsr(element, element, fixed_point); \ 5647 dst = fixed_point; \ 5650 switch (DecodeMsaDataFormat()) {
5652 for (
int i = 0;
i < kMSALanesWord;
i++) {
5654 FTQ_DF(ws.w[
i], wd.h[
i + kMSALanesHalf / 2],
float, int16_t)
5655 FTQ_DF(wt.w[
i], wd.h[
i],
float, int16_t)
5660 for (
int i = 0;
i < kMSALanesDword;
i++) {
5661 FTQ_DF(ws.d[
i], wd.w[
i + kMSALanesWord / 2],
double, int32_t)
5662 FTQ_DF(wt.d[
i], wd.w[
i],
double, int32_t)
5670 #define MSA_3RF_DF(T1, T2, Lanes, ws, wt, wd) \ 5671 for (int i = 0; i < Lanes; i++) { \ 5672 Msa3RFInstrHelper<T1, T2>(opcode, ws, wt, wd); \ 5674 #define MSA_3RF_DF2(T1, T2, Lanes, ws, wt, wd) \ 5675 for (int i = 0; i < Lanes; i++) { \ 5676 Msa3RFInstrHelper2<T1, T2>(opcode, ws, wt, wd); \ 5682 get_msa_register(wd_reg(), &wd);
5686 switch (DecodeMsaDataFormat()) {
5688 MSA_3RF_DF2(int16_t, int32_t, kMSALanesHalf, ws.h[
i], wt.h[
i],
5692 MSA_3RF_DF2(int32_t,
int64_t, kMSALanesWord, ws.w[
i], wt.w[
i],
5700 if (opcode == FMADD || opcode == FMSUB) {
5701 get_msa_register(wd_reg(), &wd);
5703 switch (DecodeMsaDataFormat()) {
5705 MSA_3RF_DF(int32_t,
float, kMSALanesWord, ws.w[
i], wt.w[
i], wd.w[
i])
5708 MSA_3RF_DF(
int64_t,
double, kMSALanesDword, ws.d[
i], wt.d[
i], wd.d[
i])
5717 set_msa_register(wd_reg(), &wd);
5721 void Simulator::DecodeTypeMsaVec() {
5722 DCHECK(IsMipsArchVariant(kMips32r6));
5723 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5724 uint32_t opcode = instr_.InstructionBits() & kMsaVECMask;
5725 msa_reg_t wd, ws, wt;
5727 get_msa_register(instr_.WsValue(), ws.w);
5728 get_msa_register(instr_.WtValue(), wt.w);
5729 if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
5730 get_msa_register(instr_.WdValue(), wd.w);
5733 for (
int i = 0;
i < kMSALanesWord;
i++) {
5736 wd.w[
i] = ws.w[
i] & wt.w[
i];
5739 wd.w[
i] = ws.w[
i] | wt.w[
i];
5742 wd.w[
i] = ~(ws.w[
i] | wt.w[
i]);
5745 wd.w[
i] = ws.w[
i] ^ wt.w[
i];
5748 wd.w[
i] = (wt.w[
i] & ws.w[
i]) | (~wt.w[
i] & wd.w[
i]);
5751 wd.w[
i] = (~wt.w[
i] & ws.w[
i]) | (wt.w[
i] & wd.w[
i]);
5754 wd.w[
i] = (~wd.w[
i] & ws.w[
i]) | (wd.w[
i] & wt.w[
i]);
5760 set_msa_register(instr_.WdValue(), wd.w);
5761 TraceMSARegWr(wd.d);
5764 void Simulator::DecodeTypeMsa2R() {
5765 DCHECK(IsMipsArchVariant(kMips32r6));
5766 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
5767 uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
5771 switch (DecodeMsaDataFormat()) {
5773 int32_t rs = get_register(instr_.WsValue());
5774 for (
int i = 0;
i < kMSALanesByte;
i++) {
5775 wd.b[
i] = rs & 0xFFu;
5777 set_msa_register(instr_.WdValue(), wd.b);
5778 TraceMSARegWr(wd.b);
5782 int32_t rs = get_register(instr_.WsValue());
5783 for (
int i = 0;
i < kMSALanesHalf;
i++) {
5784 wd.h[
i] = rs & 0xFFFFu;
5786 set_msa_register(instr_.WdValue(), wd.h);
5787 TraceMSARegWr(wd.h);
5791 int32_t rs = get_register(instr_.WsValue());
5792 for (
int i = 0;
i < kMSALanesWord;
i++) {
5795 set_msa_register(instr_.WdValue(), wd.w);
5796 TraceMSARegWr(wd.w);
5804 #define PCNT_DF(elem, num_of_lanes) \ 5805 get_msa_register(instr_.WsValue(), ws.elem); \ 5806 for (int i = 0; i < num_of_lanes; i++) { \ 5807 uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \ 5808 wd.elem[i] = base::bits::CountPopulation(u64elem); \ 5810 set_msa_register(instr_.WdValue(), wd.elem); \ 5811 TraceMSARegWr(wd.elem) 5813 switch (DecodeMsaDataFormat()) {
5815 PCNT_DF(ub, kMSALanesByte);
5818 PCNT_DF(uh, kMSALanesHalf);
5821 PCNT_DF(uw, kMSALanesWord);
5824 PCNT_DF(ud, kMSALanesDword);
5832 #define NLOC_DF(elem, num_of_lanes) \ 5833 get_msa_register(instr_.WsValue(), ws.elem); \ 5834 for (int i = 0; i < num_of_lanes; i++) { \ 5835 const uint64_t mask = (num_of_lanes == kMSALanesDword) \ 5837 : (1ULL << (kMSARegSize / num_of_lanes)) - 1; \ 5838 uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask; \ 5839 wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \ 5840 (64 - kMSARegSize / num_of_lanes); \ 5842 set_msa_register(instr_.WdValue(), wd.elem); \ 5843 TraceMSARegWr(wd.elem) 5845 switch (DecodeMsaDataFormat()) {
5847 NLOC_DF(ub, kMSALanesByte);
5850 NLOC_DF(uh, kMSALanesHalf);
5853 NLOC_DF(uw, kMSALanesWord);
5856 NLOC_DF(ud, kMSALanesDword);
5864 #define NLZC_DF(elem, num_of_lanes) \ 5865 get_msa_register(instr_.WsValue(), ws.elem); \ 5866 for (int i = 0; i < num_of_lanes; i++) { \ 5867 uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \ 5868 wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \ 5869 (64 - kMSARegSize / num_of_lanes); \ 5871 set_msa_register(instr_.WdValue(), wd.elem); \ 5872 TraceMSARegWr(wd.elem) 5874 switch (DecodeMsaDataFormat()) {
5876 NLZC_DF(ub, kMSALanesByte);
5879 NLZC_DF(uh, kMSALanesHalf);
5882 NLZC_DF(uw, kMSALanesWord);
5885 NLZC_DF(ud, kMSALanesDword);
5897 #define BIT(n) (0x1LL << n) 5898 #define QUIET_BIT_S(nan) (bit_cast<int32_t>(nan) & BIT(22)) 5899 #define QUIET_BIT_D(nan) (bit_cast<int64_t>(nan) & BIT(51)) 5900 static inline bool isSnan(
float fp) {
return !QUIET_BIT_S(fp); }
5901 static inline bool isSnan(
double fp) {
return !QUIET_BIT_D(fp); }
5905 template <
typename T_
int,
typename T_fp,
typename T_src,
typename T_dst>
5906 T_int Msa2RFInstrHelper(
uint32_t opcode, T_src src, T_dst& dst,
5908 typedef typename std::make_unsigned<T_int>::type T_uint;
5911 #define SNAN_BIT BIT(0) 5912 #define QNAN_BIT BIT(1) 5913 #define NEG_INFINITY_BIT BIT(2) 5914 #define NEG_NORMAL_BIT BIT(3) 5915 #define NEG_SUBNORMAL_BIT BIT(4) 5916 #define NEG_ZERO_BIT BIT(5) 5917 #define POS_INFINITY_BIT BIT(6) 5918 #define POS_NORMAL_BIT BIT(7) 5919 #define POS_SUBNORMAL_BIT BIT(8) 5920 #define POS_ZERO_BIT BIT(9) 5921 T_fp element = *
reinterpret_cast<T_fp*
>(&src);
5922 switch (std::fpclassify(element)) {
5924 if (std::signbit(element)) {
5925 dst = NEG_INFINITY_BIT;
5927 dst = POS_INFINITY_BIT;
5931 if (isSnan(element)) {
5938 if (std::signbit(element)) {
5939 dst = NEG_NORMAL_BIT;
5941 dst = POS_NORMAL_BIT;
5945 if (std::signbit(element)) {
5946 dst = NEG_SUBNORMAL_BIT;
5948 dst = POS_SUBNORMAL_BIT;
5952 if (std::signbit(element)) {
5966 #undef NEG_INFINITY_BIT 5967 #undef NEG_NORMAL_BIT 5968 #undef NEG_SUBNORMAL_BIT 5970 #undef POS_INFINITY_BIT 5971 #undef POS_NORMAL_BIT 5972 #undef POS_SUBNORMAL_BIT 5975 T_fp element = bit_cast<T_fp>(src);
5976 const T_int max_int = std::numeric_limits<T_int>::max();
5977 const T_int min_int = std::numeric_limits<T_int>::min();
5978 if (std::isnan(element)) {
5980 }
else if (element >= max_int || element <= min_int) {
5981 dst = element >= max_int ? max_int : min_int;
5983 dst =
static_cast<T_int
>(std::trunc(element));
5988 T_fp element = bit_cast<T_fp>(src);
5989 const T_uint max_int = std::numeric_limits<T_uint>::max();
5990 if (std::isnan(element)) {
5992 }
else if (element >= max_int || element <= 0) {
5993 dst = element >= max_int ? max_int : 0;
5995 dst =
static_cast<T_uint
>(std::trunc(element));
6000 T_fp element = bit_cast<T_fp>(src);
6001 if (element < 0 || std::isnan(element)) {
6002 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6004 dst = bit_cast<T_int>(std::sqrt(element));
6009 T_fp element = bit_cast<T_fp>(src);
6010 if (element < 0 || std::isnan(element)) {
6011 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6013 dst = bit_cast<T_int>(1 / std::sqrt(element));
6018 T_fp element = bit_cast<T_fp>(src);
6019 if (std::isnan(element)) {
6020 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6022 dst = bit_cast<T_int>(1 / element);
6027 T_fp element = bit_cast<T_fp>(src);
6028 if (std::isnan(element)) {
6029 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6032 sim->round_according_to_msacsr<T_fp, T_int>(element, element, dummy);
6033 dst = bit_cast<T_int>(element);
6038 T_fp element = bit_cast<T_fp>(src);
6039 switch (std::fpclassify(element)) {
6042 dst = bit_cast<T_int>(std::logb(element));
6045 dst = bit_cast<T_int>(-std::numeric_limits<T_fp>::infinity());
6048 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6052 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::quiet_NaN());
6054 dst = bit_cast<T_int>(std::numeric_limits<T_fp>::infinity());
6063 T_fp element = bit_cast<T_fp>(src);
6064 const T_int max_int = std::numeric_limits<T_int>::max();
6065 const T_int min_int = std::numeric_limits<T_int>::min();
6066 if (std::isnan(element)) {
6068 }
else if (element < min_int || element > max_int) {
6069 dst = element > max_int ? max_int : min_int;
6071 sim->round_according_to_msacsr<T_fp, T_int>(element, element, dst);
6076 T_fp element = bit_cast<T_fp>(src);
6077 const T_uint max_uint = std::numeric_limits<T_uint>::max();
6078 if (std::isnan(element)) {
6080 }
else if (element < 0 || element > max_uint) {
6081 dst = element > max_uint ? max_uint : 0;
6084 sim->round_according_to_msacsr<T_fp, T_uint>(element, element, res);
6085 dst = *
reinterpret_cast<T_int*
>(&res);
6090 dst = bit_cast<T_int>(
static_cast<T_fp
>(src));
6093 typedef typename std::make_unsigned<T_src>::type uT_src;
6094 dst = bit_cast<T_int>(
static_cast<T_fp
>(bit_cast<uT_src>(src)));
6102 template <
typename T_
int,
typename T_fp,
typename T_reg>
6103 T_int Msa2RFInstrHelper2(
uint32_t opcode, T_reg ws,
int i) {
6105 #define EXTRACT_FLOAT16_SIGN(fp16) (fp16 >> 15) 6106 #define EXTRACT_FLOAT16_EXP(fp16) (fp16 >> 10 & 0x1F) 6107 #define EXTRACT_FLOAT16_FRAC(fp16) (fp16 & 0x3FF) 6108 #define PACK_FLOAT32(sign, exp, frac) \ 6109 static_cast<uint32_t>(((sign) << 31) + ((exp) << 23) + (frac)) 6110 #define FEXUP_DF(src_index) \ 6111 uint_fast16_t element = ws.uh[src_index]; \ 6112 uint_fast32_t aSign, aFrac; \ 6113 int_fast32_t aExp; \ 6114 aSign = EXTRACT_FLOAT16_SIGN(element); \ 6115 aExp = EXTRACT_FLOAT16_EXP(element); \ 6116 aFrac = EXTRACT_FLOAT16_FRAC(element); \ 6117 if (V8_LIKELY(aExp && aExp != 0x1F)) { \ 6118 return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \ 6119 } else if (aExp == 0x1F) { \ 6121 return bit_cast<int32_t>(std::numeric_limits<float>::quiet_NaN()); \ 6123 return bit_cast<uint32_t>(std::numeric_limits<float>::infinity()) | \ 6124 static_cast<uint32_t>(aSign) << 31; \ 6128 return PACK_FLOAT32(aSign, 0, 0); \ 6130 int_fast16_t shiftCount = \ 6131 base::bits::CountLeadingZeros32(static_cast<uint32_t>(aFrac)) - 21; \ 6132 aFrac <<= shiftCount; \ 6133 aExp = -shiftCount; \ 6134 return PACK_FLOAT32(aSign, aExp + 0x70, aFrac << 13); \ 6138 if (std::is_same<int32_t, T_int>::value) {
6139 FEXUP_DF(
i + kMSALanesWord)
6142 static_cast<double>(bit_cast<
float>(ws.w[
i + kMSALanesDword])));
6145 if (std::is_same<int32_t, T_int>::value) {
6148 return bit_cast<
int64_t>(
static_cast<double>(bit_cast<
float>(ws.w[
i])));
6151 if (std::is_same<int32_t, T_int>::value) {
6152 return bit_cast<int32_t>(
static_cast<float>(ws.h[
i + kMSALanesWord]) /
6155 return bit_cast<
int64_t>(
static_cast<double>(ws.w[
i + kMSALanesDword]) /
6161 if (std::is_same<int32_t, T_int>::value) {
6162 return bit_cast<int32_t>(
static_cast<float>(ws.h[
i]) / (1U << 15));
6164 return bit_cast<
int64_t>(
static_cast<double>(ws.w[
i]) / (1U << 31));
6171 #undef EXTRACT_FLOAT16_SIGN 6172 #undef EXTRACT_FLOAT16_EXP 6173 #undef EXTRACT_FLOAT16_FRAC 6178 void Simulator::DecodeTypeMsa2RF() {
6179 DCHECK(IsMipsArchVariant(kMips32r6));
6180 DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
6181 uint32_t opcode = instr_.InstructionBits() & kMsa2RFMask;
6183 get_msa_register(ws_reg(), &ws);
6184 if (opcode == FEXUPL || opcode == FEXUPR || opcode == FFQL ||
6186 switch (DecodeMsaDataFormat()) {
6188 for (
int i = 0;
i < kMSALanesWord;
i++) {
6189 wd.w[
i] = Msa2RFInstrHelper2<int32_t, float>(opcode, ws,
i);
6193 for (
int i = 0;
i < kMSALanesDword;
i++) {
6194 wd.d[
i] = Msa2RFInstrHelper2<int64_t, double>(opcode, ws,
i);
6201 switch (DecodeMsaDataFormat()) {
6203 for (
int i = 0;
i < kMSALanesWord;
i++) {
6204 Msa2RFInstrHelper<int32_t, float>(opcode, ws.w[
i], wd.w[
i],
this);
6208 for (
int i = 0;
i < kMSALanesDword;
i++) {
6209 Msa2RFInstrHelper<int64_t, double>(opcode, ws.d[
i], wd.d[
i],
this);
6216 set_msa_register(wd_reg(), &wd);
6220 void Simulator::DecodeTypeRegister() {
6222 switch (instr_.OpcodeFieldRaw()) {
6224 DecodeTypeRegisterCOP1();
6227 DecodeTypeRegisterCOP1X();
6230 DecodeTypeRegisterSPECIAL();
6233 DecodeTypeRegisterSPECIAL2();
6236 DecodeTypeRegisterSPECIAL3();
6239 switch (instr_.MSAMinorOpcodeField()) {
6269 void Simulator::DecodeTypeImmediate() {
6271 Opcode op = instr_.OpcodeFieldRaw();
6272 int32_t rs_reg = instr_.RsValue();
6273 int32_t rs = get_register(instr_.RsValue());
6275 int32_t rt_reg = instr_.RtValue();
6276 int32_t rt = get_register(rt_reg);
6277 int16_t imm16 = instr_.Imm16Value();
6279 int32_t ft_reg = instr_.FtValue();
6282 uint32_t oe_imm16 = 0xFFFF & imm16;
6284 int32_t se_imm16 = imm16;
6287 int32_t next_pc = bad_ra;
6290 bool execute_branch_delay_instruction =
false;
6293 int32_t alu_out = 0;
6299 auto BranchAndLinkHelper =
6300 [
this, &next_pc, &execute_branch_delay_instruction](
bool do_branch) {
6301 execute_branch_delay_instruction =
true;
6302 int32_t current_pc = get_pc();
6303 set_register(31, current_pc + 2 * kInstrSize);
6305 int16_t imm16 = this->instr_.Imm16Value();
6306 next_pc = current_pc + (imm16 << 2) + kInstrSize;
6308 next_pc = current_pc + 2 * kInstrSize;
6312 auto BranchHelper = [
this, &next_pc,
6313 &execute_branch_delay_instruction](
bool do_branch) {
6314 execute_branch_delay_instruction =
true;
6315 int32_t current_pc = get_pc();
6317 int16_t imm16 = this->instr_.Imm16Value();
6318 next_pc = current_pc + (imm16 << 2) + kInstrSize;
6320 next_pc = current_pc + 2 * kInstrSize;
6324 auto BranchHelper_MSA = [
this, &next_pc, imm16,
6325 &execute_branch_delay_instruction](
bool do_branch) {
6326 execute_branch_delay_instruction =
true;
6327 int32_t current_pc = get_pc();
6328 const int32_t bitsIn16Int =
sizeof(int16_t) * kBitsPerByte;
6330 if (FLAG_debug_code) {
6331 int16_t bits = imm16 & 0xFC;
6335 CHECK_EQ(bits ^ 0xFC, 0);
6340 int16_t offset =
static_cast<int16_t
>(imm16 << (bitsIn16Int - 10)) >>
6342 next_pc = current_pc + offset + kInstrSize;
6344 next_pc = current_pc + 2 * kInstrSize;
6348 auto BranchAndLinkCompactHelper = [
this, &next_pc](
bool do_branch,
int bits) {
6349 int32_t current_pc = get_pc();
6350 CheckForbiddenSlot(current_pc);
6352 int32_t imm = this->instr_.ImmValue(bits);
6355 next_pc = current_pc + (imm << 2) + kInstrSize;
6356 set_register(31, current_pc + kInstrSize);
6360 auto BranchCompactHelper = [
this, &next_pc](
bool do_branch,
int bits) {
6361 int32_t current_pc = get_pc();
6362 CheckForbiddenSlot(current_pc);
6364 int32_t imm = this->instr_.ImmValue(bits);
6367 next_pc = get_pc() + (imm << 2) + kInstrSize;
6374 switch (instr_.RsFieldRaw()) {
6378 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
6379 uint32_t cc_value = test_fcsr_bit(fcsr_cc);
6380 bool do_branch = (instr_.FBtrueValue()) ? cc_value : !cc_value;
6381 BranchHelper(do_branch);
6385 BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
6388 BranchHelper(get_fpu_register(ft_reg) & 0x1);
6392 get_msa_register(wt_reg(), &wt);
6393 BranchHelper_MSA(wt.d[0] == 0 && wt.d[1] == 0);
6395 #define BZ_DF(witdh, lanes) \ 6398 get_msa_register(wt_reg(), &wt); \ 6400 for (i = 0; i < lanes; ++i) { \ 6401 if (wt.witdh[i] == 0) { \ 6405 BranchHelper_MSA(i != lanes); \ 6408 BZ_DF(b, kMSALanesByte)
6411 BZ_DF(h, kMSALanesHalf)
6414 BZ_DF(w, kMSALanesWord)
6417 BZ_DF(d, kMSALanesDword)
6422 get_msa_register(wt_reg(), &wt);
6423 BranchHelper_MSA(wt.d[0] != 0 || wt.d[1] != 0);
6425 #define BNZ_DF(witdh, lanes) \ 6428 get_msa_register(wt_reg(), &wt); \ 6430 for (i = 0; i < lanes; ++i) { \ 6431 if (wt.witdh[i] == 0) { \ 6435 BranchHelper_MSA(i == lanes); \ 6438 BNZ_DF(b, kMSALanesByte)
6441 BNZ_DF(h, kMSALanesHalf)
6444 BNZ_DF(w, kMSALanesWord)
6447 BNZ_DF(d, kMSALanesDword)
6456 switch (instr_.RtFieldRaw()) {
6458 BranchHelper(rs < 0);
6461 BranchHelper(rs >= 0);
6464 BranchAndLinkHelper(rs < 0);
6467 BranchAndLinkHelper(rs >= 0);
6477 BranchHelper(rs == rt);
6480 BranchHelper(rs != rt);
6483 if (IsMipsArchVariant(kMips32r6)) {
6486 BranchAndLinkCompactHelper(rt <= 0, 16);
6488 if (rs_reg == rt_reg) {
6489 BranchAndLinkCompactHelper(rt >= 0, 16);
6491 BranchCompactHelper(
6492 static_cast<uint32_t>(rs) >= static_cast<uint32_t>(rt), 16);
6496 BranchHelper(rs <= 0);
6499 BranchHelper(rs <= 0);
6503 if (IsMipsArchVariant(kMips32r6)) {
6506 BranchAndLinkCompactHelper(rt > 0, 16);
6508 if (rt_reg == rs_reg) {
6509 BranchAndLinkCompactHelper(rt < 0, 16);
6511 BranchCompactHelper(
6512 static_cast<uint32_t>(rs) < static_cast<uint32_t>(rt), 16);
6516 BranchHelper(rs > 0);
6519 BranchHelper(rs > 0);
6523 if (IsMipsArchVariant(kMips32r6)) {
6526 BranchCompactHelper(rt <= 0, 16);
6528 if (rs_reg == rt_reg) {
6529 BranchCompactHelper(rt >= 0, 16);
6531 BranchCompactHelper(rs >= rt, 16);
6536 BranchAndLinkHelper(rs <= 0);
6540 if (IsMipsArchVariant(kMips32r6)) {
6543 BranchCompactHelper(rt > 0, 16);
6545 if (rs_reg == rt_reg) {
6546 BranchCompactHelper(rt < 0, 16);
6548 BranchCompactHelper(rs < rt, 16);
6553 BranchAndLinkHelper(rs > 0);
6558 BranchCompactHelper(rs == 0, 21);
6560 next_pc = rt + imm16;
6565 BranchCompactHelper(rs != 0, 21);
6567 set_register(31, get_pc() + kInstrSize);
6568 next_pc = rt + imm16;
6572 BranchCompactHelper(
true, 26);
6575 BranchAndLinkCompactHelper(
true, 26);
6578 if (IsMipsArchVariant(kMips32r6)) {
6579 if (rs_reg >= rt_reg) {
6580 if (HaveSameSign(rs, rt)) {
6582 BranchCompactHelper(rs > Registers::kMaxValue - rt, 16);
6583 }
else if (rs < 0) {
6584 BranchCompactHelper(rs < Registers::kMinValue - rt, 16);
6589 BranchAndLinkCompactHelper(rt == 0, 16);
6591 BranchCompactHelper(rt == rs, 16);
6595 if (HaveSameSign(rs, se_imm16)) {
6597 if (rs <= Registers::kMaxValue - se_imm16) {
6598 SignalException(kIntegerOverflow);
6600 }
else if (rs < 0) {
6601 if (rs >= Registers::kMinValue - se_imm16) {
6602 SignalException(kIntegerUnderflow);
6606 SetResult(rt_reg, rs + se_imm16);
6610 if (IsMipsArchVariant(kMips32r6)) {
6611 if (rs_reg >= rt_reg) {
6612 if (!HaveSameSign(rs, rt) || rs == 0 || rt == 0) {
6613 BranchCompactHelper(
true, 16);
6616 BranchCompactHelper(rs <= Registers::kMaxValue - rt, 16);
6617 }
else if (rs < 0) {
6618 BranchCompactHelper(rs >= Registers::kMinValue - rt, 16);
6623 BranchAndLinkCompactHelper(rt != 0, 16);
6625 BranchCompactHelper(rt != rs, 16);
6632 SetResult(rt_reg, rs + se_imm16);
6635 SetResult(rt_reg, rs < se_imm16 ? 1 : 0);
6638 SetResult(rt_reg, rs_u < static_cast<uint32_t>(se_imm16) ? 1 : 0);
6641 SetResult(rt_reg, rs & oe_imm16);
6644 SetResult(rt_reg, rs | oe_imm16);
6647 SetResult(rt_reg, rs ^ oe_imm16);
6652 DCHECK(IsMipsArchVariant(kMips32r6));
6653 SetResult(rt_reg, rs + (se_imm16 << 16));
6656 SetResult(rt_reg, oe_imm16 << 16);
6661 set_register(rt_reg, ReadB(rs + se_imm16));
6664 set_register(rt_reg, ReadH(rs + se_imm16, instr_.instr()));
6668 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
6669 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
6670 uint32_t mask = (1 << byte_shift * 8) - 1;
6671 addr = rs + se_imm16 - al_offset;
6672 alu_out = ReadW(addr, instr_.instr());
6673 alu_out <<= byte_shift * 8;
6674 alu_out |= rt & mask;
6675 set_register(rt_reg, alu_out);
6679 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
6682 set_register(rt_reg, ReadBU(rs + se_imm16));
6685 set_register(rt_reg, ReadHU(rs + se_imm16, instr_.instr()));
6689 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
6690 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
6691 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
6692 addr = rs + se_imm16 - al_offset;
6693 alu_out = ReadW(addr, instr_.instr());
6694 alu_out =
static_cast<uint32_t> (alu_out) >> al_offset * 8;
6695 alu_out |= rt & mask;
6696 set_register(rt_reg, alu_out);
6700 WriteB(rs + se_imm16, static_cast<int8_t>(rt));
6703 WriteH(rs + se_imm16, static_cast<uint16_t>(rt), instr_.instr());
6706 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
6707 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
6708 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
6709 addr = rs + se_imm16 - al_offset;
6711 uint32_t mem_value = ReadW(addr, instr_.instr()) & mask;
6712 mem_value |=
static_cast<uint32_t>(rt) >> byte_shift * 8;
6713 WriteW(addr, mem_value, instr_.instr());
6717 WriteW(rs + se_imm16, rt, instr_.instr());
6720 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
6721 uint32_t mask = (1 << al_offset * 8) - 1;
6722 addr = rs + se_imm16 - al_offset;
6723 uint32_t mem_value = ReadW(addr, instr_.instr());
6724 mem_value = (rt << al_offset * 8) | (mem_value & mask);
6725 WriteW(addr, mem_value, instr_.instr());
6730 DCHECK(!IsMipsArchVariant(kMips32r6));
6731 set_register(rt_reg, ReadW(rs + se_imm16, instr_.instr()));
6736 DCHECK(!IsMipsArchVariant(kMips32r6));
6737 WriteW(rs + se_imm16, rt, instr_.instr());
6738 set_register(rt_reg, 1);
6742 set_fpu_register_hi_word(ft_reg, 0);
6743 set_fpu_register_word(ft_reg,
6744 ReadW(rs + se_imm16, instr_.instr(), FLOAT));
6746 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg - 1), FLOAT_DOUBLE);
6748 TraceMemRd(rs + se_imm16, get_fpu_register_word(ft_reg), FLOAT);
6752 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr()));
6753 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg), DOUBLE);
6756 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr());
6757 TraceMemWr(rs + se_imm16, get_fpu_register_word(ft_reg));
6760 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr());
6761 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg));
6766 int32_t imm21 = instr_.Imm21Value();
6767 int32_t current_pc = get_pc();
6768 uint8_t rt = (imm21 >> kImm16Bits);
6771 addr = current_pc + (se_imm16 << 16);
6772 alu_out =
static_cast<int64_t>(~0x0FFFF) & addr;
6775 alu_out = current_pc + (se_imm16 << 16);
6778 int32_t imm19 = instr_.Imm19Value();
6780 rt = (imm21 >> kImm19Bits);
6784 imm19 <<= (kOpcodeBits + kRsBits + 2);
6785 imm19 >>= (kOpcodeBits + kRsBits + 2);
6786 addr = current_pc + (imm19 << 2);
6792 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xFFF80000 : 0);
6793 alu_out = current_pc + (se_imm19 << 2);
6802 SetResult(rs_reg, alu_out);
6806 switch (instr_.FunctionFieldRaw()) {
6809 DCHECK(IsMipsArchVariant(kMips32r6));
6810 int32_t base = get_register(instr_.BaseValue());
6811 int32_t offset9 = instr_.Imm9Value();
6812 set_register(rt_reg, ReadW(base + offset9, instr_.instr()));
6817 DCHECK(IsMipsArchVariant(kMips32r6));
6818 int32_t base = get_register(instr_.BaseValue());
6819 int32_t offset9 = instr_.Imm9Value();
6820 int32_t bit6 = instr_.Bit(6);
6821 WriteW(base + offset9, rt, instr_.instr());
6824 set_register(rt_reg, 1);
6834 switch (instr_.MSAMinorOpcodeField()) {
6851 DecodeTypeMsaMI10();
6862 if (execute_branch_delay_instruction) {
6866 Instruction* branch_delay_instr =
6867 reinterpret_cast<Instruction*
>(get_pc() + kInstrSize);
6868 BranchDelayInstructionDecode(branch_delay_instr);
6872 if (next_pc != bad_ra) {
6879 void Simulator::DecodeTypeJump() {
6880 SimInstruction simInstr = instr_;
6882 int32_t current_pc = get_pc();
6884 int32_t pc_high_bits = current_pc & 0xF0000000;
6887 int32_t next_pc = pc_high_bits | (simInstr.Imm26Value() << 2);
6892 Instruction* branch_delay_instr =
6893 reinterpret_cast<Instruction*
>(current_pc + kInstrSize);
6894 BranchDelayInstructionDecode(branch_delay_instr);
6898 if (simInstr.IsLinkingInstruction()) {
6899 set_register(31, current_pc + 2 * kInstrSize);
6902 pc_modified_ =
true;
6907 void Simulator::InstructionDecode(Instruction* instr) {
6908 if (v8::internal::FLAG_check_icache) {
6909 CheckICache(i_cache(), instr);
6911 pc_modified_ =
false;
6913 if (::v8::internal::FLAG_trace_sim) {
6914 SNPrintF(trace_buf_,
"%s",
"");
6917 dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
6921 switch (instr_.InstructionType()) {
6922 case Instruction::kRegisterType:
6923 DecodeTypeRegister();
6925 case Instruction::kImmediateType:
6926 DecodeTypeImmediate();
6928 case Instruction::kJumpType:
6934 if (::v8::internal::FLAG_trace_sim) {
6935 PrintF(
" 0x%08" PRIxPTR
" %-44s %s\n",
6936 reinterpret_cast<intptr_t>(instr), buffer.start(),
6937 trace_buf_.start());
6939 if (!pc_modified_) {
6940 set_register(pc, reinterpret_cast<int32_t>(instr) + kInstrSize);
6944 void Simulator::Execute() {
6947 int program_counter = get_pc();
6948 if (::v8::internal::FLAG_stop_sim_at == 0) {
6951 while (program_counter != end_sim_pc) {
6952 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
6954 InstructionDecode(instr);
6955 program_counter = get_pc();
6960 while (program_counter != end_sim_pc) {
6961 Instruction* instr =
reinterpret_cast<Instruction*
>(program_counter);
6963 if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) {
6964 MipsDebugger dbg(
this);
6967 InstructionDecode(instr);
6969 program_counter = get_pc();
6974 void Simulator::CallInternal(Address entry) {
6976 isolate_->stack_guard()->AdjustStackLimitForSimulator();
6979 set_register(pc, static_cast<int32_t>(entry));
6983 set_register(ra, end_sim_pc);
6988 int32_t s0_val = get_register(s0);
6989 int32_t s1_val = get_register(s1);
6990 int32_t s2_val = get_register(s2);
6991 int32_t s3_val = get_register(s3);
6992 int32_t s4_val = get_register(s4);
6993 int32_t s5_val = get_register(s5);
6994 int32_t s6_val = get_register(s6);
6995 int32_t s7_val = get_register(s7);
6996 int32_t gp_val = get_register(gp);
6997 int32_t sp_val = get_register(sp);
6998 int32_t fp_val = get_register(fp);
7002 int32_t callee_saved_value =
static_cast<int32_t
>(icount_);
7003 set_register(s0, callee_saved_value);
7004 set_register(s1, callee_saved_value);
7005 set_register(s2, callee_saved_value);
7006 set_register(s3, callee_saved_value);
7007 set_register(s4, callee_saved_value);
7008 set_register(s5, callee_saved_value);
7009 set_register(s6, callee_saved_value);
7010 set_register(s7, callee_saved_value);
7011 set_register(gp, callee_saved_value);
7012 set_register(fp, callee_saved_value);
7018 CHECK_EQ(callee_saved_value, get_register(s0));
7019 CHECK_EQ(callee_saved_value, get_register(s1));
7020 CHECK_EQ(callee_saved_value, get_register(s2));
7021 CHECK_EQ(callee_saved_value, get_register(s3));
7022 CHECK_EQ(callee_saved_value, get_register(s4));
7023 CHECK_EQ(callee_saved_value, get_register(s5));
7024 CHECK_EQ(callee_saved_value, get_register(s6));
7025 CHECK_EQ(callee_saved_value, get_register(s7));
7026 CHECK_EQ(callee_saved_value, get_register(gp));
7027 CHECK_EQ(callee_saved_value, get_register(fp));
7030 set_register(s0, s0_val);
7031 set_register(s1, s1_val);
7032 set_register(s2, s2_val);
7033 set_register(s3, s3_val);
7034 set_register(s4, s4_val);
7035 set_register(s5, s5_val);
7036 set_register(s6, s6_val);
7037 set_register(s7, s7_val);
7038 set_register(gp, gp_val);
7039 set_register(sp, sp_val);
7040 set_register(fp, fp_val);
7043 intptr_t Simulator::CallImpl(Address entry,
int argument_count,
7044 const intptr_t* arguments) {
7048 int reg_arg_count = std::min(4, argument_count);
7049 if (reg_arg_count > 0) set_register(a0, arguments[0]);
7050 if (reg_arg_count > 1) set_register(a1, arguments[1]);
7051 if (reg_arg_count > 2) set_register(a2, arguments[2]);
7052 if (reg_arg_count > 3) set_register(a3, arguments[3]);
7055 int original_stack = get_register(sp);
7057 int entry_stack = (original_stack - (argument_count - 4) *
sizeof(int32_t)
7059 if (base::OS::ActivationFrameAlignment() != 0) {
7060 entry_stack &= -base::OS::ActivationFrameAlignment();
7063 intptr_t* stack_argument =
reinterpret_cast<intptr_t*
>(entry_stack);
7064 memcpy(stack_argument + kCArgSlotCount, arguments + reg_arg_count,
7065 (argument_count - reg_arg_count) *
sizeof(*arguments));
7066 set_register(sp, entry_stack);
7068 CallInternal(entry);
7071 CHECK_EQ(entry_stack, get_register(sp));
7072 set_register(sp, original_stack);
7074 return get_register(v0);
7077 double Simulator::CallFP(Address entry,
double d0,
double d1) {
7078 if (!IsMipsSoftFloatABI) {
7079 set_fpu_register_double(f12, d0);
7080 set_fpu_register_double(f14, d1);
7083 DCHECK(
sizeof(buffer[0]) * 2 ==
sizeof(d0));
7084 memcpy(buffer, &d0,
sizeof(d0));
7085 set_dw_register(a0, buffer);
7086 memcpy(buffer, &d1,
sizeof(d1));
7087 set_dw_register(a2, buffer);
7089 CallInternal(entry);
7090 if (!IsMipsSoftFloatABI) {
7091 return get_fpu_register_double(f0);
7093 return get_double_from_register_pair(v0);
7099 int new_sp = get_register(sp) -
sizeof(
uintptr_t);
7101 *stack_slot = address;
7102 set_register(sp, new_sp);
7108 int current_sp = get_register(sp);
7111 set_register(sp, current_sp +
sizeof(
uintptr_t));
7121 #endif // USE_SIMULATOR 7123 #endif // V8_TARGET_ARCH_MIPS