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 |