Index: llvm/lib/Target/AVR/AVRInstrFormats.td =================================================================== --- llvm/lib/Target/AVR/AVRInstrFormats.td +++ 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> Index: llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp =================================================================== --- llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp +++ llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp @@ -16,6 +16,8 @@ #include "MCTargetDesc/AVRMCTargetDesc.h" #include "TargetInfo/AVRTargetInfo.h" +#include "llvm/ADT/DenseMap.h" + #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDecoderOps.h" @@ -126,6 +128,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 +293,31 @@ return MCDisassembler::Success; } +static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + 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; + + if (brInsts.find(Insn & 0x407) != brInsts.end()) { + // The above 8 instructions are not defined as aliases of BRBS/BRBC. + Inst.setOpcode(brInsts[Insn & 0x407]); + Inst.addOperand(MCOperand::createImm(Offset)); + } else { + // Fall back to 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) { Index: llvm/test/MC/AVR/inst-brbc.s =================================================================== --- llvm/test/MC/AVR/inst-brbc.s +++ 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 Index: llvm/test/MC/AVR/inst-brbs.s =================================================================== --- llvm/test/MC/AVR/inst-brbs.s +++ 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