diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/jni/quick/arm/calling_convention_arm.cc | 16 | ||||
-rw-r--r-- | compiler/jni/quick/arm/calling_convention_arm.h | 4 | ||||
-rw-r--r-- | compiler/jni/quick/arm64/calling_convention_arm64.cc | 17 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm.cc | 40 | ||||
-rw-r--r-- | compiler/utils/arm64/assembler_arm64.cc | 37 | ||||
-rw-r--r-- | compiler/utils/arm64/constants_arm64.h | 2 |
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 |