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