Index: lld/test/ELF/avr-reloc.s =================================================================== --- lld/test/ELF/avr-reloc.s +++ lld/test/ELF/avr-reloc.s @@ -62,18 +62,23 @@ sbic b, 1 ; R_AVR_PORT5 ;; The disassembler is not yet able to decode those opcodes -;; 0f c0 rjmp .+30 -;; ee cf rjmp .-36 ;; 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: rcall .-44 ; HEX-LABEL: section .PCREL: -; HEX-NEXT: 0fc0eecf 69f061f3 +; HEX-NEXT: 0fc0eecf 69f061f3 0bd0eadf foo: -rjmp foo + 32 ; R_AVR_13_PCREL -rjmp foo - 32 ; R_AVR_13_PCREL -breq foo + 32 ; R_AVR_7_PCREL -breq foo - 32 ; R_AVR_7_PCREL +rjmp foo + 32 ; R_AVR_13_PCREL +rjmp foo - 32 ; R_AVR_13_PCREL +breq foo + 32 ; R_AVR_7_PCREL +breq foo - 32 ; R_AVR_7_PCREL +rcall foo + 32 ; R_AVR_13_PCREL +rcall foo - 32 ; R_AVR_13_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 @@ -460,6 +460,8 @@ let Inst{15 - 13} = 0b110; let Inst{12} = f; let Inst{11 - 0} = k; + + let DecoderMethod = "decodeFBRk"; } //===----------------------------------------------------------------------===// Index: llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp =================================================================== --- llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp +++ llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp @@ -123,6 +123,9 @@ static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder); +static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address, + const MCDisassembler *Decoder); + static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder); @@ -265,6 +268,25 @@ return MCDisassembler::Success; } +static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address, + const MCDisassembler *Decoder) { + // Decode the opcode. + switch (Insn & 0xf000) { + case 0xc000: + Inst.setOpcode(AVR::RJMPk); + break; + case 0xd000: + Inst.setOpcode(AVR::RCALLk); + break; + default: // Unknown relative branch instruction. + return MCDisassembler::Fail; + } + // Decode the relative offset. + int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3; + Inst.addOperand(MCOperand::createImm(Offset)); + return MCDisassembler::Success; +} + static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder) { @@ -275,7 +297,7 @@ if ((Insn & 0xf000) == 0x8000) { unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30; unsigned Offset = Insn & 7; // We need not consider offset > 7. - if ((Insn & 0x200) == 0) { // Decode LDD. + if ((Insn & 0x200) == 0) { // Decode LDD. Inst.setOpcode(AVR::LDDRdPtrQ); Inst.addOperand(MCOperand::createReg(RegVal)); Inst.addOperand(MCOperand::createReg(RegBase));