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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 // Shift instruction register fields encodings. | 93 // Shift instruction register fields encodings. |
| 94 static constexpr IValueT kShiftImmShift = 7; | 94 static constexpr IValueT kShiftImmShift = 7; |
| 95 static constexpr IValueT kShiftImmBits = 5; | 95 static constexpr IValueT kShiftImmBits = 5; |
| 96 static constexpr IValueT kShiftShift = 5; | 96 static constexpr IValueT kShiftShift = 5; |
| 97 static constexpr IValueT kImmed12Bits = 12; | 97 static constexpr IValueT kImmed12Bits = 12; |
| 98 static constexpr IValueT kImm12Shift = 0; | 98 static constexpr IValueT kImm12Shift = 0; |
| 99 | 99 |
| 100 // Rotation instructions (uxtb etc.). | 100 // Rotation instructions (uxtb etc.). |
| 101 static constexpr IValueT kRotationShift = 10; | 101 static constexpr IValueT kRotationShift = 10; |
| 102 | 102 |
| 103 // MemEx instructions. | |
| 104 static constexpr IValueT kMemExOpcodeShift = 20; | |
| 105 | |
| 103 // Div instruction register field encodings. | 106 // Div instruction register field encodings. |
| 104 static constexpr IValueT kDivRdShift = 16; | 107 static constexpr IValueT kDivRdShift = 16; |
| 105 static constexpr IValueT kDivRmShift = 8; | 108 static constexpr IValueT kDivRmShift = 8; |
| 106 static constexpr IValueT kDivRnShift = 0; | 109 static constexpr IValueT kDivRnShift = 0; |
| 107 | 110 |
| 108 // Type of instruction encoding (bits 25-27). See ARM section A5.1 | 111 // Type of instruction encoding (bits 25-27). See ARM section A5.1 |
| 109 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 | 112 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 |
| 110 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 | 113 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 |
| 111 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 | 114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 |
| 112 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 | 115 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 } | 173 } |
| 171 | 174 |
| 172 // Extract out a Bit in Value. | 175 // Extract out a Bit in Value. |
| 173 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } | 176 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } |
| 174 | 177 |
| 175 // Returns the GPR register at given Shift in Value. | 178 // Returns the GPR register at given Shift in Value. |
| 176 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { | 179 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { |
| 177 return decodeGPRRegister((Value >> Shift) & 0xF); | 180 return decodeGPRRegister((Value >> Shift) & 0xF); |
| 178 } | 181 } |
| 179 | 182 |
| 183 // Defines alternate layouts of instruction operands, should the (common) | |
| 184 // default pattern not be used. | |
| 185 enum OpEncoding { | |
| 186 // No alternate layout specified. | |
| 187 DefaultOpEncoding, | |
| 188 // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and | |
| 189 // ldrh. | |
| 190 OpEncoding3, | |
| 191 // Alternate encoding for memory operands for ldrex and strex, which only | |
| 192 // actually expect a register. | |
| 193 OpEncodingMemEx | |
| 194 }; | |
| 195 | |
| 196 IValueT getEncodedGPRegNum(const Variable *Var) { | |
| 197 int32_t Reg = Var->getRegNum(); | |
| 198 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) | |
| 199 : RegARM32::getEncodedGPR(Reg); | |
| 200 } | |
| 201 | |
| 180 // The way an operand is encoded into a sequence of bits in functions | 202 // The way an operand is encoded into a sequence of bits in functions |
| 181 // encodeOperand and encodeAddress below. | 203 // encodeOperand and encodeAddress below. |
| 182 enum EncodedOperand { | 204 enum EncodedOperand { |
| 183 // Unable to encode, value left undefined. | 205 // Unable to encode, value left undefined. |
| 184 CantEncode = 0, | 206 CantEncode = 0, |
| 185 // Value is register found. | 207 // Value is register found. |
| 186 EncodedAsRegister, | 208 EncodedAsRegister, |
| 187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 209 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
| 188 // value. | 210 // value. |
| 189 EncodedAsRotatedImm8, | 211 EncodedAsRotatedImm8, |
| 212 // EncodedAsImmRegOffset is a memory operand that can take three forms, based | |
| 213 // on OpEncoding: | |
| 214 // | |
| 215 // ***** DefaultOpEncoding ***** | |
| 216 // | |
| 190 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 217 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
| 191 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | 218 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to |
| 192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. | 219 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
| 193 EncodedAsImmRegOffset, | 220 // |
| 221 // ***** OpEncoding3 ***** | |
| 222 // | |
| 194 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 | 223 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
| 195 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to | 224 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to |
| 196 // Rn. | 225 // Rn. |
| 197 EncodedAsImmRegOffsetEnc3, | 226 // |
| 227 // ***** OpEncodingMemEx ***** | |
| 228 // | |
| 229 // Value=000000000000nnnn0000000000000000 where nnnn=Rn. | |
| 230 EncodedAsImmRegOffset, | |
| 198 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 231 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
| 199 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift | 232 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift |
| 200 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if | 233 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
| 201 // writeback to Rn. | 234 // writeback to Rn. |
| 202 EncodedAsShiftRotateImm5, | 235 EncodedAsShiftRotateImm5, |
| 203 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value | 236 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
| 204 // to shift. | 237 // to shift. |
| 205 EncodedAsShiftImm5, | 238 EncodedAsShiftImm5, |
| 206 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 239 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
| 207 // kind, and iiiii is the shift amount. | 240 // kind, and iiiii is the shift amount. |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 233 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 266 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
| 234 IValueT Rs) { | 267 IValueT Rs) { |
| 235 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 268 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
| 236 (Rm << kRmShift); | 269 (Rm << kRmShift); |
| 237 } | 270 } |
| 238 | 271 |
| 239 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { | 272 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { |
| 240 Value = 0; // Make sure initialized. | 273 Value = 0; // Make sure initialized. |
| 241 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 274 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
| 242 if (Var->hasReg()) { | 275 if (Var->hasReg()) { |
| 243 Value = Var->getRegNum(); | 276 Value = getEncodedGPRegNum(Var); |
| 244 return EncodedAsRegister; | 277 return EncodedAsRegister; |
| 245 } | 278 } |
| 246 return CantEncode; | 279 return CantEncode; |
| 247 } | 280 } |
| 248 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 281 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
| 249 const IValueT Immed8 = FlexImm->getImm(); | 282 const IValueT Immed8 = FlexImm->getImm(); |
| 250 const IValueT Rotate = FlexImm->getRotateAmt(); | 283 const IValueT Rotate = FlexImm->getRotateAmt(); |
| 251 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) | 284 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) |
| 252 return CantEncode; | 285 return CantEncode; |
| 253 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 286 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 IValueT Value = Mode | (Rn << kRnShift); | 342 IValueT Value = Mode | (Rn << kRnShift); |
| 310 if (Imm8 < 0) { | 343 if (Imm8 < 0) { |
| 311 Imm8 = -Imm8; | 344 Imm8 = -Imm8; |
| 312 Value = (Value ^ U); | 345 Value = (Value ^ U); |
| 313 } | 346 } |
| 314 assert(Imm8 < (1 << 8)); | 347 assert(Imm8 < (1 << 8)); |
| 315 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); | 348 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); |
| 316 return Value; | 349 return Value; |
| 317 } | 350 } |
| 318 | 351 |
| 319 // Defines alternate layouts of instruction operands, should the (common) | 352 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, |
| 320 // default pattern not be used. | 353 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { |
| 321 enum OpEncoding { | 354 switch (AddressEncoding) { |
| 322 // No alternate layout specified. | 355 case DefaultOpEncoding: |
| 323 DefaultOpEncoding, | 356 return encodeImmRegOffset(Reg, Offset, Mode); |
| 324 // Alternate encoding 3. | 357 case OpEncoding3: |
| 325 OpEncoding3 | 358 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); |
| 326 }; | 359 case OpEncodingMemEx: |
| 360 assert(Offset == 0); | |
| 361 assert(Mode == OperandARM32Mem::Offset); | |
| 362 return Reg << kRnShift; | |
| 363 } | |
| 364 } | |
| 327 | 365 |
| 328 // Encodes memory address Opnd, and encodes that information into Value, based | 366 // Encodes memory address Opnd, and encodes that information into Value, based |
| 329 // on how ARM represents the address. Returns how the value was encoded. | 367 // on how ARM represents the address. Returns how the value was encoded. |
| 330 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, | 368 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
| 331 const AssemblerARM32::TargetInfo &TInfo, | 369 const AssemblerARM32::TargetInfo &TInfo, |
| 332 OpEncoding AddressEncoding = DefaultOpEncoding) { | 370 OpEncoding AddressEncoding = DefaultOpEncoding) { |
| 333 Value = 0; // Make sure initialized. | 371 Value = 0; // Make sure initialized. |
| 334 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 372 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
| 335 // Should be a stack variable, with an offset. | 373 // Should be a stack variable, with an offset. |
| 336 if (Var->hasReg()) | 374 if (Var->hasReg()) |
| 337 return CantEncode; | 375 return CantEncode; |
| 338 IOffsetT Offset = Var->getStackOffset(); | 376 IOffsetT Offset = Var->getStackOffset(); |
| 339 if (!Utils::IsAbsoluteUint(12, Offset)) | 377 if (!Utils::IsAbsoluteUint(12, Offset)) |
| 340 return CantEncode; | 378 return CantEncode; |
| 341 int32_t BaseRegNum = Var->getBaseRegNum(); | 379 int32_t BaseRegNum = Var->getBaseRegNum(); |
| 342 if (BaseRegNum == Variable::NoRegister) | 380 if (BaseRegNum == Variable::NoRegister) |
| 343 BaseRegNum = TInfo.FrameOrStackReg; | 381 BaseRegNum = TInfo.FrameOrStackReg; |
| 344 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); | 382 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, |
| 383 OperandARM32Mem::Offset); | |
| 345 return EncodedAsImmRegOffset; | 384 return EncodedAsImmRegOffset; |
| 346 } | 385 } |
| 347 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 386 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
| 348 Variable *Var = Mem->getBase(); | 387 Variable *Var = Mem->getBase(); |
| 349 if (!Var->hasReg()) | 388 if (!Var->hasReg()) |
| 350 return CantEncode; | 389 return CantEncode; |
| 351 IValueT Rn = Var->getRegNum(); | 390 IValueT Rn = getEncodedGPRegNum(Var); |
| 352 if (Mem->isRegReg()) { | 391 if (Mem->isRegReg()) { |
| 353 const Variable *Index = Mem->getIndex(); | 392 const Variable *Index = Mem->getIndex(); |
| 354 if (Var == nullptr) | 393 if (Var == nullptr) |
| 355 return CantEncode; | 394 return CantEncode; |
| 356 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 395 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
| 357 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), | 396 encodeShiftRotateImm5(getEncodedGPRegNum(Index), Mem->getShiftOp() , |
| 358 Mem->getShiftAmt()); | 397 Mem->getShiftAmt()); |
| 359 return EncodedAsShiftRotateImm5; | 398 return EncodedAsShiftRotateImm5; |
| 360 } | 399 } |
| 361 // Encoded as immediate register offset. | 400 // Encoded as immediate register offset. |
| 362 ConstantInteger32 *Offset = Mem->getOffset(); | 401 ConstantInteger32 *Offset = Mem->getOffset(); |
| 363 switch (AddressEncoding) { | 402 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), |
| 364 case DefaultOpEncoding: | 403 Mem->getAddrMode()); |
| 365 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); | 404 return EncodedAsImmRegOffset; |
| 366 return EncodedAsImmRegOffset; | |
| 367 case OpEncoding3: | |
| 368 Value = | |
| 369 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode()); | |
| 370 return EncodedAsImmRegOffsetEnc3; | |
| 371 } | |
| 372 } | 405 } |
| 373 return CantEncode; | 406 return CantEncode; |
| 374 } | 407 } |
| 375 | 408 |
| 376 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 409 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
| 377 bool canEncodeBranchOffset(IOffsetT Offset) { | 410 bool canEncodeBranchOffset(IOffsetT Offset) { |
| 378 return Utils::IsAligned(Offset, 4) && | 411 return Utils::IsAligned(Offset, 4) && |
| 379 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 412 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
| 380 } | 413 } |
| 381 | 414 |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 | 825 |
| 793 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 826 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
| 794 IValueT Rt, const Operand *OpAddress, | 827 IValueT Rt, const Operand *OpAddress, |
| 795 const TargetInfo &TInfo, | 828 const TargetInfo &TInfo, |
| 796 const char *InstName) { | 829 const char *InstName) { |
| 797 IValueT Address; | 830 IValueT Address; |
| 798 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 831 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
| 799 default: | 832 default: |
| 800 llvm::report_fatal_error(std::string(InstName) + | 833 llvm::report_fatal_error(std::string(InstName) + |
| 801 ": Memory address not understood"); | 834 ": Memory address not understood"); |
| 802 case EncodedAsImmRegOffsetEnc3: { | 835 case EncodedAsImmRegOffset: { |
| 803 // XXXH (immediate) | 836 // XXXH (immediate) |
| 804 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] | 837 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
| 805 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] | 838 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
| 806 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 839 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
| 807 // | 840 // |
| 808 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, | 841 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
| 809 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, | 842 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, |
| 810 // and pu0w0nnnn0000iiii0000jjjj=Address. | 843 // and pu0w0nnnn0000iiii0000jjjj=Address. |
| 811 verifyRegDefined(Rt, "Rt", InstName); | 844 verifyRegDefined(Rt, "Rt", InstName); |
| 812 verifyCondDefined(Cond, InstName); | 845 verifyCondDefined(Cond, InstName); |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1159 | 1192 |
| 1160 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 1193 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
| 1161 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1194 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1162 constexpr const char *LdrName = "ldr"; | 1195 constexpr const char *LdrName = "ldr"; |
| 1163 constexpr bool IsLoad = true; | 1196 constexpr bool IsLoad = true; |
| 1164 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); | 1197 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); |
| 1165 const Type Ty = OpRt->getType(); | 1198 const Type Ty = OpRt->getType(); |
| 1166 switch (typeWidthInBytesLog2(Ty)) { | 1199 switch (typeWidthInBytesLog2(Ty)) { |
| 1167 case 3: | 1200 case 3: |
| 1168 // LDRD is not implemented because target lowering handles i64 and double by | 1201 // LDRD is not implemented because target lowering handles i64 and double by |
| 1169 // using two (32-bit) load instructions. Note: Intenionally drop to default | 1202 // using two (32-bit) load instructions. Note: Intenionally drop to default |
|
Jim Stichnoth
2015/12/11 20:17:25
Intentionally
Karl
2015/12/11 21:00:12
Done.
| |
| 1170 // case. | 1203 // case. |
| 1171 default: | 1204 default: |
| 1172 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + | 1205 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + |
| 1173 " not implementable\n"); | 1206 " not implementable"); |
| 1174 case 0: { | 1207 case 0: { |
| 1175 // Handles i1 and i8 loads. | 1208 // Handles i1 and i8 loads. |
| 1176 // | 1209 // |
| 1177 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 1210 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
| 1178 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1211 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1179 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1212 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 1180 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1213 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 1181 // | 1214 // |
| 1182 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1215 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1183 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1216 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1226 // | 1259 // |
| 1227 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1260 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
| 1228 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1261 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
| 1229 constexpr bool IsByte = false; | 1262 constexpr bool IsByte = false; |
| 1230 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); | 1263 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
| 1231 return; | 1264 return; |
| 1232 } | 1265 } |
| 1233 } | 1266 } |
| 1234 } | 1267 } |
| 1235 | 1268 |
| 1269 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad, | |
| 1270 const Operand *OpRd, IValueT Rt, | |
| 1271 const Operand *OpAddress, | |
| 1272 const TargetInfo &TInfo, | |
| 1273 const char *InstName) { | |
| 1274 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | |
| 1275 IValueT MemExOpcode = IsLoad ? B0 : 0; | |
| 1276 switch (typeWidthInBytesLog2(Ty)) { | |
| 1277 default: | |
| 1278 llvm::report_fatal_error(std::string(InstName) + ": Type " + | |
| 1279 typeString(Ty) + " not implementable"); | |
| 1280 case 0: | |
| 1281 MemExOpcode |= B2; | |
| 1282 break; | |
| 1283 case 1: | |
| 1284 MemExOpcode |= B2 | B1; | |
| 1285 break; | |
| 1286 case 2: | |
| 1287 break; | |
| 1288 case 3: | |
| 1289 MemExOpcode |= B1; | |
| 1290 } | |
| 1291 IValueT AddressRn; | |
| 1292 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) != | |
| 1293 EncodedAsImmRegOffset) | |
| 1294 llvm::report_fatal_error(std::string(InstName) + | |
| 1295 ": Can't extract Rn from address"); | |
| 1296 assert(Utils::IsAbsoluteUint(3, MemExOpcode)); | |
| 1297 verifyRegDefined(Rd, "Rd", InstName); | |
| 1298 verifyRegDefined(Rt, "Rt", InstName); | |
| 1299 verifyCondDefined(Cond, InstName); | |
| 1300 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
| 1301 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 | | |
| 1302 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) | | |
| 1303 AddressRn | (Rd << kRdShift) | (Rt << kRmShift); | |
| 1304 emitInst(Encoding); | |
| 1305 return; | |
| 1306 } | |
| 1307 | |
| 1308 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress, | |
| 1309 CondARM32::Cond Cond, const TargetInfo &TInfo) { | |
| 1310 // LDREXB - ARM section A8.8.76, encoding A1: | |
| 1311 // ldrexb<c> <Rt>, [<Rn>] | |
| 1312 // | |
| 1313 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
| 1314 // | |
| 1315 // LDREXH - ARM section A8.8.78, encoding A1: | |
| 1316 // ldrexh<c> <Rt>, [<Rn>] | |
| 1317 // | |
| 1318 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
| 1319 // | |
| 1320 // LDREX - ARM section A8.8.75, encoding A1: | |
| 1321 // ldrex<c> <Rt>, [<Rn>] | |
| 1322 // | |
| 1323 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
| 1324 // | |
| 1325 // LDREXD - ARM section A8. | |
| 1326 // ldrexd<c> <Rt>, [<Rn>] | |
| 1327 // | |
| 1328 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
| 1329 constexpr const char *LdrexName = "ldrex"; | |
| 1330 const Type Ty = OpRt->getType(); | |
| 1331 constexpr bool IsLoad = true; | |
| 1332 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc; | |
| 1333 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName); | |
| 1334 } | |
| 1335 | |
| 1236 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, | 1336 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, |
| 1237 const OperandARM32::ShiftKind Shift, | 1337 const OperandARM32::ShiftKind Shift, |
| 1238 const Operand *OpRd, const Operand *OpRm, | 1338 const Operand *OpRd, const Operand *OpRm, |
| 1239 const Operand *OpSrc1, const bool SetFlags, | 1339 const Operand *OpSrc1, const bool SetFlags, |
| 1240 const char *InstName) { | 1340 const char *InstName) { |
| 1241 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 | 1341 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 |
| 1242 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | 1342 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
| 1243 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); | 1343 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); |
| 1244 IValueT Value; | 1344 IValueT Value; |
| 1245 switch (encodeOperand(OpSrc1, Value)) { | 1345 switch (encodeOperand(OpSrc1, Value)) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1443 | 1543 |
| 1444 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 1544 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
| 1445 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 1545 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 1446 constexpr const char *StrName = "str"; | 1546 constexpr const char *StrName = "str"; |
| 1447 constexpr bool IsLoad = false; | 1547 constexpr bool IsLoad = false; |
| 1448 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); | 1548 IValueT Rt = encodeRegister(OpRt, "Rt", StrName); |
| 1449 const Type Ty = OpRt->getType(); | 1549 const Type Ty = OpRt->getType(); |
| 1450 switch (typeWidthInBytesLog2(Ty)) { | 1550 switch (typeWidthInBytesLog2(Ty)) { |
| 1451 case 3: | 1551 case 3: |
| 1452 // STRD is not implemented because target lowering handles i64 and double by | 1552 // STRD is not implemented because target lowering handles i64 and double by |
| 1453 // using two (32-bit) store instructions. Note: Intenionally drop to | 1553 // using two (32-bit) store instructions. Note: Intenionally drop to |
|
Jim Stichnoth
2015/12/11 20:17:25
Intentionally
Karl
2015/12/11 21:00:12
Done.
| |
| 1454 // default case. | 1554 // default case. |
| 1455 default: | 1555 default: |
| 1456 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + | 1556 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + |
| 1457 " not implemented"); | 1557 " not implemented"); |
| 1458 case 0: { | 1558 case 0: { |
| 1459 // Handles i1 and i8 stores. | 1559 // Handles i1 and i8 stores. |
| 1460 // | 1560 // |
| 1461 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 1561 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 1462 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1562 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 1463 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1563 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1495 // | 1595 // |
| 1496 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1596 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 1497 // iiiiiiiiiiii=imm12, u=1 if +. | 1597 // iiiiiiiiiiii=imm12, u=1 if +. |
| 1498 constexpr bool IsByte = false; | 1598 constexpr bool IsByte = false; |
| 1499 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); | 1599 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
| 1500 return; | 1600 return; |
| 1501 } | 1601 } |
| 1502 } | 1602 } |
| 1503 } | 1603 } |
| 1504 | 1604 |
| 1605 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt, | |
| 1606 const Operand *OpAddress, CondARM32::Cond Cond, | |
| 1607 const TargetInfo &TInfo) { | |
| 1608 // STREXB - ARM section A8.8.213, encoding A1: | |
| 1609 // strexb<c> <Rd>, <Rt>, [<Rn>] | |
| 1610 // | |
| 1611 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
| 1612 // nnnn=Rn. | |
| 1613 // | |
| 1614 // STREXH - ARM section A8.8.215, encoding A1: | |
| 1615 // strexh<c> <Rd>, <Rt>, [<Rn>] | |
| 1616 // | |
| 1617 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
| 1618 // nnnn=Rn. | |
| 1619 // | |
| 1620 // STREX - ARM section A8.8.212, encoding A1: | |
| 1621 // strex<c> <Rd>, <Rt>, [<Rn>] | |
| 1622 // | |
| 1623 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
| 1624 // nnnn=Rn. | |
| 1625 // | |
| 1626 // STREXD - ARM section A8.8.214, encoding A1: | |
| 1627 // strexd<c> <Rd>, <Rt>, [<Rn>] | |
| 1628 // | |
| 1629 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
| 1630 // nnnn=Rn. | |
| 1631 constexpr const char *StrexName = "strex"; | |
| 1632 // Note: Rt uses Rm shift in encoding. | |
| 1633 IValueT Rt = encodeRegister(OpRt, "Rt", StrexName); | |
| 1634 const Type Ty = OpRt->getType(); | |
| 1635 constexpr bool IsLoad = true; | |
| 1636 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName); | |
| 1637 } | |
| 1638 | |
| 1505 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1639 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
| 1506 const Operand *OpSrc1, bool SetFlags, | 1640 const Operand *OpSrc1, bool SetFlags, |
| 1507 CondARM32::Cond Cond) { | 1641 CondARM32::Cond Cond) { |
| 1508 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1642 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| 1509 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1643 // orr{s}<c> <Rd>, <Rn>, <Rm> |
| 1510 // | 1644 // |
| 1511 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1645 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 1512 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. | 1646 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
| 1513 // | 1647 // |
| 1514 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1648 // ORR (register) - ARM Section A8.8.123, encoding A1: |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1778 | 1912 |
| 1779 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1913 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
| 1780 CondARM32::Cond Cond) { | 1914 CondARM32::Cond Cond) { |
| 1781 constexpr const char *UxtName = "uxt"; | 1915 constexpr const char *UxtName = "uxt"; |
| 1782 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 1916 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
| 1783 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 1917 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
| 1784 } | 1918 } |
| 1785 | 1919 |
| 1786 } // end of namespace ARM32 | 1920 } // end of namespace ARM32 |
| 1787 } // end of namespace Ice | 1921 } // end of namespace Ice |
| OLD | NEW |