diff options
author | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2011-02-18 19:45:59 +0000 |
---|---|---|
committer | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2011-02-18 19:45:59 +0000 |
commit | 584bf7bb03e4cf1475b26851edcc1ddb66b85028 (patch) | |
tree | 8f7aa705e98d2655f8a322fb778e62bf2744d300 /lib/Target/ARM/AsmParser/ARMAsmParser.cpp | |
parent | 6309b3e9bed13e34cf8803509b7f6b642731353a (diff) |
Add assembly parsing support for "msr" and also fix its encoding. Also add
testcases for the disassembler to make sure it still works for "msr".
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125948 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index e9a507088a..7cd0394fdf 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -100,6 +100,8 @@ class ARMAsmParser : public TargetAsmParser { SmallVectorImpl<MCParsedAsmOperand*> &); OperandMatchResultTy tryParseProcIFlagsOperand( SmallVectorImpl<MCParsedAsmOperand*> &); + OperandMatchResultTy tryParseMSRMaskOperand( + SmallVectorImpl<MCParsedAsmOperand*> &); public: ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) @@ -128,6 +130,7 @@ class ARMOperand : public MCParsedAsmOperand { Immediate, MemBarrierOpt, Memory, + MSRMask, ProcIFlags, Register, RegisterList, @@ -157,6 +160,10 @@ class ARMOperand : public MCParsedAsmOperand { } IFlags; struct { + unsigned Val; + } MMask; + + struct { const char *Data; unsigned Length; } Tok; @@ -222,6 +229,9 @@ public: case Memory: Mem = o.Mem; break; + case MSRMask: + MMask = o.MMask; + break; case ProcIFlags: IFlags = o.IFlags; } @@ -273,6 +283,11 @@ public: return IFlags.Val; } + unsigned getMSRMask() const { + assert(Kind == MSRMask && "Invalid access!"); + return MMask.Val; + } + /// @name Memory Operand Accessors /// @{ @@ -347,6 +362,7 @@ public: uint64_t Value = CE->getValue(); return ((Value & 0x3) == 0 && Value <= 124); } + bool isMSRMask() const { return Kind == MSRMask; } bool isProcIFlags() const { return Kind == ProcIFlags; } void addExpr(MCInst &Inst, const MCExpr *Expr) const { @@ -448,6 +464,11 @@ public: Inst.addOperand(MCOperand::CreateImm(CE->getValue())); } + void addMSRMaskOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask()))); + } + void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); @@ -584,6 +605,14 @@ public: Op->EndLoc = S; return Op; } + + static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) { + ARMOperand *Op = new ARMOperand(MSRMask); + Op->MMask.Val = MMask; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } }; } // end anonymous namespace. @@ -602,6 +631,9 @@ void ARMOperand::dump(raw_ostream &OS) const { case CoprocReg: OS << "<coprocessor register: " << getCoproc() << ">"; break; + case MSRMask: + OS << "<mask: " << getMSRMask() << ">"; + break; case Immediate: getImm()->print(OS); break; @@ -950,6 +982,69 @@ tryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +/// tryParseMSRMaskOperand - Try to parse mask flags from MSR instruction. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + StringRef Mask = Tok.getString(); + + // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" + size_t Start = 0, Next = Mask.find('_'); + StringRef Flags = ""; + StringRef SpecReg = Mask.slice(Start, Next); + if (Next != StringRef::npos) + Flags = Mask.slice(Next+1, Mask.size()); + + // FlagsVal contains the complete mask: + // 3-0: Mask + // 4: Special Reg (cpsr, apsr => 0; spsr => 1) + unsigned FlagsVal = 0; + + if (SpecReg == "apsr") { + FlagsVal = StringSwitch<unsigned>(Flags) + .Case("nzcvq", 0x8) // same as CPSR_c + .Case("g", 0x4) // same as CPSR_s + .Case("nzcvqg", 0xc) // same as CPSR_fs + .Default(~0U); + + if (FlagsVal == ~0U) + if (!Flags.empty()) + return MatchOperand_NoMatch; + else + FlagsVal = 0; // No flag + } else if (SpecReg == "cpsr" || SpecReg == "spsr") { + for (int i = 0, e = Flags.size(); i != e; ++i) { + unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1)) + .Case("c", 1) + .Case("x", 2) + .Case("s", 4) + .Case("f", 8) + .Default(~0U); + + // If some specific flag is already set, it means that some letter is + // present more than once, this is not acceptable. + if (FlagsVal == ~0U || (FlagsVal & Flag)) + return MatchOperand_NoMatch; + FlagsVal |= Flag; + } + } else // No match for special register. + return MatchOperand_NoMatch; + + // Special register without flags are equivalent to "fc" flags. + if (!FlagsVal) + FlagsVal = 0x9; + + // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1) + if (SpecReg == "spsr") + FlagsVal |= 16; + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); + return MatchOperand_Success; +} + /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. /// |