1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// 2 // 3 // The Subzero Code Generator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief Declares the InstARM32 and OperandARM32 classes and their subclasses. 12 /// 13 /// This represents the machine instructions and operands used for ARM32 code 14 /// selection. 15 /// 16 //===----------------------------------------------------------------------===// 17 18 #ifndef SUBZERO_SRC_ICEINSTARM32_H 19 #define SUBZERO_SRC_ICEINSTARM32_H 20 21 #include "IceConditionCodesARM32.h" 22 #include "IceDefs.h" 23 #include "IceInst.h" 24 #include "IceInstARM32.def" 25 #include "IceOperand.h" 26 #include "IceRegistersARM32.h" 27 28 namespace Ice { 29 namespace ARM32 { 30 31 /// Encoding of an ARM 32-bit instruction. 32 using IValueT = uint32_t; 33 34 /// An Offset value (+/-) used in an ARM 32-bit instruction. 35 using IOffsetT = int32_t; 36 37 class TargetARM32; 38 39 /// OperandARM32 extends the Operand hierarchy. Its subclasses are 40 /// OperandARM32Mem and OperandARM32Flex. 41 class OperandARM32 : public Operand { 42 OperandARM32() = delete; 43 OperandARM32(const OperandARM32 &) = delete; 44 OperandARM32 &operator=(const OperandARM32 &) = delete; 45 46 public: 47 enum OperandKindARM32 { 48 k__Start = Operand::kTarget, 49 kMem, 50 kShAmtImm, 51 kFlexStart, 52 kFlexImm = kFlexStart, 53 kFlexFpImm, 54 kFlexFpZero, 55 kFlexReg, 56 kFlexEnd = kFlexReg 57 }; 58 59 enum ShiftKind { 60 kNoShift = -1, 61 #define X(enum, emit) enum, 62 ICEINSTARM32SHIFT_TABLE 63 #undef X 64 }; 65 66 using Operand::dump; 67 void dump(const Cfg *, Ostream &Str) const override { 68 if (BuildDefs::dump()) 69 Str << "<OperandARM32>"; 70 } 71 72 protected: 73 OperandARM32(OperandKindARM32 Kind, Type Ty) 74 : Operand(static_cast<OperandKind>(Kind), Ty) {} 75 }; 76 77 /// OperandARM32Mem represents a memory operand in any of the various ARM32 78 /// addressing modes. 79 class OperandARM32Mem : public OperandARM32 { 80 OperandARM32Mem() = delete; 81 OperandARM32Mem(const OperandARM32Mem &) = delete; 82 OperandARM32Mem &operator=(const OperandARM32Mem &) = delete; 83 84 public: 85 /// Memory operand addressing mode. 86 /// The enum value also carries the encoding. 87 // TODO(jvoung): unify with the assembler. 88 enum AddrMode { 89 // bit encoding P U 0 W 90 Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base) 91 PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback 92 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback 93 NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base) 94 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback 95 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback 96 }; 97 98 /// Provide two constructors. 99 /// NOTE: The Variable-typed operands have to be registers. 100 /// 101 /// (1) Reg + Imm. The Immediate actually has a limited number of bits 102 /// for encoding, so check canHoldOffset first. It cannot handle general 103 /// Constant operands like ConstantRelocatable, since a relocatable can 104 /// potentially take up too many bits. 105 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 106 ConstantInteger32 *ImmOffset, 107 AddrMode Mode = Offset) { 108 return new (Func->allocate<OperandARM32Mem>()) 109 OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode); 110 } 111 /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that 112 /// this mode is disallowed in the NaCl sandbox. 113 static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 114 Variable *Index, ShiftKind ShiftOp = kNoShift, 115 uint16_t ShiftAmt = 0, 116 AddrMode Mode = Offset) { 117 return new (Func->allocate<OperandARM32Mem>()) 118 OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode); 119 } 120 Variable *getBase() const { return Base; } 121 ConstantInteger32 *getOffset() const { return ImmOffset; } 122 Variable *getIndex() const { return Index; } 123 ShiftKind getShiftOp() const { return ShiftOp; } 124 uint16_t getShiftAmt() const { return ShiftAmt; } 125 AddrMode getAddrMode() const { return Mode; } 126 127 bool isRegReg() const { return Index != nullptr; } 128 bool isNegAddrMode() const { 129 // Positive address modes have the "U" bit set, and negative modes don't. 130 static_assert((PreIndex & (4 << 21)) != 0, 131 "Positive addr modes should have U bit set."); 132 static_assert((NegPreIndex & (4 << 21)) == 0, 133 "Negative addr modes should have U bit clear."); 134 return (Mode & (4 << 21)) == 0; 135 } 136 137 void emit(const Cfg *Func) const override; 138 using OperandARM32::dump; 139 void dump(const Cfg *Func, Ostream &Str) const override; 140 141 static bool classof(const Operand *Operand) { 142 return Operand->getKind() == static_cast<OperandKind>(kMem); 143 } 144 145 /// Return true if a load/store instruction for an element of type Ty can 146 /// encode the Offset directly in the immediate field of the 32-bit ARM 147 /// instruction. For some types, if the load is Sign extending, then the range 148 /// is reduced. 149 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); 150 151 private: 152 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, 153 ConstantInteger32 *ImmOffset, AddrMode Mode); 154 OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index, 155 ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode); 156 157 Variable *Base; 158 ConstantInteger32 *ImmOffset; 159 Variable *Index; 160 ShiftKind ShiftOp; 161 uint16_t ShiftAmt; 162 AddrMode Mode; 163 }; 164 165 /// OperandARM32ShAmtImm represents an Immediate that is used in one of the 166 /// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate 167 /// shifted registers. 168 class OperandARM32ShAmtImm : public OperandARM32 { 169 OperandARM32ShAmtImm() = delete; 170 OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete; 171 OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete; 172 173 public: 174 static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) { 175 return new (Func->allocate<OperandARM32ShAmtImm>()) 176 OperandARM32ShAmtImm(ShAmt); 177 } 178 179 static bool classof(const Operand *Operand) { 180 return Operand->getKind() == static_cast<OperandKind>(kShAmtImm); 181 } 182 183 void emit(const Cfg *Func) const override; 184 using OperandARM32::dump; 185 void dump(const Cfg *Func, Ostream &Str) const override; 186 187 uint32_t getShAmtImm() const { return ShAmt->getValue(); } 188 189 private: 190 explicit OperandARM32ShAmtImm(ConstantInteger32 *SA); 191 192 const ConstantInteger32 *const ShAmt; 193 }; 194 195 /// OperandARM32Flex represent the "flexible second operand" for data-processing 196 /// instructions. It can be a rotatable 8-bit constant, or a register with an 197 /// optional shift operand. The shift amount can even be a third register. 198 class OperandARM32Flex : public OperandARM32 { 199 OperandARM32Flex() = delete; 200 OperandARM32Flex(const OperandARM32Flex &) = delete; 201 OperandARM32Flex &operator=(const OperandARM32Flex &) = delete; 202 203 public: 204 static bool classof(const Operand *Operand) { 205 return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() && 206 Operand->getKind() <= static_cast<OperandKind>(kFlexEnd); 207 } 208 209 protected: 210 OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {} 211 }; 212 213 /// Rotated immediate variant. 214 class OperandARM32FlexImm : public OperandARM32Flex { 215 OperandARM32FlexImm() = delete; 216 OperandARM32FlexImm(const OperandARM32FlexImm &) = delete; 217 OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete; 218 219 public: 220 /// Immed_8 rotated by an even number of bits (2 * RotateAmt). 221 static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm, 222 uint32_t RotateAmt); 223 224 void emit(const Cfg *Func) const override; 225 using OperandARM32::dump; 226 void dump(const Cfg *Func, Ostream &Str) const override; 227 228 static bool classof(const Operand *Operand) { 229 return Operand->getKind() == static_cast<OperandKind>(kFlexImm); 230 } 231 232 /// Return true if the Immediate can fit in the ARM flexible operand. Fills in 233 /// the out-params RotateAmt and Immed_8 if Immediate fits. 234 static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt, 235 uint32_t *Immed_8); 236 237 uint32_t getImm() const { return Imm; } 238 uint32_t getRotateAmt() const { return RotateAmt; } 239 240 private: 241 OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); 242 243 uint32_t Imm; 244 uint32_t RotateAmt; 245 }; 246 247 /// Modified Floating-point constant. 248 class OperandARM32FlexFpImm : public OperandARM32Flex { 249 OperandARM32FlexFpImm() = delete; 250 OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete; 251 OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete; 252 253 public: 254 static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty, 255 uint32_t ModifiedImm) { 256 return new (Func->allocate<OperandARM32FlexFpImm>()) 257 OperandARM32FlexFpImm(Func, Ty, ModifiedImm); 258 } 259 260 void emit(const Cfg *Func) const override; 261 using OperandARM32::dump; 262 void dump(const Cfg *Func, Ostream &Str) const override; 263 264 static bool classof(const Operand *Operand) { 265 return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm); 266 } 267 268 static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm); 269 270 uint32_t getModifiedImm() const { return ModifiedImm; } 271 272 private: 273 OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm); 274 275 const uint32_t ModifiedImm; 276 }; 277 278 /// An operand for representing the 0.0 immediate in vcmp. 279 class OperandARM32FlexFpZero : public OperandARM32Flex { 280 OperandARM32FlexFpZero() = delete; 281 OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete; 282 OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete; 283 284 public: 285 static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) { 286 return new (Func->allocate<OperandARM32FlexFpZero>()) 287 OperandARM32FlexFpZero(Func, Ty); 288 } 289 290 void emit(const Cfg *Func) const override; 291 using OperandARM32::dump; 292 void dump(const Cfg *Func, Ostream &Str) const override; 293 294 static bool classof(const Operand *Operand) { 295 return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero); 296 } 297 298 private: 299 OperandARM32FlexFpZero(Cfg *Func, Type Ty); 300 }; 301 302 /// Shifted register variant. 303 class OperandARM32FlexReg : public OperandARM32Flex { 304 OperandARM32FlexReg() = delete; 305 OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; 306 OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; 307 308 public: 309 /// Register with immediate/reg shift amount and shift operation. 310 static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg, 311 ShiftKind ShiftOp, Operand *ShiftAmt) { 312 return new (Func->allocate<OperandARM32FlexReg>()) 313 OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt); 314 } 315 316 void emit(const Cfg *Func) const override; 317 using OperandARM32::dump; 318 void dump(const Cfg *Func, Ostream &Str) const override; 319 320 static bool classof(const Operand *Operand) { 321 return Operand->getKind() == static_cast<OperandKind>(kFlexReg); 322 } 323 324 Variable *getReg() const { return Reg; } 325 ShiftKind getShiftOp() const { return ShiftOp; } 326 /// ShiftAmt can represent an immediate or a register. 327 Operand *getShiftAmt() const { return ShiftAmt; } 328 329 private: 330 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, 331 Operand *ShiftAmt); 332 333 Variable *Reg; 334 ShiftKind ShiftOp; 335 Operand *ShiftAmt; 336 }; 337 338 /// StackVariable represents a Var that isn't assigned a register (stack-only). 339 /// It is assigned a stack slot, but the slot's offset may be too large to 340 /// represent in the native addressing mode, and so it has a separate base 341 /// register from SP/FP, where the offset from that base register is then in 342 /// range. 343 class StackVariable final : public Variable { 344 StackVariable() = delete; 345 StackVariable(const StackVariable &) = delete; 346 StackVariable &operator=(const StackVariable &) = delete; 347 348 public: 349 static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) { 350 return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index); 351 } 352 constexpr static auto StackVariableKind = 353 static_cast<OperandKind>(kVariable_Target); 354 static bool classof(const Operand *Operand) { 355 return Operand->getKind() == StackVariableKind; 356 } 357 void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; } 358 RegNumT getBaseRegNum() const override { return BaseRegNum; } 359 // Inherit dump() and emit() from Variable. 360 361 private: 362 StackVariable(const Cfg *Func, Type Ty, SizeT Index) 363 : Variable(Func, StackVariableKind, Ty, Index) {} 364 RegNumT BaseRegNum; 365 }; 366 367 /// Base class for ARM instructions. While most ARM instructions can be 368 /// conditionally executed, a few of them are not predicable (halt, memory 369 /// barriers, etc.). 370 class InstARM32 : public InstTarget { 371 InstARM32() = delete; 372 InstARM32(const InstARM32 &) = delete; 373 InstARM32 &operator=(const InstARM32 &) = delete; 374 375 public: 376 // Defines form that assembly instruction should be synthesized. 377 enum EmitForm { Emit_Text, Emit_Binary }; 378 379 enum InstKindARM32 { 380 k__Start = Inst::Target, 381 Adc, 382 Add, 383 And, 384 Asr, 385 Bic, 386 Br, 387 Call, 388 Clz, 389 Cmn, 390 Cmp, 391 Dmb, 392 Eor, 393 Extract, 394 Insert, 395 Label, 396 Ldr, 397 Ldrex, 398 Lsl, 399 Lsr, 400 Nop, 401 Mla, 402 Mls, 403 Mov, 404 Movt, 405 Movw, 406 Mul, 407 Mvn, 408 Orr, 409 Pop, 410 Push, 411 Rbit, 412 Ret, 413 Rev, 414 Rsb, 415 Rsc, 416 Sbc, 417 Sdiv, 418 Str, 419 Strex, 420 Sub, 421 Sxt, 422 Trap, 423 Tst, 424 Udiv, 425 Umull, 426 Uxt, 427 Vabs, 428 Vadd, 429 Vand, 430 Vbsl, 431 Vceq, 432 Vcge, 433 Vcgt, 434 Vcmp, 435 Vcvt, 436 Vdiv, 437 Vdup, 438 Veor, 439 Vldr1d, 440 Vldr1q, 441 Vmla, 442 Vmlap, 443 Vmls, 444 Vmovl, 445 Vmovh, 446 Vmovhl, 447 Vmovlh, 448 Vmrs, 449 Vmul, 450 Vmulh, 451 Vmvn, 452 Vneg, 453 Vorr, 454 Vqadd, 455 Vqmovn2, 456 Vqsub, 457 Vshl, 458 Vshr, 459 Vsqrt, 460 Vstr1, 461 Vsub, 462 Vzip 463 }; 464 465 static constexpr size_t InstSize = sizeof(uint32_t); 466 467 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); 468 469 /// Called inside derived methods emit() to communicate that multiple 470 /// instructions are being generated. Used by emitIAS() methods to 471 /// generate textual fixups for instructions that are not yet 472 /// implemented. 473 void startNextInst(const Cfg *Func) const; 474 475 /// FPSign is used for certain vector instructions (particularly, right 476 /// shifts) that require an operand sign specification. 477 enum FPSign { 478 FS_None, 479 FS_Signed, 480 FS_Unsigned, 481 }; 482 /// Shared emit routines for common forms of instructions. 483 /// @{ 484 static void emitThreeAddrFP(const char *Opcode, FPSign Sign, 485 const InstARM32 *Instr, const Cfg *Func, 486 Type OpType); 487 static void emitFourAddrFP(const char *Opcode, FPSign Sign, 488 const InstARM32 *Instr, const Cfg *Func); 489 /// @} 490 491 void dump(const Cfg *Func) const override; 492 493 void emitIAS(const Cfg *Func) const override; 494 495 protected: 496 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) 497 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} 498 499 static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) { 500 return Instr->getKind() == static_cast<InstKind>(MyKind); 501 } 502 503 // Generates text of assembly instruction using method emit(), and then adds 504 // to the assembly buffer as a Fixup. 505 void emitUsingTextFixup(const Cfg *Func) const; 506 }; 507 508 /// A predicable ARM instruction. 509 class InstARM32Pred : public InstARM32 { 510 InstARM32Pred() = delete; 511 InstARM32Pred(const InstARM32Pred &) = delete; 512 InstARM32Pred &operator=(const InstARM32Pred &) = delete; 513 514 public: 515 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest, 516 CondARM32::Cond Predicate) 517 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {} 518 519 CondARM32::Cond getPredicate() const { return Predicate; } 520 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; } 521 522 static const char *predString(CondARM32::Cond Predicate); 523 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; 524 525 /// Shared emit routines for common forms of instructions. 526 static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr, 527 const Cfg *Func, bool NeedsWidthSuffix); 528 static void emitUnaryopFP(const char *Opcode, FPSign Sign, 529 const InstARM32Pred *Instr, const Cfg *Func); 530 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr, 531 const Cfg *Func); 532 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr, 533 const Cfg *Func, bool SetFlags); 534 static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr, 535 const Cfg *Func); 536 static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr, 537 const Cfg *Func); 538 539 protected: 540 CondARM32::Cond Predicate; 541 }; 542 543 template <typename StreamType> 544 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { 545 Stream << InstARM32Pred::predString(Predicate); 546 return Stream; 547 } 548 549 /// Instructions of the form x := op(y). 550 template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix> 551 class InstARM32UnaryopGPR : public InstARM32Pred { 552 InstARM32UnaryopGPR() = delete; 553 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; 554 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; 555 556 public: 557 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 558 CondARM32::Cond Predicate) { 559 return new (Func->allocate<InstARM32UnaryopGPR>()) 560 InstARM32UnaryopGPR(Func, Dest, Src, Predicate); 561 } 562 void emit(const Cfg *Func) const override { 563 if (!BuildDefs::dump()) 564 return; 565 emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix); 566 } 567 void emitIAS(const Cfg *Func) const override; 568 void dump(const Cfg *Func) const override { 569 if (!BuildDefs::dump()) 570 return; 571 Ostream &Str = Func->getContext()->getStrDump(); 572 dumpDest(Func); 573 Str << " = "; 574 dumpOpcodePred(Str, Opcode, getDest()->getType()); 575 Str << " "; 576 dumpSources(Func); 577 } 578 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 579 580 private: 581 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, 582 CondARM32::Cond Predicate) 583 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 584 addSource(Src); 585 } 586 587 static const char *Opcode; 588 }; 589 590 /// Instructions of the form x := op(y), for vector/FP. 591 template <InstARM32::InstKindARM32 K> 592 class InstARM32UnaryopFP : public InstARM32Pred { 593 InstARM32UnaryopFP() = delete; 594 InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete; 595 InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete; 596 597 public: 598 static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src, 599 CondARM32::Cond Predicate) { 600 return new (Func->allocate<InstARM32UnaryopFP>()) 601 InstARM32UnaryopFP(Func, Dest, Src, Predicate); 602 } 603 void emit(const Cfg *Func) const override { 604 if (!BuildDefs::dump()) 605 return; 606 emitUnaryopFP(Opcode, Sign, this, Func); 607 } 608 void emitIAS(const Cfg *Func) const override; 609 void dump(const Cfg *Func) const override { 610 if (!BuildDefs::dump()) 611 return; 612 Ostream &Str = Func->getContext()->getStrDump(); 613 dumpDest(Func); 614 Str << " = "; 615 dumpOpcodePred(Str, Opcode, getDest()->getType()); 616 Str << " "; 617 dumpSources(Func); 618 } 619 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 620 621 protected: 622 InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src, 623 CondARM32::Cond Predicate) 624 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 625 addSource(Src); 626 } 627 628 FPSign Sign = FS_None; 629 static const char *Opcode; 630 }; 631 632 template <InstARM32::InstKindARM32 K> 633 class InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> { 634 InstARM32UnaryopSignAwareFP() = delete; 635 InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete; 636 InstARM32UnaryopSignAwareFP & 637 operator=(const InstARM32UnaryopSignAwareFP &) = delete; 638 639 public: 640 static InstARM32UnaryopSignAwareFP * 641 create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) { 642 return new (Func->allocate<InstARM32UnaryopSignAwareFP>()) 643 InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate); 644 } 645 void emitIAS(const Cfg *Func) const override; 646 void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; } 647 648 private: 649 InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src, 650 CondARM32::Cond Predicate) 651 : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {} 652 }; 653 654 /// Instructions of the form x := x op y. 655 template <InstARM32::InstKindARM32 K> 656 class InstARM32TwoAddrGPR : public InstARM32Pred { 657 InstARM32TwoAddrGPR() = delete; 658 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; 659 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; 660 661 public: 662 /// Dest must be a register. 663 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 664 CondARM32::Cond Predicate) { 665 return new (Func->allocate<InstARM32TwoAddrGPR>()) 666 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate); 667 } 668 void emit(const Cfg *Func) const override { 669 if (!BuildDefs::dump()) 670 return; 671 emitTwoAddr(Opcode, this, Func); 672 } 673 void emitIAS(const Cfg *Func) const override; 674 void dump(const Cfg *Func) const override { 675 if (!BuildDefs::dump()) 676 return; 677 Ostream &Str = Func->getContext()->getStrDump(); 678 dumpDest(Func); 679 Str << " = "; 680 dumpOpcodePred(Str, Opcode, getDest()->getType()); 681 Str << " "; 682 dumpSources(Func); 683 } 684 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 685 686 private: 687 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, 688 CondARM32::Cond Predicate) 689 : InstARM32Pred(Func, K, 2, Dest, Predicate) { 690 addSource(Dest); 691 addSource(Src); 692 } 693 694 static const char *Opcode; 695 }; 696 697 /// Base class for load instructions. 698 template <InstARM32::InstKindARM32 K> 699 class InstARM32LoadBase : public InstARM32Pred { 700 InstARM32LoadBase() = delete; 701 InstARM32LoadBase(const InstARM32LoadBase &) = delete; 702 InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete; 703 704 public: 705 static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source, 706 CondARM32::Cond Predicate) { 707 return new (Func->allocate<InstARM32LoadBase>()) 708 InstARM32LoadBase(Func, Dest, Source, Predicate); 709 } 710 void emit(const Cfg *Func) const override; 711 void emitIAS(const Cfg *Func) const override; 712 void dump(const Cfg *Func) const override { 713 if (!BuildDefs::dump()) 714 return; 715 Ostream &Str = Func->getContext()->getStrDump(); 716 dumpOpcodePred(Str, Opcode, getDest()->getType()); 717 Str << " "; 718 dumpDest(Func); 719 Str << ", "; 720 dumpSources(Func); 721 } 722 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 723 724 private: 725 InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source, 726 CondARM32::Cond Predicate) 727 : InstARM32Pred(Func, K, 1, Dest, Predicate) { 728 addSource(Source); 729 } 730 731 static const char *Opcode; 732 }; 733 734 /// Instructions of the form x := y op z. May have the side-effect of setting 735 /// status flags. 736 template <InstARM32::InstKindARM32 K> 737 class InstARM32ThreeAddrGPR : public InstARM32Pred { 738 InstARM32ThreeAddrGPR() = delete; 739 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; 740 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; 741 742 public: 743 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1 744 /// must be registers. 745 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, 746 Variable *Src0, Operand *Src1, 747 CondARM32::Cond Predicate, 748 bool SetFlags = false) { 749 return new (Func->allocate<InstARM32ThreeAddrGPR>()) 750 InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags); 751 } 752 void emit(const Cfg *Func) const override { 753 if (!BuildDefs::dump()) 754 return; 755 emitThreeAddr(Opcode, this, Func, SetFlags); 756 } 757 void emitIAS(const Cfg *Func) const override; 758 void dump(const Cfg *Func) const override { 759 if (!BuildDefs::dump()) 760 return; 761 Ostream &Str = Func->getContext()->getStrDump(); 762 dumpDest(Func); 763 Str << " = "; 764 dumpOpcodePred(Str, Opcode, getDest()->getType()); 765 Str << (SetFlags ? ".s " : " "); 766 dumpSources(Func); 767 } 768 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 769 770 private: 771 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, 772 Operand *Src1, CondARM32::Cond Predicate, bool SetFlags) 773 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { 774 HasSideEffects = SetFlags; 775 addSource(Src0); 776 addSource(Src1); 777 } 778 779 static const char *Opcode; 780 bool SetFlags; 781 }; 782 783 /// Instructions of the form x := y op z, for vector/FP. We leave these as 784 /// unconditional: "ARM deprecates the conditional execution of any instruction 785 /// encoding provided by the Advanced SIMD Extension that is not also provided 786 /// by the floating-point (VFP) extension". They do not set flags. 787 template <InstARM32::InstKindARM32 K> 788 class InstARM32ThreeAddrFP : public InstARM32 { 789 InstARM32ThreeAddrFP() = delete; 790 InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete; 791 InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete; 792 793 public: 794 /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything 795 /// must be a register. 796 static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0, 797 Variable *Src1) { 798 return new (Func->allocate<InstARM32ThreeAddrFP>()) 799 InstARM32ThreeAddrFP(Func, Dest, Src0, Src1); 800 } 801 void emit(const Cfg *Func) const override { 802 if (!BuildDefs::dump()) 803 return; 804 const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType(); 805 emitThreeAddrFP(Opcode, Sign, this, Func, OpType); 806 } 807 void emitIAS(const Cfg *Func) const override; 808 void dump(const Cfg *Func) const override { 809 if (!BuildDefs::dump()) 810 return; 811 Ostream &Str = Func->getContext()->getStrDump(); 812 dumpDest(Func); 813 const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType(); 814 Str << " = " << Opcode << "." << OpType << " "; 815 dumpSources(Func); 816 } 817 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 818 819 protected: 820 FPSign Sign = FS_None; 821 822 InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1) 823 : InstARM32(Func, K, 2, Dest) { 824 addSource(Src0); 825 addSource(Src1); 826 } 827 828 static const char *Opcode; 829 830 private: 831 static constexpr bool isVectorCompare() { 832 return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge; 833 } 834 }; 835 836 template <InstARM32::InstKindARM32 K> 837 class InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> { 838 InstARM32ThreeAddrSignAwareFP() = delete; 839 InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete; 840 InstARM32ThreeAddrSignAwareFP & 841 operator=(const InstARM32ThreeAddrSignAwareFP &) = delete; 842 843 public: 844 /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything 845 /// must be a register. 846 static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest, 847 Variable *Src0, Variable *Src1) { 848 return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>()) 849 InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1); 850 } 851 852 static InstARM32ThreeAddrSignAwareFP * 853 create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) { 854 return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>()) 855 InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1); 856 } 857 858 void emitIAS(const Cfg *Func) const override; 859 void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; } 860 861 private: 862 InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0, 863 Operand *Src1) 864 : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {} 865 }; 866 867 /// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate. 868 template <InstARM32::InstKindARM32 K> 869 class InstARM32FourAddrGPR : public InstARM32Pred { 870 InstARM32FourAddrGPR() = delete; 871 InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete; 872 InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete; 873 874 public: 875 // Every operand must be a register. 876 static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0, 877 Variable *Src1, Variable *Src2, 878 CondARM32::Cond Predicate) { 879 return new (Func->allocate<InstARM32FourAddrGPR>()) 880 InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate); 881 } 882 void emit(const Cfg *Func) const override { 883 if (!BuildDefs::dump()) 884 return; 885 emitFourAddr(Opcode, this, Func); 886 } 887 void emitIAS(const Cfg *Func) const override; 888 void dump(const Cfg *Func) const override { 889 if (!BuildDefs::dump()) 890 return; 891 Ostream &Str = Func->getContext()->getStrDump(); 892 dumpDest(Func); 893 Str << " = "; 894 dumpOpcodePred(Str, Opcode, getDest()->getType()); 895 Str << " "; 896 dumpSources(Func); 897 } 898 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 899 900 private: 901 InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, 902 Variable *Src1, Variable *Src2, 903 CondARM32::Cond Predicate) 904 : InstARM32Pred(Func, K, 3, Dest, Predicate) { 905 addSource(Src0); 906 addSource(Src1); 907 addSource(Src2); 908 } 909 910 static const char *Opcode; 911 }; 912 913 /// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate. 914 /// We leave these as unconditional: "ARM deprecates the conditional execution 915 /// of any instruction encoding provided by the Advanced SIMD Extension that is 916 /// not also provided by the floating-point (VFP) extension". They do not set 917 /// flags. 918 template <InstARM32::InstKindARM32 K> 919 class InstARM32FourAddrFP : public InstARM32 { 920 InstARM32FourAddrFP() = delete; 921 InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete; 922 InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete; 923 924 public: 925 // Every operand must be a register. 926 static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0, 927 Variable *Src1) { 928 return new (Func->allocate<InstARM32FourAddrFP>()) 929 InstARM32FourAddrFP(Func, Dest, Src0, Src1); 930 } 931 void emit(const Cfg *Func) const override { 932 if (!BuildDefs::dump()) 933 return; 934 emitFourAddrFP(Opcode, Sign, this, Func); 935 } 936 void emitIAS(const Cfg *Func) const override; 937 void dump(const Cfg *Func) const override { 938 if (!BuildDefs::dump()) 939 return; 940 Ostream &Str = Func->getContext()->getStrDump(); 941 dumpDest(Func); 942 Str << " = "; 943 Str << Opcode << "." << getDest()->getType() << " "; 944 dumpDest(Func); 945 Str << ", "; 946 dumpSources(Func); 947 } 948 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 949 950 private: 951 InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1) 952 : InstARM32(Func, K, 3, Dest) { 953 addSource(Dest); 954 addSource(Src0); 955 addSource(Src1); 956 } 957 958 FPSign Sign = FS_None; 959 static const char *Opcode; 960 }; 961 962 /// Instructions of the form x cmpop y (setting flags). 963 template <InstARM32::InstKindARM32 K> 964 class InstARM32CmpLike : public InstARM32Pred { 965 InstARM32CmpLike() = delete; 966 InstARM32CmpLike(const InstARM32CmpLike &) = delete; 967 InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete; 968 969 public: 970 static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1, 971 CondARM32::Cond Predicate) { 972 return new (Func->allocate<InstARM32CmpLike>()) 973 InstARM32CmpLike(Func, Src0, Src1, Predicate); 974 } 975 void emit(const Cfg *Func) const override { 976 if (!BuildDefs::dump()) 977 return; 978 emitCmpLike(Opcode, this, Func); 979 } 980 void emitIAS(const Cfg *Func) const override; 981 void dump(const Cfg *Func) const override { 982 if (!BuildDefs::dump()) 983 return; 984 Ostream &Str = Func->getContext()->getStrDump(); 985 dumpOpcodePred(Str, Opcode, getSrc(0)->getType()); 986 Str << " "; 987 dumpSources(Func); 988 } 989 static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 990 991 private: 992 InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1, 993 CondARM32::Cond Predicate) 994 : InstARM32Pred(Func, K, 2, nullptr, Predicate) { 995 HasSideEffects = true; 996 addSource(Src0); 997 addSource(Src1); 998 } 999 1000 static const char *Opcode; 1001 }; 1002 1003 using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>; 1004 using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>; 1005 using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>; 1006 using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>; 1007 using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>; 1008 using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>; 1009 using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>; 1010 using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>; 1011 using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>; 1012 using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>; 1013 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>; 1014 using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>; 1015 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>; 1016 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>; 1017 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>; 1018 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>; 1019 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>; 1020 using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>; 1021 using InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>; 1022 using InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>; 1023 using InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>; 1024 using InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>; 1025 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>; 1026 using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>; 1027 using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>; 1028 using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>; 1029 using InstARM32Vmovl = InstARM32ThreeAddrFP<InstARM32::Vmovl>; 1030 using InstARM32Vmovh = InstARM32ThreeAddrFP<InstARM32::Vmovh>; 1031 using InstARM32Vmovhl = InstARM32ThreeAddrFP<InstARM32::Vmovhl>; 1032 using InstARM32Vmovlh = InstARM32ThreeAddrFP<InstARM32::Vmovlh>; 1033 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>; 1034 using InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>; 1035 using InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>; 1036 using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>; 1037 using InstARM32Vqadd = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>; 1038 using InstARM32Vqsub = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>; 1039 using InstARM32Vqmovn2 = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>; 1040 using InstARM32Vmulh = InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>; 1041 using InstARM32Vmlap = InstARM32ThreeAddrFP<InstARM32::Vmlap>; 1042 using InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>; 1043 using InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>; 1044 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>; 1045 using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>; 1046 using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>; 1047 using InstARM32Vldr1d = InstARM32LoadBase<InstARM32::Vldr1d>; 1048 using InstARM32Vldr1q = InstARM32LoadBase<InstARM32::Vldr1q>; 1049 using InstARM32Vzip = InstARM32ThreeAddrFP<InstARM32::Vzip>; 1050 /// MovT leaves the bottom bits alone so dest is also a source. This helps 1051 /// indicate that a previous MovW setting dest is not dead code. 1052 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>; 1053 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>; 1054 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>; 1055 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>; 1056 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>; 1057 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>; 1058 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand 1059 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't 1060 // using that for now, so just model as a Unaryop. 1061 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>; 1062 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>; 1063 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>; 1064 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>; 1065 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>; 1066 using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>; 1067 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>; 1068 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>; 1069 1070 // InstARM32Label represents an intra-block label that is the target of an 1071 // intra-block branch. The offset between the label and the branch must be fit 1072 // in the instruction immediate (considered "near"). 1073 class InstARM32Label : public InstARM32 { 1074 InstARM32Label() = delete; 1075 InstARM32Label(const InstARM32Label &) = delete; 1076 InstARM32Label &operator=(const InstARM32Label &) = delete; 1077 1078 public: 1079 static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) { 1080 return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target); 1081 } 1082 uint32_t getEmitInstCount() const override { return 0; } 1083 GlobalString getLabelName() const { return Name; } 1084 SizeT getNumber() const { return Number; } 1085 void emit(const Cfg *Func) const override; 1086 void emitIAS(const Cfg *Func) const override; 1087 void dump(const Cfg *Func) const override; 1088 void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; } 1089 1090 private: 1091 InstARM32Label(Cfg *Func, TargetARM32 *Target); 1092 1093 RelocOffset *OffsetReloc = nullptr; 1094 SizeT Number; // used for unique label generation. 1095 GlobalString Name; 1096 }; 1097 1098 /// Direct branch instruction. 1099 class InstARM32Br : public InstARM32Pred { 1100 InstARM32Br() = delete; 1101 InstARM32Br(const InstARM32Br &) = delete; 1102 InstARM32Br &operator=(const InstARM32Br &) = delete; 1103 1104 public: 1105 /// Create a conditional branch to one of two nodes. 1106 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, 1107 CfgNode *TargetFalse, CondARM32::Cond Predicate) { 1108 assert(Predicate != CondARM32::AL); 1109 constexpr InstARM32Label *NoLabel = nullptr; 1110 return new (Func->allocate<InstARM32Br>()) 1111 InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate); 1112 } 1113 /// Create an unconditional branch to a node. 1114 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { 1115 constexpr CfgNode *NoCondTarget = nullptr; 1116 constexpr InstARM32Label *NoLabel = nullptr; 1117 return new (Func->allocate<InstARM32Br>()) 1118 InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL); 1119 } 1120 /// Create a non-terminator conditional branch to a node, with a fallthrough 1121 /// to the next instruction in the current node. This is used for switch 1122 /// lowering. 1123 static InstARM32Br *create(Cfg *Func, CfgNode *Target, 1124 CondARM32::Cond Predicate) { 1125 assert(Predicate != CondARM32::AL); 1126 constexpr CfgNode *NoUncondTarget = nullptr; 1127 constexpr InstARM32Label *NoLabel = nullptr; 1128 return new (Func->allocate<InstARM32Br>()) 1129 InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate); 1130 } 1131 // Create a conditional intra-block branch (or unconditional, if 1132 // Condition==AL) to a label in the current block. 1133 static InstARM32Br *create(Cfg *Func, InstARM32Label *Label, 1134 CondARM32::Cond Predicate) { 1135 constexpr CfgNode *NoCondTarget = nullptr; 1136 constexpr CfgNode *NoUncondTarget = nullptr; 1137 return new (Func->allocate<InstARM32Br>()) 1138 InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate); 1139 } 1140 const CfgNode *getTargetTrue() const { return TargetTrue; } 1141 const CfgNode *getTargetFalse() const { return TargetFalse; } 1142 bool optimizeBranch(const CfgNode *NextNode); 1143 uint32_t getEmitInstCount() const override { 1144 uint32_t Sum = 0; 1145 if (Label) 1146 ++Sum; 1147 if (getTargetTrue()) 1148 ++Sum; 1149 if (getTargetFalse()) 1150 ++Sum; 1151 return Sum; 1152 } 1153 bool isUnconditionalBranch() const override { 1154 return getPredicate() == CondARM32::AL; 1155 } 1156 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 1157 void emit(const Cfg *Func) const override; 1158 void emitIAS(const Cfg *Func) const override; 1159 void dump(const Cfg *Func) const override; 1160 static bool classof(const Inst *Instr) { return isClassof(Instr, Br); } 1161 1162 private: 1163 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 1164 const InstARM32Label *Label, CondARM32::Cond Predicate); 1165 1166 const CfgNode *TargetTrue; 1167 const CfgNode *TargetFalse; 1168 const InstARM32Label *Label; // Intra-block branch target 1169 }; 1170 1171 /// Call instruction (bl/blx). Arguments should have already been pushed. 1172 /// Technically bl and the register form of blx can be predicated, but we'll 1173 /// leave that out until needed. 1174 class InstARM32Call : public InstARM32 { 1175 InstARM32Call() = delete; 1176 InstARM32Call(const InstARM32Call &) = delete; 1177 InstARM32Call &operator=(const InstARM32Call &) = delete; 1178 1179 public: 1180 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 1181 return new (Func->allocate<InstARM32Call>()) 1182 InstARM32Call(Func, Dest, CallTarget); 1183 } 1184 Operand *getCallTarget() const { return getSrc(0); } 1185 void emit(const Cfg *Func) const override; 1186 void emitIAS(const Cfg *Func) const override; 1187 void dump(const Cfg *Func) const override; 1188 static bool classof(const Inst *Instr) { return isClassof(Instr, Call); } 1189 1190 private: 1191 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); 1192 }; 1193 1194 class InstARM32RegisterStackOp : public InstARM32 { 1195 InstARM32RegisterStackOp() = delete; 1196 InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete; 1197 InstARM32RegisterStackOp & 1198 operator=(const InstARM32RegisterStackOp &) = delete; 1199 1200 public: 1201 void emit(const Cfg *Func) const override; 1202 void emitIAS(const Cfg *Func) const override; 1203 void dump(const Cfg *Func) const override; 1204 1205 protected: 1206 InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, 1207 Variable *Dest) 1208 : InstARM32(Func, Kind, Maxsrcs, Dest) {} 1209 void emitUsingForm(const Cfg *Func, const EmitForm Form) const; 1210 void emitGPRsAsText(const Cfg *Func) const; 1211 void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg, 1212 SizeT Regcount) const; 1213 void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg, 1214 SizeT RegCount, SizeT InstIndex) const; 1215 virtual const char *getDumpOpcode() const { return getGPROpcode(); } 1216 virtual const char *getGPROpcode() const = 0; 1217 virtual const char *getSRegOpcode() const = 0; 1218 virtual Variable *getStackReg(SizeT Index) const = 0; 1219 virtual SizeT getNumStackRegs() const = 0; 1220 virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form, 1221 const Variable *Reg) const = 0; 1222 virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form, 1223 IValueT Registers) const = 0; 1224 virtual void emitSRegs(const Cfg *Func, const EmitForm Form, 1225 const Variable *BaseReg, SizeT RegCount) const = 0; 1226 }; 1227 1228 /// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s" 1229 /// regs, but not both. In any case, the list must be sorted. 1230 class InstARM32Pop final : public InstARM32RegisterStackOp { 1231 InstARM32Pop() = delete; 1232 InstARM32Pop(const InstARM32Pop &) = delete; 1233 InstARM32Pop &operator=(const InstARM32Pop &) = delete; 1234 1235 public: 1236 static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { 1237 return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); 1238 } 1239 static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); } 1240 1241 private: 1242 InstARM32Pop(Cfg *Func, const VarList &Dests); 1243 virtual const char *getGPROpcode() const final; 1244 virtual const char *getSRegOpcode() const final; 1245 Variable *getStackReg(SizeT Index) const final; 1246 SizeT getNumStackRegs() const final; 1247 void emitSingleGPR(const Cfg *Func, const EmitForm Form, 1248 const Variable *Reg) const final; 1249 void emitMultipleGPRs(const Cfg *Func, const EmitForm Form, 1250 IValueT Registers) const final; 1251 void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg, 1252 SizeT RegCount) const final; 1253 VarList Dests; 1254 }; 1255 1256 /// Pushes a list of registers. Just like Pop (see above), the list may be of 1257 /// GPRs, or VFP "s" registers, but not both. 1258 class InstARM32Push final : public InstARM32RegisterStackOp { 1259 InstARM32Push() = delete; 1260 InstARM32Push(const InstARM32Push &) = delete; 1261 InstARM32Push &operator=(const InstARM32Push &) = delete; 1262 1263 public: 1264 static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { 1265 return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); 1266 } 1267 static bool classof(const Inst *Instr) { return isClassof(Instr, Push); } 1268 1269 private: 1270 InstARM32Push(Cfg *Func, const VarList &Srcs); 1271 const char *getGPROpcode() const final; 1272 const char *getSRegOpcode() const final; 1273 Variable *getStackReg(SizeT Index) const final; 1274 SizeT getNumStackRegs() const final; 1275 void emitSingleGPR(const Cfg *Func, const EmitForm Form, 1276 const Variable *Reg) const final; 1277 void emitMultipleGPRs(const Cfg *Func, const EmitForm Form, 1278 IValueT Registers) const final; 1279 void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg, 1280 SizeT RegCount) const final; 1281 }; 1282 1283 /// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr" 1284 /// register operand, but epilogue lowering will search for a Ret instead of a 1285 /// generic "bx". This instruction also takes a Source operand (for non-void 1286 /// returning functions) for liveness analysis, though a FakeUse before the ret 1287 /// would do just as well. 1288 /// 1289 /// NOTE: Even though "bx" can be predicated, for now leave out the predication 1290 /// since it's not yet known to be useful for Ret. That may complicate finding 1291 /// the terminator instruction if it's not guaranteed to be executed. 1292 class InstARM32Ret : public InstARM32 { 1293 InstARM32Ret() = delete; 1294 InstARM32Ret(const InstARM32Ret &) = delete; 1295 InstARM32Ret &operator=(const InstARM32Ret &) = delete; 1296 1297 public: 1298 static InstARM32Ret *create(Cfg *Func, Variable *LR, 1299 Variable *Source = nullptr) { 1300 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); 1301 } 1302 void emit(const Cfg *Func) const override; 1303 void emitIAS(const Cfg *Func) const override; 1304 void dump(const Cfg *Func) const override; 1305 static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); } 1306 1307 private: 1308 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); 1309 }; 1310 1311 /// Store instruction. It's important for liveness that there is no Dest operand 1312 /// (OperandARM32Mem instead of Dest Variable). 1313 class InstARM32Str final : public InstARM32Pred { 1314 InstARM32Str() = delete; 1315 InstARM32Str(const InstARM32Str &) = delete; 1316 InstARM32Str &operator=(const InstARM32Str &) = delete; 1317 1318 public: 1319 /// Value must be a register. 1320 static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1321 CondARM32::Cond Predicate) { 1322 return new (Func->allocate<InstARM32Str>()) 1323 InstARM32Str(Func, Value, Mem, Predicate); 1324 } 1325 void emit(const Cfg *Func) const override; 1326 void emitIAS(const Cfg *Func) const override; 1327 void dump(const Cfg *Func) const override; 1328 static bool classof(const Inst *Instr) { return isClassof(Instr, Str); } 1329 1330 private: 1331 InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1332 CondARM32::Cond Predicate); 1333 }; 1334 1335 /// Exclusive Store instruction. Like its non-exclusive sibling, it's important 1336 /// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest 1337 /// Variable). 1338 class InstARM32Strex final : public InstARM32Pred { 1339 InstARM32Strex() = delete; 1340 InstARM32Strex(const InstARM32Strex &) = delete; 1341 InstARM32Strex &operator=(const InstARM32Strex &) = delete; 1342 1343 public: 1344 /// Value must be a register. 1345 static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value, 1346 OperandARM32Mem *Mem, 1347 CondARM32::Cond Predicate) { 1348 return new (Func->allocate<InstARM32Strex>()) 1349 InstARM32Strex(Func, Dest, Value, Mem, Predicate); 1350 } 1351 void emit(const Cfg *Func) const override; 1352 void emitIAS(const Cfg *Func) const override; 1353 void dump(const Cfg *Func) const override; 1354 static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); } 1355 1356 private: 1357 InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value, 1358 OperandARM32Mem *Mem, CondARM32::Cond Predicate); 1359 }; 1360 1361 /// Sub-vector store instruction. It's important for liveness that there is no 1362 /// Dest operand (OperandARM32Mem instead of Dest Variable). 1363 class InstARM32Vstr1 final : public InstARM32Pred { 1364 InstARM32Vstr1() = delete; 1365 InstARM32Vstr1(const InstARM32Vstr1 &) = delete; 1366 InstARM32Vstr1 &operator=(const InstARM32Vstr1 &) = delete; 1367 1368 public: 1369 /// Value must be a register. 1370 static InstARM32Vstr1 *create(Cfg *Func, Variable *Value, 1371 OperandARM32Mem *Mem, CondARM32::Cond Predicate, 1372 SizeT Size) { 1373 return new (Func->allocate<InstARM32Vstr1>()) 1374 InstARM32Vstr1(Func, Value, Mem, Predicate, Size); 1375 } 1376 void emit(const Cfg *Func) const override; 1377 void emitIAS(const Cfg *Func) const override; 1378 void dump(const Cfg *Func) const override; 1379 static bool classof(const Inst *Instr) { return isClassof(Instr, Vstr1); } 1380 1381 private: 1382 InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1383 CondARM32::Cond Predicate, SizeT Size); 1384 1385 SizeT Size; 1386 }; 1387 1388 /// Vector element duplication/replication instruction. 1389 class InstARM32Vdup final : public InstARM32Pred { 1390 InstARM32Vdup() = delete; 1391 InstARM32Vdup(const InstARM32Vdup &) = delete; 1392 InstARM32Vdup &operator=(const InstARM32Vdup &) = delete; 1393 1394 public: 1395 /// Value must be a register. 1396 static InstARM32Vdup *create(Cfg *Func, Variable *Dest, Variable *Src, 1397 IValueT Idx) { 1398 return new (Func->allocate<InstARM32Vdup>()) 1399 InstARM32Vdup(Func, Dest, Src, Idx); 1400 } 1401 void emit(const Cfg *Func) const override; 1402 void emitIAS(const Cfg *Func) const override; 1403 void dump(const Cfg *Func) const override; 1404 static bool classof(const Inst *Instr) { return isClassof(Instr, Vdup); } 1405 1406 private: 1407 InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src, IValueT Idx); 1408 1409 const IValueT Idx; 1410 }; 1411 1412 class InstARM32Trap : public InstARM32 { 1413 InstARM32Trap() = delete; 1414 InstARM32Trap(const InstARM32Trap &) = delete; 1415 InstARM32Trap &operator=(const InstARM32Trap &) = delete; 1416 1417 public: 1418 static InstARM32Trap *create(Cfg *Func) { 1419 return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func); 1420 } 1421 void emit(const Cfg *Func) const override; 1422 void emitIAS(const Cfg *Func) const override; 1423 void dump(const Cfg *Func) const override; 1424 static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); } 1425 1426 private: 1427 explicit InstARM32Trap(Cfg *Func); 1428 }; 1429 1430 /// Unsigned Multiply Long: d.lo, d.hi := x * y 1431 class InstARM32Umull : public InstARM32Pred { 1432 InstARM32Umull() = delete; 1433 InstARM32Umull(const InstARM32Umull &) = delete; 1434 InstARM32Umull &operator=(const InstARM32Umull &) = delete; 1435 1436 public: 1437 /// Everything must be a register. 1438 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, 1439 Variable *Src0, Variable *Src1, 1440 CondARM32::Cond Predicate) { 1441 return new (Func->allocate<InstARM32Umull>()) 1442 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); 1443 } 1444 void emit(const Cfg *Func) const override; 1445 void emitIAS(const Cfg *Func) const override; 1446 void dump(const Cfg *Func) const override; 1447 static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); } 1448 1449 private: 1450 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, 1451 Variable *Src1, CondARM32::Cond Predicate); 1452 1453 Variable *DestHi; 1454 }; 1455 1456 /// Handles fp2int, int2fp, and fp2fp conversions. 1457 class InstARM32Vcvt final : public InstARM32Pred { 1458 InstARM32Vcvt() = delete; 1459 InstARM32Vcvt(const InstARM32Vcvt &) = delete; 1460 InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete; 1461 1462 public: 1463 enum VcvtVariant { 1464 S2si, 1465 S2ui, 1466 Si2s, 1467 Ui2s, 1468 D2si, 1469 D2ui, 1470 Si2d, 1471 Ui2d, 1472 S2d, 1473 D2s, 1474 Vs2si, 1475 Vs2ui, 1476 Vsi2s, 1477 Vui2s, 1478 }; 1479 static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src, 1480 VcvtVariant Variant, CondARM32::Cond Predicate) { 1481 return new (Func->allocate<InstARM32Vcvt>()) 1482 InstARM32Vcvt(Func, Dest, Src, Variant, Predicate); 1483 } 1484 void emit(const Cfg *Func) const override; 1485 void emitIAS(const Cfg *Func) const override; 1486 void dump(const Cfg *Func) const override; 1487 static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); } 1488 1489 private: 1490 InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant, 1491 CondARM32::Cond Predicate); 1492 1493 const VcvtVariant Variant; 1494 }; 1495 1496 /// Handles (some of) vmov's various formats. 1497 class InstARM32Mov final : public InstARM32Pred { 1498 InstARM32Mov() = delete; 1499 InstARM32Mov(const InstARM32Mov &) = delete; 1500 InstARM32Mov &operator=(const InstARM32Mov &) = delete; 1501 1502 public: 1503 static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src, 1504 CondARM32::Cond Predicate) { 1505 return new (Func->allocate<InstARM32Mov>()) 1506 InstARM32Mov(Func, Dest, Src, Predicate); 1507 } 1508 bool isRedundantAssign() const override { 1509 return !isMultiDest() && !isMultiSource() && 1510 getPredicate() == CondARM32::AL && 1511 checkForRedundantAssign(getDest(), getSrc(0)); 1512 } 1513 bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); } 1514 void emit(const Cfg *Func) const override; 1515 void emitIAS(const Cfg *Func) const override; 1516 void dump(const Cfg *Func) const override; 1517 static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); } 1518 1519 bool isMultiDest() const { return DestHi != nullptr; } 1520 1521 bool isMultiSource() const { 1522 assert(getSrcSize() == 1 || getSrcSize() == 2); 1523 return getSrcSize() == 2; 1524 } 1525 1526 Variable *getDestHi() const { return DestHi; } 1527 1528 private: 1529 InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src, 1530 CondARM32::Cond Predicate); 1531 void emitMultiDestSingleSource(const Cfg *Func) const; 1532 void emitSingleDestMultiSource(const Cfg *Func) const; 1533 void emitSingleDestSingleSource(const Cfg *Func) const; 1534 1535 Variable *DestHi = nullptr; 1536 }; 1537 1538 /// Generates vmov Rd, Dn[x] instructions, and their related floating point 1539 /// versions. 1540 class InstARM32Extract final : public InstARM32Pred { 1541 InstARM32Extract() = delete; 1542 InstARM32Extract(const InstARM32Extract &) = delete; 1543 InstARM32Extract &operator=(const InstARM32Extract &) = delete; 1544 1545 public: 1546 static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0, 1547 uint32_t Index, CondARM32::Cond Predicate) { 1548 return new (Func->allocate<InstARM32Extract>()) 1549 InstARM32Extract(Func, Dest, Src0, Index, Predicate); 1550 } 1551 void emit(const Cfg *Func) const override; 1552 void emitIAS(const Cfg *Func) const override; 1553 static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); } 1554 1555 private: 1556 InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index, 1557 CondARM32::Cond Predicate) 1558 : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate), 1559 Index(Index) { 1560 assert(Index < typeNumElements(Src0->getType())); 1561 addSource(Src0); 1562 } 1563 1564 const uint32_t Index; 1565 }; 1566 1567 /// Generates vmov Dn[x], Rd instructions, and their related floating point 1568 /// versions. 1569 class InstARM32Insert final : public InstARM32Pred { 1570 InstARM32Insert() = delete; 1571 InstARM32Insert(const InstARM32Insert &) = delete; 1572 InstARM32Insert &operator=(const InstARM32Insert &) = delete; 1573 1574 public: 1575 static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0, 1576 uint32_t Index, CondARM32::Cond Predicate) { 1577 return new (Func->allocate<InstARM32Insert>()) 1578 InstARM32Insert(Func, Dest, Src0, Index, Predicate); 1579 } 1580 void emit(const Cfg *Func) const override; 1581 void emitIAS(const Cfg *Func) const override; 1582 static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); } 1583 1584 private: 1585 InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index, 1586 CondARM32::Cond Predicate) 1587 : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate), 1588 Index(Index) { 1589 assert(Index < typeNumElements(Dest->getType())); 1590 addSource(Src0); 1591 } 1592 1593 const uint32_t Index; 1594 }; 1595 1596 class InstARM32Vcmp final : public InstARM32Pred { 1597 InstARM32Vcmp() = delete; 1598 InstARM32Vcmp(const InstARM32Vcmp &) = delete; 1599 InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete; 1600 1601 public: 1602 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1, 1603 CondARM32::Cond Predicate) { 1604 return new (Func->allocate<InstARM32Vcmp>()) 1605 InstARM32Vcmp(Func, Src0, Src1, Predicate); 1606 } 1607 static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, 1608 OperandARM32FlexFpZero *Src1, 1609 CondARM32::Cond Predicate) { 1610 return new (Func->allocate<InstARM32Vcmp>()) 1611 InstARM32Vcmp(Func, Src0, Src1, Predicate); 1612 } 1613 void emit(const Cfg *Func) const override; 1614 void emitIAS(const Cfg *Func) const override; 1615 void dump(const Cfg *Func) const override; 1616 static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); } 1617 1618 private: 1619 InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1, 1620 CondARM32::Cond Predicate); 1621 }; 1622 1623 /// Copies the FP Status and Control Register the core flags. 1624 class InstARM32Vmrs final : public InstARM32Pred { 1625 InstARM32Vmrs() = delete; 1626 InstARM32Vmrs(const InstARM32Vmrs &) = delete; 1627 InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete; 1628 1629 public: 1630 static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) { 1631 return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate); 1632 } 1633 void emit(const Cfg *Func) const override; 1634 void emitIAS(const Cfg *Func) const override; 1635 void dump(const Cfg *Func) const override; 1636 static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); } 1637 1638 private: 1639 InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate); 1640 }; 1641 1642 class InstARM32Vabs final : public InstARM32Pred { 1643 InstARM32Vabs() = delete; 1644 InstARM32Vabs(const InstARM32Vabs &) = delete; 1645 InstARM32Vabs &operator=(const InstARM32Vabs &) = delete; 1646 1647 public: 1648 static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src, 1649 CondARM32::Cond Predicate) { 1650 return new (Func->allocate<InstARM32Vabs>()) 1651 InstARM32Vabs(Func, Dest, Src, Predicate); 1652 } 1653 void emit(const Cfg *Func) const override; 1654 void emitIAS(const Cfg *Func) const override; 1655 void dump(const Cfg *Func) const override; 1656 static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); } 1657 1658 private: 1659 InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src, 1660 CondARM32::Cond Predicate); 1661 }; 1662 1663 class InstARM32Dmb final : public InstARM32Pred { 1664 InstARM32Dmb() = delete; 1665 InstARM32Dmb(const InstARM32Dmb &) = delete; 1666 InstARM32Dmb &operator=(const InstARM32Dmb &) = delete; 1667 1668 public: 1669 static InstARM32Dmb *create(Cfg *Func) { 1670 return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func); 1671 } 1672 void emit(const Cfg *Func) const override; 1673 void emitIAS(const Cfg *Func) const override; 1674 void dump(const Cfg *Func) const override; 1675 static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); } 1676 1677 private: 1678 explicit InstARM32Dmb(Cfg *Func); 1679 }; 1680 1681 class InstARM32Nop final : public InstARM32Pred { 1682 InstARM32Nop() = delete; 1683 InstARM32Nop(const InstARM32Nop &) = delete; 1684 InstARM32Nop &operator=(const InstARM32Nop &) = delete; 1685 1686 public: 1687 static InstARM32Nop *create(Cfg *Func) { 1688 return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func); 1689 } 1690 void emit(const Cfg *Func) const override; 1691 void emitIAS(const Cfg *Func) const override; 1692 void dump(const Cfg *Func) const override; 1693 static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); } 1694 1695 private: 1696 explicit InstARM32Nop(Cfg *Func); 1697 }; 1698 1699 // Declare partial template specializations of emit() methods that already have 1700 // default implementations. Without this, there is the possibility of ODR 1701 // violations and link errors. 1702 1703 template <> void InstARM32Ldr::emit(const Cfg *Func) const; 1704 template <> void InstARM32Movw::emit(const Cfg *Func) const; 1705 template <> void InstARM32Movt::emit(const Cfg *Func) const; 1706 template <> void InstARM32Vldr1d::emit(const Cfg *Func) const; 1707 template <> void InstARM32Vldr1q::emit(const Cfg *Func) const; 1708 1709 } // end of namespace ARM32 1710 } // end of namespace Ice 1711 1712 #endif // SUBZERO_SRC_ICEINSTARM32_H 1713