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