OLD | NEW |
---|---|
1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
6 // | 6 // |
7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { | 349 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { |
350 const IValueT Immed5 = ShImm->getShAmtImm(); | 350 const IValueT Immed5 = ShImm->getShAmtImm(); |
351 assert(Immed5 < (1 << kShiftImmBits)); | 351 assert(Immed5 < (1 << kShiftImmBits)); |
352 Value = (Immed5 << kShiftImmShift); | 352 Value = (Immed5 << kShiftImmShift); |
353 return EncodedAsShiftImm5; | 353 return EncodedAsShiftImm5; |
354 } | 354 } |
355 return CantEncode; | 355 return CantEncode; |
356 } | 356 } |
357 | 357 |
358 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, | 358 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, |
359 OperandARM32Mem::AddrMode Mode) { | 359 OperandARM32Mem::AddrMode Mode, |
360 IValueT OffsetShift = 0) { | |
360 IValueT Value = Mode | (Reg << kRnShift); | 361 IValueT Value = Mode | (Reg << kRnShift); |
361 if (Offset < 0) { | 362 if (Offset < 0) { |
362 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. | 363 Offset = -Offset; |
363 } else { | 364 Value ^= U; // Flip U to adjust sign. |
364 Value |= Offset; | |
365 } | 365 } |
366 return Value; | 366 return Value | (Offset >> OffsetShift); |
367 } | 367 } |
368 | 368 |
369 // Encodes immediate register offset using encoding 3. | 369 // Encodes immediate register offset using encoding 3. |
370 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, | 370 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, |
371 OperandARM32Mem::AddrMode Mode) { | 371 OperandARM32Mem::AddrMode Mode) { |
372 IValueT Value = Mode | (Rn << kRnShift); | 372 IValueT Value = Mode | (Rn << kRnShift); |
373 if (Imm8 < 0) { | 373 if (Imm8 < 0) { |
374 Imm8 = -Imm8; | 374 Imm8 = -Imm8; |
375 Value = (Value ^ U); | 375 Value = (Value ^ U); |
376 } | 376 } |
377 assert(Imm8 < (1 << 8)); | 377 assert(Imm8 < (1 << 8)); |
378 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); | 378 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); |
379 return Value; | 379 return Value; |
380 } | 380 } |
381 | 381 |
382 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, | 382 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, |
383 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { | 383 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { |
384 switch (AddressEncoding) { | 384 switch (AddressEncoding) { |
385 case DefaultOpEncoding: | 385 case DefaultOpEncoding: |
386 return encodeImmRegOffset(Reg, Offset, Mode); | 386 return encodeImmRegOffset(Reg, Offset, Mode); |
387 case ImmRegOffsetDiv4: | 387 case ImmRegOffsetDiv4: { |
388 assert((Offset & 0x3) == 0); | 388 assert((Offset & 0x3) == 0); |
389 return encodeImmRegOffset(Reg, Offset >> 2, Mode); | 389 constexpr IValueT RightShift2 = 2; |
390 return encodeImmRegOffset(Reg, Offset, Mode, RightShift2); | |
391 } | |
390 case OpEncoding3: | 392 case OpEncoding3: |
391 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); | 393 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); |
392 case OpEncodingMemEx: | 394 case OpEncodingMemEx: |
393 assert(Offset == 0); | 395 assert(Offset == 0); |
394 assert(Mode == OperandARM32Mem::Offset); | 396 assert(Mode == OperandARM32Mem::Offset); |
395 return Reg << kRnShift; | 397 return Reg << kRnShift; |
396 } | 398 } |
397 llvm_unreachable("(silence g++ warning)"); | 399 llvm_unreachable("(silence g++ warning)"); |
398 } | 400 } |
399 | 401 |
(...skipping 1835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2235 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] | 2237 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] |
2236 // | 2238 // |
2237 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, | 2239 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, |
2238 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. | 2240 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. |
2239 constexpr const char *Vldrd = "vldrd"; | 2241 constexpr const char *Vldrd = "vldrd"; |
2240 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); | 2242 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); |
2241 assert(CondARM32::isDefined(Cond)); | 2243 assert(CondARM32::isDefined(Cond)); |
2242 IValueT Address; | 2244 IValueT Address; |
2243 EncodedOperand AddressEncoding = | 2245 EncodedOperand AddressEncoding = |
2244 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2246 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2245 if (AddressEncoding != EncodedAsImmRegOffset) | 2247 (void)AddressEncoding; // Make MINIMAL build happy. |
John
2016/01/22 18:47:40
no need for this comment. This is a pretty common
Karl
2016/01/22 20:42:19
Done.
| |
2246 // TODO(kschimpf) Fix this. | 2248 assert(AddressEncoding == EncodedAsImmRegOffset); |
2247 return setNeedsTextFixup(); | |
2248 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2249 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2249 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | | 2250 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | |
2250 (encodeCondition(Cond) << kConditionShift) | | 2251 (encodeCondition(Cond) << kConditionShift) | |
2251 (getYInRegYXXXX(Dd) << 22) | | 2252 (getYInRegYXXXX(Dd) << 22) | |
2252 (getXXXXInRegYXXXX(Dd) << 12) | Address; | 2253 (getXXXXInRegYXXXX(Dd) << 12) | Address; |
2253 emitInst(Encoding); | 2254 emitInst(Encoding); |
2254 } | 2255 } |
2255 | 2256 |
2256 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, | 2257 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, |
2257 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2258 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
2258 // VDLR - ARM section A8.8.333, encoding A2. | 2259 // VDLR - ARM section A8.8.333, encoding A2. |
2259 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] | 2260 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] |
2260 // | 2261 // |
2261 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, | 2262 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, |
2262 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; | 2263 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; |
2263 constexpr const char *Vldrs = "vldrs"; | 2264 constexpr const char *Vldrs = "vldrs"; |
2264 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); | 2265 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); |
2265 assert(CondARM32::isDefined(Cond)); | 2266 assert(CondARM32::isDefined(Cond)); |
2266 IValueT Address; | 2267 IValueT Address; |
2267 EncodedOperand AddressEncoding = encodeAddress(OpAddress, Address, TInfo); | 2268 EncodedOperand AddressEncoding = |
2268 (void)AddressEncoding; | 2269 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2270 (void)AddressEncoding; // Make MINIMAL build happy. | |
2269 assert(AddressEncoding == EncodedAsImmRegOffset); | 2271 assert(AddressEncoding == EncodedAsImmRegOffset); |
2270 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2272 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2271 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | | 2273 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | |
2272 (encodeCondition(Cond) << kConditionShift) | | 2274 (encodeCondition(Cond) << kConditionShift) | |
2273 (getYInRegXXXXY(Sd) << 22) | | 2275 (getYInRegXXXXY(Sd) << 22) | |
2274 (getXXXXInRegXXXXY(Sd) << 12) | Address; | 2276 (getXXXXInRegXXXXY(Sd) << 12) | Address; |
2275 emitInst(Encoding); | 2277 emitInst(Encoding); |
2276 } | 2278 } |
2277 | 2279 |
2278 void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn, | 2280 void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2311 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] | 2313 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] |
2312 // | 2314 // |
2313 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, | 2315 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, |
2314 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. | 2316 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. |
2315 constexpr const char *Vstrd = "vstrd"; | 2317 constexpr const char *Vstrd = "vstrd"; |
2316 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); | 2318 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); |
2317 assert(CondARM32::isDefined(Cond)); | 2319 assert(CondARM32::isDefined(Cond)); |
2318 IValueT Address; | 2320 IValueT Address; |
2319 IValueT AddressEncoding = | 2321 IValueT AddressEncoding = |
2320 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2322 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2321 if (AddressEncoding != EncodedAsImmRegOffset) | 2323 (void)AddressEncoding; // Make MINIMAL build happy. |
2322 // TODO(kschimpf) Fix this. | 2324 assert(AddressEncoding == EncodedAsImmRegOffset); |
2323 return setNeedsTextFixup(); | |
2324 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2325 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2325 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | | 2326 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | |
2326 (encodeCondition(Cond) << kConditionShift) | | 2327 (encodeCondition(Cond) << kConditionShift) | |
2327 (getYInRegYXXXX(Dd) << 22) | | 2328 (getYInRegYXXXX(Dd) << 22) | |
2328 (getXXXXInRegYXXXX(Dd) << 12) | Address; | 2329 (getXXXXInRegYXXXX(Dd) << 12) | Address; |
2329 emitInst(Encoding); | 2330 emitInst(Encoding); |
2330 } | 2331 } |
2331 | 2332 |
2332 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, | 2333 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, |
2333 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2334 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
2334 // VSTR - ARM section A8.8.413, encoding A2: | 2335 // VSTR - ARM section A8.8.413, encoding A2: |
2335 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] | 2336 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] |
2336 // | 2337 // |
2337 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, | 2338 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, |
2338 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; | 2339 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; |
2339 constexpr const char *Vstrs = "vstrs"; | 2340 constexpr const char *Vstrs = "vstrs"; |
2340 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); | 2341 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); |
2341 assert(CondARM32::isDefined(Cond)); | 2342 assert(CondARM32::isDefined(Cond)); |
2342 IValueT Address; | 2343 IValueT Address; |
2343 if (encodeAddress(OpAddress, Address, TInfo) != EncodedAsImmRegOffset) | 2344 IValueT AddressEncoding = |
2344 assert(false); | 2345 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2346 (void)AddressEncoding; // Make MINIMAL build happy. | |
2347 assert(AddressEncoding == EncodedAsImmRegOffset); | |
2345 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2348 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2346 IValueT Encoding = | 2349 IValueT Encoding = |
2347 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | | 2350 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | |
2348 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; | 2351 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; |
2349 emitInst(Encoding); | 2352 emitInst(Encoding); |
2350 } | 2353 } |
2351 | 2354 |
2352 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, | 2355 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, |
2353 const Operand *OpSm, CondARM32::Cond Cond) { | 2356 const Operand *OpSm, CondARM32::Cond Cond) { |
2354 // VSUB (floating-point) - ARM section A8.8.415, encoding A2: | 2357 // VSUB (floating-point) - ARM section A8.8.415, encoding A2: |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2421 // | 2424 // |
2422 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and | 2425 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and |
2423 // iiiiiiii=NumConsecRegs. | 2426 // iiiiiiii=NumConsecRegs. |
2424 constexpr IValueT VpushOpcode = | 2427 constexpr IValueT VpushOpcode = |
2425 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; | 2428 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; |
2426 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); | 2429 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); |
2427 } | 2430 } |
2428 | 2431 |
2429 } // end of namespace ARM32 | 2432 } // end of namespace ARM32 |
2430 } // end of namespace Ice | 2433 } // end of namespace Ice |
OLD | NEW |