diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td --- a/llvm/lib/Target/AVR/AVRInstrFormats.td +++ b/llvm/lib/Target/AVR/AVRInstrFormats.td @@ -432,6 +432,8 @@ let Inst{10} = f; let Inst{9 - 3} = k; let Inst{2 - 0} = s; + + let DecoderMethod = "decodeCondBranch"; } //===----------------------------------------------------------------------===// @@ -561,6 +563,8 @@ let Inst{3} = k{0}; let Inst{2 - 0} = s; + + let DecoderMethod = "decodeCondBranch"; } class ExtensionPseudo pattern> diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp --- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp +++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp @@ -16,6 +16,9 @@ #include "MCTargetDesc/AVRMCTargetDesc.h" #include "TargetInfo/AVRTargetInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" + #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDecoderOps.h" @@ -126,6 +129,10 @@ static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder); +static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn, + uint64_t Address, + const MCDisassembler *Decoder); + static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder); @@ -287,6 +294,40 @@ return MCDisassembler::Success; } +static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + // These 8 instructions are not defined as aliases of BRBS/BRBC. + DenseMap brInsts = { + {0x000, AVR::BRLOk}, {0x400, AVR::BRSHk}, {0x001, AVR::BREQk}, + {0x401, AVR::BRNEk}, {0x002, AVR::BRMIk}, {0x402, AVR::BRPLk}, + {0x004, AVR::BRLTk}, {0x404, AVR::BRGEk}}; + + // Get the relative offset. + int16_t Offset = ((int16_t)((Insn & 0x3f8) << 6)) >> 8; + + // Search the instruction pattern. + auto NotAlias = [&Insn](const std::pair &I) { + return (Insn & 0x407) != I.first; + }; + llvm::partition(brInsts, NotAlias); + auto It = llvm::partition_point(brInsts, NotAlias); + + // Decode the instruction. + if (It != brInsts.end()) { + // This instruction is not an alias of BRBC/BRBS. + Inst.setOpcode(It->second); + Inst.addOperand(MCOperand::createImm(Offset)); + } else { + // Fall back to an ordinary BRBS/BRBC. + Inst.setOpcode(Insn & 0x400 ? AVR::BRBCsk : AVR::BRBSsk); + Inst.addOperand(MCOperand::createImm(Insn & 7)); + Inst.addOperand(MCOperand::createImm(Offset)); + } + + return MCDisassembler::Success; +} + static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder) { diff --git a/llvm/test/MC/AVR/inst-brbc.s b/llvm/test/MC/AVR/inst-brbc.s --- a/llvm/test/MC/AVR/inst-brbc.s +++ b/llvm/test/MC/AVR/inst-brbc.s @@ -1,12 +1,24 @@ ; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s - +; RUN: llvm-mc -filetype=obj -triple avr < %s \ +; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s foo: brbc 3, .+8 brbc 0, .-16 + .short 0xf759 + .short 0xf752 + .short 0xf74c + .short 0xf4c7 ; CHECK: brvc .Ltmp0+8 ; encoding: [0bAAAAA011,0b111101AA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp0+8, kind: fixup_7_pcrel ; CHECK: brcc .Ltmp1-16 ; encoding: [0bAAAAA000,0b111101AA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp1-16, kind: fixup_7_pcrel + +; INST: brvc .+0 +; INST: brsh .+0 +; INST: brne .-42 +; INST: brpl .-44 +; INST: brge .-46 +; INST: brid .+48 diff --git a/llvm/test/MC/AVR/inst-brbs.s b/llvm/test/MC/AVR/inst-brbs.s --- a/llvm/test/MC/AVR/inst-brbs.s +++ b/llvm/test/MC/AVR/inst-brbs.s @@ -1,12 +1,24 @@ ; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s - +; RUN: llvm-mc -filetype=obj -triple avr < %s \ +; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s foo: brbs 3, .+8 brbs 0, .-12 + .short 0xf359 + .short 0xf352 + .short 0xf34c + .short 0xf077 ; CHECK: brvs .Ltmp0+8 ; encoding: [0bAAAAA011,0b111100AA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp0+8, kind: fixup_7_pcrel ; CHECK: brcs .Ltmp1-12 ; encoding: [0bAAAAA000,0b111100AA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp1-12, kind: fixup_7_pcrel + +; INST: brvs .+0 +; INST: brlo .+0 +; INST: breq .-42 +; INST brmi .-44 +; INST brlt .-46 +; InST: brie .+28