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

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

Issue 348019: Add vfp support on ARM. Patch from John Jozwiak. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 1 month 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/arm/simulator-arm.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/simulator-arm.cc
===================================================================
--- src/arm/simulator-arm.cc (revision 3208)
+++ src/arm/simulator-arm.cc (working copy)
@@ -342,6 +342,11 @@
PrintF("Z flag: %d; ", sim_->z_flag_);
PrintF("C flag: %d; ", sim_->c_flag_);
PrintF("V flag: %d\n", sim_->v_flag_);
+ PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
+ PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
+ PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
+ PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
+ PrintF("INEXACT flag: %d; ", sim_->inexact_vfp_flag_);
} else if (strcmp(cmd, "unstop") == 0) {
intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
@@ -429,6 +434,24 @@
c_flag_ = false;
v_flag_ = false;
+ // Initializing VFP registers.
+ // All registers are initialized to zero to start with.
+ // even though s_registers_ & d_registers_ share the same
+ // physical registers in the target
+ for (int i = 0; i < num_s_registers; i++) {
+ vfp_register[i] = 0;
+ }
+ n_flag_FPSCR_ = false;
+ z_flag_FPSCR_ = false;
+ c_flag_FPSCR_ = false;
+ v_flag_FPSCR_ = false;
+
+ inv_op_vfp_flag_ = false;
+ div_zero_vfp_flag_ = false;
+ overflow_vfp_flag_ = false;
+ underflow_vfp_flag_ = false;
+ inexact_vfp_flag_ = false;
+
// The sp is initialized to point to the bottom (high address) of the
// allocated stack area. To be safe in potential stack underflows we leave
// some buffer below.
@@ -544,7 +567,92 @@
return registers_[pc];
}
+// Getting from and setting into VFP registers.
+void Simulator::set_s_register(int sreg, unsigned int value) {
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
+ vfp_register[sreg] = value;
+}
+unsigned int Simulator::get_s_register(int sreg) const {
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
+ return vfp_register[sreg];
+}
+
+void Simulator::set_s_register_from_float(int sreg, const float flt) {
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
+ // Read the bits from the single precision floating point value
+ // into the unsigned integer element of vfp_register[] given by index=sreg.
+ char buffer[sizeof(vfp_register[0])];
+ memcpy(buffer, &flt, sizeof(vfp_register[0]));
+ memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0]));
+}
+
+void Simulator::set_s_register_from_sinteger(int sreg, const int sint) {
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
+ // Read the bits from the integer value
+ // into the unsigned integer element of vfp_register[] given by index=sreg.
+ char buffer[sizeof(vfp_register[0])];
+ memcpy(buffer, &sint, sizeof(vfp_register[0]));
+ memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0]));
+}
+
+void Simulator::set_d_register_from_double(int dreg, const double& dbl) {
+ ASSERT((dreg >= 0) && (dreg < num_d_registers));
+ // Read the bits from the double precision floating point value
+ // into the two consecutive unsigned integer elements of vfp_register[]
+ // given by index 2*sreg and 2*sreg+1.
+ char buffer[2 * sizeof(vfp_register[0])];
+ memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0]));
+#ifndef BIG_ENDIAN_FLOATING_POINT
+ memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0]));
+#else
+ memcpy(&vfp_register[dreg * 2], &buffer[4], sizeof(vfp_register[0]));
+ memcpy(&vfp_register[dreg * 2 + 1], &buffer[0], sizeof(vfp_register[0]));
+#endif
+}
+
+float Simulator::get_float_from_s_register(int sreg) {
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
+
+ float sm_val = 0.0;
+ // Read the bits from the unsigned integer vfp_register[] array
+ // into the single precision floating point value and return it.
+ char buffer[sizeof(vfp_register[0])];
+ memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0]));
+ memcpy(&sm_val, buffer, sizeof(vfp_register[0]));
+ return(sm_val);
+}
+
+int Simulator::get_sinteger_from_s_register(int sreg) {
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
+
+ int sm_val = 0;
+ // Read the bits from the unsigned integer vfp_register[] array
+ // into the single precision floating point value and return it.
+ char buffer[sizeof(vfp_register[0])];
+ memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0]));
+ memcpy(&sm_val, buffer, sizeof(vfp_register[0]));
+ return(sm_val);
+}
+
+double Simulator::get_double_from_d_register(int dreg) {
+ ASSERT((dreg >= 0) && (dreg < num_d_registers));
+
+ double dm_val = 0.0;
+ // Read the bits from the unsigned integer vfp_register[] array
+ // into the double precision floating point value and return it.
+ char buffer[2 * sizeof(vfp_register[0])];
+#ifndef BIG_ENDIAN_FLOATING_POINT
+ memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0]));
+#else
+ memcpy(&buffer[0], &vfp_register[2 * dreg + 1], sizeof(vfp_register[0]));
+ memcpy(&buffer[4], &vfp_register[2 * dreg], sizeof(vfp_register[0]));
+#endif
+ memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0]));
+ return(dm_val);
+}
+
+
// For use in calls that take two double values, constructed from r0, r1, r2
// and r3.
void Simulator::GetFpArgs(double* x, double* y) {
@@ -771,7 +879,38 @@
return overflow;
}
+// Support for VFP comparisons.
+void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
+ // All Non-Nan cases
+ if (val1 == val2) {
+ n_flag_FPSCR_ = false;
+ z_flag_FPSCR_ = true;
+ c_flag_FPSCR_ = true;
+ v_flag_FPSCR_ = false;
+ } else if (val1 < val2) {
+ n_flag_FPSCR_ = true;
+ z_flag_FPSCR_ = false;
+ c_flag_FPSCR_ = false;
+ v_flag_FPSCR_ = false;
+ } else {
+ // Case when (val1 > val2).
+ n_flag_FPSCR_ = false;
+ z_flag_FPSCR_ = false;
+ c_flag_FPSCR_ = true;
+ v_flag_FPSCR_ = false;
+ }
+}
+
+void Simulator::Copy_FPSCR_to_APSR() {
+ n_flag_ = n_flag_FPSCR_;
+ z_flag_ = z_flag_FPSCR_;
+ c_flag_ = c_flag_FPSCR_;
+ v_flag_ = v_flag_FPSCR_;
+}
+
+
+
// Addressing Mode 1 - Data-processing operands:
// Get the value based on the shifter_operand with register.
int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
@@ -1664,16 +1803,15 @@
void Simulator::DecodeType6(Instr* instr) {
- UNIMPLEMENTED();
+ DecodeType6CoprocessorIns(instr);
}
void Simulator::DecodeType7(Instr* instr) {
if (instr->Bit(24) == 1) {
- // Format(instr, "swi 'swi");
SoftwareInterrupt(instr);
} else {
- UNIMPLEMENTED();
+ DecodeTypeVFP(instr);
}
}
@@ -1745,6 +1883,178 @@
}
+// void Simulator::DecodeTypeVFP(Instr* instr)
+// The Following ARMv7 VFPv instructions are currently supported.
+// fmsr :Sn = Rt
+// fmrs :Rt = Sn
+// fsitod: Dd = Sm
+// ftosid: Sd = Dm
+// Dd = faddd(Dn, Dm)
+// Dd = fsubd(Dn, Dm)
+// Dd = fmuld(Dn, Dm)
+// Dd = fdivd(Dn, Dm)
+// vcmp(Dd, Dm)
+// VMRS
+void Simulator::DecodeTypeVFP(Instr* instr) {
+ ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
+
+ int rt = instr->RtField();
+ int vm = instr->VmField();
+ int vn = instr->VnField();
+ int vd = instr->VdField();
+
+ if (instr->Bit(23) == 1) {
+ if ((instr->Bits(21, 19) == 0x7) &&
+ (instr->Bits(18, 16) == 0x5) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 1) &&
+ (instr->Bit(6) == 1) &&
+ (instr->Bit(4) == 0)) {
+ double dm_val = get_double_from_d_register(vm);
+ int32_t int_value = static_cast<int32_t>(dm_val);
+ set_s_register_from_sinteger(((vd<<1) | instr->DField()), int_value);
+ } else if ((instr->Bits(21, 19) == 0x7) &&
+ (instr->Bits(18, 16) == 0x0) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 1) &&
+ (instr->Bit(7) == 1) &&
+ (instr->Bit(6) == 1) &&
+ (instr->Bit(4) == 0)) {
+ int32_t int_value = get_sinteger_from_s_register(((vm<<1) |
+ instr->MField()));
+ double dbl_value = static_cast<double>(int_value);
+ set_d_register_from_double(vd, dbl_value);
+ } else if ((instr->Bit(21) == 0x0) &&
+ (instr->Bit(20) == 0x0) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 1) &&
+ (instr->Bit(6) == 0) &&
+ (instr->Bit(4) == 0)) {
+ double dn_value = get_double_from_d_register(vn);
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = dn_value / dm_value;
+ set_d_register_from_double(vd, dd_value);
+ } else if ((instr->Bits(21, 20) == 0x3) &&
+ (instr->Bits(19, 16) == 0x4) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 0x1) &&
+ (instr->Bit(6) == 0x1) &&
+ (instr->Bit(4) == 0x0)) {
+ double dd_value = get_double_from_d_register(vd);
+ double dm_value = get_double_from_d_register(vm);
+ Compute_FPSCR_Flags(dd_value, dm_value);
+ } else if ((instr->Bits(23, 20) == 0xF) &&
+ (instr->Bits(19, 16) == 0x1) &&
+ (instr->Bits(11, 8) == 0xA) &&
+ (instr->Bits(7, 5) == 0x0) &&
+ (instr->Bit(4) == 0x1) &&
+ (instr->Bits(3, 0) == 0x0)) {
+ if (instr->Bits(15, 12) == 0xF)
+ Copy_FPSCR_to_APSR();
+ else
+ UNIMPLEMENTED(); // not used by V8 now
+ } else {
+ UNIMPLEMENTED(); // not used by V8 now
+ }
+ } else if (instr->Bit(21) == 1) {
+ if ((instr->Bit(20) == 0x1) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 0x1) &&
+ (instr->Bit(6) == 0) &&
+ (instr->Bit(4) == 0)) {
+ double dn_value = get_double_from_d_register(vn);
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = dn_value + dm_value;
+ set_d_register_from_double(vd, dd_value);
+ } else if ((instr->Bit(20) == 0x1) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 0x1) &&
+ (instr->Bit(6) == 1) &&
+ (instr->Bit(4) == 0)) {
+ double dn_value = get_double_from_d_register(vn);
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = dn_value - dm_value;
+ set_d_register_from_double(vd, dd_value);
+ } else if ((instr->Bit(20) == 0x0) &&
+ (instr->Bits(11, 9) == 0x5) &&
+ (instr->Bit(8) == 0x1) &&
+ (instr->Bit(6) == 0) &&
+ (instr->Bit(4) == 0)) {
+ double dn_value = get_double_from_d_register(vn);
+ double dm_value = get_double_from_d_register(vm);
+ double dd_value = dn_value * dm_value;
+ set_d_register_from_double(vd, dd_value);
+ } else {
+ UNIMPLEMENTED(); // not used by V8 now
+ }
+ } else {
+ if ((instr->Bit(20) == 0x0) &&
+ (instr->Bits(11, 8) == 0xA) &&
+ (instr->Bits(6, 5) == 0x0) &&
+ (instr->Bit(4) == 1) &&
+ (instr->Bits(3, 0) == 0x0)) {
+ int32_t rs_val = get_register(rt);
+ set_s_register_from_sinteger(((vn<<1) | instr->NField()), rs_val);
+ } else if ((instr->Bit(20) == 0x1) &&
+ (instr->Bits(11, 8) == 0xA) &&
+ (instr->Bits(6, 5) == 0x0) &&
+ (instr->Bit(4) == 1) &&
+ (instr->Bits(3, 0) == 0x0)) {
+ int32_t int_value = get_sinteger_from_s_register(((vn<<1) |
+ instr->NField()));
+ set_register(rt, int_value);
+ } else {
+ UNIMPLEMENTED(); // not used by V8 now
+ }
+ }
+}
+
+
+
+// void Simulator::DecodeType6CoprocessorIns(Instr* instr)
+// Decode Type 6 coprocessor instructions
+// Dm = fmdrr(Rt, Rt2)
+// <Rt, Rt2> = fmrrd(Dm)
+void Simulator::DecodeType6CoprocessorIns(Instr* instr) {
+ ASSERT((instr->TypeField() == 6));
+
+ int rt = instr->RtField();
+ int rn = instr->RnField();
+ int vm = instr->VmField();
+
+ if (instr->Bit(23) == 1) {
+ UNIMPLEMENTED();
+ } else if (instr->Bit(22) == 1) {
+ if ((instr->Bits(27, 24) == 0xC) &&
+ (instr->Bit(22) == 1) &&
+ (instr->Bits(11, 8) == 0xB) &&
+ (instr->Bits(7, 6) == 0x0) &&
+ (instr->Bit(4) == 1)) {
+ if (instr->Bit(20) == 0) {
+ int32_t rs_val = get_register(rt);
+ int32_t rn_val = get_register(rn);
+
+ set_s_register_from_sinteger(2*vm, rs_val);
+ set_s_register_from_sinteger((2*vm+1), rn_val);
+
+ } else if (instr->Bit(20) == 1) {
+ int32_t rt_int_value = get_sinteger_from_s_register(2*vm);
+ int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1);
+
+ set_register(rt, rt_int_value);
+ set_register(rn, rn_int_value);
+ }
+ } else {
+ UNIMPLEMENTED();
+ }
+ } else if (instr->Bit(21) == 1) {
+ UNIMPLEMENTED();
+ } else {
+ UNIMPLEMENTED();
+ }
+}
+
+
// Executes the current instruction.
void Simulator::InstructionDecode(Instr* instr) {
pc_modified_ = false;
@@ -1802,7 +2112,6 @@
}
-//
void Simulator::Execute() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698