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

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

Issue 993002: Port of optimized ICs for external and pixel arrays from ia32 to ARM. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 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
Index: src/arm/simulator-arm.cc
===================================================================
--- src/arm/simulator-arm.cc (revision 4136)
+++ src/arm/simulator-arm.cc (working copy)
@@ -72,6 +72,8 @@
int32_t GetRegisterValue(int regnum);
bool GetValue(const char* desc, int32_t* value);
+ bool GetVFPSingleValue(const char* desc, float* value);
+ bool GetVFPDoubleValue(const char* desc, double* value);
// Set or delete a breakpoint. Returns true if successful.
bool SetBreakpoint(Instr* breakpc);
@@ -154,6 +156,28 @@
}
+bool Debugger::GetVFPSingleValue(const char* desc, float* value) {
+ bool is_double;
+ int regnum = VFPRegisters::Number(desc, &is_double);
+ if (regnum != kNoRegister && !is_double) {
+ *value = sim_->get_float_from_s_register(regnum);
+ return true;
+ }
+ return false;
+}
+
+
+bool Debugger::GetVFPDoubleValue(const char* desc, double* value) {
+ bool is_double;
+ int regnum = VFPRegisters::Number(desc, &is_double);
+ if (regnum != kNoRegister && is_double) {
+ *value = sim_->get_double_from_d_register(regnum);
+ return true;
+ }
+ return false;
+}
+
+
bool Debugger::SetBreakpoint(Instr* breakpc) {
// Check if a breakpoint can be set. If not return without any side-effects.
if (sim_->break_pc_ != NULL) {
@@ -249,6 +273,8 @@
} else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
if (args == 2) {
int32_t value;
+ float svalue;
+ double dvalue;
if (strcmp(arg1, "all") == 0) {
for (int i = 0; i < kNumRegisters; i++) {
value = GetRegisterValue(i);
@@ -257,6 +283,10 @@
} else {
if (GetValue(arg1, &value)) {
PrintF("%s: 0x%08x %d \n", arg1, value, value);
+ } else if (GetVFPSingleValue(arg1, &svalue)) {
+ PrintF("%s: %f \n", arg1, svalue);
+ } else if (GetVFPDoubleValue(arg1, &dvalue)) {
+ PrintF("%s: %lf \n", arg1, dvalue);
} else {
PrintF("%s unrecognized\n", arg1);
}
@@ -1919,6 +1949,13 @@
}
+// Depending on value of last_bit flag glue register code from vm and m values
+// (where m is expected to be a single bit).
+static int GlueRegCode(bool last_bit, int vm, int m) {
+ return last_bit ? ((vm << 1) | m) : ((m << 4) | vm);
+}
+
+
// void Simulator::DecodeTypeVFP(Instr* instr)
// The Following ARMv7 VFPv instructions are currently supported.
// vmov :Sn = Rt
@@ -1933,114 +1970,212 @@
// VMRS
void Simulator::DecodeTypeVFP(Instr* instr) {
ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
+ ASSERT(instr->Bits(11, 9) == 0x5);
- int rt = instr->RtField();
int vm = instr->VmField();
+ int vd = instr->VdField();
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)) {
+ if (instr->Bit(4) == 0) {
+ if (instr->Opc1Field() == 0x7) {
+ // Other data processing instructions
+ if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) {
+ DecodeVCVTBetweenDoubleAndSingle(instr);
+ } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) {
+ DecodeVCVTBetweenFloatingPointAndInteger(instr);
+ } else if (((instr->Opc2Field() >> 1) == 0x6) &&
+ (instr->Opc3Field() & 0x1)) {
+ DecodeVCVTBetweenFloatingPointAndInteger(instr);
+ } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
+ (instr->Opc3Field() & 0x1)) {
+ DecodeVCMP(instr);
+ } else {
+ UNREACHABLE(); // Not used by V8.
+ }
+ } else if (instr->Opc1Field() == 0x3) {
+ if (instr->SzField() != 0x1) {
+ UNREACHABLE(); // Not used by V8.
+ }
+
+ if (instr->Opc3Field() & 0x1) {
+ // vsub
+ 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 {
+ // vadd
+ 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->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) {
+ // vmul
+ if (instr->SzField() != 0x1) {
+ UNREACHABLE(); // Not used by V8.
+ }
+
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->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) {
+ // vdiv
+ if (instr->SzField() != 0x1) {
+ UNREACHABLE(); // Not used by V8.
+ }
+
+ 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)
+ } else {
+ UNIMPLEMENTED(); // Not used by V8.
+ }
+ } else {
+ if ((instr->VCField() == 0x0) &&
+ (instr->VAField() == 0x0)) {
+ DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
+ } else if ((instr->VLField() == 0x1) &&
+ (instr->VCField() == 0x0) &&
+ (instr->VAField() == 0x7) &&
+ (instr->Bits(19, 16) == 0x1)) {
+ // vmrs
+ if (instr->RtField() == 0xF)
Copy_FPSCR_to_APSR();
else
UNIMPLEMENTED(); // Not used by V8.
} else {
UNIMPLEMENTED(); // Not used by V8.
}
- } 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 {
+ }
+}
+
+
+void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) {
+ ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) &&
+ (instr->VAField() == 0x0));
+
+ int t = instr->RtField();
+ int n = GlueRegCode(true, instr->VnField(), instr->NField());
+ bool to_arm_register = (instr->VLField() == 0x1);
+
+ if (to_arm_register) {
+ int32_t int_value = get_sinteger_from_s_register(n);
+ set_register(t, int_value);
+ } else {
+ int32_t rs_val = get_register(t);
+ set_s_register_from_sinteger(n, rs_val);
+ }
+}
+
+
+void Simulator::DecodeVCMP(Instr* instr) {
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
+ ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
+ (instr->Opc3Field() & 0x1));
+
+ // Comparison.
+ bool dp_operation = (instr->SzField() == 1);
+
+ if (instr->Bit(7) != 0) {
+ // Raising exceptions for quiet NaNs are not supported.
+ UNIMPLEMENTED(); // Not used by V8.
+ }
+
+ int d = GlueRegCode(!dp_operation, instr->VdField(), instr->DField());
+ int m = GlueRegCode(!dp_operation, instr->VmField(), instr->MField());
+
+ if (dp_operation) {
+ double dd_value = get_double_from_d_register(d);
+ double dm_value = get_double_from_d_register(m);
+
+ Compute_FPSCR_Flags(dd_value, dm_value);
+ } else {
+ UNIMPLEMENTED(); // Not used by V8.
+ }
+}
+
+
+void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) {
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
+ ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3));
+
+ bool double_to_single = (instr->SzField() == 1);
+ int dst = GlueRegCode(double_to_single, instr->VdField(), instr->DField());
+ int src = GlueRegCode(!double_to_single, instr->VmField(), instr->MField());
+
+ if (double_to_single) {
+ double val = get_double_from_d_register(src);
+ set_s_register_from_float(dst, static_cast<float>(val));
+ } else {
+ float val = get_float_from_s_register(src);
+ set_d_register_from_double(dst, static_cast<double>(val));
+ }
+}
+
+
+void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
+ ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) ||
+ (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1)));
+
+ // Conversion between floating-point and integer.
+ int vd = instr->VdField();
+ int d = instr->DField();
+ int vm = instr->VmField();
+ int m = instr->MField();
+
+ bool to_integer = (instr->Bit(18) == 1);
+ bool dp_operation = (instr->SzField() == 1);
+ if (to_integer) {
+ bool unsigned_integer = (instr->Bit(16) == 0);
+ if (instr->Bit(7) != 1) {
+ // Only rounding towards zero supported.
UNIMPLEMENTED(); // Not used by V8.
}
+
+ int dst = GlueRegCode(true, vd, d);
+ int src = GlueRegCode(!dp_operation, vm, m);
+
+ if (dp_operation) {
+ double val = get_double_from_d_register(src);
+
+ int sint = unsigned_integer ? static_cast<uint32_t>(val) :
+ static_cast<int32_t>(val);
+
+ set_s_register_from_sinteger(dst, sint);
+ } else {
+ float val = get_float_from_s_register(src);
+
+ int sint = unsigned_integer ? static_cast<uint32_t>(val) :
+ static_cast<int32_t>(val);
+
+ set_s_register_from_sinteger(dst, sint);
+ }
} 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);
+ bool unsigned_integer = (instr->Bit(7) == 0);
+
+ int dst = GlueRegCode(!dp_operation, vd, d);
+ int src = GlueRegCode(true, vm, m);
+
+ int val = get_sinteger_from_s_register(src);
+
+ if (dp_operation) {
+ if (unsigned_integer) {
+ set_d_register_from_double(dst,
+ static_cast<double>((uint32_t)val));
+ } else {
+ set_d_register_from_double(dst, static_cast<double>(val));
+ }
} else {
- UNIMPLEMENTED(); // Not used by V8.
+ if (unsigned_integer) {
+ set_s_register_from_float(dst,
+ static_cast<float>((uint32_t)val));
+ } else {
+ set_s_register_from_float(dst, static_cast<float>(val));
+ }
}
}
}
@@ -2055,10 +2190,33 @@
void Simulator::DecodeType6CoprocessorIns(Instr* instr) {
ASSERT((instr->TypeField() == 6));
- if (instr->CoprocessorField() != 0xB) {
- UNIMPLEMENTED(); // Not used by V8.
- } else {
+ if (instr->CoprocessorField() == 0xA) {
switch (instr->OpcodeField()) {
+ case 0x8:
+ case 0xC: { // Load and store float to memory.
+ int rn = instr->RnField();
+ int vd = instr->VdField();
+ int offset = instr->Immed8Field();
+ if (!instr->HasU()) {
+ offset = -offset;
+ }
+
+ int32_t address = get_register(rn) + 4 * offset;
+ if (instr->HasL()) {
+ // Load double from memory: vldr.
+ set_s_register_from_sinteger(vd, ReadW(address, instr));
+ } else {
+ // Store double to memory: vstr.
+ WriteW(address, get_sinteger_from_s_register(vd), instr);
+ }
+ break;
+ }
+ default:
+ UNIMPLEMENTED(); // Not used by V8.
+ break;
+ }
+ } else if (instr->CoprocessorField() == 0xB) {
+ switch (instr->OpcodeField()) {
case 0x2:
// Load and store double to two GP registers
if (instr->Bits(7, 4) != 0x1) {
@@ -2106,6 +2264,8 @@
UNIMPLEMENTED(); // Not used by V8.
break;
}
+ } else {
+ UNIMPLEMENTED(); // Not used by V8.
}
}
« src/arm/ic-arm.cc ('K') | « src/arm/simulator-arm.h ('k') | src/globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698