[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
This commit is contained in:
Ben Shi 2023-01-07 15:25:38 +08:00
parent 54971c8a39
commit 4d9969ebe3
4 changed files with 71 additions and 2 deletions

View File

@ -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>

View File

@ -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) {

View File

@ -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

View File

@ -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