From: Matheus Almeida Date: Mon, 18 Nov 2013 12:32:49 +0000 (+0000) Subject: [mips][msa] Fix immediate value of LSA instruction as it was being wrongly encoded. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=95adf91f29980e374bf094e15bc3f2764ef9baf4;p=oota-llvm.git [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 --- diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 89e2b3b0227..cdae6c2f37e 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 &Operands); - bool searchSymbolAlias(SmallVectorImpl &Operands, + MipsAsmParser::OperandMatchResultTy + parseLSAImm(SmallVectorImpl &Operands); + + bool searchSymbolAlias(SmallVectorImpl &Operands, unsigned RegKind); bool ParseOperand(SmallVectorImpl &, @@ -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 &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseLSAImm(SmallVectorImpl &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 b890d3a887c..60508a8c4fc 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 79818ec0bfb..66428bdfa74 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 &Fixups) const; + // getLSAImmEncoding - Return binary encoding of LSA immediate. + unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; + unsigned getExprOpValue(const MCExpr *Expr,SmallVectorImpl &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 &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 f4e1e1848ee..ca4163d4e58 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 f3c1e955b2b..c309fa4b4f7 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -65,6 +65,21 @@ def uimm2 : Operand { 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 { + let PrintMethod = "printUnsignedImm"; + let EncoderMethod = "getLSAImmEncoding"; + let DecoderMethod = "DecodeLSAImm"; + let ParserMatchClass = uimm2LSAAsmOperand; +} + def uimm3 : Operand { 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 Pattern = [(set GPR32Opnd:$rd, (add GPR32Opnd:$rs, (shl GPR32Opnd:$rt, diff --git a/test/MC/Mips/msa/test_lsa.s b/test/MC/Mips/msa/test_lsa.s index 6798ed38906..6d1d868fc86 100644 --- a/test/MC/Mips/msa/test_lsa.s +++ b/test/MC/Mips/msa/test_lsa.s @@ -2,8 +2,17 @@ # # RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa -arch=mips -filetype=obj -o - | llvm-objdump -d -triple=mipsel-unknown-linux -mattr=+msa -arch=mips - | FileCheck %s -check-prefix=CHECKOBJDUMP # -# CHECK: lsa $8, $9, $10, 2 # encoding: [0x01,0x2a,0x40,0x85] +# CHECK: lsa $8, $9, $10, 1 # encoding: [0x01,0x2a,0x40,0x05] +# CHECK: lsa $8, $9, $10, 2 # encoding: [0x01,0x2a,0x40,0x45] +# CHECK: lsa $8, $9, $10, 3 # encoding: [0x01,0x2a,0x40,0x85] +# CHECK: lsa $8, $9, $10, 4 # encoding: [0x01,0x2a,0x40,0xc5] +# CHECKOBJDUMP: lsa $8, $9, $10, 1 # CHECKOBJDUMP: lsa $8, $9, $10, 2 +# CHECKOBJDUMP: lsa $8, $9, $10, 3 +# CHECKOBJDUMP: lsa $8, $9, $10, 4 + lsa $8, $9, $10, 1 lsa $8, $9, $10, 2 + lsa $8, $9, $10, 3 + lsa $8, $9, $10, 4