calling_convention.GetRegisterPairAt(index));
return Location::RegisterPairLocation(pair.AsRegisterPairLow(), pair.AsRegisterPairHigh());
} else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
- return Location::QuickParameter(stack_index);
+ return Location::QuickParameter(index, stack_index);
} else {
return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index));
}
} else if (source.IsFpuRegister()) {
UNIMPLEMENTED(FATAL);
} else if (source.IsQuickParameter()) {
- uint32_t argument_index = source.GetQuickParameterIndex();
+ uint16_t register_index = source.GetQuickParameterRegisterIndex();
+ uint16_t stack_index = source.GetQuickParameterStackIndex();
InvokeDexCallingConvention calling_convention;
__ Mov(destination.AsRegisterPairLow<Register>(),
- calling_convention.GetRegisterAt(argument_index));
+ calling_convention.GetRegisterAt(register_index));
__ LoadFromOffset(kLoadWord, destination.AsRegisterPairHigh<Register>(),
- SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize());
+ SP, calling_convention.GetStackOffsetOf(stack_index + 1) + GetFrameSize());
} else {
DCHECK(source.IsDoubleStackSlot());
if (destination.AsRegisterPairLow<Register>() == R1) {
}
} else if (destination.IsQuickParameter()) {
InvokeDexCallingConvention calling_convention;
- uint32_t argument_index = destination.GetQuickParameterIndex();
+ uint16_t register_index = destination.GetQuickParameterRegisterIndex();
+ uint16_t stack_index = destination.GetQuickParameterStackIndex();
if (source.IsRegisterPair()) {
- __ Mov(calling_convention.GetRegisterAt(argument_index),
+ __ Mov(calling_convention.GetRegisterAt(register_index),
source.AsRegisterPairLow<Register>());
__ StoreToOffset(kStoreWord, source.AsRegisterPairHigh<Register>(),
- SP, calling_convention.GetStackOffsetOf(argument_index + 1));
+ SP, calling_convention.GetStackOffsetOf(stack_index + 1));
} else if (source.IsFpuRegister()) {
UNIMPLEMENTED(FATAL);
} else {
DCHECK(source.IsDoubleStackSlot());
__ LoadFromOffset(
- kLoadWord, calling_convention.GetRegisterAt(argument_index), SP, source.GetStackIndex());
+ kLoadWord, calling_convention.GetRegisterAt(register_index), SP, source.GetStackIndex());
__ LoadFromOffset(kLoadWord, R0, SP, source.GetHighStackIndex(kArmWordSize));
- __ StoreToOffset(kStoreWord, R0, SP, calling_convention.GetStackOffsetOf(argument_index + 1));
+ __ StoreToOffset(kStoreWord, R0, SP, calling_convention.GetStackOffsetOf(stack_index + 1));
}
} else {
DCHECK(destination.IsDoubleStackSlot());
}
} else if (source.IsQuickParameter()) {
InvokeDexCallingConvention calling_convention;
- uint32_t argument_index = source.GetQuickParameterIndex();
- __ StoreToOffset(kStoreWord, calling_convention.GetRegisterAt(argument_index),
+ uint16_t register_index = source.GetQuickParameterRegisterIndex();
+ uint16_t stack_index = source.GetQuickParameterStackIndex();
+ __ StoreToOffset(kStoreWord, calling_convention.GetRegisterAt(register_index),
SP, destination.GetStackIndex());
__ LoadFromOffset(kLoadWord, R0,
- SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize());
+ SP, calling_convention.GetStackOffsetOf(stack_index + 1) + GetFrameSize());
__ StoreToOffset(kStoreWord, R0, SP, destination.GetHighStackIndex(kArmWordSize));
} else if (source.IsFpuRegisterPair()) {
__ StoreDToOffset(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
calling_convention.GetRegisterPairAt(index));
return Location::RegisterPairLocation(pair.AsRegisterPairLow(), pair.AsRegisterPairHigh());
} else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
- return Location::QuickParameter(index);
+ // On X86, the register index and stack index of a quick parameter is the same, since
+ // we are passing floating pointer values in core registers.
+ return Location::QuickParameter(index, index);
} else {
return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
}
} else if (source.IsFpuRegister()) {
LOG(FATAL) << "Unimplemented";
} else if (source.IsQuickParameter()) {
- uint32_t argument_index = source.GetQuickParameterIndex();
+ uint16_t register_index = source.GetQuickParameterRegisterIndex();
+ uint16_t stack_index = source.GetQuickParameterStackIndex();
InvokeDexCallingConvention calling_convention;
__ movl(destination.AsRegisterPairLow<Register>(),
- calling_convention.GetRegisterAt(argument_index));
+ calling_convention.GetRegisterAt(register_index));
__ movl(destination.AsRegisterPairHigh<Register>(), Address(ESP,
- calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+ calling_convention.GetStackOffsetOf(stack_index + 1) + GetFrameSize()));
} else {
DCHECK(source.IsDoubleStackSlot());
__ movl(destination.AsRegisterPairLow<Register>(), Address(ESP, source.GetStackIndex()));
}
} else if (destination.IsQuickParameter()) {
InvokeDexCallingConvention calling_convention;
- uint32_t argument_index = destination.GetQuickParameterIndex();
+ uint16_t register_index = destination.GetQuickParameterRegisterIndex();
+ uint16_t stack_index = destination.GetQuickParameterStackIndex();
if (source.IsRegister()) {
- __ movl(calling_convention.GetRegisterAt(argument_index), source.AsRegisterPairLow<Register>());
- __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
+ __ movl(calling_convention.GetRegisterAt(register_index), source.AsRegisterPairLow<Register>());
+ __ movl(Address(ESP, calling_convention.GetStackOffsetOf(stack_index + 1)),
source.AsRegisterPairHigh<Register>());
} else if (source.IsFpuRegister()) {
LOG(FATAL) << "Unimplemented";
} else {
DCHECK(source.IsDoubleStackSlot());
- __ movl(calling_convention.GetRegisterAt(argument_index),
+ __ movl(calling_convention.GetRegisterAt(register_index),
Address(ESP, source.GetStackIndex()));
__ pushl(Address(ESP, source.GetHighStackIndex(kX86WordSize)));
- __ popl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)));
+ __ popl(Address(ESP, calling_convention.GetStackOffsetOf(stack_index + 1)));
}
} else if (destination.IsFpuRegister()) {
if (source.IsDoubleStackSlot()) {
source.AsRegisterPairHigh<Register>());
} else if (source.IsQuickParameter()) {
InvokeDexCallingConvention calling_convention;
- uint32_t argument_index = source.GetQuickParameterIndex();
+ uint16_t register_index = source.GetQuickParameterRegisterIndex();
+ uint16_t stack_index = source.GetQuickParameterStackIndex();
__ movl(Address(ESP, destination.GetStackIndex()),
- calling_convention.GetRegisterAt(argument_index));
- DCHECK_EQ(calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize(),
+ calling_convention.GetRegisterAt(register_index));
+ DCHECK_EQ(calling_convention.GetStackOffsetOf(stack_index + 1) + GetFrameSize(),
static_cast<size_t>(destination.GetHighStackIndex(kX86WordSize)));
} else if (source.IsFpuRegister()) {
__ movsd(Address(ESP, destination.GetStackIndex()), source.As<XmmRegister>());
return GetPayload() - kStackIndexBias + word_size;
}
- static Location QuickParameter(uint32_t parameter_index) {
- return Location(kQuickParameter, parameter_index);
+ static Location QuickParameter(uint16_t register_index, uint16_t stack_index) {
+ return Location(kQuickParameter, register_index << 16 | stack_index);
}
- uint32_t GetQuickParameterIndex() const {
+ uint32_t GetQuickParameterRegisterIndex() const {
DCHECK(IsQuickParameter());
- return GetPayload();
+ return GetPayload() >> 16;
+ }
+
+ uint32_t GetQuickParameterStackIndex() const {
+ DCHECK(IsQuickParameter());
+ return GetPayload() & 0xFFFF;
}
bool IsQuickParameter() const {
--- /dev/null
+Regression test for the long parameter passed both in stack and register
+on 32bits architectures. The move to hard float ABI makes it so that the
+register index does not necessarily match the stack index anymore.
--- /dev/null
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ if ($opt$TestCallee(1.0, 2.0, 1L, 2L) != 1L) {
+ throw new Error("Unexpected result");
+ }
+ if ($opt$TestCaller() != 1L) {
+ throw new Error("Unexpected result");
+ }
+ }
+
+ public static long $opt$TestCallee(double a, double b, long c, long d) {
+ return d - c;
+ }
+
+ public static long $opt$TestCaller() {
+ return $opt$TestCallee(1.0, 2.0, 1L, 2L);
+ }
+}