1327952Sdim//===- HexagonBitTracker.cpp ----------------------------------------------===// 2286425Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6286425Sdim// 7286425Sdim//===----------------------------------------------------------------------===// 8286425Sdim 9321369Sdim#include "HexagonBitTracker.h" 10286425Sdim#include "Hexagon.h" 11286425Sdim#include "HexagonInstrInfo.h" 12286425Sdim#include "HexagonRegisterInfo.h" 13327952Sdim#include "HexagonSubtarget.h" 14327952Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 15314564Sdim#include "llvm/CodeGen/MachineFunction.h" 16314564Sdim#include "llvm/CodeGen/MachineInstr.h" 17314564Sdim#include "llvm/CodeGen/MachineOperand.h" 18314564Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 19327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h" 20314564Sdim#include "llvm/IR/Argument.h" 21314564Sdim#include "llvm/IR/Attributes.h" 22314564Sdim#include "llvm/IR/Function.h" 23314564Sdim#include "llvm/IR/Type.h" 24327952Sdim#include "llvm/Support/Compiler.h" 25314564Sdim#include "llvm/Support/Debug.h" 26314564Sdim#include "llvm/Support/ErrorHandling.h" 27314564Sdim#include "llvm/Support/MathExtras.h" 28314564Sdim#include "llvm/Support/raw_ostream.h" 29314564Sdim#include <cassert> 30314564Sdim#include <cstddef> 31314564Sdim#include <cstdint> 32314564Sdim#include <cstdlib> 33314564Sdim#include <utility> 34314564Sdim#include <vector> 35286425Sdim 36286425Sdimusing namespace llvm; 37286425Sdim 38327952Sdimusing BT = BitTracker; 39286425Sdim 40286425SdimHexagonEvaluator::HexagonEvaluator(const HexagonRegisterInfo &tri, 41286425Sdim MachineRegisterInfo &mri, 42286425Sdim const HexagonInstrInfo &tii, 43286425Sdim MachineFunction &mf) 44314564Sdim : MachineEvaluator(tri, mri), MF(mf), MFI(mf.getFrameInfo()), TII(tii) { 45286425Sdim // Populate the VRX map (VR to extension-type). 46286425Sdim // Go over all the formal parameters of the function. If a given parameter 47286425Sdim // P is sign- or zero-extended, locate the virtual register holding that 48286425Sdim // parameter and create an entry in the VRX map indicating the type of ex- 49286425Sdim // tension (and the source type). 50286425Sdim // This is a bit complicated to do accurately, since the memory layout in- 51286425Sdim // formation is necessary to precisely determine whether an aggregate para- 52286425Sdim // meter will be passed in a register or in memory. What is given in MRI 53286425Sdim // is the association between the physical register that is live-in (i.e. 54286425Sdim // holds an argument), and the virtual register that this value will be 55286425Sdim // copied into. This, by itself, is not sufficient to map back the virtual 56286425Sdim // register to a formal parameter from Function (since consecutive live-ins 57286425Sdim // from MRI may not correspond to consecutive formal parameters from Func- 58286425Sdim // tion). To avoid the complications with in-memory arguments, only consi- 59286425Sdim // der the initial sequence of formal parameters that are known to be 60286425Sdim // passed via registers. 61286425Sdim unsigned InVirtReg, InPhysReg = 0; 62327952Sdim 63327952Sdim for (const Argument &Arg : MF.getFunction().args()) { 64286425Sdim Type *ATy = Arg.getType(); 65286425Sdim unsigned Width = 0; 66286425Sdim if (ATy->isIntegerTy()) 67286425Sdim Width = ATy->getIntegerBitWidth(); 68286425Sdim else if (ATy->isPointerTy()) 69286425Sdim Width = 32; 70286425Sdim // If pointer size is not set through target data, it will default to 71286425Sdim // Module::AnyPointerSize. 72286425Sdim if (Width == 0 || Width > 64) 73286425Sdim break; 74321369Sdim if (Arg.hasAttribute(Attribute::ByVal)) 75314564Sdim continue; 76286425Sdim InPhysReg = getNextPhysReg(InPhysReg, Width); 77286425Sdim if (!InPhysReg) 78286425Sdim break; 79286425Sdim InVirtReg = getVirtRegFor(InPhysReg); 80286425Sdim if (!InVirtReg) 81286425Sdim continue; 82321369Sdim if (Arg.hasAttribute(Attribute::SExt)) 83286425Sdim VRX.insert(std::make_pair(InVirtReg, ExtType(ExtType::SExt, Width))); 84321369Sdim else if (Arg.hasAttribute(Attribute::ZExt)) 85286425Sdim VRX.insert(std::make_pair(InVirtReg, ExtType(ExtType::ZExt, Width))); 86286425Sdim } 87286425Sdim} 88286425Sdim 89314564SdimBT::BitMask HexagonEvaluator::mask(unsigned Reg, unsigned Sub) const { 90286425Sdim if (Sub == 0) 91286425Sdim return MachineEvaluator::mask(Reg, 0); 92327952Sdim const TargetRegisterClass &RC = *MRI.getRegClass(Reg); 93327952Sdim unsigned ID = RC.getID(); 94286425Sdim uint16_t RW = getRegBitWidth(RegisterRef(Reg, Sub)); 95344779Sdim const auto &HRI = static_cast<const HexagonRegisterInfo&>(TRI); 96314564Sdim bool IsSubLo = (Sub == HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_lo)); 97286425Sdim switch (ID) { 98327952Sdim case Hexagon::DoubleRegsRegClassID: 99327952Sdim case Hexagon::HvxWRRegClassID: 100344779Sdim case Hexagon::HvxVQRRegClassID: 101314564Sdim return IsSubLo ? BT::BitMask(0, RW-1) 102314564Sdim : BT::BitMask(RW, 2*RW-1); 103286425Sdim default: 104286425Sdim break; 105286425Sdim } 106286425Sdim#ifndef NDEBUG 107327952Sdim dbgs() << printReg(Reg, &TRI, Sub) << " in reg class " 108327952Sdim << TRI.getRegClassName(&RC) << '\n'; 109286425Sdim#endif 110286425Sdim llvm_unreachable("Unexpected register/subregister"); 111286425Sdim} 112286425Sdim 113327952Sdimuint16_t HexagonEvaluator::getPhysRegBitWidth(unsigned Reg) const { 114360784Sdim assert(Register::isPhysicalRegister(Reg)); 115327952Sdim 116327952Sdim using namespace Hexagon; 117344779Sdim const auto &HST = MF.getSubtarget<HexagonSubtarget>(); 118344779Sdim if (HST.useHVXOps()) { 119344779Sdim for (auto &RC : {HvxVRRegClass, HvxWRRegClass, HvxQRRegClass, 120344779Sdim HvxVQRRegClass}) 121344779Sdim if (RC.contains(Reg)) 122344779Sdim return TRI.getRegSizeInBits(RC); 123344779Sdim } 124327952Sdim // Default treatment for other physical registers. 125327952Sdim if (const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg)) 126327952Sdim return TRI.getRegSizeInBits(*RC); 127327952Sdim 128327952Sdim llvm_unreachable( 129327952Sdim (Twine("Unhandled physical register") + TRI.getName(Reg)).str().c_str()); 130327952Sdim} 131327952Sdim 132327952Sdimconst TargetRegisterClass &HexagonEvaluator::composeWithSubRegIndex( 133327952Sdim const TargetRegisterClass &RC, unsigned Idx) const { 134327952Sdim if (Idx == 0) 135327952Sdim return RC; 136327952Sdim 137327952Sdim#ifndef NDEBUG 138327952Sdim const auto &HRI = static_cast<const HexagonRegisterInfo&>(TRI); 139327952Sdim bool IsSubLo = (Idx == HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_lo)); 140327952Sdim bool IsSubHi = (Idx == HRI.getHexagonSubRegIndex(RC, Hexagon::ps_sub_hi)); 141327952Sdim assert(IsSubLo != IsSubHi && "Must refer to either low or high subreg"); 142327952Sdim#endif 143327952Sdim 144327952Sdim switch (RC.getID()) { 145327952Sdim case Hexagon::DoubleRegsRegClassID: 146327952Sdim return Hexagon::IntRegsRegClass; 147327952Sdim case Hexagon::HvxWRRegClassID: 148327952Sdim return Hexagon::HvxVRRegClass; 149344779Sdim case Hexagon::HvxVQRRegClassID: 150344779Sdim return Hexagon::HvxWRRegClass; 151327952Sdim default: 152327952Sdim break; 153327952Sdim } 154327952Sdim#ifndef NDEBUG 155327952Sdim dbgs() << "Reg class id: " << RC.getID() << " idx: " << Idx << '\n'; 156327952Sdim#endif 157327952Sdim llvm_unreachable("Unimplemented combination of reg class/subreg idx"); 158327952Sdim} 159327952Sdim 160286425Sdimnamespace { 161314564Sdim 162296417Sdimclass RegisterRefs { 163296417Sdim std::vector<BT::RegisterRef> Vector; 164286425Sdim 165296417Sdimpublic: 166309124Sdim RegisterRefs(const MachineInstr &MI) : Vector(MI.getNumOperands()) { 167296417Sdim for (unsigned i = 0, n = Vector.size(); i < n; ++i) { 168309124Sdim const MachineOperand &MO = MI.getOperand(i); 169286425Sdim if (MO.isReg()) 170296417Sdim Vector[i] = BT::RegisterRef(MO); 171286425Sdim // For indices that don't correspond to registers, the entry will 172286425Sdim // remain constructed via the default constructor. 173286425Sdim } 174286425Sdim } 175296417Sdim 176296417Sdim size_t size() const { return Vector.size(); } 177314564Sdim 178296417Sdim const BT::RegisterRef &operator[](unsigned n) const { 179296417Sdim // The main purpose of this operator is to assert with bad argument. 180296417Sdim assert(n < Vector.size()); 181296417Sdim return Vector[n]; 182296417Sdim } 183296417Sdim}; 184286425Sdim 185314564Sdim} // end anonymous namespace 186314564Sdim 187309124Sdimbool HexagonEvaluator::evaluate(const MachineInstr &MI, 188309124Sdim const CellMapType &Inputs, 189309124Sdim CellMapType &Outputs) const { 190314564Sdim using namespace Hexagon; 191314564Sdim 192286425Sdim unsigned NumDefs = 0; 193286425Sdim 194286425Sdim // Sanity verification: there should not be any defs with subregisters. 195327952Sdim for (const MachineOperand &MO : MI.operands()) { 196286425Sdim if (!MO.isReg() || !MO.isDef()) 197286425Sdim continue; 198286425Sdim NumDefs++; 199286425Sdim assert(MO.getSubReg() == 0); 200286425Sdim } 201286425Sdim 202286425Sdim if (NumDefs == 0) 203286425Sdim return false; 204286425Sdim 205314564Sdim unsigned Opc = MI.getOpcode(); 206286425Sdim 207314564Sdim if (MI.mayLoad()) { 208314564Sdim switch (Opc) { 209314564Sdim // These instructions may be marked as mayLoad, but they are generating 210314564Sdim // immediate values, so skip them. 211314564Sdim case CONST32: 212314564Sdim case CONST64: 213314564Sdim break; 214314564Sdim default: 215314564Sdim return evaluateLoad(MI, Inputs, Outputs); 216314564Sdim } 217314564Sdim } 218314564Sdim 219286425Sdim // Check COPY instructions that copy formal parameters into virtual 220286425Sdim // registers. Such parameters can be sign- or zero-extended at the 221286425Sdim // call site, and we should take advantage of this knowledge. The MRI 222286425Sdim // keeps a list of pairs of live-in physical and virtual registers, 223286425Sdim // which provides information about which virtual registers will hold 224286425Sdim // the argument values. The function will still contain instructions 225286425Sdim // defining those virtual registers, and in practice those are COPY 226286425Sdim // instructions from a physical to a virtual register. In such cases, 227286425Sdim // applying the argument extension to the virtual register can be seen 228286425Sdim // as simply mirroring the extension that had already been applied to 229286425Sdim // the physical register at the call site. If the defining instruction 230286425Sdim // was not a COPY, it would not be clear how to mirror that extension 231286425Sdim // on the callee's side. For that reason, only check COPY instructions 232286425Sdim // for potential extensions. 233309124Sdim if (MI.isCopy()) { 234286425Sdim if (evaluateFormalCopy(MI, Inputs, Outputs)) 235286425Sdim return true; 236286425Sdim } 237286425Sdim 238286425Sdim // Beyond this point, if any operand is a global, skip that instruction. 239286425Sdim // The reason is that certain instructions that can take an immediate 240286425Sdim // operand can also have a global symbol in that operand. To avoid 241286425Sdim // checking what kind of operand a given instruction has individually 242286425Sdim // for each instruction, do it here. Global symbols as operands gene- 243286425Sdim // rally do not provide any useful information. 244327952Sdim for (const MachineOperand &MO : MI.operands()) { 245286425Sdim if (MO.isGlobal() || MO.isBlockAddress() || MO.isSymbol() || MO.isJTI() || 246286425Sdim MO.isCPI()) 247286425Sdim return false; 248286425Sdim } 249286425Sdim 250286425Sdim RegisterRefs Reg(MI); 251309124Sdim#define op(i) MI.getOperand(i) 252309124Sdim#define rc(i) RegisterCell::ref(getCell(Reg[i], Inputs)) 253309124Sdim#define im(i) MI.getOperand(i).getImm() 254286425Sdim 255286425Sdim // If the instruction has no register operands, skip it. 256286425Sdim if (Reg.size() == 0) 257286425Sdim return false; 258286425Sdim 259286425Sdim // Record result for register in operand 0. 260286425Sdim auto rr0 = [this,Reg] (const BT::RegisterCell &Val, CellMapType &Outputs) 261286425Sdim -> bool { 262286425Sdim putCell(Reg[0], Val, Outputs); 263286425Sdim return true; 264286425Sdim }; 265286425Sdim // Get the cell corresponding to the N-th operand. 266309124Sdim auto cop = [this, &Reg, &MI, &Inputs](unsigned N, 267309124Sdim uint16_t W) -> BT::RegisterCell { 268309124Sdim const MachineOperand &Op = MI.getOperand(N); 269286425Sdim if (Op.isImm()) 270286425Sdim return eIMM(Op.getImm(), W); 271286425Sdim if (!Op.isReg()) 272286425Sdim return RegisterCell::self(0, W); 273286425Sdim assert(getRegBitWidth(Reg[N]) == W && "Register width mismatch"); 274286425Sdim return rc(N); 275286425Sdim }; 276286425Sdim // Extract RW low bits of the cell. 277286425Sdim auto lo = [this] (const BT::RegisterCell &RC, uint16_t RW) 278286425Sdim -> BT::RegisterCell { 279286425Sdim assert(RW <= RC.width()); 280286425Sdim return eXTR(RC, 0, RW); 281286425Sdim }; 282286425Sdim // Extract RW high bits of the cell. 283286425Sdim auto hi = [this] (const BT::RegisterCell &RC, uint16_t RW) 284286425Sdim -> BT::RegisterCell { 285286425Sdim uint16_t W = RC.width(); 286286425Sdim assert(RW <= W); 287286425Sdim return eXTR(RC, W-RW, W); 288286425Sdim }; 289286425Sdim // Extract N-th halfword (counting from the least significant position). 290286425Sdim auto half = [this] (const BT::RegisterCell &RC, unsigned N) 291286425Sdim -> BT::RegisterCell { 292286425Sdim assert(N*16+16 <= RC.width()); 293286425Sdim return eXTR(RC, N*16, N*16+16); 294286425Sdim }; 295286425Sdim // Shuffle bits (pick even/odd from cells and merge into result). 296286425Sdim auto shuffle = [this] (const BT::RegisterCell &Rs, const BT::RegisterCell &Rt, 297286425Sdim uint16_t BW, bool Odd) -> BT::RegisterCell { 298286425Sdim uint16_t I = Odd, Ws = Rs.width(); 299286425Sdim assert(Ws == Rt.width()); 300286425Sdim RegisterCell RC = eXTR(Rt, I*BW, I*BW+BW).cat(eXTR(Rs, I*BW, I*BW+BW)); 301286425Sdim I += 2; 302286425Sdim while (I*BW < Ws) { 303286425Sdim RC.cat(eXTR(Rt, I*BW, I*BW+BW)).cat(eXTR(Rs, I*BW, I*BW+BW)); 304286425Sdim I += 2; 305286425Sdim } 306286425Sdim return RC; 307286425Sdim }; 308286425Sdim 309286425Sdim // The bitwidth of the 0th operand. In most (if not all) of the 310286425Sdim // instructions below, the 0th operand is the defined register. 311286425Sdim // Pre-compute the bitwidth here, because it is needed in many cases 312286425Sdim // cases below. 313286425Sdim uint16_t W0 = (Reg[0].Reg != 0) ? getRegBitWidth(Reg[0]) : 0; 314286425Sdim 315321369Sdim // Register id of the 0th operand. It can be 0. 316321369Sdim unsigned Reg0 = Reg[0].Reg; 317321369Sdim 318286425Sdim switch (Opc) { 319286425Sdim // Transfer immediate: 320286425Sdim 321286425Sdim case A2_tfrsi: 322286425Sdim case A2_tfrpi: 323286425Sdim case CONST32: 324314564Sdim case CONST64: 325286425Sdim return rr0(eIMM(im(1), W0), Outputs); 326314564Sdim case PS_false: 327286425Sdim return rr0(RegisterCell(W0).fill(0, W0, BT::BitValue::Zero), Outputs); 328314564Sdim case PS_true: 329286425Sdim return rr0(RegisterCell(W0).fill(0, W0, BT::BitValue::One), Outputs); 330314564Sdim case PS_fi: { 331286425Sdim int FI = op(1).getIndex(); 332286425Sdim int Off = op(2).getImm(); 333286425Sdim unsigned A = MFI.getObjectAlignment(FI) + std::abs(Off); 334341825Sdim unsigned L = countTrailingZeros(A); 335286425Sdim RegisterCell RC = RegisterCell::self(Reg[0].Reg, W0); 336286425Sdim RC.fill(0, L, BT::BitValue::Zero); 337286425Sdim return rr0(RC, Outputs); 338286425Sdim } 339286425Sdim 340286425Sdim // Transfer register: 341286425Sdim 342286425Sdim case A2_tfr: 343286425Sdim case A2_tfrp: 344286425Sdim case C2_pxfer_map: 345286425Sdim return rr0(rc(1), Outputs); 346286425Sdim case C2_tfrpr: { 347286425Sdim uint16_t RW = W0; 348286425Sdim uint16_t PW = 8; // XXX Pred size: getRegBitWidth(Reg[1]); 349286425Sdim assert(PW <= RW); 350286425Sdim RegisterCell PC = eXTR(rc(1), 0, PW); 351286425Sdim RegisterCell RC = RegisterCell(RW).insert(PC, BT::BitMask(0, PW-1)); 352286425Sdim RC.fill(PW, RW, BT::BitValue::Zero); 353286425Sdim return rr0(RC, Outputs); 354286425Sdim } 355286425Sdim case C2_tfrrp: { 356341825Sdim uint16_t RW = W0; 357341825Sdim uint16_t PW = 8; // XXX Pred size: getRegBitWidth(Reg[1]); 358341825Sdim RegisterCell RC = RegisterCell::self(Reg[0].Reg, RW); 359341825Sdim RC.fill(PW, RW, BT::BitValue::Zero); 360341825Sdim return rr0(eINS(RC, eXTR(rc(1), 0, PW), 0), Outputs); 361286425Sdim } 362286425Sdim 363286425Sdim // Arithmetic: 364286425Sdim 365286425Sdim case A2_abs: 366286425Sdim case A2_absp: 367286425Sdim // TODO 368286425Sdim break; 369286425Sdim 370286425Sdim case A2_addsp: { 371286425Sdim uint16_t W1 = getRegBitWidth(Reg[1]); 372286425Sdim assert(W0 == 64 && W1 == 32); 373286425Sdim RegisterCell CW = RegisterCell(W0).insert(rc(1), BT::BitMask(0, W1-1)); 374286425Sdim RegisterCell RC = eADD(eSXT(CW, W1), rc(2)); 375286425Sdim return rr0(RC, Outputs); 376286425Sdim } 377286425Sdim case A2_add: 378286425Sdim case A2_addp: 379286425Sdim return rr0(eADD(rc(1), rc(2)), Outputs); 380286425Sdim case A2_addi: 381286425Sdim return rr0(eADD(rc(1), eIMM(im(2), W0)), Outputs); 382286425Sdim case S4_addi_asl_ri: { 383286425Sdim RegisterCell RC = eADD(eIMM(im(1), W0), eASL(rc(2), im(3))); 384286425Sdim return rr0(RC, Outputs); 385286425Sdim } 386286425Sdim case S4_addi_lsr_ri: { 387286425Sdim RegisterCell RC = eADD(eIMM(im(1), W0), eLSR(rc(2), im(3))); 388286425Sdim return rr0(RC, Outputs); 389286425Sdim } 390286425Sdim case S4_addaddi: { 391286425Sdim RegisterCell RC = eADD(rc(1), eADD(rc(2), eIMM(im(3), W0))); 392286425Sdim return rr0(RC, Outputs); 393286425Sdim } 394286425Sdim case M4_mpyri_addi: { 395286425Sdim RegisterCell M = eMLS(rc(2), eIMM(im(3), W0)); 396286425Sdim RegisterCell RC = eADD(eIMM(im(1), W0), lo(M, W0)); 397286425Sdim return rr0(RC, Outputs); 398286425Sdim } 399286425Sdim case M4_mpyrr_addi: { 400286425Sdim RegisterCell M = eMLS(rc(2), rc(3)); 401286425Sdim RegisterCell RC = eADD(eIMM(im(1), W0), lo(M, W0)); 402286425Sdim return rr0(RC, Outputs); 403286425Sdim } 404286425Sdim case M4_mpyri_addr_u2: { 405286425Sdim RegisterCell M = eMLS(eIMM(im(2), W0), rc(3)); 406286425Sdim RegisterCell RC = eADD(rc(1), lo(M, W0)); 407286425Sdim return rr0(RC, Outputs); 408286425Sdim } 409286425Sdim case M4_mpyri_addr: { 410286425Sdim RegisterCell M = eMLS(rc(2), eIMM(im(3), W0)); 411286425Sdim RegisterCell RC = eADD(rc(1), lo(M, W0)); 412286425Sdim return rr0(RC, Outputs); 413286425Sdim } 414286425Sdim case M4_mpyrr_addr: { 415286425Sdim RegisterCell M = eMLS(rc(2), rc(3)); 416286425Sdim RegisterCell RC = eADD(rc(1), lo(M, W0)); 417286425Sdim return rr0(RC, Outputs); 418286425Sdim } 419286425Sdim case S4_subaddi: { 420286425Sdim RegisterCell RC = eADD(rc(1), eSUB(eIMM(im(2), W0), rc(3))); 421286425Sdim return rr0(RC, Outputs); 422286425Sdim } 423286425Sdim case M2_accii: { 424286425Sdim RegisterCell RC = eADD(rc(1), eADD(rc(2), eIMM(im(3), W0))); 425286425Sdim return rr0(RC, Outputs); 426286425Sdim } 427286425Sdim case M2_acci: { 428286425Sdim RegisterCell RC = eADD(rc(1), eADD(rc(2), rc(3))); 429286425Sdim return rr0(RC, Outputs); 430286425Sdim } 431286425Sdim case M2_subacc: { 432286425Sdim RegisterCell RC = eADD(rc(1), eSUB(rc(2), rc(3))); 433286425Sdim return rr0(RC, Outputs); 434286425Sdim } 435286425Sdim case S2_addasl_rrri: { 436286425Sdim RegisterCell RC = eADD(rc(1), eASL(rc(2), im(3))); 437286425Sdim return rr0(RC, Outputs); 438286425Sdim } 439286425Sdim case C4_addipc: { 440286425Sdim RegisterCell RPC = RegisterCell::self(Reg[0].Reg, W0); 441286425Sdim RPC.fill(0, 2, BT::BitValue::Zero); 442286425Sdim return rr0(eADD(RPC, eIMM(im(2), W0)), Outputs); 443286425Sdim } 444286425Sdim case A2_sub: 445286425Sdim case A2_subp: 446286425Sdim return rr0(eSUB(rc(1), rc(2)), Outputs); 447286425Sdim case A2_subri: 448286425Sdim return rr0(eSUB(eIMM(im(1), W0), rc(2)), Outputs); 449286425Sdim case S4_subi_asl_ri: { 450286425Sdim RegisterCell RC = eSUB(eIMM(im(1), W0), eASL(rc(2), im(3))); 451286425Sdim return rr0(RC, Outputs); 452286425Sdim } 453286425Sdim case S4_subi_lsr_ri: { 454286425Sdim RegisterCell RC = eSUB(eIMM(im(1), W0), eLSR(rc(2), im(3))); 455286425Sdim return rr0(RC, Outputs); 456286425Sdim } 457286425Sdim case M2_naccii: { 458286425Sdim RegisterCell RC = eSUB(rc(1), eADD(rc(2), eIMM(im(3), W0))); 459286425Sdim return rr0(RC, Outputs); 460286425Sdim } 461286425Sdim case M2_nacci: { 462286425Sdim RegisterCell RC = eSUB(rc(1), eADD(rc(2), rc(3))); 463286425Sdim return rr0(RC, Outputs); 464286425Sdim } 465286425Sdim // 32-bit negation is done by "Rd = A2_subri 0, Rs" 466286425Sdim case A2_negp: 467286425Sdim return rr0(eSUB(eIMM(0, W0), rc(1)), Outputs); 468286425Sdim 469286425Sdim case M2_mpy_up: { 470286425Sdim RegisterCell M = eMLS(rc(1), rc(2)); 471286425Sdim return rr0(hi(M, W0), Outputs); 472286425Sdim } 473286425Sdim case M2_dpmpyss_s0: 474286425Sdim return rr0(eMLS(rc(1), rc(2)), Outputs); 475286425Sdim case M2_dpmpyss_acc_s0: 476286425Sdim return rr0(eADD(rc(1), eMLS(rc(2), rc(3))), Outputs); 477286425Sdim case M2_dpmpyss_nac_s0: 478286425Sdim return rr0(eSUB(rc(1), eMLS(rc(2), rc(3))), Outputs); 479286425Sdim case M2_mpyi: { 480286425Sdim RegisterCell M = eMLS(rc(1), rc(2)); 481286425Sdim return rr0(lo(M, W0), Outputs); 482286425Sdim } 483286425Sdim case M2_macsip: { 484286425Sdim RegisterCell M = eMLS(rc(2), eIMM(im(3), W0)); 485286425Sdim RegisterCell RC = eADD(rc(1), lo(M, W0)); 486286425Sdim return rr0(RC, Outputs); 487286425Sdim } 488286425Sdim case M2_macsin: { 489286425Sdim RegisterCell M = eMLS(rc(2), eIMM(im(3), W0)); 490286425Sdim RegisterCell RC = eSUB(rc(1), lo(M, W0)); 491286425Sdim return rr0(RC, Outputs); 492286425Sdim } 493286425Sdim case M2_maci: { 494286425Sdim RegisterCell M = eMLS(rc(2), rc(3)); 495286425Sdim RegisterCell RC = eADD(rc(1), lo(M, W0)); 496286425Sdim return rr0(RC, Outputs); 497286425Sdim } 498286425Sdim case M2_mpysmi: { 499286425Sdim RegisterCell M = eMLS(rc(1), eIMM(im(2), W0)); 500286425Sdim return rr0(lo(M, 32), Outputs); 501286425Sdim } 502286425Sdim case M2_mpysin: { 503286425Sdim RegisterCell M = eMLS(rc(1), eIMM(-im(2), W0)); 504286425Sdim return rr0(lo(M, 32), Outputs); 505286425Sdim } 506286425Sdim case M2_mpysip: { 507286425Sdim RegisterCell M = eMLS(rc(1), eIMM(im(2), W0)); 508286425Sdim return rr0(lo(M, 32), Outputs); 509286425Sdim } 510286425Sdim case M2_mpyu_up: { 511286425Sdim RegisterCell M = eMLU(rc(1), rc(2)); 512286425Sdim return rr0(hi(M, W0), Outputs); 513286425Sdim } 514286425Sdim case M2_dpmpyuu_s0: 515286425Sdim return rr0(eMLU(rc(1), rc(2)), Outputs); 516286425Sdim case M2_dpmpyuu_acc_s0: 517286425Sdim return rr0(eADD(rc(1), eMLU(rc(2), rc(3))), Outputs); 518286425Sdim case M2_dpmpyuu_nac_s0: 519286425Sdim return rr0(eSUB(rc(1), eMLU(rc(2), rc(3))), Outputs); 520286425Sdim //case M2_mpysu_up: 521286425Sdim 522286425Sdim // Logical/bitwise: 523286425Sdim 524286425Sdim case A2_andir: 525286425Sdim return rr0(eAND(rc(1), eIMM(im(2), W0)), Outputs); 526286425Sdim case A2_and: 527286425Sdim case A2_andp: 528286425Sdim return rr0(eAND(rc(1), rc(2)), Outputs); 529286425Sdim case A4_andn: 530286425Sdim case A4_andnp: 531286425Sdim return rr0(eAND(rc(1), eNOT(rc(2))), Outputs); 532286425Sdim case S4_andi_asl_ri: { 533286425Sdim RegisterCell RC = eAND(eIMM(im(1), W0), eASL(rc(2), im(3))); 534286425Sdim return rr0(RC, Outputs); 535286425Sdim } 536286425Sdim case S4_andi_lsr_ri: { 537286425Sdim RegisterCell RC = eAND(eIMM(im(1), W0), eLSR(rc(2), im(3))); 538286425Sdim return rr0(RC, Outputs); 539286425Sdim } 540286425Sdim case M4_and_and: 541286425Sdim return rr0(eAND(rc(1), eAND(rc(2), rc(3))), Outputs); 542286425Sdim case M4_and_andn: 543286425Sdim return rr0(eAND(rc(1), eAND(rc(2), eNOT(rc(3)))), Outputs); 544286425Sdim case M4_and_or: 545286425Sdim return rr0(eAND(rc(1), eORL(rc(2), rc(3))), Outputs); 546286425Sdim case M4_and_xor: 547286425Sdim return rr0(eAND(rc(1), eXOR(rc(2), rc(3))), Outputs); 548286425Sdim case A2_orir: 549286425Sdim return rr0(eORL(rc(1), eIMM(im(2), W0)), Outputs); 550286425Sdim case A2_or: 551286425Sdim case A2_orp: 552286425Sdim return rr0(eORL(rc(1), rc(2)), Outputs); 553286425Sdim case A4_orn: 554286425Sdim case A4_ornp: 555286425Sdim return rr0(eORL(rc(1), eNOT(rc(2))), Outputs); 556286425Sdim case S4_ori_asl_ri: { 557286425Sdim RegisterCell RC = eORL(eIMM(im(1), W0), eASL(rc(2), im(3))); 558286425Sdim return rr0(RC, Outputs); 559286425Sdim } 560286425Sdim case S4_ori_lsr_ri: { 561286425Sdim RegisterCell RC = eORL(eIMM(im(1), W0), eLSR(rc(2), im(3))); 562286425Sdim return rr0(RC, Outputs); 563286425Sdim } 564286425Sdim case M4_or_and: 565286425Sdim return rr0(eORL(rc(1), eAND(rc(2), rc(3))), Outputs); 566286425Sdim case M4_or_andn: 567286425Sdim return rr0(eORL(rc(1), eAND(rc(2), eNOT(rc(3)))), Outputs); 568286425Sdim case S4_or_andi: 569286425Sdim case S4_or_andix: { 570286425Sdim RegisterCell RC = eORL(rc(1), eAND(rc(2), eIMM(im(3), W0))); 571286425Sdim return rr0(RC, Outputs); 572286425Sdim } 573286425Sdim case S4_or_ori: { 574286425Sdim RegisterCell RC = eORL(rc(1), eORL(rc(2), eIMM(im(3), W0))); 575286425Sdim return rr0(RC, Outputs); 576286425Sdim } 577286425Sdim case M4_or_or: 578286425Sdim return rr0(eORL(rc(1), eORL(rc(2), rc(3))), Outputs); 579286425Sdim case M4_or_xor: 580286425Sdim return rr0(eORL(rc(1), eXOR(rc(2), rc(3))), Outputs); 581286425Sdim case A2_xor: 582286425Sdim case A2_xorp: 583286425Sdim return rr0(eXOR(rc(1), rc(2)), Outputs); 584286425Sdim case M4_xor_and: 585286425Sdim return rr0(eXOR(rc(1), eAND(rc(2), rc(3))), Outputs); 586286425Sdim case M4_xor_andn: 587286425Sdim return rr0(eXOR(rc(1), eAND(rc(2), eNOT(rc(3)))), Outputs); 588286425Sdim case M4_xor_or: 589286425Sdim return rr0(eXOR(rc(1), eORL(rc(2), rc(3))), Outputs); 590286425Sdim case M4_xor_xacc: 591286425Sdim return rr0(eXOR(rc(1), eXOR(rc(2), rc(3))), Outputs); 592286425Sdim case A2_not: 593286425Sdim case A2_notp: 594286425Sdim return rr0(eNOT(rc(1)), Outputs); 595286425Sdim 596286425Sdim case S2_asl_i_r: 597286425Sdim case S2_asl_i_p: 598286425Sdim return rr0(eASL(rc(1), im(2)), Outputs); 599286425Sdim case A2_aslh: 600286425Sdim return rr0(eASL(rc(1), 16), Outputs); 601286425Sdim case S2_asl_i_r_acc: 602286425Sdim case S2_asl_i_p_acc: 603286425Sdim return rr0(eADD(rc(1), eASL(rc(2), im(3))), Outputs); 604286425Sdim case S2_asl_i_r_nac: 605286425Sdim case S2_asl_i_p_nac: 606286425Sdim return rr0(eSUB(rc(1), eASL(rc(2), im(3))), Outputs); 607286425Sdim case S2_asl_i_r_and: 608286425Sdim case S2_asl_i_p_and: 609286425Sdim return rr0(eAND(rc(1), eASL(rc(2), im(3))), Outputs); 610286425Sdim case S2_asl_i_r_or: 611286425Sdim case S2_asl_i_p_or: 612286425Sdim return rr0(eORL(rc(1), eASL(rc(2), im(3))), Outputs); 613286425Sdim case S2_asl_i_r_xacc: 614286425Sdim case S2_asl_i_p_xacc: 615286425Sdim return rr0(eXOR(rc(1), eASL(rc(2), im(3))), Outputs); 616286425Sdim case S2_asl_i_vh: 617286425Sdim case S2_asl_i_vw: 618286425Sdim // TODO 619286425Sdim break; 620286425Sdim 621286425Sdim case S2_asr_i_r: 622286425Sdim case S2_asr_i_p: 623286425Sdim return rr0(eASR(rc(1), im(2)), Outputs); 624286425Sdim case A2_asrh: 625286425Sdim return rr0(eASR(rc(1), 16), Outputs); 626286425Sdim case S2_asr_i_r_acc: 627286425Sdim case S2_asr_i_p_acc: 628286425Sdim return rr0(eADD(rc(1), eASR(rc(2), im(3))), Outputs); 629286425Sdim case S2_asr_i_r_nac: 630286425Sdim case S2_asr_i_p_nac: 631286425Sdim return rr0(eSUB(rc(1), eASR(rc(2), im(3))), Outputs); 632286425Sdim case S2_asr_i_r_and: 633286425Sdim case S2_asr_i_p_and: 634286425Sdim return rr0(eAND(rc(1), eASR(rc(2), im(3))), Outputs); 635286425Sdim case S2_asr_i_r_or: 636286425Sdim case S2_asr_i_p_or: 637286425Sdim return rr0(eORL(rc(1), eASR(rc(2), im(3))), Outputs); 638286425Sdim case S2_asr_i_r_rnd: { 639286425Sdim // The input is first sign-extended to 64 bits, then the output 640286425Sdim // is truncated back to 32 bits. 641286425Sdim assert(W0 == 32); 642286425Sdim RegisterCell XC = eSXT(rc(1).cat(eIMM(0, W0)), W0); 643286425Sdim RegisterCell RC = eASR(eADD(eASR(XC, im(2)), eIMM(1, 2*W0)), 1); 644286425Sdim return rr0(eXTR(RC, 0, W0), Outputs); 645286425Sdim } 646286425Sdim case S2_asr_i_r_rnd_goodsyntax: { 647286425Sdim int64_t S = im(2); 648286425Sdim if (S == 0) 649286425Sdim return rr0(rc(1), Outputs); 650286425Sdim // Result: S2_asr_i_r_rnd Rs, u5-1 651286425Sdim RegisterCell XC = eSXT(rc(1).cat(eIMM(0, W0)), W0); 652286425Sdim RegisterCell RC = eLSR(eADD(eASR(XC, S-1), eIMM(1, 2*W0)), 1); 653286425Sdim return rr0(eXTR(RC, 0, W0), Outputs); 654286425Sdim } 655286425Sdim case S2_asr_r_vh: 656286425Sdim case S2_asr_i_vw: 657286425Sdim case S2_asr_i_svw_trun: 658286425Sdim // TODO 659286425Sdim break; 660286425Sdim 661286425Sdim case S2_lsr_i_r: 662286425Sdim case S2_lsr_i_p: 663286425Sdim return rr0(eLSR(rc(1), im(2)), Outputs); 664286425Sdim case S2_lsr_i_r_acc: 665286425Sdim case S2_lsr_i_p_acc: 666286425Sdim return rr0(eADD(rc(1), eLSR(rc(2), im(3))), Outputs); 667286425Sdim case S2_lsr_i_r_nac: 668286425Sdim case S2_lsr_i_p_nac: 669286425Sdim return rr0(eSUB(rc(1), eLSR(rc(2), im(3))), Outputs); 670286425Sdim case S2_lsr_i_r_and: 671286425Sdim case S2_lsr_i_p_and: 672286425Sdim return rr0(eAND(rc(1), eLSR(rc(2), im(3))), Outputs); 673286425Sdim case S2_lsr_i_r_or: 674286425Sdim case S2_lsr_i_p_or: 675286425Sdim return rr0(eORL(rc(1), eLSR(rc(2), im(3))), Outputs); 676286425Sdim case S2_lsr_i_r_xacc: 677286425Sdim case S2_lsr_i_p_xacc: 678286425Sdim return rr0(eXOR(rc(1), eLSR(rc(2), im(3))), Outputs); 679286425Sdim 680286425Sdim case S2_clrbit_i: { 681286425Sdim RegisterCell RC = rc(1); 682286425Sdim RC[im(2)] = BT::BitValue::Zero; 683286425Sdim return rr0(RC, Outputs); 684286425Sdim } 685286425Sdim case S2_setbit_i: { 686286425Sdim RegisterCell RC = rc(1); 687286425Sdim RC[im(2)] = BT::BitValue::One; 688286425Sdim return rr0(RC, Outputs); 689286425Sdim } 690286425Sdim case S2_togglebit_i: { 691286425Sdim RegisterCell RC = rc(1); 692286425Sdim uint16_t BX = im(2); 693286425Sdim RC[BX] = RC[BX].is(0) ? BT::BitValue::One 694286425Sdim : RC[BX].is(1) ? BT::BitValue::Zero 695286425Sdim : BT::BitValue::self(); 696286425Sdim return rr0(RC, Outputs); 697286425Sdim } 698286425Sdim 699286425Sdim case A4_bitspliti: { 700286425Sdim uint16_t W1 = getRegBitWidth(Reg[1]); 701286425Sdim uint16_t BX = im(2); 702286425Sdim // Res.uw[1] = Rs[bx+1:], Res.uw[0] = Rs[0:bx] 703286425Sdim const BT::BitValue Zero = BT::BitValue::Zero; 704286425Sdim RegisterCell RZ = RegisterCell(W0).fill(BX, W1, Zero) 705286425Sdim .fill(W1+(W1-BX), W0, Zero); 706286425Sdim RegisterCell BF1 = eXTR(rc(1), 0, BX), BF2 = eXTR(rc(1), BX, W1); 707286425Sdim RegisterCell RC = eINS(eINS(RZ, BF1, 0), BF2, W1); 708286425Sdim return rr0(RC, Outputs); 709286425Sdim } 710286425Sdim case S4_extract: 711286425Sdim case S4_extractp: 712286425Sdim case S2_extractu: 713286425Sdim case S2_extractup: { 714286425Sdim uint16_t Wd = im(2), Of = im(3); 715286425Sdim assert(Wd <= W0); 716286425Sdim if (Wd == 0) 717286425Sdim return rr0(eIMM(0, W0), Outputs); 718286425Sdim // If the width extends beyond the register size, pad the register 719286425Sdim // with 0 bits. 720286425Sdim RegisterCell Pad = (Wd+Of > W0) ? rc(1).cat(eIMM(0, Wd+Of-W0)) : rc(1); 721286425Sdim RegisterCell Ext = eXTR(Pad, Of, Wd+Of); 722286425Sdim // Ext is short, need to extend it with 0s or sign bit. 723286425Sdim RegisterCell RC = RegisterCell(W0).insert(Ext, BT::BitMask(0, Wd-1)); 724286425Sdim if (Opc == S2_extractu || Opc == S2_extractup) 725286425Sdim return rr0(eZXT(RC, Wd), Outputs); 726286425Sdim return rr0(eSXT(RC, Wd), Outputs); 727286425Sdim } 728286425Sdim case S2_insert: 729286425Sdim case S2_insertp: { 730286425Sdim uint16_t Wd = im(3), Of = im(4); 731286425Sdim assert(Wd < W0 && Of < W0); 732286425Sdim // If Wd+Of exceeds W0, the inserted bits are truncated. 733286425Sdim if (Wd+Of > W0) 734286425Sdim Wd = W0-Of; 735286425Sdim if (Wd == 0) 736286425Sdim return rr0(rc(1), Outputs); 737286425Sdim return rr0(eINS(rc(1), eXTR(rc(2), 0, Wd), Of), Outputs); 738286425Sdim } 739286425Sdim 740286425Sdim // Bit permutations: 741286425Sdim 742286425Sdim case A2_combineii: 743286425Sdim case A4_combineii: 744286425Sdim case A4_combineir: 745286425Sdim case A4_combineri: 746286425Sdim case A2_combinew: 747314564Sdim case V6_vcombine: 748286425Sdim assert(W0 % 2 == 0); 749286425Sdim return rr0(cop(2, W0/2).cat(cop(1, W0/2)), Outputs); 750286425Sdim case A2_combine_ll: 751286425Sdim case A2_combine_lh: 752286425Sdim case A2_combine_hl: 753286425Sdim case A2_combine_hh: { 754286425Sdim assert(W0 == 32); 755286425Sdim assert(getRegBitWidth(Reg[1]) == 32 && getRegBitWidth(Reg[2]) == 32); 756286425Sdim // Low half in the output is 0 for _ll and _hl, 1 otherwise: 757286425Sdim unsigned LoH = !(Opc == A2_combine_ll || Opc == A2_combine_hl); 758286425Sdim // High half in the output is 0 for _ll and _lh, 1 otherwise: 759286425Sdim unsigned HiH = !(Opc == A2_combine_ll || Opc == A2_combine_lh); 760286425Sdim RegisterCell R1 = rc(1); 761286425Sdim RegisterCell R2 = rc(2); 762286425Sdim RegisterCell RC = half(R2, LoH).cat(half(R1, HiH)); 763286425Sdim return rr0(RC, Outputs); 764286425Sdim } 765286425Sdim case S2_packhl: { 766286425Sdim assert(W0 == 64); 767286425Sdim assert(getRegBitWidth(Reg[1]) == 32 && getRegBitWidth(Reg[2]) == 32); 768286425Sdim RegisterCell R1 = rc(1); 769286425Sdim RegisterCell R2 = rc(2); 770286425Sdim RegisterCell RC = half(R2, 0).cat(half(R1, 0)).cat(half(R2, 1)) 771286425Sdim .cat(half(R1, 1)); 772286425Sdim return rr0(RC, Outputs); 773286425Sdim } 774286425Sdim case S2_shuffeb: { 775286425Sdim RegisterCell RC = shuffle(rc(1), rc(2), 8, false); 776286425Sdim return rr0(RC, Outputs); 777286425Sdim } 778286425Sdim case S2_shuffeh: { 779286425Sdim RegisterCell RC = shuffle(rc(1), rc(2), 16, false); 780286425Sdim return rr0(RC, Outputs); 781286425Sdim } 782286425Sdim case S2_shuffob: { 783286425Sdim RegisterCell RC = shuffle(rc(1), rc(2), 8, true); 784286425Sdim return rr0(RC, Outputs); 785286425Sdim } 786286425Sdim case S2_shuffoh: { 787286425Sdim RegisterCell RC = shuffle(rc(1), rc(2), 16, true); 788286425Sdim return rr0(RC, Outputs); 789286425Sdim } 790286425Sdim case C2_mask: { 791286425Sdim uint16_t WR = W0; 792286425Sdim uint16_t WP = 8; // XXX Pred size: getRegBitWidth(Reg[1]); 793286425Sdim assert(WR == 64 && WP == 8); 794286425Sdim RegisterCell R1 = rc(1); 795286425Sdim RegisterCell RC(WR); 796286425Sdim for (uint16_t i = 0; i < WP; ++i) { 797286425Sdim const BT::BitValue &V = R1[i]; 798286425Sdim BT::BitValue F = (V.is(0) || V.is(1)) ? V : BT::BitValue::self(); 799286425Sdim RC.fill(i*8, i*8+8, F); 800286425Sdim } 801286425Sdim return rr0(RC, Outputs); 802286425Sdim } 803286425Sdim 804286425Sdim // Mux: 805286425Sdim 806286425Sdim case C2_muxii: 807286425Sdim case C2_muxir: 808286425Sdim case C2_muxri: 809286425Sdim case C2_mux: { 810286425Sdim BT::BitValue PC0 = rc(1)[0]; 811286425Sdim RegisterCell R2 = cop(2, W0); 812286425Sdim RegisterCell R3 = cop(3, W0); 813286425Sdim if (PC0.is(0) || PC0.is(1)) 814286425Sdim return rr0(RegisterCell::ref(PC0 ? R2 : R3), Outputs); 815286425Sdim R2.meet(R3, Reg[0].Reg); 816286425Sdim return rr0(R2, Outputs); 817286425Sdim } 818286425Sdim case C2_vmux: 819286425Sdim // TODO 820286425Sdim break; 821286425Sdim 822286425Sdim // Sign- and zero-extension: 823286425Sdim 824286425Sdim case A2_sxtb: 825286425Sdim return rr0(eSXT(rc(1), 8), Outputs); 826286425Sdim case A2_sxth: 827286425Sdim return rr0(eSXT(rc(1), 16), Outputs); 828286425Sdim case A2_sxtw: { 829286425Sdim uint16_t W1 = getRegBitWidth(Reg[1]); 830286425Sdim assert(W0 == 64 && W1 == 32); 831286425Sdim RegisterCell RC = eSXT(rc(1).cat(eIMM(0, W1)), W1); 832286425Sdim return rr0(RC, Outputs); 833286425Sdim } 834286425Sdim case A2_zxtb: 835286425Sdim return rr0(eZXT(rc(1), 8), Outputs); 836286425Sdim case A2_zxth: 837286425Sdim return rr0(eZXT(rc(1), 16), Outputs); 838286425Sdim 839321369Sdim // Saturations 840321369Sdim 841321369Sdim case A2_satb: 842321369Sdim return rr0(eSXT(RegisterCell::self(0, W0).regify(Reg0), 8), Outputs); 843321369Sdim case A2_sath: 844321369Sdim return rr0(eSXT(RegisterCell::self(0, W0).regify(Reg0), 16), Outputs); 845321369Sdim case A2_satub: 846321369Sdim return rr0(eZXT(RegisterCell::self(0, W0).regify(Reg0), 8), Outputs); 847321369Sdim case A2_satuh: 848321369Sdim return rr0(eZXT(RegisterCell::self(0, W0).regify(Reg0), 16), Outputs); 849321369Sdim 850286425Sdim // Bit count: 851286425Sdim 852286425Sdim case S2_cl0: 853286425Sdim case S2_cl0p: 854286425Sdim // Always produce a 32-bit result. 855314564Sdim return rr0(eCLB(rc(1), false/*bit*/, 32), Outputs); 856286425Sdim case S2_cl1: 857286425Sdim case S2_cl1p: 858314564Sdim return rr0(eCLB(rc(1), true/*bit*/, 32), Outputs); 859286425Sdim case S2_clb: 860286425Sdim case S2_clbp: { 861286425Sdim uint16_t W1 = getRegBitWidth(Reg[1]); 862286425Sdim RegisterCell R1 = rc(1); 863286425Sdim BT::BitValue TV = R1[W1-1]; 864286425Sdim if (TV.is(0) || TV.is(1)) 865286425Sdim return rr0(eCLB(R1, TV, 32), Outputs); 866286425Sdim break; 867286425Sdim } 868286425Sdim case S2_ct0: 869286425Sdim case S2_ct0p: 870314564Sdim return rr0(eCTB(rc(1), false/*bit*/, 32), Outputs); 871286425Sdim case S2_ct1: 872286425Sdim case S2_ct1p: 873314564Sdim return rr0(eCTB(rc(1), true/*bit*/, 32), Outputs); 874286425Sdim case S5_popcountp: 875286425Sdim // TODO 876286425Sdim break; 877286425Sdim 878286425Sdim case C2_all8: { 879286425Sdim RegisterCell P1 = rc(1); 880286425Sdim bool Has0 = false, All1 = true; 881286425Sdim for (uint16_t i = 0; i < 8/*XXX*/; ++i) { 882286425Sdim if (!P1[i].is(1)) 883286425Sdim All1 = false; 884286425Sdim if (!P1[i].is(0)) 885286425Sdim continue; 886286425Sdim Has0 = true; 887286425Sdim break; 888286425Sdim } 889286425Sdim if (!Has0 && !All1) 890286425Sdim break; 891286425Sdim RegisterCell RC(W0); 892286425Sdim RC.fill(0, W0, (All1 ? BT::BitValue::One : BT::BitValue::Zero)); 893286425Sdim return rr0(RC, Outputs); 894286425Sdim } 895286425Sdim case C2_any8: { 896286425Sdim RegisterCell P1 = rc(1); 897286425Sdim bool Has1 = false, All0 = true; 898286425Sdim for (uint16_t i = 0; i < 8/*XXX*/; ++i) { 899286425Sdim if (!P1[i].is(0)) 900286425Sdim All0 = false; 901286425Sdim if (!P1[i].is(1)) 902286425Sdim continue; 903286425Sdim Has1 = true; 904286425Sdim break; 905286425Sdim } 906286425Sdim if (!Has1 && !All0) 907286425Sdim break; 908286425Sdim RegisterCell RC(W0); 909286425Sdim RC.fill(0, W0, (Has1 ? BT::BitValue::One : BT::BitValue::Zero)); 910286425Sdim return rr0(RC, Outputs); 911286425Sdim } 912286425Sdim case C2_and: 913286425Sdim return rr0(eAND(rc(1), rc(2)), Outputs); 914286425Sdim case C2_andn: 915286425Sdim return rr0(eAND(rc(1), eNOT(rc(2))), Outputs); 916286425Sdim case C2_not: 917286425Sdim return rr0(eNOT(rc(1)), Outputs); 918286425Sdim case C2_or: 919286425Sdim return rr0(eORL(rc(1), rc(2)), Outputs); 920286425Sdim case C2_orn: 921286425Sdim return rr0(eORL(rc(1), eNOT(rc(2))), Outputs); 922286425Sdim case C2_xor: 923286425Sdim return rr0(eXOR(rc(1), rc(2)), Outputs); 924286425Sdim case C4_and_and: 925286425Sdim return rr0(eAND(rc(1), eAND(rc(2), rc(3))), Outputs); 926286425Sdim case C4_and_andn: 927286425Sdim return rr0(eAND(rc(1), eAND(rc(2), eNOT(rc(3)))), Outputs); 928286425Sdim case C4_and_or: 929286425Sdim return rr0(eAND(rc(1), eORL(rc(2), rc(3))), Outputs); 930286425Sdim case C4_and_orn: 931286425Sdim return rr0(eAND(rc(1), eORL(rc(2), eNOT(rc(3)))), Outputs); 932286425Sdim case C4_or_and: 933286425Sdim return rr0(eORL(rc(1), eAND(rc(2), rc(3))), Outputs); 934286425Sdim case C4_or_andn: 935286425Sdim return rr0(eORL(rc(1), eAND(rc(2), eNOT(rc(3)))), Outputs); 936286425Sdim case C4_or_or: 937286425Sdim return rr0(eORL(rc(1), eORL(rc(2), rc(3))), Outputs); 938286425Sdim case C4_or_orn: 939286425Sdim return rr0(eORL(rc(1), eORL(rc(2), eNOT(rc(3)))), Outputs); 940286425Sdim case C2_bitsclr: 941286425Sdim case C2_bitsclri: 942286425Sdim case C2_bitsset: 943286425Sdim case C4_nbitsclr: 944286425Sdim case C4_nbitsclri: 945286425Sdim case C4_nbitsset: 946286425Sdim // TODO 947286425Sdim break; 948286425Sdim case S2_tstbit_i: 949286425Sdim case S4_ntstbit_i: { 950286425Sdim BT::BitValue V = rc(1)[im(2)]; 951286425Sdim if (V.is(0) || V.is(1)) { 952286425Sdim // If instruction is S2_tstbit_i, test for 1, otherwise test for 0. 953286425Sdim bool TV = (Opc == S2_tstbit_i); 954286425Sdim BT::BitValue F = V.is(TV) ? BT::BitValue::One : BT::BitValue::Zero; 955286425Sdim return rr0(RegisterCell(W0).fill(0, W0, F), Outputs); 956286425Sdim } 957286425Sdim break; 958286425Sdim } 959286425Sdim 960286425Sdim default: 961341825Sdim // For instructions that define a single predicate registers, store 962341825Sdim // the low 8 bits of the register only. 963341825Sdim if (unsigned DefR = getUniqueDefVReg(MI)) { 964341825Sdim if (MRI.getRegClass(DefR) == &Hexagon::PredRegsRegClass) { 965341825Sdim BT::RegisterRef PD(DefR, 0); 966341825Sdim uint16_t RW = getRegBitWidth(PD); 967341825Sdim uint16_t PW = 8; // XXX Pred size: getRegBitWidth(Reg[1]); 968341825Sdim RegisterCell RC = RegisterCell::self(DefR, RW); 969341825Sdim RC.fill(PW, RW, BT::BitValue::Zero); 970341825Sdim putCell(PD, RC, Outputs); 971341825Sdim return true; 972341825Sdim } 973341825Sdim } 974286425Sdim return MachineEvaluator::evaluate(MI, Inputs, Outputs); 975286425Sdim } 976286425Sdim #undef im 977286425Sdim #undef rc 978286425Sdim #undef op 979286425Sdim return false; 980286425Sdim} 981286425Sdim 982309124Sdimbool HexagonEvaluator::evaluate(const MachineInstr &BI, 983309124Sdim const CellMapType &Inputs, 984309124Sdim BranchTargetList &Targets, 985309124Sdim bool &FallsThru) const { 986314564Sdim // We need to evaluate one branch at a time. TII::analyzeBranch checks 987286425Sdim // all the branches in a basic block at once, so we cannot use it. 988309124Sdim unsigned Opc = BI.getOpcode(); 989286425Sdim bool SimpleBranch = false; 990286425Sdim bool Negated = false; 991286425Sdim switch (Opc) { 992286425Sdim case Hexagon::J2_jumpf: 993314564Sdim case Hexagon::J2_jumpfpt: 994286425Sdim case Hexagon::J2_jumpfnew: 995286425Sdim case Hexagon::J2_jumpfnewpt: 996286425Sdim Negated = true; 997321369Sdim LLVM_FALLTHROUGH; 998286425Sdim case Hexagon::J2_jumpt: 999314564Sdim case Hexagon::J2_jumptpt: 1000286425Sdim case Hexagon::J2_jumptnew: 1001286425Sdim case Hexagon::J2_jumptnewpt: 1002286425Sdim // Simple branch: if([!]Pn) jump ... 1003286425Sdim // i.e. Op0 = predicate, Op1 = branch target. 1004286425Sdim SimpleBranch = true; 1005286425Sdim break; 1006286425Sdim case Hexagon::J2_jump: 1007309124Sdim Targets.insert(BI.getOperand(0).getMBB()); 1008286425Sdim FallsThru = false; 1009286425Sdim return true; 1010286425Sdim default: 1011286425Sdim // If the branch is of unknown type, assume that all successors are 1012286425Sdim // executable. 1013286425Sdim return false; 1014286425Sdim } 1015286425Sdim 1016286425Sdim if (!SimpleBranch) 1017286425Sdim return false; 1018286425Sdim 1019286425Sdim // BI is a conditional branch if we got here. 1020309124Sdim RegisterRef PR = BI.getOperand(0); 1021286425Sdim RegisterCell PC = getCell(PR, Inputs); 1022286425Sdim const BT::BitValue &Test = PC[0]; 1023286425Sdim 1024286425Sdim // If the condition is neither true nor false, then it's unknown. 1025286425Sdim if (!Test.is(0) && !Test.is(1)) 1026286425Sdim return false; 1027286425Sdim 1028286425Sdim // "Test.is(!Negated)" means "branch condition is true". 1029286425Sdim if (!Test.is(!Negated)) { 1030286425Sdim // Condition known to be false. 1031286425Sdim FallsThru = true; 1032286425Sdim return true; 1033286425Sdim } 1034286425Sdim 1035309124Sdim Targets.insert(BI.getOperand(1).getMBB()); 1036286425Sdim FallsThru = false; 1037286425Sdim return true; 1038286425Sdim} 1039286425Sdim 1040341825Sdimunsigned HexagonEvaluator::getUniqueDefVReg(const MachineInstr &MI) const { 1041341825Sdim unsigned DefReg = 0; 1042341825Sdim for (const MachineOperand &Op : MI.operands()) { 1043341825Sdim if (!Op.isReg() || !Op.isDef()) 1044341825Sdim continue; 1045360784Sdim Register R = Op.getReg(); 1046360784Sdim if (!Register::isVirtualRegister(R)) 1047341825Sdim continue; 1048341825Sdim if (DefReg != 0) 1049341825Sdim return 0; 1050341825Sdim DefReg = R; 1051341825Sdim } 1052341825Sdim return DefReg; 1053341825Sdim} 1054341825Sdim 1055309124Sdimbool HexagonEvaluator::evaluateLoad(const MachineInstr &MI, 1056309124Sdim const CellMapType &Inputs, 1057309124Sdim CellMapType &Outputs) const { 1058314564Sdim using namespace Hexagon; 1059314564Sdim 1060286425Sdim if (TII.isPredicated(MI)) 1061286425Sdim return false; 1062309124Sdim assert(MI.mayLoad() && "A load that mayn't?"); 1063309124Sdim unsigned Opc = MI.getOpcode(); 1064286425Sdim 1065286425Sdim uint16_t BitNum; 1066286425Sdim bool SignEx; 1067286425Sdim 1068286425Sdim switch (Opc) { 1069286425Sdim default: 1070286425Sdim return false; 1071286425Sdim 1072286425Sdim#if 0 1073286425Sdim // memb_fifo 1074286425Sdim case L2_loadalignb_pbr: 1075286425Sdim case L2_loadalignb_pcr: 1076286425Sdim case L2_loadalignb_pi: 1077286425Sdim // memh_fifo 1078286425Sdim case L2_loadalignh_pbr: 1079286425Sdim case L2_loadalignh_pcr: 1080286425Sdim case L2_loadalignh_pi: 1081286425Sdim // membh 1082286425Sdim case L2_loadbsw2_pbr: 1083286425Sdim case L2_loadbsw2_pci: 1084286425Sdim case L2_loadbsw2_pcr: 1085286425Sdim case L2_loadbsw2_pi: 1086286425Sdim case L2_loadbsw4_pbr: 1087286425Sdim case L2_loadbsw4_pci: 1088286425Sdim case L2_loadbsw4_pcr: 1089286425Sdim case L2_loadbsw4_pi: 1090286425Sdim // memubh 1091286425Sdim case L2_loadbzw2_pbr: 1092286425Sdim case L2_loadbzw2_pci: 1093286425Sdim case L2_loadbzw2_pcr: 1094286425Sdim case L2_loadbzw2_pi: 1095286425Sdim case L2_loadbzw4_pbr: 1096286425Sdim case L2_loadbzw4_pci: 1097286425Sdim case L2_loadbzw4_pcr: 1098286425Sdim case L2_loadbzw4_pi: 1099286425Sdim#endif 1100286425Sdim 1101286425Sdim case L2_loadrbgp: 1102286425Sdim case L2_loadrb_io: 1103286425Sdim case L2_loadrb_pbr: 1104286425Sdim case L2_loadrb_pci: 1105286425Sdim case L2_loadrb_pcr: 1106286425Sdim case L2_loadrb_pi: 1107314564Sdim case PS_loadrbabs: 1108286425Sdim case L4_loadrb_ap: 1109286425Sdim case L4_loadrb_rr: 1110286425Sdim case L4_loadrb_ur: 1111286425Sdim BitNum = 8; 1112286425Sdim SignEx = true; 1113286425Sdim break; 1114286425Sdim 1115286425Sdim case L2_loadrubgp: 1116286425Sdim case L2_loadrub_io: 1117286425Sdim case L2_loadrub_pbr: 1118286425Sdim case L2_loadrub_pci: 1119286425Sdim case L2_loadrub_pcr: 1120286425Sdim case L2_loadrub_pi: 1121314564Sdim case PS_loadrubabs: 1122286425Sdim case L4_loadrub_ap: 1123286425Sdim case L4_loadrub_rr: 1124286425Sdim case L4_loadrub_ur: 1125286425Sdim BitNum = 8; 1126286425Sdim SignEx = false; 1127286425Sdim break; 1128286425Sdim 1129286425Sdim case L2_loadrhgp: 1130286425Sdim case L2_loadrh_io: 1131286425Sdim case L2_loadrh_pbr: 1132286425Sdim case L2_loadrh_pci: 1133286425Sdim case L2_loadrh_pcr: 1134286425Sdim case L2_loadrh_pi: 1135314564Sdim case PS_loadrhabs: 1136286425Sdim case L4_loadrh_ap: 1137286425Sdim case L4_loadrh_rr: 1138286425Sdim case L4_loadrh_ur: 1139286425Sdim BitNum = 16; 1140286425Sdim SignEx = true; 1141286425Sdim break; 1142286425Sdim 1143286425Sdim case L2_loadruhgp: 1144286425Sdim case L2_loadruh_io: 1145286425Sdim case L2_loadruh_pbr: 1146286425Sdim case L2_loadruh_pci: 1147286425Sdim case L2_loadruh_pcr: 1148286425Sdim case L2_loadruh_pi: 1149286425Sdim case L4_loadruh_rr: 1150314564Sdim case PS_loadruhabs: 1151286425Sdim case L4_loadruh_ap: 1152286425Sdim case L4_loadruh_ur: 1153286425Sdim BitNum = 16; 1154286425Sdim SignEx = false; 1155286425Sdim break; 1156286425Sdim 1157286425Sdim case L2_loadrigp: 1158286425Sdim case L2_loadri_io: 1159286425Sdim case L2_loadri_pbr: 1160286425Sdim case L2_loadri_pci: 1161286425Sdim case L2_loadri_pcr: 1162286425Sdim case L2_loadri_pi: 1163286425Sdim case L2_loadw_locked: 1164314564Sdim case PS_loadriabs: 1165286425Sdim case L4_loadri_ap: 1166286425Sdim case L4_loadri_rr: 1167286425Sdim case L4_loadri_ur: 1168286425Sdim case LDriw_pred: 1169286425Sdim BitNum = 32; 1170286425Sdim SignEx = true; 1171286425Sdim break; 1172286425Sdim 1173286425Sdim case L2_loadrdgp: 1174286425Sdim case L2_loadrd_io: 1175286425Sdim case L2_loadrd_pbr: 1176286425Sdim case L2_loadrd_pci: 1177286425Sdim case L2_loadrd_pcr: 1178286425Sdim case L2_loadrd_pi: 1179286425Sdim case L4_loadd_locked: 1180314564Sdim case PS_loadrdabs: 1181286425Sdim case L4_loadrd_ap: 1182286425Sdim case L4_loadrd_rr: 1183286425Sdim case L4_loadrd_ur: 1184286425Sdim BitNum = 64; 1185286425Sdim SignEx = true; 1186286425Sdim break; 1187286425Sdim } 1188286425Sdim 1189309124Sdim const MachineOperand &MD = MI.getOperand(0); 1190286425Sdim assert(MD.isReg() && MD.isDef()); 1191286425Sdim RegisterRef RD = MD; 1192286425Sdim 1193286425Sdim uint16_t W = getRegBitWidth(RD); 1194286425Sdim assert(W >= BitNum && BitNum > 0); 1195286425Sdim RegisterCell Res(W); 1196286425Sdim 1197286425Sdim for (uint16_t i = 0; i < BitNum; ++i) 1198286425Sdim Res[i] = BT::BitValue::self(BT::BitRef(RD.Reg, i)); 1199286425Sdim 1200286425Sdim if (SignEx) { 1201286425Sdim const BT::BitValue &Sign = Res[BitNum-1]; 1202286425Sdim for (uint16_t i = BitNum; i < W; ++i) 1203286425Sdim Res[i] = BT::BitValue::ref(Sign); 1204286425Sdim } else { 1205286425Sdim for (uint16_t i = BitNum; i < W; ++i) 1206286425Sdim Res[i] = BT::BitValue::Zero; 1207286425Sdim } 1208286425Sdim 1209286425Sdim putCell(RD, Res, Outputs); 1210286425Sdim return true; 1211286425Sdim} 1212286425Sdim 1213309124Sdimbool HexagonEvaluator::evaluateFormalCopy(const MachineInstr &MI, 1214309124Sdim const CellMapType &Inputs, 1215309124Sdim CellMapType &Outputs) const { 1216286425Sdim // If MI defines a formal parameter, but is not a copy (loads are handled 1217286425Sdim // in evaluateLoad), then it's not clear what to do. 1218309124Sdim assert(MI.isCopy()); 1219286425Sdim 1220309124Sdim RegisterRef RD = MI.getOperand(0); 1221309124Sdim RegisterRef RS = MI.getOperand(1); 1222286425Sdim assert(RD.Sub == 0); 1223360784Sdim if (!Register::isPhysicalRegister(RS.Reg)) 1224286425Sdim return false; 1225286425Sdim RegExtMap::const_iterator F = VRX.find(RD.Reg); 1226286425Sdim if (F == VRX.end()) 1227286425Sdim return false; 1228286425Sdim 1229286425Sdim uint16_t EW = F->second.Width; 1230286425Sdim // Store RD's cell into the map. This will associate the cell with a virtual 1231286425Sdim // register, and make zero-/sign-extends possible (otherwise we would be ex- 1232286425Sdim // tending "self" bit values, which will have no effect, since "self" values 1233286425Sdim // cannot be references to anything). 1234286425Sdim putCell(RD, getCell(RS, Inputs), Outputs); 1235286425Sdim 1236286425Sdim RegisterCell Res; 1237286425Sdim // Read RD's cell from the outputs instead of RS's cell from the inputs: 1238286425Sdim if (F->second.Type == ExtType::SExt) 1239286425Sdim Res = eSXT(getCell(RD, Outputs), EW); 1240286425Sdim else if (F->second.Type == ExtType::ZExt) 1241286425Sdim Res = eZXT(getCell(RD, Outputs), EW); 1242286425Sdim 1243286425Sdim putCell(RD, Res, Outputs); 1244286425Sdim return true; 1245286425Sdim} 1246286425Sdim 1247286425Sdimunsigned HexagonEvaluator::getNextPhysReg(unsigned PReg, unsigned Width) const { 1248286425Sdim using namespace Hexagon; 1249314564Sdim 1250286425Sdim bool Is64 = DoubleRegsRegClass.contains(PReg); 1251286425Sdim assert(PReg == 0 || Is64 || IntRegsRegClass.contains(PReg)); 1252286425Sdim 1253286425Sdim static const unsigned Phys32[] = { R0, R1, R2, R3, R4, R5 }; 1254286425Sdim static const unsigned Phys64[] = { D0, D1, D2 }; 1255286425Sdim const unsigned Num32 = sizeof(Phys32)/sizeof(unsigned); 1256286425Sdim const unsigned Num64 = sizeof(Phys64)/sizeof(unsigned); 1257286425Sdim 1258286425Sdim // Return the first parameter register of the required width. 1259286425Sdim if (PReg == 0) 1260286425Sdim return (Width <= 32) ? Phys32[0] : Phys64[0]; 1261286425Sdim 1262286425Sdim // Set Idx32, Idx64 in such a way that Idx+1 would give the index of the 1263286425Sdim // next register. 1264286425Sdim unsigned Idx32 = 0, Idx64 = 0; 1265286425Sdim if (!Is64) { 1266286425Sdim while (Idx32 < Num32) { 1267286425Sdim if (Phys32[Idx32] == PReg) 1268286425Sdim break; 1269286425Sdim Idx32++; 1270286425Sdim } 1271286425Sdim Idx64 = Idx32/2; 1272286425Sdim } else { 1273286425Sdim while (Idx64 < Num64) { 1274286425Sdim if (Phys64[Idx64] == PReg) 1275286425Sdim break; 1276286425Sdim Idx64++; 1277286425Sdim } 1278286425Sdim Idx32 = Idx64*2+1; 1279286425Sdim } 1280286425Sdim 1281286425Sdim if (Width <= 32) 1282286425Sdim return (Idx32+1 < Num32) ? Phys32[Idx32+1] : 0; 1283286425Sdim return (Idx64+1 < Num64) ? Phys64[Idx64+1] : 0; 1284286425Sdim} 1285286425Sdim 1286286425Sdimunsigned HexagonEvaluator::getVirtRegFor(unsigned PReg) const { 1287327952Sdim for (std::pair<unsigned,unsigned> P : MRI.liveins()) 1288327952Sdim if (P.first == PReg) 1289327952Sdim return P.second; 1290286425Sdim return 0; 1291286425Sdim} 1292