mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 16:24:23 +00:00
[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:
@ -157,7 +157,10 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||||||
MipsAsmParser::OperandMatchResultTy
|
MipsAsmParser::OperandMatchResultTy
|
||||||
parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
|
parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
|
||||||
|
|
||||||
bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
|
||||||
|
|
||||||
|
bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
unsigned RegKind);
|
unsigned RegKind);
|
||||||
|
|
||||||
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
|
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
|
||||||
@ -299,7 +302,8 @@ private:
|
|||||||
k_PostIndexRegister,
|
k_PostIndexRegister,
|
||||||
k_Register,
|
k_Register,
|
||||||
k_PtrReg,
|
k_PtrReg,
|
||||||
k_Token
|
k_Token,
|
||||||
|
k_LSAImm
|
||||||
} Kind;
|
} Kind;
|
||||||
|
|
||||||
MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
|
MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
|
||||||
@ -374,6 +378,7 @@ public:
|
|||||||
bool isMem() const { return Kind == k_Memory; }
|
bool isMem() const { return Kind == k_Memory; }
|
||||||
bool isPtrReg() const { return Kind == k_PtrReg; }
|
bool isPtrReg() const { return Kind == k_PtrReg; }
|
||||||
bool isInvNum() const { return Kind == k_Immediate; }
|
bool isInvNum() const { return Kind == k_Immediate; }
|
||||||
|
bool isLSAImm() const { return Kind == k_LSAImm; }
|
||||||
|
|
||||||
StringRef getToken() const {
|
StringRef getToken() const {
|
||||||
assert(Kind == k_Token && "Invalid access!");
|
assert(Kind == k_Token && "Invalid access!");
|
||||||
@ -396,7 +401,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MCExpr *getImm() const {
|
const MCExpr *getImm() const {
|
||||||
assert((Kind == k_Immediate) && "Invalid access!");
|
assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!");
|
||||||
return Imm.Val;
|
return Imm.Val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,8 +448,16 @@ public:
|
|||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
|
static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) {
|
||||||
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);
|
MipsOperand *Op = new MipsOperand(k_Memory);
|
||||||
Op->Mem.Base = Base;
|
Op->Mem.Base = Base;
|
||||||
Op->Mem.Off = Off;
|
Op->Mem.Off = Off;
|
||||||
@ -2058,6 +2071,45 @@ MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
|
|||||||
return MatchOperand_Success;
|
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 MipsAsmParser::getVariantKind(StringRef Symbol) {
|
||||||
|
|
||||||
MCSymbolRefExpr::VariantKind VK =
|
MCSymbolRefExpr::VariantKind VK =
|
||||||
|
@ -246,6 +246,13 @@ static DecodeStatus DecodeSimm16(MCInst &Inst,
|
|||||||
uint64_t Address,
|
uint64_t Address,
|
||||||
const void *Decoder);
|
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,
|
static DecodeStatus DecodeInsSize(MCInst &Inst,
|
||||||
unsigned Insn,
|
unsigned Insn,
|
||||||
uint64_t Address,
|
uint64_t Address,
|
||||||
@ -785,6 +792,15 @@ static DecodeStatus DecodeSimm16(MCInst &Inst,
|
|||||||
return MCDisassembler::Success;
|
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,
|
static DecodeStatus DecodeInsSize(MCInst &Inst,
|
||||||
unsigned Insn,
|
unsigned Insn,
|
||||||
uint64_t Address,
|
uint64_t Address,
|
||||||
|
@ -116,6 +116,10 @@ public:
|
|||||||
unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
|
unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
|
// getLSAImmEncoding - Return binary encoding of LSA immediate.
|
||||||
|
unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const;
|
getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
@ -521,5 +525,13 @@ MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
|
|||||||
return Position + Size - 1;
|
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"
|
#include "MipsGenMCCodeEmitter.inc"
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ private:
|
|||||||
unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const;
|
unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const;
|
||||||
unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||||
unsigned getSizeInsEncoding(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,
|
void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc,
|
||||||
int Offset) const;
|
int Offset) const;
|
||||||
@ -236,6 +237,12 @@ unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI,
|
|||||||
getMachineOpValue(MI, MI.getOperand(OpNo)) - 1;
|
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
|
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||||
/// operand requires relocation, record the relocation and return zero.
|
/// operand requires relocation, record the relocation and return zero.
|
||||||
unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI,
|
unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI,
|
||||||
|
@ -65,6 +65,21 @@ def uimm2 : Operand<i32> {
|
|||||||
let PrintMethod = "printUnsignedImm";
|
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> {
|
def uimm3 : Operand<i32> {
|
||||||
let PrintMethod = "printUnsignedImm8";
|
let PrintMethod = "printUnsignedImm8";
|
||||||
}
|
}
|
||||||
@ -2283,7 +2298,7 @@ class LDI_D_DESC : MSA_I10_LDI_DESC_BASE<"ldi.d", MSA128DOpnd>;
|
|||||||
|
|
||||||
class LSA_DESC {
|
class LSA_DESC {
|
||||||
dag OutOperandList = (outs GPR32Opnd:$rd);
|
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";
|
string AsmString = "lsa\t$rd, $rs, $rt, $sa";
|
||||||
list<dag> Pattern = [(set GPR32Opnd:$rd, (add GPR32Opnd:$rs,
|
list<dag> Pattern = [(set GPR32Opnd:$rd, (add GPR32Opnd:$rs,
|
||||||
(shl GPR32Opnd:$rt,
|
(shl GPR32Opnd:$rt,
|
||||||
|
@ -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
|
# 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, 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, 2
|
||||||
|
lsa $8, $9, $10, 3
|
||||||
|
lsa $8, $9, $10, 4
|
||||||
|
Reference in New Issue
Block a user