| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ | 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_H_ |
| 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ | 6 #define V8_ARM64_ASSEMBLER_ARM64_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <list> | 9 #include <list> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31) | 48 V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31) |
| 49 | 49 |
| 50 #define DOUBLE_REGISTERS(R) \ | 50 #define DOUBLE_REGISTERS(R) \ |
| 51 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ | 51 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ |
| 52 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \ | 52 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \ |
| 53 R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \ | 53 R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \ |
| 54 R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31) | 54 R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31) |
| 55 | 55 |
| 56 #define SIMD128_REGISTERS(V) \ | 56 #define SIMD128_REGISTERS(V) \ |
| 57 V(q0) V(q1) V(q2) V(q3) V(q4) V(q5) V(q6) V(q7) \ | 57 V(q0) V(q1) V(q2) V(q3) V(q4) V(q5) V(q6) V(q7) \ |
| 58 V(q8) V(q9) V(q10) V(q11) V(q12) V(q13) V(q14) V(q15) \ | 58 V(q8) V(q9) V(q10) V(q11) V(q12) V(q13) V(q14) V(q15) |
| 59 V(q16) V(q17) V(q18) V(q19) V(q20) V(q21) V(q22) V(q23) \ | |
| 60 V(q24) V(q25) V(q26) V(q27) V(q28) V(q29) V(q30) V(q31) | |
| 61 | 59 |
| 62 #define ALLOCATABLE_DOUBLE_REGISTERS(R) \ | 60 #define ALLOCATABLE_DOUBLE_REGISTERS(R) \ |
| 63 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ | 61 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ |
| 64 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \ | 62 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \ |
| 65 R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \ | 63 R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \ |
| 66 R(d25) R(d26) R(d27) R(d28) | 64 R(d25) R(d26) R(d27) R(d28) |
| 67 // clang-format on | 65 // clang-format on |
| 68 | 66 |
| 69 constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; | 67 constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; |
| 70 static const int kNoCodeAgeSequenceLength = 5 * kInstructionSize; | 68 static const int kNoCodeAgeSequenceLength = 5 * kInstructionSize; |
| 71 | 69 |
| 72 // Some CPURegister methods can return Register and VRegister types, so we | 70 // Some CPURegister methods can return Register and FPRegister types, so we |
| 73 // need to declare them in advance. | 71 // need to declare them in advance. |
| 74 struct Register; | 72 struct Register; |
| 75 struct VRegister; | 73 struct FPRegister; |
| 74 |
| 76 | 75 |
| 77 struct CPURegister { | 76 struct CPURegister { |
| 78 enum Code { | 77 enum Code { |
| 79 #define REGISTER_CODE(R) kCode_##R, | 78 #define REGISTER_CODE(R) kCode_##R, |
| 80 GENERAL_REGISTERS(REGISTER_CODE) | 79 GENERAL_REGISTERS(REGISTER_CODE) |
| 81 #undef REGISTER_CODE | 80 #undef REGISTER_CODE |
| 82 kAfterLast, | 81 kAfterLast, |
| 83 kCode_no_reg = -1 | 82 kCode_no_reg = -1 |
| 84 }; | 83 }; |
| 85 | 84 |
| 86 enum RegisterType { | 85 enum RegisterType { |
| 87 // The kInvalid value is used to detect uninitialized static instances, | 86 // The kInvalid value is used to detect uninitialized static instances, |
| 88 // which are always zero-initialized before any constructors are called. | 87 // which are always zero-initialized before any constructors are called. |
| 89 kInvalid = 0, | 88 kInvalid = 0, |
| 90 kRegister, | 89 kRegister, |
| 91 kVRegister, | 90 kFPRegister, |
| 92 kNoRegister | 91 kNoRegister |
| 93 }; | 92 }; |
| 94 | 93 |
| 95 constexpr CPURegister() : CPURegister(0, 0, CPURegister::kNoRegister) {} | 94 constexpr CPURegister() : CPURegister(0, 0, CPURegister::kNoRegister) {} |
| 96 | 95 |
| 97 constexpr CPURegister(int reg_code, int reg_size, RegisterType reg_type, | 96 constexpr CPURegister(int reg_code, int reg_size, RegisterType reg_type) |
| 98 int lane_count = 1) | 97 : reg_code(reg_code), reg_size(reg_size), reg_type(reg_type) {} |
| 99 : reg_code(reg_code), | |
| 100 reg_size(reg_size), | |
| 101 reg_type(reg_type), | |
| 102 lane_count(lane_count) {} | |
| 103 | 98 |
| 104 static CPURegister Create(int reg_code, int reg_size, RegisterType reg_type, | 99 static CPURegister Create(int code, int size, RegisterType type) { |
| 105 int lane_count = 1) { | 100 CPURegister r = {code, size, type}; |
| 106 CPURegister r = {reg_code, reg_size, reg_type, lane_count}; | |
| 107 return r; | 101 return r; |
| 108 } | 102 } |
| 109 | 103 |
| 110 int code() const; | 104 int code() const; |
| 111 RegisterType type() const; | 105 RegisterType type() const; |
| 112 RegList Bit() const; | 106 RegList Bit() const; |
| 113 int SizeInBits() const; | 107 int SizeInBits() const; |
| 114 int SizeInBytes() const; | 108 int SizeInBytes() const; |
| 115 bool Is8Bits() const; | |
| 116 bool Is16Bits() const; | |
| 117 bool Is32Bits() const; | 109 bool Is32Bits() const; |
| 118 bool Is64Bits() const; | 110 bool Is64Bits() const; |
| 119 bool Is128Bits() const; | |
| 120 bool IsValid() const; | 111 bool IsValid() const; |
| 121 bool IsValidOrNone() const; | 112 bool IsValidOrNone() const; |
| 122 bool IsValidRegister() const; | 113 bool IsValidRegister() const; |
| 123 bool IsValidVRegister() const; | 114 bool IsValidFPRegister() const; |
| 124 bool IsNone() const; | 115 bool IsNone() const; |
| 125 bool Is(const CPURegister& other) const; | 116 bool Is(const CPURegister& other) const; |
| 126 bool Aliases(const CPURegister& other) const; | 117 bool Aliases(const CPURegister& other) const; |
| 127 | 118 |
| 128 bool IsZero() const; | 119 bool IsZero() const; |
| 129 bool IsSP() const; | 120 bool IsSP() const; |
| 130 | 121 |
| 131 bool IsRegister() const; | 122 bool IsRegister() const; |
| 132 bool IsVRegister() const; | 123 bool IsFPRegister() const; |
| 133 | |
| 134 bool IsFPRegister() const { return IsS() || IsD(); } | |
| 135 | |
| 136 bool IsW() const { return IsValidRegister() && Is32Bits(); } | |
| 137 bool IsX() const { return IsValidRegister() && Is64Bits(); } | |
| 138 | |
| 139 // These assertions ensure that the size and type of the register are as | |
| 140 // described. They do not consider the number of lanes that make up a vector. | |
| 141 // So, for example, Is8B() implies IsD(), and Is1D() implies IsD, but IsD() | |
| 142 // does not imply Is1D() or Is8B(). | |
| 143 // Check the number of lanes, ie. the format of the vector, using methods such | |
| 144 // as Is8B(), Is1D(), etc. in the VRegister class. | |
| 145 bool IsV() const { return IsVRegister(); } | |
| 146 bool IsB() const { return IsV() && Is8Bits(); } | |
| 147 bool IsH() const { return IsV() && Is16Bits(); } | |
| 148 bool IsS() const { return IsV() && Is32Bits(); } | |
| 149 bool IsD() const { return IsV() && Is64Bits(); } | |
| 150 bool IsQ() const { return IsV() && Is128Bits(); } | |
| 151 | 124 |
| 152 Register X() const; | 125 Register X() const; |
| 153 Register W() const; | 126 Register W() const; |
| 154 VRegister V() const; | 127 FPRegister D() const; |
| 155 VRegister B() const; | 128 FPRegister S() const; |
| 156 VRegister H() const; | |
| 157 VRegister D() const; | |
| 158 VRegister S() const; | |
| 159 VRegister Q() const; | |
| 160 | 129 |
| 161 bool IsSameSizeAndType(const CPURegister& other) const; | 130 bool IsSameSizeAndType(const CPURegister& other) const; |
| 162 | 131 |
| 163 // V8 compatibility. | 132 // V8 compatibility. |
| 164 bool is(const CPURegister& other) const { return Is(other); } | 133 bool is(const CPURegister& other) const { return Is(other); } |
| 165 bool is_valid() const { return IsValid(); } | 134 bool is_valid() const { return IsValid(); } |
| 166 | 135 |
| 167 int reg_code; | 136 int reg_code; |
| 168 int reg_size; | 137 int reg_size; |
| 169 RegisterType reg_type; | 138 RegisterType reg_type; |
| 170 int lane_count; | |
| 171 }; | 139 }; |
| 172 | 140 |
| 173 | 141 |
| 174 struct Register : public CPURegister { | 142 struct Register : public CPURegister { |
| 175 static Register Create(int code, int size) { | 143 static Register Create(int code, int size) { |
| 176 return Register(CPURegister::Create(code, size, CPURegister::kRegister)); | 144 return Register(CPURegister::Create(code, size, CPURegister::kRegister)); |
| 177 } | 145 } |
| 178 | 146 |
| 179 constexpr Register() : CPURegister() {} | 147 constexpr Register() : CPURegister() {} |
| 180 | 148 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 // Always return an X register. | 183 // Always return an X register. |
| 216 return Register::Create(code, kXRegSizeInBits); | 184 return Register::Create(code, kXRegSizeInBits); |
| 217 } | 185 } |
| 218 | 186 |
| 219 // End of V8 compatibility section ----------------------- | 187 // End of V8 compatibility section ----------------------- |
| 220 }; | 188 }; |
| 221 | 189 |
| 222 constexpr bool kSimpleFPAliasing = true; | 190 constexpr bool kSimpleFPAliasing = true; |
| 223 constexpr bool kSimdMaskRegisters = false; | 191 constexpr bool kSimdMaskRegisters = false; |
| 224 | 192 |
| 225 struct VRegister : public CPURegister { | 193 struct FPRegister : public CPURegister { |
| 226 enum Code { | 194 enum Code { |
| 227 #define REGISTER_CODE(R) kCode_##R, | 195 #define REGISTER_CODE(R) kCode_##R, |
| 228 DOUBLE_REGISTERS(REGISTER_CODE) | 196 DOUBLE_REGISTERS(REGISTER_CODE) |
| 229 #undef REGISTER_CODE | 197 #undef REGISTER_CODE |
| 230 kAfterLast, | 198 kAfterLast, |
| 231 kCode_no_reg = -1 | 199 kCode_no_reg = -1 |
| 232 }; | 200 }; |
| 233 | 201 |
| 234 static VRegister Create(int reg_code, int reg_size, int lane_count = 1) { | 202 static FPRegister Create(int code, int size) { |
| 235 DCHECK(base::bits::IsPowerOfTwo32(lane_count) && (lane_count <= 16)); | 203 return FPRegister( |
| 236 VRegister v(CPURegister::Create(reg_code, reg_size, CPURegister::kVRegister, | 204 CPURegister::Create(code, size, CPURegister::kFPRegister)); |
| 237 lane_count)); | |
| 238 DCHECK(v.IsValidVRegister()); | |
| 239 return v; | |
| 240 } | 205 } |
| 241 | 206 |
| 242 static VRegister Create(int reg_code, VectorFormat format) { | 207 constexpr FPRegister() : CPURegister() {} |
| 243 int reg_size = RegisterSizeInBitsFromFormat(format); | 208 |
| 244 int reg_count = IsVectorFormat(format) ? LaneCountFromFormat(format) : 1; | 209 constexpr explicit FPRegister(const CPURegister& r) : CPURegister(r) {} |
| 245 return VRegister::Create(reg_code, reg_size, reg_count); | 210 |
| 211 bool IsValid() const { |
| 212 DCHECK(IsFPRegister() || IsNone()); |
| 213 return IsValidFPRegister(); |
| 246 } | 214 } |
| 247 | 215 |
| 248 constexpr VRegister() : CPURegister() {} | 216 static FPRegister SRegFromCode(unsigned code); |
| 249 | 217 static FPRegister DRegFromCode(unsigned code); |
| 250 constexpr explicit VRegister(const CPURegister& r) : CPURegister(r) {} | |
| 251 | |
| 252 bool IsValid() const { | |
| 253 DCHECK(IsVRegister() || IsNone()); | |
| 254 return IsValidVRegister(); | |
| 255 } | |
| 256 | |
| 257 static VRegister BRegFromCode(unsigned code); | |
| 258 static VRegister HRegFromCode(unsigned code); | |
| 259 static VRegister SRegFromCode(unsigned code); | |
| 260 static VRegister DRegFromCode(unsigned code); | |
| 261 static VRegister QRegFromCode(unsigned code); | |
| 262 static VRegister VRegFromCode(unsigned code); | |
| 263 | |
| 264 VRegister V8B() const { | |
| 265 return VRegister::Create(code(), kDRegSizeInBits, 8); | |
| 266 } | |
| 267 VRegister V16B() const { | |
| 268 return VRegister::Create(code(), kQRegSizeInBits, 16); | |
| 269 } | |
| 270 VRegister V4H() const { | |
| 271 return VRegister::Create(code(), kDRegSizeInBits, 4); | |
| 272 } | |
| 273 VRegister V8H() const { | |
| 274 return VRegister::Create(code(), kQRegSizeInBits, 8); | |
| 275 } | |
| 276 VRegister V2S() const { | |
| 277 return VRegister::Create(code(), kDRegSizeInBits, 2); | |
| 278 } | |
| 279 VRegister V4S() const { | |
| 280 return VRegister::Create(code(), kQRegSizeInBits, 4); | |
| 281 } | |
| 282 VRegister V2D() const { | |
| 283 return VRegister::Create(code(), kQRegSizeInBits, 2); | |
| 284 } | |
| 285 VRegister V1D() const { | |
| 286 return VRegister::Create(code(), kDRegSizeInBits, 1); | |
| 287 } | |
| 288 | |
| 289 bool Is8B() const { return (Is64Bits() && (lane_count == 8)); } | |
| 290 bool Is16B() const { return (Is128Bits() && (lane_count == 16)); } | |
| 291 bool Is4H() const { return (Is64Bits() && (lane_count == 4)); } | |
| 292 bool Is8H() const { return (Is128Bits() && (lane_count == 8)); } | |
| 293 bool Is2S() const { return (Is64Bits() && (lane_count == 2)); } | |
| 294 bool Is4S() const { return (Is128Bits() && (lane_count == 4)); } | |
| 295 bool Is1D() const { return (Is64Bits() && (lane_count == 1)); } | |
| 296 bool Is2D() const { return (Is128Bits() && (lane_count == 2)); } | |
| 297 | |
| 298 // For consistency, we assert the number of lanes of these scalar registers, | |
| 299 // even though there are no vectors of equivalent total size with which they | |
| 300 // could alias. | |
| 301 bool Is1B() const { | |
| 302 DCHECK(!(Is8Bits() && IsVector())); | |
| 303 return Is8Bits(); | |
| 304 } | |
| 305 bool Is1H() const { | |
| 306 DCHECK(!(Is16Bits() && IsVector())); | |
| 307 return Is16Bits(); | |
| 308 } | |
| 309 bool Is1S() const { | |
| 310 DCHECK(!(Is32Bits() && IsVector())); | |
| 311 return Is32Bits(); | |
| 312 } | |
| 313 | |
| 314 bool IsLaneSizeB() const { return LaneSizeInBits() == kBRegSizeInBits; } | |
| 315 bool IsLaneSizeH() const { return LaneSizeInBits() == kHRegSizeInBits; } | |
| 316 bool IsLaneSizeS() const { return LaneSizeInBits() == kSRegSizeInBits; } | |
| 317 bool IsLaneSizeD() const { return LaneSizeInBits() == kDRegSizeInBits; } | |
| 318 | |
| 319 bool IsScalar() const { return lane_count == 1; } | |
| 320 bool IsVector() const { return lane_count > 1; } | |
| 321 | |
| 322 bool IsSameFormat(const VRegister& other) const { | |
| 323 return (reg_size == other.reg_size) && (lane_count == other.lane_count); | |
| 324 } | |
| 325 | |
| 326 int LaneCount() const { return lane_count; } | |
| 327 | |
| 328 unsigned LaneSizeInBytes() const { return SizeInBytes() / lane_count; } | |
| 329 | |
| 330 unsigned LaneSizeInBits() const { return LaneSizeInBytes() * 8; } | |
| 331 | 218 |
| 332 // Start of V8 compatibility section --------------------- | 219 // Start of V8 compatibility section --------------------- |
| 333 static constexpr int kMaxNumRegisters = kNumberOfVRegisters; | 220 static constexpr int kMaxNumRegisters = kNumberOfFPRegisters; |
| 334 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast); | 221 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast); |
| 335 | 222 |
| 336 // Crankshaft can use all the V registers except: | 223 // Crankshaft can use all the FP registers except: |
| 337 // - d15 which is used to keep the 0 double value | 224 // - d15 which is used to keep the 0 double value |
| 338 // - d30 which is used in crankshaft as a double scratch register | 225 // - d30 which is used in crankshaft as a double scratch register |
| 339 // - d31 which is used in the MacroAssembler as a double scratch register | 226 // - d31 which is used in the MacroAssembler as a double scratch register |
| 340 static VRegister from_code(int code) { | 227 static FPRegister from_code(int code) { |
| 341 // Always return a D register. | 228 // Always return a D register. |
| 342 return VRegister::Create(code, kDRegSizeInBits); | 229 return FPRegister::Create(code, kDRegSizeInBits); |
| 343 } | 230 } |
| 344 // End of V8 compatibility section ----------------------- | 231 // End of V8 compatibility section ----------------------- |
| 345 }; | 232 }; |
| 346 | 233 |
| 347 static_assert(sizeof(CPURegister) == sizeof(Register), | 234 |
| 348 "CPURegister must be same size as Register"); | 235 STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); |
| 349 static_assert(sizeof(CPURegister) == sizeof(VRegister), | 236 STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); |
| 350 "CPURegister must be same size as VRegister"); | |
| 351 | 237 |
| 352 #define DEFINE_REGISTER(register_class, name, code, size, type) \ | 238 #define DEFINE_REGISTER(register_class, name, code, size, type) \ |
| 353 constexpr register_class name { CPURegister(code, size, type) } | 239 constexpr register_class name { CPURegister(code, size, type) } |
| 354 #define ALIAS_REGISTER(register_class, alias, name) \ | 240 #define ALIAS_REGISTER(register_class, alias, name) \ |
| 355 constexpr register_class alias = name | 241 constexpr register_class alias = name |
| 356 | 242 |
| 357 // No*Reg is used to indicate an unused argument, or an error case. Note that | 243 // No*Reg is used to indicate an unused argument, or an error case. Note that |
| 358 // these all compare equal (using the Is() method). The Register and VRegister | 244 // these all compare equal (using the Is() method). The Register and FPRegister |
| 359 // variants are provided for convenience. | 245 // variants are provided for convenience. |
| 360 DEFINE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister); | 246 DEFINE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister); |
| 361 DEFINE_REGISTER(VRegister, NoVReg, 0, 0, CPURegister::kNoRegister); | 247 DEFINE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister); |
| 362 DEFINE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); | 248 DEFINE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); |
| 363 | 249 |
| 364 // v8 compatibility. | 250 // v8 compatibility. |
| 365 DEFINE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); | 251 DEFINE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); |
| 366 | 252 |
| 367 #define DEFINE_REGISTERS(N) \ | 253 #define DEFINE_REGISTERS(N) \ |
| 368 DEFINE_REGISTER(Register, w##N, N, kWRegSizeInBits, CPURegister::kRegister); \ | 254 DEFINE_REGISTER(Register, w##N, N, kWRegSizeInBits, CPURegister::kRegister); \ |
| 369 DEFINE_REGISTER(Register, x##N, N, kXRegSizeInBits, CPURegister::kRegister); | 255 DEFINE_REGISTER(Register, x##N, N, kXRegSizeInBits, CPURegister::kRegister); |
| 370 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) | 256 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) |
| 371 #undef DEFINE_REGISTERS | 257 #undef DEFINE_REGISTERS |
| 372 | 258 |
| 373 DEFINE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, | 259 DEFINE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, |
| 374 CPURegister::kRegister); | 260 CPURegister::kRegister); |
| 375 DEFINE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, | 261 DEFINE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, |
| 376 CPURegister::kRegister); | 262 CPURegister::kRegister); |
| 377 | 263 |
| 378 #define DEFINE_VREGISTERS(N) \ | 264 #define DEFINE_FPREGISTERS(N) \ |
| 379 DEFINE_REGISTER(VRegister, b##N, N, kBRegSizeInBits, \ | 265 DEFINE_REGISTER(FPRegister, s##N, N, kSRegSizeInBits, \ |
| 380 CPURegister::kVRegister); \ | 266 CPURegister::kFPRegister); \ |
| 381 DEFINE_REGISTER(VRegister, h##N, N, kHRegSizeInBits, \ | 267 DEFINE_REGISTER(FPRegister, d##N, N, kDRegSizeInBits, \ |
| 382 CPURegister::kVRegister); \ | 268 CPURegister::kFPRegister); |
| 383 DEFINE_REGISTER(VRegister, s##N, N, kSRegSizeInBits, \ | 269 GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS) |
| 384 CPURegister::kVRegister); \ | 270 #undef DEFINE_FPREGISTERS |
| 385 DEFINE_REGISTER(VRegister, d##N, N, kDRegSizeInBits, \ | |
| 386 CPURegister::kVRegister); \ | |
| 387 DEFINE_REGISTER(VRegister, q##N, N, kQRegSizeInBits, \ | |
| 388 CPURegister::kVRegister); \ | |
| 389 DEFINE_REGISTER(VRegister, v##N, N, kQRegSizeInBits, CPURegister::kVRegister); | |
| 390 GENERAL_REGISTER_CODE_LIST(DEFINE_VREGISTERS) | |
| 391 #undef DEFINE_VREGISTERS | |
| 392 | 271 |
| 393 #undef DEFINE_REGISTER | 272 #undef DEFINE_REGISTER |
| 394 | 273 |
| 395 // Registers aliases. | 274 // Registers aliases. |
| 396 ALIAS_REGISTER(VRegister, v8_, v8); // Avoid conflicts with namespace v8. | |
| 397 ALIAS_REGISTER(Register, ip0, x16); | 275 ALIAS_REGISTER(Register, ip0, x16); |
| 398 ALIAS_REGISTER(Register, ip1, x17); | 276 ALIAS_REGISTER(Register, ip1, x17); |
| 399 ALIAS_REGISTER(Register, wip0, w16); | 277 ALIAS_REGISTER(Register, wip0, w16); |
| 400 ALIAS_REGISTER(Register, wip1, w17); | 278 ALIAS_REGISTER(Register, wip1, w17); |
| 401 // Root register. | 279 // Root register. |
| 402 ALIAS_REGISTER(Register, root, x26); | 280 ALIAS_REGISTER(Register, root, x26); |
| 403 ALIAS_REGISTER(Register, rr, x26); | 281 ALIAS_REGISTER(Register, rr, x26); |
| 404 // Context pointer register. | 282 // Context pointer register. |
| 405 ALIAS_REGISTER(Register, cp, x27); | 283 ALIAS_REGISTER(Register, cp, x27); |
| 406 // We use a register as a JS stack pointer to overcome the restriction on the | 284 // We use a register as a JS stack pointer to overcome the restriction on the |
| 407 // architectural SP alignment. | 285 // architectural SP alignment. |
| 408 // We chose x28 because it is contiguous with the other specific purpose | 286 // We chose x28 because it is contiguous with the other specific purpose |
| 409 // registers. | 287 // registers. |
| 410 STATIC_ASSERT(kJSSPCode == 28); | 288 STATIC_ASSERT(kJSSPCode == 28); |
| 411 ALIAS_REGISTER(Register, jssp, x28); | 289 ALIAS_REGISTER(Register, jssp, x28); |
| 412 ALIAS_REGISTER(Register, wjssp, w28); | 290 ALIAS_REGISTER(Register, wjssp, w28); |
| 413 ALIAS_REGISTER(Register, fp, x29); | 291 ALIAS_REGISTER(Register, fp, x29); |
| 414 ALIAS_REGISTER(Register, lr, x30); | 292 ALIAS_REGISTER(Register, lr, x30); |
| 415 ALIAS_REGISTER(Register, xzr, x31); | 293 ALIAS_REGISTER(Register, xzr, x31); |
| 416 ALIAS_REGISTER(Register, wzr, w31); | 294 ALIAS_REGISTER(Register, wzr, w31); |
| 417 | 295 |
| 418 // Keeps the 0 double value. | 296 // Keeps the 0 double value. |
| 419 ALIAS_REGISTER(VRegister, fp_zero, d15); | 297 ALIAS_REGISTER(FPRegister, fp_zero, d15); |
| 420 // Crankshaft double scratch register. | 298 // Crankshaft double scratch register. |
| 421 ALIAS_REGISTER(VRegister, crankshaft_fp_scratch, d29); | 299 ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29); |
| 422 // MacroAssembler double scratch registers. | 300 // MacroAssembler double scratch registers. |
| 423 ALIAS_REGISTER(VRegister, fp_scratch, d30); | 301 ALIAS_REGISTER(FPRegister, fp_scratch, d30); |
| 424 ALIAS_REGISTER(VRegister, fp_scratch1, d30); | 302 ALIAS_REGISTER(FPRegister, fp_scratch1, d30); |
| 425 ALIAS_REGISTER(VRegister, fp_scratch2, d31); | 303 ALIAS_REGISTER(FPRegister, fp_scratch2, d31); |
| 426 | 304 |
| 427 #undef ALIAS_REGISTER | 305 #undef ALIAS_REGISTER |
| 428 | 306 |
| 429 | 307 |
| 430 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, | 308 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, |
| 431 Register reg2 = NoReg, | 309 Register reg2 = NoReg, |
| 432 Register reg3 = NoReg, | 310 Register reg3 = NoReg, |
| 433 Register reg4 = NoReg); | 311 Register reg4 = NoReg); |
| 434 | 312 |
| 435 | 313 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 450 // arguments. At least one argument (reg1) must be valid (not NoCPUReg). | 328 // arguments. At least one argument (reg1) must be valid (not NoCPUReg). |
| 451 bool AreSameSizeAndType(const CPURegister& reg1, | 329 bool AreSameSizeAndType(const CPURegister& reg1, |
| 452 const CPURegister& reg2, | 330 const CPURegister& reg2, |
| 453 const CPURegister& reg3 = NoCPUReg, | 331 const CPURegister& reg3 = NoCPUReg, |
| 454 const CPURegister& reg4 = NoCPUReg, | 332 const CPURegister& reg4 = NoCPUReg, |
| 455 const CPURegister& reg5 = NoCPUReg, | 333 const CPURegister& reg5 = NoCPUReg, |
| 456 const CPURegister& reg6 = NoCPUReg, | 334 const CPURegister& reg6 = NoCPUReg, |
| 457 const CPURegister& reg7 = NoCPUReg, | 335 const CPURegister& reg7 = NoCPUReg, |
| 458 const CPURegister& reg8 = NoCPUReg); | 336 const CPURegister& reg8 = NoCPUReg); |
| 459 | 337 |
| 460 // AreSameFormat returns true if all of the specified VRegisters have the same | 338 typedef FPRegister FloatRegister; |
| 461 // vector format. Arguments set to NoVReg are ignored, as are any subsequent | 339 typedef FPRegister DoubleRegister; |
| 462 // arguments. At least one argument (reg1) must be valid (not NoVReg). | |
| 463 bool AreSameFormat(const VRegister& reg1, const VRegister& reg2, | |
| 464 const VRegister& reg3 = NoVReg, | |
| 465 const VRegister& reg4 = NoVReg); | |
| 466 | 340 |
| 467 // AreConsecutive returns true if all of the specified VRegisters are | 341 // TODO(arm64) Define SIMD registers. |
| 468 // consecutive in the register file. Arguments may be set to NoVReg, and if so, | 342 typedef FPRegister Simd128Register; |
| 469 // subsequent arguments must also be NoVReg. At least one argument (reg1) must | |
| 470 // be valid (not NoVReg). | |
| 471 bool AreConsecutive(const VRegister& reg1, const VRegister& reg2, | |
| 472 const VRegister& reg3 = NoVReg, | |
| 473 const VRegister& reg4 = NoVReg); | |
| 474 | |
| 475 typedef VRegister FloatRegister; | |
| 476 typedef VRegister DoubleRegister; | |
| 477 typedef VRegister Simd128Register; | |
| 478 | 343 |
| 479 // ----------------------------------------------------------------------------- | 344 // ----------------------------------------------------------------------------- |
| 480 // Lists of registers. | 345 // Lists of registers. |
| 481 class CPURegList { | 346 class CPURegList { |
| 482 public: | 347 public: |
| 483 explicit CPURegList(CPURegister reg1, | 348 explicit CPURegList(CPURegister reg1, |
| 484 CPURegister reg2 = NoCPUReg, | 349 CPURegister reg2 = NoCPUReg, |
| 485 CPURegister reg3 = NoCPUReg, | 350 CPURegister reg3 = NoCPUReg, |
| 486 CPURegister reg4 = NoCPUReg) | 351 CPURegister reg4 = NoCPUReg) |
| 487 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), | 352 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), |
| 488 size_(reg1.SizeInBits()), type_(reg1.type()) { | 353 size_(reg1.SizeInBits()), type_(reg1.type()) { |
| 489 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4)); | 354 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4)); |
| 490 DCHECK(IsValid()); | 355 DCHECK(IsValid()); |
| 491 } | 356 } |
| 492 | 357 |
| 493 CPURegList(CPURegister::RegisterType type, int size, RegList list) | 358 CPURegList(CPURegister::RegisterType type, int size, RegList list) |
| 494 : list_(list), size_(size), type_(type) { | 359 : list_(list), size_(size), type_(type) { |
| 495 DCHECK(IsValid()); | 360 DCHECK(IsValid()); |
| 496 } | 361 } |
| 497 | 362 |
| 498 CPURegList(CPURegister::RegisterType type, int size, int first_reg, | 363 CPURegList(CPURegister::RegisterType type, int size, int first_reg, |
| 499 int last_reg) | 364 int last_reg) |
| 500 : size_(size), type_(type) { | 365 : size_(size), type_(type) { |
| 501 DCHECK( | 366 DCHECK(((type == CPURegister::kRegister) && |
| 502 ((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) || | 367 (last_reg < kNumberOfRegisters)) || |
| 503 ((type == CPURegister::kVRegister) && | 368 ((type == CPURegister::kFPRegister) && |
| 504 (last_reg < kNumberOfVRegisters))); | 369 (last_reg < kNumberOfFPRegisters))); |
| 505 DCHECK(last_reg >= first_reg); | 370 DCHECK(last_reg >= first_reg); |
| 506 list_ = (1UL << (last_reg + 1)) - 1; | 371 list_ = (1UL << (last_reg + 1)) - 1; |
| 507 list_ &= ~((1UL << first_reg) - 1); | 372 list_ &= ~((1UL << first_reg) - 1); |
| 508 DCHECK(IsValid()); | 373 DCHECK(IsValid()); |
| 509 } | 374 } |
| 510 | 375 |
| 511 CPURegister::RegisterType type() const { | 376 CPURegister::RegisterType type() const { |
| 512 DCHECK(IsValid()); | 377 DCHECK(IsValid()); |
| 513 return type_; | 378 return type_; |
| 514 } | 379 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 | 412 |
| 548 // Remove all callee-saved registers from the list. This can be useful when | 413 // Remove all callee-saved registers from the list. This can be useful when |
| 549 // preparing registers for an AAPCS64 function call, for example. | 414 // preparing registers for an AAPCS64 function call, for example. |
| 550 void RemoveCalleeSaved(); | 415 void RemoveCalleeSaved(); |
| 551 | 416 |
| 552 CPURegister PopLowestIndex(); | 417 CPURegister PopLowestIndex(); |
| 553 CPURegister PopHighestIndex(); | 418 CPURegister PopHighestIndex(); |
| 554 | 419 |
| 555 // AAPCS64 callee-saved registers. | 420 // AAPCS64 callee-saved registers. |
| 556 static CPURegList GetCalleeSaved(int size = kXRegSizeInBits); | 421 static CPURegList GetCalleeSaved(int size = kXRegSizeInBits); |
| 557 static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits); | 422 static CPURegList GetCalleeSavedFP(int size = kDRegSizeInBits); |
| 558 | 423 |
| 559 // AAPCS64 caller-saved registers. Note that this includes lr. | 424 // AAPCS64 caller-saved registers. Note that this includes lr. |
| 560 // TODO(all): Determine how we handle d8-d15 being callee-saved, but the top | |
| 561 // 64-bits being caller-saved. | |
| 562 static CPURegList GetCallerSaved(int size = kXRegSizeInBits); | 425 static CPURegList GetCallerSaved(int size = kXRegSizeInBits); |
| 563 static CPURegList GetCallerSavedV(int size = kDRegSizeInBits); | 426 static CPURegList GetCallerSavedFP(int size = kDRegSizeInBits); |
| 564 | 427 |
| 565 // Registers saved as safepoints. | 428 // Registers saved as safepoints. |
| 566 static CPURegList GetSafepointSavedRegisters(); | 429 static CPURegList GetSafepointSavedRegisters(); |
| 567 | 430 |
| 568 bool IsEmpty() const { | 431 bool IsEmpty() const { |
| 569 DCHECK(IsValid()); | 432 DCHECK(IsValid()); |
| 570 return list_ == 0; | 433 return list_ == 0; |
| 571 } | 434 } |
| 572 | 435 |
| 573 bool IncludesAliasOf(const CPURegister& other1, | 436 bool IncludesAliasOf(const CPURegister& other1, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 604 return RegisterSizeInBytes() * Count(); | 467 return RegisterSizeInBytes() * Count(); |
| 605 } | 468 } |
| 606 | 469 |
| 607 private: | 470 private: |
| 608 RegList list_; | 471 RegList list_; |
| 609 int size_; | 472 int size_; |
| 610 CPURegister::RegisterType type_; | 473 CPURegister::RegisterType type_; |
| 611 | 474 |
| 612 bool IsValid() const { | 475 bool IsValid() const { |
| 613 const RegList kValidRegisters = 0x8000000ffffffff; | 476 const RegList kValidRegisters = 0x8000000ffffffff; |
| 614 const RegList kValidVRegisters = 0x0000000ffffffff; | 477 const RegList kValidFPRegisters = 0x0000000ffffffff; |
| 615 switch (type_) { | 478 switch (type_) { |
| 616 case CPURegister::kRegister: | 479 case CPURegister::kRegister: |
| 617 return (list_ & kValidRegisters) == list_; | 480 return (list_ & kValidRegisters) == list_; |
| 618 case CPURegister::kVRegister: | 481 case CPURegister::kFPRegister: |
| 619 return (list_ & kValidVRegisters) == list_; | 482 return (list_ & kValidFPRegisters) == list_; |
| 620 case CPURegister::kNoRegister: | 483 case CPURegister::kNoRegister: |
| 621 return list_ == 0; | 484 return list_ == 0; |
| 622 default: | 485 default: |
| 623 UNREACHABLE(); | 486 UNREACHABLE(); |
| 624 return false; | 487 return false; |
| 625 } | 488 } |
| 626 } | 489 } |
| 627 }; | 490 }; |
| 628 | 491 |
| 629 | 492 |
| 630 // AAPCS64 callee-saved registers. | 493 // AAPCS64 callee-saved registers. |
| 631 #define kCalleeSaved CPURegList::GetCalleeSaved() | 494 #define kCalleeSaved CPURegList::GetCalleeSaved() |
| 632 #define kCalleeSavedV CPURegList::GetCalleeSavedV() | 495 #define kCalleeSavedFP CPURegList::GetCalleeSavedFP() |
| 496 |
| 633 | 497 |
| 634 // AAPCS64 caller-saved registers. Note that this includes lr. | 498 // AAPCS64 caller-saved registers. Note that this includes lr. |
| 635 #define kCallerSaved CPURegList::GetCallerSaved() | 499 #define kCallerSaved CPURegList::GetCallerSaved() |
| 636 #define kCallerSavedV CPURegList::GetCallerSavedV() | 500 #define kCallerSavedFP CPURegList::GetCallerSavedFP() |
| 637 | 501 |
| 638 // ----------------------------------------------------------------------------- | 502 // ----------------------------------------------------------------------------- |
| 639 // Immediates. | 503 // Immediates. |
| 640 class Immediate { | 504 class Immediate { |
| 641 public: | 505 public: |
| 642 template<typename T> | 506 template<typename T> |
| 643 inline explicit Immediate(Handle<T> handle); | 507 inline explicit Immediate(Handle<T> handle); |
| 644 | 508 |
| 645 // This is allowed to be an implicit constructor because Immediate is | 509 // This is allowed to be an implicit constructor because Immediate is |
| 646 // a wrapper class that doesn't normally perform any type conversion. | 510 // a wrapper class that doesn't normally perform any type conversion. |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 // Bit clear (A & ~B). | 1057 // Bit clear (A & ~B). |
| 1194 void bic(const Register& rd, | 1058 void bic(const Register& rd, |
| 1195 const Register& rn, | 1059 const Register& rn, |
| 1196 const Operand& operand); | 1060 const Operand& operand); |
| 1197 | 1061 |
| 1198 // Bit clear (A & ~B) and update status flags. | 1062 // Bit clear (A & ~B) and update status flags. |
| 1199 void bics(const Register& rd, | 1063 void bics(const Register& rd, |
| 1200 const Register& rn, | 1064 const Register& rn, |
| 1201 const Operand& operand); | 1065 const Operand& operand); |
| 1202 | 1066 |
| 1203 // Bitwise and. | |
| 1204 void and_(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1205 | |
| 1206 // Bit clear immediate. | |
| 1207 void bic(const VRegister& vd, const int imm8, const int left_shift = 0); | |
| 1208 | |
| 1209 // Bit clear. | |
| 1210 void bic(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1211 | |
| 1212 // Bitwise insert if false. | |
| 1213 void bif(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1214 | |
| 1215 // Bitwise insert if true. | |
| 1216 void bit(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1217 | |
| 1218 // Bitwise select. | |
| 1219 void bsl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1220 | |
| 1221 // Polynomial multiply. | |
| 1222 void pmul(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1223 | |
| 1224 // Vector move immediate. | |
| 1225 void movi(const VRegister& vd, const uint64_t imm, Shift shift = LSL, | |
| 1226 const int shift_amount = 0); | |
| 1227 | |
| 1228 // Bitwise not. | |
| 1229 void mvn(const VRegister& vd, const VRegister& vn); | |
| 1230 | |
| 1231 // Vector move inverted immediate. | |
| 1232 void mvni(const VRegister& vd, const int imm8, Shift shift = LSL, | |
| 1233 const int shift_amount = 0); | |
| 1234 | |
| 1235 // Signed saturating accumulate of unsigned value. | |
| 1236 void suqadd(const VRegister& vd, const VRegister& vn); | |
| 1237 | |
| 1238 // Unsigned saturating accumulate of signed value. | |
| 1239 void usqadd(const VRegister& vd, const VRegister& vn); | |
| 1240 | |
| 1241 // Absolute value. | |
| 1242 void abs(const VRegister& vd, const VRegister& vn); | |
| 1243 | |
| 1244 // Signed saturating absolute value. | |
| 1245 void sqabs(const VRegister& vd, const VRegister& vn); | |
| 1246 | |
| 1247 // Negate. | |
| 1248 void neg(const VRegister& vd, const VRegister& vn); | |
| 1249 | |
| 1250 // Signed saturating negate. | |
| 1251 void sqneg(const VRegister& vd, const VRegister& vn); | |
| 1252 | |
| 1253 // Bitwise not. | |
| 1254 void not_(const VRegister& vd, const VRegister& vn); | |
| 1255 | |
| 1256 // Extract narrow. | |
| 1257 void xtn(const VRegister& vd, const VRegister& vn); | |
| 1258 | |
| 1259 // Extract narrow (second part). | |
| 1260 void xtn2(const VRegister& vd, const VRegister& vn); | |
| 1261 | |
| 1262 // Signed saturating extract narrow. | |
| 1263 void sqxtn(const VRegister& vd, const VRegister& vn); | |
| 1264 | |
| 1265 // Signed saturating extract narrow (second part). | |
| 1266 void sqxtn2(const VRegister& vd, const VRegister& vn); | |
| 1267 | |
| 1268 // Unsigned saturating extract narrow. | |
| 1269 void uqxtn(const VRegister& vd, const VRegister& vn); | |
| 1270 | |
| 1271 // Unsigned saturating extract narrow (second part). | |
| 1272 void uqxtn2(const VRegister& vd, const VRegister& vn); | |
| 1273 | |
| 1274 // Signed saturating extract unsigned narrow. | |
| 1275 void sqxtun(const VRegister& vd, const VRegister& vn); | |
| 1276 | |
| 1277 // Signed saturating extract unsigned narrow (second part). | |
| 1278 void sqxtun2(const VRegister& vd, const VRegister& vn); | |
| 1279 | |
| 1280 // Move register to register. | |
| 1281 void mov(const VRegister& vd, const VRegister& vn); | |
| 1282 | |
| 1283 // Bitwise not or. | |
| 1284 void orn(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1285 | |
| 1286 // Bitwise exclusive or. | |
| 1287 void eor(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1288 | |
| 1289 // Bitwise or (A | B). | 1067 // Bitwise or (A | B). |
| 1290 void orr(const Register& rd, const Register& rn, const Operand& operand); | 1068 void orr(const Register& rd, const Register& rn, const Operand& operand); |
| 1291 | 1069 |
| 1292 // Bitwise or. | |
| 1293 void orr(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1294 | |
| 1295 // Bitwise or immediate. | |
| 1296 void orr(const VRegister& vd, const int imm8, const int left_shift = 0); | |
| 1297 | |
| 1298 // Bitwise nor (A | ~B). | 1070 // Bitwise nor (A | ~B). |
| 1299 void orn(const Register& rd, const Register& rn, const Operand& operand); | 1071 void orn(const Register& rd, const Register& rn, const Operand& operand); |
| 1300 | 1072 |
| 1301 // Bitwise eor/xor (A ^ B). | 1073 // Bitwise eor/xor (A ^ B). |
| 1302 void eor(const Register& rd, const Register& rn, const Operand& operand); | 1074 void eor(const Register& rd, const Register& rn, const Operand& operand); |
| 1303 | 1075 |
| 1304 // Bitwise enor/xnor (A ^ ~B). | 1076 // Bitwise enor/xnor (A ^ ~B). |
| 1305 void eon(const Register& rd, const Register& rn, const Operand& operand); | 1077 void eon(const Register& rd, const Register& rn, const Operand& operand); |
| 1306 | 1078 |
| 1307 // Logical shift left variable. | 1079 // Logical shift left variable. |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1694 ADR_FAR_NOP, | 1466 ADR_FAR_NOP, |
| 1695 FIRST_NOP_MARKER = DEBUG_BREAK_NOP, | 1467 FIRST_NOP_MARKER = DEBUG_BREAK_NOP, |
| 1696 LAST_NOP_MARKER = ADR_FAR_NOP | 1468 LAST_NOP_MARKER = ADR_FAR_NOP |
| 1697 }; | 1469 }; |
| 1698 | 1470 |
| 1699 void nop(NopMarkerTypes n) { | 1471 void nop(NopMarkerTypes n) { |
| 1700 DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER)); | 1472 DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER)); |
| 1701 mov(Register::XRegFromCode(n), Register::XRegFromCode(n)); | 1473 mov(Register::XRegFromCode(n), Register::XRegFromCode(n)); |
| 1702 } | 1474 } |
| 1703 | 1475 |
| 1704 // Add. | |
| 1705 void add(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1706 | |
| 1707 // Unsigned halving add. | |
| 1708 void uhadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1709 | |
| 1710 // Subtract. | |
| 1711 void sub(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1712 | |
| 1713 // Signed halving add. | |
| 1714 void shadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1715 | |
| 1716 // Multiply by scalar element. | |
| 1717 void mul(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1718 int vm_index); | |
| 1719 | |
| 1720 // Multiply-add by scalar element. | |
| 1721 void mla(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1722 int vm_index); | |
| 1723 | |
| 1724 // Multiply-subtract by scalar element. | |
| 1725 void mls(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1726 int vm_index); | |
| 1727 | |
| 1728 // Signed long multiply-add by scalar element. | |
| 1729 void smlal(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1730 int vm_index); | |
| 1731 | |
| 1732 // Signed long multiply-add by scalar element (second part). | |
| 1733 void smlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1734 int vm_index); | |
| 1735 | |
| 1736 // Unsigned long multiply-add by scalar element. | |
| 1737 void umlal(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1738 int vm_index); | |
| 1739 | |
| 1740 // Unsigned long multiply-add by scalar element (second part). | |
| 1741 void umlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1742 int vm_index); | |
| 1743 | |
| 1744 // Signed long multiply-sub by scalar element. | |
| 1745 void smlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1746 int vm_index); | |
| 1747 | |
| 1748 // Signed long multiply-sub by scalar element (second part). | |
| 1749 void smlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1750 int vm_index); | |
| 1751 | |
| 1752 // Unsigned long multiply-sub by scalar element. | |
| 1753 void umlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1754 int vm_index); | |
| 1755 | |
| 1756 // Unsigned long multiply-sub by scalar element (second part). | |
| 1757 void umlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1758 int vm_index); | |
| 1759 | |
| 1760 // Signed long multiply by scalar element. | |
| 1761 void smull(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1762 int vm_index); | |
| 1763 | |
| 1764 // Signed long multiply by scalar element (second part). | |
| 1765 void smull2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1766 int vm_index); | |
| 1767 | |
| 1768 // Unsigned long multiply by scalar element. | |
| 1769 void umull(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1770 int vm_index); | |
| 1771 | |
| 1772 // Unsigned long multiply by scalar element (second part). | |
| 1773 void umull2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1774 int vm_index); | |
| 1775 | |
| 1776 // Add narrow returning high half. | |
| 1777 void addhn(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1778 | |
| 1779 // Add narrow returning high half (second part). | |
| 1780 void addhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1781 | |
| 1782 // Signed saturating double long multiply by element. | |
| 1783 void sqdmull(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1784 int vm_index); | |
| 1785 | |
| 1786 // Signed saturating double long multiply by element (second part). | |
| 1787 void sqdmull2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1788 int vm_index); | |
| 1789 | |
| 1790 // Signed saturating doubling long multiply-add by element. | |
| 1791 void sqdmlal(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1792 int vm_index); | |
| 1793 | |
| 1794 // Signed saturating doubling long multiply-add by element (second part). | |
| 1795 void sqdmlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1796 int vm_index); | |
| 1797 | |
| 1798 // Signed saturating doubling long multiply-sub by element. | |
| 1799 void sqdmlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1800 int vm_index); | |
| 1801 | |
| 1802 // Signed saturating doubling long multiply-sub by element (second part). | |
| 1803 void sqdmlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1804 int vm_index); | |
| 1805 | |
| 1806 // Compare bitwise to zero. | |
| 1807 void cmeq(const VRegister& vd, const VRegister& vn, int value); | |
| 1808 | |
| 1809 // Compare signed greater than or equal to zero. | |
| 1810 void cmge(const VRegister& vd, const VRegister& vn, int value); | |
| 1811 | |
| 1812 // Compare signed greater than zero. | |
| 1813 void cmgt(const VRegister& vd, const VRegister& vn, int value); | |
| 1814 | |
| 1815 // Compare signed less than or equal to zero. | |
| 1816 void cmle(const VRegister& vd, const VRegister& vn, int value); | |
| 1817 | |
| 1818 // Compare signed less than zero. | |
| 1819 void cmlt(const VRegister& vd, const VRegister& vn, int value); | |
| 1820 | |
| 1821 // Unsigned rounding halving add. | |
| 1822 void urhadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1823 | |
| 1824 // Compare equal. | |
| 1825 void cmeq(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1826 | |
| 1827 // Compare signed greater than or equal. | |
| 1828 void cmge(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1829 | |
| 1830 // Compare signed greater than. | |
| 1831 void cmgt(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1832 | |
| 1833 // Compare unsigned higher. | |
| 1834 void cmhi(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1835 | |
| 1836 // Compare unsigned higher or same. | |
| 1837 void cmhs(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1838 | |
| 1839 // Compare bitwise test bits nonzero. | |
| 1840 void cmtst(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1841 | |
| 1842 // Signed shift left by register. | |
| 1843 void sshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1844 | |
| 1845 // Unsigned shift left by register. | |
| 1846 void ushl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1847 | |
| 1848 // Signed saturating doubling long multiply-subtract. | |
| 1849 void sqdmlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1850 | |
| 1851 // Signed saturating doubling long multiply-subtract (second part). | |
| 1852 void sqdmlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1853 | |
| 1854 // Signed saturating doubling long multiply. | |
| 1855 void sqdmull(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1856 | |
| 1857 // Signed saturating doubling long multiply (second part). | |
| 1858 void sqdmull2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1859 | |
| 1860 // Signed saturating doubling multiply returning high half. | |
| 1861 void sqdmulh(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1862 | |
| 1863 // Signed saturating rounding doubling multiply returning high half. | |
| 1864 void sqrdmulh(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1865 | |
| 1866 // Signed saturating doubling multiply element returning high half. | |
| 1867 void sqdmulh(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1868 int vm_index); | |
| 1869 | |
| 1870 // Signed saturating rounding doubling multiply element returning high half. | |
| 1871 void sqrdmulh(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 1872 int vm_index); | |
| 1873 | |
| 1874 // Unsigned long multiply long. | |
| 1875 void umull(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1876 | |
| 1877 // Unsigned long multiply (second part). | |
| 1878 void umull2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1879 | |
| 1880 // Rounding add narrow returning high half. | |
| 1881 void raddhn(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1882 | |
| 1883 // Subtract narrow returning high half. | |
| 1884 void subhn(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1885 | |
| 1886 // Subtract narrow returning high half (second part). | |
| 1887 void subhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1888 | |
| 1889 // Rounding add narrow returning high half (second part). | |
| 1890 void raddhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1891 | |
| 1892 // Rounding subtract narrow returning high half. | |
| 1893 void rsubhn(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1894 | |
| 1895 // Rounding subtract narrow returning high half (second part). | |
| 1896 void rsubhn2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1897 | |
| 1898 // Signed saturating shift left by register. | |
| 1899 void sqshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1900 | |
| 1901 // Unsigned saturating shift left by register. | |
| 1902 void uqshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1903 | |
| 1904 // Signed rounding shift left by register. | |
| 1905 void srshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1906 | |
| 1907 // Unsigned rounding shift left by register. | |
| 1908 void urshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1909 | |
| 1910 // Signed saturating rounding shift left by register. | |
| 1911 void sqrshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1912 | |
| 1913 // Unsigned saturating rounding shift left by register. | |
| 1914 void uqrshl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1915 | |
| 1916 // Signed absolute difference. | |
| 1917 void sabd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1918 | |
| 1919 // Unsigned absolute difference and accumulate. | |
| 1920 void uaba(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1921 | |
| 1922 // Shift left by immediate and insert. | |
| 1923 void sli(const VRegister& vd, const VRegister& vn, int shift); | |
| 1924 | |
| 1925 // Shift right by immediate and insert. | |
| 1926 void sri(const VRegister& vd, const VRegister& vn, int shift); | |
| 1927 | |
| 1928 // Signed maximum. | |
| 1929 void smax(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1930 | |
| 1931 // Signed pairwise maximum. | |
| 1932 void smaxp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1933 | |
| 1934 // Add across vector. | |
| 1935 void addv(const VRegister& vd, const VRegister& vn); | |
| 1936 | |
| 1937 // Signed add long across vector. | |
| 1938 void saddlv(const VRegister& vd, const VRegister& vn); | |
| 1939 | |
| 1940 // Unsigned add long across vector. | |
| 1941 void uaddlv(const VRegister& vd, const VRegister& vn); | |
| 1942 | |
| 1943 // FP maximum number across vector. | |
| 1944 void fmaxnmv(const VRegister& vd, const VRegister& vn); | |
| 1945 | |
| 1946 // FP maximum across vector. | |
| 1947 void fmaxv(const VRegister& vd, const VRegister& vn); | |
| 1948 | |
| 1949 // FP minimum number across vector. | |
| 1950 void fminnmv(const VRegister& vd, const VRegister& vn); | |
| 1951 | |
| 1952 // FP minimum across vector. | |
| 1953 void fminv(const VRegister& vd, const VRegister& vn); | |
| 1954 | |
| 1955 // Signed maximum across vector. | |
| 1956 void smaxv(const VRegister& vd, const VRegister& vn); | |
| 1957 | |
| 1958 // Signed minimum. | |
| 1959 void smin(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1960 | |
| 1961 // Signed minimum pairwise. | |
| 1962 void sminp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 1963 | |
| 1964 // Signed minimum across vector. | |
| 1965 void sminv(const VRegister& vd, const VRegister& vn); | |
| 1966 | |
| 1967 // One-element structure store from one register. | |
| 1968 void st1(const VRegister& vt, const MemOperand& src); | |
| 1969 | |
| 1970 // One-element structure store from two registers. | |
| 1971 void st1(const VRegister& vt, const VRegister& vt2, const MemOperand& src); | |
| 1972 | |
| 1973 // One-element structure store from three registers. | |
| 1974 void st1(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 1975 const MemOperand& src); | |
| 1976 | |
| 1977 // One-element structure store from four registers. | |
| 1978 void st1(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 1979 const VRegister& vt4, const MemOperand& src); | |
| 1980 | |
| 1981 // One-element single structure store from one lane. | |
| 1982 void st1(const VRegister& vt, int lane, const MemOperand& src); | |
| 1983 | |
| 1984 // Two-element structure store from two registers. | |
| 1985 void st2(const VRegister& vt, const VRegister& vt2, const MemOperand& src); | |
| 1986 | |
| 1987 // Two-element single structure store from two lanes. | |
| 1988 void st2(const VRegister& vt, const VRegister& vt2, int lane, | |
| 1989 const MemOperand& src); | |
| 1990 | |
| 1991 // Three-element structure store from three registers. | |
| 1992 void st3(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 1993 const MemOperand& src); | |
| 1994 | |
| 1995 // Three-element single structure store from three lanes. | |
| 1996 void st3(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 1997 int lane, const MemOperand& src); | |
| 1998 | |
| 1999 // Four-element structure store from four registers. | |
| 2000 void st4(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2001 const VRegister& vt4, const MemOperand& src); | |
| 2002 | |
| 2003 // Four-element single structure store from four lanes. | |
| 2004 void st4(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2005 const VRegister& vt4, int lane, const MemOperand& src); | |
| 2006 | |
| 2007 // Unsigned add long. | |
| 2008 void uaddl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2009 | |
| 2010 // Unsigned add long (second part). | |
| 2011 void uaddl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2012 | |
| 2013 // Unsigned add wide. | |
| 2014 void uaddw(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2015 | |
| 2016 // Unsigned add wide (second part). | |
| 2017 void uaddw2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2018 | |
| 2019 // Signed add long. | |
| 2020 void saddl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2021 | |
| 2022 // Signed add long (second part). | |
| 2023 void saddl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2024 | |
| 2025 // Signed add wide. | |
| 2026 void saddw(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2027 | |
| 2028 // Signed add wide (second part). | |
| 2029 void saddw2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2030 | |
| 2031 // Unsigned subtract long. | |
| 2032 void usubl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2033 | |
| 2034 // Unsigned subtract long (second part). | |
| 2035 void usubl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2036 | |
| 2037 // Unsigned subtract wide. | |
| 2038 void usubw(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2039 | |
| 2040 // Signed subtract long. | |
| 2041 void ssubl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2042 | |
| 2043 // Signed subtract long (second part). | |
| 2044 void ssubl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2045 | |
| 2046 // Signed integer subtract wide. | |
| 2047 void ssubw(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2048 | |
| 2049 // Signed integer subtract wide (second part). | |
| 2050 void ssubw2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2051 | |
| 2052 // Unsigned subtract wide (second part). | |
| 2053 void usubw2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2054 | |
| 2055 // Unsigned maximum. | |
| 2056 void umax(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2057 | |
| 2058 // Unsigned pairwise maximum. | |
| 2059 void umaxp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2060 | |
| 2061 // Unsigned maximum across vector. | |
| 2062 void umaxv(const VRegister& vd, const VRegister& vn); | |
| 2063 | |
| 2064 // Unsigned minimum. | |
| 2065 void umin(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2066 | |
| 2067 // Unsigned pairwise minimum. | |
| 2068 void uminp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2069 | |
| 2070 // Unsigned minimum across vector. | |
| 2071 void uminv(const VRegister& vd, const VRegister& vn); | |
| 2072 | |
| 2073 // Transpose vectors (primary). | |
| 2074 void trn1(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2075 | |
| 2076 // Transpose vectors (secondary). | |
| 2077 void trn2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2078 | |
| 2079 // Unzip vectors (primary). | |
| 2080 void uzp1(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2081 | |
| 2082 // Unzip vectors (secondary). | |
| 2083 void uzp2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2084 | |
| 2085 // Zip vectors (primary). | |
| 2086 void zip1(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2087 | |
| 2088 // Zip vectors (secondary). | |
| 2089 void zip2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2090 | |
| 2091 // Signed shift right by immediate. | |
| 2092 void sshr(const VRegister& vd, const VRegister& vn, int shift); | |
| 2093 | |
| 2094 // Unsigned shift right by immediate. | |
| 2095 void ushr(const VRegister& vd, const VRegister& vn, int shift); | |
| 2096 | |
| 2097 // Signed rounding shift right by immediate. | |
| 2098 void srshr(const VRegister& vd, const VRegister& vn, int shift); | |
| 2099 | |
| 2100 // Unsigned rounding shift right by immediate. | |
| 2101 void urshr(const VRegister& vd, const VRegister& vn, int shift); | |
| 2102 | |
| 2103 // Signed shift right by immediate and accumulate. | |
| 2104 void ssra(const VRegister& vd, const VRegister& vn, int shift); | |
| 2105 | |
| 2106 // Unsigned shift right by immediate and accumulate. | |
| 2107 void usra(const VRegister& vd, const VRegister& vn, int shift); | |
| 2108 | |
| 2109 // Signed rounding shift right by immediate and accumulate. | |
| 2110 void srsra(const VRegister& vd, const VRegister& vn, int shift); | |
| 2111 | |
| 2112 // Unsigned rounding shift right by immediate and accumulate. | |
| 2113 void ursra(const VRegister& vd, const VRegister& vn, int shift); | |
| 2114 | |
| 2115 // Shift right narrow by immediate. | |
| 2116 void shrn(const VRegister& vd, const VRegister& vn, int shift); | |
| 2117 | |
| 2118 // Shift right narrow by immediate (second part). | |
| 2119 void shrn2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2120 | |
| 2121 // Rounding shift right narrow by immediate. | |
| 2122 void rshrn(const VRegister& vd, const VRegister& vn, int shift); | |
| 2123 | |
| 2124 // Rounding shift right narrow by immediate (second part). | |
| 2125 void rshrn2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2126 | |
| 2127 // Unsigned saturating shift right narrow by immediate. | |
| 2128 void uqshrn(const VRegister& vd, const VRegister& vn, int shift); | |
| 2129 | |
| 2130 // Unsigned saturating shift right narrow by immediate (second part). | |
| 2131 void uqshrn2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2132 | |
| 2133 // Unsigned saturating rounding shift right narrow by immediate. | |
| 2134 void uqrshrn(const VRegister& vd, const VRegister& vn, int shift); | |
| 2135 | |
| 2136 // Unsigned saturating rounding shift right narrow by immediate (second part). | |
| 2137 void uqrshrn2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2138 | |
| 2139 // Signed saturating shift right narrow by immediate. | |
| 2140 void sqshrn(const VRegister& vd, const VRegister& vn, int shift); | |
| 2141 | |
| 2142 // Signed saturating shift right narrow by immediate (second part). | |
| 2143 void sqshrn2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2144 | |
| 2145 // Signed saturating rounded shift right narrow by immediate. | |
| 2146 void sqrshrn(const VRegister& vd, const VRegister& vn, int shift); | |
| 2147 | |
| 2148 // Signed saturating rounded shift right narrow by immediate (second part). | |
| 2149 void sqrshrn2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2150 | |
| 2151 // Signed saturating shift right unsigned narrow by immediate. | |
| 2152 void sqshrun(const VRegister& vd, const VRegister& vn, int shift); | |
| 2153 | |
| 2154 // Signed saturating shift right unsigned narrow by immediate (second part). | |
| 2155 void sqshrun2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2156 | |
| 2157 // Signed sat rounded shift right unsigned narrow by immediate. | |
| 2158 void sqrshrun(const VRegister& vd, const VRegister& vn, int shift); | |
| 2159 | |
| 2160 // Signed sat rounded shift right unsigned narrow by immediate (second part). | |
| 2161 void sqrshrun2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2162 | |
| 2163 // FP reciprocal step. | |
| 2164 void frecps(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2165 | |
| 2166 // FP reciprocal estimate. | |
| 2167 void frecpe(const VRegister& vd, const VRegister& vn); | |
| 2168 | |
| 2169 // FP reciprocal square root estimate. | |
| 2170 void frsqrte(const VRegister& vd, const VRegister& vn); | |
| 2171 | |
| 2172 // FP reciprocal square root step. | |
| 2173 void frsqrts(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2174 | |
| 2175 // Signed absolute difference and accumulate long. | |
| 2176 void sabal(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2177 | |
| 2178 // Signed absolute difference and accumulate long (second part). | |
| 2179 void sabal2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2180 | |
| 2181 // Unsigned absolute difference and accumulate long. | |
| 2182 void uabal(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2183 | |
| 2184 // Unsigned absolute difference and accumulate long (second part). | |
| 2185 void uabal2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2186 | |
| 2187 // Signed absolute difference long. | |
| 2188 void sabdl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2189 | |
| 2190 // Signed absolute difference long (second part). | |
| 2191 void sabdl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2192 | |
| 2193 // Unsigned absolute difference long. | |
| 2194 void uabdl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2195 | |
| 2196 // Unsigned absolute difference long (second part). | |
| 2197 void uabdl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2198 | |
| 2199 // Polynomial multiply long. | |
| 2200 void pmull(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2201 | |
| 2202 // Polynomial multiply long (second part). | |
| 2203 void pmull2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2204 | |
| 2205 // Signed long multiply-add. | |
| 2206 void smlal(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2207 | |
| 2208 // Signed long multiply-add (second part). | |
| 2209 void smlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2210 | |
| 2211 // Unsigned long multiply-add. | |
| 2212 void umlal(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2213 | |
| 2214 // Unsigned long multiply-add (second part). | |
| 2215 void umlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2216 | |
| 2217 // Signed long multiply-sub. | |
| 2218 void smlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2219 | |
| 2220 // Signed long multiply-sub (second part). | |
| 2221 void smlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2222 | |
| 2223 // Unsigned long multiply-sub. | |
| 2224 void umlsl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2225 | |
| 2226 // Unsigned long multiply-sub (second part). | |
| 2227 void umlsl2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2228 | |
| 2229 // Signed long multiply. | |
| 2230 void smull(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2231 | |
| 2232 // Signed long multiply (second part). | |
| 2233 void smull2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2234 | |
| 2235 // Signed saturating doubling long multiply-add. | |
| 2236 void sqdmlal(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2237 | |
| 2238 // Signed saturating doubling long multiply-add (second part). | |
| 2239 void sqdmlal2(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2240 | |
| 2241 // Unsigned absolute difference. | |
| 2242 void uabd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2243 | |
| 2244 // Signed absolute difference and accumulate. | |
| 2245 void saba(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2246 | |
| 2247 // FP instructions. | 1476 // FP instructions. |
| 2248 // Move immediate to FP register. | 1477 // Move immediate to FP register. |
| 2249 void fmov(const VRegister& fd, double imm); | 1478 void fmov(FPRegister fd, double imm); |
| 2250 void fmov(const VRegister& fd, float imm); | 1479 void fmov(FPRegister fd, float imm); |
| 2251 | 1480 |
| 2252 // Move FP register to register. | 1481 // Move FP register to register. |
| 2253 void fmov(const Register& rd, const VRegister& fn); | 1482 void fmov(Register rd, FPRegister fn); |
| 2254 | 1483 |
| 2255 // Move register to FP register. | 1484 // Move register to FP register. |
| 2256 void fmov(const VRegister& fd, const Register& rn); | 1485 void fmov(FPRegister fd, Register rn); |
| 2257 | 1486 |
| 2258 // Move FP register to FP register. | 1487 // Move FP register to FP register. |
| 2259 void fmov(const VRegister& fd, const VRegister& fn); | 1488 void fmov(FPRegister fd, FPRegister fn); |
| 2260 | |
| 2261 // Move 64-bit register to top half of 128-bit FP register. | |
| 2262 void fmov(const VRegister& vd, int index, const Register& rn); | |
| 2263 | |
| 2264 // Move top half of 128-bit FP register to 64-bit register. | |
| 2265 void fmov(const Register& rd, const VRegister& vn, int index); | |
| 2266 | 1489 |
| 2267 // FP add. | 1490 // FP add. |
| 2268 void fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1491 void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2269 | 1492 |
| 2270 // FP subtract. | 1493 // FP subtract. |
| 2271 void fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1494 void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2272 | 1495 |
| 2273 // FP multiply. | 1496 // FP multiply. |
| 2274 void fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1497 void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2275 | 1498 |
| 2276 // FP compare equal to zero. | 1499 // FP fused multiply and add. |
| 2277 void fcmeq(const VRegister& vd, const VRegister& vn, double imm); | 1500 void fmadd(const FPRegister& fd, |
| 1501 const FPRegister& fn, |
| 1502 const FPRegister& fm, |
| 1503 const FPRegister& fa); |
| 2278 | 1504 |
| 2279 // FP greater than zero. | 1505 // FP fused multiply and subtract. |
| 2280 void fcmgt(const VRegister& vd, const VRegister& vn, double imm); | 1506 void fmsub(const FPRegister& fd, |
| 1507 const FPRegister& fn, |
| 1508 const FPRegister& fm, |
| 1509 const FPRegister& fa); |
| 2281 | 1510 |
| 2282 // FP greater than or equal to zero. | 1511 // FP fused multiply, add and negate. |
| 2283 void fcmge(const VRegister& vd, const VRegister& vn, double imm); | 1512 void fnmadd(const FPRegister& fd, |
| 1513 const FPRegister& fn, |
| 1514 const FPRegister& fm, |
| 1515 const FPRegister& fa); |
| 2284 | 1516 |
| 2285 // FP less than or equal to zero. | 1517 // FP fused multiply, subtract and negate. |
| 2286 void fcmle(const VRegister& vd, const VRegister& vn, double imm); | 1518 void fnmsub(const FPRegister& fd, |
| 2287 | 1519 const FPRegister& fn, |
| 2288 // FP less than to zero. | 1520 const FPRegister& fm, |
| 2289 void fcmlt(const VRegister& vd, const VRegister& vn, double imm); | 1521 const FPRegister& fa); |
| 2290 | |
| 2291 // FP absolute difference. | |
| 2292 void fabd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2293 | |
| 2294 // FP pairwise add vector. | |
| 2295 void faddp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2296 | |
| 2297 // FP pairwise add scalar. | |
| 2298 void faddp(const VRegister& vd, const VRegister& vn); | |
| 2299 | |
| 2300 // FP pairwise maximum scalar. | |
| 2301 void fmaxp(const VRegister& vd, const VRegister& vn); | |
| 2302 | |
| 2303 // FP pairwise maximum number scalar. | |
| 2304 void fmaxnmp(const VRegister& vd, const VRegister& vn); | |
| 2305 | |
| 2306 // FP pairwise minimum number scalar. | |
| 2307 void fminnmp(const VRegister& vd, const VRegister& vn); | |
| 2308 | |
| 2309 // FP vector multiply accumulate. | |
| 2310 void fmla(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2311 | |
| 2312 // FP vector multiply subtract. | |
| 2313 void fmls(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2314 | |
| 2315 // FP vector multiply extended. | |
| 2316 void fmulx(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2317 | |
| 2318 // FP absolute greater than or equal. | |
| 2319 void facge(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2320 | |
| 2321 // FP absolute greater than. | |
| 2322 void facgt(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2323 | |
| 2324 // FP multiply by element. | |
| 2325 void fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2326 int vm_index); | |
| 2327 | |
| 2328 // FP fused multiply-add to accumulator by element. | |
| 2329 void fmla(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2330 int vm_index); | |
| 2331 | |
| 2332 // FP fused multiply-sub from accumulator by element. | |
| 2333 void fmls(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2334 int vm_index); | |
| 2335 | |
| 2336 // FP multiply extended by element. | |
| 2337 void fmulx(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2338 int vm_index); | |
| 2339 | |
| 2340 // FP compare equal. | |
| 2341 void fcmeq(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2342 | |
| 2343 // FP greater than. | |
| 2344 void fcmgt(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2345 | |
| 2346 // FP greater than or equal. | |
| 2347 void fcmge(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2348 | |
| 2349 // FP pairwise maximum vector. | |
| 2350 void fmaxp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2351 | |
| 2352 // FP pairwise minimum vector. | |
| 2353 void fminp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2354 | |
| 2355 // FP pairwise minimum scalar. | |
| 2356 void fminp(const VRegister& vd, const VRegister& vn); | |
| 2357 | |
| 2358 // FP pairwise maximum number vector. | |
| 2359 void fmaxnmp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2360 | |
| 2361 // FP pairwise minimum number vector. | |
| 2362 void fminnmp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2363 | |
| 2364 // FP fused multiply-add. | |
| 2365 void fmadd(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2366 const VRegister& va); | |
| 2367 | |
| 2368 // FP fused multiply-subtract. | |
| 2369 void fmsub(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2370 const VRegister& va); | |
| 2371 | |
| 2372 // FP fused multiply-add and negate. | |
| 2373 void fnmadd(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2374 const VRegister& va); | |
| 2375 | |
| 2376 // FP fused multiply-subtract and negate. | |
| 2377 void fnmsub(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2378 const VRegister& va); | |
| 2379 | |
| 2380 // FP multiply-negate scalar. | |
| 2381 void fnmul(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2382 | |
| 2383 // FP reciprocal exponent scalar. | |
| 2384 void frecpx(const VRegister& vd, const VRegister& vn); | |
| 2385 | 1522 |
| 2386 // FP divide. | 1523 // FP divide. |
| 2387 void fdiv(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1524 void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2388 | 1525 |
| 2389 // FP maximum. | 1526 // FP maximum. |
| 2390 void fmax(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1527 void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2391 | 1528 |
| 2392 // FP minimum. | 1529 // FP minimum. |
| 2393 void fmin(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1530 void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2394 | 1531 |
| 2395 // FP maximum. | 1532 // FP maximum. |
| 2396 void fmaxnm(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1533 void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2397 | 1534 |
| 2398 // FP minimum. | 1535 // FP minimum. |
| 2399 void fminnm(const VRegister& vd, const VRegister& vn, const VRegister& vm); | 1536 void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); |
| 2400 | 1537 |
| 2401 // FP absolute. | 1538 // FP absolute. |
| 2402 void fabs(const VRegister& vd, const VRegister& vn); | 1539 void fabs(const FPRegister& fd, const FPRegister& fn); |
| 2403 | 1540 |
| 2404 // FP negate. | 1541 // FP negate. |
| 2405 void fneg(const VRegister& vd, const VRegister& vn); | 1542 void fneg(const FPRegister& fd, const FPRegister& fn); |
| 2406 | 1543 |
| 2407 // FP square root. | 1544 // FP square root. |
| 2408 void fsqrt(const VRegister& vd, const VRegister& vn); | 1545 void fsqrt(const FPRegister& fd, const FPRegister& fn); |
| 2409 | 1546 |
| 2410 // FP round to integer nearest with ties to away. | 1547 // FP round to integer (nearest with ties to away). |
| 2411 void frinta(const VRegister& vd, const VRegister& vn); | 1548 void frinta(const FPRegister& fd, const FPRegister& fn); |
| 2412 | 1549 |
| 2413 // FP round to integer, implicit rounding. | 1550 // FP round to integer (toward minus infinity). |
| 2414 void frinti(const VRegister& vd, const VRegister& vn); | 1551 void frintm(const FPRegister& fd, const FPRegister& fn); |
| 2415 | 1552 |
| 2416 // FP round to integer toward minus infinity. | 1553 // FP round to integer (nearest with ties to even). |
| 2417 void frintm(const VRegister& vd, const VRegister& vn); | 1554 void frintn(const FPRegister& fd, const FPRegister& fn); |
| 2418 | 1555 |
| 2419 // FP round to integer nearest with ties to even. | 1556 // FP round to integer (towards plus infinity). |
| 2420 void frintn(const VRegister& vd, const VRegister& vn); | 1557 void frintp(const FPRegister& fd, const FPRegister& fn); |
| 2421 | 1558 |
| 2422 // FP round to integer towards plus infinity. | 1559 // FP round to integer (towards zero.) |
| 2423 void frintp(const VRegister& vd, const VRegister& vn); | 1560 void frintz(const FPRegister& fd, const FPRegister& fn); |
| 2424 | |
| 2425 // FP round to integer, exact, implicit rounding. | |
| 2426 void frintx(const VRegister& vd, const VRegister& vn); | |
| 2427 | |
| 2428 // FP round to integer towards zero. | |
| 2429 void frintz(const VRegister& vd, const VRegister& vn); | |
| 2430 | 1561 |
| 2431 // FP compare registers. | 1562 // FP compare registers. |
| 2432 void fcmp(const VRegister& vn, const VRegister& vm); | 1563 void fcmp(const FPRegister& fn, const FPRegister& fm); |
| 2433 | 1564 |
| 2434 // FP compare immediate. | 1565 // FP compare immediate. |
| 2435 void fcmp(const VRegister& vn, double value); | 1566 void fcmp(const FPRegister& fn, double value); |
| 2436 | 1567 |
| 2437 // FP conditional compare. | 1568 // FP conditional compare. |
| 2438 void fccmp(const VRegister& vn, const VRegister& vm, StatusFlags nzcv, | 1569 void fccmp(const FPRegister& fn, |
| 1570 const FPRegister& fm, |
| 1571 StatusFlags nzcv, |
| 2439 Condition cond); | 1572 Condition cond); |
| 2440 | 1573 |
| 2441 // FP conditional select. | 1574 // FP conditional select. |
| 2442 void fcsel(const VRegister& vd, const VRegister& vn, const VRegister& vm, | 1575 void fcsel(const FPRegister& fd, |
| 1576 const FPRegister& fn, |
| 1577 const FPRegister& fm, |
| 2443 Condition cond); | 1578 Condition cond); |
| 2444 | 1579 |
| 2445 // Common FP Convert functions. | 1580 // Common FP Convert function |
| 2446 void NEONFPConvertToInt(const Register& rd, const VRegister& vn, Instr op); | 1581 void FPConvertToInt(const Register& rd, |
| 2447 void NEONFPConvertToInt(const VRegister& vd, const VRegister& vn, Instr op); | 1582 const FPRegister& fn, |
| 1583 FPIntegerConvertOp op); |
| 2448 | 1584 |
| 2449 // FP convert between precisions. | 1585 // FP convert between single and double precision. |
| 2450 void fcvt(const VRegister& vd, const VRegister& vn); | 1586 void fcvt(const FPRegister& fd, const FPRegister& fn); |
| 2451 | 1587 |
| 2452 // FP convert to higher precision. | 1588 // Convert FP to unsigned integer (nearest with ties to away). |
| 2453 void fcvtl(const VRegister& vd, const VRegister& vn); | 1589 void fcvtau(const Register& rd, const FPRegister& fn); |
| 2454 | 1590 |
| 2455 // FP convert to higher precision (second part). | 1591 // Convert FP to signed integer (nearest with ties to away). |
| 2456 void fcvtl2(const VRegister& vd, const VRegister& vn); | 1592 void fcvtas(const Register& rd, const FPRegister& fn); |
| 2457 | 1593 |
| 2458 // FP convert to lower precision. | 1594 // Convert FP to unsigned integer (round towards -infinity). |
| 2459 void fcvtn(const VRegister& vd, const VRegister& vn); | 1595 void fcvtmu(const Register& rd, const FPRegister& fn); |
| 2460 | 1596 |
| 2461 // FP convert to lower prevision (second part). | 1597 // Convert FP to signed integer (round towards -infinity). |
| 2462 void fcvtn2(const VRegister& vd, const VRegister& vn); | 1598 void fcvtms(const Register& rd, const FPRegister& fn); |
| 2463 | 1599 |
| 2464 // FP convert to lower precision, rounding to odd. | 1600 // Convert FP to unsigned integer (nearest with ties to even). |
| 2465 void fcvtxn(const VRegister& vd, const VRegister& vn); | 1601 void fcvtnu(const Register& rd, const FPRegister& fn); |
| 2466 | 1602 |
| 2467 // FP convert to lower precision, rounding to odd (second part). | 1603 // Convert FP to signed integer (nearest with ties to even). |
| 2468 void fcvtxn2(const VRegister& vd, const VRegister& vn); | 1604 void fcvtns(const Register& rd, const FPRegister& fn); |
| 2469 | 1605 |
| 2470 // FP convert to signed integer, nearest with ties to away. | 1606 // Convert FP to unsigned integer (round towards zero). |
| 2471 void fcvtas(const Register& rd, const VRegister& vn); | 1607 void fcvtzu(const Register& rd, const FPRegister& fn); |
| 2472 | 1608 |
| 2473 // FP convert to unsigned integer, nearest with ties to away. | 1609 // Convert FP to signed integer (rounf towards zero). |
| 2474 void fcvtau(const Register& rd, const VRegister& vn); | 1610 void fcvtzs(const Register& rd, const FPRegister& fn); |
| 2475 | |
| 2476 // FP convert to signed integer, nearest with ties to away. | |
| 2477 void fcvtas(const VRegister& vd, const VRegister& vn); | |
| 2478 | |
| 2479 // FP convert to unsigned integer, nearest with ties to away. | |
| 2480 void fcvtau(const VRegister& vd, const VRegister& vn); | |
| 2481 | |
| 2482 // FP convert to signed integer, round towards -infinity. | |
| 2483 void fcvtms(const Register& rd, const VRegister& vn); | |
| 2484 | |
| 2485 // FP convert to unsigned integer, round towards -infinity. | |
| 2486 void fcvtmu(const Register& rd, const VRegister& vn); | |
| 2487 | |
| 2488 // FP convert to signed integer, round towards -infinity. | |
| 2489 void fcvtms(const VRegister& vd, const VRegister& vn); | |
| 2490 | |
| 2491 // FP convert to unsigned integer, round towards -infinity. | |
| 2492 void fcvtmu(const VRegister& vd, const VRegister& vn); | |
| 2493 | |
| 2494 // FP convert to signed integer, nearest with ties to even. | |
| 2495 void fcvtns(const Register& rd, const VRegister& vn); | |
| 2496 | |
| 2497 // FP convert to unsigned integer, nearest with ties to even. | |
| 2498 void fcvtnu(const Register& rd, const VRegister& vn); | |
| 2499 | |
| 2500 // FP convert to signed integer, nearest with ties to even. | |
| 2501 void fcvtns(const VRegister& rd, const VRegister& vn); | |
| 2502 | |
| 2503 // FP convert to unsigned integer, nearest with ties to even. | |
| 2504 void fcvtnu(const VRegister& rd, const VRegister& vn); | |
| 2505 | |
| 2506 // FP convert to signed integer or fixed-point, round towards zero. | |
| 2507 void fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0); | |
| 2508 | |
| 2509 // FP convert to unsigned integer or fixed-point, round towards zero. | |
| 2510 void fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0); | |
| 2511 | |
| 2512 // FP convert to signed integer or fixed-point, round towards zero. | |
| 2513 void fcvtzs(const VRegister& vd, const VRegister& vn, int fbits = 0); | |
| 2514 | |
| 2515 // FP convert to unsigned integer or fixed-point, round towards zero. | |
| 2516 void fcvtzu(const VRegister& vd, const VRegister& vn, int fbits = 0); | |
| 2517 | |
| 2518 // FP convert to signed integer, round towards +infinity. | |
| 2519 void fcvtps(const Register& rd, const VRegister& vn); | |
| 2520 | |
| 2521 // FP convert to unsigned integer, round towards +infinity. | |
| 2522 void fcvtpu(const Register& rd, const VRegister& vn); | |
| 2523 | |
| 2524 // FP convert to signed integer, round towards +infinity. | |
| 2525 void fcvtps(const VRegister& vd, const VRegister& vn); | |
| 2526 | |
| 2527 // FP convert to unsigned integer, round towards +infinity. | |
| 2528 void fcvtpu(const VRegister& vd, const VRegister& vn); | |
| 2529 | 1611 |
| 2530 // Convert signed integer or fixed point to FP. | 1612 // Convert signed integer or fixed point to FP. |
| 2531 void scvtf(const VRegister& fd, const Register& rn, int fbits = 0); | 1613 void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); |
| 2532 | 1614 |
| 2533 // Convert unsigned integer or fixed point to FP. | 1615 // Convert unsigned integer or fixed point to FP. |
| 2534 void ucvtf(const VRegister& fd, const Register& rn, int fbits = 0); | 1616 void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); |
| 2535 | |
| 2536 // Convert signed integer or fixed-point to FP. | |
| 2537 void scvtf(const VRegister& fd, const VRegister& vn, int fbits = 0); | |
| 2538 | |
| 2539 // Convert unsigned integer or fixed-point to FP. | |
| 2540 void ucvtf(const VRegister& fd, const VRegister& vn, int fbits = 0); | |
| 2541 | |
| 2542 // Extract vector from pair of vectors. | |
| 2543 void ext(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 2544 int index); | |
| 2545 | |
| 2546 // Duplicate vector element to vector or scalar. | |
| 2547 void dup(const VRegister& vd, const VRegister& vn, int vn_index); | |
| 2548 | |
| 2549 // Duplicate general-purpose register to vector. | |
| 2550 void dup(const VRegister& vd, const Register& rn); | |
| 2551 | |
| 2552 // Insert vector element from general-purpose register. | |
| 2553 void ins(const VRegister& vd, int vd_index, const Register& rn); | |
| 2554 | |
| 2555 // Move general-purpose register to a vector element. | |
| 2556 void mov(const VRegister& vd, int vd_index, const Register& rn); | |
| 2557 | |
| 2558 // Unsigned move vector element to general-purpose register. | |
| 2559 void umov(const Register& rd, const VRegister& vn, int vn_index); | |
| 2560 | |
| 2561 // Move vector element to general-purpose register. | |
| 2562 void mov(const Register& rd, const VRegister& vn, int vn_index); | |
| 2563 | |
| 2564 // Move vector element to scalar. | |
| 2565 void mov(const VRegister& vd, const VRegister& vn, int vn_index); | |
| 2566 | |
| 2567 // Insert vector element from another vector element. | |
| 2568 void ins(const VRegister& vd, int vd_index, const VRegister& vn, | |
| 2569 int vn_index); | |
| 2570 | |
| 2571 // Move vector element to another vector element. | |
| 2572 void mov(const VRegister& vd, int vd_index, const VRegister& vn, | |
| 2573 int vn_index); | |
| 2574 | |
| 2575 // Signed move vector element to general-purpose register. | |
| 2576 void smov(const Register& rd, const VRegister& vn, int vn_index); | |
| 2577 | |
| 2578 // One-element structure load to one register. | |
| 2579 void ld1(const VRegister& vt, const MemOperand& src); | |
| 2580 | |
| 2581 // One-element structure load to two registers. | |
| 2582 void ld1(const VRegister& vt, const VRegister& vt2, const MemOperand& src); | |
| 2583 | |
| 2584 // One-element structure load to three registers. | |
| 2585 void ld1(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2586 const MemOperand& src); | |
| 2587 | |
| 2588 // One-element structure load to four registers. | |
| 2589 void ld1(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2590 const VRegister& vt4, const MemOperand& src); | |
| 2591 | |
| 2592 // One-element single structure load to one lane. | |
| 2593 void ld1(const VRegister& vt, int lane, const MemOperand& src); | |
| 2594 | |
| 2595 // One-element single structure load to all lanes. | |
| 2596 void ld1r(const VRegister& vt, const MemOperand& src); | |
| 2597 | |
| 2598 // Two-element structure load. | |
| 2599 void ld2(const VRegister& vt, const VRegister& vt2, const MemOperand& src); | |
| 2600 | |
| 2601 // Two-element single structure load to one lane. | |
| 2602 void ld2(const VRegister& vt, const VRegister& vt2, int lane, | |
| 2603 const MemOperand& src); | |
| 2604 | |
| 2605 // Two-element single structure load to all lanes. | |
| 2606 void ld2r(const VRegister& vt, const VRegister& vt2, const MemOperand& src); | |
| 2607 | |
| 2608 // Three-element structure load. | |
| 2609 void ld3(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2610 const MemOperand& src); | |
| 2611 | |
| 2612 // Three-element single structure load to one lane. | |
| 2613 void ld3(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2614 int lane, const MemOperand& src); | |
| 2615 | |
| 2616 // Three-element single structure load to all lanes. | |
| 2617 void ld3r(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2618 const MemOperand& src); | |
| 2619 | |
| 2620 // Four-element structure load. | |
| 2621 void ld4(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2622 const VRegister& vt4, const MemOperand& src); | |
| 2623 | |
| 2624 // Four-element single structure load to one lane. | |
| 2625 void ld4(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2626 const VRegister& vt4, int lane, const MemOperand& src); | |
| 2627 | |
| 2628 // Four-element single structure load to all lanes. | |
| 2629 void ld4r(const VRegister& vt, const VRegister& vt2, const VRegister& vt3, | |
| 2630 const VRegister& vt4, const MemOperand& src); | |
| 2631 | |
| 2632 // Count leading sign bits. | |
| 2633 void cls(const VRegister& vd, const VRegister& vn); | |
| 2634 | |
| 2635 // Count leading zero bits (vector). | |
| 2636 void clz(const VRegister& vd, const VRegister& vn); | |
| 2637 | |
| 2638 // Population count per byte. | |
| 2639 void cnt(const VRegister& vd, const VRegister& vn); | |
| 2640 | |
| 2641 // Reverse bit order. | |
| 2642 void rbit(const VRegister& vd, const VRegister& vn); | |
| 2643 | |
| 2644 // Reverse elements in 16-bit halfwords. | |
| 2645 void rev16(const VRegister& vd, const VRegister& vn); | |
| 2646 | |
| 2647 // Reverse elements in 32-bit words. | |
| 2648 void rev32(const VRegister& vd, const VRegister& vn); | |
| 2649 | |
| 2650 // Reverse elements in 64-bit doublewords. | |
| 2651 void rev64(const VRegister& vd, const VRegister& vn); | |
| 2652 | |
| 2653 // Unsigned reciprocal square root estimate. | |
| 2654 void ursqrte(const VRegister& vd, const VRegister& vn); | |
| 2655 | |
| 2656 // Unsigned reciprocal estimate. | |
| 2657 void urecpe(const VRegister& vd, const VRegister& vn); | |
| 2658 | |
| 2659 // Signed pairwise long add and accumulate. | |
| 2660 void sadalp(const VRegister& vd, const VRegister& vn); | |
| 2661 | |
| 2662 // Signed pairwise long add. | |
| 2663 void saddlp(const VRegister& vd, const VRegister& vn); | |
| 2664 | |
| 2665 // Unsigned pairwise long add. | |
| 2666 void uaddlp(const VRegister& vd, const VRegister& vn); | |
| 2667 | |
| 2668 // Unsigned pairwise long add and accumulate. | |
| 2669 void uadalp(const VRegister& vd, const VRegister& vn); | |
| 2670 | |
| 2671 // Shift left by immediate. | |
| 2672 void shl(const VRegister& vd, const VRegister& vn, int shift); | |
| 2673 | |
| 2674 // Signed saturating shift left by immediate. | |
| 2675 void sqshl(const VRegister& vd, const VRegister& vn, int shift); | |
| 2676 | |
| 2677 // Signed saturating shift left unsigned by immediate. | |
| 2678 void sqshlu(const VRegister& vd, const VRegister& vn, int shift); | |
| 2679 | |
| 2680 // Unsigned saturating shift left by immediate. | |
| 2681 void uqshl(const VRegister& vd, const VRegister& vn, int shift); | |
| 2682 | |
| 2683 // Signed shift left long by immediate. | |
| 2684 void sshll(const VRegister& vd, const VRegister& vn, int shift); | |
| 2685 | |
| 2686 // Signed shift left long by immediate (second part). | |
| 2687 void sshll2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2688 | |
| 2689 // Signed extend long. | |
| 2690 void sxtl(const VRegister& vd, const VRegister& vn); | |
| 2691 | |
| 2692 // Signed extend long (second part). | |
| 2693 void sxtl2(const VRegister& vd, const VRegister& vn); | |
| 2694 | |
| 2695 // Unsigned shift left long by immediate. | |
| 2696 void ushll(const VRegister& vd, const VRegister& vn, int shift); | |
| 2697 | |
| 2698 // Unsigned shift left long by immediate (second part). | |
| 2699 void ushll2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2700 | |
| 2701 // Shift left long by element size. | |
| 2702 void shll(const VRegister& vd, const VRegister& vn, int shift); | |
| 2703 | |
| 2704 // Shift left long by element size (second part). | |
| 2705 void shll2(const VRegister& vd, const VRegister& vn, int shift); | |
| 2706 | |
| 2707 // Unsigned extend long. | |
| 2708 void uxtl(const VRegister& vd, const VRegister& vn); | |
| 2709 | |
| 2710 // Unsigned extend long (second part). | |
| 2711 void uxtl2(const VRegister& vd, const VRegister& vn); | |
| 2712 | |
| 2713 // Signed rounding halving add. | |
| 2714 void srhadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2715 | |
| 2716 // Unsigned halving sub. | |
| 2717 void uhsub(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2718 | |
| 2719 // Signed halving sub. | |
| 2720 void shsub(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2721 | |
| 2722 // Unsigned saturating add. | |
| 2723 void uqadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2724 | |
| 2725 // Signed saturating add. | |
| 2726 void sqadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2727 | |
| 2728 // Unsigned saturating subtract. | |
| 2729 void uqsub(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2730 | |
| 2731 // Signed saturating subtract. | |
| 2732 void sqsub(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2733 | |
| 2734 // Add pairwise. | |
| 2735 void addp(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2736 | |
| 2737 // Add pair of elements scalar. | |
| 2738 void addp(const VRegister& vd, const VRegister& vn); | |
| 2739 | |
| 2740 // Multiply-add to accumulator. | |
| 2741 void mla(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2742 | |
| 2743 // Multiply-subtract to accumulator. | |
| 2744 void mls(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2745 | |
| 2746 // Multiply. | |
| 2747 void mul(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2748 | |
| 2749 // Table lookup from one register. | |
| 2750 void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2751 | |
| 2752 // Table lookup from two registers. | |
| 2753 void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vn2, | |
| 2754 const VRegister& vm); | |
| 2755 | |
| 2756 // Table lookup from three registers. | |
| 2757 void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vn2, | |
| 2758 const VRegister& vn3, const VRegister& vm); | |
| 2759 | |
| 2760 // Table lookup from four registers. | |
| 2761 void tbl(const VRegister& vd, const VRegister& vn, const VRegister& vn2, | |
| 2762 const VRegister& vn3, const VRegister& vn4, const VRegister& vm); | |
| 2763 | |
| 2764 // Table lookup extension from one register. | |
| 2765 void tbx(const VRegister& vd, const VRegister& vn, const VRegister& vm); | |
| 2766 | |
| 2767 // Table lookup extension from two registers. | |
| 2768 void tbx(const VRegister& vd, const VRegister& vn, const VRegister& vn2, | |
| 2769 const VRegister& vm); | |
| 2770 | |
| 2771 // Table lookup extension from three registers. | |
| 2772 void tbx(const VRegister& vd, const VRegister& vn, const VRegister& vn2, | |
| 2773 const VRegister& vn3, const VRegister& vm); | |
| 2774 | |
| 2775 // Table lookup extension from four registers. | |
| 2776 void tbx(const VRegister& vd, const VRegister& vn, const VRegister& vn2, | |
| 2777 const VRegister& vn3, const VRegister& vn4, const VRegister& vm); | |
| 2778 | 1617 |
| 2779 // Instruction functions used only for test, debug, and patching. | 1618 // Instruction functions used only for test, debug, and patching. |
| 2780 // Emit raw instructions in the instruction stream. | 1619 // Emit raw instructions in the instruction stream. |
| 2781 void dci(Instr raw_inst) { Emit(raw_inst); } | 1620 void dci(Instr raw_inst) { Emit(raw_inst); } |
| 2782 | 1621 |
| 2783 // Emit 8 bits of data in the instruction stream. | 1622 // Emit 8 bits of data in the instruction stream. |
| 2784 void dc8(uint8_t data) { EmitData(&data, sizeof(data)); } | 1623 void dc8(uint8_t data) { EmitData(&data, sizeof(data)); } |
| 2785 | 1624 |
| 2786 // Emit 32 bits of data in the instruction stream. | 1625 // Emit 32 bits of data in the instruction stream. |
| 2787 void dc32(uint32_t data) { EmitData(&data, sizeof(data)); } | 1626 void dc32(uint32_t data) { EmitData(&data, sizeof(data)); } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2817 Instruction* InstructionAt(ptrdiff_t offset) const { | 1656 Instruction* InstructionAt(ptrdiff_t offset) const { |
| 2818 return reinterpret_cast<Instruction*>(buffer_ + offset); | 1657 return reinterpret_cast<Instruction*>(buffer_ + offset); |
| 2819 } | 1658 } |
| 2820 | 1659 |
| 2821 ptrdiff_t InstructionOffset(Instruction* instr) const { | 1660 ptrdiff_t InstructionOffset(Instruction* instr) const { |
| 2822 return reinterpret_cast<byte*>(instr) - buffer_; | 1661 return reinterpret_cast<byte*>(instr) - buffer_; |
| 2823 } | 1662 } |
| 2824 | 1663 |
| 2825 // Register encoding. | 1664 // Register encoding. |
| 2826 static Instr Rd(CPURegister rd) { | 1665 static Instr Rd(CPURegister rd) { |
| 2827 DCHECK_NE(rd.code(), kSPRegInternalCode); | 1666 DCHECK(rd.code() != kSPRegInternalCode); |
| 2828 return rd.code() << Rd_offset; | 1667 return rd.code() << Rd_offset; |
| 2829 } | 1668 } |
| 2830 | 1669 |
| 2831 static Instr Rn(CPURegister rn) { | 1670 static Instr Rn(CPURegister rn) { |
| 2832 DCHECK_NE(rn.code(), kSPRegInternalCode); | 1671 DCHECK(rn.code() != kSPRegInternalCode); |
| 2833 return rn.code() << Rn_offset; | 1672 return rn.code() << Rn_offset; |
| 2834 } | 1673 } |
| 2835 | 1674 |
| 2836 static Instr Rm(CPURegister rm) { | 1675 static Instr Rm(CPURegister rm) { |
| 2837 DCHECK_NE(rm.code(), kSPRegInternalCode); | 1676 DCHECK(rm.code() != kSPRegInternalCode); |
| 2838 return rm.code() << Rm_offset; | 1677 return rm.code() << Rm_offset; |
| 2839 } | 1678 } |
| 2840 | 1679 |
| 2841 static Instr RmNot31(CPURegister rm) { | |
| 2842 DCHECK_NE(rm.code(), kSPRegInternalCode); | |
| 2843 DCHECK(!rm.IsZero()); | |
| 2844 return Rm(rm); | |
| 2845 } | |
| 2846 | |
| 2847 static Instr Ra(CPURegister ra) { | 1680 static Instr Ra(CPURegister ra) { |
| 2848 DCHECK_NE(ra.code(), kSPRegInternalCode); | 1681 DCHECK(ra.code() != kSPRegInternalCode); |
| 2849 return ra.code() << Ra_offset; | 1682 return ra.code() << Ra_offset; |
| 2850 } | 1683 } |
| 2851 | 1684 |
| 2852 static Instr Rt(CPURegister rt) { | 1685 static Instr Rt(CPURegister rt) { |
| 2853 DCHECK_NE(rt.code(), kSPRegInternalCode); | 1686 DCHECK(rt.code() != kSPRegInternalCode); |
| 2854 return rt.code() << Rt_offset; | 1687 return rt.code() << Rt_offset; |
| 2855 } | 1688 } |
| 2856 | 1689 |
| 2857 static Instr Rt2(CPURegister rt2) { | 1690 static Instr Rt2(CPURegister rt2) { |
| 2858 DCHECK_NE(rt2.code(), kSPRegInternalCode); | 1691 DCHECK(rt2.code() != kSPRegInternalCode); |
| 2859 return rt2.code() << Rt2_offset; | 1692 return rt2.code() << Rt2_offset; |
| 2860 } | 1693 } |
| 2861 | 1694 |
| 2862 static Instr Rs(CPURegister rs) { | 1695 static Instr Rs(CPURegister rs) { |
| 2863 DCHECK_NE(rs.code(), kSPRegInternalCode); | 1696 DCHECK(rs.code() != kSPRegInternalCode); |
| 2864 return rs.code() << Rs_offset; | 1697 return rs.code() << Rs_offset; |
| 2865 } | 1698 } |
| 2866 | 1699 |
| 2867 // These encoding functions allow the stack pointer to be encoded, and | 1700 // These encoding functions allow the stack pointer to be encoded, and |
| 2868 // disallow the zero register. | 1701 // disallow the zero register. |
| 2869 static Instr RdSP(Register rd) { | 1702 static Instr RdSP(Register rd) { |
| 2870 DCHECK(!rd.IsZero()); | 1703 DCHECK(!rd.IsZero()); |
| 2871 return (rd.code() & kRegCodeMask) << Rd_offset; | 1704 return (rd.code() & kRegCodeMask) << Rd_offset; |
| 2872 } | 1705 } |
| 2873 | 1706 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2909 static bool IsImmAddSub(int64_t immediate); | 1742 static bool IsImmAddSub(int64_t immediate); |
| 2910 static bool IsImmLogical(uint64_t value, | 1743 static bool IsImmLogical(uint64_t value, |
| 2911 unsigned width, | 1744 unsigned width, |
| 2912 unsigned* n, | 1745 unsigned* n, |
| 2913 unsigned* imm_s, | 1746 unsigned* imm_s, |
| 2914 unsigned* imm_r); | 1747 unsigned* imm_r); |
| 2915 | 1748 |
| 2916 // MemOperand offset encoding. | 1749 // MemOperand offset encoding. |
| 2917 inline static Instr ImmLSUnsigned(int imm12); | 1750 inline static Instr ImmLSUnsigned(int imm12); |
| 2918 inline static Instr ImmLS(int imm9); | 1751 inline static Instr ImmLS(int imm9); |
| 2919 inline static Instr ImmLSPair(int imm7, unsigned size); | 1752 inline static Instr ImmLSPair(int imm7, LSDataSize size); |
| 2920 inline static Instr ImmShiftLS(unsigned shift_amount); | 1753 inline static Instr ImmShiftLS(unsigned shift_amount); |
| 2921 inline static Instr ImmException(int imm16); | 1754 inline static Instr ImmException(int imm16); |
| 2922 inline static Instr ImmSystemRegister(int imm15); | 1755 inline static Instr ImmSystemRegister(int imm15); |
| 2923 inline static Instr ImmHint(int imm7); | 1756 inline static Instr ImmHint(int imm7); |
| 2924 inline static Instr ImmBarrierDomain(int imm2); | 1757 inline static Instr ImmBarrierDomain(int imm2); |
| 2925 inline static Instr ImmBarrierType(int imm2); | 1758 inline static Instr ImmBarrierType(int imm2); |
| 2926 inline static unsigned CalcLSDataSize(LoadStoreOp op); | 1759 inline static LSDataSize CalcLSDataSize(LoadStoreOp op); |
| 2927 | |
| 2928 // Instruction bits for vector format in data processing operations. | |
| 2929 static Instr VFormat(VRegister vd) { | |
| 2930 if (vd.Is64Bits()) { | |
| 2931 switch (vd.LaneCount()) { | |
| 2932 case 2: | |
| 2933 return NEON_2S; | |
| 2934 case 4: | |
| 2935 return NEON_4H; | |
| 2936 case 8: | |
| 2937 return NEON_8B; | |
| 2938 default: | |
| 2939 UNREACHABLE(); | |
| 2940 return kUnallocatedInstruction; | |
| 2941 } | |
| 2942 } else { | |
| 2943 DCHECK(vd.Is128Bits()); | |
| 2944 switch (vd.LaneCount()) { | |
| 2945 case 2: | |
| 2946 return NEON_2D; | |
| 2947 case 4: | |
| 2948 return NEON_4S; | |
| 2949 case 8: | |
| 2950 return NEON_8H; | |
| 2951 case 16: | |
| 2952 return NEON_16B; | |
| 2953 default: | |
| 2954 UNREACHABLE(); | |
| 2955 return kUnallocatedInstruction; | |
| 2956 } | |
| 2957 } | |
| 2958 } | |
| 2959 | |
| 2960 // Instruction bits for vector format in floating point data processing | |
| 2961 // operations. | |
| 2962 static Instr FPFormat(VRegister vd) { | |
| 2963 if (vd.LaneCount() == 1) { | |
| 2964 // Floating point scalar formats. | |
| 2965 DCHECK(vd.Is32Bits() || vd.Is64Bits()); | |
| 2966 return vd.Is64Bits() ? FP64 : FP32; | |
| 2967 } | |
| 2968 | |
| 2969 // Two lane floating point vector formats. | |
| 2970 if (vd.LaneCount() == 2) { | |
| 2971 DCHECK(vd.Is64Bits() || vd.Is128Bits()); | |
| 2972 return vd.Is128Bits() ? NEON_FP_2D : NEON_FP_2S; | |
| 2973 } | |
| 2974 | |
| 2975 // Four lane floating point vector format. | |
| 2976 DCHECK((vd.LaneCount() == 4) && vd.Is128Bits()); | |
| 2977 return NEON_FP_4S; | |
| 2978 } | |
| 2979 | |
| 2980 // Instruction bits for vector format in load and store operations. | |
| 2981 static Instr LSVFormat(VRegister vd) { | |
| 2982 if (vd.Is64Bits()) { | |
| 2983 switch (vd.LaneCount()) { | |
| 2984 case 1: | |
| 2985 return LS_NEON_1D; | |
| 2986 case 2: | |
| 2987 return LS_NEON_2S; | |
| 2988 case 4: | |
| 2989 return LS_NEON_4H; | |
| 2990 case 8: | |
| 2991 return LS_NEON_8B; | |
| 2992 default: | |
| 2993 UNREACHABLE(); | |
| 2994 return kUnallocatedInstruction; | |
| 2995 } | |
| 2996 } else { | |
| 2997 DCHECK(vd.Is128Bits()); | |
| 2998 switch (vd.LaneCount()) { | |
| 2999 case 2: | |
| 3000 return LS_NEON_2D; | |
| 3001 case 4: | |
| 3002 return LS_NEON_4S; | |
| 3003 case 8: | |
| 3004 return LS_NEON_8H; | |
| 3005 case 16: | |
| 3006 return LS_NEON_16B; | |
| 3007 default: | |
| 3008 UNREACHABLE(); | |
| 3009 return kUnallocatedInstruction; | |
| 3010 } | |
| 3011 } | |
| 3012 } | |
| 3013 | |
| 3014 // Instruction bits for scalar format in data processing operations. | |
| 3015 static Instr SFormat(VRegister vd) { | |
| 3016 DCHECK(vd.IsScalar()); | |
| 3017 switch (vd.SizeInBytes()) { | |
| 3018 case 1: | |
| 3019 return NEON_B; | |
| 3020 case 2: | |
| 3021 return NEON_H; | |
| 3022 case 4: | |
| 3023 return NEON_S; | |
| 3024 case 8: | |
| 3025 return NEON_D; | |
| 3026 default: | |
| 3027 UNREACHABLE(); | |
| 3028 return kUnallocatedInstruction; | |
| 3029 } | |
| 3030 } | |
| 3031 | |
| 3032 static Instr ImmNEONHLM(int index, int num_bits) { | |
| 3033 int h, l, m; | |
| 3034 if (num_bits == 3) { | |
| 3035 DCHECK(is_uint3(index)); | |
| 3036 h = (index >> 2) & 1; | |
| 3037 l = (index >> 1) & 1; | |
| 3038 m = (index >> 0) & 1; | |
| 3039 } else if (num_bits == 2) { | |
| 3040 DCHECK(is_uint2(index)); | |
| 3041 h = (index >> 1) & 1; | |
| 3042 l = (index >> 0) & 1; | |
| 3043 m = 0; | |
| 3044 } else { | |
| 3045 DCHECK(is_uint1(index) && (num_bits == 1)); | |
| 3046 h = (index >> 0) & 1; | |
| 3047 l = 0; | |
| 3048 m = 0; | |
| 3049 } | |
| 3050 return (h << NEONH_offset) | (l << NEONL_offset) | (m << NEONM_offset); | |
| 3051 } | |
| 3052 | |
| 3053 static Instr ImmNEONExt(int imm4) { | |
| 3054 DCHECK(is_uint4(imm4)); | |
| 3055 return imm4 << ImmNEONExt_offset; | |
| 3056 } | |
| 3057 | |
| 3058 static Instr ImmNEON5(Instr format, int index) { | |
| 3059 DCHECK(is_uint4(index)); | |
| 3060 int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format)); | |
| 3061 int imm5 = (index << (s + 1)) | (1 << s); | |
| 3062 return imm5 << ImmNEON5_offset; | |
| 3063 } | |
| 3064 | |
| 3065 static Instr ImmNEON4(Instr format, int index) { | |
| 3066 DCHECK(is_uint4(index)); | |
| 3067 int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format)); | |
| 3068 int imm4 = index << s; | |
| 3069 return imm4 << ImmNEON4_offset; | |
| 3070 } | |
| 3071 | |
| 3072 static Instr ImmNEONabcdefgh(int imm8) { | |
| 3073 DCHECK(is_uint8(imm8)); | |
| 3074 Instr instr; | |
| 3075 instr = ((imm8 >> 5) & 7) << ImmNEONabc_offset; | |
| 3076 instr |= (imm8 & 0x1f) << ImmNEONdefgh_offset; | |
| 3077 return instr; | |
| 3078 } | |
| 3079 | |
| 3080 static Instr NEONCmode(int cmode) { | |
| 3081 DCHECK(is_uint4(cmode)); | |
| 3082 return cmode << NEONCmode_offset; | |
| 3083 } | |
| 3084 | |
| 3085 static Instr NEONModImmOp(int op) { | |
| 3086 DCHECK(is_uint1(op)); | |
| 3087 return op << NEONModImmOp_offset; | |
| 3088 } | |
| 3089 | 1760 |
| 3090 static bool IsImmLSUnscaled(int64_t offset); | 1761 static bool IsImmLSUnscaled(int64_t offset); |
| 3091 static bool IsImmLSScaled(int64_t offset, unsigned size); | 1762 static bool IsImmLSScaled(int64_t offset, LSDataSize size); |
| 3092 static bool IsImmLLiteral(int64_t offset); | 1763 static bool IsImmLLiteral(int64_t offset); |
| 3093 | 1764 |
| 3094 // Move immediates encoding. | 1765 // Move immediates encoding. |
| 3095 inline static Instr ImmMoveWide(int imm); | 1766 inline static Instr ImmMoveWide(int imm); |
| 3096 inline static Instr ShiftMoveWide(int shift); | 1767 inline static Instr ShiftMoveWide(int shift); |
| 3097 | 1768 |
| 3098 // FP Immediates. | 1769 // FP Immediates. |
| 3099 static Instr ImmFP(double imm); | 1770 static Instr ImmFP32(float imm); |
| 3100 static Instr ImmNEONFP(double imm); | 1771 static Instr ImmFP64(double imm); |
| 3101 inline static Instr FPScale(unsigned scale); | 1772 inline static Instr FPScale(unsigned scale); |
| 3102 | 1773 |
| 3103 // FP register type. | 1774 // FP register type. |
| 3104 inline static Instr FPType(VRegister fd); | 1775 inline static Instr FPType(FPRegister fd); |
| 3105 | 1776 |
| 3106 // Class for scoping postponing the constant pool generation. | 1777 // Class for scoping postponing the constant pool generation. |
| 3107 class BlockConstPoolScope { | 1778 class BlockConstPoolScope { |
| 3108 public: | 1779 public: |
| 3109 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { | 1780 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { |
| 3110 assem_->StartBlockConstPool(); | 1781 assem_->StartBlockConstPool(); |
| 3111 } | 1782 } |
| 3112 ~BlockConstPoolScope() { | 1783 ~BlockConstPoolScope() { |
| 3113 assem_->EndBlockConstPool(); | 1784 assem_->EndBlockConstPool(); |
| 3114 } | 1785 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3168 | 1839 |
| 3169 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope); | 1840 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope); |
| 3170 }; | 1841 }; |
| 3171 | 1842 |
| 3172 protected: | 1843 protected: |
| 3173 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const; | 1844 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const; |
| 3174 | 1845 |
| 3175 void LoadStore(const CPURegister& rt, | 1846 void LoadStore(const CPURegister& rt, |
| 3176 const MemOperand& addr, | 1847 const MemOperand& addr, |
| 3177 LoadStoreOp op); | 1848 LoadStoreOp op); |
| 1849 |
| 3178 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2, | 1850 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2, |
| 3179 const MemOperand& addr, LoadStorePairOp op); | 1851 const MemOperand& addr, LoadStorePairOp op); |
| 3180 void LoadStoreStruct(const VRegister& vt, const MemOperand& addr, | 1852 static bool IsImmLSPair(int64_t offset, LSDataSize size); |
| 3181 NEONLoadStoreMultiStructOp op); | |
| 3182 void LoadStoreStruct1(const VRegister& vt, int reg_count, | |
| 3183 const MemOperand& addr); | |
| 3184 void LoadStoreStructSingle(const VRegister& vt, uint32_t lane, | |
| 3185 const MemOperand& addr, | |
| 3186 NEONLoadStoreSingleStructOp op); | |
| 3187 void LoadStoreStructSingleAllLanes(const VRegister& vt, | |
| 3188 const MemOperand& addr, | |
| 3189 NEONLoadStoreSingleStructOp op); | |
| 3190 void LoadStoreStructVerify(const VRegister& vt, const MemOperand& addr, | |
| 3191 Instr op); | |
| 3192 | |
| 3193 static bool IsImmLSPair(int64_t offset, unsigned size); | |
| 3194 | 1853 |
| 3195 void Logical(const Register& rd, | 1854 void Logical(const Register& rd, |
| 3196 const Register& rn, | 1855 const Register& rn, |
| 3197 const Operand& operand, | 1856 const Operand& operand, |
| 3198 LogicalOp op); | 1857 LogicalOp op); |
| 3199 void LogicalImmediate(const Register& rd, | 1858 void LogicalImmediate(const Register& rd, |
| 3200 const Register& rn, | 1859 const Register& rn, |
| 3201 unsigned n, | 1860 unsigned n, |
| 3202 unsigned imm_s, | 1861 unsigned imm_s, |
| 3203 unsigned imm_r, | 1862 unsigned imm_r, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3248 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); | 1907 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); |
| 3249 | 1908 |
| 3250 // Remove the specified branch from the unbound label link chain. | 1909 // Remove the specified branch from the unbound label link chain. |
| 3251 // If available, a veneer for this label can be used for other branches in the | 1910 // If available, a veneer for this label can be used for other branches in the |
| 3252 // chain if the link chain cannot be fixed up without this branch. | 1911 // chain if the link chain cannot be fixed up without this branch. |
| 3253 void RemoveBranchFromLabelLinkChain(Instruction* branch, | 1912 void RemoveBranchFromLabelLinkChain(Instruction* branch, |
| 3254 Label* label, | 1913 Label* label, |
| 3255 Instruction* label_veneer = NULL); | 1914 Instruction* label_veneer = NULL); |
| 3256 | 1915 |
| 3257 private: | 1916 private: |
| 3258 static uint32_t FPToImm8(double imm); | |
| 3259 | |
| 3260 // Instruction helpers. | 1917 // Instruction helpers. |
| 3261 void MoveWide(const Register& rd, | 1918 void MoveWide(const Register& rd, |
| 3262 uint64_t imm, | 1919 uint64_t imm, |
| 3263 int shift, | 1920 int shift, |
| 3264 MoveWideImmediateOp mov_op); | 1921 MoveWideImmediateOp mov_op); |
| 3265 void DataProcShiftedRegister(const Register& rd, | 1922 void DataProcShiftedRegister(const Register& rd, |
| 3266 const Register& rn, | 1923 const Register& rn, |
| 3267 const Operand& operand, | 1924 const Operand& operand, |
| 3268 FlagsUpdate S, | 1925 FlagsUpdate S, |
| 3269 Instr op); | 1926 Instr op); |
| 3270 void DataProcExtendedRegister(const Register& rd, | 1927 void DataProcExtendedRegister(const Register& rd, |
| 3271 const Register& rn, | 1928 const Register& rn, |
| 3272 const Operand& operand, | 1929 const Operand& operand, |
| 3273 FlagsUpdate S, | 1930 FlagsUpdate S, |
| 3274 Instr op); | 1931 Instr op); |
| 3275 void ConditionalSelect(const Register& rd, | 1932 void ConditionalSelect(const Register& rd, |
| 3276 const Register& rn, | 1933 const Register& rn, |
| 3277 const Register& rm, | 1934 const Register& rm, |
| 3278 Condition cond, | 1935 Condition cond, |
| 3279 ConditionalSelectOp op); | 1936 ConditionalSelectOp op); |
| 3280 void DataProcessing1Source(const Register& rd, | 1937 void DataProcessing1Source(const Register& rd, |
| 3281 const Register& rn, | 1938 const Register& rn, |
| 3282 DataProcessing1SourceOp op); | 1939 DataProcessing1SourceOp op); |
| 3283 void DataProcessing3Source(const Register& rd, | 1940 void DataProcessing3Source(const Register& rd, |
| 3284 const Register& rn, | 1941 const Register& rn, |
| 3285 const Register& rm, | 1942 const Register& rm, |
| 3286 const Register& ra, | 1943 const Register& ra, |
| 3287 DataProcessing3SourceOp op); | 1944 DataProcessing3SourceOp op); |
| 3288 void FPDataProcessing1Source(const VRegister& fd, const VRegister& fn, | 1945 void FPDataProcessing1Source(const FPRegister& fd, |
| 1946 const FPRegister& fn, |
| 3289 FPDataProcessing1SourceOp op); | 1947 FPDataProcessing1SourceOp op); |
| 3290 void FPDataProcessing2Source(const VRegister& fd, const VRegister& fn, | 1948 void FPDataProcessing2Source(const FPRegister& fd, |
| 3291 const VRegister& fm, | 1949 const FPRegister& fn, |
| 1950 const FPRegister& fm, |
| 3292 FPDataProcessing2SourceOp op); | 1951 FPDataProcessing2SourceOp op); |
| 3293 void FPDataProcessing3Source(const VRegister& fd, const VRegister& fn, | 1952 void FPDataProcessing3Source(const FPRegister& fd, |
| 3294 const VRegister& fm, const VRegister& fa, | 1953 const FPRegister& fn, |
| 1954 const FPRegister& fm, |
| 1955 const FPRegister& fa, |
| 3295 FPDataProcessing3SourceOp op); | 1956 FPDataProcessing3SourceOp op); |
| 3296 void NEONAcrossLanesL(const VRegister& vd, const VRegister& vn, | |
| 3297 NEONAcrossLanesOp op); | |
| 3298 void NEONAcrossLanes(const VRegister& vd, const VRegister& vn, | |
| 3299 NEONAcrossLanesOp op); | |
| 3300 void NEONModifiedImmShiftLsl(const VRegister& vd, const int imm8, | |
| 3301 const int left_shift, | |
| 3302 NEONModifiedImmediateOp op); | |
| 3303 void NEONModifiedImmShiftMsl(const VRegister& vd, const int imm8, | |
| 3304 const int shift_amount, | |
| 3305 NEONModifiedImmediateOp op); | |
| 3306 void NEON3Same(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 3307 NEON3SameOp vop); | |
| 3308 void NEONFP3Same(const VRegister& vd, const VRegister& vn, | |
| 3309 const VRegister& vm, Instr op); | |
| 3310 void NEON3DifferentL(const VRegister& vd, const VRegister& vn, | |
| 3311 const VRegister& vm, NEON3DifferentOp vop); | |
| 3312 void NEON3DifferentW(const VRegister& vd, const VRegister& vn, | |
| 3313 const VRegister& vm, NEON3DifferentOp vop); | |
| 3314 void NEON3DifferentHN(const VRegister& vd, const VRegister& vn, | |
| 3315 const VRegister& vm, NEON3DifferentOp vop); | |
| 3316 void NEONFP2RegMisc(const VRegister& vd, const VRegister& vn, | |
| 3317 NEON2RegMiscOp vop, double value = 0.0); | |
| 3318 void NEON2RegMisc(const VRegister& vd, const VRegister& vn, | |
| 3319 NEON2RegMiscOp vop, int value = 0); | |
| 3320 void NEONFP2RegMisc(const VRegister& vd, const VRegister& vn, Instr op); | |
| 3321 void NEONAddlp(const VRegister& vd, const VRegister& vn, NEON2RegMiscOp op); | |
| 3322 void NEONPerm(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 3323 NEONPermOp op); | |
| 3324 void NEONFPByElement(const VRegister& vd, const VRegister& vn, | |
| 3325 const VRegister& vm, int vm_index, | |
| 3326 NEONByIndexedElementOp op); | |
| 3327 void NEONByElement(const VRegister& vd, const VRegister& vn, | |
| 3328 const VRegister& vm, int vm_index, | |
| 3329 NEONByIndexedElementOp op); | |
| 3330 void NEONByElementL(const VRegister& vd, const VRegister& vn, | |
| 3331 const VRegister& vm, int vm_index, | |
| 3332 NEONByIndexedElementOp op); | |
| 3333 void NEONShiftImmediate(const VRegister& vd, const VRegister& vn, | |
| 3334 NEONShiftImmediateOp op, int immh_immb); | |
| 3335 void NEONShiftLeftImmediate(const VRegister& vd, const VRegister& vn, | |
| 3336 int shift, NEONShiftImmediateOp op); | |
| 3337 void NEONShiftRightImmediate(const VRegister& vd, const VRegister& vn, | |
| 3338 int shift, NEONShiftImmediateOp op); | |
| 3339 void NEONShiftImmediateL(const VRegister& vd, const VRegister& vn, int shift, | |
| 3340 NEONShiftImmediateOp op); | |
| 3341 void NEONShiftImmediateN(const VRegister& vd, const VRegister& vn, int shift, | |
| 3342 NEONShiftImmediateOp op); | |
| 3343 void NEONXtn(const VRegister& vd, const VRegister& vn, NEON2RegMiscOp vop); | |
| 3344 void NEONTable(const VRegister& vd, const VRegister& vn, const VRegister& vm, | |
| 3345 NEONTableOp op); | |
| 3346 | |
| 3347 Instr LoadStoreStructAddrModeField(const MemOperand& addr); | |
| 3348 | 1957 |
| 3349 // Label helpers. | 1958 // Label helpers. |
| 3350 | 1959 |
| 3351 // Return an offset for a label-referencing instruction, typically a branch. | 1960 // Return an offset for a label-referencing instruction, typically a branch. |
| 3352 int LinkAndGetByteOffsetTo(Label* label); | 1961 int LinkAndGetByteOffsetTo(Label* label); |
| 3353 | 1962 |
| 3354 // This is the same as LinkAndGetByteOffsetTo, but return an offset | 1963 // This is the same as LinkAndGetByteOffsetTo, but return an offset |
| 3355 // suitable for fields that take instruction offsets. | 1964 // suitable for fields that take instruction offsets. |
| 3356 inline int LinkAndGetInstructionOffsetTo(Label* label); | 1965 inline int LinkAndGetInstructionOffsetTo(Label* label); |
| 3357 | 1966 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3594 public: | 2203 public: |
| 3595 explicit EnsureSpace(Assembler* assembler) { | 2204 explicit EnsureSpace(Assembler* assembler) { |
| 3596 assembler->CheckBufferSpace(); | 2205 assembler->CheckBufferSpace(); |
| 3597 } | 2206 } |
| 3598 }; | 2207 }; |
| 3599 | 2208 |
| 3600 } // namespace internal | 2209 } // namespace internal |
| 3601 } // namespace v8 | 2210 } // namespace v8 |
| 3602 | 2211 |
| 3603 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ | 2212 #endif // V8_ARM64_ASSEMBLER_ARM64_H_ |
| OLD | NEW |