| 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 static constexpr uint32_t kRotateShift = 8; | 63 static constexpr uint32_t kRotateShift = 8; |
| 64 | 64 |
| 65 // Shift instruction register fields encodings. | 65 // Shift instruction register fields encodings. |
| 66 static constexpr uint32_t kShiftImmShift = 7; | 66 static constexpr uint32_t kShiftImmShift = 7; |
| 67 static constexpr uint32_t kShiftImmBits = 5; | 67 static constexpr uint32_t kShiftImmBits = 5; |
| 68 static constexpr uint32_t kShiftShift = 5; | 68 static constexpr uint32_t kShiftShift = 5; |
| 69 | 69 |
| 70 static constexpr uint32_t kImmed12Bits = 12; | 70 static constexpr uint32_t kImmed12Bits = 12; |
| 71 static constexpr uint32_t kImm12Shift = 0; | 71 static constexpr uint32_t kImm12Shift = 0; |
| 72 | 72 |
| 73 // Type of instruction encoding (bits 25-27). |
| 74 static constexpr uint32_t kInstTypeRegister = 0; // i.e. 000 |
| 75 static constexpr uint32_t kInstTypeImmediate = 1; // i.e. 001 |
| 76 |
| 73 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } | 77 inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
| 74 | 78 |
| 75 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { | 79 inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
| 76 return static_cast<uint32_t>(Rn); | 80 return static_cast<uint32_t>(Rn); |
| 77 } | 81 } |
| 78 | 82 |
| 79 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { | 83 inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) { |
| 80 return R != RegARM32::Encoded_Not_GPR; | 84 return R != RegARM32::Encoded_Not_GPR; |
| 81 } | 85 } |
| 82 | 86 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 OperandARM32Mem::Offset); | 196 OperandARM32Mem::Offset); |
| 193 return DecodedAsImmRegOffset; | 197 return DecodedAsImmRegOffset; |
| 194 } | 198 } |
| 195 return CantDecode; | 199 return CantDecode; |
| 196 } | 200 } |
| 197 | 201 |
| 198 } // end of anonymous namespace | 202 } // end of anonymous namespace |
| 199 | 203 |
| 200 namespace Ice { | 204 namespace Ice { |
| 201 | 205 |
| 206 size_t ARM32::TextInstFixup::emit(GlobalContext *Ctx, |
| 207 RelocOffsetT OverrideOffset, |
| 208 bool IsPCRel) const { |
| 209 (void)OverrideOffset; |
| 210 (void)IsPCRel; |
| 211 Ctx->getStrEmit() << Message << "\n"; |
| 212 static constexpr size_t FixupSize = 4; // i.e. #bytes in instruction. |
| 213 return FixupSize; |
| 214 } |
| 215 |
| 202 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, | 216 Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number, |
| 203 LabelVector &Labels) { | 217 LabelVector &Labels) { |
| 204 Label *L = nullptr; | 218 Label *L = nullptr; |
| 205 if (Number == Labels.size()) { | 219 if (Number == Labels.size()) { |
| 206 L = new (this->allocate<Label>()) Label(); | 220 L = new (this->allocate<Label>()) Label(); |
| 207 Labels.push_back(L); | 221 Labels.push_back(L); |
| 208 return L; | 222 return L; |
| 209 } | 223 } |
| 210 if (Number > Labels.size()) { | 224 if (Number > Labels.size()) { |
| 211 Labels.resize(Number + 1); | 225 Labels.resize(Number + 1); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 224 while (label->isLinked()) { | 238 while (label->isLinked()) { |
| 225 intptr_t position = label->getLinkPosition(); | 239 intptr_t position = label->getLinkPosition(); |
| 226 intptr_t next = Buffer.load<int32_t>(position); | 240 intptr_t next = Buffer.load<int32_t>(position); |
| 227 Buffer.store<int32_t>(position, bound - (position + 4)); | 241 Buffer.store<int32_t>(position, bound - (position + 4)); |
| 228 label->setPosition(next); | 242 label->setPosition(next); |
| 229 } | 243 } |
| 230 // TODO(kschimpf) Decide if we have near jumps. | 244 // TODO(kschimpf) Decide if we have near jumps. |
| 231 label->bindTo(bound); | 245 label->bindTo(bound); |
| 232 } | 246 } |
| 233 | 247 |
| 248 void ARM32::AssemblerARM32::emitTextInst(const std::string &Text) { |
| 249 AssemblerFixup *F = |
| 250 new (allocate<ARM32::TextInstFixup>()) ARM32::TextInstFixup(Text); |
| 251 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 252 installFixup(F); |
| 253 emitFixup(F); |
| 254 emitInst(0); |
| 255 } |
| 256 |
| 234 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, | 257 void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
| 235 uint32_t Opcode, bool SetCc, uint32_t Rn, | 258 uint32_t Opcode, bool SetCc, uint32_t Rn, |
| 236 uint32_t Rd, uint32_t Imm12) { | 259 uint32_t Rd, uint32_t Imm12) { |
| 237 assert(isGPRRegisterDefined(Rd)); | 260 assert(isGPRRegisterDefined(Rd)); |
| 238 // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 261 // TODO(kschimpf): Remove void cast when MINIMAL build allows. |
| 239 (void)isGPRRegisterDefined(Rd); | 262 (void)isGPRRegisterDefined(Rd); |
| 240 assert(Cond != CondARM32::kNone); | 263 assert(Cond != CondARM32::kNone); |
| 241 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 264 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 242 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | 265 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 243 (Type << kTypeShift) | (Opcode << kOpcodeShift) | | 266 (Type << kTypeShift) | (Opcode << kOpcodeShift) | |
| 244 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | | 267 (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |
| 245 (Rd << kRdShift) | Imm12; | 268 (Rd << kRdShift) | Imm12; |
| 246 emitInst(Encoding); | 269 emitInst(Encoding); |
| 247 } | 270 } |
| 248 | 271 |
| 249 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, | 272 void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, |
| 250 bool IsLoad, bool IsByte, uint32_t Rt, | 273 bool IsLoad, bool IsByte, uint32_t Rt, |
| 251 uint32_t Address) { | 274 uint32_t Address) { |
| 252 assert(isGPRRegisterDefined(Rt)); | 275 assert(isGPRRegisterDefined(Rt)); |
| 253 assert(Cond != CondARM32::kNone); | 276 assert(Cond != CondARM32::kNone); |
| 254 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 277 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 255 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | | 278 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | |
| 256 (InstType << kTypeShift) | (IsLoad ? L : 0) | | 279 (InstType << kTypeShift) | (IsLoad ? L : 0) | |
| 257 (IsByte ? B : 0) | (Rt << kRdShift) | Address; | 280 (IsByte ? B : 0) | (Rt << kRdShift) | Address; |
| 258 emitInst(Encoding); | 281 emitInst(Encoding); |
| 259 } | 282 } |
| 260 | 283 |
| 261 void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, | 284 bool ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, |
| 262 const Operand *OpSrc1, bool SetFlags, | 285 const Operand *OpSrc1, bool SetFlags, |
| 263 CondARM32::Cond Cond) { | 286 CondARM32::Cond Cond) { |
| 264 // Note: Loop is used so that we can short circuit using break; | 287 uint32_t Rd; |
| 265 do { | 288 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
| 266 uint32_t Rd; | 289 return false; |
| 267 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 290 uint32_t Rn; |
| 268 break; | 291 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
| 269 uint32_t Rn; | 292 return false; |
| 270 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 293 constexpr uint32_t Add = B2; // 0100 |
| 271 break; | 294 uint32_t Src1Value; |
| 272 constexpr uint32_t Add = B2; // 0100 | 295 // TODO(kschimpf) Other possible decodings of add. |
| 273 uint32_t Src1Value; | 296 switch (decodeOperand(OpSrc1, Src1Value)) { |
| 274 // TODO(kschimpf) Other possible decodings of add. | 297 default: |
| 275 switch (decodeOperand(OpSrc1, Src1Value)) { | 298 return false; |
| 276 default: | 299 case DecodedAsRegister: { |
| 277 break; | 300 // ADD (register) - ARM section A8.8.7, encoding A1: |
| 278 case DecodedAsRegister: { | 301 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
| 279 // ADD (register) - ARM section A8.8.7, encoding A1: | 302 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: |
| 280 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} | 303 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} |
| 281 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: | 304 // |
| 282 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} | 305 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 283 // | 306 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags |
| 284 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 307 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
| 285 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags | 308 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
| 286 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | 309 // Conditions of rule violated. |
| 287 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | 310 return false; |
| 288 // Conditions of rule violated. | 311 emitType01(Cond, kInstTypeRegister, Add, SetFlags, Rn, Rd, Src1Value); |
| 289 break; | 312 return true; |
| 290 constexpr uint32_t InstTypeRegister = 0; | 313 } |
| 291 emitType01(Cond, InstTypeRegister, Add, SetFlags, Rn, Rd, Src1Value); | 314 case DecodedAsRotatedImm8: { |
| 292 return; | 315 // ADD (Immediate) - ARM section A8.8.5, encoding A1: |
| 293 } | 316 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 294 case DecodedAsRotatedImm8: { | 317 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. |
| 295 // ADD (Immediate) - ARM section A8.8.5, encoding A1: | 318 // add{s}<c> <Rd>, sp, #<RotatedImm8> |
| 296 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 319 // |
| 297 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. | 320 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 298 // add{s}<c> <Rd>, sp, #<RotatedImm8> | 321 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. |
| 299 // | 322 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
| 300 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 323 // Conditions of rule violated. |
| 301 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. | 324 return false; |
| 302 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 325 emitType01(Cond, kInstTypeImmediate, Add, SetFlags, Rn, Rd, Src1Value); |
| 303 // Conditions of rule violated. | 326 return true; |
| 304 break; | 327 } |
| 305 constexpr uint32_t InstTypeImmediate = 1; | 328 }; |
| 306 emitType01(Cond, InstTypeImmediate, Add, SetFlags, Rn, Rd, Src1Value); | |
| 307 return; | |
| 308 } | |
| 309 } | |
| 310 } while (0); | |
| 311 UnimplementedError(Ctx->getFlags()); | |
| 312 } | 329 } |
| 313 | 330 |
| 314 void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { | 331 bool ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { |
| 315 // BKPT - ARM section A*.8.24 - encoding A1: | 332 // BKPT - ARM section A*.8.24 - encoding A1: |
| 316 // bkpt #<Imm16> | 333 // bkpt #<Imm16> |
| 317 // | 334 // |
| 318 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 | 335 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 |
| 319 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 336 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 320 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | | 337 const uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | |
| 321 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); | 338 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); |
| 322 emitInst(Encoding); | 339 emitInst(Encoding); |
| 340 return true; |
| 323 } | 341 } |
| 324 | 342 |
| 325 void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { | 343 bool ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
| 326 // BX - ARM section A8.8.27, encoding A1: | 344 // BX - ARM section A8.8.27, encoding A1: |
| 327 // bx<c> <Rm> | 345 // bx<c> <Rm> |
| 328 // | 346 // |
| 329 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. | 347 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
| 330 assert(isGPRRegisterDefined(Rm)); | 348 if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond))) |
| 331 // TODO(kschimpf): Remove void cast when MINIMAL build allows. | 349 return false; |
| 332 (void)isGPRRegisterDefined(Rm); | |
| 333 assert(isConditionDefined(Cond)); | |
| 334 (void)isConditionDefined(Cond); | |
| 335 AssemblerBuffer::EnsureCapacity ensured(&Buffer); | 350 AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
| 336 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | | 351 const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |
| 337 B21 | (0xfff << 8) | B4 | | 352 B21 | (0xfff << 8) | B4 | |
| 338 (encodeGPRRegister(Rm) << kRmShift); | 353 (encodeGPRRegister(Rm) << kRmShift); |
| 339 emitInst(Encoding); | 354 emitInst(Encoding); |
| 355 return true; |
| 340 } | 356 } |
| 341 | 357 |
| 342 void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, | 358 bool ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
| 343 CondARM32::Cond Cond) { | 359 CondARM32::Cond Cond) { |
| 344 // Note: Loop is used so that we can short ciruit using break; | 360 uint32_t Rt; |
| 345 do { | 361 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 346 uint32_t Rt; | 362 return false; |
| 347 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 363 uint32_t Address; |
| 348 break; | 364 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
| 349 uint32_t Address; | 365 return false; |
| 350 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 366 // LDR (immediate) - ARM section A8.8.63, encoding A1: |
| 351 break; | 367 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 352 // LDR (immediate) - ARM section A8.8.63, encoding A1: | 368 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 353 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 369 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 354 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 370 // LDRB (immediate) - ARM section A8.8.68, encoding A1: |
| 355 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 371 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 356 // LDRB (immediate) - ARM section A8.8.68, encoding A1: | 372 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 357 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 373 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 358 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 374 // |
| 359 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 375 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 360 // | 376 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. |
| 361 // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 377 constexpr bool IsLoad = true; |
| 362 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 378 const Type Ty = OpRt->getType(); |
| 363 constexpr uint32_t InstType = B1; // 010 | 379 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
| 364 constexpr bool IsLoad = true; | 380 return false; |
| 365 const Type Ty = OpRt->getType(); | 381 const bool IsByte = typeWidthInBytes(Ty) == 1; |
| 366 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 382 // Check conditions of rules violated. |
| 367 break; | 383 if (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) |
| 368 const bool IsByte = typeWidthInBytes(Ty) == 1; | 384 return false; |
| 369 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 385 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 370 (!isBitSet(P, Address) && isBitSet(W, Address)) || | 386 return false; |
| 371 (!IsByte && | 387 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
| 372 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 388 !isBitSet(P, Address) && isBitSet(U, Address) & !isBitSet(W, Address) && |
| 373 !isBitSet(P, Address) && | 389 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
| 374 isBitSet(U, Address) & !isBitSet(W, Address) && | 390 return false; |
| 375 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 391 emitMemOp(Cond, kInstTypeImmediate, IsLoad, IsByte, Rt, Address); |
| 376 break; | 392 return true; |
| 377 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | |
| 378 return; | |
| 379 } while (0); | |
| 380 UnimplementedError(Ctx->getFlags()); | |
| 381 } | 393 } |
| 382 | 394 |
| 383 void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, | 395 bool ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
| 384 CondARM32::Cond Cond) { | 396 CondARM32::Cond Cond) { |
| 385 // Note: Loop is used so that we can short ciruit using break; | 397 uint32_t Rd; |
| 386 do { | 398 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
| 387 uint32_t Rd; | 399 return false; |
| 388 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 400 uint32_t Src; |
| 389 break; | 401 // TODO(kschimpf) Handle other forms of mov. |
| 390 uint32_t Src; | 402 if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8) |
| 391 // TODO(kschimpf) Handle other forms of mov. | 403 return false; |
| 392 if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { | 404 // MOV (immediate) - ARM section A8.8.102, encoding A1: |
| 393 // MOV (immediate) - ARM section A8.8.102, encoding A1: | 405 // mov{S}<c> <Rd>, #<RotatedImm8> |
| 394 // mov{S}<c> <Rd>, #<RotatedImm8> | 406 // |
| 395 // | 407 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
| 396 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, | 408 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
| 397 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this | 409 // assembler. |
| 398 // assembler. | 410 constexpr bool SetFlags = false; |
| 399 constexpr bool SetFlags = false; | 411 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
| 400 if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) | 412 // Conditions of rule violated. |
| 401 // Conditions of rule violated. | 413 return false; |
| 402 break; | 414 constexpr uint32_t Rn = 0; |
| 403 constexpr uint32_t Rn = 0; | 415 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |
| 404 constexpr uint32_t Mov = B3 | B2 | B0; // 1101. | 416 emitType01(Cond, kInstTypeImmediate, Mov, SetFlags, Rn, Rd, Src); |
| 405 constexpr uint32_t InstType = 1; | 417 return true; |
| 406 emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); | |
| 407 return; | |
| 408 } | |
| 409 } while (0); | |
| 410 UnimplementedError(Ctx->getFlags()); | |
| 411 } | 418 } |
| 412 | 419 |
| 413 void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, | 420 bool ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
| 414 CondARM32::Cond Cond) { | 421 CondARM32::Cond Cond) { |
| 415 // Note: Loop is used so that we can short ciruit using break; | 422 uint32_t Rt; |
| 416 do { | 423 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
| 417 uint32_t Rt; | 424 return false; |
| 418 if (decodeOperand(OpRt, Rt) != DecodedAsRegister) | 425 uint32_t Address; |
| 419 break; | 426 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
| 420 uint32_t Address; | 427 return false; |
| 421 if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) | 428 // STR (immediate) - ARM section A8.8.204, encoding A1: |
| 422 break; | 429 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 423 // STR (immediate) - ARM section A8.8.204, encoding A1: | 430 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 424 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 431 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 425 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 432 // STRB (immediate) - ARM section A8.8.207, encoding A1: |
| 426 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 433 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 |
| 427 // STRB (immediate) - ARM section A8.8.207, encoding A1: | 434 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 |
| 428 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 | 435 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 |
| 429 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 | 436 // |
| 430 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 | 437 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, |
| 431 // | 438 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. |
| 432 // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, | 439 constexpr bool IsLoad = false; |
| 433 // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +. | 440 const Type Ty = OpRt->getType(); |
| 434 constexpr uint32_t InstType = B1; // 010 | 441 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
| 435 constexpr bool IsLoad = false; | 442 return false; |
| 436 const Type Ty = OpRt->getType(); | 443 const bool IsByte = typeWidthInBytes(Ty) == 1; |
| 437 if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? | 444 // Check for rule violations. |
| 438 break; | 445 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc)) |
| 439 const bool IsByte = typeWidthInBytes(Ty) == 1; | 446 return false; |
| 440 // Check for rule violations. | 447 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 441 if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || | 448 return false; |
| 442 (!isBitSet(P, Address) && isBitSet(W, Address)) || | 449 if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
| 443 (!IsByte && | 450 isBitSet(P, Address) && !isBitSet(U, Address) && isBitSet(W, Address) && |
| 444 (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && | 451 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) |
| 445 isBitSet(P, Address) && !isBitSet(U, Address) && | 452 return false; |
| 446 isBitSet(W, Address) && | 453 emitMemOp(Cond, kInstTypeImmediate, IsLoad, IsByte, Rt, Address); |
| 447 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) | 454 return true; |
| 448 // Conditions of rule violated. | |
| 449 break; | |
| 450 emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); | |
| 451 return; | |
| 452 } while (0); | |
| 453 UnimplementedError(Ctx->getFlags()); | |
| 454 } | 455 } |
| 455 | 456 |
| 456 void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, | 457 bool ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
| 457 const Operand *OpSrc1, bool SetFlags, | 458 const Operand *OpSrc1, bool SetFlags, |
| 458 CondARM32::Cond Cond) { | 459 CondARM32::Cond Cond) { |
| 459 // Note: Loop is used so that we can short circuit using break; | 460 uint32_t Rd; |
| 460 do { | 461 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
| 461 uint32_t Rd; | 462 return false; |
| 462 if (decodeOperand(OpRd, Rd) != DecodedAsRegister) | 463 uint32_t Rn; |
| 463 break; | 464 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
| 464 uint32_t Rn; | 465 return false; |
| 465 if (decodeOperand(OpRn, Rn) != DecodedAsRegister) | 466 constexpr uint32_t Sub = B1; // 0010 |
| 466 break; | 467 uint32_t Src1Value; |
| 467 constexpr uint32_t Sub = B1; // 0010 | 468 // TODO(kschimpf) Other possible decodings of sub. |
| 468 uint32_t Src1Value; | 469 switch (decodeOperand(OpSrc1, Src1Value)) { |
| 469 // TODO(kschimpf) Other possible decodings of sub. | 470 default: |
| 470 switch (decodeOperand(OpSrc1, Src1Value)) { | 471 return false; |
| 471 default: | 472 case DecodedAsRegister: { |
| 472 break; | 473 // SUB (register) - ARM section A8.8.223, encoding A1: |
| 473 case DecodedAsRegister: { | 474 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
| 474 // SUB (register) - ARM section A8.8.223, encoding A1: | 475 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: |
| 475 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} | 476 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} |
| 476 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: | 477 // |
| 477 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} | 478 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 478 // | 479 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. |
| 479 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, | 480 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
| 480 // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. | 481 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
| 481 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); | 482 // Conditions of rule violated. |
| 482 constexpr uint32_t InstType = 0; // i.e. register | 483 return false; |
| 483 if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) | 484 emitType01(Cond, kInstTypeRegister, Sub, SetFlags, Rn, Rd, Src1Value); |
| 484 // Conditions of rule violated. | 485 return true; |
| 485 break; | 486 } |
| 486 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); | 487 case DecodedAsRotatedImm8: { |
| 487 return; | 488 // Sub (Immediate) - ARM section A8.8.222, encoding A1: |
| 488 } | 489 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
| 489 case DecodedAsRotatedImm8: { | 490 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: |
| 490 // Sub (Immediate) - ARM section A8.8.222, encoding A1: | 491 // sub{s}<c> sp, <Rn>, #<RotatedImm8> |
| 491 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> | 492 // |
| 492 // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: | 493 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
| 493 // sub{s}<c> sp, <Rn>, #<RotatedImm8> | 494 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 |
| 494 // | 495 if (Rd == RegARM32::Encoded_Reg_pc) |
| 495 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, | 496 // Conditions of rule violated. |
| 496 // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 | 497 return false; |
| 497 if (Rd == RegARM32::Encoded_Reg_pc) | 498 emitType01(Cond, kInstTypeImmediate, Sub, SetFlags, Rn, Rd, Src1Value); |
| 498 // Conditions of rule violated. | 499 return true; |
| 499 break; | 500 } |
| 500 constexpr uint32_t InstType = 1; | 501 } |
| 501 emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); | |
| 502 return; | |
| 503 } | |
| 504 } | |
| 505 } while (0); | |
| 506 UnimplementedError(Ctx->getFlags()); | |
| 507 } | 502 } |
| 508 | 503 |
| 509 } // end of namespace Ice | 504 } // end of namespace Ice |
| OLD | NEW |