[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
This commit is contained in:
Matheus Almeida 2013-11-18 12:32:49 +00:00
parent f56f1dfecc
commit 95adf91f29
6 changed files with 118 additions and 7 deletions

View File

@ -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 =

View File

@ -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,

View File

@ -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"

View File

@ -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,

View File

@ -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,

View File

@ -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