[mips][microMIPS] Implement SWP and LWP instructions

Differential Revision: http://reviews.llvm.org/D5667


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224338 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zoran Jovanovic 2014-12-16 14:59:10 +00:00
parent 51c2bdca72
commit 78f6aad800
10 changed files with 119 additions and 1 deletions

View File

@ -146,6 +146,9 @@ class MipsAsmParser : public MCTargetAsmParser {
MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands); MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy
parseRegisterPair (OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy MipsAsmParser::OperandMatchResultTy
parseRegisterList (OperandVector &Operands); parseRegisterList (OperandVector &Operands);
@ -428,7 +431,8 @@ private:
k_PhysRegister, /// A physical register from the Mips namespace k_PhysRegister, /// A physical register from the Mips namespace
k_RegisterIndex, /// A register index in one or more RegKind. k_RegisterIndex, /// A register index in one or more RegKind.
k_Token, /// A simple token k_Token, /// A simple token
k_RegList /// A physical register list k_RegList, /// A physical register list
k_RegPair /// A pair of physical register
} Kind; } Kind;
public: public:
@ -781,6 +785,13 @@ public:
Inst.addOperand(MCOperand::CreateReg(RegNo)); Inst.addOperand(MCOperand::CreateReg(RegNo));
} }
void addRegPairOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
unsigned RegNo = getRegPair();
Inst.addOperand(MCOperand::CreateReg(RegNo++));
Inst.addOperand(MCOperand::CreateReg(RegNo));
}
bool isReg() const override { bool isReg() const override {
// As a special case until we sort out the definition of div/divu, pretend // As a special case until we sort out the definition of div/divu, pretend
// that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
@ -845,6 +856,7 @@ public:
assert(Kind == k_Token && "Invalid access!"); assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length); return StringRef(Tok.Data, Tok.Length);
} }
bool isRegPair() const { return Kind == k_RegPair; }
unsigned getReg() const override { unsigned getReg() const override {
// As a special case until we sort out the definition of div/divu, pretend // As a special case until we sort out the definition of div/divu, pretend
@ -886,6 +898,11 @@ public:
return *(RegList.List); return *(RegList.List);
} }
unsigned getRegPair() const {
assert((Kind == k_RegPair) && "Invalid access!");
return RegIdx.Index;
}
static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
MipsAsmParser &Parser) { MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_Token, Parser); auto Op = make_unique<MipsOperand>(k_Token, Parser);
@ -995,6 +1012,15 @@ public:
return Op; return Op;
} }
static std::unique_ptr<MipsOperand>
CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Op->RegIdx.Index = RegNo;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
bool isGPRAsmReg() const { bool isGPRAsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
} }
@ -1061,6 +1087,7 @@ public:
case k_PhysRegister: case k_PhysRegister:
case k_RegisterIndex: case k_RegisterIndex:
case k_Token: case k_Token:
case k_RegPair:
break; break;
} }
} }
@ -1094,6 +1121,9 @@ public:
OS << Reg << " "; OS << Reg << " ";
OS << ">"; OS << ">";
break; break;
case k_RegPair:
OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
break;
} }
} }
}; // class MipsOperand }; // class MipsOperand
@ -2723,6 +2753,22 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) {
return MatchOperand_Success; return MatchOperand_Success;
} }
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
SMLoc S = Parser.getTok().getLoc();
if (parseAnyRegister(Operands) != MatchOperand_Success)
return MatchOperand_ParseFail;
SMLoc E = Parser.getTok().getLoc();
MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
unsigned Reg = Op.getGPR32Reg();
Operands.pop_back();
Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
return MatchOperand_Success;
}
MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
MCSymbolRefExpr::VariantKind VK = MCSymbolRefExpr::VariantKind VK =

View File

@ -1222,6 +1222,9 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
// fallthrough // fallthrough
default: default:
Inst.addOperand(MCOperand::CreateReg(Reg)); Inst.addOperand(MCOperand::CreateReg(Reg));
if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM)
Inst.addOperand(MCOperand::CreateReg(Reg+1));
Inst.addOperand(MCOperand::CreateReg(Base)); Inst.addOperand(MCOperand::CreateReg(Base));
Inst.addOperand(MCOperand::CreateImm(Offset)); Inst.addOperand(MCOperand::CreateImm(Offset));
} }

View File

@ -261,6 +261,11 @@ printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
O << MipsFCCToString((Mips::CondCode)MO.getImm()); O << MipsFCCToString((Mips::CondCode)MO.getImm());
} }
void MipsInstPrinter::
printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O) {
printRegName(O, MI->getOperand(opNum).getReg());
}
void MipsInstPrinter:: void MipsInstPrinter::
printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) { printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) {
llvm_unreachable("TODO"); llvm_unreachable("TODO");

View File

@ -99,6 +99,7 @@ private:
void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O);
void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O);
void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O);
void printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O);
void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O); void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O);
bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo,

