Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(858)

Unified Diff: src/mips/simulator-mips.cc

Issue 467583002: Reland "MIPS: Add support for arch. revision 6 to mips32 port." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix for gclient runhooks failure. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mips/simulator-mips.h ('k') | test/cctest/test-assembler-mips.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips/simulator-mips.cc
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 30924569bc0a9532d210b4b1399e8e004768a3a4..d40fac7cb0541b8bf8c0d0ea6b1ed9fcfd331210 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -67,11 +67,12 @@ class MipsDebugger {
Simulator* sim_;
int32_t GetRegisterValue(int regnum);
- int32_t GetFPURegisterValueInt(int regnum);
- int64_t GetFPURegisterValueLong(int regnum);
+ int32_t GetFPURegisterValue32(int regnum);
+ int64_t GetFPURegisterValue64(int regnum);
float GetFPURegisterValueFloat(int regnum);
double GetFPURegisterValueDouble(int regnum);
bool GetValue(const char* desc, int32_t* value);
+ bool GetValue(const char* desc, int64_t* value);
// Set or delete a breakpoint. Returns true if successful.
bool SetBreakpoint(Instruction* breakpc);
@@ -160,20 +161,20 @@ int32_t MipsDebugger::GetRegisterValue(int regnum) {
}
-int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
+int32_t MipsDebugger::GetFPURegisterValue32(int regnum) {
if (regnum == kNumFPURegisters) {
return sim_->get_pc();
} else {
- return sim_->get_fpu_register(regnum);
+ return sim_->get_fpu_register_word(regnum);
}
}
-int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
+int64_t MipsDebugger::GetFPURegisterValue64(int regnum) {
if (regnum == kNumFPURegisters) {
return sim_->get_pc();
} else {
- return sim_->get_fpu_register_long(regnum);
+ return sim_->get_fpu_register(regnum);
}
}
@@ -204,7 +205,7 @@ bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
*value = GetRegisterValue(regnum);
return true;
} else if (fpuregnum != kInvalidFPURegister) {
- *value = GetFPURegisterValueInt(fpuregnum);
+ *value = GetFPURegisterValue32(fpuregnum);
return true;
} else if (strncmp(desc, "0x", 2) == 0) {
return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
@@ -215,6 +216,26 @@ bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
}
+bool MipsDebugger::GetValue(const char* desc, int64_t* value) {
+ int regnum = Registers::Number(desc);
+ int fpuregnum = FPURegisters::Number(desc);
+
+ if (regnum != kInvalidRegister) {
+ *value = GetRegisterValue(regnum);
+ return true;
+ } else if (fpuregnum != kInvalidFPURegister) {
+ *value = GetFPURegisterValue64(fpuregnum);
+ return true;
+ } else if (strncmp(desc, "0x", 2) == 0) {
+ return SScanF(desc + 2, "%" SCNx64,
+ reinterpret_cast<uint64_t*>(value)) == 1;
+ } else {
+ return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
+ }
+ return false;
+}
+
+
bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
// Check if a breakpoint can be set. If not return without any side-effects.
if (sim_->break_pc_ != NULL) {
@@ -295,34 +316,76 @@ void MipsDebugger::PrintAllRegs() {
void MipsDebugger::PrintAllRegsIncludingFPU() {
-#define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
- GetFPURegisterValueInt(n+1), \
- GetFPURegisterValueInt(n), \
- GetFPURegisterValueDouble(n)
+#define FPU_REG_INFO32(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
+ GetFPURegisterValue32(n+1), \
+ GetFPURegisterValue32(n), \
+ GetFPURegisterValueDouble(n)
+
+#define FPU_REG_INFO64(n) FPURegisters::Name(n), \
+ GetFPURegisterValue64(n), \
+ GetFPURegisterValueDouble(n)
PrintAllRegs();
PrintF("\n\n");
// f0, f1, f2, ... f31.
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
+ // This must be a compile-time switch,
+ // compiler will throw out warnings otherwise.
+ if (kFpuMode == kFP64) {
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(0) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(1) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(2) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(3) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(4) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(5) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(6) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(7) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(8) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(9) );
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(10));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(11));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(12));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(13));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(14));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(15));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(16));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(17));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(18));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(19));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(20));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(21));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(22));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(23));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(24));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(25));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(26));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(27));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(28));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(29));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(30));
+ PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(31));
+ } else {
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(0) );
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(2) );
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(4) );
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(6) );
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(8) );
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(10));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(12));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(14));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(16));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(18));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(20));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(22));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(24));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(26));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(28));
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(30));
+ }
#undef REG_INFO
-#undef FPU_REG_INFO
+#undef FPU_REG_INFO32
+#undef FPU_REG_INFO64
}
@@ -397,8 +460,6 @@ void MipsDebugger::Debug() {
done = true;
} else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
if (argc == 2) {
- int32_t value;
- float fvalue;
if (strcmp(arg1, "all") == 0) {
PrintAllRegs();
} else if (strcmp(arg1, "allf") == 0) {
@@ -408,24 +469,36 @@ void MipsDebugger::Debug() {
int fpuregnum = FPURegisters::Number(arg1);
if (regnum != kInvalidRegister) {
+ int32_t value;
value = GetRegisterValue(regnum);
PrintF("%s: 0x%08x %d \n", arg1, value, value);
} else if (fpuregnum != kInvalidFPURegister) {
- if (fpuregnum % 2 == 1) {
- value = GetFPURegisterValueInt(fpuregnum);
- fvalue = GetFPURegisterValueFloat(fpuregnum);
- PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
+ if (IsFp64Mode()) {
+ int64_t value;
+ double dvalue;
+ value = GetFPURegisterValue64(fpuregnum);
+ dvalue = GetFPURegisterValueDouble(fpuregnum);
+ PrintF("%3s: 0x%016llx %16.4e\n",
+ FPURegisters::Name(fpuregnum), value, dvalue);
} else {
- double dfvalue;
- int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
- int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
- dfvalue = GetFPURegisterValueDouble(fpuregnum);
- PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
- FPURegisters::Name(fpuregnum+1),
- FPURegisters::Name(fpuregnum),
- lvalue1,
- lvalue2,
- dfvalue);
+ if (fpuregnum % 2 == 1) {
+ int32_t value;
+ float fvalue;
+ value = GetFPURegisterValue32(fpuregnum);
+ fvalue = GetFPURegisterValueFloat(fpuregnum);
+ PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
+ } else {
+ double dfvalue;
+ int32_t lvalue1 = GetFPURegisterValue32(fpuregnum);
+ int32_t lvalue2 = GetFPURegisterValue32(fpuregnum + 1);
+ dfvalue = GetFPURegisterValueDouble(fpuregnum);
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
+ FPURegisters::Name(fpuregnum+1),
+ FPURegisters::Name(fpuregnum),
+ lvalue1,
+ lvalue2,
+ dfvalue);
+ }
}
} else {
PrintF("%s unrecognized\n", arg1);
@@ -439,7 +512,7 @@ void MipsDebugger::Debug() {
int fpuregnum = FPURegisters::Number(arg1);
if (fpuregnum != kInvalidFPURegister) {
- value = GetFPURegisterValueInt(fpuregnum);
+ value = GetFPURegisterValue32(fpuregnum);
fvalue = GetFPURegisterValueFloat(fpuregnum);
PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
} else {
@@ -489,15 +562,28 @@ void MipsDebugger::Debug() {
next_arg++;
}
- int32_t words;
- if (argc == next_arg) {
- words = 10;
+ // TODO(palfia): optimize this.
+ if (IsFp64Mode()) {
+ int64_t words;
+ if (argc == next_arg) {
+ words = 10;
+ } else {
+ if (!GetValue(argv[next_arg], &words)) {
+ words = 10;
+ }
+ }
+ end = cur + words;
} else {
- if (!GetValue(argv[next_arg], &words)) {
+ int32_t words;
+ if (argc == next_arg) {
words = 10;
+ } else {
+ if (!GetValue(argv[next_arg], &words)) {
+ words = 10;
+ }
}
+ end = cur + words;
}
- end = cur + words;
while (cur < end) {
PrintF(" 0x%08x: 0x%08x %10d",
@@ -1012,12 +1098,31 @@ void Simulator::set_dw_register(int reg, const int* dbl) {
}
-void Simulator::set_fpu_register(int fpureg, int32_t value) {
+void Simulator::set_fpu_register(int fpureg, int64_t value) {
+ DCHECK(IsFp64Mode());
DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
FPUregisters_[fpureg] = value;
}
+void Simulator::set_fpu_register_word(int fpureg, int32_t value) {
+ // Set ONLY lower 32-bits, leaving upper bits untouched.
+ // TODO(plind): big endian issue.
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]);
+ *pword = value;
+}
+
+
+void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
+ // Set ONLY upper 32-bits, leaving lower bits untouched.
+ // TODO(plind): big endian issue.
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1;
+ *phiword = value;
+}
+
+
void Simulator::set_fpu_register_float(int fpureg, float value) {
DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
*BitCast<float*>(&FPUregisters_[fpureg]) = value;
@@ -1025,8 +1130,15 @@ void Simulator::set_fpu_register_float(int fpureg, float value) {
void Simulator::set_fpu_register_double(int fpureg, double value) {
- DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
- *BitCast<double*>(&FPUregisters_[fpureg]) = value;
+ if (IsFp64Mode()) {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ *BitCast<double*>(&FPUregisters_[fpureg]) = value;
+ } else {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
+ int64_t i64 = BitCast<int64_t>(value);
+ set_fpu_register_word(fpureg, i64 & 0xffffffff);
+ set_fpu_register_word(fpureg + 1, i64 >> 32);
+ }
}
@@ -1042,6 +1154,7 @@ int32_t Simulator::get_register(int reg) const {
double Simulator::get_double_from_register_pair(int reg) {
+ // TODO(plind): bad ABI stuff, refactor or remove.
DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
double dm_val = 0.0;
@@ -1054,29 +1167,49 @@ double Simulator::get_double_from_register_pair(int reg) {
}
-int32_t Simulator::get_fpu_register(int fpureg) const {
+int64_t Simulator::get_fpu_register(int fpureg) const {
+ DCHECK(IsFp64Mode());
DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
return FPUregisters_[fpureg];
}
-int64_t Simulator::get_fpu_register_long(int fpureg) const {
- DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
- return *BitCast<int64_t*>(
- const_cast<int32_t*>(&FPUregisters_[fpureg]));
+int32_t Simulator::get_fpu_register_word(int fpureg) const {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
+}
+
+
+int32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
+}
+
+
+int32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff);
}
float Simulator::get_fpu_register_float(int fpureg) const {
DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
return *BitCast<float*>(
- const_cast<int32_t*>(&FPUregisters_[fpureg]));
+ const_cast<int64_t*>(&FPUregisters_[fpureg]));
}
double Simulator::get_fpu_register_double(int fpureg) const {
- DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
- return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
+ if (IsFp64Mode()) {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
+ return *BitCast<double*>(&FPUregisters_[fpureg]);
+ } else {
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
+ int64_t i64;
+ i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg));
+ i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32;
+ return BitCast<double>(i64);
+ }
}
@@ -1089,6 +1222,7 @@ void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
*y = get_fpu_register_double(14);
*z = get_register(a2);
} else {
+ // TODO(plind): bad ABI stuff, refactor or remove.
// We use a char buffer to get around the strict-aliasing rules which
// otherwise allow the compiler to optimize away the copy.
char buffer[sizeof(*x)];
@@ -1143,6 +1277,8 @@ bool Simulator::test_fcsr_bit(uint32_t cc) {
// Returns true if the operation was invalid.
bool Simulator::set_fcsr_round_error(double original, double rounded) {
bool ret = false;
+ double max_int32 = std::numeric_limits<int32_t>::max();
+ double min_int32 = std::numeric_limits<int32_t>::min();
if (!std::isfinite(original) || !std::isfinite(rounded)) {
set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
@@ -1158,7 +1294,7 @@ bool Simulator::set_fcsr_round_error(double original, double rounded) {
ret = true;
}
- if (rounded > INT_MAX || rounded < INT_MIN) {
+ if (rounded > max_int32 || rounded < min_int32) {
set_fcsr_bit(kFCSROverflowFlagBit, true);
// The reference is not really clear but it seems this is required:
set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
@@ -1420,18 +1556,35 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
switch (redirection->type()) {
case ExternalReference::BUILTIN_FP_FP_CALL:
case ExternalReference::BUILTIN_COMPARE_CALL:
- arg0 = get_fpu_register(f12);
- arg1 = get_fpu_register(f13);
- arg2 = get_fpu_register(f14);
- arg3 = get_fpu_register(f15);
+ if (IsFp64Mode()) {
+ arg0 = get_fpu_register_word(f12);
+ arg1 = get_fpu_register_hi_word(f12);
+ arg2 = get_fpu_register_word(f14);
+ arg3 = get_fpu_register_hi_word(f14);
+ } else {
+ arg0 = get_fpu_register_word(f12);
+ arg1 = get_fpu_register_word(f13);
+ arg2 = get_fpu_register_word(f14);
+ arg3 = get_fpu_register_word(f15);
+ }
break;
case ExternalReference::BUILTIN_FP_CALL:
- arg0 = get_fpu_register(f12);
- arg1 = get_fpu_register(f13);
+ if (IsFp64Mode()) {
+ arg0 = get_fpu_register_word(f12);
+ arg1 = get_fpu_register_hi_word(f12);
+ } else {
+ arg0 = get_fpu_register_word(f12);
+ arg1 = get_fpu_register_word(f13);
+ }
break;
case ExternalReference::BUILTIN_FP_INT_CALL:
- arg0 = get_fpu_register(f12);
- arg1 = get_fpu_register(f13);
+ if (IsFp64Mode()) {
+ arg0 = get_fpu_register_word(f12);
+ arg1 = get_fpu_register_hi_word(f12);
+ } else {
+ arg0 = get_fpu_register_word(f12);
+ arg1 = get_fpu_register_word(f13);
+ }
arg2 = get_register(a2);
break;
default:
@@ -1735,25 +1888,20 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
switch (op) {
case COP1: // Coprocessor instructions.
switch (instr->RsFieldRaw()) {
- case BC1: // Handled in DecodeTypeImmed, should never come here.
- UNREACHABLE();
- break;
case CFC1:
// At the moment only FCSR is supported.
DCHECK(fs_reg == kFCSRRegister);
*alu_out = FCSR_;
break;
case MFC1:
- *alu_out = get_fpu_register(fs_reg);
+ *alu_out = get_fpu_register_word(fs_reg);
break;
case MFHC1:
- UNIMPLEMENTED_MIPS();
+ *alu_out = get_fpu_register_hi_word(fs_reg);
break;
case CTC1:
case MTC1:
case MTHC1:
- // Do the store in the execution step.
- break;
case S:
case D:
case W:
@@ -1762,7 +1910,8 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
// Do everything in the execution step.
break;
default:
- UNIMPLEMENTED_MIPS();
+ // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
+ UNREACHABLE();
}
break;
case COP1X:
@@ -1810,17 +1959,53 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
case SRAV:
*alu_out = rt >> rs;
break;
- case MFHI:
- *alu_out = get_register(HI);
+ case MFHI: // MFHI == CLZ on R6.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ DCHECK(instr->SaValue() == 0);
+ *alu_out = get_register(HI);
+ } else {
+ // MIPS spec: If no bits were set in GPR rs, the result written to
+ // GPR rd is 32.
+ // GCC __builtin_clz: If input is 0, the result is undefined.
+ DCHECK(instr->SaValue() == 1);
+ *alu_out =
+ rs_u == 0 ? 32 : CompilerIntrinsics::CountLeadingZeros(rs_u);
+ }
break;
case MFLO:
*alu_out = get_register(LO);
break;
- case MULT:
- *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
+ case MULT: // MULT == MUL_MUH.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ case MUH_OP:
+ *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
- case MULTU:
- *u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
+ case MULTU: // MULTU == MUL_MUH_U.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ *u64hilo = static_cast<uint64_t>(rs_u) *
+ static_cast<uint64_t>(rt_u);
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ case MUH_OP:
+ *u64hilo = static_cast<uint64_t>(rs_u) *
+ static_cast<uint64_t>(rt_u);
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
case ADD:
if (HaveSameSign(rs, rt)) {
@@ -1998,16 +2183,14 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
switch (op) {
case COP1:
switch (instr->RsFieldRaw()) {
- case BC1: // Branch on coprocessor condition.
- UNREACHABLE();
- break;
case CFC1:
set_register(rt_reg, alu_out);
+ break;
case MFC1:
set_register(rt_reg, alu_out);
break;
case MFHC1:
- UNIMPLEMENTED_MIPS();
+ set_register(rt_reg, alu_out);
break;
case CTC1:
// At the moment only FCSR is supported.
@@ -2015,10 +2198,12 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
FCSR_ = registers_[rt_reg];
break;
case MTC1:
- FPUregisters_[fs_reg] = registers_[rt_reg];
+ // Hardware writes upper 32-bits to zero on mtc1.
+ set_fpu_register_hi_word(fs_reg, 0);
+ set_fpu_register_word(fs_reg, registers_[rt_reg]);
break;
case MTHC1:
- UNIMPLEMENTED_MIPS();
+ set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
break;
case S:
float f;
@@ -2027,20 +2212,9 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
f = get_fpu_register_float(fs_reg);
set_fpu_register_double(fd_reg, static_cast<double>(f));
break;
- case CVT_W_S:
- case CVT_L_S:
- case TRUNC_W_S:
- case TRUNC_L_S:
- case ROUND_W_S:
- case ROUND_L_S:
- case FLOOR_W_S:
- case FLOOR_L_S:
- case CEIL_W_S:
- case CEIL_L_S:
- case CVT_PS_S:
- UNIMPLEMENTED_MIPS();
- break;
default:
+ // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
+ // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
UNREACHABLE();
}
break;
@@ -2114,7 +2288,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
// round to the even one.
result--;
}
- set_fpu_register(fd_reg, result);
+ set_fpu_register_word(fd_reg, result);
if (set_fcsr_round_error(fs, rounded)) {
set_fpu_register(fd_reg, kFPUInvalidResult);
}
@@ -2124,7 +2298,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
{
double rounded = trunc(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register(fd_reg, result);
+ set_fpu_register_word(fd_reg, result);
if (set_fcsr_round_error(fs, rounded)) {
set_fpu_register(fd_reg, kFPUInvalidResult);
}
@@ -2134,7 +2308,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
{
double rounded = std::floor(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register(fd_reg, result);
+ set_fpu_register_word(fd_reg, result);
if (set_fcsr_round_error(fs, rounded)) {
set_fpu_register(fd_reg, kFPUInvalidResult);
}
@@ -2144,7 +2318,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
{
double rounded = std::ceil(fs);
int32_t result = static_cast<int32_t>(rounded);
- set_fpu_register(fd_reg, result);
+ set_fpu_register_word(fd_reg, result);
if (set_fcsr_round_error(fs, rounded)) {
set_fpu_register(fd_reg, kFPUInvalidResult);
}
@@ -2156,34 +2330,54 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word.
double rounded = trunc(fs);
i64 = static_cast<int64_t>(rounded);
- set_fpu_register(fd_reg, i64 & 0xffffffff);
- set_fpu_register(fd_reg + 1, i64 >> 32);
+ if (IsFp64Mode()) {
+ set_fpu_register(fd_reg, i64);
+ } else {
+ set_fpu_register_word(fd_reg, i64 & 0xffffffff);
+ set_fpu_register_word(fd_reg + 1, i64 >> 32);
+ }
break;
}
case TRUNC_L_D: { // Mips32r2 instruction.
double rounded = trunc(fs);
i64 = static_cast<int64_t>(rounded);
- set_fpu_register(fd_reg, i64 & 0xffffffff);
- set_fpu_register(fd_reg + 1, i64 >> 32);
+ if (IsFp64Mode()) {
+ set_fpu_register(fd_reg, i64);
+ } else {
+ set_fpu_register_word(fd_reg, i64 & 0xffffffff);
+ set_fpu_register_word(fd_reg + 1, i64 >> 32);
+ }
break;
}
case ROUND_L_D: { // Mips32r2 instruction.
double rounded =
fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5);
i64 = static_cast<int64_t>(rounded);
- set_fpu_register(fd_reg, i64 & 0xffffffff);
- set_fpu_register(fd_reg + 1, i64 >> 32);
+ if (IsFp64Mode()) {
+ set_fpu_register(fd_reg, i64);
+ } else {
+ set_fpu_register_word(fd_reg, i64 & 0xffffffff);
+ set_fpu_register_word(fd_reg + 1, i64 >> 32);
+ }
break;
}
case FLOOR_L_D: // Mips32r2 instruction.
i64 = static_cast<int64_t>(std::floor(fs));
- set_fpu_register(fd_reg, i64 & 0xffffffff);
- set_fpu_register(fd_reg + 1, i64 >> 32);
+ if (IsFp64Mode()) {
+ set_fpu_register(fd_reg, i64);
+ } else {
+ set_fpu_register_word(fd_reg, i64 & 0xffffffff);
+ set_fpu_register_word(fd_reg + 1, i64 >> 32);
+ }
break;
case CEIL_L_D: // Mips32r2 instruction.
i64 = static_cast<int64_t>(std::ceil(fs));
- set_fpu_register(fd_reg, i64 & 0xffffffff);
- set_fpu_register(fd_reg + 1, i64 >> 32);
+ if (IsFp64Mode()) {
+ set_fpu_register(fd_reg, i64);
+ } else {
+ set_fpu_register_word(fd_reg, i64 & 0xffffffff);
+ set_fpu_register_word(fd_reg + 1, i64 >> 32);
+ }
break;
case C_F_D:
UNIMPLEMENTED_MIPS();
@@ -2195,35 +2389,92 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
case W:
switch (instr->FunctionFieldRaw()) {
case CVT_S_W: // Convert word to float (single).
- alu_out = get_fpu_register(fs_reg);
+ alu_out = get_fpu_register_signed_word(fs_reg);
set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
break;
case CVT_D_W: // Convert word to double.
- alu_out = get_fpu_register(fs_reg);
+ alu_out = get_fpu_register_signed_word(fs_reg);
set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
break;
- default:
+ default: // Mips64r6 CMP.S instructions unimplemented.
UNREACHABLE();
}
break;
case L:
+ fs = get_fpu_register_double(fs_reg);
+ ft = get_fpu_register_double(ft_reg);
switch (instr->FunctionFieldRaw()) {
case CVT_D_L: // Mips32r2 instruction.
// Watch the signs here, we want 2 32-bit vals
// to make a sign-64.
- i64 = static_cast<uint32_t>(get_fpu_register(fs_reg));
- i64 |= static_cast<int64_t>(get_fpu_register(fs_reg + 1)) << 32;
+ if (IsFp64Mode()) {
+ i64 = get_fpu_register(fs_reg);
+ } else {
+ i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg));
+ i64 |= static_cast<int64_t>(
+ get_fpu_register_word(fs_reg + 1)) << 32;
+ }
set_fpu_register_double(fd_reg, static_cast<double>(i64));
break;
case CVT_S_L:
UNIMPLEMENTED_MIPS();
break;
- default:
+ case CMP_AF: // Mips64r6 CMP.D instructions.
+ UNIMPLEMENTED_MIPS();
+ break;
+ case CMP_UN:
+ if (std::isnan(fs) || std::isnan(ft)) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_EQ:
+ if (fs == ft) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_UEQ:
+ if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_LT:
+ if (fs < ft) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_ULT:
+ if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_LE:
+ if (fs <= ft) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_ULE:
+ if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED.
UNREACHABLE();
}
break;
- case PS:
- break;
default:
UNREACHABLE();
}
@@ -2263,30 +2514,100 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
}
// Instructions using HI and LO registers.
case MULT:
- set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
- set_register(HI, static_cast<int32_t>(i64hilo >> 32));
+ if (!IsMipsArchVariant(kMips32r6)) {
+ set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
+ set_register(HI, static_cast<int32_t>(i64hilo >> 32));
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ set_register(rd_reg,
+ static_cast<int32_t>(i64hilo & 0xffffffff));
+ break;
+ case MUH_OP:
+ set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
case MULTU:
- set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
- set_register(HI, static_cast<int32_t>(u64hilo >> 32));
+ if (!IsMipsArchVariant(kMips32r6)) {
+ set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
+ set_register(HI, static_cast<int32_t>(u64hilo >> 32));
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ set_register(rd_reg,
+ static_cast<int32_t>(u64hilo & 0xffffffff));
+ break;
+ case MUH_OP:
+ set_register(rd_reg, static_cast<int32_t>(u64hilo >> 32));
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
case DIV:
- // Divide by zero and overflow was not checked in the configuration
- // step - div and divu do not raise exceptions. On division by 0
- // the result will be UNPREDICTABLE. On overflow (INT_MIN/-1),
- // return INT_MIN which is what the hardware does.
- if (rs == INT_MIN && rt == -1) {
- set_register(LO, INT_MIN);
- set_register(HI, 0);
- } else if (rt != 0) {
- set_register(LO, rs / rt);
- set_register(HI, rs % rt);
+ if (IsMipsArchVariant(kMips32r6)) {
+ switch (instr->SaValue()) {
+ case DIV_OP:
+ if (rs == INT_MIN && rt == -1) {
+ set_register(rd_reg, INT_MIN);
+ } else if (rt != 0) {
+ set_register(rd_reg, rs / rt);
+ }
+ break;
+ case MOD_OP:
+ if (rs == INT_MIN && rt == -1) {
+ set_register(rd_reg, 0);
+ } else if (rt != 0) {
+ set_register(rd_reg, rs % rt);
+ }
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ } else {
+ // Divide by zero and overflow was not checked in the
+ // configuration step - div and divu do not raise exceptions. On
+ // division by 0 the result will be UNPREDICTABLE. On overflow
+ // (INT_MIN/-1), return INT_MIN which is what the hardware does.
+ if (rs == INT_MIN && rt == -1) {
+ set_register(LO, INT_MIN);
+ set_register(HI, 0);
+ } else if (rt != 0) {
+ set_register(LO, rs / rt);
+ set_register(HI, rs % rt);
+ }
}
break;
case DIVU:
- if (rt_u != 0) {
- set_register(LO, rs_u / rt_u);
- set_register(HI, rs_u % rt_u);
+ if (IsMipsArchVariant(kMips32r6)) {
+ switch (instr->SaValue()) {
+ case DIV_OP:
+ if (rt_u != 0) {
+ set_register(rd_reg, rs_u / rt_u);
+ }
+ break;
+ case MOD_OP:
+ if (rt_u != 0) {
+ set_register(rd_reg, rs_u % rt_u);
+ }
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ } else {
+ if (rt_u != 0) {
+ set_register(LO, rs_u / rt_u);
+ set_register(HI, rs_u % rt_u);
+ }
}
break;
// Break and trap instructions.
@@ -2368,6 +2689,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
int16_t imm16 = instr->Imm16Value();
int32_t ft_reg = instr->FtValue(); // Destination register.
+ int64_t ft;
// Zero extended immediate.
uint32_t oe_imm16 = 0xffff & imm16;
@@ -2412,6 +2734,28 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
next_pc = current_pc + kBranchReturnOffset;
}
break;
+ case BC1EQZ:
+ ft = get_fpu_register(ft_reg);
+ do_branch = (ft & 0x1) ? false : true;
+ execute_branch_delay_instruction = true;
+ // Set next_pc.
+ if (do_branch) {
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+ } else {
+ next_pc = current_pc + kBranchReturnOffset;
+ }
+ break;
+ case BC1NEZ:
+ ft = get_fpu_register(ft_reg);
+ do_branch = (ft & 0x1) ? true : false;
+ execute_branch_delay_instruction = true;
+ // Set next_pc.
+ if (do_branch) {
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+ } else {
+ next_pc = current_pc + kBranchReturnOffset;
+ }
+ break;
default:
UNREACHABLE();
}
@@ -2646,14 +2990,15 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
WriteW(addr, mem_value, instr);
break;
case LWC1:
- set_fpu_register(ft_reg, alu_out);
+ set_fpu_register_hi_word(ft_reg, 0);
+ set_fpu_register_word(ft_reg, alu_out);
break;
case LDC1:
set_fpu_register_double(ft_reg, fp_out);
break;
case SWC1:
addr = rs + se_imm16;
- WriteW(addr, get_fpu_register(ft_reg), instr);
+ WriteW(addr, get_fpu_register_word(ft_reg), instr);
break;
case SDC1:
addr = rs + se_imm16;
« no previous file with comments | « src/mips/simulator-mips.h ('k') | test/cctest/test-assembler-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698