[llvm] 4d9969e - [AVR] Fix incorrect decoding of conditional branch instructions

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 29 00:28:53 PST 2023


Author: Ben Shi
Date: 2023-01-29T16:28:42+08:00
New Revision: 4d9969ebe32ec800498f858e542e59cdb5556f6d

URL: https://github.com/llvm/llvm-project/commit/4d9969ebe32ec800498f858e542e59cdb5556f6d
DIFF: https://github.com/llvm/llvm-project/commit/4d9969ebe32ec800498f858e542e59cdb5556f6d.diff

LOG: [AVR] Fix incorrect decoding of conditional branch instructions

This patch fixes the inaccurate decoding of the offset operand of
the conditional branch instructions.

Reviewed By: aykevl

Differential Revision: https://reviews.llvm.org/D140816

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td
index 96b48a504376a..653c7276ba7f0 100644
--- a/llvm/lib/Target/AVR/AVRInstrFormats.td
+++ b/llvm/lib/Target/AVR/AVRInstrFormats.td
@@ -432,6 +432,8 @@ class FBRsk<bit f, bits<3> s, dag outs, dag ins, string asmstr,
   let Inst{10} = f;
   let Inst{9 - 3} = k;
   let Inst{2 - 0} = s;
+
+  let DecoderMethod = "decodeCondBranch";
 }
 
 //===----------------------------------------------------------------------===//
@@ -561,6 +563,8 @@ class FSK<bit f, dag outs, dag ins, string asmstr, list<dag> pattern>
 
   let Inst{3} = k{0};
   let Inst{2 - 0} = s;
+
+  let DecoderMethod = "decodeCondBranch";
 }
 
 class ExtensionPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>

diff  --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index 7674d9e354faf..df047ed8ecae0 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -16,6 +16,9 @@
 #include "MCTargetDesc/AVRMCTargetDesc.h"
 #include "TargetInfo/AVRTargetInfo.h"
 
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDecoderOps.h"
@@ -126,6 +129,10 @@ static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
 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 +294,40 @@ static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
+                                     uint64_t Address,
+                                     const MCDisassembler *Decoder) {
+  // These 8 instructions are not defined as aliases of BRBS/BRBC.
+  DenseMap<unsigned, unsigned> 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;
+
+  // Search the instruction pattern.
+  auto NotAlias = [&Insn](const std::pair<unsigned, unsigned> &I) {
+    return (Insn & 0x407) != I.first;
+  };
+  llvm::partition(brInsts, NotAlias);
+  auto It = llvm::partition_point(brInsts, NotAlias);
+
+  // Decode the instruction.
+  if (It != brInsts.end()) {
+    // This instruction is not an alias of BRBC/BRBS.
+    Inst.setOpcode(It->second);
+    Inst.addOperand(MCOperand::createImm(Offset));
+  } else {
+    // Fall back to an 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) {

diff  --git a/llvm/test/MC/AVR/inst-brbc.s b/llvm/test/MC/AVR/inst-brbc.s
index 2f92416a40700..bf9dba470f2aa 100644
--- a/llvm/test/MC/AVR/inst-brbc.s
+++ b/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

diff  --git a/llvm/test/MC/AVR/inst-brbs.s b/llvm/test/MC/AVR/inst-brbs.s
index bf2ca31f88318..ad4cc46871937 100644
--- a/llvm/test/MC/AVR/inst-brbs.s
+++ b/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


        


More information about the llvm-commits mailing list