diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -5129,6 +5129,7 @@ def TSB : AInoP<(outs), (ins tsb_opt:$opt), MiscFrm, NoItinerary, "tsb", "\t$opt", []>, Requires<[IsARM, HasV8_4a]> { let Inst{31-0} = 0xe320f012; + let DecoderMethod = "DecodeTSBInstruction"; } } diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -3561,6 +3561,7 @@ def t2TSB : T2I<(outs), (ins tsb_opt:$opt), NoItinerary, "tsb", "\t$opt", []>, Requires<[IsThumb, HasV8_4a]> { let Inst{31-0} = 0xf3af8012; + let DecoderMethod = "DecodeTSBInstruction"; } } diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -265,6 +265,8 @@ uint64_t Address, const void *Decoder); static DecodeStatus DecodeAddrMode3Instruction(MCInst &Inst,unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeTSBInstruction(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSORegRegOperand(MCInst &Inst, unsigned Insn, @@ -2013,6 +2015,19 @@ return S; } +static DecodeStatus DecodeTSBInstruction(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder) { + if (Inst.getOpcode() != ARM::TSB && Inst.getOpcode() != ARM::t2TSB) + return MCDisassembler::Fail; + + // The "csync" operand is not encoded into the "tsb" instruction (as this is + // the only available operand), but LLVM expects the instruction to have one + // operand, so we need to add the csync when decoding. + Inst.addOperand(MCOperand::createImm(ARM_TSB::CSYNC)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeAddrMode3Instruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { diff --git a/llvm/test/MC/ARM/armv8.4a-trace.s b/llvm/test/MC/ARM/armv8.4a-trace.s --- a/llvm/test/MC/ARM/armv8.4a-trace.s +++ b/llvm/test/MC/ARM/armv8.4a-trace.s @@ -2,10 +2,18 @@ // RUN: llvm-mc -triple thumb -mattr=+v8.4a -show-encoding < %s | FileCheck %s --check-prefix=CHECK-T32 // RUN: not llvm-mc -triple arm -mattr=-v8.4a -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V84 +// RUN: llvm-mc -filetype=obj -triple arm -mattr=+v8.4a < %s \ +// RUN: | llvm-objdump --triple=arm --mattr=+v8.4a -r -d - \ +// RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %s +// RUN: llvm-mc -filetype=obj -triple thumb -mattr=+v8.4a < %s \ +// RUN: | llvm-objdump --triple=thumb --mattr=+v8.4a -r -d - \ +// RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %s + tsb csync //CHECK-A32: tsb csync @ encoding: [0x12,0xf0,0x20,0xe3] //CHECK-T32: tsb csync @ encoding: [0xaf,0xf3,0x12,0x80] +//CHECK-OBJDUMP: tsb csync //CHECK-NO-V84: error: invalid instruction //CHECK-NO-V84: tsb csync