1 //===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===// 2 // 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 5 // BSD-style license that can be found in the LICENSE file. 6 // 7 // Modified by the Subzero authors. 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // The Subzero Code Generator 12 // 13 // This file is distributed under the University of Illinois Open Source 14 // License. See LICENSE.TXT for details. 15 // 16 //===----------------------------------------------------------------------===// 17 /// 18 /// \file 19 /// \brief Declares the Assembler class for ARM32. 20 /// 21 /// Note: All references to ARM "section" documentation refers to the "ARM 22 /// Architecture Reference Manual, ARMv7-A and ARMv7-R edition". See: 23 /// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c 24 /// 25 //===----------------------------------------------------------------------===// 26 27 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H 28 #define SUBZERO_SRC_ICEASSEMBLERARM32_H 29 30 #include "IceAssembler.h" 31 #include "IceConditionCodesARM32.h" 32 #include "IceDefs.h" 33 #include "IceFixups.h" 34 #include "IceInstARM32.h" 35 #include "IceRegistersARM32.h" 36 #include "IceTargetLowering.h" 37 38 namespace Ice { 39 namespace ARM32 { 40 41 /// Handles encoding of bottom/top 16 bits of an address using movw/movt. 42 class MoveRelocatableFixup final : public AssemblerFixup { 43 MoveRelocatableFixup &operator=(const MoveRelocatableFixup &) = delete; 44 MoveRelocatableFixup(const MoveRelocatableFixup &) = default; 45 46 public: 47 MoveRelocatableFixup() = default; 48 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final; 49 void emitOffset(Assembler *Asm) const; 50 }; 51 52 /// Handles encoding of branch and link to global location. 53 class BlRelocatableFixup final : public AssemblerFixup { 54 BlRelocatableFixup(const BlRelocatableFixup &) = delete; 55 BlRelocatableFixup &operator=(const BlRelocatableFixup &) = delete; 56 57 public: 58 BlRelocatableFixup() = default; 59 size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final; 60 void emitOffset(Assembler *Asm) const; 61 }; 62 63 class AssemblerARM32 : public Assembler { 64 AssemblerARM32(const AssemblerARM32 &) = delete; 65 AssemblerARM32 &operator=(const AssemblerARM32 &) = delete; 66 67 public: 68 // Rotation values. 69 enum RotationValue { 70 kRotateNone, // Omitted 71 kRotate8, // ror #8 72 kRotate16, // ror #16 73 kRotate24 // ror #24 74 }; 75 76 // Encoding of the number of D registers in a list of D registers. 77 enum DRegListSize { 78 DRegListSize1 = 7, // 0b0111 79 DRegListSize2 = 10, // 0b1010 80 DRegListSIze3 = 6, // 0b0110 81 DRegListSize4 = 2 // 0b0010 82 }; 83 84 class TargetInfo { 85 TargetInfo(const TargetInfo &) = delete; 86 TargetInfo &operator=(const TargetInfo &) = delete; 87 88 public: TargetInfo(bool HasFramePointer,RegNumT FrameOrStackReg)89 TargetInfo(bool HasFramePointer, RegNumT FrameOrStackReg) 90 : HasFramePointer(HasFramePointer), FrameOrStackReg(FrameOrStackReg) {} TargetInfo(const TargetLowering * Target)91 explicit TargetInfo(const TargetLowering *Target) 92 : HasFramePointer(Target->hasFramePointer()), 93 FrameOrStackReg(Target->getFrameOrStackReg()) {} 94 const bool HasFramePointer; 95 const RegNumT FrameOrStackReg; 96 }; 97 AssemblerARM32()98 AssemblerARM32() : Assembler(Asm_ARM32) {} ~AssemblerARM32()99 ~AssemblerARM32() override { 100 if (BuildDefs::asserts()) { 101 for (const Label *Label : CfgNodeLabels) { 102 Label->finalCheck(); 103 } 104 for (const Label *Label : LocalLabels) { 105 Label->finalCheck(); 106 } 107 } 108 } 109 110 MoveRelocatableFixup *createMoveFixup(bool IsMovW, const Constant *Value); 111 112 BlRelocatableFixup *createBlFixup(const ConstantRelocatable *BlTarget); 113 alignFunction()114 void alignFunction() override { 115 const SizeT Align = 1 << getBundleAlignLog2Bytes(); 116 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); 117 constexpr SizeT InstSize = sizeof(IValueT); 118 assert(BytesNeeded % InstARM32::InstSize == 0); 119 while (BytesNeeded > 0) { 120 trap(); 121 BytesNeeded -= InstSize; 122 } 123 } 124 getBundleAlignLog2Bytes()125 SizeT getBundleAlignLog2Bytes() const override { return 4; } 126 getAlignDirective()127 const char *getAlignDirective() const override { return ".p2alignl"; } 128 129 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override; 130 131 void padWithNop(intptr_t Padding) override; 132 getCfgNodeLabel(SizeT NodeNumber)133 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { 134 assert(NodeNumber < CfgNodeLabels.size()); 135 return CfgNodeLabels[NodeNumber]; 136 } 137 getOrCreateCfgNodeLabel(SizeT NodeNumber)138 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { 139 return getOrCreateLabel(NodeNumber, CfgNodeLabels); 140 } 141 getOrCreateLocalLabel(SizeT Number)142 Label *getOrCreateLocalLabel(SizeT Number) { 143 return getOrCreateLabel(Number, LocalLabels); 144 } 145 bindLocalLabel(const InstARM32Label * InstL,SizeT Number)146 void bindLocalLabel(const InstARM32Label *InstL, SizeT Number) { 147 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) { 148 constexpr SizeT InstSize = 0; 149 emitTextInst(InstL->getLabelName() + ":", InstSize); 150 } 151 Label *L = getOrCreateLocalLabel(Number); 152 if (!getPreliminary()) 153 this->bind(L); 154 } 155 fixupIsPCRel(FixupKind Kind)156 bool fixupIsPCRel(FixupKind Kind) const override { 157 if (Kind == llvm::ELF::R_ARM_MOVW_PREL_NC) 158 return true; 159 if (Kind == llvm::ELF::R_ARM_MOVT_PREL) 160 return true; 161 return false; 162 } 163 164 /// Accessors to keep track of the number of bytes generated inside 165 /// InstARM32::emit() methods, when run inside of 166 /// InstARM32::emitUsingTextFixup(). resetEmitTextSize()167 void resetEmitTextSize() { EmitTextSize = 0; } incEmitTextSize(size_t Amount)168 void incEmitTextSize(size_t Amount) { EmitTextSize += Amount; } decEmitTextSize(size_t Amount)169 void decEmitTextSize(size_t Amount) { EmitTextSize -= Amount; } getEmitTextSize()170 size_t getEmitTextSize() const { return EmitTextSize; } 171 172 void bind(Label *label); 173 174 // List of instructions implemented by integrated assembler. 175 176 void adc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 177 bool SetFlags, CondARM32::Cond Cond); 178 179 void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 180 bool SetFlags, CondARM32::Cond Cond); 181 182 void and_(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 183 bool SetFlags, CondARM32::Cond Cond); 184 185 void asr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 186 bool SetFlags, CondARM32::Cond Cond); 187 188 void b(Label *L, CondARM32::Cond Cond); 189 190 void bkpt(uint16_t Imm16); 191 192 void bic(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 193 bool SetFlags, CondARM32::Cond Cond); 194 195 void bl(const ConstantRelocatable *Target); 196 197 void blx(const Operand *Target); 198 199 void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL); 200 201 void clz(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); 202 203 void cmn(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond); 204 205 void cmp(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond); 206 207 void dmb(IValueT Option); // Option is a 4-bit value. 208 209 void eor(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 210 bool SetFlags, CondARM32::Cond Cond); 211 212 void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond, 213 const TargetInfo &TInfo); 214 ldr(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)215 void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond, 216 const TargetLowering *Lowering) { 217 const TargetInfo TInfo(Lowering); 218 ldr(OpRt, OpAddress, Cond, TInfo); 219 } 220 221 void ldrex(const Operand *OpRt, const Operand *OpAddress, 222 CondARM32::Cond Cond, const TargetInfo &TInfo); 223 ldrex(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)224 void ldrex(const Operand *OpRt, const Operand *OpAddress, 225 CondARM32::Cond Cond, const TargetLowering *Lowering) { 226 const TargetInfo TInfo(Lowering); 227 ldrex(OpRt, OpAddress, Cond, TInfo); 228 } 229 230 void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 231 bool SetFlags, CondARM32::Cond Cond); 232 233 void lsr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 234 bool SetFlags, CondARM32::Cond Cond); 235 236 void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); 237 238 void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); 239 240 void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); 241 242 void mla(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm, 243 const Operand *OpRa, CondARM32::Cond Cond); 244 245 void mls(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm, 246 const Operand *OpRa, CondARM32::Cond Cond); 247 248 void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 249 bool SetFlags, CondARM32::Cond Cond); 250 251 void mvn(const Operand *OpRd, const Operand *OpScc, CondARM32::Cond Cond); 252 253 void nop(); 254 255 void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 256 bool SetFlags, CondARM32::Cond Cond); 257 258 void pop(const Variable *OpRt, CondARM32::Cond Cond); 259 260 // Note: Registers is a bitset, where bit n corresponds to register Rn. 261 void popList(const IValueT Registers, CondARM32::Cond Cond); 262 263 void push(const Operand *OpRt, CondARM32::Cond Cond); 264 265 // Note: Registers is a bitset, where bit n corresponds to register Rn. 266 void pushList(const IValueT Registers, CondARM32::Cond Cond); 267 268 void rbit(const Operand *OpRd, const Operand *OpRm, CondARM32::Cond Cond); 269 270 void rev(const Operand *OpRd, const Operand *OpRm, CondARM32::Cond Cond); 271 272 void rsb(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 273 bool SetFlags, CondARM32::Cond Cond); 274 275 void rsc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 276 bool SetFlags, CondARM32::Cond Cond); 277 278 void sbc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 279 bool SetFlags, CondARM32::Cond Cond); 280 281 void sdiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 282 CondARM32::Cond Cond); 283 284 void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond, 285 const TargetInfo &TInfo); 286 str(const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)287 void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond, 288 const TargetLowering *Lowering) { 289 const TargetInfo TInfo(Lowering); 290 str(OpRt, OpAddress, Cond, TInfo); 291 } 292 293 void strex(const Operand *OpRd, const Operand *OpRt, const Operand *OpAddress, 294 CondARM32::Cond Cond, const TargetInfo &TInfo); 295 strex(const Operand * OpRd,const Operand * OpRt,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)296 void strex(const Operand *OpRd, const Operand *OpRt, const Operand *OpAddress, 297 CondARM32::Cond Cond, const TargetLowering *Lowering) { 298 const TargetInfo TInfo(Lowering); 299 strex(OpRd, OpRt, OpAddress, Cond, TInfo); 300 } 301 302 void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 303 bool SetFlags, CondARM32::Cond Cond); 304 305 // Implements sxtb/sxth depending on type of OpSrc0. 306 void sxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond); 307 308 void trap(); 309 310 void tst(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond); 311 312 void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, 313 CondARM32::Cond Cond); 314 315 void umull(const Operand *OpRdLo, const Operand *OpRdHi, const Operand *OpRn, 316 const Operand *OpRm, CondARM32::Cond Cond); 317 318 // Implements uxtb/uxth depending on type of OpSrc0. 319 void uxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond); 320 321 void vabss(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond); 322 323 void vabsd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond); 324 325 void vabsq(const Operand *OpQd, const Operand *OpQm); 326 327 void vaddd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, 328 CondARM32::Cond Cond); 329 330 void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, 331 CondARM32::Cond Cond); 332 333 // Integer vector add. 334 void vaddqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 335 const Operand *OpQn); 336 337 // Float vector add. 338 void vaddqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 339 340 void vandq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 341 342 void vbslq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 343 344 void vceqqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 345 const Operand *OpQn); 346 347 void vceqqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 348 349 void vcgeqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 350 const Operand *OpQn); 351 352 void vcugeqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 353 const Operand *OpQn); 354 355 void vcgeqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 356 357 void vcgtqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 358 const Operand *OpQn); 359 360 void vcugtqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 361 const Operand *OpQn); 362 363 void vcgtqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 364 365 void vcmpd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond cond); 366 367 // Second argument of compare is zero (+0.0). 368 void vcmpdz(const Operand *OpDd, CondARM32::Cond cond); 369 370 void vcmps(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond cond); 371 372 // Second argument of compare is zero (+0.0). 373 void vcmpsz(const Operand *OpSd, CondARM32::Cond cond); 374 375 void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond); 376 377 // vcvt<c>.S32.F32 378 void vcvtis(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond); 379 380 // vcvt<c>.S32.F64 381 void vcvtid(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond); 382 383 // vcvt<c>.F64.S32 384 void vcvtdi(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond); 385 386 // vcvt<c>.F64.U32 387 void vcvtdu(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond); 388 389 void vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond); 390 391 // vcvt<c>.F32.S32 392 void vcvtsi(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond); 393 394 // vcvt<c>.F32.U32 395 void vcvtsu(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond); 396 397 // vcvt<c>.U32.F64 398 void vcvtud(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond); 399 400 // vcvt<c>.u32.f32 401 void vcvtus(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond); 402 403 void vcvtqsi(const Operand *OpQd, const Operand *OpQm); 404 405 void vcvtqsu(const Operand *OpQd, const Operand *OpQm); 406 407 void vcvtqis(const Operand *OpQd, const Operand *OpQm); 408 409 void vcvtqus(const Operand *OpQd, const Operand *OpQm); 410 411 void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, 412 CondARM32::Cond Cond); 413 414 void vdivs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, 415 CondARM32::Cond Cond); 416 417 void veord(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm); 418 419 void veorq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm); 420 421 void vldrd(const Operand *OpDd, const Operand *OpAddress, 422 CondARM32::Cond Cond, const TargetInfo &TInfo); 423 vldrd(const Operand * OpDd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)424 void vldrd(const Operand *OpDd, const Operand *OpAddress, 425 CondARM32::Cond Cond, const TargetLowering *Lowering) { 426 const TargetInfo TInfo(Lowering); 427 vldrd(OpDd, OpAddress, Cond, TInfo); 428 } 429 430 void vldrs(const Operand *OpSd, const Operand *OpAddress, 431 CondARM32::Cond Cond, const TargetInfo &TInfo); 432 vldrs(const Operand * OpSd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)433 void vldrs(const Operand *OpSd, const Operand *OpAddress, 434 CondARM32::Cond Cond, const TargetLowering *Lowering) { 435 const TargetInfo TInfo(Lowering); 436 vldrs(OpSd, OpAddress, Cond, TInfo); 437 } 438 439 void vldrq(const Operand *OpQd, const Operand *OpAddress, 440 CondARM32::Cond Cond, const TargetInfo &TInfo); 441 vldrq(const Operand * OpQd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)442 void vldrq(const Operand *OpQd, const Operand *OpAddress, 443 CondARM32::Cond Cond, const TargetLowering *Lowering) { 444 const TargetInfo TInfo(Lowering); 445 vldrq(OpQd, OpAddress, Cond, TInfo); 446 } 447 448 // ElmtSize = #bits in vector element. 449 void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn, 450 const TargetInfo &TInfo); 451 452 void vld1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn, 453 const TargetInfo &TInfo); 454 vld1qr(size_t ElmtSize,const Operand * OpQd,const Operand * OpRn,const TargetLowering * Lowering)455 void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn, 456 const TargetLowering *Lowering) { 457 const TargetInfo TInfo(Lowering); 458 vld1qr(ElmtSize, OpQd, OpRn, TInfo); 459 } 460 vld1(size_t ElmtSize,const Operand * OpQd,const Operand * OpRn,const TargetLowering * Lowering)461 void vld1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn, 462 const TargetLowering *Lowering) { 463 const TargetInfo TInfo(Lowering); 464 vld1(ElmtSize, OpQd, OpRn, TInfo); 465 } 466 467 // Qn[i] = Imm for all i in vector. Returns true iff Imm can be defined as an 468 // Imm8 using AdvSIMDExpandImm(). 469 bool vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm); 470 471 // Dn = FpImm 472 void vmovd(const Operand *OpDn, const OperandARM32FlexFpImm *OpFpImm, 473 CondARM32::Cond Cond); 474 475 // Dd = Dm 476 void vmovdd(const Operand *OpDd, const Variable *OpDm, CondARM32::Cond Cond); 477 478 // Dm = Rt:Rt2 479 void vmovdrr(const Operand *OpDm, const Operand *OpRt, const Operand *OpRt2, 480 CondARM32::Cond Cond); 481 482 // Qd[Index] = Rt 483 void vmovqir(const Operand *OpQd, uint32_t Index, const Operand *OpRt, 484 CondARM32::Cond Cond); 485 486 // Qd[Index] = Sm 487 void vmovqis(const Operand *OpQd, uint32_t Indx, const Operand *OpSm, 488 CondARM32::Cond Cond); 489 490 // Rt = Qm[Index] 491 void vmovrqi(const Operand *OpRt, const Operand *OpQd, uint32_t Index, 492 CondARM32::Cond Cond); 493 494 // Rt:Rt2 = Dm 495 void vmovrrd(const Operand *OpRt, const Operand *OpRt2, const Operand *OpDm, 496 CondARM32::Cond Cond); 497 498 // Rt = Sn 499 void vmovrs(const Operand *OpRt, const Operand *OpSn, CondARM32::Cond Cond); 500 501 // Sn = FpImm 502 void vmovs(const Operand *OpSn, const OperandARM32FlexFpImm *OpFpImm, 503 CondARM32::Cond Cond); 504 505 // Sd = Sm 506 void vmovss(const Operand *OpSd, const Variable *OpSm, CondARM32::Cond Cond); 507 508 // Sd = Qm[Index] 509 void vmovsqi(const Operand *OpSd, const Operand *OpQm, uint32_t Index, 510 CondARM32::Cond Cond); 511 512 // Sn = Rt 513 void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond); 514 515 void vmlad(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, 516 CondARM32::Cond Cond); 517 518 void vmlas(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, 519 CondARM32::Cond Cond); 520 521 void vmlsd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, 522 CondARM32::Cond Cond); 523 524 void vmlss(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, 525 CondARM32::Cond Cond); 526 527 // Uses APSR_nzcv as register 528 void vmrsAPSR_nzcv(CondARM32::Cond Cond); 529 530 void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, 531 CondARM32::Cond Cond); 532 533 // Integer vector multiply. 534 void vmulqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, 535 const Operand *OpQm); 536 537 // Integer vector multiply high. 538 void vmulh(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, 539 const Operand *OpQm, bool Unsigned); 540 541 // Integer vector multiply add pairwise. 542 void vmlap(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, 543 const Operand *OpQm); 544 545 // Vector element replication. 546 void vdup(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, IValueT Idx); 547 548 // Vector interleave lower halves. 549 void vzip(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, 550 const Operand *OpQm); 551 552 // Float vector multiply. 553 void vmulqf(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm); 554 555 void vmuls(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, 556 CondARM32::Cond Cond); 557 558 void vmvnq(const Operand *OpQd, const Operand *OpQm); 559 560 void vmovlq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm); 561 void vmovhq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm); 562 void vmovhlq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm); 563 void vmovlhq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm); 564 565 void vnegqs(const Operand *OpQd, const Operand *OpQm); 566 567 void vnegqs(Type ElmtTy, const Operand *OpQd, const Operand *OpQm); 568 569 void vorrq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 570 571 void vpop(const Variable *OpBaseReg, SizeT NumConsecRegs, 572 CondARM32::Cond Cond); 573 574 void vpush(const Variable *OpBaseReg, SizeT NumConsecRegs, 575 CondARM32::Cond Cond); 576 577 void vshlqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 578 const Operand *OpQn); 579 580 void vshlqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 581 const Operand *OpQn); 582 583 void vshlqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 584 const ConstantInteger32 *OpQn); 585 586 void vshrqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 587 const ConstantInteger32 *OpQn, InstARM32::FPSign Sign); 588 589 void vsqrtd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond); 590 591 void vsqrts(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond); 592 593 void vstrd(const Operand *OpDd, const Operand *OpAddress, 594 CondARM32::Cond Cond, const TargetInfo &TInfo); 595 vstrd(const Operand * OpDd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)596 void vstrd(const Operand *OpDd, const Operand *OpAddress, 597 CondARM32::Cond Cond, const TargetLowering *Lowering) { 598 const TargetInfo TInfo(Lowering); 599 vstrd(OpDd, OpAddress, Cond, TInfo); 600 } 601 602 void vstrs(const Operand *OpSd, const Operand *OpAddress, 603 CondARM32::Cond Cond, const TargetInfo &TInfo); 604 vstrs(const Operand * OpSd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)605 void vstrs(const Operand *OpSd, const Operand *OpAddress, 606 CondARM32::Cond Cond, const TargetLowering *Lowering) { 607 const TargetInfo TInfo(Lowering); 608 vstrs(OpSd, OpAddress, Cond, TInfo); 609 } 610 611 void vstrq(const Operand *OpQd, const Operand *OpAddress, 612 CondARM32::Cond Cond, const TargetInfo &TInfo); 613 vstrq(const Operand * OpQd,const Operand * OpAddress,CondARM32::Cond Cond,const TargetLowering * Lowering)614 void vstrq(const Operand *OpQd, const Operand *OpAddress, 615 CondARM32::Cond Cond, const TargetLowering *Lowering) { 616 const TargetInfo TInfo(Lowering); 617 vstrq(OpQd, OpAddress, Cond, TInfo); 618 } 619 620 // ElmtSize = #bits in vector element. 621 void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress, 622 const TargetInfo &TInfo); 623 vst1qr(size_t ElmtSize,const Operand * OpQd,const Operand * OpRn,const TargetLowering * Lowering)624 void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn, 625 const TargetLowering *Lowering) { 626 const TargetInfo TInfo(Lowering); 627 vst1qr(ElmtSize, OpQd, OpRn, TInfo); 628 } 629 630 void vst1(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress, 631 const TargetInfo &TInfo); 632 vst1(size_t ElmtSize,const Operand * OpQd,const Operand * OpRn,const TargetLowering * Lowering)633 void vst1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn, 634 const TargetLowering *Lowering) { 635 const TargetInfo TInfo(Lowering); 636 vst1(ElmtSize, OpQd, OpRn, TInfo); 637 } 638 639 void vsubd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, 640 CondARM32::Cond Cond); 641 642 // Integer vector subtract. 643 void vsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 644 const Operand *OpQn); 645 646 // Integer vector saturating subtract. 647 void vqsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 648 const Operand *OpQn); 649 void vqsubqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 650 const Operand *OpQn); 651 652 // Integer vector saturating add. 653 void vqaddqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 654 const Operand *OpQn); 655 void vqaddqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 656 const Operand *OpQn); 657 658 // Integer vector packing with optional saturation. 659 void vqmovn2(Type ElmtTy, const Operand *OpQd, const Operand *OpQm, 660 const Operand *OpQn, bool Unsigned, bool Saturating); 661 662 // Float vector subtract 663 void vsubqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn); 664 665 void vsubs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, 666 CondARM32::Cond Cond); 667 classof(const Assembler * Asm)668 static bool classof(const Assembler *Asm) { 669 return Asm->getKind() == Asm_ARM32; 670 } 671 672 void emitTextInst(const std::string &Text, SizeT InstSize); 673 674 private: 675 ENABLE_MAKE_UNIQUE; 676 677 // A vector of pool-allocated x86 labels for CFG nodes. 678 using LabelVector = std::vector<Label *>; 679 LabelVector CfgNodeLabels; 680 // A vector of pool-allocated x86 labels for Local labels. 681 LabelVector LocalLabels; 682 // Number of bytes emitted by InstARM32::emit() methods, when run inside 683 // InstARM32::emitUsingTextFixup(). 684 size_t EmitTextSize = 0; 685 686 // Load/store multiple addressing mode. 687 enum BlockAddressMode { 688 // bit encoding P U W 689 DA = (0 | 0 | 0) << 21, // decrement after 690 IA = (0 | 4 | 0) << 21, // increment after 691 DB = (8 | 0 | 0) << 21, // decrement before 692 IB = (8 | 4 | 0) << 21, // increment before 693 DA_W = (0 | 0 | 1) << 21, // decrement after with writeback to base 694 IA_W = (0 | 4 | 1) << 21, // increment after with writeback to base 695 DB_W = (8 | 0 | 1) << 21, // decrement before with writeback to base 696 IB_W = (8 | 4 | 1) << 21 // increment before with writeback to base 697 }; 698 699 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); 700 701 void bindCfgNodeLabel(const CfgNode *Node) override; 702 703 // SIMD encoding for the vector ElmtTy. 704 static IValueT encodeElmtType(Type ElmtTy); 705 emitInst(IValueT Value)706 void emitInst(IValueT Value) { 707 AssemblerBuffer::EnsureCapacity _(&Buffer); 708 Buffer.emit<IValueT>(Value); 709 } 710 711 // List of possible checks to apply when calling emitType01() (below). 712 enum EmitChecks { NoChecks, RdIsPcAndSetFlags }; 713 714 // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=InstType, 715 // s=SetFlags, oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM 716 // section A5.2.3). 717 void emitType01(CondARM32::Cond Cond, IValueT InstType, IValueT Opcode, 718 bool SetFlags, IValueT Rn, IValueT Rd, IValueT imm12, 719 EmitChecks RuleChecks, const char *InstName); 720 721 // Converts appropriate representation on a data operation, and then calls 722 // emitType01 above. 723 void emitType01(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd, 724 const Operand *OpRn, const Operand *OpSrc1, bool SetFlags, 725 EmitChecks RuleChecks, const char *InstName); 726 727 // Same as above, but the value for Rd and Rn have already been converted 728 // into instruction values. 729 void emitType01(CondARM32::Cond Cond, IValueT Opcode, IValueT OpRd, 730 IValueT OpRn, const Operand *OpSrc1, bool SetFlags, 731 EmitChecks RuleChecks, const char *InstName); 732 733 void emitType05(CondARM32::Cond Cond, int32_t Offset, bool Link); 734 735 // Emit ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond, 736 // ooo=InstType, l=isLoad, b=isByte, and 737 // aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that Address is assumed to be 738 // defined by decodeAddress() in IceAssemblerARM32.cpp. 739 void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad, 740 bool IsByte, IValueT Rt, IValueT Address); 741 742 // Emit ccccxxxxxxxxxxxxddddxxxxxxxxmmmm where cccc=Cond, 743 // xxxxxxxxxxxx0000xxxxxxxx0000=Opcode, dddd=Rd, and mmmm=Rm. 744 void emitRdRm(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd, 745 const Operand *OpRm, const char *InstName); 746 747 // Emit ldr/ldrb/str/strb instruction with given address. 748 void emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, IValueT Rt, 749 const Operand *OpAddress, const TargetInfo &TInfo, 750 const char *InstName); 751 752 // Emit ldrh/ldrd/strh/strd instruction with given address using encoding 3. 753 void emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, IValueT Rt, 754 const Operand *OpAddress, const TargetInfo &TInfo, 755 const char *InstName); 756 757 // Emit cccc00011xxlnnnndddd11111001tttt where cccc=Cond, xx encodes type 758 // size, l=IsLoad, nnnn=Rn (as defined by OpAddress), and tttt=Rt. 759 void emitMemExOp(CondARM32::Cond, Type Ty, bool IsLoad, const Operand *OpRd, 760 IValueT Rt, const Operand *OpAddress, 761 const TargetInfo &TInfo, const char *InstName); 762 763 // Pattern cccc100aaaalnnnnrrrrrrrrrrrrrrrr where cccc=Cond, 764 // aaaa<<21=AddressMode, l=IsLoad, nnnn=BaseReg, and 765 // rrrrrrrrrrrrrrrr is bitset of Registers. 766 void emitMultiMemOp(CondARM32::Cond Cond, BlockAddressMode AddressMode, 767 bool IsLoad, IValueT BaseReg, IValueT Registers); 768 769 // Pattern ccccxxxxxDxxxxxxddddxxxxiiiiiiii where cccc=Cond, ddddD=BaseReg, 770 // iiiiiiii=NumConsecRegs, and xxxxx0xxxxxx0000xxxx00000000=Opcode. 771 void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, 772 const Variable *OpBaseReg, SizeT NumConsecRegs); 773 774 // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, ddddD=Sd, 775 // Mmmmm=Dm, and xx0xxxxxxdddd000xxx0x0000=Opcode. 776 void emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Dm); 777 778 // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, Ddddd=Dd, 779 // mmmmM=Sm, and xx0xxxxxxdddd000xxx0x0000=Opcode. 780 void emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Sm); 781 782 // Pattern 111100000D00nnnnddddttttssaammmm | Opcode where Ddddd=Dd, nnnn=Rn, 783 // mmmmm=Rm, tttt=NumDRegs, ElmtSize in {8, 16, 32, 64) and defines ss, and 784 // aa=Align. 785 void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm, 786 DRegListSize NumDRegs, size_t ElmtSize, IValueT Align, 787 const char *InstName); 788 789 // Pattern 111100000D00nnnnddddss00aaaammmm | Opcode where Ddddd=Dd, nnnn=Rn, 790 // mmmmm=Rm, ElmtSize in {8, 16, 32) and defines ss, and aa=Align. 791 void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm, 792 size_t ElmtSize, IValueT Align, const char *InstName); 793 794 // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond, 795 // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm. 796 void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn, 797 IValueT Rm); 798 799 // cccc1110iiiennnntttt1011Njj10000 where cccc=Cond, tttt=Rt, Ndddd=2*Qn=Dn, 800 // iii=Opcode1, jj=Opcode2, Opcode1Opcode2 encodes Index and the 801 // corresponding element size of the vector element, and e=IsExtract. 802 void emitInsertExtractInt(CondARM32::Cond Cond, const Operand *OpQn, 803 uint32_t Index, const Operand *OpRt, bool IsExtract, 804 const char *InstName); 805 806 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 807 // Assigns Sd the value of Sm. 808 void emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm); 809 810 // Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 811 // mmmm=Rm, ssss=Rs, f=SetFlags and xxxxxxx=Opcode. 812 void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn, 813 IValueT Rm, IValueT Rs, bool SetFlags); 814 815 // Pattern cccc0001101s0000ddddxxxxxtt0mmmm where cccc=Cond, s=SetFlags, 816 // dddd=Rd, mmmm=Rm, tt=Shift, and xxxxx is defined by OpSrc1. OpSrc1 defines 817 // either xxxxx=Imm5, or xxxxx=ssss0 where ssss=Rs. 818 void emitShift(const CondARM32::Cond Cond, 819 const OperandARM32::ShiftKind Shift, const Operand *OpRd, 820 const Operand *OpRm, const Operand *OpSrc1, 821 const bool SetFlags, const char *InstName); 822 823 // Implements various forms of signed/unsigned extend value, using pattern 824 // ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode, 825 // nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm. 826 void emitSignExtend(CondARM32::Cond, IValueT Opcode, const Operand *OpRd, 827 const Operand *OpSrc0, const char *InstName); 828 829 // Implements various forms of vector (SIMD) operations. Implements pattern 830 // 111100100D00nnnndddn00F0NQM0mmmm where Dddd=Dd, Nnnn=Dn, Mmmm=Dm, 831 // Q=UseQRegs, F=IsFloatTy, and Opcode is unioned into the pattern. 832 void emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn, IValueT Dm, 833 bool UseQRegs, bool IsFloatTy); 834 835 // Same as emitSIMDBase above, except ElmtShift=20 and ElmtSize is computed 836 // from ElmtTy. 837 void emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, IValueT Dn, IValueT Dm, 838 bool UseQRegs); 839 840 // Implements various integer forms of vector (SIMD) operations using Q 841 // registers. Implements pattern 111100100D00nnn0ddd000F0N1M0mmm0 where 842 // Dddd=Qd, Nnnn=Qn, Mmmm=Qm, F=IsFloatTy, and Opcode is unioned into the 843 // pattern. 844 void emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd, const Operand *OpQn, 845 const Operand *OpQm, bool IsFloatTy, 846 const char *OpcodeName); 847 848 // Same as emitSIMD above, except ElmtShift=20 and ElmtSize is computed from 849 // ElmtTy. 850 void emitSIMDqqq(IValueT Opcode, Type ElmtTy, const Operand *OpQd, 851 const Operand *OpQn, const Operand *OpQm, 852 const char *OpcodeName); 853 854 // Implements various forms of vector (SIMD) shifts using Q registers. 855 // Implements pattern 111100101Diiiiiidddd010101M1mmmm where Dddd=Qd, Mmmm=Qm, 856 // iiiiii=Imm6, and Opcode is unioned into the pattern. 857 void emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd, 858 const Operand *OpQm, const IValueT Imm6, 859 const char *OpcodeName); 860 861 // Implements various forms of vector (SIMD) casts between (signed and 862 // unsigned) integer and floating point types (f32). Implements pattern 863 // 111100111D11ss11dddd011ooQM0mmmm where Dddd=Qd, Mmmm=Qm, 10=ss, op=00, 1=Q, 864 // and Opcode is unioned into the pattern. 865 void emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd, const Operand *OpQm, 866 const char *CvtName); 867 868 // Pattern cccctttxxxxnnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, 869 // ttt=Instruction type (derived from OpSrc1), iiiiiiiiiiii is derived from 870 // OpSrc1, and xxxx=Opcode. 871 void emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRn, 872 const Operand *OpSrc1, const char *CmpName); 873 874 void emitBranch(Label *L, CondARM32::Cond, bool Link); 875 876 // Returns the offset encoded in the branch instruction Inst. 877 static IOffsetT decodeBranchOffset(IValueT Inst); 878 879 // Implements movw/movt, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii 880 // where cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and 881 // iiiiiiiiiiiiiiii=Imm16. 882 void emitMovwt(CondARM32::Cond Cond, bool IsMovw, const Operand *OpRd, 883 const Operand *OpSrc, const char *MovName); 884 885 // Emit VFP instruction with 3 D registers. 886 void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpDd, 887 const Operand *OpDn, const Operand *OpDm, 888 const char *InstName); 889 890 void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Dn, 891 IValueT Dm); 892 893 // Emit VFP instruction with 3 S registers. 894 void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Sn, 895 IValueT Sm); 896 897 void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpSd, 898 const Operand *OpSn, const Operand *OpSm, 899 const char *InstName); 900 }; 901 902 } // end of namespace ARM32 903 } // end of namespace Ice 904 905 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H 906