[llvm] 6dc85bd - [AVR] Fix incorrect decoding of RJMP and RCALL

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 7 07:32:28 PST 2023


Author: Ben Shi
Date: 2023-01-07T23:26:40+08:00
New Revision: 6dc85bd3fde7df2999fda07e9e9f2e83d52c6125

URL: https://github.com/llvm/llvm-project/commit/6dc85bd3fde7df2999fda07e9e9f2e83d52c6125
DIFF: https://github.com/llvm/llvm-project/commit/6dc85bd3fde7df2999fda07e9e9f2e83d52c6125.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Target/AVR/AVRInstrFormats.td
    llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
    llvm/test/MC/AVR/inst-rcall.s
    llvm/test/MC/AVR/inst-rjmp.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td
index dd8da7092d471..96b48a504376a 100644
--- a/llvm/lib/Target/AVR/AVRInstrFormats.td
+++ b/llvm/lib/Target/AVR/AVRInstrFormats.td
@@ -460,6 +460,8 @@ class FBRk<bit f, dag outs, dag ins, string asmstr, list<dag> 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 d8734596148d5..7674d9e354faf 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 84a7343c52517..4e75620b147e7 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 22d9f2f8d9b2a..472d654ce3460 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


        


More information about the llvm-commits mailing list