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 21 matching lines...) Expand all Loading... | |
32 static constexpr uint32_t B2 = 1 << 2; | 32 static constexpr uint32_t B2 = 1 << 2; |
33 static constexpr uint32_t B3 = 1 << 3; | 33 static constexpr uint32_t B3 = 1 << 3; |
34 static constexpr uint32_t B4 = 1 << 4; | 34 static constexpr uint32_t B4 = 1 << 4; |
35 static constexpr uint32_t B5 = 1 << 5; | 35 static constexpr uint32_t B5 = 1 << 5; |
36 static constexpr uint32_t B6 = 1 << 6; | 36 static constexpr uint32_t B6 = 1 << 6; |
37 static constexpr uint32_t B21 = 1 << 21; | 37 static constexpr uint32_t B21 = 1 << 21; |
38 static constexpr uint32_t B24 = 1 << 24; | 38 static constexpr uint32_t B24 = 1 << 24; |
39 | 39 |
40 // Constants used for the decoding or encoding of the individual fields of | 40 // Constants used for the decoding or encoding of the individual fields of |
41 // instructions. Based on ARM section A5.1. | 41 // instructions. Based on ARM section A5.1. |
42 static constexpr uint32_t L = 1 << 20; // load (or store) | |
43 static constexpr uint32_t W = 1 << 21; // writeback base register (or leave | |
44 // unchanged) | |
45 static constexpr uint32_t B = 1 << 22; // unsigned byte (or word) | |
46 static constexpr uint32_t U = 1 << 23; // positive (or negative) offset/index | |
47 static constexpr uint32_t P = 1 << 24; // offset/pre-indexed addressing (or | |
48 // post-indexed addressing) | |
49 | |
42 static constexpr uint32_t kConditionShift = 28; | 50 static constexpr uint32_t kConditionShift = 28; |
43 static constexpr uint32_t kOpcodeShift = 21; | 51 static constexpr uint32_t kOpcodeShift = 21; |
44 static constexpr uint32_t kRdShift = 12; | 52 static constexpr uint32_t kRdShift = 12; |
45 static constexpr uint32_t kRmShift = 0; | 53 static constexpr uint32_t kRmShift = 0; |
46 static constexpr uint32_t kRnShift = 16; | 54 static constexpr uint32_t kRnShift = 16; |
47 static constexpr uint32_t kSShift = 20; | 55 static constexpr uint32_t kSShift = 20; |
48 static constexpr uint32_t kTypeShift = 25; | 56 static constexpr uint32_t kTypeShift = 25; |
49 | 57 |
50 // Immediate instruction fields encoding. | 58 // Immediate instruction fields encoding. |
51 static constexpr uint32_t kImmed8Bits = 8; | 59 static constexpr uint32_t kImmed8Bits = 8; |
52 static constexpr uint32_t kImmed8Shift = 0; | 60 static constexpr uint32_t kImmed8Shift = 0; |
53 static constexpr uint32_t kRotateBits = 4; | 61 static constexpr uint32_t kRotateBits = 4; |
54 static constexpr uint32_t kRotateShift = 8; | 62 static constexpr uint32_t kRotateShift = 8; |
55 | 63 |
64 static constexpr uint32_t kImmed12Bits = 12; | |
65 static constexpr uint32_t kImm12Shift = 0; | |
66 | |
67 template <typename T> static inline bool isUint(int N, T Value) { | |
Jim Stichnoth
2015/10/15 20:41:29
Can you just use the (inappropriately named) IsUin
Karl
2015/10/15 22:03:33
Done.
| |
68 assert((0 < N) && (static_cast<unsigned>(N) < (CHAR_BIT * sizeof(Value)))); | |
69 T Limit = static_cast<T>(1) << N; | |
70 return (0 <= Value) && (Value < Limit); | |
71 } | |
72 | |
73 template <typename T> inline bool isAbsoluteUint(int N, T Value) { | |
74 assert(N < 30 && static_cast<unsigned>(N) < (CHAR_BIT * sizeof(T))); | |
75 if (Value < 0) | |
76 Value = -Value; | |
77 return isUint(N, Value); | |
78 } | |
79 | |
56 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } | 80 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
57 | 81 |
58 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { | 82 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
59 return static_cast<uint32_t>(Rn); | 83 return static_cast<uint32_t>(Rn); |
60 } | 84 } |
61 | 85 |
62 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | 86 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |
63 return R != RegARM32::Encoded_Not_GPR; | 87 return R != RegARM32::Encoded_Not_GPR; |
64 } | 88 } |
65 | 89 |
66 inline bool isGPRRegisterDefined(uint32_t R) { | 90 inline bool isGPRRegisterDefined(uint32_t R) { |
67 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); | 91 return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR); |
68 } | 92 } |
69 | 93 |
70 inline bool isConditionDefined(CondARM32::Cond Cond) { | 94 inline bool isConditionDefined(CondARM32::Cond Cond) { |
71 return Cond != CondARM32::kNone; | 95 return Cond != CondARM32::kNone; |
72 } | 96 } |
73 | 97 |
74 inline uint32_t encodeCondition(CondARM32::Cond Cond) { | 98 inline uint32_t encodeCondition(CondARM32::Cond Cond) { |
75 return static_cast<uint32_t>(Cond); | 99 return static_cast<uint32_t>(Cond); |
76 } | 100 } |
77 | 101 |
78 // The way an operand was decoded in function decode below. | 102 // Returns the bits int the corresponding masked value |
Jim Stichnoth
2015/10/15 20:41:29
"int" ? Also, end sentence with period.
Karl
2015/10/15 22:03:33
Done.
| |
103 inline uint32_t mask(uint32_t Value, uint32_t Shift, uint32_t Bits) { | |
104 return (Value >> Shift) & ((1 << Bits) - 1); | |
105 } | |
106 | |
107 // Extract out a Bit in Value. | |
108 inline bool isBitSet(uint32_t Bit, uint32_t Value) { | |
109 return (Value & Bit) == Bit; | |
110 } | |
111 | |
112 // Returns the GPR register at given Shift in Value. | |
113 inline RegARM32::GPRRegister getGPRReg(uint32_t Shift, uint32_t Value) { | |
114 return static_cast<RegARM32::GPRRegister>((Value >> Shift) & 0xF); | |
115 } | |
116 | |
117 // The way an operand was decoded in functions decodeOperand and decodeAddress | |
118 // below. | |
79 enum DecodedResult { | 119 enum DecodedResult { |
80 CantDecode = 0, // I.e. will fail in test. | 120 // Unable to decode, value left undefined. |
121 CantDecode = 0, | |
122 // Value is register found. | |
81 DecodedAsRegister, | 123 DecodedAsRegister, |
82 DecodedAsRotatedImm8 | 124 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 |
125 // value. | |
126 DecodedAsRotatedImm8, | |
127 // i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, | |
128 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to | |
129 // Rn should be used, and iiiiiiiiiiii is the offset. | |
130 DecodedAsImmRegOffset | |
83 }; | 131 }; |
84 | 132 |
85 DecodedResult decode(const Operand *Opnd, uint32_t &Value) { | 133 DecodedResult decodeOperand(const Operand *Opnd, uint32_t &Value) { |
86 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 134 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
87 if (Var->hasReg()) { | 135 if (Var->hasReg()) { |
88 Value = Var->getRegNum(); | 136 Value = Var->getRegNum(); |
89 return DecodedAsRegister; | 137 return DecodedAsRegister; |
90 } | 138 } |
91 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 139 } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
92 uint32_t Immed8 = FlexImm->getImm(); | 140 uint32_t Immed8 = FlexImm->getImm(); |
93 uint32_t Rotate = FlexImm->getRotateAmt(); | 141 uint32_t Rotate = FlexImm->getRotateAmt(); |
94 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); | 142 assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits))); |
95 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); | 143 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); |
96 return DecodedAsRotatedImm8; | 144 return DecodedAsRotatedImm8; |
97 } | 145 } |
98 return CantDecode; | 146 return CantDecode; |
99 } | 147 } |
100 | 148 |
149 uint32_t decodeImmRegOffset(RegARM32::GPRRegister Reg, int32_t Offset, | |
150 OperandARM32Mem::AddrMode Mode) { | |
151 uint32_t Value = Mode | (encodeGPRRegister(Reg) << kRnShift); | |
152 if (Offset < 0) { | |
153 Value = (Value ^ U) | -Offset; // Flip U to adjust sign. | |
154 } else { | |
155 Value |= Offset; | |
156 } | |
157 return Value; | |
158 } | |
159 | |
160 // Decodes memory address Opnd, and encodes that information into Value, | |
161 // based on how ARM represents the address. Returns how the value was encoded. | |
162 DecodedResult decodeAddress(const Operand *Opnd, uint32_t &Value) { | |
163 // Note: Loop is used so that we can short ciruit using break; | |
Jim Stichnoth
2015/10/15 20:41:29
Would it make sense here to just "return CantDecod
Karl
2015/10/15 22:03:33
Good idea. Removing loop as well.
| |
164 do { | |
165 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | |
166 // Should be a stack variable, with an offset. | |
167 if (Var->hasReg()) | |
168 break; | |
169 int32_t Offset = Var->getStackOffset(); | |
170 if (!isAbsoluteUint(12, Offset)) | |
171 break; | |
172 Value = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, Offset, | |
173 OperandARM32Mem::Offset); | |
174 return DecodedAsImmRegOffset; | |
175 } | |
176 } while (0); | |
177 return CantDecode; | |
178 } | |
179 | |
101 } // end of anonymous namespace | 180 } // end of anonymous namespace |
102 | 181 |
103 namespace Ice { | 182 namespace Ice { |
104 | 183 |
105 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, | 184 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, |
106 LabelVector &Labels) { | 185 LabelVector &Labels) { |
107 Label *L = nullptr; | 186 Label *L = nullptr; |
108 if (Number == Labels.size()) { | 187 if (Number == Labels.size()) { |
109 L = new (this->allocate<Label>()) Label(); | 188 L = new (this->allocate<Label>()) Label(); |
110 Labels.push_back(L); | 189 Labels.push_back(L); |
(...skipping 22 matching lines...) Expand all Loading... | |
133 // TODO(kschimpf) Decide if we have near jumps. | 212 // TODO(kschimpf) Decide if we have near jumps. |
134 label->bindTo(bound); | 213 label->bindTo(bound); |
135 } | 214 } |
136 | 215 |
137 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, | 216 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
138 uint32_t Opcode, bool SetCc, uint32_t Rn, | 217 uint32_t Opcode, bool SetCc, uint32_t Rn, |
139 uint32_t Rd, uint32_t Imm12) { | 218 uint32_t Rd, uint32_t Imm12) { |
140 assert(isGPRRegisterDefined(Rd)); | 219 assert(isGPRRegisterDefined(Rd)); |
141 assert(Cond != CondARM32::kNone); | 220 assert(Cond != CondARM32::kNone); |
142 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 221 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
143 uint32_t Encoding = encodeCondition(Cond) << kConditionShift | | 222 uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |
144 (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 223 (Type << kTypeShift) | (Opcode << kOpcodeShift) | |
145 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | | 224 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |
146 (Rd << kRdShift) | Imm12; | 225 (Rd << kRdShift) | Imm12; |
147 emitInst(Encoding); | 226 emitInst(Encoding); |
148 } | 227 } |
149 | 228 |
229 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, | |
230 bool IsLoad, bool IsByte, uint32_t Rt, | |
231 uint32_t Address) { | |
232 assert(isGPRRegisterDefined(Rt)); | |
233 assert(Cond != CondARM32::kNone); | |
234 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | |
235 uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | |
236 (InstType << kTypeShift) | (IsLoad ? L : 0) | | |
237 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | |
238 emitInst(Encoding); | |
239 } | |
240 | |
150 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, | 241 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, |
151 const Operand *OpSrc1, bool SetFlags, | 242 const Operand *OpSrc1, bool SetFlags, |
152 CondARM32::Cond Cond) { | 243 CondARM32::Cond Cond) { |
153 // Note: Loop is used so that we can short circuit using break; | 244 // Note: Loop is used so that we can short circuit using break; |
154 do { | 245 do { |
155 uint32_t Rd; | 246 uint32_t Rd; |
156 if (decode(OpRd, Rd) != DecodedAsRegister) | 247 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
157 break; | 248 break; |
158 uint32_t Rn; | 249 uint32_t Rn; |
159 if (decode(OpRn, Rn) != DecodedAsRegister) | 250 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
160 break; | 251 break; |
161 uint32_t Src1Value; | 252 uint32_t Src1Value; |
162 // TODO(kschimpf) Other possible decodings of add. | 253 // TODO(kschimpf) Other possible decodings of add. |
163 if (decode(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | 254 if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { |
164 // ADD (Immediate): See ARM section A8.8.5, rule A1. | 255 // ADD (Immediate): See ARM section A8.8.5, rule A1. |
165 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 256 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
166 // s=SetFlags and iiiiiiiiiiii=Src1Value | 257 // s=SetFlags and iiiiiiiiiiii=Src1Value |
167 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | 258 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || |
168 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | 259 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) |
169 // Conditions of rule violated. | 260 // Conditions of rule violated. |
170 break; | 261 break; |
171 uint32_t Add = B2; // 0100 | 262 uint32_t Add = B2; // 0100 |
172 uint32_t InstType = 1; | 263 uint32_t InstType = 1; |
173 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | 264 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); |
(...skipping 14 matching lines...) Expand all Loading... | |
188 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 279 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
189 // (ARM section A8.8.27, encoding A1). | 280 // (ARM section A8.8.27, encoding A1). |
190 assert(isGPRRegisterDefined(Rm)); | 281 assert(isGPRRegisterDefined(Rm)); |
191 assert(isConditionDefined(Cond)); | 282 assert(isConditionDefined(Cond)); |
192 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 283 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
193 uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | | 284 uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | |
194 (0xfff << 8) | B4 | (encodeGPRRegister(Rm) << kRmShift); | 285 (0xfff << 8) | B4 | (encodeGPRRegister(Rm) << kRmShift); |
195 emitInst(Encoding); | 286 emitInst(Encoding); |
196 } | 287 } |
197 | 288 |
289 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | |
290 CondARM32::Cond Cond) { | |
291 // Note: Loop is used so that we can short ciruit using break; | |
292 do { | |
293 uint32_t Rt; | |
294 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | |
295 break; | |
296 uint32_t Address; | |
297 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | |
298 break; | |
299 // cccc010pu0w1nnnnttttiiiiiiiiiiii (ARM section A8.8.63, encoding A1; and | |
300 // section A8.6.68, encoding A1). | |
301 uint32_t InstType = B1; // 010 | |
302 bool IsLoad = true; | |
303 Type Ty = OpRt->getType(); | |
304 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | |
305 break; | |
306 bool IsByte = Ty == IceType_i8; | |
307 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | |
308 (!IsByte && !isBitSet(P, Address) && isBitSet(W, Address)) || | |
309 ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | |
310 !isBitSet(P, Address) && | |
311 isBitSet(U, Address) & !isBitSet(W, Address) && | |
312 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | |
313 break; | |
314 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | |
315 return; | |
316 } while (0); | |
317 UnimplementedError(Ctx->getFlags()); | |
318 } | |
319 | |
198 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 320 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
199 CondARM32::Cond Cond) { | 321 CondARM32::Cond Cond) { |
200 // Note: Loop is used so that we can short ciruit using break; | 322 // Note: Loop is used so that we can short ciruit using break; |
201 do { | 323 do { |
202 uint32_t Rd; | 324 uint32_t Rd; |
203 if (decode(OpRd, Rd) != DecodedAsRegister) | 325 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
204 break; | 326 break; |
205 uint32_t Src; | 327 uint32_t Src; |
206 // TODO(kschimpf) Handle other forms of mov. | 328 // TODO(kschimpf) Handle other forms of mov. |
207 if (decode(OpSrc, Src) == DecodedAsRotatedImm8) { | 329 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { |
208 // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) | 330 // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1) |
209 // Note: We don't use movs in this assembler. | 331 // Note: We don't use movs in this assembler. |
210 constexpr bool SetFlags = false; | 332 constexpr bool SetFlags = false; |
211 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags)) | 333 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags)) |
212 // Conditions of rule violated. | 334 // Conditions of rule violated. |
213 break; | 335 break; |
214 uint32_t Rn = 0; | 336 uint32_t Rn = 0; |
215 uint32_t Mov = B3 | B2 | B0; // 1101. | 337 uint32_t Mov = B3 | B2 | B0; // 1101. |
216 uint32_t InstType = 1; | 338 uint32_t InstType = 1; |
217 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | 339 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); |
218 return; | 340 return; |
219 } | 341 } |
220 } while (0); | 342 } while (0); |
221 UnimplementedError(Ctx->getFlags()); | 343 UnimplementedError(Ctx->getFlags()); |
222 } | 344 } |
223 | 345 |
346 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | |
347 CondARM32::Cond Cond) { | |
348 // Note: Loop is used so that we can short ciruit using break; | |
349 do { | |
350 uint32_t Rt; | |
351 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | |
352 break; | |
353 uint32_t Address; | |
354 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | |
355 break; | |
356 // cccc010pub0nnnnttttiiiiiiiiiiii (ARM section A8.8.204, encoding A1; and | |
357 // section 18.8.207, encoding A1). | |
358 uint32_t InstType = B1; // 010 | |
359 bool IsLoad = false; | |
360 Type Ty = OpRt->getType(); | |
361 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | |
362 break; | |
363 bool IsByte = Ty == IceType_i8; | |
Jim Stichnoth
2015/10/15 20:41:29
IceType_i1 should also qualify as IsByte, since st
John
2015/10/15 20:59:25
const bool IsByte = ...
also, please assert that
Karl
2015/10/15 22:03:33
Using typeWidthInBytes to resolve if is byte. Note
| |
364 // Check for rule violations. | |
365 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | |
366 (!isBitSet(P, Address) && isBitSet(W, Address)) || | |
367 (!IsByte && | |
368 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | |
369 isBitSet(P, Address) && !isBitSet(U, Address) && | |
370 isBitSet(W, Address) && | |
371 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | |
372 break; | |
373 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | |
374 return; | |
375 } while (0); | |
376 UnimplementedError(Ctx->getFlags()); | |
377 } | |
378 | |
224 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 379 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
225 const Operand *OpSrc1, bool SetFlags, | 380 const Operand *OpSrc1, bool SetFlags, |
226 CondARM32::Cond Cond) { | 381 CondARM32::Cond Cond) { |
227 // Note: Loop is used so that we can short circuit using break; | 382 // Note: Loop is used so that we can short circuit using break; |
228 do { | 383 do { |
229 uint32_t Rd; | 384 uint32_t Rd; |
230 if (decode(OpRd, Rd) != DecodedAsRegister) | 385 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
231 break; | 386 break; |
232 uint32_t Rn; | 387 uint32_t Rn; |
233 if (decode(OpRn, Rn) != DecodedAsRegister) | 388 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
234 break; | 389 break; |
235 uint32_t Src1Value; | 390 uint32_t Src1Value; |
236 // TODO(kschimpf) Other possible decodings of add. | 391 // TODO(kschimpf) Other possible decodings of add. |
237 if (decode(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { | 392 if (decodeOperand(OpSrc1, Src1Value) == DecodedAsRotatedImm8) { |
238 // Sub (Immediate): See ARM section A8.8.222, rule A1. | 393 // Sub (Immediate): See ARM section A8.8.222, rule A1. |
239 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 394 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
240 // s=SetFlags and iiiiiiiiiiii=Src1Value | 395 // s=SetFlags and iiiiiiiiiiii=Src1Value |
241 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || | 396 if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) || |
242 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) | 397 (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags)) |
243 // Conditions of rule violated. | 398 // Conditions of rule violated. |
244 break; | 399 break; |
245 uint32_t Add = B1; // 0010 | 400 uint32_t Add = B1; // 0010 |
246 uint32_t InstType = 1; | 401 uint32_t InstType = 1; |
247 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); | 402 emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value); |
248 return; | 403 return; |
249 } | 404 } |
250 } while (0); | 405 } while (0); |
251 UnimplementedError(Ctx->getFlags()); | 406 UnimplementedError(Ctx->getFlags()); |
252 } | 407 } |
253 | 408 |
254 } // end of namespace Ice | 409 } // end of namespace Ice |
OLD | NEW |