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