1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_OPTIMIZING_COMMON_ARM_H_ 18 #define ART_COMPILER_OPTIMIZING_COMMON_ARM_H_ 19 20 #include "instruction_simplifier_shared.h" 21 #include "debug/dwarf/register.h" 22 #include "locations.h" 23 #include "nodes.h" 24 #include "utils/arm/constants_arm.h" 25 26 // TODO(VIXL): Make VIXL compile with -Wshadow. 27 #pragma GCC diagnostic push 28 #pragma GCC diagnostic ignored "-Wshadow" 29 #include "aarch32/macro-assembler-aarch32.h" 30 #pragma GCC diagnostic pop 31 32 namespace art { 33 34 using helpers::HasShifterOperand; 35 36 namespace arm { 37 namespace helpers { 38 39 static_assert(vixl::aarch32::kSpCode == SP, "vixl::aarch32::kSpCode must equal ART's SP"); 40 41 inline dwarf::Reg DWARFReg(vixl::aarch32::Register reg) { 42 return dwarf::Reg::ArmCore(static_cast<int>(reg.GetCode())); 43 } 44 45 inline dwarf::Reg DWARFReg(vixl::aarch32::SRegister reg) { 46 return dwarf::Reg::ArmFp(static_cast<int>(reg.GetCode())); 47 } 48 49 inline vixl::aarch32::Register HighRegisterFrom(Location location) { 50 DCHECK(location.IsRegisterPair()) << location; 51 return vixl::aarch32::Register(location.AsRegisterPairHigh<vixl::aarch32::Register>()); 52 } 53 54 inline vixl::aarch32::DRegister HighDRegisterFrom(Location location) { 55 DCHECK(location.IsFpuRegisterPair()) << location; 56 return vixl::aarch32::DRegister(location.AsFpuRegisterPairHigh<vixl::aarch32::DRegister>()); 57 } 58 59 inline vixl::aarch32::Register LowRegisterFrom(Location location) { 60 DCHECK(location.IsRegisterPair()) << location; 61 return vixl::aarch32::Register(location.AsRegisterPairLow<vixl::aarch32::Register>()); 62 } 63 64 inline vixl::aarch32::SRegister LowSRegisterFrom(Location location) { 65 DCHECK(location.IsFpuRegisterPair()) << location; 66 return vixl::aarch32::SRegister(location.AsFpuRegisterPairLow<vixl::aarch32::SRegister>()); 67 } 68 69 inline vixl::aarch32::SRegister HighSRegisterFrom(Location location) { 70 DCHECK(location.IsFpuRegisterPair()) << location; 71 return vixl::aarch32::SRegister(location.AsFpuRegisterPairHigh<vixl::aarch32::SRegister>()); 72 } 73 74 inline vixl::aarch32::Register RegisterFrom(Location location) { 75 DCHECK(location.IsRegister()) << location; 76 return vixl::aarch32::Register(location.reg()); 77 } 78 79 inline vixl::aarch32::Register RegisterFrom(Location location, Primitive::Type type) { 80 DCHECK(type != Primitive::kPrimVoid && !Primitive::IsFloatingPointType(type)) << type; 81 return RegisterFrom(location); 82 } 83 84 inline vixl::aarch32::DRegister DRegisterFrom(Location location) { 85 DCHECK(location.IsFpuRegisterPair()) << location; 86 int reg_code = location.low(); 87 DCHECK_EQ(reg_code % 2, 0) << reg_code; 88 return vixl::aarch32::DRegister(reg_code / 2); 89 } 90 91 inline vixl::aarch32::SRegister SRegisterFrom(Location location) { 92 DCHECK(location.IsFpuRegister()) << location; 93 return vixl::aarch32::SRegister(location.reg()); 94 } 95 96 inline vixl::aarch32::SRegister OutputSRegister(HInstruction* instr) { 97 Primitive::Type type = instr->GetType(); 98 DCHECK_EQ(type, Primitive::kPrimFloat) << type; 99 return SRegisterFrom(instr->GetLocations()->Out()); 100 } 101 102 inline vixl::aarch32::DRegister OutputDRegister(HInstruction* instr) { 103 Primitive::Type type = instr->GetType(); 104 DCHECK_EQ(type, Primitive::kPrimDouble) << type; 105 return DRegisterFrom(instr->GetLocations()->Out()); 106 } 107 108 inline vixl::aarch32::VRegister OutputVRegister(HInstruction* instr) { 109 Primitive::Type type = instr->GetType(); 110 if (type == Primitive::kPrimFloat) { 111 return OutputSRegister(instr); 112 } else { 113 return OutputDRegister(instr); 114 } 115 } 116 117 inline vixl::aarch32::SRegister InputSRegisterAt(HInstruction* instr, int input_index) { 118 Primitive::Type type = instr->InputAt(input_index)->GetType(); 119 DCHECK_EQ(type, Primitive::kPrimFloat) << type; 120 return SRegisterFrom(instr->GetLocations()->InAt(input_index)); 121 } 122 123 inline vixl::aarch32::DRegister InputDRegisterAt(HInstruction* instr, int input_index) { 124 Primitive::Type type = instr->InputAt(input_index)->GetType(); 125 DCHECK_EQ(type, Primitive::kPrimDouble) << type; 126 return DRegisterFrom(instr->GetLocations()->InAt(input_index)); 127 } 128 129 inline vixl::aarch32::VRegister InputVRegisterAt(HInstruction* instr, int input_index) { 130 Primitive::Type type = instr->InputAt(input_index)->GetType(); 131 if (type == Primitive::kPrimFloat) { 132 return InputSRegisterAt(instr, input_index); 133 } else { 134 DCHECK_EQ(type, Primitive::kPrimDouble); 135 return InputDRegisterAt(instr, input_index); 136 } 137 } 138 139 inline vixl::aarch32::VRegister InputVRegister(HInstruction* instr) { 140 DCHECK_EQ(instr->InputCount(), 1u); 141 return InputVRegisterAt(instr, 0); 142 } 143 144 inline vixl::aarch32::Register OutputRegister(HInstruction* instr) { 145 return RegisterFrom(instr->GetLocations()->Out(), instr->GetType()); 146 } 147 148 inline vixl::aarch32::Register InputRegisterAt(HInstruction* instr, int input_index) { 149 return RegisterFrom(instr->GetLocations()->InAt(input_index), 150 instr->InputAt(input_index)->GetType()); 151 } 152 153 inline vixl::aarch32::Register InputRegister(HInstruction* instr) { 154 DCHECK_EQ(instr->InputCount(), 1u); 155 return InputRegisterAt(instr, 0); 156 } 157 158 inline vixl::aarch32::DRegister DRegisterFromS(vixl::aarch32::SRegister s) { 159 vixl::aarch32::DRegister d = vixl::aarch32::DRegister(s.GetCode() / 2); 160 DCHECK(s.Is(d.GetLane(0)) || s.Is(d.GetLane(1))); 161 return d; 162 } 163 164 inline int32_t Int32ConstantFrom(HInstruction* instr) { 165 if (instr->IsIntConstant()) { 166 return instr->AsIntConstant()->GetValue(); 167 } else if (instr->IsNullConstant()) { 168 return 0; 169 } else { 170 DCHECK(instr->IsLongConstant()) << instr->DebugName(); 171 const int64_t ret = instr->AsLongConstant()->GetValue(); 172 DCHECK_GE(ret, std::numeric_limits<int32_t>::min()); 173 DCHECK_LE(ret, std::numeric_limits<int32_t>::max()); 174 return ret; 175 } 176 } 177 178 inline int32_t Int32ConstantFrom(Location location) { 179 return Int32ConstantFrom(location.GetConstant()); 180 } 181 182 inline int64_t Int64ConstantFrom(Location location) { 183 HConstant* instr = location.GetConstant(); 184 if (instr->IsIntConstant()) { 185 return instr->AsIntConstant()->GetValue(); 186 } else if (instr->IsNullConstant()) { 187 return 0; 188 } else { 189 DCHECK(instr->IsLongConstant()) << instr->DebugName(); 190 return instr->AsLongConstant()->GetValue(); 191 } 192 } 193 194 inline uint64_t Uint64ConstantFrom(HInstruction* instr) { 195 DCHECK(instr->IsConstant()) << instr->DebugName(); 196 return instr->AsConstant()->GetValueAsUint64(); 197 } 198 199 inline vixl::aarch32::Operand OperandFrom(Location location, Primitive::Type type) { 200 if (location.IsRegister()) { 201 return vixl::aarch32::Operand(RegisterFrom(location, type)); 202 } else { 203 return vixl::aarch32::Operand(Int32ConstantFrom(location)); 204 } 205 } 206 207 inline vixl::aarch32::Operand InputOperandAt(HInstruction* instr, int input_index) { 208 return OperandFrom(instr->GetLocations()->InAt(input_index), 209 instr->InputAt(input_index)->GetType()); 210 } 211 212 inline Location LocationFrom(const vixl::aarch32::Register& reg) { 213 return Location::RegisterLocation(reg.GetCode()); 214 } 215 216 inline Location LocationFrom(const vixl::aarch32::SRegister& reg) { 217 return Location::FpuRegisterLocation(reg.GetCode()); 218 } 219 220 inline Location LocationFrom(const vixl::aarch32::Register& low, 221 const vixl::aarch32::Register& high) { 222 return Location::RegisterPairLocation(low.GetCode(), high.GetCode()); 223 } 224 225 inline Location LocationFrom(const vixl::aarch32::SRegister& low, 226 const vixl::aarch32::SRegister& high) { 227 return Location::FpuRegisterPairLocation(low.GetCode(), high.GetCode()); 228 } 229 230 inline bool ShifterOperandSupportsExtension(HInstruction* instruction) { 231 DCHECK(HasShifterOperand(instruction, kArm)); 232 // TODO: HAdd applied to the other integral types could make use of 233 // the SXTAB, SXTAH, UXTAB and UXTAH instructions. 234 return instruction->GetType() == Primitive::kPrimLong && 235 (instruction->IsAdd() || instruction->IsSub()); 236 } 237 238 } // namespace helpers 239 } // namespace arm 240 } // namespace art 241 242 #endif // ART_COMPILER_OPTIMIZING_COMMON_ARM_H_ 243