diff options
author | Oliver Stannard <oliver.stannard@arm.com> | 2014-11-05 12:06:39 +0000 |
---|---|---|
committer | Oliver Stannard <oliver.stannard@arm.com> | 2014-11-05 12:06:39 +0000 |
commit | 9e89d8cc5cd048b5ed2037f472f3d38ce2c8328f (patch) | |
tree | 885f70aaf959a2338916c3c23aee98c8bea4614d /llvm/lib/Target/ARM | |
parent | e20ce07a2fa6c447872da3f8230c08e46166d9e3 (diff) | |
download | bcm5719-llvm-9e89d8cc5cd048b5ed2037f472f3d38ce2c8328f.tar.gz bcm5719-llvm-9e89d8cc5cd048b5ed2037f472f3d38ce2c8328f.zip |
[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.
llvm-svn: 221341
Diffstat (limited to 'llvm/lib/Target/ARM')
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 6 |
2 files changed, 12 insertions, 1 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c642fdc24ca..682ab9374f5 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/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/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index b85b7eba794..1d1b8dad002 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/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]; |