summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/jni/quick/arm/calling_convention_arm.cc16
-rw-r--r--compiler/jni/quick/arm/calling_convention_arm.h4
-rw-r--r--compiler/jni/quick/arm64/calling_convention_arm64.cc17
-rw-r--r--compiler/utils/arm/assembler_arm.cc40
-rw-r--r--compiler/utils/arm64/assembler_arm64.cc37
-rw-r--r--compiler/utils/arm64/constants_arm64.h2
6 files changed, 100 insertions, 16 deletions
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index 669c3bb716..d3690b271f 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -31,6 +31,10 @@ static const SRegister kHFSArgumentRegisters[] = {
S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15
};
+static const SRegister kHFSCalleeSaveRegisters[] = {
+ S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31
+};
+
static const DRegister kHFDArgumentRegisters[] = {
D0, D1, D2, D3, D4, D5, D6, D7
};
@@ -226,6 +230,10 @@ ArmJniCallingConvention::ArmJniCallingConvention(bool is_static, bool is_synchro
callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R8));
callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R10));
callee_save_regs_.push_back(ArmManagedRegister::FromCoreRegister(R11));
+
+ for (size_t i = 0; i < arraysize(kHFSCalleeSaveRegisters); ++i) {
+ callee_save_regs_.push_back(ArmManagedRegister::FromSRegister(kHFSCalleeSaveRegisters[i]));
+ }
}
uint32_t ArmJniCallingConvention::CoreSpillMask() const {
@@ -235,6 +243,14 @@ uint32_t ArmJniCallingConvention::CoreSpillMask() const {
return result;
}
+uint32_t ArmJniCallingConvention::FpSpillMask() const {
+ uint32_t result = 0;
+ for (size_t i = 0; i < arraysize(kHFSCalleeSaveRegisters); ++i) {
+ result |= (1 << kHFSCalleeSaveRegisters[i]);
+ }
+ return result;
+}
+
ManagedRegister ArmJniCallingConvention::ReturnScratchRegister() const {
return ArmManagedRegister::FromCoreRegister(R2);
}
diff --git a/compiler/jni/quick/arm/calling_convention_arm.h b/compiler/jni/quick/arm/calling_convention_arm.h
index 604ce1c821..dbecb8eb95 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.h
+++ b/compiler/jni/quick/arm/calling_convention_arm.h
@@ -63,9 +63,7 @@ class ArmJniCallingConvention FINAL : public JniCallingConvention {
}
ManagedRegister ReturnScratchRegister() const OVERRIDE;
uint32_t CoreSpillMask() const OVERRIDE;
- uint32_t FpSpillMask() const OVERRIDE {
- return 0; // Floats aren't spilled in JNI down call
- }
+ uint32_t FpSpillMask() const OVERRIDE;
bool IsCurrentParamInRegister() OVERRIDE;
bool IsCurrentParamOnStack() OVERRIDE;
ManagedRegister CurrentParamRegister() OVERRIDE;
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index b9c81787f0..05eb80a51a 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -38,6 +38,10 @@ static const SRegister kSArgumentRegisters[] = {
S0, S1, S2, S3, S4, S5, S6, S7
};
+static const DRegister kDCalleeSaveRegisters[] = {
+ D8, D9, D10, D11, D12, D13, D14, D15
+};
+
// Calling convention
ManagedRegister Arm64ManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
return Arm64ManagedRegister::FromXRegister(X20); // saved on entry restored on exit
@@ -166,6 +170,10 @@ Arm64JniCallingConvention::Arm64JniCallingConvention(bool is_static, bool is_syn
callee_save_regs_.push_back(Arm64ManagedRegister::FromXRegister(X28));
callee_save_regs_.push_back(Arm64ManagedRegister::FromXRegister(X29));
callee_save_regs_.push_back(Arm64ManagedRegister::FromXRegister(X30));
+
+ for (size_t i = 0; i < arraysize(kDCalleeSaveRegisters); ++i) {
+ callee_save_regs_.push_back(Arm64ManagedRegister::FromDRegister(kDCalleeSaveRegisters[i]));
+ }
}
uint32_t Arm64JniCallingConvention::CoreSpillMask() const {
@@ -184,10 +192,11 @@ uint32_t Arm64JniCallingConvention::CoreSpillMask() const {
}
uint32_t Arm64JniCallingConvention::FpSpillMask() const {
- // Compute spill mask to agree with callee saves initialized in the constructor
- // Note: All callee-save fp registers will be preserved by aapcs64. And they are not used
- // in the jni method.
- return 0;
+ uint32_t result = 0;
+ for (size_t i = 0; i < arraysize(kDCalleeSaveRegisters); ++i) {
+ result |= (1 << kDCalleeSaveRegisters[i]);
+ }
+ return result;
}
ManagedRegister Arm64JniCallingConvention::ReturnScratchRegister() const {
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index a52e6eb30f..a02191bc13 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -385,12 +385,24 @@ void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
// Push callee saves and link register.
RegList push_list = 1 << LR;
size_t pushed_values = 1;
+ int32_t min_s = kNumberOfSRegisters;
+ int32_t max_s = -1;
for (size_t i = 0; i < callee_save_regs.size(); i++) {
- Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
- push_list |= 1 << reg;
- pushed_values++;
+ if (callee_save_regs.at(i).AsArm().IsCoreRegister()) {
+ Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
+ push_list |= 1 << reg;
+ pushed_values++;
+ } else {
+ CHECK(callee_save_regs.at(i).AsArm().IsSRegister());
+ min_s = std::min(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), min_s);
+ max_s = std::max(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), max_s);
+ }
}
PushList(push_list);
+ if (max_s != -1) {
+ pushed_values += 1 + max_s - min_s;
+ vpushs(static_cast<SRegister>(min_s), 1 + max_s - min_s);
+ }
// Increase frame to required size.
CHECK_GT(frame_size, pushed_values * kFramePointerSize); // Must at least have space for Method*.
@@ -427,10 +439,22 @@ void ArmAssembler::RemoveFrame(size_t frame_size,
// Compute callee saves to pop and PC.
RegList pop_list = 1 << PC;
size_t pop_values = 1;
+ int32_t min_s = kNumberOfSRegisters;
+ int32_t max_s = -1;
for (size_t i = 0; i < callee_save_regs.size(); i++) {
- Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
- pop_list |= 1 << reg;
- pop_values++;
+ if (callee_save_regs.at(i).AsArm().IsCoreRegister()) {
+ Register reg = callee_save_regs.at(i).AsArm().AsCoreRegister();
+ pop_list |= 1 << reg;
+ pop_values++;
+ } else {
+ CHECK(callee_save_regs.at(i).AsArm().IsSRegister());
+ min_s = std::min(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), min_s);
+ max_s = std::max(static_cast<int>(callee_save_regs.at(i).AsArm().AsSRegister()), max_s);
+ }
+ }
+
+ if (max_s != -1) {
+ pop_values += 1 + max_s - min_s;
}
// Decrease frame to start of callee saves.
@@ -438,6 +462,10 @@ void ArmAssembler::RemoveFrame(size_t frame_size,
size_t adjust = frame_size - (pop_values * kFramePointerSize);
DecreaseFrameSize(adjust);
+ if (max_s != -1) {
+ vpops(static_cast<SRegister>(min_s), 1 + max_s - min_s);
+ }
+
// Pop callee saves and PC.
PopList(pop_list);
}
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index 21014c8bba..58c73674da 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -639,6 +639,7 @@ void Arm64Assembler::EmitExceptionPoll(Arm64Exception *exception) {
}
constexpr size_t kFramePointerSize = 8;
+constexpr unsigned int kJniRefSpillRegsSize = 11 + 8;
void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
const std::vector<ManagedRegister>& callee_save_regs,
@@ -648,7 +649,7 @@ void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
// TODO: *create APCS FP - end of FP chain;
// *add support for saving a different set of callee regs.
- // For now we check that the size of callee regs vector is 11.
+ // For now we check that the size of callee regs vector is 11 core registers and 8 fp registers.
CHECK_EQ(callee_save_regs.size(), kJniRefSpillRegsSize);
// Increase frame to required size - must be at least space to push StackReference<Method>.
CHECK_GT(frame_size, kJniRefSpillRegsSize * kFramePointerSize);
@@ -682,6 +683,23 @@ void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
reg_offset -= 8;
StoreToOffset(X20, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D15, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D14, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D13, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D12, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D11, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D10, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D9, SP, reg_offset);
+ reg_offset -= 8;
+ StoreDToOffset(D8, SP, reg_offset);
+
// Move TR(Caller saved) to ETR(Callee saved). The original (ETR)X21 has been saved on stack.
// This way we make sure that TR is not trashed by native code.
___ Mov(reg_x(ETR), reg_x(TR));
@@ -753,6 +771,23 @@ void Arm64Assembler::RemoveFrame(size_t frame_size, const std::vector<ManagedReg
reg_offset -= 8;
LoadFromOffset(X20, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D15, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D14, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D13, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D12, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D11, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D10, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D9, SP, reg_offset);
+ reg_offset -= 8;
+ LoadDFromOffset(D8, SP, reg_offset);
+
// Decrease frame size to start of callee saved regs.
DecreaseFrameSize(frame_size);
diff --git a/compiler/utils/arm64/constants_arm64.h b/compiler/utils/arm64/constants_arm64.h
index ffb54d322f..01e8be9de6 100644
--- a/compiler/utils/arm64/constants_arm64.h
+++ b/compiler/utils/arm64/constants_arm64.h
@@ -29,8 +29,6 @@
namespace art {
namespace arm64 {
-constexpr unsigned int kJniRefSpillRegsSize = 11;
-
constexpr size_t kArm64BaseBufferSize = 4096;
} // namespace arm64