[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
parseRegisterPair (OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy
parseRegisterList (OperandVector &Operands);
@ -428,7 +431,8 @@ private:
k_PhysRegister, /// A physical register from the Mips namespace
k_RegisterIndex, /// A register index in one or more RegKind.
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;
public:
@ -781,6 +785,13 @@ public:
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 {
// 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.
@ -845,6 +856,7 @@ public:
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
bool isRegPair() const { return Kind == k_RegPair; }
unsigned getReg() const override {
// As a special case until we sort out the definition of div/divu, pretend
@ -886,6 +898,11 @@ public:
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,
MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_Token, Parser);
@ -995,6 +1012,15 @@ public:
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 {
return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
}
@ -1061,6 +1087,7 @@ public:
case k_PhysRegister:
case k_RegisterIndex:
case k_Token:
case k_RegPair:
break;
}
}
@ -1094,6 +1121,9 @@ public:
OS << Reg << " ";
OS << ">";
break;
case k_RegPair:
OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
break;
}
}
}; // class MipsOperand
@ -2723,6 +2753,22 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) {
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 VK =

View File

@ -1222,6 +1222,9 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
// fallthrough
default:
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::CreateImm(Offset));
}

View File

@ -261,6 +261,11 @@ printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) {
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::
printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) {
llvm_unreachable("TODO");

View File

@ -99,6 +99,7 @@ private:
void printMemOperand(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 printRegisterPair(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,

View File

@ -862,4 +862,11 @@ MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
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"

View File

@ -184,6 +184,10 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
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,
const MCSubtargetInfo &STI) const;

View File

@ -148,6 +148,36 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
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> :
InstSE<(outs RO:$rt), (ins mem_mm_12:$addr),
!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 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
def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd,
NoItinerary>, ADD_FM_MM<0, 0x58>;

View File

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

View File

@ -343,6 +343,12 @@
# CHECK: swm32 $16, $17, 8($4)
0x44 0x20 0x08 0xd0
# CHECK: swp $16, 8($4)
0x04 0x22 0x08 0x90
# CHECK: lwp $16, 8($4)
0x04 0x22 0x08 0x10
# CHECK: nop
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: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x12,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
#------------------------------------------------------------------------------
@ -56,6 +58,8 @@
# 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: 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)
lbu $6, 8($4)
lh $2, 8($4)
@ -78,3 +82,5 @@
swm32 $16 - $19, 8($4)
lwm16 $16, $17, $ra, 8($sp)
swm16 $16, $17, $ra, 8($sp)
swp $16, 8($4)
lwp $16, 8($4)