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

Unified Diff: runtime/vm/intermediate_language_arm.cc

Issue 15899010: Implement a few more features on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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/flow_graph_compiler_arm.cc ('k') | runtime/vm/intrinsifier_arm.cc » ('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 23368)
+++ runtime/vm/intermediate_language_arm.cc (working copy)
@@ -1135,7 +1135,33 @@
if ((representation() == kUnboxedDouble) ||
(representation() == kUnboxedMint) ||
(representation() == kUnboxedFloat32x4)) {
- UNIMPLEMENTED();
+ DRegister result = locs()->out().fpu_reg();
+ switch (class_id()) {
+ case kTypedDataInt32ArrayCid:
+ UNIMPLEMENTED();
+ break;
+ case kTypedDataUint32ArrayCid:
+ UNIMPLEMENTED();
+ break;
+ case kTypedDataFloat32ArrayCid:
+ // Load single precision float and promote to double.
+ // vldrs does not support indexed addressing.
+ __ add(index.reg(), index.reg(), ShifterOperand(array));
+ element_address = Address(index.reg(), 0);
+ __ vldrs(S0, element_address);
+ __ vcvtds(result, S0);
+ break;
+ case kTypedDataFloat64ArrayCid:
+ // vldrd does not support indexed addressing.
+ __ add(index.reg(), index.reg(), ShifterOperand(array));
+ element_address = Address(index.reg(), 0);
+ __ vldrd(result, element_address);
+ break;
+ case kTypedDataFloat32x4ArrayCid:
+ UNIMPLEMENTED();
+ break;
+ }
+ return;
}
Register result = locs()->out().reg();
@@ -2057,19 +2083,31 @@
LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
if (op_kind() == Token::kTRUNCDIV) {
- UNIMPLEMENTED();
- return NULL;
- } else {
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- summary->set_in(0, Location::RequiresRegister());
- summary->set_in(1, Location::RegisterOrSmiConstant(right()));
- // We make use of 3-operand instructions by not requiring result register
- // to be identical to first input register as on Intel.
- summary->set_out(Location::RequiresRegister());
+ if (RightIsPowerOfTwoConstant()) {
+ summary->set_in(0, Location::RequiresRegister());
+ ConstantInstr* right_constant = right()->definition()->AsConstant();
+ summary->set_in(1, Location::Constant(right_constant->value()));
+ summary->set_out(Location::RequiresRegister());
+ } else {
+ // Both inputs must be writable because they will be untagged.
+ summary->set_in(0, Location::WritableRegister());
+ summary->set_in(1, Location::WritableRegister());
+ summary->set_out(Location::RequiresRegister());
+ }
return summary;
}
+ const intptr_t kNumTemps = 0;
zra 2013/05/29 22:54:07 Could you have just one kNumTemps and one summary
regis 2013/05/29 23:10:14 Done.
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+ // We make use of 3-operand instructions by not requiring result register
+ // to be identical to first input register as on Intel.
+ summary->set_out(Location::RequiresRegister());
+ return summary;
}
@@ -2130,7 +2168,31 @@
break;
}
case Token::kTRUNCDIV: {
- UNIMPLEMENTED();
+ const intptr_t value = Smi::Cast(constant).Value();
+ if (value == 1) {
+ // Do nothing.
+ break;
+ } else if (value == -1) {
+ // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+ // case we cannot negate the result.
+ __ CompareImmediate(left, 0x80000000);
+ __ b(deopt, EQ);
+ __ rsb(result, left, ShifterOperand(0));
+ break;
+ }
+ ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
+ const intptr_t shift_count =
+ Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
+ ASSERT(kSmiTagSize == 1);
+ __ mov(IP, ShifterOperand(left, ASR, 31));
+ ASSERT(shift_count > 1); // 1, -1 case handled above.
+ __ add(left, left, ShifterOperand(IP, LSR, 32 - shift_count));
+ ASSERT(shift_count > 0);
+ __ mov(result, ShifterOperand(left, ASR, shift_count));
+ if (value < 0) {
+ __ rsb(result, result, ShifterOperand(0));
+ }
+ __ SmiTag(result);
break;
}
case Token::kBIT_AND: {
@@ -2245,7 +2307,20 @@
break;
}
case Token::kTRUNCDIV: {
- UNIMPLEMENTED();
+ // Handle divide by zero in runtime.
+ __ cmp(right, ShifterOperand(0));
+ __ b(deopt, EQ);
+ __ SmiUntag(left);
+ __ SmiUntag(right);
+ if (!CPUFeatures::integer_division_supported()) {
+ UNIMPLEMENTED();
+ }
+ __ sdiv(result, left, right);
+ // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+ // case we cannot tag the result.
+ __ CompareImmediate(result, 0x40000000);
+ __ b(deopt, EQ);
+ __ SmiTag(result);
break;
}
case Token::kSHR: {
@@ -2278,35 +2353,142 @@
LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ intptr_t left_cid = left()->Type()->ToCid();
+ intptr_t right_cid = right()->Type()->ToCid();
+ ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RequiresRegister());
+ return summary;
}
void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
+ intptr_t left_cid = left()->Type()->ToCid();
+ intptr_t right_cid = right()->Type()->ToCid();
+ Register left = locs()->in(0).reg();
+ Register right = locs()->in(1).reg();
+ if (left_cid == kSmiCid) {
+ __ tst(right, ShifterOperand(kSmiTagMask));
+ } else if (right_cid == kSmiCid) {
+ __ tst(left, ShifterOperand(kSmiTagMask));
+ } else {
+ __ orr(IP, left, ShifterOperand(right));
+ __ tst(IP, ShifterOperand(kSmiTagMask));
+ }
+ __ b(deopt, EQ);
}
LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs,
+ kNumTemps,
+ LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresRegister());
+ return summary;
}
+class BoxDoubleSlowPath : public SlowPathCode {
+ public:
+ explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
+ : instruction_(instruction) { }
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Comment("BoxDoubleSlowPath");
+ __ Bind(entry_label());
+ const Class& double_class = compiler->double_class();
+ const Code& stub =
+ Code::Handle(StubCode::GetAllocationStubForClass(double_class));
+ const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
+
+ LocationSummary* locs = instruction_->locs();
+ locs->live_registers()->Remove(locs->out());
+
+ compiler->SaveLiveRegisters(locs);
+ compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position.
+ &label,
+ PcDescriptors::kOther,
+ locs);
+ __ MoveRegister(locs->out().reg(), R0);
+ compiler->RestoreLiveRegisters(locs);
+
+ __ b(exit_label());
+ }
+
+ private:
+ BoxDoubleInstr* instruction_;
+};
+
+
void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
+ compiler->AddSlowPathCode(slow_path);
+
+ Register out_reg = locs()->out().reg();
+ DRegister value = locs()->in(0).fpu_reg();
+
+ __ TryAllocate(compiler->double_class(),
+ slow_path->entry_label(),
+ out_reg);
+ __ Bind(slow_path->exit_label());
+ __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
}
LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
+ const bool needs_writable_input = (value_cid == kSmiCid);
+ const intptr_t kNumTemps = needs_temp ? 1 : 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, needs_writable_input
+ ? Location::WritableRegister()
+ : Location::RequiresRegister());
+ if (needs_temp) summary->set_temp(0, Location::RequiresRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const Register value = locs()->in(0).reg();
+ const DRegister result = locs()->out().fpu_reg();
+
+ if (value_cid == kDoubleCid) {
+ __ vldrd(result, FieldAddress(value, Double::value_offset()));
zra 2013/05/29 22:54:07 You can't use FieldAddress in vldrd, right?
regis 2013/05/29 23:10:14 Done.
+ } else if (value_cid == kSmiCid) {
+ __ SmiUntag(value); // Untag input before conversion.
+ __ vmovsr(S0, value);
zra 2013/05/29 22:54:07 I didn't check, but if there is a problem with reg
regis 2013/05/29 23:10:14 FpuTMP is set to D0 on ARM. So D0 will not be used
+ __ vcvtdi(result, S0);
+ } else {
+ Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
+ Register temp = locs()->temp(0).reg();
+ Label is_smi, done;
+ __ tst(value, ShifterOperand(kSmiTagMask));
+ __ b(&is_smi, EQ);
+ __ CompareClassId(value, kDoubleCid, temp);
+ __ b(deopt, NE);
+ __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
+ __ b(&done);
+ __ Bind(&is_smi);
+ // TODO(regis): Why do we preserve value here but not above?
+ __ mov(IP, ShifterOperand(value, ASR, 1)); // Copy and untag.
+ __ vmovsr(S0, IP);
+ __ vcvtdi(result, S0);
+ __ Bind(&done);
+ }
}
@@ -2355,13 +2537,28 @@
LocationSummary* BinaryDoubleOpInstr::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 BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ DRegister left = locs()->in(0).fpu_reg();
+ DRegister right = locs()->in(1).fpu_reg();
+ DRegister result = locs()->out().fpu_reg();
+ switch (op_kind()) {
+ case Token::kADD: __ vaddd(result, left, right); break;
+ case Token::kSUB: __ vsubd(result, left, right); break;
+ case Token::kMUL: __ vmuld(result, left, right); break;
+ case Token::kDIV: __ vdivd(result, left, right); break;
+ default: UNREACHABLE();
+ }
}
@@ -2585,13 +2782,37 @@
LocationSummary* UnarySmiOpInstr::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::RequiresRegister());
+ // We make use of 3-operand instructions by not requiring result register
+ // to be identical to first input register as on Intel.
+ summary->set_out(Location::RequiresRegister());
+ return summary;
}
void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Register value = locs()->in(0).reg();
+ Register result = locs()->out().reg();
+ switch (op_kind()) {
+ case Token::kNEGATE: {
+ Label* deopt = compiler->AddDeoptStub(deopt_id(),
+ kDeoptUnaryOp);
+ __ rsbs(result, value, ShifterOperand(0));
+ __ b(deopt, VS);
+ break;
+ }
+ case Token::kBIT_NOT:
+ __ mvn(result, ShifterOperand(value));
+ // Remove inverted smi-tag.
+ __ bic(result, result, ShifterOperand(kSmiTagMask));
+ break;
+ default:
+ UNREACHABLE();
+ }
}
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intrinsifier_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698