]> granicus.if.org Git - llvm/commitdiff
[AVR] Rewrite the CBRRdK instruction as an alias of ANDIRdK
authorDylan McKay <me@dylanmckay.io>
Fri, 18 Jan 2019 07:31:34 +0000 (07:31 +0000)
committerDylan McKay <me@dylanmckay.io>
Fri, 18 Jan 2019 07:31:34 +0000 (07:31 +0000)
The CBR instruction is just an ANDI instruction with the immediate
complemented.

Because of this, prior to this change TableGen would warn due to a
decoding conflict.

This commit fixes the existing compilation warning:

  ===============
  [423/492] Building AVRGenDisassemblerTables.inc...
  Decoding Conflict:
                  0111............
                  01..............
                  ................
          ANDIRdK 0111____________
          CBRRdK 0111____________
  ================

After this commit, there are no more decoding conflicts in the AVR
backend's instruction definitions.

Thanks to Eli F for pointing me torward `t2_so_imm_not` as an example of
how to perform a complement in an instruction alias.

Fixes BugZilla PR38802.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351526 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AVR/AVRInstrInfo.td
lib/Target/AVR/AsmParser/AVRAsmParser.cpp

index 5720af7d8df6167c046997d2064f74ecaca9142b..fffa66faa8c8d624c834a4eea916613b2ad98f2f 100644 (file)
@@ -90,6 +90,22 @@ def imm0_63_neg : PatLeaf<(imm),
 
 def uimm6 : PatLeaf<(imm), [{ return isUInt<6>(N->getZExtValue()); }]>;
 
+// imm_com8_XFORM - Return the complement of a t2_so_imm value
+def imm_com8_XFORM : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant(~((uint8_t)N->getZExtValue()), SDLoc(N),
+                                   MVT::i8);
+}]>;
+
+// imm_com8 - Match an immediate that is a complement
+// of a 8-bit immediate.
+// Note: this pattern doesn't require an encoder method and such, as it's
+// only used on aliases (Pat<> and InstAlias<>). The actual encoding
+// is handled by the destination instructions, which use t2_so_imm.
+def imm_com8_asmoperand : AsmOperandClass { let Name = "ImmCom8"; }
+def imm_com8 : Operand<i8> {
+  let ParserMatchClass = imm_com8_asmoperand;
+}
+
 def ioaddr_XFORM : SDNodeXForm<imm,
 [{
   return CurDAG->getTargetConstant(uint8_t(N->getZExtValue()) - 0x20, SDLoc(N), MVT::i8);
@@ -157,13 +173,6 @@ def memspi : Operand<iPTR>
   let MIOperandInfo = (ops GPRSP, i16imm);
 }
 
-def imm_com8 : Operand<i8>
-{
-  let EncoderMethod = "encodeComplement";
-
-  let MIOperandInfo = (ops i8imm);
-}
-
 def relbrtarget_7 : Operand<OtherVT>
 {
     let PrintMethod   = "printPCRelImm";
@@ -1729,20 +1738,7 @@ def BLD : FRdB<0b00,
                "bld\t$rd, $b",
                []>;
 
-// Set/clear bit in register operations.
-let Constraints = "$src = $rd",
-Defs = [SREG] in
-{
-  // CBR Rd, K
-  // Alias for `ANDI Rd, COM(K)` where COM(K) is the complement of K.
-  // FIXME: This uses the 'complement' encoder. We need it to also use the
-  // imm_ldi8 encoder. This will cause no fixups to be created on this instruction.
-  def CBRRdK : FRdK<0b0111,
-                    (outs LD8:$rd),
-                    (ins LD8:$src, imm_com8:$k),
-                    "cbr\t$rd, $k",
-                    []>;
-}
+def CBR : InstAlias<"cbr\t$rd, $k", (ANDIRdK LD8:$rd, imm_com8:$k), 0>;
 
 // CLR Rd
 // Alias for EOR Rd, Rd
index f2bb59265271b4625115e9a051cfbd47453e5c71..f496dea64d1687a90c87233ea8fe3590c07ade99 100644 (file)
@@ -160,6 +160,22 @@ public:
     addExpr(Inst, getImm());
   }
 
+  void addImmCom8Operands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    // The operand is actually a imm8, but we have its bitwise
+    // negation in the assembly source, so twiddle it here.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    Inst.addOperand(MCOperand::createImm(~(uint8_t)CE->getValue()));
+  }
+
+  bool isImmCom8() const {
+    if (!isImm()) return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE) return false;
+    int64_t Value = CE->getValue();
+    return isUInt<8>(Value);
+  }
+
   bool isReg() const { return Kind == k_Register; }
   bool isImm() const { return Kind == k_Immediate; }
   bool isToken() const { return Kind == k_Token; }