Skip to content

Commit 3a34194

Browse files
committed
[ARM] Fix Asm/Disasm of TBB/TBH instructions
Summary: This fixes Bugzilla llvm#46616 in which it was reported that "tbb [pc, r0]" was marked as SoftFail (aka unpredictable) incorrectly. Expected behaviour is: * ARMv8 is required to use sp as rn or rm (tbb/tbh only have a Thumb encoding so using Arm mode is not an option) * If rm is the pc then the instruction is always unpredictable Some of this was implemented already and this fixes the rest. Added tests cover the new and pre-existing handling. Reviewers: ostannard Reviewed By: ostannard Subscribers: kristof.beyls, hiraditya, danielkiss, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D84227
1 parent 54eea61 commit 3a34194

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed

llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10598,6 +10598,12 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1059810598
(isThumb() && !hasV8Ops()))
1059910599
return Match_InvalidOperand;
1060010600
break;
10601+
case ARM::t2TBB:
10602+
case ARM::t2TBH:
10603+
// Rn = sp is only allowed with ARMv8-A
10604+
if (!hasV8Ops() && (Inst.getOperand(0).getReg() == ARM::SP))
10605+
return Match_RequiresV8;
10606+
break;
1060110607
default:
1060210608
break;
1060310609
}

llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4529,12 +4529,14 @@ static DecodeStatus DecodeCoprocessor(MCInst &Inst, unsigned Val,
45294529
static DecodeStatus
45304530
DecodeThumbTableBranch(MCInst &Inst, unsigned Insn,
45314531
uint64_t Address, const void *Decoder) {
4532+
const FeatureBitset &FeatureBits =
4533+
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
45324534
DecodeStatus S = MCDisassembler::Success;
45334535

45344536
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
45354537
unsigned Rm = fieldFromInstruction(Insn, 0, 4);
45364538

4537-
if (Rn == ARM::SP) S = MCDisassembler::SoftFail;
4539+
if (Rn == 13 && !FeatureBits[ARM::HasV8Ops]) S = MCDisassembler::SoftFail;
45384540
if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
45394541
return MCDisassembler::Fail;
45404542
if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))

llvm/test/MC/ARM/thumb2-diagnostics.s

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,25 @@ foo2:
165165
@ CHECK-ERRORS-V7: error: operand must be a register in range [r0, r12] or r14
166166
@ CHECK-ERRORS-V7: operand must be a register in range [r0, r12] or r14
167167
@ CHECK-ERRORS-V7: operand must be a register in range [r0, r12] or r14
168+
169+
tbb [r0, sp]
170+
@ v8 allows rm = sp
171+
@ CHECK-ERRORS-V7: error: instruction variant requires ARMv8 or later
172+
tbb [r0, pc]
173+
@ rm = pc is always unpredictable
174+
@ CHECK-ERRORS: error: invalid operand for instruction
175+
tbb [sp, r0]
176+
@ v8 allows rn = sp
177+
@ CHECK-ERRORS-V7: error: instruction variant requires ARMv8 or later
178+
@ rn = pc is allowed so not included here
179+
180+
tbh [r0, sp, lsl #1]
181+
@ v8 allows rm = sp
182+
@ CHECK-ERRORS-V7: error: instruction variant requires ARMv8 or later
183+
tbh [r0, pc, lsl #1]
184+
@ rm = pc is always unpredictable
185+
@ CHECK-ERRORS: error: invalid operand for instruction
186+
tbh [sp, r0, lsl #1]
187+
@ v8 allows rn = sp
188+
@ CHECK-ERRORS-V7: error: instruction variant requires ARMv8 or later
189+
@ rn=pc is allowed so not included here
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# RUN: llvm-mc -triple=thumbv7 -disassemble %s 2>&1 | \
2+
# RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V7
3+
# RUN: llvm-mc -triple=thumbv8 -disassemble %s 2>&1 | \
4+
# RUN: FileCheck %s --check-prefix=CHECK
5+
6+
# tbb [r0, sp]
7+
0xd0 0xe8 0x0d 0xf0
8+
# CHECK-V7: warning: potentially undefined instruction encoding
9+
# CHECK-V7-NEXT: 0xd0 0xe8 0x0d 0xf0
10+
11+
# tbb [r0, pc]
12+
0xd0 0xe8 0x0f 0xf0
13+
# CHECK: warning: potentially undefined instruction encoding
14+
# CHECK-NEXT: 0xd0 0xe8 0x0f 0xf0
15+
16+
# tbb [sp, r0]
17+
0xdd 0xe8 0x00 0xf0
18+
# CHECK-V7: warning: potentially undefined instruction encoding
19+
# CHECK-V7-NEXT: 0xdd 0xe8 0x00 0xf0
20+
21+
# tbb [pc, r0]
22+
0xdf 0xe8 0x00 0xf0
23+
24+
# tbh [r0, sp, lsl #1]
25+
0xd0 0xe8 0x1d 0xf0
26+
# CHECK-V7: warning: potentially undefined instruction encoding
27+
# CHECK-V7-NEXT: 0xd0 0xe8 0x1d 0xf0
28+
29+
# tbh [r0, pc, lsl #1]
30+
0xd0 0xe8 0x1f 0xf0
31+
# CHECK: warning: potentially undefined instruction encoding
32+
# CHECK-NEXT: 0xd0 0xe8 0x1f 0xf0
33+
34+
# tbh [sp, r0, lsl #1]
35+
0xdd 0xe8 0x10 0xf0
36+
# CHECK-V7: warning: potentially undefined instruction encoding
37+
# CHECK-V7-NEXT: 0xdd 0xe8 0x10 0xf0
38+
39+
# tbh [pc, r0, lsl #1]
40+
0xdf 0xe8 0x10 0xf0
41+
42+
# CHECK: tbb [r0, sp]
43+
# CHECK: tbb [r0, pc]
44+
# CHECK: tbb [sp, r0]
45+
# CHECK: tbb [pc, r0]
46+
# CHECK: tbh [r0, sp, lsl #1]
47+
# CHECK: tbh [r0, pc, lsl #1]
48+
# CHECK: tbh [sp, r0, lsl #1]
49+
# CHECK: tbh [pc, r0, lsl #1]

0 commit comments

Comments
 (0)