From 382f7d717cc02b3339bf0ce5a625a19d007fcd91 Mon Sep 17 00:00:00 2001 From: Oliver Stannard Date: Wed, 5 Nov 2014 12:06:39 +0000 Subject: [PATCH] [ARM] Honor FeatureD16 in the assembler and disassembler Some ARM FPUs only have 16 double-precision registers, rather than the normal 32. LLVM represents this with the D16 target feature. This is currently used by CodeGen to avoid using high registers when they are not available, but the assembler and disassembler do not. I fix this in the assmebler and disassembler rather than the InstrInfo.td files, as the latter would require a large number of changes everywhere one of the floating-point instructions is referenced in the backend. This solution is similar to the one used for co-processor numbers and MSR masks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221341 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 7 ++++++ .../ARM/Disassembler/ARMDisassembler.cpp | 6 ++++- test/MC/ARM/d16.s | 24 +++++++++++++++++++ test/MC/ARM/directive-fpu-instrs.s | 2 +- test/MC/ARM/vfp4.s | 12 +++++----- test/MC/Disassembler/ARM/d16.txt | 23 ++++++++++++++++++ 6 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 test/MC/ARM/d16.s create mode 100644 test/MC/Disassembler/ARM/d16.txt diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c642fdc24ca..682ab9374f5 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -270,6 +270,9 @@ class ARMAsmParser : public MCTargetAsmParser { bool hasThumb2DSP() const { return STI.getFeatureBits() & ARM::FeatureDSPThumb2; } + bool hasD16() const { + return STI.getFeatureBits() & ARM::FeatureD16; + } void SwitchMode() { uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); @@ -2988,6 +2991,10 @@ int ARMAsmParser::tryParseRegister() { return Entry->getValue(); } + // Some FPUs only have 16 D registers, so D16-D31 are invalid + if (hasD16() && RegNum >= ARM::D16 && RegNum <= ARM::D31) + return -1; + Parser.Lex(); // Eat identifier token. return RegNum; diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index b85b7eba794..1d1b8dad002 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -1017,7 +1017,11 @@ static const uint16_t DPRDecoderTable[] = { static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - if (RegNo > 31) + uint64_t featureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo() + .getFeatureBits(); + bool hasD16 = featureBits & ARM::FeatureD16; + + if (RegNo > 31 || (hasD16 && RegNo > 15)) return MCDisassembler::Fail; unsigned Register = DPRDecoderTable[RegNo]; diff --git a/test/MC/ARM/d16.s b/test/MC/ARM/d16.s new file mode 100644 index 00000000000..40abbfb4793 --- /dev/null +++ b/test/MC/ARM/d16.s @@ -0,0 +1,24 @@ +@ RUN: llvm-mc < %s -triple thumbv7-unknown-unknown -show-encoding -mattr=+vfp4,-d16 |& FileCheck %s --check-prefix=D32 +@ RUN: not llvm-mc < %s -triple thumbv7-unknown-unknown -show-encoding -mattr=+vfp4,+d16 |& FileCheck %s --check-prefix=D16 + +@ D32-NOT: error: + +@ D16: invalid operand for instruction +@ D16-NEXT: vadd.f64 d1, d2, d16 +vadd.f64 d1, d2, d16 + +@ D16: invalid operand for instruction +@ D16-NEXT: vadd.f64 d1, d17, d6 +vadd.f64 d1, d17, d6 + +@ D16: invalid operand for instruction +@ D16-NEXT: vadd.f64 d19, d7, d6 +vadd.f64 d19, d7, d6 + +@ D16: invalid operand for instruction +@ D16-NEXT: vcvt.f64.f32 d22, s4 +vcvt.f64.f32 d22, s4 + +@ D16: invalid operand for instruction +@ D16-NEXT: vcvt.f32.f64 s26, d30 +vcvt.f32.f64 s26, d30 diff --git a/test/MC/ARM/directive-fpu-instrs.s b/test/MC/ARM/directive-fpu-instrs.s index 0b1e8cc3528..ec97a77aef6 100644 --- a/test/MC/ARM/directive-fpu-instrs.s +++ b/test/MC/ARM/directive-fpu-instrs.s @@ -1,4 +1,4 @@ -// RUN: llvm-mc -triple armv7-unknown-linux-gnueabi -mattr=+vfp3,+d16,-neon %s +// RUN: llvm-mc -triple armv7-unknown-linux-gnueabi -mattr=+vfp3,-neon %s .fpu neon VAND d3, d5, d5 diff --git a/test/MC/ARM/vfp4.s b/test/MC/ARM/vfp4.s index 8b1b0e0c538..1563b5aef71 100644 --- a/test/MC/ARM/vfp4.s +++ b/test/MC/ARM/vfp4.s @@ -6,7 +6,7 @@ @ ARM: vfma.f64 d16, d18, d17 @ encoding: [0xa1,0x0b,0xe2,0xee] @ THUMB: vfma.f64 d16, d18, d17 @ encoding: [0xe2,0xee,0xa1,0x0b] -@ THUMB_V7EM-ERRORS: error: instruction requires: double precision VFP +@ THUMB_V7EM-ERRORS: error: invalid operand for instruction @ THUMB_V7EM-ERRORS-NEXT: vfma.f64 d16, d18, d17 vfma.f64 d16, d18, d17 @@ -17,7 +17,7 @@ vfma.f32 s2, s4, s0 @ ARM: vfma.f32 d16, d18, d17 @ encoding: [0xb1,0x0c,0x42,0xf2] @ THUMB: vfma.f32 d16, d18, d17 @ encoding: [0x42,0xef,0xb1,0x0c] -@ THUMB_V7EM-ERRORS: error: instruction requires: NEON +@ THUMB_V7EM-ERRORS: error: invalid operand for instruction @ THUMB_V7EM-ERRORS-NEXT: vfma.f32 d16, d18, d17 vfma.f32 d16, d18, d17 @@ -29,7 +29,7 @@ vfma.f32 q2, q4, q0 @ ARM: vfnma.f64 d16, d18, d17 @ encoding: [0xe1,0x0b,0xd2,0xee] @ THUMB: vfnma.f64 d16, d18, d17 @ encoding: [0xd2,0xee,0xe1,0x0b] -@ THUMB_V7EM-ERRORS: error: instruction requires: double precision VFP +@ THUMB_V7EM-ERRORS: error: invalid operand for instruction @ THUMB_V7EM-ERRORS-NEXT: vfnma.f64 d16, d18, d17 vfnma.f64 d16, d18, d17 @@ -40,7 +40,7 @@ vfnma.f32 s2, s4, s0 @ ARM: vfms.f64 d16, d18, d17 @ encoding: [0xe1,0x0b,0xe2,0xee] @ THUMB: vfms.f64 d16, d18, d17 @ encoding: [0xe2,0xee,0xe1,0x0b] -@ THUMB_V7EM-ERRORS: error: instruction requires: double precision VFP +@ THUMB_V7EM-ERRORS: error: invalid operand for instruction @ THUMB_V7EM-ERRORS-NEXT: vfms.f64 d16, d18, d17 vfms.f64 d16, d18, d17 @@ -51,7 +51,7 @@ vfms.f32 s2, s4, s0 @ ARM: vfms.f32 d16, d18, d17 @ encoding: [0xb1,0x0c,0x62,0xf2] @ THUMB: vfms.f32 d16, d18, d17 @ encoding: [0x62,0xef,0xb1,0x0c] -@ THUMB_V7EM-ERRORS: error: instruction requires: NEON +@ THUMB_V7EM-ERRORS: error: invalid operand for instruction @ THUMB_V7EM-ERRORS-NEXT: vfms.f32 d16, d18, d17 vfms.f32 d16, d18, d17 @@ -63,7 +63,7 @@ vfms.f32 q2, q4, q0 @ ARM: vfnms.f64 d16, d18, d17 @ encoding: [0xa1,0x0b,0xd2,0xee] @ THUMB: vfnms.f64 d16, d18, d17 @ encoding: [0xd2,0xee,0xa1,0x0b] -@ THUMB_V7EM-ERRORS: error: instruction requires: double precision VFP +@ THUMB_V7EM-ERRORS: error: invalid operand for instruction @ THUMB_V7EM-ERRORS-NEXT: vfnms.f64 d16, d18, d17 vfnms.f64 d16, d18, d17 diff --git a/test/MC/Disassembler/ARM/d16.txt b/test/MC/Disassembler/ARM/d16.txt new file mode 100644 index 00000000000..42560e19b39 --- /dev/null +++ b/test/MC/Disassembler/ARM/d16.txt @@ -0,0 +1,23 @@ +# RUN: llvm-mc < %s -triple thumbv7-unknown-unknown -disassemble -mattr=+vfp4,-d16 |& FileCheck %s --check-prefix=D32 +# RUN: llvm-mc < %s -triple thumbv7-unknown-unknown -disassemble -mattr=+vfp4,-d16 |& FileCheck %s --check-prefix=D32 + + +# D32: vadd.f64 d1, d2, d16 +# D16: warning: invalid instruction encoding +[0x32,0xee,0x20,0x1b] + +# D32: vadd.f64 d1, d17, d6 +# D16: warning: invalid instruction encoding +[0x31,0xee,0x86,0x1b] + +# D32: vadd.f64 d19, d7, d6 +# D16: warning: invalid instruction encoding +[0x77,0xee,0x06,0x3b] + +# D32: vcvt.f64.f32 d22, s4 +# D16: warning: invalid instruction encoding +[0xf7,0xee,0xc2,0x6a] + +# D32: vcvt.f32.f64 s26, d30 +# D16: warning: invalid instruction encoding +[0xb7,0xee,0xee,0xdb] -- 2.34.1