diff options
author | Matheus Almeida <matheus.almeida@imgtec.com> | 2013-11-18 12:32:49 +0000 |
---|---|---|
committer | Matheus Almeida <matheus.almeida@imgtec.com> | 2013-11-18 12:32:49 +0000 |
commit | 95adf91f29980e374bf094e15bc3f2764ef9baf4 (patch) | |
tree | 96d3e0751088d9406351c72e4d6eff646098f0e2 /lib | |
parent | f56f1dfecc04078dd76121cf06dae4024372f329 (diff) | |
download | external_llvm-95adf91f29980e374bf094e15bc3f2764ef9baf4.zip external_llvm-95adf91f29980e374bf094e15bc3f2764ef9baf4.tar.gz external_llvm-95adf91f29980e374bf094e15bc3f2764ef9baf4.tar.bz2 |
[mips][msa] Fix immediate value of LSA instruction as it was being wrongly encoded.
The immediate field should be encoded as "imm - 1" as the CPU always adds one to that field.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195004 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 62 | ||||
-rw-r--r-- | lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 16 | ||||
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 12 | ||||
-rw-r--r-- | lib/Target/Mips/MipsCodeEmitter.cpp | 7 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMSAInstrInfo.td | 17 |
5 files changed, 108 insertions, 6 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 89e2b3b..cdae6c2 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -157,7 +157,10 @@ class MipsAsmParser : public MCTargetAsmParser { MipsAsmParser::OperandMatchResultTy parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands); - bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands, + MipsAsmParser::OperandMatchResultTy + parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands); + + bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind); bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &, @@ -299,7 +302,8 @@ private: k_PostIndexRegister, k_Register, k_PtrReg, - k_Token + k_Token, + k_LSAImm } Kind; MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} @@ -374,6 +378,7 @@ public: bool isMem() const { return Kind == k_Memory; } bool isPtrReg() const { return Kind == k_PtrReg; } bool isInvNum() const { return Kind == k_Immediate; } + bool isLSAImm() const { return Kind == k_LSAImm; } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -396,7 +401,7 @@ public: } const MCExpr *getImm() const { - assert((Kind == k_Immediate) && "Invalid access!"); + assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!"); return Imm.Val; } @@ -443,8 +448,16 @@ public: return Op; } - static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S, - SMLoc E) { + static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MipsOperand *Op = new MipsOperand(k_LSAImm); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, + SMLoc S, SMLoc E) { MipsOperand *Op = new MipsOperand(k_Memory); Op->Mem.Base = Base; Op->Mem.Off = Off; @@ -2058,6 +2071,45 @@ MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) { + switch (getLexer().getKind()) { + default: + return MatchOperand_NoMatch; + case AsmToken::LParen: + case AsmToken::Plus: + case AsmToken::Minus: + case AsmToken::Integer: + break; + } + + const MCExpr *Expr; + SMLoc S = Parser.getTok().getLoc(); + + if (getParser().parseExpression(Expr)) + return MatchOperand_ParseFail; + + int64_t Val; + if (!Expr->EvaluateAsAbsolute(Val)) { + Error(S, "expected immediate value"); + return MatchOperand_ParseFail; + } + + // The LSA instruction allows a 2-bit unsigned immediate. For this reason + // and because the CPU always adds one to the immediate field, the allowed + // range becomes 1..4. We'll only check the range here and will deal + // with the addition/subtraction when actually decoding/encoding + // the instruction. + if (Val < 1 || Val > 4) { + Error(S, "immediate not in range (1..4)"); + return MatchOperand_ParseFail; + } + + Operands.push_back(MipsOperand::CreateLSAImm(Expr, S, + Parser.getTok().getLoc())); + return MatchOperand_Success; +} + MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind VK = diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index b890d3a..60508a8 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -246,6 +246,13 @@ static DecodeStatus DecodeSimm16(MCInst &Inst, uint64_t Address, const void *Decoder); +// Decode the immediate field of an LSA instruction which +// is off by one. +static DecodeStatus DecodeLSAImm(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeInsSize(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -785,6 +792,15 @@ static DecodeStatus DecodeSimm16(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeLSAImm(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + // We add one to the immediate field as it was encoded as 'imm - 1'. + Inst.addOperand(MCOperand::CreateImm(Insn + 1)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeInsSize(MCInst &Inst, unsigned Insn, uint64_t Address, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 79818ec..66428bd 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -116,6 +116,10 @@ public: unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; + // getLSAImmEncoding - Return binary encoding of LSA immediate. + unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const; @@ -521,5 +525,13 @@ MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, return Position + Size - 1; } +unsigned +MipsMCCodeEmitter::getLSAImmEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + assert(MI.getOperand(OpNo).isImm()); + // The immediate is encoded as 'immediate - 1'. + return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups) - 1; +} + #include "MipsGenMCCodeEmitter.inc" diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index f4e1e18..ca4163d 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -114,6 +114,7 @@ private: unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getLSAImmEncoding(const MachineInstr &MI, unsigned OpNo) const; void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc, int Offset) const; @@ -236,6 +237,12 @@ unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; } +unsigned MipsCodeEmitter::getLSAImmEncoding(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("Unimplemented function."); + return 0; +} + /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index f3c1e95..c309fa4 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -65,6 +65,21 @@ def uimm2 : Operand<i32> { let PrintMethod = "printUnsignedImm"; } +// The immediate of an LSA instruction needs special handling +// as the encoded value should be subtracted by one. +def uimm2LSAAsmOperand : AsmOperandClass { + let Name = "LSAImm"; + let ParserMethod = "parseLSAImm"; + let RenderMethod = "addImmOperands"; +} + +def LSAImm : Operand<i32> { + let PrintMethod = "printUnsignedImm"; + let EncoderMethod = "getLSAImmEncoding"; + let DecoderMethod = "DecodeLSAImm"; + let ParserMatchClass = uimm2LSAAsmOperand; +} + def uimm3 : Operand<i32> { let PrintMethod = "printUnsignedImm8"; } @@ -2283,7 +2298,7 @@ class LDI_D_DESC : MSA_I10_LDI_DESC_BASE<"ldi.d", MSA128DOpnd>; class LSA_DESC { dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins GPR32Opnd:$rs, GPR32Opnd:$rt, uimm2:$sa); + dag InOperandList = (ins GPR32Opnd:$rs, GPR32Opnd:$rt, LSAImm:$sa); string AsmString = "lsa\t$rd, $rs, $rt, $sa"; list<dag> Pattern = [(set GPR32Opnd:$rd, (add GPR32Opnd:$rs, (shl GPR32Opnd:$rt, |