[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