Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: src/IceAssemblerARM32.cpp

Issue 1402403002: Handle stack spills in ARM integrated assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix nits. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698