Chromium Code Reviews| 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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 // No alternate layout specified. | 189 // No alternate layout specified. |
| 190 DefaultOpEncoding, | 190 DefaultOpEncoding, |
| 191 // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and | 191 // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and |
| 192 // ldrh. | 192 // ldrh. |
| 193 OpEncoding3, | 193 OpEncoding3, |
| 194 // Alternate encoding for memory operands for ldrex and strex, which only | 194 // Alternate encoding for memory operands for ldrex and strex, which only |
| 195 // actually expect a register. | 195 // actually expect a register. |
| 196 OpEncodingMemEx | 196 OpEncodingMemEx |
| 197 }; | 197 }; |
| 198 | 198 |
| 199 IValueT getEncodedGPRegNum(const Variable *Var) { | |
| 200 int32_t Reg = Var->getRegNum(); | |
| 201 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) | |
| 202 : RegARM32::getEncodedGPR(Reg); | |
| 203 } | |
| 204 | |
| 205 IValueT getEncodedSRegNum(const Variable *Var) { | |
| 206 assert(Var->hasReg()); | |
| 207 assert(RegARM32::isEncodedSReg(Var->getRegNum())); | |
| 208 return RegARM32::getEncodedSReg(Var->getRegNum()); | |
| 209 } | |
| 210 | |
| 211 // The way an operand is encoded into a sequence of bits in functions | 199 // The way an operand is encoded into a sequence of bits in functions |
| 212 // encodeOperand and encodeAddress below. | 200 // encodeOperand and encodeAddress below. |
| 213 enum EncodedOperand { | 201 enum EncodedOperand { |
| 214 // Unable to encode, value left undefined. | 202 // Unable to encode, value left undefined. |
| 215 CantEncode = 0, | 203 CantEncode = 0, |
| 216 // Value is register found. | 204 // Value is register found. |
| 217 EncodedAsRegister, | 205 EncodedAsRegister, |
| 218 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 206 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
| 219 // value. | 207 // value. |
| 220 EncodedAsRotatedImm8, | 208 EncodedAsRotatedImm8, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 263 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
| 276 IValueT Rs) { | 264 IValueT Rs) { |
| 277 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 265 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
| 278 (Rm << kRmShift); | 266 (Rm << kRmShift); |
| 279 } | 267 } |
| 280 | 268 |
| 281 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { | 269 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { |
| 282 Value = 0; // Make sure initialized. | 270 Value = 0; // Make sure initialized. |
| 283 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 271 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
| 284 if (Var->hasReg()) { | 272 if (Var->hasReg()) { |
| 285 Value = getEncodedGPRegNum(Var); | 273 Value = ARM32::AssemblerARM32::getEncodedGPRegNum(Var); |
| 286 return EncodedAsRegister; | 274 return EncodedAsRegister; |
| 287 } | 275 } |
| 288 return CantEncode; | 276 return CantEncode; |
| 289 } | 277 } |
| 290 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 278 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
| 291 const IValueT Immed8 = FlexImm->getImm(); | 279 const IValueT Immed8 = FlexImm->getImm(); |
| 292 const IValueT Rotate = FlexImm->getRotateAmt(); | 280 const IValueT Rotate = FlexImm->getRotateAmt(); |
| 293 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) | 281 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) |
| 294 return CantEncode; | 282 return CantEncode; |
| 295 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 283 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 if (BaseRegNum == Variable::NoRegister) | 377 if (BaseRegNum == Variable::NoRegister) |
| 390 BaseRegNum = TInfo.FrameOrStackReg; | 378 BaseRegNum = TInfo.FrameOrStackReg; |
| 391 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, | 379 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, |
| 392 OperandARM32Mem::Offset); | 380 OperandARM32Mem::Offset); |
| 393 return EncodedAsImmRegOffset; | 381 return EncodedAsImmRegOffset; |
| 394 } | 382 } |
| 395 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 383 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
| 396 Variable *Var = Mem->getBase(); | 384 Variable *Var = Mem->getBase(); |
| 397 if (!Var->hasReg()) | 385 if (!Var->hasReg()) |
| 398 return CantEncode; | 386 return CantEncode; |
| 399 IValueT Rn = getEncodedGPRegNum(Var); | 387 IValueT Rn = ARM32::AssemblerARM32::getEncodedGPRegNum(Var); |
| 400 if (Mem->isRegReg()) { | 388 if (Mem->isRegReg()) { |
| 401 const Variable *Index = Mem->getIndex(); | 389 const Variable *Index = Mem->getIndex(); |
| 402 if (Var == nullptr) | 390 if (Var == nullptr) |
| 403 return CantEncode; | 391 return CantEncode; |
| 404 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 392 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
| 405 encodeShiftRotateImm5(getEncodedGPRegNum(Index), | 393 encodeShiftRotateImm5( |
| 406 Mem->getShiftOp(), Mem->getShiftAmt()); | 394 ARM32::AssemblerARM32::getEncodedGPRegNum(Index), |
| 395 Mem->getShiftOp(), Mem->getShiftAmt()); | |
| 407 return EncodedAsShiftRotateImm5; | 396 return EncodedAsShiftRotateImm5; |
| 408 } | 397 } |
| 409 // Encoded as immediate register offset. | 398 // Encoded as immediate register offset. |
| 410 ConstantInteger32 *Offset = Mem->getOffset(); | 399 ConstantInteger32 *Offset = Mem->getOffset(); |
| 411 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), | 400 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), |
| 412 Mem->getAddrMode()); | 401 Mem->getAddrMode()); |
| 413 return EncodedAsImmRegOffset; | 402 return EncodedAsImmRegOffset; |
| 414 } | 403 } |
| 415 return CantEncode; | 404 return CantEncode; |
| 416 } | 405 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 } | 517 } |
| 529 | 518 |
| 530 void AssemblerARM32::padWithNop(intptr_t Padding) { | 519 void AssemblerARM32::padWithNop(intptr_t Padding) { |
| 531 constexpr intptr_t InstWidth = sizeof(IValueT); | 520 constexpr intptr_t InstWidth = sizeof(IValueT); |
| 532 assert(Padding % InstWidth == 0 && | 521 assert(Padding % InstWidth == 0 && |
| 533 "Padding not multiple of instruction size"); | 522 "Padding not multiple of instruction size"); |
| 534 for (intptr_t i = 0; i < Padding; i += InstWidth) | 523 for (intptr_t i = 0; i < Padding; i += InstWidth) |
| 535 nop(); | 524 nop(); |
| 536 } | 525 } |
| 537 | 526 |
| 527 IValueT AssemblerARM32::getEncodedGPRegNum(const Variable *Var) { | |
| 528 int32_t Reg = Var->getRegNum(); | |
| 529 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) | |
| 530 : RegARM32::getEncodedGPR(Reg); | |
| 531 } | |
| 532 | |
| 533 IValueT AssemblerARM32::getEncodedSRegNum(const Variable *Var) { | |
| 534 assert(Var->hasReg()); | |
|
John
2016/01/06 16:10:21
optional: This assertion is not needed -- Var->get
Karl
2016/01/06 23:21:58
Done.
| |
| 535 assert(RegARM32::isEncodedSReg(Var->getRegNum())); | |
| 536 return RegARM32::getEncodedSReg(Var->getRegNum()); | |
| 537 } | |
| 538 | |
| 538 BlRelocatableFixup * | 539 BlRelocatableFixup * |
| 539 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { | 540 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { |
| 540 BlRelocatableFixup *F = | 541 BlRelocatableFixup *F = |
| 541 new (allocate<BlRelocatableFixup>()) BlRelocatableFixup(); | 542 new (allocate<BlRelocatableFixup>()) BlRelocatableFixup(); |
| 542 F->set_kind(llvm::ELF::R_ARM_CALL); | 543 F->set_kind(llvm::ELF::R_ARM_CALL); |
| 543 F->set_value(BlTarget); | 544 F->set_value(BlTarget); |
| 544 Buffer.installFixup(F); | 545 Buffer.installFixup(F); |
| 545 return F; | 546 return F; |
| 546 } | 547 } |
| 547 | 548 |
| (...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1681 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 1682 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 1682 // | 1683 // |
| 1683 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 1684 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1684 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. | 1685 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
| 1685 constexpr const char *OrrName = "orr"; | 1686 constexpr const char *OrrName = "orr"; |
| 1686 constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100 | 1687 constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100 |
| 1687 emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, | 1688 emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, |
| 1688 OrrName); | 1689 OrrName); |
| 1689 } | 1690 } |
| 1690 | 1691 |
| 1691 void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) { | 1692 void AssemblerARM32::pop(const Variable *OpRt, CondARM32::Cond Cond) { |
| 1692 // POP - ARM section A8.8.132, encoding A2: | 1693 // POP - ARM section A8.8.132, encoding A2: |
| 1693 // pop<c> {Rt} | 1694 // pop<c> {Rt} |
| 1694 // | 1695 // |
| 1695 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. | 1696 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. |
| 1696 constexpr const char *Pop = "pop"; | 1697 constexpr const char *Pop = "pop"; |
| 1697 IValueT Rt = encodeRegister(OpRt, "Rt", Pop); | 1698 const IValueT Rt = encodeRegister(OpRt, "Rt", Pop); |
| 1698 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); | 1699 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); |
| 1699 // Same as load instruction. | 1700 // Same as load instruction. |
| 1700 constexpr bool IsLoad = true; | 1701 constexpr bool IsLoad = true; |
| 1701 constexpr bool IsByte = false; | 1702 constexpr bool IsByte = false; |
| 1702 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, | 1703 IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, |
| 1703 OperandARM32Mem::PostIndex); | 1704 OperandARM32Mem::PostIndex); |
| 1704 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, Pop); | 1705 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, Pop); |
| 1705 } | 1706 } |
| 1706 | 1707 |
| 1707 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { | 1708 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2002 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 2003 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
| 2003 CondARM32::Cond Cond) { | 2004 CondARM32::Cond Cond) { |
| 2004 constexpr const char *UxtName = "uxt"; | 2005 constexpr const char *UxtName = "uxt"; |
| 2005 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 2006 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
| 2006 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 2007 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
| 2007 } | 2008 } |
| 2008 | 2009 |
| 2009 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, | 2010 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, |
| 2010 const Variable *OpBaseReg, | 2011 const Variable *OpBaseReg, |
| 2011 SizeT NumConsecRegs, const char *InstName) { | 2012 SizeT NumConsecRegs, const char *InstName) { |
| 2012 | |
| 2013 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); | 2013 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); |
| 2014 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. | 2014 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. |
| 2015 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. | 2015 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. |
| 2016 assert(0 < NumConsecRegs); | 2016 assert(0 < NumConsecRegs); |
| 2017 (void)VpushVpopMaxConsecRegs; | 2017 (void)VpushVpopMaxConsecRegs; |
| 2018 assert(NumConsecRegs <= VpushVpopMaxConsecRegs); | 2018 assert(NumConsecRegs <= VpushVpopMaxConsecRegs); |
| 2019 assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs()); | 2019 assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs()); |
| 2020 verifyCondDefined(Cond, InstName); | 2020 verifyCondDefined(Cond, InstName); |
| 2021 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 2021 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 2022 const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit | | 2022 const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit | |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 2051 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and | 2051 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and |
| 2052 // iiiiiiii=NumConsecRegs. | 2052 // iiiiiiii=NumConsecRegs. |
| 2053 constexpr const char *VpushName = "vpush"; | 2053 constexpr const char *VpushName = "vpush"; |
| 2054 constexpr IValueT VpushOpcode = | 2054 constexpr IValueT VpushOpcode = |
| 2055 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; | 2055 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; |
| 2056 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs, VpushName); | 2056 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs, VpushName); |
| 2057 } | 2057 } |
| 2058 | 2058 |
| 2059 } // end of namespace ARM32 | 2059 } // end of namespace ARM32 |
| 2060 } // end of namespace Ice | 2060 } // end of namespace Ice |
| OLD | NEW |