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 23 matching lines...) Expand all Loading... | |
34 | 34 |
35 // The following define individual bits. | 35 // The following define individual bits. |
36 static constexpr IValueT B0 = 1; | 36 static constexpr IValueT B0 = 1; |
37 static constexpr IValueT B1 = 1 << 1; | 37 static constexpr IValueT B1 = 1 << 1; |
38 static constexpr IValueT B2 = 1 << 2; | 38 static constexpr IValueT B2 = 1 << 2; |
39 static constexpr IValueT B3 = 1 << 3; | 39 static constexpr IValueT B3 = 1 << 3; |
40 static constexpr IValueT B4 = 1 << 4; | 40 static constexpr IValueT B4 = 1 << 4; |
41 static constexpr IValueT B5 = 1 << 5; | 41 static constexpr IValueT B5 = 1 << 5; |
42 static constexpr IValueT B6 = 1 << 6; | 42 static constexpr IValueT B6 = 1 << 6; |
43 static constexpr IValueT B7 = 1 << 7; | 43 static constexpr IValueT B7 = 1 << 7; |
44 static constexpr IValueT B8 = 1 << 8; | |
45 static constexpr IValueT B9 = 1 << 9; | |
46 static constexpr IValueT B10 = 1 << 10; | |
47 static constexpr IValueT B11 = 1 << 11; | |
44 static constexpr IValueT B12 = 1 << 12; | 48 static constexpr IValueT B12 = 1 << 12; |
45 static constexpr IValueT B13 = 1 << 13; | 49 static constexpr IValueT B13 = 1 << 13; |
46 static constexpr IValueT B14 = 1 << 14; | 50 static constexpr IValueT B14 = 1 << 14; |
47 static constexpr IValueT B15 = 1 << 15; | 51 static constexpr IValueT B15 = 1 << 15; |
48 static constexpr IValueT B16 = 1 << 16; | 52 static constexpr IValueT B16 = 1 << 16; |
49 static constexpr IValueT B17 = 1 << 17; | 53 static constexpr IValueT B17 = 1 << 17; |
50 static constexpr IValueT B18 = 1 << 18; | 54 static constexpr IValueT B18 = 1 << 18; |
51 static constexpr IValueT B19 = 1 << 19; | 55 static constexpr IValueT B19 = 1 << 19; |
52 static constexpr IValueT B20 = 1 << 20; | 56 static constexpr IValueT B20 = 1 << 20; |
53 static constexpr IValueT B21 = 1 << 21; | 57 static constexpr IValueT B21 = 1 << 21; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 // Shift instruction register fields encodings. | 93 // Shift instruction register fields encodings. |
90 static constexpr IValueT kShiftImmShift = 7; | 94 static constexpr IValueT kShiftImmShift = 7; |
91 static constexpr IValueT kShiftImmBits = 5; | 95 static constexpr IValueT kShiftImmBits = 5; |
92 static constexpr IValueT kShiftShift = 5; | 96 static constexpr IValueT kShiftShift = 5; |
93 static constexpr IValueT kImmed12Bits = 12; | 97 static constexpr IValueT kImmed12Bits = 12; |
94 static constexpr IValueT kImm12Shift = 0; | 98 static constexpr IValueT kImm12Shift = 0; |
95 | 99 |
96 // Rotation instructions (uxtb etc.). | 100 // Rotation instructions (uxtb etc.). |
97 static constexpr IValueT kRotationShift = 10; | 101 static constexpr IValueT kRotationShift = 10; |
98 | 102 |
103 // MemEx instructions. | |
104 static constexpr IValueT kMemExOpcodeShift = 20; | |
105 | |
99 // Div instruction register field encodings. | 106 // Div instruction register field encodings. |
100 static constexpr IValueT kDivRdShift = 16; | 107 static constexpr IValueT kDivRdShift = 16; |
101 static constexpr IValueT kDivRmShift = 8; | 108 static constexpr IValueT kDivRmShift = 8; |
102 static constexpr IValueT kDivRnShift = 0; | 109 static constexpr IValueT kDivRnShift = 0; |
103 | 110 |
104 // 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 |
105 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 | 112 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 |
106 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 | 113 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 |
107 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 | 114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 |
108 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... | |
166 } | 173 } |
167 | 174 |
168 // Extract out a Bit in Value. | 175 // Extract out a Bit in Value. |
169 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } | 176 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } |
170 | 177 |
171 // Returns the GPR register at given Shift in Value. | 178 // Returns the GPR register at given Shift in Value. |
172 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { | 179 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { |
173 return decodeGPRRegister((Value >> Shift) & 0xF); | 180 return decodeGPRRegister((Value >> Shift) & 0xF); |
174 } | 181 } |
175 | 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 getVarRegNum(const Variable *Var) { | |
Jim Stichnoth
2015/12/11 17:24:57
This function name should be changed, to reflect t
Karl
2015/12/11 18:05:08
Changed to getEncodedGPRegNum.
| |
197 int32_t Reg = Var->getRegNum(); | |
198 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) | |
199 : RegARM32::getEncodedGPR(Reg); | |
200 } | |
201 | |
176 // 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 |
177 // encodeOperand and encodeAddress below. | 203 // encodeOperand and encodeAddress below. |
178 enum EncodedOperand { | 204 enum EncodedOperand { |
179 // Unable to encode, value left undefined. | 205 // Unable to encode, value left undefined. |
180 CantEncode = 0, | 206 CantEncode = 0, |
181 // Value is register found. | 207 // Value is register found. |
182 EncodedAsRegister, | 208 EncodedAsRegister, |
183 // 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 |
184 // value. | 210 // value. |
185 EncodedAsRotatedImm8, | 211 EncodedAsRotatedImm8, |
212 // EncodedAsImmRegOffset is a memory operand that can take three forms, based | |
213 // on OpEncoding: | |
214 // | |
215 // case DefaultOpEncoding: | |
Jim Stichnoth
2015/12/11 17:24:57
This style of comment made me think you had some s
Karl
2015/12/11 18:05:08
Ok. Done.
| |
216 // | |
186 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 217 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, |
187 // 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 |
188 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. | 219 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
189 EncodedAsImmRegOffset, | 220 // |
221 // case OpEncoding3: | |
222 // | |
190 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 | 223 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 |
191 // 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 |
192 // Rn. | 225 // Rn. |
193 EncodedAsImmRegOffsetEnc3, | 226 // |
227 // case OpEncodingMemEx: | |
228 // | |
229 // Value=000000000000nnnn0000000000000000 where nnnn=Rn. | |
230 EncodedAsImmRegOffset, | |
194 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 231 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, |
195 // 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 |
196 // 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 |
197 // writeback to Rn. | 234 // writeback to Rn. |
198 EncodedAsShiftRotateImm5, | 235 EncodedAsShiftRotateImm5, |
199 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value | 236 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value |
200 // to shift. | 237 // to shift. |
201 EncodedAsShiftImm5, | 238 EncodedAsShiftImm5, |
202 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift | 239 // i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift |
203 // kind, and iiiii is the shift amount. | 240 // kind, and iiiii is the shift amount. |
(...skipping 23 matching lines...) Expand all Loading... | |
227 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 264 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
228 IValueT Rs) { | 265 IValueT Rs) { |
229 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 266 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
230 (Rm << kRmShift); | 267 (Rm << kRmShift); |
231 } | 268 } |
232 | 269 |
233 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { | 270 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value) { |
234 Value = 0; // Make sure initialized. | 271 Value = 0; // Make sure initialized. |
235 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 272 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
236 if (Var->hasReg()) { | 273 if (Var->hasReg()) { |
237 Value = Var->getRegNum(); | 274 Value = getVarRegNum(Var); |
238 return EncodedAsRegister; | 275 return EncodedAsRegister; |
239 } | 276 } |
240 return CantEncode; | 277 return CantEncode; |
241 } | 278 } |
242 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 279 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
243 const IValueT Immed8 = FlexImm->getImm(); | 280 const IValueT Immed8 = FlexImm->getImm(); |
244 const IValueT Rotate = FlexImm->getRotateAmt(); | 281 const IValueT Rotate = FlexImm->getRotateAmt(); |
245 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) | 282 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) |
246 return CantEncode; | 283 return CantEncode; |
247 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 284 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 IValueT Value = Mode | (Rn << kRnShift); | 326 IValueT Value = Mode | (Rn << kRnShift); |
290 if (Imm8 < 0) { | 327 if (Imm8 < 0) { |
291 Imm8 = -Imm8; | 328 Imm8 = -Imm8; |
292 Value = (Value ^ U); | 329 Value = (Value ^ U); |
293 } | 330 } |
294 assert(Imm8 < (1 << 8)); | 331 assert(Imm8 < (1 << 8)); |
295 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); | 332 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); |
296 return Value; | 333 return Value; |
297 } | 334 } |
298 | 335 |
299 // Defines alternate layouts of instruction operands, should the (common) | 336 IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, |
300 // default pattern not be used. | 337 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { |
301 enum OpEncoding { | 338 switch (AddressEncoding) { |
302 // No alternate layout specified. | 339 case DefaultOpEncoding: |
303 DefaultOpEncoding, | 340 return encodeImmRegOffset(Reg, Offset, Mode); |
304 // Alternate encoding 3. | 341 case OpEncoding3: |
305 OpEncoding3 | 342 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); |
306 }; | 343 case OpEncodingMemEx: |
344 assert(Offset == 0); | |
345 assert(Mode == OperandARM32Mem::Offset); | |
346 return Reg << kRnShift; | |
347 } | |
348 } | |
307 | 349 |
308 // Encodes memory address Opnd, and encodes that information into Value, based | 350 // Encodes memory address Opnd, and encodes that information into Value, based |
309 // on how ARM represents the address. Returns how the value was encoded. | 351 // on how ARM represents the address. Returns how the value was encoded. |
310 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, | 352 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, |
311 const AssemblerARM32::TargetInfo &TInfo, | 353 const AssemblerARM32::TargetInfo &TInfo, |
312 OpEncoding AddressEncoding = DefaultOpEncoding) { | 354 OpEncoding AddressEncoding = DefaultOpEncoding) { |
313 Value = 0; // Make sure initialized. | 355 Value = 0; // Make sure initialized. |
314 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 356 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
315 // Should be a stack variable, with an offset. | 357 // Should be a stack variable, with an offset. |
316 if (Var->hasReg()) | 358 if (Var->hasReg()) |
317 return CantEncode; | 359 return CantEncode; |
318 IOffsetT Offset = Var->getStackOffset(); | 360 IOffsetT Offset = Var->getStackOffset(); |
319 if (!Utils::IsAbsoluteUint(12, Offset)) | 361 if (!Utils::IsAbsoluteUint(12, Offset)) |
320 return CantEncode; | 362 return CantEncode; |
321 int32_t BaseRegNum = Var->getBaseRegNum(); | 363 int32_t BaseRegNum = Var->getBaseRegNum(); |
322 if (BaseRegNum == Variable::NoRegister) | 364 if (BaseRegNum == Variable::NoRegister) |
323 BaseRegNum = TInfo.FrameOrStackReg; | 365 BaseRegNum = TInfo.FrameOrStackReg; |
324 Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset); | 366 Value = encodeImmRegOffset(AddressEncoding, BaseRegNum, Offset, |
367 OperandARM32Mem::Offset); | |
325 return EncodedAsImmRegOffset; | 368 return EncodedAsImmRegOffset; |
326 } | 369 } |
327 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { | 370 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { |
328 Variable *Var = Mem->getBase(); | 371 Variable *Var = Mem->getBase(); |
329 if (!Var->hasReg()) | 372 if (!Var->hasReg()) |
330 return CantEncode; | 373 return CantEncode; |
331 IValueT Rn = Var->getRegNum(); | 374 IValueT Rn = getVarRegNum(Var); |
332 if (Mem->isRegReg()) { | 375 if (Mem->isRegReg()) { |
333 const Variable *Index = Mem->getIndex(); | 376 const Variable *Index = Mem->getIndex(); |
334 if (Var == nullptr) | 377 if (Var == nullptr) |
335 return CantEncode; | 378 return CantEncode; |
336 Value = (Rn << kRnShift) | Mem->getAddrMode() | | 379 Value = (Rn << kRnShift) | Mem->getAddrMode() | |
337 encodeShiftRotateImm5(Index->getRegNum(), Mem->getShiftOp(), | 380 encodeShiftRotateImm5(getVarRegNum(Index), Mem->getShiftOp(), |
338 Mem->getShiftAmt()); | 381 Mem->getShiftAmt()); |
339 return EncodedAsShiftRotateImm5; | 382 return EncodedAsShiftRotateImm5; |
340 } | 383 } |
341 // Encoded as immediate register offset. | 384 // Encoded as immediate register offset. |
342 ConstantInteger32 *Offset = Mem->getOffset(); | 385 ConstantInteger32 *Offset = Mem->getOffset(); |
343 switch (AddressEncoding) { | 386 Value = encodeImmRegOffset(AddressEncoding, Rn, Offset->getValue(), |
344 case DefaultOpEncoding: | 387 Mem->getAddrMode()); |
345 Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode()); | 388 return EncodedAsImmRegOffset; |
346 return EncodedAsImmRegOffset; | |
347 case OpEncoding3: | |
348 Value = | |
349 encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode()); | |
350 return EncodedAsImmRegOffsetEnc3; | |
351 } | |
352 } | 389 } |
353 return CantEncode; | 390 return CantEncode; |
354 } | 391 } |
355 | 392 |
356 // Checks that Offset can fit in imm24 constant of branch (b) instruction. | 393 // Checks that Offset can fit in imm24 constant of branch (b) instruction. |
357 bool canEncodeBranchOffset(IOffsetT Offset) { | 394 bool canEncodeBranchOffset(IOffsetT Offset) { |
358 return Utils::IsAligned(Offset, 4) && | 395 return Utils::IsAligned(Offset, 4) && |
359 Utils::IsInt(kBranchOffsetBits, Offset >> 2); | 396 Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
360 } | 397 } |
361 | 398 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
761 | 798 |
762 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, | 799 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, |
763 IValueT Rt, const Operand *OpAddress, | 800 IValueT Rt, const Operand *OpAddress, |
764 const TargetInfo &TInfo, | 801 const TargetInfo &TInfo, |
765 const char *InstName) { | 802 const char *InstName) { |
766 IValueT Address; | 803 IValueT Address; |
767 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { | 804 switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) { |
768 default: | 805 default: |
769 llvm::report_fatal_error(std::string(InstName) + | 806 llvm::report_fatal_error(std::string(InstName) + |
770 ": Memory address not understood"); | 807 ": Memory address not understood"); |
771 case EncodedAsImmRegOffsetEnc3: { | 808 case EncodedAsImmRegOffset: { |
772 // XXXH (immediate) | 809 // XXXH (immediate) |
773 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] | 810 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] |
774 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] | 811 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] |
775 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! | 812 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! |
776 // | 813 // |
777 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, | 814 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, |
778 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, | 815 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, |
779 // and pu0w0nnnn0000iiii0000jjjj=Address. | 816 // and pu0w0nnnn0000iiii0000jjjj=Address. |
780 verifyRegDefined(Rt, "Rt", InstName); | 817 verifyRegDefined(Rt, "Rt", InstName); |
781 verifyCondDefined(Cond, InstName); | 818 verifyCondDefined(Cond, InstName); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1132 constexpr bool IsLoad = true; | 1169 constexpr bool IsLoad = true; |
1133 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); | 1170 IValueT Rt = encodeRegister(OpRt, "Rt", LdrName); |
1134 const Type Ty = OpRt->getType(); | 1171 const Type Ty = OpRt->getType(); |
1135 switch (typeWidthInBytesLog2(Ty)) { | 1172 switch (typeWidthInBytesLog2(Ty)) { |
1136 case 3: | 1173 case 3: |
1137 // LDRD is not implemented because target lowering handles i64 and double by | 1174 // LDRD is not implemented because target lowering handles i64 and double by |
1138 // using two (32-bit) load instructions. Note: Intenionally drop to default | 1175 // using two (32-bit) load instructions. Note: Intenionally drop to default |
1139 // case. | 1176 // case. |
1140 default: | 1177 default: |
1141 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + | 1178 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + |
1142 " not implementable\n"); | 1179 " not implementable"); |
1143 case 0: { | 1180 case 0: { |
1144 // Handles i1 and i8 loads. | 1181 // Handles i1 and i8 loads. |
1145 // | 1182 // |
1146 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 1183 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
1147 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 1184 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
1148 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 1185 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
1149 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 1186 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
1150 // | 1187 // |
1151 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1188 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1152 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and | 1189 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1195 // | 1232 // |
1196 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b | 1233 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b |
1197 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. | 1234 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. |
1198 constexpr bool IsByte = false; | 1235 constexpr bool IsByte = false; |
1199 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); | 1236 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); |
1200 return; | 1237 return; |
1201 } | 1238 } |
1202 } | 1239 } |
1203 } | 1240 } |
1204 | 1241 |
1242 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad, | |
1243 const Operand *OpRd, IValueT Rt, | |
1244 const Operand *OpAddress, | |
1245 const TargetInfo &TInfo, | |
1246 const char *InstName) { | |
1247 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | |
1248 IValueT MemExOpcode = IsLoad ? B0 : 0; | |
1249 switch (typeWidthInBytesLog2(Ty)) { | |
John
2015/12/11 16:59:09
Why did you switch on the type width? can you swit
Karl
2015/12/11 18:05:08
I did it this way for the following reasons:
1) I
John
2015/12/11 18:10:46
IceType_i[8|16|32|64] are declared sequentially in
Karl
2015/12/11 21:00:12
OK, I'll change it, but you are slightly incorrect
| |
1250 default: | |
1251 llvm::report_fatal_error(std::string(InstName) + ": Type " + | |
1252 typeString(Ty) + " not implementable"); | |
1253 case 0: | |
1254 MemExOpcode |= B2; | |
1255 break; | |
1256 case 1: | |
1257 MemExOpcode |= B2 | B1; | |
1258 break; | |
1259 case 2: | |
1260 break; | |
1261 case 3: | |
1262 MemExOpcode |= B1; | |
1263 } | |
1264 // emitMemExOp(Cond, MemExOpcode, Rd, Rt, OpAddress, TInfo, InstName); | |
Jim Stichnoth
2015/12/11 17:24:57
Remove this comment?
Karl
2015/12/11 18:05:08
Really? I like useless comments. Removing...
| |
1265 IValueT AddressRn; | |
1266 if (encodeAddress(OpAddress, AddressRn, TInfo, OpEncodingMemEx) != | |
1267 EncodedAsImmRegOffset) | |
1268 llvm::report_fatal_error(std::string(InstName) + | |
1269 ": Can't extract Rn from address"); | |
1270 assert(Utils::IsAbsoluteUint(3, MemExOpcode)); | |
1271 verifyRegDefined(Rd, "Rd", InstName); | |
1272 verifyRegDefined(Rt, "Rt", InstName); | |
1273 verifyCondDefined(Cond, InstName); | |
1274 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
1275 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 | | |
1276 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) | | |
1277 AddressRn | (Rd << kRdShift) | (Rt << kRmShift); | |
1278 emitInst(Encoding); | |
1279 return; | |
1280 } | |
1281 | |
1282 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress, | |
1283 CondARM32::Cond Cond, const TargetInfo &TInfo) { | |
1284 // LDREXB - ARM section A8.8.76, encoding A1: | |
1285 // ldrexb<c> <Rt>, [<Rn>] | |
1286 // | |
1287 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
1288 // | |
1289 // LDREXH - ARM section A8.8.78, encoding A1: | |
1290 // ldrexh<c> <Rt>, [<Rn>] | |
1291 // | |
1292 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
1293 // | |
1294 // LDREX - ARM section A8.8.75, encoding A1: | |
1295 // ldrex<c> <Rt>, [<Rn>] | |
1296 // | |
1297 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
1298 // | |
1299 // LDREXD - ARM section A8. | |
1300 // ldrexd<c> <Rt>, [<Rn>] | |
1301 // | |
1302 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. | |
1303 constexpr const char *LdrexName = "ldrex"; | |
1304 const Type Ty = OpRt->getType(); | |
1305 constexpr bool IsLoad = true; | |
1306 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc; | |
1307 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName); | |
1308 } | |
1309 | |
1205 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, | 1310 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, |
1206 const OperandARM32::ShiftKind Shift, | 1311 const OperandARM32::ShiftKind Shift, |
1207 const Operand *OpRd, const Operand *OpRm, | 1312 const Operand *OpRd, const Operand *OpRm, |
1208 const Operand *OpSrc1, const bool SetFlags, | 1313 const Operand *OpSrc1, const bool SetFlags, |
1209 const char *InstName) { | 1314 const char *InstName) { |
1210 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 | 1315 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 |
1211 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); | 1316 IValueT Rd = encodeRegister(OpRd, "Rd", InstName); |
1212 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); | 1317 IValueT Rm = encodeRegister(OpRm, "Rm", InstName); |
1213 IValueT Value; | 1318 IValueT Value; |
1214 switch (encodeOperand(OpSrc1, Value)) { | 1319 switch (encodeOperand(OpSrc1, Value)) { |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1464 // | 1569 // |
1465 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 1570 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
1466 // iiiiiiiiiiii=imm12, u=1 if +. | 1571 // iiiiiiiiiiii=imm12, u=1 if +. |
1467 constexpr bool IsByte = false; | 1572 constexpr bool IsByte = false; |
1468 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); | 1573 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); |
1469 return; | 1574 return; |
1470 } | 1575 } |
1471 } | 1576 } |
1472 } | 1577 } |
1473 | 1578 |
1579 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt, | |
1580 const Operand *OpAddress, CondARM32::Cond Cond, | |
1581 const TargetInfo &TInfo) { | |
1582 // STREXB - ARM section A8.8.213, encoding A1: | |
1583 // strexb<c> <Rd>, <Rt>, [<Rn>] | |
1584 // | |
1585 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
1586 // nnnn=Rn. | |
1587 // | |
1588 // STREXH - ARM section A8.8.215, encoding A1: | |
1589 // strexh<c> <Rd>, <Rt>, [<Rn>] | |
1590 // | |
1591 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
1592 // nnnn=Rn. | |
1593 // | |
1594 // STREX - ARM section A8.8.212, encoding A1: | |
1595 // strex<c> <Rd>, <Rt>, [<Rn>] | |
1596 // | |
1597 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
1598 // nnnn=Rn. | |
1599 // | |
1600 // STREXD - ARM section A8.8.214, encoding A1: | |
1601 // strexd<c> <Rd>, <Rt>, [<Rn>] | |
1602 // | |
1603 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and | |
1604 // nnnn=Rn. | |
1605 constexpr const char *StrexName = "strex"; | |
1606 // Note: Rt uses Rm shift in encoding. | |
1607 IValueT Rt = encodeRegister(OpRt, "Rt", StrexName); | |
1608 const Type Ty = OpRt->getType(); | |
1609 constexpr bool IsLoad = true; | |
1610 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName); | |
1611 return; | |
Jim Stichnoth
2015/12/11 17:24:57
Remove this explicit return.
Karl
2015/12/11 18:05:08
Done.
| |
1612 } | |
1613 | |
1474 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, | 1614 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
1475 const Operand *OpSrc1, bool SetFlags, | 1615 const Operand *OpSrc1, bool SetFlags, |
1476 CondARM32::Cond Cond) { | 1616 CondARM32::Cond Cond) { |
1477 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1617 // ORR (register) - ARM Section A8.8.123, encoding A1: |
1478 // orr{s}<c> <Rd>, <Rn>, <Rm> | 1618 // orr{s}<c> <Rd>, <Rn>, <Rm> |
1479 // | 1619 // |
1480 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1620 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
1481 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. | 1621 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
1482 // | 1622 // |
1483 // ORR (register) - ARM Section A8.8.123, encoding A1: | 1623 // ORR (register) - ARM Section A8.8.123, encoding A1: |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1704 | 1844 |
1705 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, | 1845 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, |
1706 CondARM32::Cond Cond) { | 1846 CondARM32::Cond Cond) { |
1707 constexpr const char *UxtName = "uxt"; | 1847 constexpr const char *UxtName = "uxt"; |
1708 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; | 1848 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; |
1709 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); | 1849 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); |
1710 } | 1850 } |
1711 | 1851 |
1712 } // end of namespace ARM32 | 1852 } // end of namespace ARM32 |
1713 } // end of namespace Ice | 1853 } // end of namespace Ice |
OLD | NEW |