summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_arm.cc
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2014-11-17 11:55:59 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-11-17 11:55:59 +0000
commit1c18d5d0141ffa76b0838fb99615186dcbefc50e (patch)
tree3789d51fabf7fa297575d6ce485a03e16faa1903 /compiler/optimizing/code_generator_arm.cc
parent610b21cc7f62c61fcb7d88c1ffcc74bfa9ca5ef8 (diff)
parentbacfec30ee9f2f6fdfd190f11b105b609938efca (diff)
downloadart-1c18d5d0141ffa76b0838fb99615186dcbefc50e.tar.gz
art-1c18d5d0141ffa76b0838fb99615186dcbefc50e.tar.bz2
art-1c18d5d0141ffa76b0838fb99615186dcbefc50e.zip
Merge "[optimizing compiler] Add REM_INT, REM_LONG"
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r--compiler/optimizing/code_generator_arm.cc80
1 files changed, 80 insertions, 0 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c17142d7c9..746d4afeec 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1873,6 +1873,86 @@ void InstructionCodeGeneratorARM::VisitDiv(HDiv* div) {
}
}
+void LocationsBuilderARM::VisitRem(HRem* rem) {
+ LocationSummary::CallKind call_kind = rem->GetResultType() == Primitive::kPrimLong
+ ? LocationSummary::kCall
+ : LocationSummary::kNoCall;
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind);
+
+ switch (rem->GetResultType()) {
+ case Primitive::kPrimInt: {
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ locations->AddTemp(Location::RequiresRegister());
+ break;
+ }
+ case Primitive::kPrimLong: {
+ InvokeRuntimeCallingConvention calling_convention;
+ locations->SetInAt(0, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
+ locations->SetInAt(1, Location::RegisterPairLocation(
+ calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3)));
+ // The runtime helper puts the output in R2,R3.
+ locations->SetOut(Location::RegisterPairLocation(R2, R3));
+ break;
+ }
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType();
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected rem type " << rem->GetResultType();
+ }
+}
+
+void InstructionCodeGeneratorARM::VisitRem(HRem* rem) {
+ LocationSummary* locations = rem->GetLocations();
+ Location out = locations->Out();
+ Location first = locations->InAt(0);
+ Location second = locations->InAt(1);
+
+ switch (rem->GetResultType()) {
+ case Primitive::kPrimInt: {
+ Register reg1 = first.As<Register>();
+ Register reg2 = second.As<Register>();
+ Register temp = locations->GetTemp(0).As<Register>();
+
+ // temp = reg1 / reg2 (integer division)
+ // temp = temp * reg2
+ // dest = reg1 - temp
+ __ sdiv(temp, reg1, reg2);
+ __ mul(temp, temp, reg2);
+ __ sub(out.As<Register>(), reg1, ShifterOperand(temp));
+ break;
+ }
+
+ case Primitive::kPrimLong: {
+ InvokeRuntimeCallingConvention calling_convention;
+ DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegisterPairLow<Register>());
+ DCHECK_EQ(calling_convention.GetRegisterAt(1), first.AsRegisterPairHigh<Register>());
+ DCHECK_EQ(calling_convention.GetRegisterAt(2), second.AsRegisterPairLow<Register>());
+ DCHECK_EQ(calling_convention.GetRegisterAt(3), second.AsRegisterPairHigh<Register>());
+ DCHECK_EQ(R2, out.AsRegisterPairLow<Register>());
+ DCHECK_EQ(R3, out.AsRegisterPairHigh<Register>());
+
+ codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLmod), rem, rem->GetDexPc());
+ break;
+ }
+
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble: {
+ LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType();
+ break;
+ }
+
+ default:
+ LOG(FATAL) << "Unexpected rem type " << rem->GetResultType();
+ }
+}
+
void LocationsBuilderARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);