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

Unified Diff: runtime/vm/simulator_mips.cc

Issue 14206002: Adds some floating point instructions to MIPS simulator, assembler, disassembler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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
« runtime/vm/assembler_mips.h ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/simulator_mips.cc
===================================================================
--- runtime/vm/simulator_mips.cc (revision 21293)
+++ runtime/vm/simulator_mips.cc (working copy)
@@ -642,8 +642,7 @@
}
-// Sets the register in the architecture state. It will also deal with updating
-// Simulator internal state for special registers such as PC.
+// Sets the register in the architecture state.
void Simulator::set_register(Register reg, int32_t value) {
if (reg != R0) {
registers_[reg] = value;
@@ -651,8 +650,36 @@
}
-// Get the register from the architecture state. This function does handle
-// the special case of accessing the PC register.
+void Simulator::set_fregister(FRegister reg, int32_t value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ fregisters_[reg] = value;
+}
+
+
+void Simulator::set_fregister_float(FRegister reg, float value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ fregisters_[reg] = bit_cast<int32_t, float>(value);
+}
+
+
+void Simulator::set_fregister_long(FRegister reg, int64_t value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ ASSERT((reg & 1) == 0);
+ fregisters_[reg] = Utils::Low32Bits(value);
+ fregisters_[reg + 1] = Utils::High32Bits(value);
+}
+
+
+void Simulator::set_fregister_double(FRegister reg, double value) {
+ const int64_t ival = bit_cast<int64_t, double>(value);
+ set_fregister_long(reg, ival);
+}
+
+
+// Get the register from the architecture state.
int32_t Simulator::get_register(Register reg) const {
if (reg == R0) {
return 0;
@@ -661,18 +688,39 @@
}
-void Simulator::set_fregister(FRegister reg, double value) {
+int32_t Simulator::get_fregister(FRegister reg) const {
ASSERT((reg >= 0) && (reg < kNumberOfFRegisters));
- fregisters_[reg] = value;
+ return fregisters_[reg];
}
-double Simulator::get_fregister(FRegister reg) const {
- ASSERT((reg >= 0) && (reg < kNumberOfFRegisters));
- return fregisters_[reg];
+float Simulator::get_fregister_float(FRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ return bit_cast<float, int32_t>(fregisters_[reg]);
}
+int64_t Simulator::get_fregister_long(FRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ ASSERT((reg & 1) == 0);
+ const int32_t low = fregisters_[reg];
+ const int32_t high = fregisters_[reg + 1];
+ const int64_t value = Utils::LowHighTo64Bits(low, high);
+ return value;
+}
+
+
+double Simulator::get_fregister_double(FRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfFRegisters);
+ ASSERT((reg & 1) == 0);
+ const int64_t value = get_fregister_long(reg);
+ return bit_cast<double, int64_t>(value);
+}
+
+
void Simulator::UnimplementedInstruction(Instr* instr) {
char buffer[64];
snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
@@ -794,6 +842,26 @@
}
+double Simulator::ReadD(uword addr, Instr* instr) {
+ if ((addr & 7) == 0) {
+ double* ptr = reinterpret_cast<double*>(addr);
+ return *ptr;
+ }
+ UnalignedAccess("double-precision floating point read", addr, instr);
+ return 0.0;
+}
+
+
+void Simulator::WriteD(uword addr, double value, Instr* instr) {
+ if ((addr & 7) == 0) {
+ double* ptr = reinterpret_cast<double*>(addr);
+ *ptr = value;
+ return;
+ }
+ UnalignedAccess("double-precision floating point write", addr, instr);
+}
+
+
bool Simulator::OverflowFrom(int32_t alu_out,
int32_t left, int32_t right, bool addition) {
bool overflow;
@@ -905,7 +973,7 @@
set_register(RA, icount_);
// Zap floating point registers.
- double zap_dvalue = static_cast<double>(icount_);
+ int32_t zap_dvalue = icount_;
for (int i = F0; i <= F31; i++) {
set_fregister(static_cast<FRegister>(i), zap_dvalue);
}
@@ -1286,6 +1354,72 @@
}
+void Simulator::DecodeCop1(Instr* instr) {
+ ASSERT(instr->OpcodeField() == COP1);
+ if (instr->HasFormat()) {
+ // If the rs field is a valid format, then the function field identifies the
+ // instruction.
+ switch (instr->Cop1FunctionField()) {
+ case COP1_ADD: {
+ // Format(instr, "add.'fmt 'fd, 'fs, 'ft");
+ if (instr->FormatField() == FMT_S) {
+ float fs_val = get_fregister_float(instr->FsField());
+ float ft_val = get_fregister_float(instr->FtField());
+ set_fregister_float(instr->FdField(), fs_val + ft_val);
+ } else {
+ ASSERT(instr->FormatField() == FMT_D); // Only S and D supported.
+ double fs_val = get_fregister_double(instr->FsField());
+ double ft_val = get_fregister_double(instr->FtField());
+ set_fregister_double(instr->FdField(), fs_val + ft_val);
+ }
+ break;
+ }
+ case COP1_MOV: {
+ // Format(instr, "mov.'fmt 'fd, 'fs");
+ ASSERT(instr->FtField() == F0);
+ if (instr->FormatField() == FMT_S) {
+ float fs_val = get_fregister_float(instr->FsField());
+ set_fregister_float(instr->FdField(), fs_val);
+ } else {
+ ASSERT(instr->FormatField() == FMT_D);
+ double fs_val = get_fregister_double(instr->FsField());
+ set_fregister_double(instr->FdField(), fs_val);
+ }
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
+ }
+ } else {
+ // If the rs field isn't a valid format, then it must be a sub-op.
+ switch (instr->Cop1SubField()) {
+ case COP1_MF: {
+ // Format(instr, "mfc1 'rt, 'fs");
+ ASSERT(instr->Bits(0, 11) == 0);
+ int32_t fs_val = get_fregister(instr->FsField());
+ set_register(instr->RtField(), fs_val);
+ break;
+ }
+ case COP1_MT: {
+ // Format(instr, "mtc1 'rt, 'fs");
+ ASSERT(instr->Bits(0, 11) == 0);
+ int32_t rt_val = get_register(instr->RtField());
+ set_fregister(instr->FsField(), rt_val);
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
+ }
+ }
+}
+
+
void Simulator::InstructionDecode(Instr* instr) {
if (FLAG_trace_sim) {
const uword start = reinterpret_cast<uword>(instr);
@@ -1306,6 +1440,10 @@
DecodeRegImm(instr);
break;
}
+ case COP1: {
+ DecodeCop1(instr);
+ break;
+ }
case ADDIU: {
// Format(instr, "addiu 'rt, 'rs, 'imms");
int32_t rs_val = get_register(instr->RsField());
@@ -1403,6 +1541,19 @@
}
break;
}
+ case LDC1: {
+ // Format(instr, "ldc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ double value = ReadD(addr, instr);
+ set_fregister_double(instr->FtField(), value);
+ }
+ break;
+ }
case LH: {
// Format(instr, "lh 'rt, 'imms('rs)");
int32_t base_val = get_register(instr->RsField());
@@ -1447,6 +1598,19 @@
}
break;
}
+ case LWC1: {
+ // Format(instr, "lwc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ int32_t value = ReadW(addr, instr);
+ set_fregister(instr->FtField(), value);
+ }
+ break;
+ }
case ORI: {
// Format(instr, "ori 'rt, 'rs, 'immu");
int32_t rs_val = get_register(instr->RsField());
@@ -1466,6 +1630,19 @@
}
break;
}
+ case SDC1: {
+ // Format(instr, "sdc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ double value = get_fregister_double(instr->FtField());
+ WriteD(addr, value, instr);
+ }
+ break;
+ }
case SH: {
// Format(instr, "sh 'rt, 'imms('rs)");
int32_t rt_val = get_register(instr->RtField());
@@ -1492,6 +1669,19 @@
}
break;
}
+ case SWC1: {
+ // Format(instr, "swc1 'ft, 'imms('rs)");
+ int32_t base_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ uword addr = base_val + imm_val;
+ if (Simulator::IsIllegalAddress(addr)) {
+ HandleIllegalAccess(addr, instr);
+ } else {
+ int32_t value = get_fregister(instr->FtField());
+ WriteW(addr, value, instr);
+ }
+ break;
+ }
default: {
OS::PrintErr("Undecoded instruction: 0x%x at %p\n",
instr->InstructionBits(), instr);
« runtime/vm/assembler_mips.h ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698