View File

@ -862,4 +862,11 @@ MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
return (MI.getNumOperands() - 4); return (MI.getNumOperands() - 4);
} }
unsigned
MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
}
#include "MipsGenMCCodeEmitter.inc" #include "MipsGenMCCodeEmitter.inc"

View File

@ -184,6 +184,10 @@ public:
SmallVectorImpl<MCFixup> &Fixups, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const; const MCSubtargetInfo &STI) const;
unsigned getRegisterPairOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const; const MCSubtargetInfo &STI) const;

View File

@ -148,6 +148,36 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
let DecoderMethod = "DecodeMemMMImm12"; let DecoderMethod = "DecodeMemMMImm12";
} }
/// A register pair used by load/store pair instructions.
def RegPairAsmOperand : AsmOperandClass {
let Name = "RegPair";
let ParserMethod = "parseRegisterPair";
}
def regpair : Operand<i32> {
let EncoderMethod = "getRegisterPairOpValue";
let ParserMatchClass = RegPairAsmOperand;
let PrintMethod = "printRegisterPair";
let DecoderMethod = "DecodeRegPairOperand";
let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd);
}
class StorePairMM<string opstr, InstrItinClass Itin = NoItinerary,
ComplexPattern Addr = addr> :
InstSE<(outs), (ins regpair:$rt, mem_mm_12:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMemMMImm12";
let mayStore = 1;
}
class LoadPairMM<string opstr, InstrItinClass Itin = NoItinerary,
ComplexPattern Addr = addr> :
InstSE<(outs regpair:$rt), (ins mem_mm_12:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMemMMImm12";
let mayLoad = 1;
}
class LLBaseMM<string opstr, RegisterOperand RO> : class LLBaseMM<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$rt), (ins mem_mm_12:$addr), InstSE<(outs RO:$rt), (ins mem_mm_12:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
@ -555,6 +585,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>; def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>;
def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>; def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>;
/// Load and Store Pair Instructions
def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>;
def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>;
/// Move Conditional /// Move Conditional
def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd,
NoItinerary>, ADD_FM_MM<0, 0x58>; NoItinerary>, ADD_FM_MM<0, 0x58>;

View File

@ -343,6 +343,12 @@
# CHECK: swm32 $16, $17, 8($4) # CHECK: swm32 $16, $17, 8($4)
0x20 0x44 0xd0 0x08 0x20 0x44 0xd0 0x08
# CHECK: swp $16, 8($4)
0x22 0x04 0x90 0x08
# CHECK: lwp $16, 8($4)
0x22 0x04 0x10 0x08
# CHECK: nop # CHECK: nop
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

View File

@ -343,6 +343,12 @@
# CHECK: swm32 $16, $17, 8($4) # CHECK: swm32 $16, $17, 8($4)
0x44 0x20 0x08 0xd0 0x44 0x20 0x08 0xd0
# CHECK: swp $16, 8($4)
0x04 0x22 0x08 0x90
# CHECK: lwp $16, 8($4)
0x04 0x22 0x08 0x10
# CHECK: nop # CHECK: nop
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

View File

@ -31,6 +31,8 @@
# CHECK-EL: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x84,0x20,0x08,0xd0] # CHECK-EL: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x84,0x20,0x08,0xd0]
# CHECK-EL: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x12,0x45] # CHECK-EL: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x12,0x45]
# CHECK-EL: swm16 $16, $17, $ra, 8($sp) # encoding: [0x52,0x45] # CHECK-EL: swm16 $16, $17, $ra, 8($sp) # encoding: [0x52,0x45]
# CHECK-EL: swp $16, 8($4) # encoding: [0x04,0x22,0x08,0x90]
# CHECK-EL: lwp $16, 8($4) # encoding: [0x04,0x22,0x08,0x10]
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# Big endian # Big endian
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
@ -56,6 +58,8 @@
# CHECK-EB: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x20,0x84,0xd0,0x08] # CHECK-EB: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x20,0x84,0xd0,0x08]
# CHECK-EB: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x12] # CHECK-EB: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x12]
# CHECK-EB: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x52] # CHECK-EB: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x52]
# CHECK-EB: swp $16, 8($4) # encoding: [0x22,0x04,0x90,0x08]
# CHECK-EB: lwp $16, 8($4) # encoding: [0x22,0x04,0x10,0x08]
lb $5, 8($4) lb $5, 8($4)
lbu $6, 8($4) lbu $6, 8($4)
lh $2, 8($4) lh $2, 8($4)
@ -78,3 +82,5 @@
swm32 $16 - $19, 8($4) swm32 $16 - $19, 8($4)
lwm16 $16, $17, $ra, 8($sp) lwm16 $16, $17, $ra, 8($sp)
swm16 $16, $17, $ra, 8($sp) swm16 $16, $17, $ra, 8($sp)
swp $16, 8($4)
lwp $16, 8($4)