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 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 // The way an operand was decoded in functions decodeOperand and decodeAddress | 180 // The way an operand was decoded in functions decodeOperand and decodeAddress |
181 // below. | 181 // below. |
182 enum DecodedResult { | 182 enum DecodedResult { |
183 // Unable to decode, value left undefined. | 183 // Unable to decode, value left undefined. |
184 CantDecode = 0, | 184 CantDecode = 0, |
185 // Value is register found. | 185 // Value is register found. |
186 DecodedAsRegister, | 186 DecodedAsRegister, |
187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 | 187 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
188 // value. | 188 // value. |
189 DecodedAsRotatedImm8, | 189 DecodedAsRotatedImm8, |
190 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | 190 // 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 | 191 // 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. | 192 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. |
193 DecodedAsImmRegOffset, | 193 DecodedAsImmRegOffset, |
194 // i.e. 0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, | 194 // 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 | 195 // 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 | 196 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if |
197 // writeback to Rn. | 197 // writeback to Rn. |
198 DecodedAsShiftRotateImm5, | 198 DecodedAsShiftRotateImm5, |
199 // i.e. 000000000000000000000iiiii0000000 iiii defines Imm5 value to shift. | 199 // Value=000000000000000000000iiiii0000000 iiii defines the Imm5 value to |
| 200 // shift. |
200 DecodedAsShiftImm5, | 201 DecodedAsShiftImm5, |
201 // Value is 32bit integer constant. | 202 // Value is 32bit integer constant. |
202 DecodedAsConstI32 | 203 DecodedAsConstI32 |
203 }; | 204 }; |
204 | 205 |
205 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. | 206 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. |
206 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { | 207 inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { |
207 assert(RotateAmt < (1 << kRotateBits)); | 208 assert(RotateAmt < (1 << kRotateBits)); |
208 assert(Immed8 < (1 << kImmed8Bits)); | 209 assert(Immed8 < (1 << kImmed8Bits)); |
209 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); | 210 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); |
210 } | 211 } |
211 | 212 |
212 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, | 213 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, |
213 // tt=Shift, and mmmm=Rm. | 214 // tt=Shift, and mmmm=Rm. |
214 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift, | 215 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift, |
215 IOffsetT imm5) { | 216 IOffsetT imm5) { |
216 (void)kShiftImmBits; | 217 (void)kShiftImmBits; |
217 assert(imm5 < (1 << kShiftImmBits)); | 218 assert(imm5 < (1 << kShiftImmBits)); |
218 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; | 219 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; |
219 } | 220 } |
220 | 221 |
221 // Encodes mmmmtt01ssss for data-processing (2nd) operands where mmmm=Rm, | 222 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and |
222 // ssss=Rs, and tt=Shift. | 223 // tt=Shift. |
223 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 224 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
224 IValueT Rs) { | 225 IValueT Rs) { |
225 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 226 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
226 (Rm << kRmShift); | 227 (Rm << kRmShift); |
227 } | 228 } |
228 | 229 |
229 DecodedResult decodeOperand(const Operand *Opnd, IValueT &Value) { | 230 DecodedResult decodeOperand(const Operand *Opnd, IValueT &Value) { |
230 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 231 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
231 if (Var->hasReg()) { | 232 if (Var->hasReg()) { |
232 Value = Var->getRegNum(); | 233 Value = Var->getRegNum(); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 return setNeedsTextFixup(); | 475 return setNeedsTextFixup(); |
475 IValueT Rn; | 476 IValueT Rn; |
476 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 477 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
477 return setNeedsTextFixup(); | 478 return setNeedsTextFixup(); |
478 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks); | 479 emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks); |
479 } | 480 } |
480 | 481 |
481 void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn, | 482 void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn, |
482 const Operand *OpSrc1, bool SetFlags, | 483 const Operand *OpSrc1, bool SetFlags, |
483 CondARM32::Cond Cond, EmitChecks RuleChecks) { | 484 CondARM32::Cond Cond, EmitChecks RuleChecks) { |
484 switch (RuleChecks) { | |
485 case NoChecks: | |
486 break; | |
487 case RdIsPcAndSetFlags: | |
488 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | |
489 // Conditions of rule violated. | |
490 return setNeedsTextFixup(); | |
491 break; | |
492 } | |
493 | 485 |
494 IValueT Src1Value; | 486 IValueT Src1Value; |
495 // TODO(kschimpf) Other possible decodings of data operations. | 487 // TODO(kschimpf) Other possible decodings of data operations. |
496 switch (decodeOperand(OpSrc1, Src1Value)) { | 488 switch (decodeOperand(OpSrc1, Src1Value)) { |
497 default: | 489 default: |
498 return setNeedsTextFixup(); | 490 return setNeedsTextFixup(); |
499 case DecodedAsRegister: { | 491 case DecodedAsRegister: { |
500 // XXX (register) | 492 // XXX (register) |
501 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 493 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
502 // | 494 // |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 if (!needsTextFixup()) | 549 if (!needsTextFixup()) |
558 L->linkTo(Position); | 550 L->linkTo(Position); |
559 } | 551 } |
560 | 552 |
561 void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn, | 553 void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn, |
562 const Operand *OpSrc1, | 554 const Operand *OpSrc1, |
563 CondARM32::Cond Cond) { | 555 CondARM32::Cond Cond) { |
564 // XXX (register) | 556 // XXX (register) |
565 // XXX<c> <Rn>, <Rm>{, <shift>} | 557 // XXX<c> <Rn>, <Rm>{, <shift>} |
566 // | 558 // |
567 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, | 559 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii |
568 // iiiii=Shift, tt=ShiftKind, yyy=kInstTypeDataRegister, and xxxx=Opcode. | 560 // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and |
| 561 // xxxx=Opcode. |
569 // | 562 // |
570 // XXX (immediate) | 563 // XXX (immediate) |
571 // XXX<c> <Rn>, #<RotatedImm8> | 564 // XXX<c> <Rn>, #<RotatedImm8> |
572 // | 565 // |
573 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 566 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
574 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value | 567 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value |
575 // defining RotatedImm8. | 568 // defining RotatedImm8. |
576 constexpr bool SetFlags = true; | 569 constexpr bool SetFlags = true; |
577 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; | 570 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; |
578 IValueT Rn; | 571 IValueT Rn; |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 // install the correct bits. | 1033 // install the correct bits. |
1041 constexpr bool IsMovW = false; | 1034 constexpr bool IsMovW = false; |
1042 emitFixup(createMoveFixup(IsMovW, Src)); | 1035 emitFixup(createMoveFixup(IsMovW, Src)); |
1043 constexpr IValueT Imm16 = 0; | 1036 constexpr IValueT Imm16 = 0; |
1044 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | | 1037 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | |
1045 B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift | | 1038 B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift | |
1046 (Imm16 & 0xfff); | 1039 (Imm16 & 0xfff); |
1047 emitInst(Encoding); | 1040 emitInst(Encoding); |
1048 } | 1041 } |
1049 | 1042 |
| 1043 void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc, |
| 1044 CondARM32::Cond Cond) { |
| 1045 // MVN (immediate) - ARM section A8.8.115, encoding A1: |
| 1046 // mvn{s}<c> <Rd>, #<const> |
| 1047 // |
| 1048 // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd, |
| 1049 // and iiiiiiiiiiii=const |
| 1050 // |
| 1051 // MVN (register) - ARM section A8.8.116, encoding A1: |
| 1052 // mvn{s}<c> <Rd>, <Rm>{, <shift> |
| 1053 // |
| 1054 // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd, |
| 1055 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. |
| 1056 IValueT Rd; |
| 1057 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
| 1058 return setNeedsTextFixup(); |
| 1059 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 |
| 1060 constexpr IValueT Rn = 0; |
| 1061 constexpr bool SetFlags = false; |
| 1062 emitType01(MvnOpcode, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags); |
| 1063 } |
| 1064 |
1050 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, | 1065 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, |
1051 const Operand *OpSrc1, bool SetFlags, | 1066 const Operand *OpSrc1, bool SetFlags, |
1052 CondARM32::Cond Cond) { | 1067 CondARM32::Cond Cond) { |
1053 // SBC (register) - ARM section 18.8.162, encoding A1: | 1068 // SBC (register) - ARM section 18.8.162, encoding A1: |
1054 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 1069 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
1055 // | 1070 // |
1056 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 1071 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
1057 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. | 1072 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
1058 // | 1073 // |
1059 // SBC (Immediate) - ARM section A8.8.161, encoding A1: | 1074 // SBC (Immediate) - ARM section A8.8.161, encoding A1: |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 // rr defined (RotationValue) rotate. | 1386 // rr defined (RotationValue) rotate. |
1372 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; | 1387 constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20; |
1373 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); | 1388 emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation); |
1374 return; | 1389 return; |
1375 } | 1390 } |
1376 } | 1391 } |
1377 } | 1392 } |
1378 | 1393 |
1379 } // end of namespace ARM32 | 1394 } // end of namespace ARM32 |
1380 } // end of namespace Ice | 1395 } // end of namespace Ice |
OLD | NEW |