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; |
Jim Stichnoth
2016/01/22 22:47:15
I assume this is probably not possible, but it set
John
2016/01/22 23:33:25
arm32 immediates are small (usually 8-bits, someti
Karl
2016/01/25 19:03:26
Fixing with CL https://codereview.chromium.org/163
| |
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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 } | 603 } |
602 return L; | 604 return L; |
603 } | 605 } |
604 | 606 |
605 IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) { | 607 IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) { |
606 // Adjust offset to the way ARM CPUs read PC. | 608 // Adjust offset to the way ARM CPUs read PC. |
607 Offset -= kPCReadOffset; | 609 Offset -= kPCReadOffset; |
608 | 610 |
609 bool IsGoodOffset = canEncodeBranchOffset(Offset); | 611 bool IsGoodOffset = canEncodeBranchOffset(Offset); |
610 assert(IsGoodOffset); | 612 assert(IsGoodOffset); |
611 // Note: Following cast is for MINIMAL build. | |
612 (void)IsGoodOffset; | 613 (void)IsGoodOffset; |
613 | 614 |
614 // Properly preserve only the bits supported in the instruction. | 615 // Properly preserve only the bits supported in the instruction. |
615 Offset >>= 2; | 616 Offset >>= 2; |
616 Offset &= kBranchOffsetMask; | 617 Offset &= kBranchOffsetMask; |
617 return (Inst & ~kBranchOffsetMask) | Offset; | 618 return (Inst & ~kBranchOffsetMask) | Offset; |
618 } | 619 } |
619 | 620 |
620 // Pull out offset from branch Inst. | 621 // Pull out offset from branch Inst. |
621 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { | 622 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { |
(...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2235 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] | 2236 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] |
2236 // | 2237 // |
2237 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, | 2238 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, |
2238 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. | 2239 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. |
2239 constexpr const char *Vldrd = "vldrd"; | 2240 constexpr const char *Vldrd = "vldrd"; |
2240 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); | 2241 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); |
2241 assert(CondARM32::isDefined(Cond)); | 2242 assert(CondARM32::isDefined(Cond)); |
2242 IValueT Address; | 2243 IValueT Address; |
2243 EncodedOperand AddressEncoding = | 2244 EncodedOperand AddressEncoding = |
2244 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2245 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2245 if (AddressEncoding != EncodedAsImmRegOffset) | 2246 (void)AddressEncoding; |
2246 // TODO(kschimpf) Fix this. | 2247 assert(AddressEncoding == EncodedAsImmRegOffset); |
2247 return setNeedsTextFixup(); | |
2248 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2248 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2249 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | | 2249 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | |
2250 (encodeCondition(Cond) << kConditionShift) | | 2250 (encodeCondition(Cond) << kConditionShift) | |
2251 (getYInRegYXXXX(Dd) << 22) | | 2251 (getYInRegYXXXX(Dd) << 22) | |
2252 (getXXXXInRegYXXXX(Dd) << 12) | Address; | 2252 (getXXXXInRegYXXXX(Dd) << 12) | Address; |
2253 emitInst(Encoding); | 2253 emitInst(Encoding); |
2254 } | 2254 } |
2255 | 2255 |
2256 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, | 2256 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, |
2257 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2257 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
2258 // VDLR - ARM section A8.8.333, encoding A2. | 2258 // VDLR - ARM section A8.8.333, encoding A2. |
2259 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] | 2259 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] |
2260 // | 2260 // |
2261 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, | 2261 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, |
2262 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; | 2262 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; |
2263 constexpr const char *Vldrs = "vldrs"; | 2263 constexpr const char *Vldrs = "vldrs"; |
2264 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); | 2264 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); |
2265 assert(CondARM32::isDefined(Cond)); | 2265 assert(CondARM32::isDefined(Cond)); |
2266 IValueT Address; | 2266 IValueT Address; |
2267 EncodedOperand AddressEncoding = encodeAddress(OpAddress, Address, TInfo); | 2267 EncodedOperand AddressEncoding = |
2268 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | |
2268 (void)AddressEncoding; | 2269 (void)AddressEncoding; |
2269 assert(AddressEncoding == EncodedAsImmRegOffset); | 2270 assert(AddressEncoding == EncodedAsImmRegOffset); |
2270 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2271 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2271 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | | 2272 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | |
2272 (encodeCondition(Cond) << kConditionShift) | | 2273 (encodeCondition(Cond) << kConditionShift) | |
2273 (getYInRegXXXXY(Sd) << 22) | | 2274 (getYInRegXXXXY(Sd) << 22) | |
2274 (getXXXXInRegXXXXY(Sd) << 12) | Address; | 2275 (getXXXXInRegXXXXY(Sd) << 12) | Address; |
2275 emitInst(Encoding); | 2276 emitInst(Encoding); |
2276 } | 2277 } |
2277 | 2278 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2311 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] | 2312 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] |
2312 // | 2313 // |
2313 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, | 2314 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, |
2314 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. | 2315 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. |
2315 constexpr const char *Vstrd = "vstrd"; | 2316 constexpr const char *Vstrd = "vstrd"; |
2316 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); | 2317 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); |
2317 assert(CondARM32::isDefined(Cond)); | 2318 assert(CondARM32::isDefined(Cond)); |
2318 IValueT Address; | 2319 IValueT Address; |
2319 IValueT AddressEncoding = | 2320 IValueT AddressEncoding = |
2320 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); | 2321 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2321 if (AddressEncoding != EncodedAsImmRegOffset) | 2322 (void)AddressEncoding; |
2322 // TODO(kschimpf) Fix this. | 2323 assert(AddressEncoding == EncodedAsImmRegOffset); |
2323 return setNeedsTextFixup(); | |
2324 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2324 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2325 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | | 2325 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | |
2326 (encodeCondition(Cond) << kConditionShift) | | 2326 (encodeCondition(Cond) << kConditionShift) | |
2327 (getYInRegYXXXX(Dd) << 22) | | 2327 (getYInRegYXXXX(Dd) << 22) | |
2328 (getXXXXInRegYXXXX(Dd) << 12) | Address; | 2328 (getXXXXInRegYXXXX(Dd) << 12) | Address; |
2329 emitInst(Encoding); | 2329 emitInst(Encoding); |
2330 } | 2330 } |
2331 | 2331 |
2332 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, | 2332 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, |
2333 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2333 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
2334 // VSTR - ARM section A8.8.413, encoding A2: | 2334 // VSTR - ARM section A8.8.413, encoding A2: |
2335 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] | 2335 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] |
2336 // | 2336 // |
2337 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, | 2337 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, |
2338 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; | 2338 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; |
2339 constexpr const char *Vstrs = "vstrs"; | 2339 constexpr const char *Vstrs = "vstrs"; |
2340 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); | 2340 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); |
2341 assert(CondARM32::isDefined(Cond)); | 2341 assert(CondARM32::isDefined(Cond)); |
2342 IValueT Address; | 2342 IValueT Address; |
2343 if (encodeAddress(OpAddress, Address, TInfo) != EncodedAsImmRegOffset) | 2343 IValueT AddressEncoding = |
2344 assert(false); | 2344 encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); |
2345 (void)AddressEncoding; | |
2346 assert(AddressEncoding == EncodedAsImmRegOffset); | |
2345 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2347 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
2346 IValueT Encoding = | 2348 IValueT Encoding = |
2347 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | | 2349 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | |
2348 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; | 2350 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; |
2349 emitInst(Encoding); | 2351 emitInst(Encoding); |
2350 } | 2352 } |
2351 | 2353 |
2352 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, | 2354 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, |
2353 const Operand *OpSm, CondARM32::Cond Cond) { | 2355 const Operand *OpSm, CondARM32::Cond Cond) { |
2354 // VSUB (floating-point) - ARM section A8.8.415, encoding A2: | 2356 // VSUB (floating-point) - ARM section A8.8.415, encoding A2: |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2421 // | 2423 // |
2422 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and | 2424 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and |
2423 // iiiiiiii=NumConsecRegs. | 2425 // iiiiiiii=NumConsecRegs. |
2424 constexpr IValueT VpushOpcode = | 2426 constexpr IValueT VpushOpcode = |
2425 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; | 2427 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; |
2426 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); | 2428 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); |
2427 } | 2429 } |
2428 | 2430 |
2429 } // end of namespace ARM32 | 2431 } // end of namespace ARM32 |
2430 } // end of namespace Ice | 2432 } // end of namespace Ice |
OLD | NEW |