From 6dc85bd3fde7df2999fda07e9e9f2e83d52c6125 Mon Sep 17 00:00:00 2001 From: Ben Shi Date: Sat, 7 Jan 2023 14:33:24 +0800 Subject: [PATCH] [AVR] Fix incorrect decoding of RJMP and RCALL This patch fixes the inaccurate decoding of the offset operand of the RCALL & RJMP instructions. Reviewed By: aykevl, MaskRay Differential Revision: https://reviews.llvm.org/D140815 --- llvm/lib/Target/AVR/AVRInstrFormats.td | 2 ++ .../Target/AVR/Disassembler/AVRDisassembler.cpp | 24 +++++++++++++++++++++- llvm/test/MC/AVR/inst-rcall.s | 8 ++++++++ llvm/test/MC/AVR/inst-rjmp.s | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td index dd8da70..96b48a5 100644 --- a/llvm/lib/Target/AVR/AVRInstrFormats.td +++ b/llvm/lib/Target/AVR/AVRInstrFormats.td @@ -460,6 +460,8 @@ class FBRk pattern> let Inst{15 - 13} = 0b110; let Inst{12} = f; let Inst{11 - 0} = k; + + let DecoderMethod = "decodeFBRk"; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp index d873459..7674d9e 100644 --- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp +++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp @@ -123,6 +123,9 @@ static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn, 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 @@ static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address, 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 @@ static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn, 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)); diff --git a/llvm/test/MC/AVR/inst-rcall.s b/llvm/test/MC/AVR/inst-rcall.s index 84a7343..4e75620 100644 --- a/llvm/test/MC/AVR/inst-rcall.s +++ b/llvm/test/MC/AVR/inst-rcall.s @@ -1,4 +1,6 @@ ; 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: @@ -7,6 +9,7 @@ foo: rcall .-8 rcall .+12 rcall .+46 + .short 0xdfea ; CHECK: rcall .Ltmp0+0 ; encoding: [A,0b1101AAAA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp0+0, kind: fixup_13_pcrel @@ -17,3 +20,8 @@ foo: ; CHECK: rcall .Ltmp3+46 ; encoding: [A,0b1101AAAA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp3+46, kind: fixup_13_pcrel +; INST: rcall .+0 +; INST: rcall .+0 +; INST: rcall .+0 +; INST: rcall .+0 +; INST: rcall .-44 diff --git a/llvm/test/MC/AVR/inst-rjmp.s b/llvm/test/MC/AVR/inst-rjmp.s index 22d9f2f..472d654 100644 --- a/llvm/test/MC/AVR/inst-rjmp.s +++ b/llvm/test/MC/AVR/inst-rjmp.s @@ -16,6 +16,7 @@ end: rjmp .-6 x: rjmp x + .short 0xc00f ; CHECK: rjmp .Ltmp0+2 ; encoding: [A,0b1100AAAA] ; CHECK: ; fixup A - offset: 0, value: .Ltmp0+2, kind: fixup_13_pcrel @@ -45,3 +46,4 @@ x: ; INST: rjmp .+0 ; INST: rjmp .+0 ; INST: rjmp .+0 +; INST: rjmp .+30 -- 2.7.4