1b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// 2b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// 3b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// The Subzero Code Generator 4b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// 5b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// This file is distributed under the University of Illinois Open Source 6b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// License. See LICENSE.TXT for details. 7b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// 8b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===----------------------------------------------------------------------===// 99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file 1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the InstARM32 and OperandARM32 classes and their subclasses. 1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// 1392a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// This represents the machine instructions and operands used for ARM32 code 1492a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// selection. 159612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 16b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===----------------------------------------------------------------------===// 17b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 18b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#ifndef SUBZERO_SRC_ICEINSTARM32_H 19b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#define SUBZERO_SRC_ICEINSTARM32_H 20b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 213bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung#include "IceConditionCodesARM32.h" 22b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#include "IceDefs.h" 23b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceInst.h" 24b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceInstARM32.def" 25b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceOperand.h" 26658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk#include "IceRegistersARM32.h" 27b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 28b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungnamespace Ice { 294a56686b5b56db6803f90ad53514bf2fa190d9f7John Portonamespace ARM32 { 30b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 31c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf/// Encoding of an ARM 32-bit instruction. 32c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfusing IValueT = uint32_t; 33c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf 34c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf/// An Offset value (+/-) used in an ARM 32-bit instruction. 35c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfusing IOffsetT = int32_t; 36c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf 37b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungclass TargetARM32; 38b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 3957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// OperandARM32 extends the Operand hierarchy. Its subclasses are 409612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// OperandARM32Mem and OperandARM32Flex. 41b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass OperandARM32 : public Operand { 42b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32() = delete; 43b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32(const OperandARM32 &) = delete; 44b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32 &operator=(const OperandARM32 &) = delete; 45b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 46b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic: 47b3401d27a236b81393092b4d571df473b5bba64bJan Voung enum OperandKindARM32 { 48b3401d27a236b81393092b4d571df473b5bba64bJan Voung k__Start = Operand::kTarget, 49b3401d27a236b81393092b4d571df473b5bba64bJan Voung kMem, 502758bb077495d7a88b3d66368b3d760de61cedc7John Porto kShAmtImm, 51b3401d27a236b81393092b4d571df473b5bba64bJan Voung kFlexStart, 52b3401d27a236b81393092b4d571df473b5bba64bJan Voung kFlexImm = kFlexStart, 53ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto kFlexFpImm, 54ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto kFlexFpZero, 55b3401d27a236b81393092b4d571df473b5bba64bJan Voung kFlexReg, 56b3401d27a236b81393092b4d571df473b5bba64bJan Voung kFlexEnd = kFlexReg 57b3401d27a236b81393092b4d571df473b5bba64bJan Voung }; 58b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 59b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung enum ShiftKind { 60b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung kNoShift = -1, 61b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#define X(enum, emit) enum, 62b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung ICEINSTARM32SHIFT_TABLE 63b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#undef X 64b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung }; 65b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 66b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung using Operand::dump; 67b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung void dump(const Cfg *, Ostream &Str) const override { 6820b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (BuildDefs::dump()) 69b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung Str << "<OperandARM32>"; 70b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung } 71b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 72b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungprotected: 73b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32(OperandKindARM32 Kind, Type Ty) 74b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung : Operand(static_cast<OperandKind>(Kind), Ty) {} 75b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung}; 76b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 779612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// OperandARM32Mem represents a memory operand in any of the various ARM32 789612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// addressing modes. 79b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass OperandARM32Mem : public OperandARM32 { 80b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32Mem() = delete; 81b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32Mem(const OperandARM32Mem &) = delete; 82b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung OperandARM32Mem &operator=(const OperandARM32Mem &) = delete; 83b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 84b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic: 859612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Memory operand addressing mode. 869612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// The enum value also carries the encoding. 87b3401d27a236b81393092b4d571df473b5bba64bJan Voung // TODO(jvoung): unify with the assembler. 88b3401d27a236b81393092b4d571df473b5bba64bJan Voung enum AddrMode { 89cdb3ed6870ef03215a8d6ed977d8ed0e4bc328a5Karl Schimpf // bit encoding P U 0 W 90b3401d27a236b81393092b4d571df473b5bba64bJan Voung Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base) 91b3401d27a236b81393092b4d571df473b5bba64bJan Voung PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback 92b3401d27a236b81393092b4d571df473b5bba64bJan Voung PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback 93b3401d27a236b81393092b4d571df473b5bba64bJan Voung NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base) 94b3401d27a236b81393092b4d571df473b5bba64bJan Voung NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback 95b3401d27a236b81393092b4d571df473b5bba64bJan Voung NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback 96b3401d27a236b81393092b4d571df473b5bba64bJan Voung }; 97b3401d27a236b81393092b4d571df473b5bba64bJan Voung 989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Provide two constructors. 999612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// NOTE: The Variable-typed operands have to be registers. 1009612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// 1019612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// (1) Reg + Imm. The Immediate actually has a limited number of bits 10257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// for encoding, so check canHoldOffset first. It cannot handle general 10357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Constant operands like ConstantRelocatable, since a relocatable can 10457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// potentially take up too many bits. 105b3401d27a236b81393092b4d571df473b5bba64bJan Voung static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 106befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung ConstantInteger32 *ImmOffset, 107b3401d27a236b81393092b4d571df473b5bba64bJan Voung AddrMode Mode = Offset) { 108b3401d27a236b81393092b4d571df473b5bba64bJan Voung return new (Func->allocate<OperandARM32Mem>()) 109b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode); 110b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 11157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that 11257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// this mode is disallowed in the NaCl sandbox. 113b3401d27a236b81393092b4d571df473b5bba64bJan Voung static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base, 114b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *Index, ShiftKind ShiftOp = kNoShift, 115b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint16_t ShiftAmt = 0, 116b3401d27a236b81393092b4d571df473b5bba64bJan Voung AddrMode Mode = Offset) { 117b3401d27a236b81393092b4d571df473b5bba64bJan Voung return new (Func->allocate<OperandARM32Mem>()) 118b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode); 119b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 120b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *getBase() const { return Base; } 121b3401d27a236b81393092b4d571df473b5bba64bJan Voung ConstantInteger32 *getOffset() const { return ImmOffset; } 122b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *getIndex() const { return Index; } 123b3401d27a236b81393092b4d571df473b5bba64bJan Voung ShiftKind getShiftOp() const { return ShiftOp; } 124b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint16_t getShiftAmt() const { return ShiftAmt; } 125b3401d27a236b81393092b4d571df473b5bba64bJan Voung AddrMode getAddrMode() const { return Mode; } 126b3401d27a236b81393092b4d571df473b5bba64bJan Voung 127b3401d27a236b81393092b4d571df473b5bba64bJan Voung bool isRegReg() const { return Index != nullptr; } 1280fa6c5a062f465360448a672abed3b916b413ca8Jan Voung bool isNegAddrMode() const { 1290fa6c5a062f465360448a672abed3b916b413ca8Jan Voung // Positive address modes have the "U" bit set, and negative modes don't. 1300fa6c5a062f465360448a672abed3b916b413ca8Jan Voung static_assert((PreIndex & (4 << 21)) != 0, 1310fa6c5a062f465360448a672abed3b916b413ca8Jan Voung "Positive addr modes should have U bit set."); 1320fa6c5a062f465360448a672abed3b916b413ca8Jan Voung static_assert((NegPreIndex & (4 << 21)) == 0, 1330fa6c5a062f465360448a672abed3b916b413ca8Jan Voung "Negative addr modes should have U bit clear."); 1340fa6c5a062f465360448a672abed3b916b413ca8Jan Voung return (Mode & (4 << 21)) == 0; 1350fa6c5a062f465360448a672abed3b916b413ca8Jan Voung } 136b3401d27a236b81393092b4d571df473b5bba64bJan Voung 137b3401d27a236b81393092b4d571df473b5bba64bJan Voung void emit(const Cfg *Func) const override; 138b3401d27a236b81393092b4d571df473b5bba64bJan Voung using OperandARM32::dump; 139b3401d27a236b81393092b4d571df473b5bba64bJan Voung void dump(const Cfg *Func, Ostream &Str) const override; 140b3401d27a236b81393092b4d571df473b5bba64bJan Voung 141b3401d27a236b81393092b4d571df473b5bba64bJan Voung static bool classof(const Operand *Operand) { 142b3401d27a236b81393092b4d571df473b5bba64bJan Voung return Operand->getKind() == static_cast<OperandKind>(kMem); 143b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 144b3401d27a236b81393092b4d571df473b5bba64bJan Voung 14557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Return true if a load/store instruction for an element of type Ty can 14657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// encode the Offset directly in the immediate field of the 32-bit ARM 14757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// instruction. For some types, if the load is Sign extending, then the range 14857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// is reduced. 149b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); 150b3401d27a236b81393092b4d571df473b5bba64bJan Voung 151b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate: 152b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, 153b3401d27a236b81393092b4d571df473b5bba64bJan Voung ConstantInteger32 *ImmOffset, AddrMode Mode); 154b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index, 155b3401d27a236b81393092b4d571df473b5bba64bJan Voung ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode); 1561bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 157b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *Base; 158b3401d27a236b81393092b4d571df473b5bba64bJan Voung ConstantInteger32 *ImmOffset; 159b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *Index; 160b3401d27a236b81393092b4d571df473b5bba64bJan Voung ShiftKind ShiftOp; 161b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint16_t ShiftAmt; 162b3401d27a236b81393092b4d571df473b5bba64bJan Voung AddrMode Mode; 163b3401d27a236b81393092b4d571df473b5bba64bJan Voung}; 164b3401d27a236b81393092b4d571df473b5bba64bJan Voung 1652758bb077495d7a88b3d66368b3d760de61cedc7John Porto/// OperandARM32ShAmtImm represents an Immediate that is used in one of the 1662758bb077495d7a88b3d66368b3d760de61cedc7John Porto/// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate 1672758bb077495d7a88b3d66368b3d760de61cedc7John Porto/// shifted registers. 1682758bb077495d7a88b3d66368b3d760de61cedc7John Portoclass OperandARM32ShAmtImm : public OperandARM32 { 1692758bb077495d7a88b3d66368b3d760de61cedc7John Porto OperandARM32ShAmtImm() = delete; 1702758bb077495d7a88b3d66368b3d760de61cedc7John Porto OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete; 1712758bb077495d7a88b3d66368b3d760de61cedc7John Porto OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete; 1722758bb077495d7a88b3d66368b3d760de61cedc7John Porto 1732758bb077495d7a88b3d66368b3d760de61cedc7John Portopublic: 1742758bb077495d7a88b3d66368b3d760de61cedc7John Porto static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) { 1752758bb077495d7a88b3d66368b3d760de61cedc7John Porto return new (Func->allocate<OperandARM32ShAmtImm>()) 1762758bb077495d7a88b3d66368b3d760de61cedc7John Porto OperandARM32ShAmtImm(ShAmt); 1772758bb077495d7a88b3d66368b3d760de61cedc7John Porto } 1782758bb077495d7a88b3d66368b3d760de61cedc7John Porto 1792758bb077495d7a88b3d66368b3d760de61cedc7John Porto static bool classof(const Operand *Operand) { 1802758bb077495d7a88b3d66368b3d760de61cedc7John Porto return Operand->getKind() == static_cast<OperandKind>(kShAmtImm); 1812758bb077495d7a88b3d66368b3d760de61cedc7John Porto } 1822758bb077495d7a88b3d66368b3d760de61cedc7John Porto 1832758bb077495d7a88b3d66368b3d760de61cedc7John Porto void emit(const Cfg *Func) const override; 1842758bb077495d7a88b3d66368b3d760de61cedc7John Porto using OperandARM32::dump; 1852758bb077495d7a88b3d66368b3d760de61cedc7John Porto void dump(const Cfg *Func, Ostream &Str) const override; 1862758bb077495d7a88b3d66368b3d760de61cedc7John Porto 1872758bb077495d7a88b3d66368b3d760de61cedc7John Porto uint32_t getShAmtImm() const { return ShAmt->getValue(); } 1882758bb077495d7a88b3d66368b3d760de61cedc7John Porto 1892758bb077495d7a88b3d66368b3d760de61cedc7John Portoprivate: 1902758bb077495d7a88b3d66368b3d760de61cedc7John Porto explicit OperandARM32ShAmtImm(ConstantInteger32 *SA); 1912758bb077495d7a88b3d66368b3d760de61cedc7John Porto 1922758bb077495d7a88b3d66368b3d760de61cedc7John Porto const ConstantInteger32 *const ShAmt; 1932758bb077495d7a88b3d66368b3d760de61cedc7John Porto}; 1942758bb077495d7a88b3d66368b3d760de61cedc7John Porto 19557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// OperandARM32Flex represent the "flexible second operand" for data-processing 19657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// instructions. It can be a rotatable 8-bit constant, or a register with an 19757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// optional shift operand. The shift amount can even be a third register. 198b3401d27a236b81393092b4d571df473b5bba64bJan Voungclass OperandARM32Flex : public OperandARM32 { 199b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Flex() = delete; 200b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Flex(const OperandARM32Flex &) = delete; 201b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Flex &operator=(const OperandARM32Flex &) = delete; 202b3401d27a236b81393092b4d571df473b5bba64bJan Voung 203b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic: 204b3401d27a236b81393092b4d571df473b5bba64bJan Voung static bool classof(const Operand *Operand) { 205b3401d27a236b81393092b4d571df473b5bba64bJan Voung return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() && 206b3401d27a236b81393092b4d571df473b5bba64bJan Voung Operand->getKind() <= static_cast<OperandKind>(kFlexEnd); 207b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 208b3401d27a236b81393092b4d571df473b5bba64bJan Voung 209b3401d27a236b81393092b4d571df473b5bba64bJan Voungprotected: 210b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {} 211b3401d27a236b81393092b4d571df473b5bba64bJan Voung}; 212b3401d27a236b81393092b4d571df473b5bba64bJan Voung 2139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Rotated immediate variant. 214b3401d27a236b81393092b4d571df473b5bba64bJan Voungclass OperandARM32FlexImm : public OperandARM32Flex { 215b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexImm() = delete; 216b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexImm(const OperandARM32FlexImm &) = delete; 217b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete; 218b3401d27a236b81393092b4d571df473b5bba64bJan Voung 219b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic: 2209612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Immed_8 rotated by an even number of bits (2 * RotateAmt). 221b3401d27a236b81393092b4d571df473b5bba64bJan Voung static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm, 22267574d83d05f5bde748843a73adcab6247736601Karl Schimpf uint32_t RotateAmt); 223b3401d27a236b81393092b4d571df473b5bba64bJan Voung 224b3401d27a236b81393092b4d571df473b5bba64bJan Voung void emit(const Cfg *Func) const override; 225b3401d27a236b81393092b4d571df473b5bba64bJan Voung using OperandARM32::dump; 226b3401d27a236b81393092b4d571df473b5bba64bJan Voung void dump(const Cfg *Func, Ostream &Str) const override; 227b3401d27a236b81393092b4d571df473b5bba64bJan Voung 228b3401d27a236b81393092b4d571df473b5bba64bJan Voung static bool classof(const Operand *Operand) { 229b3401d27a236b81393092b4d571df473b5bba64bJan Voung return Operand->getKind() == static_cast<OperandKind>(kFlexImm); 230b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 231b3401d27a236b81393092b4d571df473b5bba64bJan Voung 23257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Return true if the Immediate can fit in the ARM flexible operand. Fills in 23357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// the out-params RotateAmt and Immed_8 if Immediate fits. 234b3401d27a236b81393092b4d571df473b5bba64bJan Voung static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt, 235b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint32_t *Immed_8); 236b3401d27a236b81393092b4d571df473b5bba64bJan Voung 237b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint32_t getImm() const { return Imm; } 238b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint32_t getRotateAmt() const { return RotateAmt; } 239b3401d27a236b81393092b4d571df473b5bba64bJan Voung 240b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate: 241b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt); 242b3401d27a236b81393092b4d571df473b5bba64bJan Voung 243b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint32_t Imm; 244b3401d27a236b81393092b4d571df473b5bba64bJan Voung uint32_t RotateAmt; 245b3401d27a236b81393092b4d571df473b5bba64bJan Voung}; 246b3401d27a236b81393092b4d571df473b5bba64bJan Voung 247ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto/// Modified Floating-point constant. 248ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoclass OperandARM32FlexFpImm : public OperandARM32Flex { 249ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpImm() = delete; 250ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete; 251ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete; 252ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 253ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portopublic: 254ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty, 255ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto uint32_t ModifiedImm) { 256ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto return new (Func->allocate<OperandARM32FlexFpImm>()) 257ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpImm(Func, Ty, ModifiedImm); 258ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 259ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 260ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void emit(const Cfg *Func) const override; 261ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto using OperandARM32::dump; 262ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void dump(const Cfg *Func, Ostream &Str) const override; 263ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 264ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto static bool classof(const Operand *Operand) { 265ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm); 266ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 267ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 268dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm); 269ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 270c64448fbaf1dca1495a55e6c085555ca637e3e74Karl Schimpf uint32_t getModifiedImm() const { return ModifiedImm; } 271c64448fbaf1dca1495a55e6c085555ca637e3e74Karl Schimpf 272ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoprivate: 273ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm); 274ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 275c64448fbaf1dca1495a55e6c085555ca637e3e74Karl Schimpf const uint32_t ModifiedImm; 276ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto}; 277ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 278ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto/// An operand for representing the 0.0 immediate in vcmp. 279ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoclass OperandARM32FlexFpZero : public OperandARM32Flex { 280ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpZero() = delete; 281ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete; 282ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete; 283ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 284ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portopublic: 285ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) { 286ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto return new (Func->allocate<OperandARM32FlexFpZero>()) 287ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpZero(Func, Ty); 288ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 289ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 290ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void emit(const Cfg *Func) const override; 291ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto using OperandARM32::dump; 292ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void dump(const Cfg *Func, Ostream &Str) const override; 293ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 294ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto static bool classof(const Operand *Operand) { 295ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero); 296ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 297ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 298ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portoprivate: 299ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpZero(Cfg *Func, Type Ty); 300ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto}; 301ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 3029612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Shifted register variant. 303b3401d27a236b81393092b4d571df473b5bba64bJan Voungclass OperandARM32FlexReg : public OperandARM32Flex { 304b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexReg() = delete; 305b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexReg(const OperandARM32FlexReg &) = delete; 306b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete; 307b3401d27a236b81393092b4d571df473b5bba64bJan Voung 308b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic: 3099612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Register with immediate/reg shift amount and shift operation. 310b3401d27a236b81393092b4d571df473b5bba64bJan Voung static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg, 311b3401d27a236b81393092b4d571df473b5bba64bJan Voung ShiftKind ShiftOp, Operand *ShiftAmt) { 312b3401d27a236b81393092b4d571df473b5bba64bJan Voung return new (Func->allocate<OperandARM32FlexReg>()) 313b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt); 314b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 315b3401d27a236b81393092b4d571df473b5bba64bJan Voung 316b3401d27a236b81393092b4d571df473b5bba64bJan Voung void emit(const Cfg *Func) const override; 317b3401d27a236b81393092b4d571df473b5bba64bJan Voung using OperandARM32::dump; 318b3401d27a236b81393092b4d571df473b5bba64bJan Voung void dump(const Cfg *Func, Ostream &Str) const override; 319b3401d27a236b81393092b4d571df473b5bba64bJan Voung 320b3401d27a236b81393092b4d571df473b5bba64bJan Voung static bool classof(const Operand *Operand) { 321b3401d27a236b81393092b4d571df473b5bba64bJan Voung return Operand->getKind() == static_cast<OperandKind>(kFlexReg); 322b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 323b3401d27a236b81393092b4d571df473b5bba64bJan Voung 324b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *getReg() const { return Reg; } 325b3401d27a236b81393092b4d571df473b5bba64bJan Voung ShiftKind getShiftOp() const { return ShiftOp; } 3269612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// ShiftAmt can represent an immediate or a register. 327b3401d27a236b81393092b4d571df473b5bba64bJan Voung Operand *getShiftAmt() const { return ShiftAmt; } 328b3401d27a236b81393092b4d571df473b5bba64bJan Voung 329b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate: 330b3401d27a236b81393092b4d571df473b5bba64bJan Voung OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, 331b3401d27a236b81393092b4d571df473b5bba64bJan Voung Operand *ShiftAmt); 332b3401d27a236b81393092b4d571df473b5bba64bJan Voung 333b3401d27a236b81393092b4d571df473b5bba64bJan Voung Variable *Reg; 334b3401d27a236b81393092b4d571df473b5bba64bJan Voung ShiftKind ShiftOp; 335b3401d27a236b81393092b4d571df473b5bba64bJan Voung Operand *ShiftAmt; 336b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung}; 337b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 33828068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung/// StackVariable represents a Var that isn't assigned a register (stack-only). 33928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung/// It is assigned a stack slot, but the slot's offset may be too large to 34057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// represent in the native addressing mode, and so it has a separate base 34157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register from SP/FP, where the offset from that base register is then in 34257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// range. 34328068adbf34a4602090efddc18b4dd123ffdeb6aJan Voungclass StackVariable final : public Variable { 34428068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung StackVariable() = delete; 34528068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung StackVariable(const StackVariable &) = delete; 34628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung StackVariable &operator=(const StackVariable &) = delete; 34728068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung 34828068adbf34a4602090efddc18b4dd123ffdeb6aJan Voungpublic: 34928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) { 350467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index); 35128068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung } 3522d6c82679e9786a924b76023aa30e1f44d0f8cbbJim Stichnoth constexpr static auto StackVariableKind = 35328068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung static_cast<OperandKind>(kVariable_Target); 35428068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung static bool classof(const Operand *Operand) { 35528068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung return Operand->getKind() == StackVariableKind; 35628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung } 3578aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; } 3588aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT getBaseRegNum() const override { return BaseRegNum; } 35928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung // Inherit dump() and emit() from Variable. 36028068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung 36128068adbf34a4602090efddc18b4dd123ffdeb6aJan Voungprivate: 362467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth StackVariable(const Cfg *Func, Type Ty, SizeT Index) 363467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth : Variable(Func, StackVariableKind, Ty, Index) {} 3645fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler RegNumT BaseRegNum; 36528068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung}; 36628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung 3679612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Base class for ARM instructions. While most ARM instructions can be 36857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// conditionally executed, a few of them are not predicable (halt, memory 36957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// barriers, etc.). 370b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass InstARM32 : public InstTarget { 371b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32() = delete; 372b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32(const InstARM32 &) = delete; 373b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32 &operator=(const InstARM32 &) = delete; 374b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 375b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic: 376c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf // Defines form that assembly instruction should be synthesized. 377c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf enum EmitForm { Emit_Text, Emit_Binary }; 378c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf 379b3401d27a236b81393092b4d571df473b5bba64bJan Voung enum InstKindARM32 { 380b3401d27a236b81393092b4d571df473b5bba64bJan Voung k__Start = Inst::Target, 3812971997a96b7484165cfedead111c7cafb3073aeJan Voung Adc, 3822971997a96b7484165cfedead111c7cafb3073aeJan Voung Add, 3832971997a96b7484165cfedead111c7cafb3073aeJan Voung And, 38466c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung Asr, 38555500dbceb14d4223533701158389e89c1f93a5eJan Voung Bic, 3863bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Br, 3873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Call, 3881956788f4459e0fedf91c10e8c266ca72a5d5fa1Karl Schimpf Clz, 389ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Cmn, 3903bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Cmp, 39116991847500a48932426d979c4f2d4adffaf3649John Porto Dmb, 3922971997a96b7484165cfedead111c7cafb3073aeJan Voung Eor, 393658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk Extract, 394658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk Insert, 3956ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Label, 3962971997a96b7484165cfedead111c7cafb3073aeJan Voung Ldr, 39716991847500a48932426d979c4f2d4adffaf3649John Porto Ldrex, 3983bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Lsl, 39966c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung Lsr, 400f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf Nop, 4012971997a96b7484165cfedead111c7cafb3073aeJan Voung Mla, 4026ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Mls, 403b3401d27a236b81393092b4d571df473b5bba64bJan Voung Mov, 404b3401d27a236b81393092b4d571df473b5bba64bJan Voung Movt, 405b3401d27a236b81393092b4d571df473b5bba64bJan Voung Movw, 4062971997a96b7484165cfedead111c7cafb3073aeJan Voung Mul, 407b3401d27a236b81393092b4d571df473b5bba64bJan Voung Mvn, 4082971997a96b7484165cfedead111c7cafb3073aeJan Voung Orr, 4090fa6c5a062f465360448a672abed3b916b413ca8Jan Voung Pop, 4100fa6c5a062f465360448a672abed3b916b413ca8Jan Voung Push, 411f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung Rbit, 412b3401d27a236b81393092b4d571df473b5bba64bJan Voung Ret, 413f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung Rev, 41466c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung Rsb, 415ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Rsc, 4162971997a96b7484165cfedead111c7cafb3073aeJan Voung Sbc, 4176ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Sdiv, 418befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung Str, 41916991847500a48932426d979c4f2d4adffaf3649John Porto Strex, 4202971997a96b7484165cfedead111c7cafb3073aeJan Voung Sub, 42166c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung Sxt, 4226ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Trap, 4236ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Tst, 4246ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Udiv, 42566c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung Umull, 42686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Uxt, 427ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto Vabs, 42886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Vadd, 429b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holk Vand, 430397f602c4e4e5697806bf74e37a651ab78680628John Porto Vbsl, 431a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Vceq, 432a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Vcge, 433a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Vcgt, 4342f5534f1c523eb022880360864f60ce42fb30ee0John Porto Vcmp, 435c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto Vcvt, 43686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Vdiv, 437f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vdup, 438ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Veor, 439675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Vldr1d, 440675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Vldr1q, 441eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Vmla, 442675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Vmlap, 443eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Vmls, 444f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vmovl, 445f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vmovh, 446f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vmovhl, 447f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vmovlh, 4482f5534f1c523eb022880360864f60ce42fb30ee0John Porto Vmrs, 44986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Vmul, 450675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Vmulh, 451a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Vmvn, 45215e77d4698df65dfce5072b59df18500ff56daa3John Porto Vneg, 453cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holk Vorr, 454b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin Vqadd, 455675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Vqmovn2, 456b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin Vqsub, 45715e77d4698df65dfce5072b59df18500ff56daa3John Porto Vshl, 458e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Vshr, 45986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Vsqrt, 460675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Vstr1, 461f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vsub, 462f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Vzip 463b3401d27a236b81393092b4d571df473b5bba64bJan Voung }; 464b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 465856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf static constexpr size_t InstSize = sizeof(uint32_t); 466856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf 4673bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); 468b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 469856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf /// Called inside derived methods emit() to communicate that multiple 470856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf /// instructions are being generated. Used by emitIAS() methods to 471856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf /// generate textual fixups for instructions that are not yet 472856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf /// implemented. 473856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf void startNextInst(const Cfg *Func) const; 474856734ca6f51025ca428494ddd740f27fab40438Karl Schimpf 47515e77d4698df65dfce5072b59df18500ff56daa3John Porto /// FPSign is used for certain vector instructions (particularly, right 47615e77d4698df65dfce5072b59df18500ff56daa3John Porto /// shifts) that require an operand sign specification. 47715e77d4698df65dfce5072b59df18500ff56daa3John Porto enum FPSign { 47815e77d4698df65dfce5072b59df18500ff56daa3John Porto FS_None, 47915e77d4698df65dfce5072b59df18500ff56daa3John Porto FS_Signed, 48015e77d4698df65dfce5072b59df18500ff56daa3John Porto FS_Unsigned, 48115e77d4698df65dfce5072b59df18500ff56daa3John Porto }; 48286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung /// Shared emit routines for common forms of instructions. 48315e77d4698df65dfce5072b59df18500ff56daa3John Porto /// @{ 48415e77d4698df65dfce5072b59df18500ff56daa3John Porto static void emitThreeAddrFP(const char *Opcode, FPSign Sign, 485a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto const InstARM32 *Instr, const Cfg *Func, 486a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Type OpType); 48715e77d4698df65dfce5072b59df18500ff56daa3John Porto static void emitFourAddrFP(const char *Opcode, FPSign Sign, 48815e77d4698df65dfce5072b59df18500ff56daa3John Porto const InstARM32 *Instr, const Cfg *Func); 48915e77d4698df65dfce5072b59df18500ff56daa3John Porto /// @} 49086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 491b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung void dump(const Cfg *Func) const override; 492b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 4932fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf void emitIAS(const Cfg *Func) const override; 4942fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf 495b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungprotected: 496b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) 497b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} 4981bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 4998cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) { 5008cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth return Instr->getKind() == static_cast<InstKind>(MyKind); 501b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung } 5022fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf 5032fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf // Generates text of assembly instruction using method emit(), and then adds 5042fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf // to the assembly buffer as a Fixup. 5052fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf void emitUsingTextFixup(const Cfg *Func) const; 506b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung}; 507b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 5089612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// A predicable ARM instruction. 5093bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Pred : public InstARM32 { 5103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Pred() = delete; 5113bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Pred(const InstARM32Pred &) = delete; 5123bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Pred &operator=(const InstARM32Pred &) = delete; 513b3401d27a236b81393092b4d571df473b5bba64bJan Voung 5143bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungpublic: 5153bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest, 5163bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) 5173bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {} 5183bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 5193bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond getPredicate() const { return Predicate; } 5203bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; } 5213bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 5223bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static const char *predString(CondARM32::Cond Predicate); 5233bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; 5243bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 5259612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Shared emit routines for common forms of instructions. 5268cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr, 527f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung const Cfg *Func, bool NeedsWidthSuffix); 52815e77d4698df65dfce5072b59df18500ff56daa3John Porto static void emitUnaryopFP(const char *Opcode, FPSign Sign, 52915e77d4698df65dfce5072b59df18500ff56daa3John Porto const InstARM32Pred *Instr, const Cfg *Func); 5308cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr, 5313bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung const Cfg *Func); 5328cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr, 5333bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung const Cfg *Func, bool SetFlags); 5348cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr, 5356ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung const Cfg *Func); 5368cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr, 5376ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung const Cfg *Func); 5383bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 5393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungprotected: 5403bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate; 5413bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung}; 5423bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 5433bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungtemplate <typename StreamType> 5443bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Vounginline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { 5453bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Stream << InstARM32Pred::predString(Predicate); 5463bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return Stream; 5473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung} 548b3401d27a236b81393092b4d571df473b5bba64bJan Voung 5499612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Instructions of the form x := op(y). 550f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voungtemplate <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix> 5513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32UnaryopGPR : public InstARM32Pred { 552b3401d27a236b81393092b4d571df473b5bba64bJan Voung InstARM32UnaryopGPR() = delete; 553b3401d27a236b81393092b4d571df473b5bba64bJan Voung InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; 554b3401d27a236b81393092b4d571df473b5bba64bJan Voung InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; 555b3401d27a236b81393092b4d571df473b5bba64bJan Voung 556b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic: 5573bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 5583bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) { 559b3401d27a236b81393092b4d571df473b5bba64bJan Voung return new (Func->allocate<InstARM32UnaryopGPR>()) 5603bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32UnaryopGPR(Func, Dest, Src, Predicate); 561b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 562b3401d27a236b81393092b4d571df473b5bba64bJan Voung void emit(const Cfg *Func) const override { 56320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 564b3401d27a236b81393092b4d571df473b5bba64bJan Voung return; 565f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix); 566b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 5677cb2db327e386372003cdb45e2c3acef774fb902Karl Schimpf void emitIAS(const Cfg *Func) const override; 568b3401d27a236b81393092b4d571df473b5bba64bJan Voung void dump(const Cfg *Func) const override { 56920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 570b3401d27a236b81393092b4d571df473b5bba64bJan Voung return; 571b3401d27a236b81393092b4d571df473b5bba64bJan Voung Ostream &Str = Func->getContext()->getStrDump(); 572b3401d27a236b81393092b4d571df473b5bba64bJan Voung dumpDest(Func); 5733bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << " = "; 5743bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung dumpOpcodePred(Str, Opcode, getDest()->getType()); 5753bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << " "; 576b3401d27a236b81393092b4d571df473b5bba64bJan Voung dumpSources(Func); 577b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 5788cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 579b3401d27a236b81393092b4d571df473b5bba64bJan Voung 580b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate: 5813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, 5823bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) 5833bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung : InstARM32Pred(Func, K, 1, Dest, Predicate) { 584b3401d27a236b81393092b4d571df473b5bba64bJan Voung addSource(Src); 585b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 5861bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 587b3401d27a236b81393092b4d571df473b5bba64bJan Voung static const char *Opcode; 588b3401d27a236b81393092b4d571df473b5bba64bJan Voung}; 589b3401d27a236b81393092b4d571df473b5bba64bJan Voung 59086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// Instructions of the form x := op(y), for vector/FP. 59186ebec12680b5268fcb7082f770a26394e8b8080Jan Voungtemplate <InstARM32::InstKindARM32 K> 59286ebec12680b5268fcb7082f770a26394e8b8080Jan Voungclass InstARM32UnaryopFP : public InstARM32Pred { 59386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32UnaryopFP() = delete; 59486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete; 59586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete; 59686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 59786ebec12680b5268fcb7082f770a26394e8b8080Jan Voungpublic: 59886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src, 59986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung CondARM32::Cond Predicate) { 60086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung return new (Func->allocate<InstARM32UnaryopFP>()) 60186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32UnaryopFP(Func, Dest, Src, Predicate); 60286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 60386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void emit(const Cfg *Func) const override { 60486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung if (!BuildDefs::dump()) 60586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung return; 60615e77d4698df65dfce5072b59df18500ff56daa3John Porto emitUnaryopFP(Opcode, Sign, this, Func); 60786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 608266c5a25bb8c07b691aa6396ccef6f8d37df9cd0Karl Schimpf void emitIAS(const Cfg *Func) const override; 60986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void dump(const Cfg *Func) const override { 61086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung if (!BuildDefs::dump()) 61186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung return; 61286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Ostream &Str = Func->getContext()->getStrDump(); 61386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung dumpDest(Func); 61486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Str << " = "; 61586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung dumpOpcodePred(Str, Opcode, getDest()->getType()); 61686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Str << " "; 61786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung dumpSources(Func); 61886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 6198cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 62086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 62115e77d4698df65dfce5072b59df18500ff56daa3John Portoprotected: 62286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src, 62386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung CondARM32::Cond Predicate) 62486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung : InstARM32Pred(Func, K, 1, Dest, Predicate) { 62586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung addSource(Src); 62686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 62786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 62815e77d4698df65dfce5072b59df18500ff56daa3John Porto FPSign Sign = FS_None; 62986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung static const char *Opcode; 63086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung}; 63186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 63215e77d4698df65dfce5072b59df18500ff56daa3John Portotemplate <InstARM32::InstKindARM32 K> 63315e77d4698df65dfce5072b59df18500ff56daa3John Portoclass InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> { 63415e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32UnaryopSignAwareFP() = delete; 63515e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete; 63615e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32UnaryopSignAwareFP & 63715e77d4698df65dfce5072b59df18500ff56daa3John Porto operator=(const InstARM32UnaryopSignAwareFP &) = delete; 63815e77d4698df65dfce5072b59df18500ff56daa3John Porto 63915e77d4698df65dfce5072b59df18500ff56daa3John Portopublic: 64015e77d4698df65dfce5072b59df18500ff56daa3John Porto static InstARM32UnaryopSignAwareFP * 64115e77d4698df65dfce5072b59df18500ff56daa3John Porto create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) { 64215e77d4698df65dfce5072b59df18500ff56daa3John Porto return new (Func->allocate<InstARM32UnaryopSignAwareFP>()) 64315e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate); 64415e77d4698df65dfce5072b59df18500ff56daa3John Porto } 64515e77d4698df65dfce5072b59df18500ff56daa3John Porto void emitIAS(const Cfg *Func) const override; 64615e77d4698df65dfce5072b59df18500ff56daa3John Porto void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; } 64715e77d4698df65dfce5072b59df18500ff56daa3John Porto 64815e77d4698df65dfce5072b59df18500ff56daa3John Portoprivate: 64915e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src, 65015e77d4698df65dfce5072b59df18500ff56daa3John Porto CondARM32::Cond Predicate) 65115e77d4698df65dfce5072b59df18500ff56daa3John Porto : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {} 65215e77d4698df65dfce5072b59df18500ff56daa3John Porto}; 65315e77d4698df65dfce5072b59df18500ff56daa3John Porto 6549612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Instructions of the form x := x op y. 655b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <InstARM32::InstKindARM32 K> 6563bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32TwoAddrGPR : public InstARM32Pred { 657b3401d27a236b81393092b4d571df473b5bba64bJan Voung InstARM32TwoAddrGPR() = delete; 658b3401d27a236b81393092b4d571df473b5bba64bJan Voung InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; 659b3401d27a236b81393092b4d571df473b5bba64bJan Voung InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; 660b3401d27a236b81393092b4d571df473b5bba64bJan Voung 661b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic: 6629612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Dest must be a register. 6633bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 6643bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) { 665b3401d27a236b81393092b4d571df473b5bba64bJan Voung return new (Func->allocate<InstARM32TwoAddrGPR>()) 6663bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32TwoAddrGPR(Func, Dest, Src, Predicate); 667b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 668b3401d27a236b81393092b4d571df473b5bba64bJan Voung void emit(const Cfg *Func) const override { 66920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 670b3401d27a236b81393092b4d571df473b5bba64bJan Voung return; 671b3401d27a236b81393092b4d571df473b5bba64bJan Voung emitTwoAddr(Opcode, this, Func); 672b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 6732fee2a2f3379d82e2e7a5a2de1e66a5004d50f27Karl Schimpf void emitIAS(const Cfg *Func) const override; 674b3401d27a236b81393092b4d571df473b5bba64bJan Voung void dump(const Cfg *Func) const override { 67520b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 676b3401d27a236b81393092b4d571df473b5bba64bJan Voung return; 677b3401d27a236b81393092b4d571df473b5bba64bJan Voung Ostream &Str = Func->getContext()->getStrDump(); 678b3401d27a236b81393092b4d571df473b5bba64bJan Voung dumpDest(Func); 6793bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << " = "; 6803bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung dumpOpcodePred(Str, Opcode, getDest()->getType()); 6813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << " "; 682b3401d27a236b81393092b4d571df473b5bba64bJan Voung dumpSources(Func); 683b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 6848cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 685b3401d27a236b81393092b4d571df473b5bba64bJan Voung 686b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate: 6873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, 6883bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) 6893bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung : InstARM32Pred(Func, K, 2, Dest, Predicate) { 690b3401d27a236b81393092b4d571df473b5bba64bJan Voung addSource(Dest); 691b3401d27a236b81393092b4d571df473b5bba64bJan Voung addSource(Src); 692b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 6931bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 694b3401d27a236b81393092b4d571df473b5bba64bJan Voung static const char *Opcode; 695b3401d27a236b81393092b4d571df473b5bba64bJan Voung}; 696b3401d27a236b81393092b4d571df473b5bba64bJan Voung 69716991847500a48932426d979c4f2d4adffaf3649John Porto/// Base class for load instructions. 698b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <InstARM32::InstKindARM32 K> 69916991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32LoadBase : public InstARM32Pred { 70016991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32LoadBase() = delete; 70116991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32LoadBase(const InstARM32LoadBase &) = delete; 70216991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete; 703b3401d27a236b81393092b4d571df473b5bba64bJan Voung 704b3401d27a236b81393092b4d571df473b5bba64bJan Voungpublic: 70516991847500a48932426d979c4f2d4adffaf3649John Porto static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source, 70616991847500a48932426d979c4f2d4adffaf3649John Porto CondARM32::Cond Predicate) { 70716991847500a48932426d979c4f2d4adffaf3649John Porto return new (Func->allocate<InstARM32LoadBase>()) 70816991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32LoadBase(Func, Dest, Source, Predicate); 709b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 710b3401d27a236b81393092b4d571df473b5bba64bJan Voung void emit(const Cfg *Func) const override; 711f0655b6cebd64b393bdd4a51706c5ee3f229ce82Karl Schimpf void emitIAS(const Cfg *Func) const override; 712b3401d27a236b81393092b4d571df473b5bba64bJan Voung void dump(const Cfg *Func) const override { 71320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 714b3401d27a236b81393092b4d571df473b5bba64bJan Voung return; 715b3401d27a236b81393092b4d571df473b5bba64bJan Voung Ostream &Str = Func->getContext()->getStrDump(); 7163bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung dumpOpcodePred(Str, Opcode, getDest()->getType()); 7173bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << " "; 718b3401d27a236b81393092b4d571df473b5bba64bJan Voung dumpDest(Func); 719b3401d27a236b81393092b4d571df473b5bba64bJan Voung Str << ", "; 720b3401d27a236b81393092b4d571df473b5bba64bJan Voung dumpSources(Func); 721b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 7228cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 723b3401d27a236b81393092b4d571df473b5bba64bJan Voung 724b3401d27a236b81393092b4d571df473b5bba64bJan Voungprivate: 72516991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source, 72616991847500a48932426d979c4f2d4adffaf3649John Porto CondARM32::Cond Predicate) 7273bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung : InstARM32Pred(Func, K, 1, Dest, Predicate) { 728b3401d27a236b81393092b4d571df473b5bba64bJan Voung addSource(Source); 729b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 730b3401d27a236b81393092b4d571df473b5bba64bJan Voung 731b3401d27a236b81393092b4d571df473b5bba64bJan Voung static const char *Opcode; 732b3401d27a236b81393092b4d571df473b5bba64bJan Voung}; 733b3401d27a236b81393092b4d571df473b5bba64bJan Voung 7349612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Instructions of the form x := y op z. May have the side-effect of setting 7359612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// status flags. 7362971997a96b7484165cfedead111c7cafb3073aeJan Voungtemplate <InstARM32::InstKindARM32 K> 7373bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32ThreeAddrGPR : public InstARM32Pred { 7382971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32ThreeAddrGPR() = delete; 7392971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; 7402971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; 7412971997a96b7484165cfedead111c7cafb3073aeJan Voung 7422971997a96b7484165cfedead111c7cafb3073aeJan Voungpublic: 74357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1 74457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// must be registers. 7452971997a96b7484165cfedead111c7cafb3073aeJan Voung static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, 7466ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Variable *Src0, Operand *Src1, 7473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate, 7482971997a96b7484165cfedead111c7cafb3073aeJan Voung bool SetFlags = false) { 7492971997a96b7484165cfedead111c7cafb3073aeJan Voung return new (Func->allocate<InstARM32ThreeAddrGPR>()) 7506ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags); 7512971997a96b7484165cfedead111c7cafb3073aeJan Voung } 7522971997a96b7484165cfedead111c7cafb3073aeJan Voung void emit(const Cfg *Func) const override { 75320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 7542971997a96b7484165cfedead111c7cafb3073aeJan Voung return; 7552971997a96b7484165cfedead111c7cafb3073aeJan Voung emitThreeAddr(Opcode, this, Func, SetFlags); 7562971997a96b7484165cfedead111c7cafb3073aeJan Voung } 757372bdd6e84a14b6bcc00b4e9ed24a1838bd0c4d7Karl Schimpf void emitIAS(const Cfg *Func) const override; 7582971997a96b7484165cfedead111c7cafb3073aeJan Voung void dump(const Cfg *Func) const override { 75920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (!BuildDefs::dump()) 7602971997a96b7484165cfedead111c7cafb3073aeJan Voung return; 7612971997a96b7484165cfedead111c7cafb3073aeJan Voung Ostream &Str = Func->getContext()->getStrDump(); 7622971997a96b7484165cfedead111c7cafb3073aeJan Voung dumpDest(Func); 7633bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << " = "; 7643bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung dumpOpcodePred(Str, Opcode, getDest()->getType()); 7653bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Str << (SetFlags ? ".s " : " "); 7662971997a96b7484165cfedead111c7cafb3073aeJan Voung dumpSources(Func); 7672971997a96b7484165cfedead111c7cafb3073aeJan Voung } 7688cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 7692971997a96b7484165cfedead111c7cafb3073aeJan Voung 7702971997a96b7484165cfedead111c7cafb3073aeJan Voungprivate: 7716ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, 7726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Operand *Src1, CondARM32::Cond Predicate, bool SetFlags) 7733bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { 774ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto HasSideEffects = SetFlags; 7756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung addSource(Src0); 7762971997a96b7484165cfedead111c7cafb3073aeJan Voung addSource(Src1); 7772971997a96b7484165cfedead111c7cafb3073aeJan Voung } 7781bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 7792971997a96b7484165cfedead111c7cafb3073aeJan Voung static const char *Opcode; 7802971997a96b7484165cfedead111c7cafb3073aeJan Voung bool SetFlags; 7812971997a96b7484165cfedead111c7cafb3073aeJan Voung}; 7822971997a96b7484165cfedead111c7cafb3073aeJan Voung 78357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Instructions of the form x := y op z, for vector/FP. We leave these as 78486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// unconditional: "ARM deprecates the conditional execution of any instruction 78586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// encoding provided by the Advanced SIMD Extension that is not also provided 786eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// by the floating-point (VFP) extension". They do not set flags. 78786ebec12680b5268fcb7082f770a26394e8b8080Jan Voungtemplate <InstARM32::InstKindARM32 K> 78886ebec12680b5268fcb7082f770a26394e8b8080Jan Voungclass InstARM32ThreeAddrFP : public InstARM32 { 78986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32ThreeAddrFP() = delete; 79086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete; 79186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete; 79286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 79386ebec12680b5268fcb7082f770a26394e8b8080Jan Voungpublic: 79457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything 79557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// must be a register. 79686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0, 79786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Variable *Src1) { 79886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung return new (Func->allocate<InstARM32ThreeAddrFP>()) 79986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung InstARM32ThreeAddrFP(Func, Dest, Src0, Src1); 80086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 80186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void emit(const Cfg *Func) const override { 80286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung if (!BuildDefs::dump()) 80386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung return; 804a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType(); 805a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto emitThreeAddrFP(Opcode, Sign, this, Func, OpType); 80686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 8074acf11ac13716f5998b56cb65c1c72341276cc5fKarl Schimpf void emitIAS(const Cfg *Func) const override; 80886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void dump(const Cfg *Func) const override { 80986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung if (!BuildDefs::dump()) 81086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung return; 81186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung Ostream &Str = Func->getContext()->getStrDump(); 81286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung dumpDest(Func); 813a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType(); 814a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Str << " = " << Opcode << "." << OpType << " "; 81586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung dumpSources(Func); 81686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 8178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 81886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 81915e77d4698df65dfce5072b59df18500ff56daa3John Portoprotected: 82015e77d4698df65dfce5072b59df18500ff56daa3John Porto FPSign Sign = FS_None; 82115e77d4698df65dfce5072b59df18500ff56daa3John Porto 82215e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1) 82386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung : InstARM32(Func, K, 2, Dest) { 82486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung addSource(Src0); 82586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung addSource(Src1); 82686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 82786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 82886ebec12680b5268fcb7082f770a26394e8b8080Jan Voung static const char *Opcode; 829a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto 830a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portoprivate: 831a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto static constexpr bool isVectorCompare() { 832a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge; 833a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto } 83486ebec12680b5268fcb7082f770a26394e8b8080Jan Voung}; 83586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung 83615e77d4698df65dfce5072b59df18500ff56daa3John Portotemplate <InstARM32::InstKindARM32 K> 83715e77d4698df65dfce5072b59df18500ff56daa3John Portoclass InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> { 83815e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32ThreeAddrSignAwareFP() = delete; 83915e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete; 84015e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32ThreeAddrSignAwareFP & 84115e77d4698df65dfce5072b59df18500ff56daa3John Porto operator=(const InstARM32ThreeAddrSignAwareFP &) = delete; 84215e77d4698df65dfce5072b59df18500ff56daa3John Porto 84315e77d4698df65dfce5072b59df18500ff56daa3John Portopublic: 84415e77d4698df65dfce5072b59df18500ff56daa3John Porto /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything 84515e77d4698df65dfce5072b59df18500ff56daa3John Porto /// must be a register. 84615e77d4698df65dfce5072b59df18500ff56daa3John Porto static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest, 84715e77d4698df65dfce5072b59df18500ff56daa3John Porto Variable *Src0, Variable *Src1) { 84815e77d4698df65dfce5072b59df18500ff56daa3John Porto return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>()) 84915e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1); 85015e77d4698df65dfce5072b59df18500ff56daa3John Porto } 85115e77d4698df65dfce5072b59df18500ff56daa3John Porto 852e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto static InstARM32ThreeAddrSignAwareFP * 853e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) { 854e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>()) 855e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1); 856e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto } 857e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto 85815e77d4698df65dfce5072b59df18500ff56daa3John Porto void emitIAS(const Cfg *Func) const override; 85915e77d4698df65dfce5072b59df18500ff56daa3John Porto void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; } 86015e77d4698df65dfce5072b59df18500ff56daa3John Porto 86115e77d4698df65dfce5072b59df18500ff56daa3John Portoprivate: 86215e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0, 863e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Operand *Src1) 86415e77d4698df65dfce5072b59df18500ff56daa3John Porto : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {} 86515e77d4698df65dfce5072b59df18500ff56daa3John Porto}; 86615e77d4698df65dfce5072b59df18500ff56daa3John Porto 86786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate. 8686ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungtemplate <InstARM32::InstKindARM32 K> 8696ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32FourAddrGPR : public InstARM32Pred { 8706ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32FourAddrGPR() = delete; 8716ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete; 8726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete; 8736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 8746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic: 8756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung // Every operand must be a register. 8766ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0, 8776ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Variable *Src1, Variable *Src2, 8786ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Predicate) { 8796ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return new (Func->allocate<InstARM32FourAddrGPR>()) 8806ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate); 8816ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 8826ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void emit(const Cfg *Func) const override { 8836ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung if (!BuildDefs::dump()) 8846ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return; 8856ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung emitFourAddr(Opcode, this, Func); 8866ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 887080b65b5e73b17d39d1f08b84af3c075b3e46e77Karl Schimpf void emitIAS(const Cfg *Func) const override; 8886ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void dump(const Cfg *Func) const override { 8896ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung if (!BuildDefs::dump()) 8906ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return; 8916ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Ostream &Str = Func->getContext()->getStrDump(); 8926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung dumpDest(Func); 8936ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Str << " = "; 8946ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung dumpOpcodePred(Str, Opcode, getDest()->getType()); 8956ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Str << " "; 8966ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung dumpSources(Func); 8976ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 8988cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 8996ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 9006ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate: 9016ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, 9026ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Variable *Src1, Variable *Src2, 9036ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Predicate) 9046ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung : InstARM32Pred(Func, K, 3, Dest, Predicate) { 9056ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung addSource(Src0); 9066ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung addSource(Src1); 9076ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung addSource(Src2); 9086ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 9096ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 9106ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static const char *Opcode; 9116ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung}; 9126ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 913eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate. 914eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// We leave these as unconditional: "ARM deprecates the conditional execution 915eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// of any instruction encoding provided by the Advanced SIMD Extension that is 916eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// not also provided by the floating-point (VFP) extension". They do not set 917eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// flags. 918eb13acc6221f60642d17473b6329a82b02ae557aJohn Portotemplate <InstARM32::InstKindARM32 K> 919eb13acc6221f60642d17473b6329a82b02ae557aJohn Portoclass InstARM32FourAddrFP : public InstARM32 { 920eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto InstARM32FourAddrFP() = delete; 921eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete; 922eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete; 923eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto 924eb13acc6221f60642d17473b6329a82b02ae557aJohn Portopublic: 925eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto // Every operand must be a register. 926eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0, 927eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Variable *Src1) { 928eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto return new (Func->allocate<InstARM32FourAddrFP>()) 929eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto InstARM32FourAddrFP(Func, Dest, Src0, Src1); 930eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto } 931eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto void emit(const Cfg *Func) const override { 932eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto if (!BuildDefs::dump()) 933eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto return; 93415e77d4698df65dfce5072b59df18500ff56daa3John Porto emitFourAddrFP(Opcode, Sign, this, Func); 935eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto } 9368c5544b529f63c81e72dc4c70930dd07e5739d85Karl Schimpf void emitIAS(const Cfg *Func) const override; 937eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto void dump(const Cfg *Func) const override { 938eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto if (!BuildDefs::dump()) 939eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto return; 940eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Ostream &Str = Func->getContext()->getStrDump(); 941eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto dumpDest(Func); 942eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Str << " = "; 943eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Str << Opcode << "." << getDest()->getType() << " "; 944eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto dumpDest(Func); 945eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Str << ", "; 946eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto dumpSources(Func); 947eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto } 9488cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 949eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto 950eb13acc6221f60642d17473b6329a82b02ae557aJohn Portoprivate: 951eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1) 952eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto : InstARM32(Func, K, 3, Dest) { 953eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto addSource(Dest); 954eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto addSource(Src0); 955eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto addSource(Src1); 956eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto } 957eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto 95815e77d4698df65dfce5072b59df18500ff56daa3John Porto FPSign Sign = FS_None; 959eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto static const char *Opcode; 960eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto}; 961eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto 96286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung/// Instructions of the form x cmpop y (setting flags). 9636ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungtemplate <InstARM32::InstKindARM32 K> 9646ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32CmpLike : public InstARM32Pred { 9656ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32CmpLike() = delete; 9666ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32CmpLike(const InstARM32CmpLike &) = delete; 9676ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete; 9686ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 9696ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic: 9706ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1, 9716ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Predicate) { 9726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return new (Func->allocate<InstARM32CmpLike>()) 9736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32CmpLike(Func, Src0, Src1, Predicate); 9746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 9756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void emit(const Cfg *Func) const override { 9766ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung if (!BuildDefs::dump()) 9776ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return; 9786ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung emitCmpLike(Opcode, this, Func); 9796ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 980f8fc12f741cdbffaf82005d4f1324dc316d9d6dfKarl Schimpf void emitIAS(const Cfg *Func) const override; 9816ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void dump(const Cfg *Func) const override { 9826ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung if (!BuildDefs::dump()) 9836ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return; 9846ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Ostream &Str = Func->getContext()->getStrDump(); 9856ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung dumpOpcodePred(Str, Opcode, getSrc(0)->getType()); 9866ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Str << " "; 9876ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung dumpSources(Func); 9886ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 9898cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, K); } 9906ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 9916ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate: 9926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1, 9936ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Predicate) 9946ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung : InstARM32Pred(Func, K, 2, nullptr, Predicate) { 995ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto HasSideEffects = true; 9966ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung addSource(Src0); 9976ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung addSource(Src1); 9986ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 9996ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 10006ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static const char *Opcode; 10016ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung}; 10026ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 10038072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>; 10048072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>; 10058072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>; 10068072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>; 10078072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>; 10088072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>; 10098072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>; 10108072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>; 10118072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>; 10128072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>; 10138072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>; 1014ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portousing InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>; 10158072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>; 10168072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>; 10178072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>; 10188072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>; 10198072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>; 1020b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holkusing InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>; 1021397f602c4e4e5697806bf74e37a651ab78680628John Portousing InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>; 1022a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>; 1023a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>; 1024a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>; 10258072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>; 1026ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portousing InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>; 1027eb13acc6221f60642d17473b6329a82b02ae557aJohn Portousing InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>; 1028eb13acc6221f60642d17473b6329a82b02ae557aJohn Portousing InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>; 1029f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovl = InstARM32ThreeAddrFP<InstARM32::Vmovl>; 1030f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovh = InstARM32ThreeAddrFP<InstARM32::Vmovh>; 1031f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovhl = InstARM32ThreeAddrFP<InstARM32::Vmovhl>; 1032f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vmovlh = InstARM32ThreeAddrFP<InstARM32::Vmovlh>; 1033eb13acc6221f60642d17473b6329a82b02ae557aJohn Portousing InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>; 1034a4d100ab21814f39591684c59e4c4e113fa0f1f4John Portousing InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>; 103515e77d4698df65dfce5072b59df18500ff56daa3John Portousing InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>; 1036cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holkusing InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>; 1037b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlinusing InstARM32Vqadd = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>; 1038b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlinusing InstARM32Vqsub = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>; 1039675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vqmovn2 = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>; 1040675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vmulh = InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>; 1041675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vmlap = InstARM32ThreeAddrFP<InstARM32::Vmlap>; 104215e77d4698df65dfce5072b59df18500ff56daa3John Portousing InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>; 1043e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Portousing InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>; 10448072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>; 104516991847500a48932426d979c4f2d4adffaf3649John Portousing InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>; 104616991847500a48932426d979c4f2d4adffaf3649John Portousing InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>; 1047675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vldr1d = InstARM32LoadBase<InstARM32::Vldr1d>; 1048675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensusing InstARM32Vldr1q = InstARM32LoadBase<InstARM32::Vldr1q>; 1049f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensusing InstARM32Vzip = InstARM32ThreeAddrFP<InstARM32::Vzip>; 105057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// MovT leaves the bottom bits alone so dest is also a source. This helps 105157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// indicate that a previous MovW setting dest is not dead code. 10528072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>; 10538072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>; 10548072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>; 10558072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>; 10568072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>; 10578072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>; 105857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand 105957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't 106057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// using that for now, so just model as a Unaryop. 10618072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>; 10628072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>; 10638072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>; 10648072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>; 10658072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>; 1066ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Portousing InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>; 10678072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>; 10688072bae156fa62e51e02925997992c4908a2682fAndrew Scullusing InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>; 10696ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 107057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// InstARM32Label represents an intra-block label that is the target of an 107157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// intra-block branch. The offset between the label and the branch must be fit 107257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// in the instruction immediate (considered "near"). 10736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32Label : public InstARM32 { 10746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Label() = delete; 10756ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Label(const InstARM32Label &) = delete; 10766ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Label &operator=(const InstARM32Label &) = delete; 10776ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 10786ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic: 10796ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) { 10806ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target); 10816ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 10826ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung uint32_t getEmitInstCount() const override { return 0; } 1083467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth GlobalString getLabelName() const { return Name; } 10846ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung SizeT getNumber() const { return Number; } 10856ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void emit(const Cfg *Func) const override; 108650a3331c517ea0945987b616f4c5cf607aa81b9bKarl Schimpf void emitIAS(const Cfg *Func) const override; 10876ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void dump(const Cfg *Func) const override; 1088dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; } 10896ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 10906ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate: 10916ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Label(Cfg *Func, TargetARM32 *Target); 10926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 1093dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto RelocOffset *OffsetReloc = nullptr; 10946ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung SizeT Number; // used for unique label generation. 1095467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth GlobalString Name; 10966ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung}; 1097b3401d27a236b81393092b4d571df473b5bba64bJan Voung 10989612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Direct branch instruction. 10993bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Br : public InstARM32Pred { 11003bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Br() = delete; 11013bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Br(const InstARM32Br &) = delete; 11023bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Br &operator=(const InstARM32Br &) = delete; 11033bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 11043bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungpublic: 11059612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create a conditional branch to one of two nodes. 11063bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, 11073bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CfgNode *TargetFalse, CondARM32::Cond Predicate) { 11083bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung assert(Predicate != CondARM32::AL); 11096ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr InstARM32Label *NoLabel = nullptr; 11103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return new (Func->allocate<InstARM32Br>()) 11116ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate); 11123bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 11139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Create an unconditional branch to a node. 11143bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static InstARM32Br *create(Cfg *Func, CfgNode *Target) { 11156ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr CfgNode *NoCondTarget = nullptr; 11166ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr InstARM32Label *NoLabel = nullptr; 11173bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return new (Func->allocate<InstARM32Br>()) 11186ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL); 11193bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 112057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// Create a non-terminator conditional branch to a node, with a fallthrough 112157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// to the next instruction in the current node. This is used for switch 112257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// lowering. 11233bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static InstARM32Br *create(Cfg *Func, CfgNode *Target, 11243bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) { 11253bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung assert(Predicate != CondARM32::AL); 11266ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr CfgNode *NoUncondTarget = nullptr; 11276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr InstARM32Label *NoLabel = nullptr; 11286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return new (Func->allocate<InstARM32Br>()) 11296ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate); 11306ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 11316ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung // Create a conditional intra-block branch (or unconditional, if 11326ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung // Condition==AL) to a label in the current block. 11336ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static InstARM32Br *create(Cfg *Func, InstARM32Label *Label, 11346ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Predicate) { 11356ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr CfgNode *NoCondTarget = nullptr; 11366ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung constexpr CfgNode *NoUncondTarget = nullptr; 11373bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return new (Func->allocate<InstARM32Br>()) 11386ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate); 11393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 11403bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung const CfgNode *getTargetTrue() const { return TargetTrue; } 11413bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung const CfgNode *getTargetFalse() const { return TargetFalse; } 11423bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung bool optimizeBranch(const CfgNode *NextNode); 11433bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung uint32_t getEmitInstCount() const override { 11443bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung uint32_t Sum = 0; 11456ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung if (Label) 11466ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung ++Sum; 11473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung if (getTargetTrue()) 11483bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung ++Sum; 11493bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung if (getTargetFalse()) 11503bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung ++Sum; 11513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return Sum; 11523bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 11533bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung bool isUnconditionalBranch() const override { 11543bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return getPredicate() == CondARM32::AL; 11553bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 115687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 11573bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void emit(const Cfg *Func) const override; 1158137e62bd843313d4b8697621989e0e6f5c2e7f81Karl Schimpf void emitIAS(const Cfg *Func) const override; 11593bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void dump(const Cfg *Func) const override; 11608cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Br); } 11613bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 11623bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungprivate: 11633bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 11646ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung const InstARM32Label *Label, CondARM32::Cond Predicate); 11651bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 11663bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung const CfgNode *TargetTrue; 11673bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung const CfgNode *TargetFalse; 11686ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung const InstARM32Label *Label; // Intra-block branch target 11693bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung}; 11703bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 117157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Call instruction (bl/blx). Arguments should have already been pushed. 11729612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Technically bl and the register form of blx can be predicated, but we'll 11739612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// leave that out until needed. 11743bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Call : public InstARM32 { 11753bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Call() = delete; 11763bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Call(const InstARM32Call &) = delete; 11773bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Call &operator=(const InstARM32Call &) = delete; 11783bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 11793bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungpublic: 11803bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { 11813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung return new (Func->allocate<InstARM32Call>()) 11823bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Call(Func, Dest, CallTarget); 11833bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 11843bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Operand *getCallTarget() const { return getSrc(0); } 11853bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void emit(const Cfg *Func) const override; 1186174531ec83bf9d51b2dc669b3f73f1fb637fbcceKarl Schimpf void emitIAS(const Cfg *Func) const override; 11873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void dump(const Cfg *Func) const override; 11888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Call); } 11893bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 11903bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungprivate: 11913bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); 11923bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung}; 11933bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung 1194c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfclass InstARM32RegisterStackOp : public InstARM32 { 1195c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf InstARM32RegisterStackOp() = delete; 1196c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete; 1197c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf InstARM32RegisterStackOp & 1198c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf operator=(const InstARM32RegisterStackOp &) = delete; 1199c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf 1200c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfpublic: 1201c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emit(const Cfg *Func) const override; 1202c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitIAS(const Cfg *Func) const override; 1203c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void dump(const Cfg *Func) const override; 1204c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf 1205c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpfprotected: 1206c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, 1207c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf Variable *Dest) 1208c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf : InstARM32(Func, Kind, Maxsrcs, Dest) {} 1209c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitUsingForm(const Cfg *Func, const EmitForm Form) const; 1210c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitGPRsAsText(const Cfg *Func) const; 1211c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg, 1212c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf SizeT Regcount) const; 121300c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpf void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg, 121400c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpf SizeT RegCount, SizeT InstIndex) const; 1215c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual const char *getDumpOpcode() const { return getGPROpcode(); } 1216c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual const char *getGPROpcode() const = 0; 1217c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual const char *getSRegOpcode() const = 0; 1218c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual Variable *getStackReg(SizeT Index) const = 0; 1219c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual SizeT getNumStackRegs() const = 0; 1220c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form, 1221c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf const Variable *Reg) const = 0; 1222c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form, 1223c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf IValueT Registers) const = 0; 1224c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual void emitSRegs(const Cfg *Func, const EmitForm Form, 1225c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf const Variable *BaseReg, SizeT RegCount) const = 0; 1226c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf}; 1227c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf 1228eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s" 1229eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// regs, but not both. In any case, the list must be sorted. 123000c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpfclass InstARM32Pop final : public InstARM32RegisterStackOp { 12310fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Pop() = delete; 12320fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Pop(const InstARM32Pop &) = delete; 12330fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Pop &operator=(const InstARM32Pop &) = delete; 12340fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 12350fa6c5a062f465360448a672abed3b916b413ca8Jan Voungpublic: 12360fa6c5a062f465360448a672abed3b916b413ca8Jan Voung static InstARM32Pop *create(Cfg *Func, const VarList &Dests) { 12370fa6c5a062f465360448a672abed3b916b413ca8Jan Voung return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests); 12380fa6c5a062f465360448a672abed3b916b413ca8Jan Voung } 12398cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); } 12400fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 12410fa6c5a062f465360448a672abed3b916b413ca8Jan Voungprivate: 12420fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Pop(Cfg *Func, const VarList &Dests); 1243c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual const char *getGPROpcode() const final; 1244c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf virtual const char *getSRegOpcode() const final; 1245c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf Variable *getStackReg(SizeT Index) const final; 1246c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf SizeT getNumStackRegs() const final; 1247c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitSingleGPR(const Cfg *Func, const EmitForm Form, 1248c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf const Variable *Reg) const final; 1249c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitMultipleGPRs(const Cfg *Func, const EmitForm Form, 1250c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf IValueT Registers) const final; 1251c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg, 1252c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf SizeT RegCount) const final; 12530fa6c5a062f465360448a672abed3b916b413ca8Jan Voung VarList Dests; 12540fa6c5a062f465360448a672abed3b916b413ca8Jan Voung}; 12550fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 1256eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// Pushes a list of registers. Just like Pop (see above), the list may be of 1257eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto/// GPRs, or VFP "s" registers, but not both. 125800c30380f299239b4782a0fd1ad1d580d12af649Karl Schimpfclass InstARM32Push final : public InstARM32RegisterStackOp { 12590fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Push() = delete; 12600fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Push(const InstARM32Push &) = delete; 12610fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Push &operator=(const InstARM32Push &) = delete; 12620fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 12630fa6c5a062f465360448a672abed3b916b413ca8Jan Voungpublic: 12640fa6c5a062f465360448a672abed3b916b413ca8Jan Voung static InstARM32Push *create(Cfg *Func, const VarList &Srcs) { 12650fa6c5a062f465360448a672abed3b916b413ca8Jan Voung return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs); 12660fa6c5a062f465360448a672abed3b916b413ca8Jan Voung } 12678cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Push); } 12680fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 12690fa6c5a062f465360448a672abed3b916b413ca8Jan Voungprivate: 12700fa6c5a062f465360448a672abed3b916b413ca8Jan Voung InstARM32Push(Cfg *Func, const VarList &Srcs); 1271c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf const char *getGPROpcode() const final; 1272c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf const char *getSRegOpcode() const final; 1273c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf Variable *getStackReg(SizeT Index) const final; 1274c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf SizeT getNumStackRegs() const final; 1275c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitSingleGPR(const Cfg *Func, const EmitForm Form, 1276c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf const Variable *Reg) const final; 1277c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitMultipleGPRs(const Cfg *Func, const EmitForm Form, 1278c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf IValueT Registers) const final; 1279c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg, 1280c411dbf1c868911d4d300c6bf1ca6caa62592a1cKarl Schimpf SizeT RegCount) const final; 12810fa6c5a062f465360448a672abed3b916b413ca8Jan Voung}; 12820fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 128357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr" 128457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// register operand, but epilogue lowering will search for a Ret instead of a 128557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// generic "bx". This instruction also takes a Source operand (for non-void 128657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// returning functions) for liveness analysis, though a FakeUse before the ret 128757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// would do just as well. 12889612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 12899612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// NOTE: Even though "bx" can be predicated, for now leave out the predication 12909612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// since it's not yet known to be useful for Ret. That may complicate finding 12919612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// the terminator instruction if it's not guaranteed to be executed. 1292b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungclass InstARM32Ret : public InstARM32 { 1293b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32Ret() = delete; 1294b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32Ret(const InstARM32Ret &) = delete; 1295b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32Ret &operator=(const InstARM32Ret &) = delete; 1296b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 1297b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungpublic: 1298b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung static InstARM32Ret *create(Cfg *Func, Variable *LR, 1299b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung Variable *Source = nullptr) { 1300b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); 1301b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung } 1302b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung void emit(const Cfg *Func) const override; 1303b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung void emitIAS(const Cfg *Func) const override; 1304b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung void dump(const Cfg *Func) const override; 13058cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); } 1306b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 1307b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voungprivate: 1308b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); 1309b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung}; 1310b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 131157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store instruction. It's important for liveness that there is no Dest operand 131257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// (OperandARM32Mem instead of Dest Variable). 131316991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32Str final : public InstARM32Pred { 1314befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung InstARM32Str() = delete; 1315befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung InstARM32Str(const InstARM32Str &) = delete; 1316befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung InstARM32Str &operator=(const InstARM32Str &) = delete; 1317befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung 1318befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voungpublic: 13199612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Value must be a register. 1320befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1321befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung CondARM32::Cond Predicate) { 1322befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung return new (Func->allocate<InstARM32Str>()) 1323befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung InstARM32Str(Func, Value, Mem, Predicate); 1324befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung } 1325befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung void emit(const Cfg *Func) const override; 1326f0655b6cebd64b393bdd4a51706c5ee3f229ce82Karl Schimpf void emitIAS(const Cfg *Func) const override; 1327befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung void dump(const Cfg *Func) const override; 13288cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Str); } 1329befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung 1330befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voungprivate: 1331befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1332befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung CondARM32::Cond Predicate); 1333befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung}; 1334befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung 133516991847500a48932426d979c4f2d4adffaf3649John Porto/// Exclusive Store instruction. Like its non-exclusive sibling, it's important 133616991847500a48932426d979c4f2d4adffaf3649John Porto/// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest 133716991847500a48932426d979c4f2d4adffaf3649John Porto/// Variable). 133816991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32Strex final : public InstARM32Pred { 133916991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Strex() = delete; 134016991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Strex(const InstARM32Strex &) = delete; 134116991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Strex &operator=(const InstARM32Strex &) = delete; 134216991847500a48932426d979c4f2d4adffaf3649John Porto 134316991847500a48932426d979c4f2d4adffaf3649John Portopublic: 134416991847500a48932426d979c4f2d4adffaf3649John Porto /// Value must be a register. 134516991847500a48932426d979c4f2d4adffaf3649John Porto static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value, 134616991847500a48932426d979c4f2d4adffaf3649John Porto OperandARM32Mem *Mem, 134716991847500a48932426d979c4f2d4adffaf3649John Porto CondARM32::Cond Predicate) { 134816991847500a48932426d979c4f2d4adffaf3649John Porto return new (Func->allocate<InstARM32Strex>()) 134916991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Strex(Func, Dest, Value, Mem, Predicate); 135016991847500a48932426d979c4f2d4adffaf3649John Porto } 135116991847500a48932426d979c4f2d4adffaf3649John Porto void emit(const Cfg *Func) const override; 13524175d45e14cf1eb0af11e0458a873e601dc395deKarl Schimpf void emitIAS(const Cfg *Func) const override; 135316991847500a48932426d979c4f2d4adffaf3649John Porto void dump(const Cfg *Func) const override; 13548cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); } 135516991847500a48932426d979c4f2d4adffaf3649John Porto 135616991847500a48932426d979c4f2d4adffaf3649John Portoprivate: 135716991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value, 135816991847500a48932426d979c4f2d4adffaf3649John Porto OperandARM32Mem *Mem, CondARM32::Cond Predicate); 135916991847500a48932426d979c4f2d4adffaf3649John Porto}; 136016991847500a48932426d979c4f2d4adffaf3649John Porto 1361675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens/// Sub-vector store instruction. It's important for liveness that there is no 1362675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens/// Dest operand (OperandARM32Mem instead of Dest Variable). 1363675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensclass InstARM32Vstr1 final : public InstARM32Pred { 1364675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens InstARM32Vstr1() = delete; 1365675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens InstARM32Vstr1(const InstARM32Vstr1 &) = delete; 1366675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens InstARM32Vstr1 &operator=(const InstARM32Vstr1 &) = delete; 1367675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens 1368675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capenspublic: 1369675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens /// Value must be a register. 1370675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens static InstARM32Vstr1 *create(Cfg *Func, Variable *Value, 1371675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens OperandARM32Mem *Mem, CondARM32::Cond Predicate, 1372675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens SizeT Size) { 1373675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens return new (Func->allocate<InstARM32Vstr1>()) 1374675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens InstARM32Vstr1(Func, Value, Mem, Predicate, Size); 1375675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 1376675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void emit(const Cfg *Func) const override; 1377675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void emitIAS(const Cfg *Func) const override; 1378675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void dump(const Cfg *Func) const override; 1379675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens static bool classof(const Inst *Instr) { return isClassof(Instr, Vstr1); } 1380675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens 1381675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capensprivate: 1382675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, 1383675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens CondARM32::Cond Predicate, SizeT Size); 1384675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens 1385675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens SizeT Size; 1386675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens}; 1387675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens 1388f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens/// Vector element duplication/replication instruction. 1389f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensclass InstARM32Vdup final : public InstARM32Pred { 1390f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens InstARM32Vdup() = delete; 1391f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens InstARM32Vdup(const InstARM32Vdup &) = delete; 1392f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens InstARM32Vdup &operator=(const InstARM32Vdup &) = delete; 1393f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens 1394f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capenspublic: 1395f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens /// Value must be a register. 1396f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens static InstARM32Vdup *create(Cfg *Func, Variable *Dest, Variable *Src, 1397f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens IValueT Idx) { 1398f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens return new (Func->allocate<InstARM32Vdup>()) 1399f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens InstARM32Vdup(Func, Dest, Src, Idx); 1400f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 1401f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void emit(const Cfg *Func) const override; 1402f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void emitIAS(const Cfg *Func) const override; 1403f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void dump(const Cfg *Func) const override; 1404f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens static bool classof(const Inst *Instr) { return isClassof(Instr, Vdup); } 1405f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens 1406f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capensprivate: 1407f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src, IValueT Idx); 1408f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens 1409f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens const IValueT Idx; 1410f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens}; 1411f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens 14126ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass InstARM32Trap : public InstARM32 { 14136ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Trap() = delete; 14146ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Trap(const InstARM32Trap &) = delete; 14156ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung InstARM32Trap &operator=(const InstARM32Trap &) = delete; 14166ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 14176ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic: 14186ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung static InstARM32Trap *create(Cfg *Func) { 14196ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func); 14206ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 14216ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void emit(const Cfg *Func) const override; 14226ddabc17eb7f79e9f6c63174a65380c8fa69c630Karl Schimpf void emitIAS(const Cfg *Func) const override; 14236ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void dump(const Cfg *Func) const override; 14248cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); } 14256ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 14266ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate: 14276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung explicit InstARM32Trap(Cfg *Func); 14286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung}; 14296ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 14309612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// Unsigned Multiply Long: d.lo, d.hi := x * y 14313bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voungclass InstARM32Umull : public InstARM32Pred { 14322971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32Umull() = delete; 14332971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32Umull(const InstARM32Umull &) = delete; 14342971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32Umull &operator=(const InstARM32Umull &) = delete; 14352971997a96b7484165cfedead111c7cafb3073aeJan Voung 14362971997a96b7484165cfedead111c7cafb3073aeJan Voungpublic: 14379612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Everything must be a register. 14382971997a96b7484165cfedead111c7cafb3073aeJan Voung static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, 14393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Variable *Src0, Variable *Src1, 14403bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Predicate) { 14412971997a96b7484165cfedead111c7cafb3073aeJan Voung return new (Func->allocate<InstARM32Umull>()) 14423bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); 14432971997a96b7484165cfedead111c7cafb3073aeJan Voung } 14442971997a96b7484165cfedead111c7cafb3073aeJan Voung void emit(const Cfg *Func) const override; 1445430e84471a54f6e5a1727054be28680e489cf28dKarl Schimpf void emitIAS(const Cfg *Func) const override; 14462971997a96b7484165cfedead111c7cafb3073aeJan Voung void dump(const Cfg *Func) const override; 14478cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); } 14482971997a96b7484165cfedead111c7cafb3073aeJan Voung 14492971997a96b7484165cfedead111c7cafb3073aeJan Voungprivate: 14502971997a96b7484165cfedead111c7cafb3073aeJan Voung InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, 14513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Variable *Src1, CondARM32::Cond Predicate); 14521bec8bcd64da0cd4855a357d740d3ad45bbef3b9John Porto 14532971997a96b7484165cfedead111c7cafb3073aeJan Voung Variable *DestHi; 14542971997a96b7484165cfedead111c7cafb3073aeJan Voung}; 14552971997a96b7484165cfedead111c7cafb3073aeJan Voung 1456c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto/// Handles fp2int, int2fp, and fp2fp conversions. 1457c31e2ed72ed52bb40e0591dd97b6d6d071631655John Portoclass InstARM32Vcvt final : public InstARM32Pred { 1458c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto InstARM32Vcvt() = delete; 1459c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto InstARM32Vcvt(const InstARM32Vcvt &) = delete; 1460c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete; 1461c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto 1462c31e2ed72ed52bb40e0591dd97b6d6d071631655John Portopublic: 1463e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto enum VcvtVariant { 1464e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto S2si, 1465e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto S2ui, 1466e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Si2s, 1467e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Ui2s, 1468e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto D2si, 1469e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto D2ui, 1470e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Si2d, 1471e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Ui2d, 1472e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto S2d, 1473e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto D2s, 1474e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Vs2si, 1475e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Vs2ui, 1476e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Vsi2s, 1477e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Vui2s, 1478e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto }; 1479c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src, 1480c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto VcvtVariant Variant, CondARM32::Cond Predicate) { 1481c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto return new (Func->allocate<InstARM32Vcvt>()) 1482c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto InstARM32Vcvt(Func, Dest, Src, Variant, Predicate); 1483c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto } 1484c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto void emit(const Cfg *Func) const override; 14856c7181c5d3f082cbc04b58dd4745253139ad51e0Karl Schimpf void emitIAS(const Cfg *Func) const override; 1486c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto void dump(const Cfg *Func) const override; 14878cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); } 1488c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto 1489c31e2ed72ed52bb40e0591dd97b6d6d071631655John Portoprivate: 1490c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant, 1491c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto CondARM32::Cond Predicate); 1492c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto 1493c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto const VcvtVariant Variant; 1494c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto}; 1495c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto 1496f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto/// Handles (some of) vmov's various formats. 1497ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoclass InstARM32Mov final : public InstARM32Pred { 1498ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Mov() = delete; 1499ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Mov(const InstARM32Mov &) = delete; 1500ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Mov &operator=(const InstARM32Mov &) = delete; 1501f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto 1502f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Portopublic: 1503ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src, 1504ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto CondARM32::Cond Predicate) { 1505ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto return new (Func->allocate<InstARM32Mov>()) 1506ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Mov(Func, Dest, Src, Predicate); 1507f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto } 1508f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto bool isRedundantAssign() const override { 1509ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto return !isMultiDest() && !isMultiSource() && 15107b3d9cbb1c1697e03c616162382d945f35c37347John Porto getPredicate() == CondARM32::AL && 1511f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto checkForRedundantAssign(getDest(), getSrc(0)); 1512f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto } 151328b71be495bb1eada446ba36b5236914d79cea0eJim Stichnoth bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); } 1514f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto void emit(const Cfg *Func) const override; 1515f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto void emitIAS(const Cfg *Func) const override; 1516f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto void dump(const Cfg *Func) const override; 15178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); } 1518f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto 1519e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto bool isMultiDest() const { return DestHi != nullptr; } 1520f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto 1521f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto bool isMultiSource() const { 1522e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto assert(getSrcSize() == 1 || getSrcSize() == 2); 1523e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto return getSrcSize() == 2; 1524ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto } 1525ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto 1526e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto Variable *getDestHi() const { return DestHi; } 1527e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto 1528ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoprivate: 1529ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src, 1530e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto CondARM32::Cond Predicate); 1531f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto void emitMultiDestSingleSource(const Cfg *Func) const; 1532f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto void emitSingleDestMultiSource(const Cfg *Func) const; 1533f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto void emitSingleDestSingleSource(const Cfg *Func) const; 1534e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto 1535e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto Variable *DestHi = nullptr; 1536f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto}; 1537f977f7157088e2fd3de41c2acf4c62bfd655f15aJohn Porto 1538658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// Generates vmov Rd, Dn[x] instructions, and their related floating point 1539658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// versions. 1540658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkclass InstARM32Extract final : public InstARM32Pred { 1541658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Extract() = delete; 1542658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Extract(const InstARM32Extract &) = delete; 1543658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Extract &operator=(const InstARM32Extract &) = delete; 1544658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1545658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkpublic: 1546658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0, 1547658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk uint32_t Index, CondARM32::Cond Predicate) { 1548658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk return new (Func->allocate<InstARM32Extract>()) 1549658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Extract(Func, Dest, Src0, Index, Predicate); 1550658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 1551658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk void emit(const Cfg *Func) const override; 15526de32b2199915462a4216399ff0f3af31ec88015Karl Schimpf void emitIAS(const Cfg *Func) const override; 1553658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); } 1554658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1555658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkprivate: 1556658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index, 1557658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk CondARM32::Cond Predicate) 1558658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate), 1559658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk Index(Index) { 1560658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk assert(Index < typeNumElements(Src0->getType())); 1561658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk addSource(Src0); 1562658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 1563658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1564658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk const uint32_t Index; 1565658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk}; 1566658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1567658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// Generates vmov Dn[x], Rd instructions, and their related floating point 1568658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk/// versions. 1569658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkclass InstARM32Insert final : public InstARM32Pred { 1570658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Insert() = delete; 1571658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Insert(const InstARM32Insert &) = delete; 1572658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Insert &operator=(const InstARM32Insert &) = delete; 1573658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1574658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkpublic: 1575658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0, 1576658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk uint32_t Index, CondARM32::Cond Predicate) { 1577658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk return new (Func->allocate<InstARM32Insert>()) 1578658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Insert(Func, Dest, Src0, Index, Predicate); 1579658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 1580658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk void emit(const Cfg *Func) const override; 15816de32b2199915462a4216399ff0f3af31ec88015Karl Schimpf void emitIAS(const Cfg *Func) const override; 1582658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); } 1583658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1584658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holkprivate: 1585658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index, 1586658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk CondARM32::Cond Predicate) 1587658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate), 1588658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk Index(Index) { 1589658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk assert(Index < typeNumElements(Dest->getType())); 1590658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk addSource(Src0); 1591658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 1592658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 1593658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk const uint32_t Index; 1594658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk}; 1595658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 15962f5534f1c523eb022880360864f60ce42fb30ee0John Portoclass InstARM32Vcmp final : public InstARM32Pred { 15972f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vcmp() = delete; 15982f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vcmp(const InstARM32Vcmp &) = delete; 15992f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete; 16002f5534f1c523eb022880360864f60ce42fb30ee0John Porto 16012f5534f1c523eb022880360864f60ce42fb30ee0John Portopublic: 16022f5534f1c523eb022880360864f60ce42fb30ee0John Porto static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1, 16032f5534f1c523eb022880360864f60ce42fb30ee0John Porto CondARM32::Cond Predicate) { 16042f5534f1c523eb022880360864f60ce42fb30ee0John Porto return new (Func->allocate<InstARM32Vcmp>()) 16052f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vcmp(Func, Src0, Src1, Predicate); 16062f5534f1c523eb022880360864f60ce42fb30ee0John Porto } 1607ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, 1608ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto OperandARM32FlexFpZero *Src1, 1609ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Predicate) { 1610ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto return new (Func->allocate<InstARM32Vcmp>()) 1611ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto InstARM32Vcmp(Func, Src0, Src1, Predicate); 1612ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 16132f5534f1c523eb022880360864f60ce42fb30ee0John Porto void emit(const Cfg *Func) const override; 1614cd5e07ec935e179d4d087379afb480c3897d8316Karl Schimpf void emitIAS(const Cfg *Func) const override; 16152f5534f1c523eb022880360864f60ce42fb30ee0John Porto void dump(const Cfg *Func) const override; 16168cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); } 16172f5534f1c523eb022880360864f60ce42fb30ee0John Porto 16182f5534f1c523eb022880360864f60ce42fb30ee0John Portoprivate: 1619ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1, 16202f5534f1c523eb022880360864f60ce42fb30ee0John Porto CondARM32::Cond Predicate); 16212f5534f1c523eb022880360864f60ce42fb30ee0John Porto}; 16222f5534f1c523eb022880360864f60ce42fb30ee0John Porto 16232f5534f1c523eb022880360864f60ce42fb30ee0John Porto/// Copies the FP Status and Control Register the core flags. 16242f5534f1c523eb022880360864f60ce42fb30ee0John Portoclass InstARM32Vmrs final : public InstARM32Pred { 16252f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vmrs() = delete; 16262f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vmrs(const InstARM32Vmrs &) = delete; 16272f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete; 16282f5534f1c523eb022880360864f60ce42fb30ee0John Porto 16292f5534f1c523eb022880360864f60ce42fb30ee0John Portopublic: 16302f5534f1c523eb022880360864f60ce42fb30ee0John Porto static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) { 16312f5534f1c523eb022880360864f60ce42fb30ee0John Porto return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate); 16322f5534f1c523eb022880360864f60ce42fb30ee0John Porto } 16332f5534f1c523eb022880360864f60ce42fb30ee0John Porto void emit(const Cfg *Func) const override; 1634ee7182759bc8e9acc9a8622e73ac315c4d2dd601Karl Schimpf void emitIAS(const Cfg *Func) const override; 16352f5534f1c523eb022880360864f60ce42fb30ee0John Porto void dump(const Cfg *Func) const override; 16368cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); } 16372f5534f1c523eb022880360864f60ce42fb30ee0John Porto 16382f5534f1c523eb022880360864f60ce42fb30ee0John Portoprivate: 16392f5534f1c523eb022880360864f60ce42fb30ee0John Porto InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate); 16402f5534f1c523eb022880360864f60ce42fb30ee0John Porto}; 16412f5534f1c523eb022880360864f60ce42fb30ee0John Porto 1642ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoclass InstARM32Vabs final : public InstARM32Pred { 1643ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Vabs() = delete; 1644ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Vabs(const InstARM32Vabs &) = delete; 1645ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Vabs &operator=(const InstARM32Vabs &) = delete; 1646ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto 1647ba6a67c960a126d85b94a87c8ea7358bec0da048John Portopublic: 1648ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src, 1649ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto CondARM32::Cond Predicate) { 1650ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto return new (Func->allocate<InstARM32Vabs>()) 1651ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Vabs(Func, Dest, Src, Predicate); 1652ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto } 1653ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto void emit(const Cfg *Func) const override; 1654bd4356d59ef318d8c82f3ef0c879dce147bb3146Karl Schimpf void emitIAS(const Cfg *Func) const override; 1655ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto void dump(const Cfg *Func) const override; 16568cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); } 1657ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto 1658ba6a67c960a126d85b94a87c8ea7358bec0da048John Portoprivate: 1659ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src, 1660ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto CondARM32::Cond Predicate); 1661ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto}; 166216991847500a48932426d979c4f2d4adffaf3649John Porto 166316991847500a48932426d979c4f2d4adffaf3649John Portoclass InstARM32Dmb final : public InstARM32Pred { 166416991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Dmb() = delete; 166516991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Dmb(const InstARM32Dmb &) = delete; 166616991847500a48932426d979c4f2d4adffaf3649John Porto InstARM32Dmb &operator=(const InstARM32Dmb &) = delete; 166716991847500a48932426d979c4f2d4adffaf3649John Porto 166816991847500a48932426d979c4f2d4adffaf3649John Portopublic: 166916991847500a48932426d979c4f2d4adffaf3649John Porto static InstARM32Dmb *create(Cfg *Func) { 167016991847500a48932426d979c4f2d4adffaf3649John Porto return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func); 167116991847500a48932426d979c4f2d4adffaf3649John Porto } 167216991847500a48932426d979c4f2d4adffaf3649John Porto void emit(const Cfg *Func) const override; 1673d3f94f7ef3e6999a7a31641096b70536af46f3f5Karl Schimpf void emitIAS(const Cfg *Func) const override; 167416991847500a48932426d979c4f2d4adffaf3649John Porto void dump(const Cfg *Func) const override; 16758cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); } 167616991847500a48932426d979c4f2d4adffaf3649John Porto 167716991847500a48932426d979c4f2d4adffaf3649John Portoprivate: 167816991847500a48932426d979c4f2d4adffaf3649John Porto explicit InstARM32Dmb(Cfg *Func); 167916991847500a48932426d979c4f2d4adffaf3649John Porto}; 168016991847500a48932426d979c4f2d4adffaf3649John Porto 1681f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpfclass InstARM32Nop final : public InstARM32Pred { 1682f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf InstARM32Nop() = delete; 1683f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf InstARM32Nop(const InstARM32Nop &) = delete; 1684f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf InstARM32Nop &operator=(const InstARM32Nop &) = delete; 1685f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf 1686f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpfpublic: 1687f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf static InstARM32Nop *create(Cfg *Func) { 1688f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func); 1689f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf } 1690f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf void emit(const Cfg *Func) const override; 1691f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf void emitIAS(const Cfg *Func) const override; 1692f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf void dump(const Cfg *Func) const override; 1693f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); } 1694f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf 1695f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpfprivate: 1696f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf explicit InstARM32Nop(Cfg *Func); 1697f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf}; 1698f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf 169957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Declare partial template specializations of emit() methods that already have 170057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// default implementations. Without this, there is the possibility of ODR 170157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// violations and link errors. 1702b3401d27a236b81393092b4d571df473b5bba64bJan Voung 170386ebec12680b5268fcb7082f770a26394e8b8080Jan Voungtemplate <> void InstARM32Ldr::emit(const Cfg *Func) const; 1704b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <> void InstARM32Movw::emit(const Cfg *Func) const; 1705b3401d27a236b81393092b4d571df473b5bba64bJan Voungtemplate <> void InstARM32Movt::emit(const Cfg *Func) const; 1706675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capenstemplate <> void InstARM32Vldr1d::emit(const Cfg *Func) const; 1707675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capenstemplate <> void InstARM32Vldr1q::emit(const Cfg *Func) const; 1708b3401d27a236b81393092b4d571df473b5bba64bJan Voung 17094a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto} // end of namespace ARM32 1710b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung} // end of namespace Ice 1711b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1712b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#endif // SUBZERO_SRC_ICEINSTARM32_H 1713