mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-22 10:29:35 +00:00
[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:
parent
51c2bdca72
commit
78f6aad800
@ -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 =
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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,
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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>;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user