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

Unified Diff: runtime/vm/intermediate_language_arm.cc

Issue 19978004: Implements Float32x4 and Uint32x4 instructions for ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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 | « runtime/vm/assembler_arm.cc ('k') | tests/lib/lib.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language_arm.cc
===================================================================
--- runtime/vm/intermediate_language_arm.cc (revision 25352)
+++ runtime/vm/intermediate_language_arm.cc (working copy)
@@ -2934,9 +2934,7 @@
case Token::kADD: __ vaddqs(result, left, right); break;
case Token::kSUB: __ vsubqs(result, left, right); break;
case Token::kMUL: __ vmulqs(result, left, right); break;
- // TODO(zra): Two options for division. Either use vdiv piecewise, or do
- // vrecpeqs followed by vmulqs.
- case Token::kDIV: UNIMPLEMENTED(); break;
+ case Token::kDIV: __ Vdivqs(result, left, right); break;
default: UNREACHABLE();
}
}
@@ -2947,7 +2945,7 @@
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- // Low (< Q7) Q registers are needed for the vcvtds instruction.
+ // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions.
summary->set_in(0, Location::FpuRegisterLocation(Q5));
summary->set_out(Location::FpuRegisterLocation(Q6));
return summary;
@@ -2958,13 +2956,20 @@
QRegister value = locs()->in(0).fpu_reg();
QRegister result = locs()->out().fpu_reg();
DRegister dresult0 = EvenDRegisterOf(result);
+ DRegister dresult1 = OddDRegisterOf(result);
SRegister sresult0 = EvenSRegisterOf(dresult0);
+ SRegister sresult1 = OddSRegisterOf(dresult0);
+ SRegister sresult2 = EvenSRegisterOf(dresult1);
+ SRegister sresult3 = OddSRegisterOf(dresult1);
DRegister dvalue0 = EvenDRegisterOf(value);
DRegister dvalue1 = OddDRegisterOf(value);
- // For these cases the vdup instruction requires fewer
- // instructions. For arbitrary shuffles, vtbl will be needed.
+ DRegister dtemp0 = DTMP;
+ DRegister dtemp1 = OddDRegisterOf(QTMP);
+
+ // For some cases the vdup instruction requires fewer
+ // instructions. For arbitrary shuffles, use vtbl.
switch (op_kind()) {
case MethodRecognizer::kFloat32x4ShuffleX:
__ vdup(kWord, result, dvalue0, 0);
@@ -2992,8 +2997,18 @@
} else if (mask_ == 0xFF) {
__ vdup(kWord, result, dvalue1, 1);
} else {
- // TODO(zra): Implement other shuffles.
- UNIMPLEMENTED();
+ SRegister svalues[4];
+
+ svalues[0] = EvenSRegisterOf(dtemp0);
+ svalues[1] = OddSRegisterOf(dtemp0);
+ svalues[2] = EvenSRegisterOf(dtemp1);
+ svalues[3] = OddSRegisterOf(dtemp1);
+
+ __ vmovq(QTMP, value);
+ __ vmovs(sresult0, svalues[mask_ & 0x3]);
+ __ vmovs(sresult1, svalues[(mask_ >> 2) & 0x3]);
+ __ vmovs(sresult2, svalues[(mask_ >> 4) & 0x3]);
+ __ vmovs(sresult3, svalues[(mask_ >> 6) & 0x3]);
}
break;
default: UNREACHABLE();
@@ -3120,57 +3135,140 @@
LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister right = locs()->in(1).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4Min:
+ __ vminqs(result, left, right);
+ break;
+ case MethodRecognizer::kFloat32x4Max:
+ __ vmaxqs(result, left, right);
+ break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Float32x4SqrtInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ summary->set_temp(0, Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4Sqrt:
+ __ Vsqrtqs(result, left);
+ break;
+ case MethodRecognizer::kFloat32x4Reciprocal:
+ __ Vreciprocalqs(result, left);
+ break;
+ case MethodRecognizer::kFloat32x4ReciprocalSqrt:
+ __ VreciprocalSqrtqs(result, left);
+ break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Float32x4ScaleInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister right = locs()->in(1).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4Scale:
+ __ vcvtsd(STMP, EvenDRegisterOf(left));
+ __ vdup(kWord, result, DTMP, 0);
+ __ vmulqs(result, result, right);
+ break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4Negate:
+ __ vnegqs(result, left);
+ break;
+ case MethodRecognizer::kFloat32x4Absolute:
+ __ vabsqs(result, left);
+ break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Float32x4ClampInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 3;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_in(2, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister lower = locs()->in(1).fpu_reg();
+ QRegister upper = locs()->in(2).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+ __ vminqs(result, left, upper);
+ __ vmaxqs(result, result, lower);
}
@@ -3223,24 +3321,70 @@
LocationSummary* Float32x4ToUint32x4Instr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ToUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister value = locs()->in(0).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ if (value != result) {
+ __ vmovq(result, value);
+ }
}
LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 4;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RequiresRegister());
+ summary->set_in(2, Location::RequiresRegister());
+ summary->set_in(3, Location::RequiresRegister());
+ summary->set_temp(0, Location::RequiresRegister());
+ // Low (< 7) Q register needed for the vmovsr instruction.
+ summary->set_out(Location::FpuRegisterLocation(Q6));
+ return summary;
}
void Uint32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register v0 = locs()->in(0).reg();
+ Register v1 = locs()->in(1).reg();
+ Register v2 = locs()->in(2).reg();
+ Register v3 = locs()->in(3).reg();
+ Register temp = locs()->temp(0).reg();
+ QRegister result = locs()->out().fpu_reg();
+ DRegister dresult0 = EvenDRegisterOf(result);
+ DRegister dresult1 = OddDRegisterOf(result);
+ SRegister sresult0 = EvenSRegisterOf(dresult0);
+ SRegister sresult1 = OddSRegisterOf(dresult0);
+ SRegister sresult2 = EvenSRegisterOf(dresult1);
+ SRegister sresult3 = OddSRegisterOf(dresult1);
+
+ __ veorq(result, result, result);
+ __ LoadImmediate(temp, 0xffffffff);
+
+ __ CompareObject(v0, Bool::True());
+ __ vmovsr(sresult0, temp, EQ);
+
+ __ CompareObject(v1, Bool::True());
+ __ vmovsr(sresult1, temp, EQ);
+
+ __ CompareObject(v2, Bool::True());
+ __ vmovsr(sresult2, temp, EQ);
+
+ __ CompareObject(v3, Bool::True());
+ __ vmovsr(sresult3, temp, EQ);
}
@@ -3290,46 +3434,142 @@
LocationSummary* Uint32x4SelectInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 3;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_in(2, Location::RequiresFpuRegister());
+ summary->set_temp(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Uint32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister mask = locs()->in(0).fpu_reg();
+ QRegister trueValue = locs()->in(1).fpu_reg();
+ QRegister falseValue = locs()->in(2).fpu_reg();
+ QRegister out = locs()->out().fpu_reg();
+ QRegister temp = locs()->temp(0).fpu_reg();
+
+ // Copy mask.
+ __ vmovq(temp, mask);
+ // Invert it.
+ __ veorq(QTMP, QTMP, QTMP); // QTMP <- 0.
+ __ vornq(temp, QTMP, temp); // temp <- ~temp.
+ // mask = mask & trueValue.
+ __ vandq(mask, mask, trueValue);
+ // temp = temp & falseValue.
+ __ vandq(temp, temp, falseValue);
+ // out = mask | temp.
+ __ vorrq(out, mask, temp);
}
LocationSummary* Uint32x4SetFlagInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresRegister());
+ // Low (< 7) Q register needed for the vmovsr instruction.
+ summary->set_out(Location::FpuRegisterLocation(Q6));
+ return summary;
}
void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister mask = locs()->in(0).fpu_reg();
+ Register flag = locs()->in(1).reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ DRegister dresult0 = EvenDRegisterOf(result);
+ DRegister dresult1 = OddDRegisterOf(result);
+ SRegister sresult0 = EvenSRegisterOf(dresult0);
+ SRegister sresult1 = OddSRegisterOf(dresult0);
+ SRegister sresult2 = EvenSRegisterOf(dresult1);
+ SRegister sresult3 = OddSRegisterOf(dresult1);
+
+ if (result != mask) {
+ __ vmovq(result, mask);
+ }
+
+ __ CompareObject(flag, Bool::True());
+ __ LoadImmediate(TMP, 0xffffffff, EQ);
+ __ LoadImmediate(TMP, 0, NE);
+ switch (op_kind()) {
+ case MethodRecognizer::kUint32x4WithFlagX:
+ __ vmovsr(sresult0, TMP);
+ break;
+ case MethodRecognizer::kUint32x4WithFlagY:
+ __ vmovsr(sresult1, TMP);
+ break;
+ case MethodRecognizer::kUint32x4WithFlagZ:
+ __ vmovsr(sresult2, TMP);
+ break;
+ case MethodRecognizer::kUint32x4WithFlagW:
+ __ vmovsr(sresult3, TMP);
+ break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Uint32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister value = locs()->in(0).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ if (value != result) {
+ __ vmovq(result, value);
+ }
}
LocationSummary* BinaryUint32x4OpInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void BinaryUint32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister right = locs()->in(1).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+ switch (op_kind()) {
+ case Token::kBIT_AND: {
+ __ vandq(result, left, right);
+ break;
+ }
+ case Token::kBIT_OR: {
+ __ vorrq(result, left, right);
+ break;
+ }
+ case Token::kBIT_XOR: {
+ __ veorq(result, left, right);
+ break;
+ }
+ default: UNREACHABLE();
+ }
}
« no previous file with comments | « runtime/vm/assembler_arm.cc ('k') | tests/lib/lib.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698