Chromium Code Reviews| 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 |