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 "base/macros.h"
21 #include "instruction_simplifier_shared.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 HIDDEN {
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 
HighRegisterFrom(Location location)41 inline vixl::aarch32::Register HighRegisterFrom(Location location) {
42   DCHECK(location.IsRegisterPair()) << location;
43   return vixl::aarch32::Register(location.AsRegisterPairHigh<vixl::aarch32::Register>());
44 }
45 
HighDRegisterFrom(Location location)46 inline vixl::aarch32::DRegister HighDRegisterFrom(Location location) {
47   DCHECK(location.IsFpuRegisterPair()) << location;
48   return vixl::aarch32::DRegister(location.AsFpuRegisterPairHigh<vixl::aarch32::DRegister>());
49 }
50 
LowRegisterFrom(Location location)51 inline vixl::aarch32::Register LowRegisterFrom(Location location) {
52   DCHECK(location.IsRegisterPair()) << location;
53   return vixl::aarch32::Register(location.AsRegisterPairLow<vixl::aarch32::Register>());
54 }
55 
LowSRegisterFrom(Location location)56 inline vixl::aarch32::SRegister LowSRegisterFrom(Location location) {
57   DCHECK(location.IsFpuRegisterPair()) << location;
58   return vixl::aarch32::SRegister(location.AsFpuRegisterPairLow<vixl::aarch32::SRegister>());
59 }
60 
HighSRegisterFrom(Location location)61 inline vixl::aarch32::SRegister HighSRegisterFrom(Location location) {
62   DCHECK(location.IsFpuRegisterPair()) << location;
63   return vixl::aarch32::SRegister(location.AsFpuRegisterPairHigh<vixl::aarch32::SRegister>());
64 }
65 
RegisterFrom(Location location)66 inline vixl::aarch32::Register RegisterFrom(Location location) {
67   DCHECK(location.IsRegister()) << location;
68   return vixl::aarch32::Register(location.reg());
69 }
70 
RegisterFrom(Location location,DataType::Type type)71 inline vixl::aarch32::Register RegisterFrom(Location location, DataType::Type type) {
72   DCHECK(type != DataType::Type::kVoid && !DataType::IsFloatingPointType(type)) << type;
73   return RegisterFrom(location);
74 }
75 
DRegisterFrom(Location location)76 inline vixl::aarch32::DRegister DRegisterFrom(Location location) {
77   DCHECK(location.IsFpuRegisterPair()) << location;
78   int reg_code = location.low();
79   DCHECK_EQ(reg_code % 2, 0) << reg_code;
80   return vixl::aarch32::DRegister(reg_code / 2);
81 }
82 
SRegisterFrom(Location location)83 inline vixl::aarch32::SRegister SRegisterFrom(Location location) {
84   DCHECK(location.IsFpuRegister()) << location;
85   return vixl::aarch32::SRegister(location.reg());
86 }
87 
OutputSRegister(HInstruction * instr)88 inline vixl::aarch32::SRegister OutputSRegister(HInstruction* instr) {
89   DataType::Type type = instr->GetType();
90   DCHECK_EQ(type, DataType::Type::kFloat32) << type;
91   return SRegisterFrom(instr->GetLocations()->Out());
92 }
93 
OutputDRegister(HInstruction * instr)94 inline vixl::aarch32::DRegister OutputDRegister(HInstruction* instr) {
95   DataType::Type type = instr->GetType();
96   DCHECK_EQ(type, DataType::Type::kFloat64) << type;
97   return DRegisterFrom(instr->GetLocations()->Out());
98 }
99 
OutputVRegister(HInstruction * instr)100 inline vixl::aarch32::VRegister OutputVRegister(HInstruction* instr) {
101   DataType::Type type = instr->GetType();
102   if (type == DataType::Type::kFloat32) {
103     return OutputSRegister(instr);
104   } else {
105     return OutputDRegister(instr);
106   }
107 }
108 
InputSRegisterAt(HInstruction * instr,int input_index)109 inline vixl::aarch32::SRegister InputSRegisterAt(HInstruction* instr, int input_index) {
110   DataType::Type type = instr->InputAt(input_index)->GetType();
111   DCHECK_EQ(type, DataType::Type::kFloat32) << type;
112   return SRegisterFrom(instr->GetLocations()->InAt(input_index));
113 }
114 
InputDRegisterAt(HInstruction * instr,int input_index)115 inline vixl::aarch32::DRegister InputDRegisterAt(HInstruction* instr, int input_index) {
116   DataType::Type type = instr->InputAt(input_index)->GetType();
117   DCHECK_EQ(type, DataType::Type::kFloat64) << type;
118   return DRegisterFrom(instr->GetLocations()->InAt(input_index));
119 }
120 
InputVRegisterAt(HInstruction * instr,int input_index)121 inline vixl::aarch32::VRegister InputVRegisterAt(HInstruction* instr, int input_index) {
122   DataType::Type type = instr->InputAt(input_index)->GetType();
123   if (type == DataType::Type::kFloat32) {
124     return InputSRegisterAt(instr, input_index);
125   } else {
126     DCHECK_EQ(type, DataType::Type::kFloat64);
127     return InputDRegisterAt(instr, input_index);
128   }
129 }
130 
InputVRegister(HInstruction * instr)131 inline vixl::aarch32::VRegister InputVRegister(HInstruction* instr) {
132   DCHECK_EQ(instr->InputCount(), 1u);
133   return InputVRegisterAt(instr, 0);
134 }
135 
OutputRegister(HInstruction * instr)136 inline vixl::aarch32::Register OutputRegister(HInstruction* instr) {
137   return RegisterFrom(instr->GetLocations()->Out(), instr->GetType());
138 }
139 
InputRegisterAt(HInstruction * instr,int input_index)140 inline vixl::aarch32::Register InputRegisterAt(HInstruction* instr, int input_index) {
141   return RegisterFrom(instr->GetLocations()->InAt(input_index),
142                       instr->InputAt(input_index)->GetType());
143 }
144 
InputRegister(HInstruction * instr)145 inline vixl::aarch32::Register InputRegister(HInstruction* instr) {
146   DCHECK_EQ(instr->InputCount(), 1u);
147   return InputRegisterAt(instr, 0);
148 }
149 
DRegisterFromS(vixl::aarch32::SRegister s)150 inline vixl::aarch32::DRegister DRegisterFromS(vixl::aarch32::SRegister s) {
151   vixl::aarch32::DRegister d = vixl::aarch32::DRegister(s.GetCode() / 2);
152   DCHECK(s.Is(d.GetLane(0)) || s.Is(d.GetLane(1)));
153   return d;
154 }
155 
Int32ConstantFrom(HInstruction * instr)156 inline int32_t Int32ConstantFrom(HInstruction* instr) {
157   if (instr->IsIntConstant()) {
158     return instr->AsIntConstant()->GetValue();
159   } else if (instr->IsNullConstant()) {
160     return 0;
161   } else {
162     DCHECK(instr->IsLongConstant()) << instr->DebugName();
163     const int64_t ret = instr->AsLongConstant()->GetValue();
164     DCHECK_GE(ret, std::numeric_limits<int32_t>::min());
165     DCHECK_LE(ret, std::numeric_limits<int32_t>::max());
166     return ret;
167   }
168 }
169 
Int32ConstantFrom(Location location)170 inline int32_t Int32ConstantFrom(Location location) {
171   return Int32ConstantFrom(location.GetConstant());
172 }
173 
Int64ConstantFrom(Location location)174 inline int64_t Int64ConstantFrom(Location location) {
175   HConstant* instr = location.GetConstant();
176   if (instr->IsIntConstant()) {
177     return instr->AsIntConstant()->GetValue();
178   } else if (instr->IsNullConstant()) {
179     return 0;
180   } else {
181     DCHECK(instr->IsLongConstant()) << instr->DebugName();
182     return instr->AsLongConstant()->GetValue();
183   }
184 }
185 
Uint64ConstantFrom(HInstruction * instr)186 inline uint64_t Uint64ConstantFrom(HInstruction* instr) {
187   DCHECK(instr->IsConstant()) << instr->DebugName();
188   return instr->AsConstant()->GetValueAsUint64();
189 }
190 
OperandFrom(Location location,DataType::Type type)191 inline vixl::aarch32::Operand OperandFrom(Location location, DataType::Type type) {
192   if (location.IsRegister()) {
193     return vixl::aarch32::Operand(RegisterFrom(location, type));
194   } else {
195     return vixl::aarch32::Operand(Int32ConstantFrom(location));
196   }
197 }
198 
InputOperandAt(HInstruction * instr,int input_index)199 inline vixl::aarch32::Operand InputOperandAt(HInstruction* instr, int input_index) {
200   return OperandFrom(instr->GetLocations()->InAt(input_index),
201                      instr->InputAt(input_index)->GetType());
202 }
203 
LocationFrom(const vixl::aarch32::Register & reg)204 inline Location LocationFrom(const vixl::aarch32::Register& reg) {
205   return Location::RegisterLocation(reg.GetCode());
206 }
207 
LocationFrom(const vixl::aarch32::SRegister & reg)208 inline Location LocationFrom(const vixl::aarch32::SRegister& reg) {
209   return Location::FpuRegisterLocation(reg.GetCode());
210 }
211 
LocationFrom(const vixl::aarch32::Register & low,const vixl::aarch32::Register & high)212 inline Location LocationFrom(const vixl::aarch32::Register& low,
213                              const vixl::aarch32::Register& high) {
214   return Location::RegisterPairLocation(low.GetCode(), high.GetCode());
215 }
216 
LocationFrom(const vixl::aarch32::SRegister & low,const vixl::aarch32::SRegister & high)217 inline Location LocationFrom(const vixl::aarch32::SRegister& low,
218                              const vixl::aarch32::SRegister& high) {
219   return Location::FpuRegisterPairLocation(low.GetCode(), high.GetCode());
220 }
221 
222 }  // namespace helpers
223 }  // namespace arm
224 }  // namespace art
225 
226 #endif  // ART_COMPILER_OPTIMIZING_COMMON_ARM_H_
227