From d770da9834227c0751aa4e05ab18bd16112f2f99 Mon Sep 17 00:00:00 2001 From: Dylan McKay Date: Fri, 18 Jan 2019 07:31:34 +0000 Subject: [PATCH] [AVR] Rewrite the CBRRdK instruction as an alias of ANDIRdK 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. llvm-svn: 351526 --- llvm/lib/Target/AVR/AVRInstrInfo.td | 38 +++++++++---------- .../lib/Target/AVR/AsmParser/AVRAsmParser.cpp | 16 ++++++++ 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td index 5720af7d8df6..fffa66faa8c8 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -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 : SDNodeXFormgetTargetConstant(~((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 { + let ParserMatchClass = imm_com8_asmoperand; +} + def ioaddr_XFORM : SDNodeXFormgetTargetConstant(uint8_t(N->getZExtValue()) - 0x20, SDLoc(N), MVT::i8); @@ -157,13 +173,6 @@ def memspi : Operand let MIOperandInfo = (ops GPRSP, i16imm); } -def imm_com8 : Operand -{ - let EncoderMethod = "encodeComplement"; - - let MIOperandInfo = (ops i8imm); -} - def relbrtarget_7 : Operand { 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 diff --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp index f2bb59265271..f496dea64d16 100644 --- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp +++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp @@ -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(getImm()); + Inst.addOperand(MCOperand::createImm(~(uint8_t)CE->getValue())); + } + + bool isImmCom8() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast(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; }