Index: lld/test/ELF/avr-reloc.s =================================================================== --- lld/test/ELF/avr-reloc.s +++ lld/test/ELF/avr-reloc.s @@ -61,17 +61,21 @@ in r20, b ; R_AVR_PORT6 sbic b, 1 ; R_AVR_PORT5 -;; The disassembler is not yet able to decode those opcodes -;; 69 f0 breq .+26 -;; 61 f3 breq .-40 .section .PCREL,"ax",@progbits ; CHECK-LABEL: section .PCREL ; CHECK: rjmp .+30 ; CHECK-NEXT: rjmp .-36 -; CHECK: rcall .+22 +; CHECK-NEXT: breq .+26 +; CHECK-NEXT: breq .-40 +; CHECK-NEXT: rcall .+22 ; CHECK-NEXT: rcall .-44 +; CHECK-NEXT: brlt .+18 +; CHECK-NEXT: brmi .-48 +; CHECK-NEXT: brts .+14 +; CHECK-NEXT: brid .-52 ; HEX-LABEL: section .PCREL: -; HEX-NEXT: 0fc0eecf 69f061f3 0bd0eadf +; HEX-NEXT: 0fc0eecf 69f061f3 0bd0eadf 4cf042f3 +; HEX-NEXT: 3ef037f7 foo: rjmp foo + 32 ; R_AVR_13_PCREL rjmp foo - 32 ; R_AVR_13_PCREL @@ -79,6 +83,10 @@ breq foo - 32 ; R_AVR_7_PCREL rcall foo + 32 ; R_AVR_13_PCREL rcall foo - 32 ; R_AVR_13_PCREL +brlt foo + 32 ; R_AVR_7_PCREL +brmi foo - 32 ; R_AVR_7_PCREL +brts foo + 32 ; R_AVR_7_PCREL +brid foo - 32 ; R_AVR_7_PCREL .section .DATA,"ax",@progbits ; HEX-LABEL: section .DATA: 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,7 @@ #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 +127,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 +292,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) {