mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
This patch tackles the problem of parsing Mips
register names in the standalone assembler llvm-mc. Registers such as $A1 can represent either a 32 or 64 bit register based on the instruction using it. In addition, based on the abi, $T0 can represent different 32 bit registers. The problem is resolved by the Mips specific AsmParser td definitions changing to work together. Many cases of RegisterClass parameters are now RegisterOperand. Contributer: Vladimir Medic git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172284 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -84,15 +84,30 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||||||
bool ParseDirective(AsmToken DirectiveID);
|
bool ParseDirective(AsmToken DirectiveID);
|
||||||
|
|
||||||
MipsAsmParser::OperandMatchResultTy
|
MipsAsmParser::OperandMatchResultTy
|
||||||
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
|
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
|
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
|
||||||
StringRef Mnemonic);
|
StringRef Mnemonic);
|
||||||
|
|
||||||
int tryParseRegister(StringRef Mnemonic);
|
int tryParseRegister(bool is64BitReg);
|
||||||
|
|
||||||
bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
StringRef Mnemonic);
|
bool is64BitReg);
|
||||||
|
|
||||||
bool needsExpansion(MCInst &Inst);
|
bool needsExpansion(MCInst &Inst);
|
||||||
|
|
||||||
@@ -107,7 +122,7 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||||||
bool reportParseError(StringRef ErrorMsg);
|
bool reportParseError(StringRef ErrorMsg);
|
||||||
|
|
||||||
bool parseMemOffset(const MCExpr *&Res);
|
bool parseMemOffset(const MCExpr *&Res);
|
||||||
bool parseRelocOperand(const MCExpr *&Res, SMLoc &E);
|
bool parseRelocOperand(const MCExpr *&Res);
|
||||||
|
|
||||||
bool parseDirectiveSet();
|
bool parseDirectiveSet();
|
||||||
|
|
||||||
@@ -128,9 +143,9 @@ class MipsAsmParser : public MCTargetAsmParser {
|
|||||||
return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
|
return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int matchRegisterName(StringRef Symbol);
|
int matchRegisterName(StringRef Symbol, bool is64BitReg);
|
||||||
|
|
||||||
int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
|
int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
|
||||||
|
|
||||||
void setFpFormat(FpFormatTy Format) {
|
void setFpFormat(FpFormatTy Format) {
|
||||||
FpFormat = Format;
|
FpFormat = Format;
|
||||||
@@ -166,6 +181,20 @@ namespace {
|
|||||||
/// instruction.
|
/// instruction.
|
||||||
class MipsOperand : public MCParsedAsmOperand {
|
class MipsOperand : public MCParsedAsmOperand {
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum RegisterKind {
|
||||||
|
Kind_None,
|
||||||
|
Kind_CPURegs,
|
||||||
|
Kind_CPU64Regs,
|
||||||
|
Kind_HWRegs,
|
||||||
|
Kind_HW64Regs,
|
||||||
|
Kind_FGR32Regs,
|
||||||
|
Kind_FGR64Regs,
|
||||||
|
Kind_AFGR32Regs,
|
||||||
|
Kind_CCRRegs
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
enum KindTy {
|
enum KindTy {
|
||||||
k_CondCode,
|
k_CondCode,
|
||||||
k_CoprocNum,
|
k_CoprocNum,
|
||||||
@@ -186,6 +215,7 @@ class MipsOperand : public MCParsedAsmOperand {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned RegNum;
|
unsigned RegNum;
|
||||||
|
RegisterKind Kind;
|
||||||
} Reg;
|
} Reg;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -246,6 +276,11 @@ public:
|
|||||||
return Reg.RegNum;
|
return Reg.RegNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRegKind(RegisterKind RegKind) {
|
||||||
|
assert((Kind == k_Register) && "Invalid access!");
|
||||||
|
Reg.Kind = RegKind;
|
||||||
|
}
|
||||||
|
|
||||||
const MCExpr *getImm() const {
|
const MCExpr *getImm() const {
|
||||||
assert((Kind == k_Immediate) && "Invalid access!");
|
assert((Kind == k_Immediate) && "Invalid access!");
|
||||||
return Imm.Val;
|
return Imm.Val;
|
||||||
@@ -296,6 +331,45 @@ public:
|
|||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isCPURegsAsm() const {
|
||||||
|
return Reg.Kind == Kind_CPURegs;
|
||||||
|
}
|
||||||
|
void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCPU64RegsAsm() const {
|
||||||
|
return Reg.Kind == Kind_CPU64Regs;
|
||||||
|
}
|
||||||
|
void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHWRegsAsm() const {
|
||||||
|
assert((Kind == k_Register) && "Invalid access!");
|
||||||
|
return Reg.Kind == Kind_HWRegs;
|
||||||
|
}
|
||||||
|
void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHW64RegsAsm() const {
|
||||||
|
assert((Kind == k_Register) && "Invalid access!");
|
||||||
|
return Reg.Kind == Kind_HW64Regs;
|
||||||
|
}
|
||||||
|
void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCCRAsm() const {
|
||||||
|
assert((Kind == k_Register) && "Invalid access!");
|
||||||
|
return Reg.Kind == Kind_CCRRegs;
|
||||||
|
}
|
||||||
|
|
||||||
/// getStartLoc - Get the location of the first token of this operand.
|
/// getStartLoc - Get the location of the first token of this operand.
|
||||||
SMLoc getStartLoc() const { return StartLoc; }
|
SMLoc getStartLoc() const { return StartLoc; }
|
||||||
/// getEndLoc - Get the location of the last token of this operand.
|
/// getEndLoc - Get the location of the last token of this operand.
|
||||||
@@ -344,31 +418,31 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
|||||||
if ( 0 <= ImmValue && ImmValue <= 65535) {
|
if ( 0 <= ImmValue && ImmValue <= 65535) {
|
||||||
// for 0 <= j <= 65535.
|
// for 0 <= j <= 65535.
|
||||||
// li d,j => ori d,$zero,j
|
// li d,j => ori d,$zero,j
|
||||||
tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
|
tmpInst.setOpcode(Mips::ORi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(
|
tmpInst.addOperand(
|
||||||
MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
|
MCOperand::CreateReg(Mips::ZERO));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||||
Instructions.push_back(tmpInst);
|
Instructions.push_back(tmpInst);
|
||||||
} else if ( ImmValue < 0 && ImmValue >= -32768) {
|
} else if ( ImmValue < 0 && ImmValue >= -32768) {
|
||||||
// for -32768 <= j < 0.
|
// for -32768 <= j < 0.
|
||||||
// li d,j => addiu d,$zero,j
|
// li d,j => addiu d,$zero,j
|
||||||
tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
|
tmpInst.setOpcode(Mips::ADDiu);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(
|
tmpInst.addOperand(
|
||||||
MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
|
MCOperand::CreateReg(Mips::ZERO));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||||
Instructions.push_back(tmpInst);
|
Instructions.push_back(tmpInst);
|
||||||
} else {
|
} else {
|
||||||
// for any other value of j that is representable as a 32-bit integer.
|
// for any other value of j that is representable as a 32-bit integer.
|
||||||
// li d,j => lui d,hi16(j)
|
// li d,j => lui d,hi16(j)
|
||||||
// ori d,d,lo16(j)
|
// ori d,d,lo16(j)
|
||||||
tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
|
tmpInst.setOpcode(Mips::LUi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||||
Instructions.push_back(tmpInst);
|
Instructions.push_back(tmpInst);
|
||||||
tmpInst.clear();
|
tmpInst.clear();
|
||||||
tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
|
tmpInst.setOpcode(Mips::ORi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
||||||
@@ -390,7 +464,7 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
|
|||||||
if ( -32768 <= ImmValue && ImmValue <= 65535) {
|
if ( -32768 <= ImmValue && ImmValue <= 65535) {
|
||||||
//for -32768 <= j <= 65535.
|
//for -32768 <= j <= 65535.
|
||||||
//la d,j(s) => addiu d,s,j
|
//la d,j(s) => addiu d,s,j
|
||||||
tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
|
tmpInst.setOpcode(Mips::ADDiu);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||||
@@ -400,12 +474,12 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
|
|||||||
//la d,j(s) => lui d,hi16(j)
|
//la d,j(s) => lui d,hi16(j)
|
||||||
// ori d,d,lo16(j)
|
// ori d,d,lo16(j)
|
||||||
// addu d,d,s
|
// addu d,d,s
|
||||||
tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
|
tmpInst.setOpcode(Mips::LUi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||||
Instructions.push_back(tmpInst);
|
Instructions.push_back(tmpInst);
|
||||||
tmpInst.clear();
|
tmpInst.clear();
|
||||||
tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
|
tmpInst.setOpcode(Mips::ORi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
||||||
@@ -433,19 +507,19 @@ void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
|
|||||||
tmpInst.setOpcode(Mips::ADDiu);
|
tmpInst.setOpcode(Mips::ADDiu);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(
|
tmpInst.addOperand(
|
||||||
MCOperand::CreateReg(isMips64()?Mips::ZERO_64:Mips::ZERO));
|
MCOperand::CreateReg(Mips::ZERO));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||||
Instructions.push_back(tmpInst);
|
Instructions.push_back(tmpInst);
|
||||||
} else {
|
} else {
|
||||||
//for any other value of j that is representable as a 32-bit integer.
|
//for any other value of j that is representable as a 32-bit integer.
|
||||||
//la d,j => lui d,hi16(j)
|
//la d,j => lui d,hi16(j)
|
||||||
// ori d,d,lo16(j)
|
// ori d,d,lo16(j)
|
||||||
tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
|
tmpInst.setOpcode(Mips::LUi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||||
Instructions.push_back(tmpInst);
|
Instructions.push_back(tmpInst);
|
||||||
tmpInst.clear();
|
tmpInst.clear();
|
||||||
tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
|
tmpInst.setOpcode(Mips::ORi);
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
||||||
@@ -498,10 +572,10 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MipsAsmParser::matchRegisterName(StringRef Name) {
|
int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
|
||||||
|
|
||||||
int CC;
|
int CC;
|
||||||
if (!isMips64())
|
if (!is64BitReg)
|
||||||
CC = StringSwitch<unsigned>(Name)
|
CC = StringSwitch<unsigned>(Name)
|
||||||
.Case("zero", Mips::ZERO)
|
.Case("zero", Mips::ZERO)
|
||||||
.Case("a0", Mips::A0)
|
.Case("a0", Mips::A0)
|
||||||
@@ -643,7 +717,7 @@ unsigned MipsAsmParser::getATReg() {
|
|||||||
unsigned Reg = Options.getATRegNum();
|
unsigned Reg = Options.getATRegNum();
|
||||||
if (isMips64())
|
if (isMips64())
|
||||||
return getReg(Mips::CPU64RegsRegClassID,Reg);
|
return getReg(Mips::CPU64RegsRegClassID,Reg);
|
||||||
|
|
||||||
return getReg(Mips::CPURegsRegClassID,Reg);
|
return getReg(Mips::CPURegsRegClassID,Reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,63 +725,41 @@ unsigned MipsAsmParser::getReg(int RC,int RegNo) {
|
|||||||
return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
|
return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
|
int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
|
||||||
|
|
||||||
if (Mnemonic.lower() == "rdhwr") {
|
|
||||||
// at the moment only hwreg29 is supported
|
|
||||||
if (RegNum != 29)
|
|
||||||
return -1;
|
|
||||||
return Mips::HWR29;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RegNum > 31)
|
if (RegNum > 31)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// MIPS64 registers are numbered 1 after the 32-bit equivalents
|
return getReg(RegClass, RegNum);
|
||||||
return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
|
int MipsAsmParser::tryParseRegister(bool is64BitReg) {
|
||||||
const AsmToken &Tok = Parser.getTok();
|
const AsmToken &Tok = Parser.getTok();
|
||||||
int RegNum = -1;
|
int RegNum = -1;
|
||||||
|
|
||||||
if (Tok.is(AsmToken::Identifier)) {
|
if (Tok.is(AsmToken::Identifier)) {
|
||||||
std::string lowerCase = Tok.getString().lower();
|
std::string lowerCase = Tok.getString().lower();
|
||||||
RegNum = matchRegisterName(lowerCase);
|
RegNum = matchRegisterName(lowerCase, is64BitReg);
|
||||||
} else if (Tok.is(AsmToken::Integer))
|
} else if (Tok.is(AsmToken::Integer))
|
||||||
RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
|
RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
|
||||||
Mnemonic.lower());
|
is64BitReg ? Mips::CPU64RegsRegClassID
|
||||||
else
|
: Mips::CPURegsRegClassID);
|
||||||
return RegNum; //error
|
|
||||||
// 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
|
|
||||||
if (isMips64() && RegNum == Mips::ZERO_64) {
|
|
||||||
if (Mnemonic.find("ddiv") != StringRef::npos)
|
|
||||||
RegNum = Mips::ZERO;
|
|
||||||
}
|
|
||||||
return RegNum;
|
return RegNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MipsAsmParser::
|
bool MipsAsmParser::
|
||||||
tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||||
StringRef Mnemonic){
|
bool is64BitReg){
|
||||||
|
|
||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
SMLoc E = Parser.getTok().getEndLoc();
|
|
||||||
int RegNo = -1;
|
int RegNo = -1;
|
||||||
|
|
||||||
// FIXME: we should make a more generic method for CCR
|
RegNo = tryParseRegister(is64BitReg);
|
||||||
if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
|
|
||||||
&& Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
|
|
||||||
RegNo = Parser.getTok().getIntVal(); // get the int value
|
|
||||||
// at the moment only fcc0 is supported
|
|
||||||
if (RegNo == 0)
|
|
||||||
RegNo = Mips::FCC0;
|
|
||||||
} else
|
|
||||||
RegNo = tryParseRegister(Mnemonic);
|
|
||||||
if (RegNo == -1)
|
if (RegNo == -1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Operands.push_back(MipsOperand::CreateReg(RegNo, S, E));
|
Operands.push_back(MipsOperand::CreateReg(RegNo, S,
|
||||||
|
Parser.getTok().getLoc()));
|
||||||
Parser.Lex(); // Eat register token.
|
Parser.Lex(); // Eat register token.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -734,7 +786,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
Parser.Lex(); // Eat dollar token.
|
Parser.Lex(); // Eat dollar token.
|
||||||
// parse register operand
|
// parse register operand
|
||||||
if (!tryParseRegisterOperand(Operands, Mnemonic)) {
|
if (!tryParseRegisterOperand(Operands, isMips64())) {
|
||||||
if (getLexer().is(AsmToken::LParen)) {
|
if (getLexer().is(AsmToken::LParen)) {
|
||||||
// check if it is indexed addressing operand
|
// check if it is indexed addressing operand
|
||||||
Operands.push_back(MipsOperand::CreateToken("(", S));
|
Operands.push_back(MipsOperand::CreateToken("(", S));
|
||||||
@@ -743,7 +795,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
Parser.Lex(); // eat dollar
|
Parser.Lex(); // eat dollar
|
||||||
if (tryParseRegisterOperand(Operands, Mnemonic))
|
if (tryParseRegisterOperand(Operands, isMips64()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!getLexer().is(AsmToken::RParen))
|
if (!getLexer().is(AsmToken::RParen))
|
||||||
@@ -760,7 +812,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|||||||
if (Parser.ParseIdentifier(Identifier))
|
if (Parser.ParseIdentifier(Identifier))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SMLoc E = SMLoc::getFromPointer(Identifier.end());
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||||
|
|
||||||
MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
|
MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
|
||||||
|
|
||||||
@@ -780,9 +832,9 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|||||||
// quoted label names
|
// quoted label names
|
||||||
const MCExpr *IdVal;
|
const MCExpr *IdVal;
|
||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
SMLoc E;
|
if (getParser().ParseExpression(IdVal))
|
||||||
if (getParser().ParseExpression(IdVal, E))
|
|
||||||
return true;
|
return true;
|
||||||
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||||
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -790,10 +842,11 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|||||||
// it is a symbol reference or constant expression
|
// it is a symbol reference or constant expression
|
||||||
const MCExpr *IdVal;
|
const MCExpr *IdVal;
|
||||||
SMLoc S = Parser.getTok().getLoc(); // start location of the operand
|
SMLoc S = Parser.getTok().getLoc(); // start location of the operand
|
||||||
SMLoc E;
|
if (parseRelocOperand(IdVal))
|
||||||
if (parseRelocOperand(IdVal, E))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||||
|
|
||||||
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
||||||
return false;
|
return false;
|
||||||
} // case AsmToken::Percent
|
} // case AsmToken::Percent
|
||||||
@@ -801,7 +854,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res, SMLoc &EndLoc) {
|
bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
|
||||||
|
|
||||||
Parser.Lex(); // eat % token
|
Parser.Lex(); // eat % token
|
||||||
const AsmToken &Tok = Parser.getTok(); // get next token, operation
|
const AsmToken &Tok = Parser.getTok(); // get next token, operation
|
||||||
@@ -813,6 +866,7 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res, SMLoc &EndLoc) {
|
|||||||
Parser.Lex(); // eat identifier
|
Parser.Lex(); // eat identifier
|
||||||
// now make expression from the rest of the operand
|
// now make expression from the rest of the operand
|
||||||
const MCExpr *IdVal;
|
const MCExpr *IdVal;
|
||||||
|
SMLoc EndLoc;
|
||||||
|
|
||||||
if (getLexer().getKind() == AsmToken::LParen) {
|
if (getLexer().getKind() == AsmToken::LParen) {
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -833,10 +887,8 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res, SMLoc &EndLoc) {
|
|||||||
if (getParser().ParseParenExpression(IdVal,EndLoc))
|
if (getParser().ParseParenExpression(IdVal,EndLoc))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
while (getLexer().getKind() == AsmToken::RParen) {
|
while (getLexer().getKind() == AsmToken::RParen)
|
||||||
EndLoc = Parser.getTok().getEndLoc();
|
|
||||||
Parser.Lex(); // eat ')' token
|
Parser.Lex(); // eat ')' token
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
return true; // parenthesis must follow reloc operand
|
return true; // parenthesis must follow reloc operand
|
||||||
@@ -868,23 +920,24 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
|
|||||||
SMLoc &EndLoc) {
|
SMLoc &EndLoc) {
|
||||||
|
|
||||||
StartLoc = Parser.getTok().getLoc();
|
StartLoc = Parser.getTok().getLoc();
|
||||||
EndLoc = Parser.getTok().getEndLoc();
|
RegNo = tryParseRegister(isMips64());
|
||||||
RegNo = tryParseRegister("");
|
EndLoc = Parser.getTok().getLoc();
|
||||||
return (RegNo == (unsigned)-1);
|
return (RegNo == (unsigned)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
|
bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
|
||||||
|
|
||||||
|
SMLoc S;
|
||||||
|
|
||||||
switch(getLexer().getKind()) {
|
switch(getLexer().getKind()) {
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
case AsmToken::Integer:
|
case AsmToken::Integer:
|
||||||
case AsmToken::Minus:
|
case AsmToken::Minus:
|
||||||
case AsmToken::Plus:
|
case AsmToken::Plus:
|
||||||
return getParser().ParseExpression(Res);
|
return (getParser().ParseExpression(Res));
|
||||||
case AsmToken::Percent: {
|
case AsmToken::Percent:
|
||||||
SMLoc E;
|
return parseRelocOperand(Res);
|
||||||
return parseRelocOperand(Res, E);
|
|
||||||
}
|
|
||||||
case AsmToken::LParen:
|
case AsmToken::LParen:
|
||||||
return false; // it's probably assuming 0
|
return false; // it's probably assuming 0
|
||||||
}
|
}
|
||||||
@@ -895,8 +948,9 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
|||||||
SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
|
SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
|
||||||
|
|
||||||
const MCExpr *IdVal = 0;
|
const MCExpr *IdVal = 0;
|
||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S;
|
||||||
SMLoc E = Parser.getTok().getEndLoc();
|
// first operand is the offset
|
||||||
|
S = Parser.getTok().getLoc();
|
||||||
|
|
||||||
if (parseMemOffset(IdVal))
|
if (parseMemOffset(IdVal))
|
||||||
return MatchOperand_ParseFail;
|
return MatchOperand_ParseFail;
|
||||||
@@ -905,6 +959,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
|||||||
if (Tok.isNot(AsmToken::LParen)) {
|
if (Tok.isNot(AsmToken::LParen)) {
|
||||||
MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
|
MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
|
||||||
if (Mnemonic->getToken() == "la") {
|
if (Mnemonic->getToken() == "la") {
|
||||||
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
|
||||||
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
||||||
return MatchOperand_Success;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
@@ -917,7 +972,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
|||||||
const AsmToken &Tok1 = Parser.getTok(); // get next token
|
const AsmToken &Tok1 = Parser.getTok(); // get next token
|
||||||
if (Tok1.is(AsmToken::Dollar)) {
|
if (Tok1.is(AsmToken::Dollar)) {
|
||||||
Parser.Lex(); // Eat '$' token.
|
Parser.Lex(); // Eat '$' token.
|
||||||
if (tryParseRegisterOperand(Operands,"")) {
|
if (tryParseRegisterOperand(Operands, isMips64())) {
|
||||||
Error(Parser.getTok().getLoc(), "unexpected token in operand");
|
Error(Parser.getTok().getLoc(), "unexpected token in operand");
|
||||||
return MatchOperand_ParseFail;
|
return MatchOperand_ParseFail;
|
||||||
}
|
}
|
||||||
@@ -933,7 +988,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
|||||||
return MatchOperand_ParseFail;
|
return MatchOperand_ParseFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
E = Parser.getTok().getEndLoc();
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||||
|
|
||||||
Parser.Lex(); // Eat ')' token.
|
Parser.Lex(); // Eat ')' token.
|
||||||
|
|
||||||
if (IdVal == 0)
|
if (IdVal == 0)
|
||||||
@@ -950,6 +1006,126 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
|||||||
return MatchOperand_Success;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
|
||||||
|
if (!isMips64())
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
// if the first token is not '$' we have an error
|
||||||
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
|
||||||
|
Parser.Lex(); // Eat $
|
||||||
|
if(!tryParseRegisterOperand(Operands, true)) {
|
||||||
|
// set the proper register kind
|
||||||
|
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
|
||||||
|
op->setRegKind(MipsOperand::Kind_CPU64Regs);
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
|
||||||
|
// if the first token is not '$' we have an error
|
||||||
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
|
||||||
|
Parser.Lex(); // Eat $
|
||||||
|
if(!tryParseRegisterOperand(Operands, false)) {
|
||||||
|
// set the propper register kind
|
||||||
|
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
|
||||||
|
op->setRegKind(MipsOperand::Kind_CPURegs);
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
|
||||||
|
// if the first token is not '$' we have error
|
||||||
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
|
Parser.Lex(); // Eat $
|
||||||
|
|
||||||
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
||||||
|
if (Tok.isNot(AsmToken::Integer))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
|
||||||
|
unsigned RegNum = Tok.getIntVal();
|
||||||
|
// at the moment only hwreg29 is supported
|
||||||
|
if (RegNum != 29)
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
|
MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
|
||||||
|
Parser.getTok().getLoc());
|
||||||
|
op->setRegKind(MipsOperand::Kind_HWRegs);
|
||||||
|
Operands.push_back(op);
|
||||||
|
|
||||||
|
Parser.Lex(); // Eat reg number
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
//if the first token is not '$' we have error
|
||||||
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
|
Parser.Lex(); // Eat $
|
||||||
|
|
||||||
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
||||||
|
if (Tok.isNot(AsmToken::Integer))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
|
||||||
|
unsigned RegNum = Tok.getIntVal();
|
||||||
|
// at the moment only hwreg29 is supported
|
||||||
|
if (RegNum != 29)
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
|
MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
|
||||||
|
Parser.getTok().getLoc());
|
||||||
|
op->setRegKind(MipsOperand::Kind_HWRegs);
|
||||||
|
Operands.push_back(op);
|
||||||
|
|
||||||
|
Parser.Lex(); // Eat reg number
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
MipsAsmParser::OperandMatchResultTy
|
||||||
|
MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
unsigned RegNum;
|
||||||
|
//if the first token is not '$' we have error
|
||||||
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
|
Parser.Lex(); // Eat $
|
||||||
|
|
||||||
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
||||||
|
if (Tok.is(AsmToken::Integer)) {
|
||||||
|
RegNum = Tok.getIntVal();
|
||||||
|
// at the moment only fcc0 is supported
|
||||||
|
if (RegNum != 0)
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
} else if (Tok.is(AsmToken::Identifier)) {
|
||||||
|
// at the moment only fcc0 is supported
|
||||||
|
if (Tok.getIdentifier() != "fcc0")
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
} else
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
|
||||||
|
MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
|
||||||
|
Parser.getTok().getLoc());
|
||||||
|
op->setRegKind(MipsOperand::Kind_CCRRegs);
|
||||||
|
Operands.push_back(op);
|
||||||
|
|
||||||
|
Parser.Lex(); // Eat reg number
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
|
MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
|
||||||
|
|
||||||
MCSymbolRefExpr::VariantKind VK
|
MCSymbolRefExpr::VariantKind VK
|
||||||
@@ -1083,8 +1259,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
|||||||
if (Cc == -1) {
|
if (Cc == -1) {
|
||||||
return Error(NameLoc, "Invalid conditional code");
|
return Error(NameLoc, "Invalid conditional code");
|
||||||
}
|
}
|
||||||
// FIXME: May include trailing whitespace...
|
SMLoc E = SMLoc::getFromPointer(
|
||||||
SMLoc E = Parser.getTok().getLoc();
|
Parser.getTok().getLoc().getPointer() -1 );
|
||||||
Operands.push_back(MipsOperand::CreateImm(
|
Operands.push_back(MipsOperand::CreateImm(
|
||||||
MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
|
MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
|
||||||
} else {
|
} else {
|
||||||
|
@@ -149,6 +149,11 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
|
|||||||
OS << ')';
|
OS << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MipsInstPrinter::printCPURegs(const MCInst *MI, unsigned OpNo,
|
||||||
|
raw_ostream &O) {
|
||||||
|
printRegName(O, MI->getOperand(OpNo).getReg());
|
||||||
|
}
|
||||||
|
|
||||||
void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
const MCOperand &Op = MI->getOperand(OpNo);
|
const MCOperand &Op = MI->getOperand(OpNo);
|
||||||
|
@@ -87,6 +87,7 @@ public:
|
|||||||
|
|
||||||
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
|
virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
|
||||||
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
|
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
|
||||||
|
void printCPURegs(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
|
@@ -71,52 +71,54 @@ let usesCustomInserter = 1, Predicates = [HasStdEnc],
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
let DecoderNamespace = "Mips64" in {
|
let DecoderNamespace = "Mips64" in {
|
||||||
/// Arithmetic Instructions (ALU Immediate)
|
/// Arithmetic Instructions (ALU Immediate)
|
||||||
def DADDi : ArithLogicI<"daddi", simm16_64, CPU64Regs>, ADDI_FM<0x18>;
|
def DADDi : ArithLogicI<"daddi", simm16_64, CPU64RegsOpnd>, ADDI_FM<0x18>;
|
||||||
def DADDiu : ArithLogicI<"daddiu", simm16_64, CPU64Regs, immSExt16, add>,
|
def DADDiu : ArithLogicI<"daddiu", simm16_64, CPU64RegsOpnd, immSExt16, add>,
|
||||||
ADDI_FM<0x19>, IsAsCheapAsAMove;
|
ADDI_FM<0x19>, IsAsCheapAsAMove;
|
||||||
def DANDi : ArithLogicI<"andi", uimm16_64, CPU64Regs, immZExt16, and>,
|
def DANDi : ArithLogicI<"andi", uimm16_64, CPU64RegsOpnd, immZExt16, and>,
|
||||||
ADDI_FM<0xc>;
|
ADDI_FM<0xc>;
|
||||||
def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, CPU64Regs>,
|
def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, CPU64Regs>,
|
||||||
SLTI_FM<0xa>;
|
SLTI_FM<0xa>;
|
||||||
def SLTiu64 : SetCC_I<"sltiu", setult, simm16_64, immSExt16, CPU64Regs>,
|
def SLTiu64 : SetCC_I<"sltiu", setult, simm16_64, immSExt16, CPU64Regs>,
|
||||||
SLTI_FM<0xb>;
|
SLTI_FM<0xb>;
|
||||||
def ORi64 : ArithLogicI<"ori", uimm16_64, CPU64Regs, immZExt16, or>,
|
def ORi64 : ArithLogicI<"ori", uimm16_64, CPU64RegsOpnd, immZExt16, or>,
|
||||||
ADDI_FM<0xd>;
|
ADDI_FM<0xd>;
|
||||||
def XORi64 : ArithLogicI<"xori", uimm16_64, CPU64Regs, immZExt16, xor>,
|
def XORi64 : ArithLogicI<"xori", uimm16_64, CPU64RegsOpnd, immZExt16, xor>,
|
||||||
ADDI_FM<0xe>;
|
ADDI_FM<0xe>;
|
||||||
def LUi64 : LoadUpper<"lui", CPU64Regs, uimm16_64>, LUI_FM;
|
def LUi64 : LoadUpper<"lui", CPU64Regs, uimm16_64>, LUI_FM;
|
||||||
|
|
||||||
/// Arithmetic Instructions (3-Operand, R-Type)
|
/// Arithmetic Instructions (3-Operand, R-Type)
|
||||||
def DADD : ArithLogicR<"dadd", CPU64Regs>, ADD_FM<0, 0x2c>;
|
def DADD : ArithLogicR<"dadd", CPU64RegsOpnd>, ADD_FM<0, 0x2c>;
|
||||||
def DADDu : ArithLogicR<"daddu", CPU64Regs, 1, IIAlu, add>, ADD_FM<0, 0x2d>;
|
def DADDu : ArithLogicR<"daddu", CPU64RegsOpnd, 1, IIAlu, add>,
|
||||||
def DSUBu : ArithLogicR<"dsubu", CPU64Regs, 0, IIAlu, sub>, ADD_FM<0, 0x2f>;
|
ADD_FM<0, 0x2d>;
|
||||||
|
def DSUBu : ArithLogicR<"dsubu", CPU64RegsOpnd, 0, IIAlu, sub>,
|
||||||
|
ADD_FM<0, 0x2f>;
|
||||||
def SLT64 : SetCC_R<"slt", setlt, CPU64Regs>, ADD_FM<0, 0x2a>;
|
def SLT64 : SetCC_R<"slt", setlt, CPU64Regs>, ADD_FM<0, 0x2a>;
|
||||||
def SLTu64 : SetCC_R<"sltu", setult, CPU64Regs>, ADD_FM<0, 0x2b>;
|
def SLTu64 : SetCC_R<"sltu", setult, CPU64Regs>, ADD_FM<0, 0x2b>;
|
||||||
def AND64 : ArithLogicR<"and", CPU64Regs, 1, IIAlu, and>, ADD_FM<0, 0x24>;
|
def AND64 : ArithLogicR<"and", CPU64RegsOpnd, 1, IIAlu, and>, ADD_FM<0, 0x24>;
|
||||||
def OR64 : ArithLogicR<"or", CPU64Regs, 1, IIAlu, or>, ADD_FM<0, 0x25>;
|
def OR64 : ArithLogicR<"or", CPU64RegsOpnd, 1, IIAlu, or>, ADD_FM<0, 0x25>;
|
||||||
def XOR64 : ArithLogicR<"xor", CPU64Regs, 1, IIAlu, xor>, ADD_FM<0, 0x26>;
|
def XOR64 : ArithLogicR<"xor", CPU64RegsOpnd, 1, IIAlu, xor>, ADD_FM<0, 0x26>;
|
||||||
def NOR64 : LogicNOR<"nor", CPU64Regs>, ADD_FM<0, 0x27>;
|
def NOR64 : LogicNOR<"nor", CPU64RegsOpnd>, ADD_FM<0, 0x27>;
|
||||||
|
|
||||||
/// Shift Instructions
|
/// Shift Instructions
|
||||||
def DSLL : shift_rotate_imm<"dsll", shamt, CPU64Regs, shl, immZExt6>,
|
def DSLL : shift_rotate_imm<"dsll", shamt, CPU64RegsOpnd, shl, immZExt6>,
|
||||||
SRA_FM<0x38, 0>;
|
SRA_FM<0x38, 0>;
|
||||||
def DSRL : shift_rotate_imm<"dsrl", shamt, CPU64Regs, srl, immZExt6>,
|
def DSRL : shift_rotate_imm<"dsrl", shamt, CPU64RegsOpnd, srl, immZExt6>,
|
||||||
SRA_FM<0x3a, 0>;
|
SRA_FM<0x3a, 0>;
|
||||||
def DSRA : shift_rotate_imm<"dsra", shamt, CPU64Regs, sra, immZExt6>,
|
def DSRA : shift_rotate_imm<"dsra", shamt, CPU64RegsOpnd, sra, immZExt6>,
|
||||||
SRA_FM<0x3b, 0>;
|
SRA_FM<0x3b, 0>;
|
||||||
def DSLLV : shift_rotate_reg<"dsllv", CPU64Regs, shl>, SRLV_FM<0x14, 0>;
|
def DSLLV : shift_rotate_reg<"dsllv", CPU64RegsOpnd, shl>, SRLV_FM<0x14, 0>;
|
||||||
def DSRLV : shift_rotate_reg<"dsrlv", CPU64Regs, srl>, SRLV_FM<0x16, 0>;
|
def DSRLV : shift_rotate_reg<"dsrlv", CPU64RegsOpnd, srl>, SRLV_FM<0x16, 0>;
|
||||||
def DSRAV : shift_rotate_reg<"dsrav", CPU64Regs, sra>, SRLV_FM<0x17, 0>;
|
def DSRAV : shift_rotate_reg<"dsrav", CPU64RegsOpnd, sra>, SRLV_FM<0x17, 0>;
|
||||||
def DSLL32 : shift_rotate_imm<"dsll32", shamt, CPU64Regs>, SRA_FM<0x3c, 0>;
|
def DSLL32 : shift_rotate_imm<"dsll32", shamt, CPU64RegsOpnd>, SRA_FM<0x3c, 0>;
|
||||||
def DSRL32 : shift_rotate_imm<"dsrl32", shamt, CPU64Regs>, SRA_FM<0x3e, 0>;
|
def DSRL32 : shift_rotate_imm<"dsrl32", shamt, CPU64RegsOpnd>, SRA_FM<0x3e, 0>;
|
||||||
def DSRA32 : shift_rotate_imm<"dsra32", shamt, CPU64Regs>, SRA_FM<0x3f, 0>;
|
def DSRA32 : shift_rotate_imm<"dsra32", shamt, CPU64RegsOpnd>, SRA_FM<0x3f, 0>;
|
||||||
}
|
}
|
||||||
// Rotate Instructions
|
// Rotate Instructions
|
||||||
let Predicates = [HasMips64r2, HasStdEnc],
|
let Predicates = [HasMips64r2, HasStdEnc],
|
||||||
DecoderNamespace = "Mips64" in {
|
DecoderNamespace = "Mips64" in {
|
||||||
def DROTR : shift_rotate_imm<"drotr", shamt, CPU64Regs, rotr, immZExt6>,
|
def DROTR : shift_rotate_imm<"drotr", shamt, CPU64RegsOpnd, rotr, immZExt6>,
|
||||||
SRA_FM<0x3a, 1>;
|
SRA_FM<0x3a, 1>;
|
||||||
def DROTRV : shift_rotate_reg<"drotrv", CPU64Regs, rotr>, SRLV_FM<0x16, 1>;
|
def DROTRV : shift_rotate_reg<"drotrv", CPU64RegsOpnd, rotr>, SRLV_FM<0x16, 1>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let DecoderNamespace = "Mips64" in {
|
let DecoderNamespace = "Mips64" in {
|
||||||
@@ -135,12 +137,11 @@ defm LD : LoadM<"ld", CPU64Regs, load>, LW_FM<0x37>;
|
|||||||
defm SD : StoreM<"sd", CPU64Regs, store>, LW_FM<0x3f>;
|
defm SD : StoreM<"sd", CPU64Regs, store>, LW_FM<0x3f>;
|
||||||
|
|
||||||
/// load/store left/right
|
/// load/store left/right
|
||||||
let isCodeGenOnly = 1 in {
|
defm LWL64 : LoadLeftRightM<"lwl", MipsLWL, CPU64Regs>, LW_FM<0x22>;
|
||||||
defm LWL64 : LoadLeftRightM<"lwl", MipsLWL, CPU64Regs>, LW_FM<0x22>;
|
defm LWR64 : LoadLeftRightM<"lwr", MipsLWR, CPU64Regs>, LW_FM<0x26>;
|
||||||
defm LWR64 : LoadLeftRightM<"lwr", MipsLWR, CPU64Regs>, LW_FM<0x26>;
|
defm SWL64 : StoreLeftRightM<"swl", MipsSWL, CPU64Regs>, LW_FM<0x2a>;
|
||||||
defm SWL64 : StoreLeftRightM<"swl", MipsSWL, CPU64Regs>, LW_FM<0x2a>;
|
defm SWR64 : StoreLeftRightM<"swr", MipsSWR, CPU64Regs>, LW_FM<0x2e>;
|
||||||
defm SWR64 : StoreLeftRightM<"swr", MipsSWR, CPU64Regs>, LW_FM<0x2e>;
|
|
||||||
}
|
|
||||||
defm LDL : LoadLeftRightM<"ldl", MipsLDL, CPU64Regs>, LW_FM<0x1a>;
|
defm LDL : LoadLeftRightM<"ldl", MipsLDL, CPU64Regs>, LW_FM<0x1a>;
|
||||||
defm LDR : LoadLeftRightM<"ldr", MipsLDR, CPU64Regs>, LW_FM<0x1b>;
|
defm LDR : LoadLeftRightM<"ldr", MipsLDR, CPU64Regs>, LW_FM<0x1b>;
|
||||||
defm SDL : StoreLeftRightM<"sdl", MipsSDL, CPU64Regs>, LW_FM<0x2c>;
|
defm SDL : StoreLeftRightM<"sdl", MipsSDL, CPU64Regs>, LW_FM<0x2c>;
|
||||||
@@ -148,13 +149,13 @@ defm SDR : StoreLeftRightM<"sdr", MipsSDR, CPU64Regs>, LW_FM<0x2d>;
|
|||||||
|
|
||||||
/// Load-linked, Store-conditional
|
/// Load-linked, Store-conditional
|
||||||
let Predicates = [NotN64, HasStdEnc] in {
|
let Predicates = [NotN64, HasStdEnc] in {
|
||||||
def LLD : LLBase<"lld", CPU64Regs, mem>, LW_FM<0x34>;
|
def LLD : LLBase<"lld", CPU64RegsOpnd, mem>, LW_FM<0x34>;
|
||||||
def SCD : SCBase<"scd", CPU64Regs, mem>, LW_FM<0x3c>;
|
def SCD : SCBase<"scd", CPU64RegsOpnd, mem>, LW_FM<0x3c>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Predicates = [IsN64, HasStdEnc], isCodeGenOnly = 1 in {
|
let Predicates = [IsN64, HasStdEnc], isCodeGenOnly = 1 in {
|
||||||
def LLD_P8 : LLBase<"lld", CPU64Regs, mem64>, LW_FM<0x34>;
|
def LLD_P8 : LLBase<"lld", CPU64RegsOpnd, mem64>, LW_FM<0x34>;
|
||||||
def SCD_P8 : SCBase<"scd", CPU64Regs, mem64>, LW_FM<0x3c>;
|
def SCD_P8 : SCBase<"scd", CPU64RegsOpnd, mem64>, LW_FM<0x3c>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Jump and Branch Instructions
|
/// Jump and Branch Instructions
|
||||||
@@ -172,11 +173,11 @@ def TAILCALL64_R : JumpFR<CPU64Regs, MipsTailCall>, MTLO_FM<8>, IsTailCall;
|
|||||||
|
|
||||||
let DecoderNamespace = "Mips64" in {
|
let DecoderNamespace = "Mips64" in {
|
||||||
/// Multiply and Divide Instructions.
|
/// Multiply and Divide Instructions.
|
||||||
def DMULT : Mult<"dmult", IIImul, CPU64Regs, [HI64, LO64]>, MULT_FM<0, 0x1c>;
|
def DMULT : Mult<"dmult", IIImul, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1c>;
|
||||||
def DMULTu : Mult<"dmultu", IIImul, CPU64Regs, [HI64, LO64]>, MULT_FM<0, 0x1d>;
|
def DMULTu : Mult<"dmultu", IIImul, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1d>;
|
||||||
def DSDIV : Div<MipsDivRem, "ddiv", IIIdiv, CPU64Regs, [HI64, LO64]>,
|
def DSDIV : Div<MipsDivRem, "ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
|
||||||
MULT_FM<0, 0x1e>;
|
MULT_FM<0, 0x1e>;
|
||||||
def DUDIV : Div<MipsDivRemU, "ddivu", IIIdiv, CPU64Regs, [HI64, LO64]>,
|
def DUDIV : Div<MipsDivRemU, "ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
|
||||||
MULT_FM<0, 0x1f>;
|
MULT_FM<0, 0x1f>;
|
||||||
|
|
||||||
def MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
|
def MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
|
||||||
@@ -189,28 +190,28 @@ def SEB64 : SignExtInReg<"seb", i8, CPU64Regs>, SEB_FM<0x10, 0x20>;
|
|||||||
def SEH64 : SignExtInReg<"seh", i16, CPU64Regs>, SEB_FM<0x18, 0x20>;
|
def SEH64 : SignExtInReg<"seh", i16, CPU64Regs>, SEB_FM<0x18, 0x20>;
|
||||||
|
|
||||||
/// Count Leading
|
/// Count Leading
|
||||||
def DCLZ : CountLeading0<"dclz", CPU64Regs>, CLO_FM<0x24>;
|
def DCLZ : CountLeading0<"dclz", CPU64RegsOpnd>, CLO_FM<0x24>;
|
||||||
def DCLO : CountLeading1<"dclo", CPU64Regs>, CLO_FM<0x25>;
|
def DCLO : CountLeading1<"dclo", CPU64RegsOpnd>, CLO_FM<0x25>;
|
||||||
|
|
||||||
/// Double Word Swap Bytes/HalfWords
|
/// Double Word Swap Bytes/HalfWords
|
||||||
def DSBH : SubwordSwap<"dsbh", CPU64Regs>, SEB_FM<2, 0x24>;
|
def DSBH : SubwordSwap<"dsbh", CPU64RegsOpnd>, SEB_FM<2, 0x24>;
|
||||||
def DSHD : SubwordSwap<"dshd", CPU64Regs>, SEB_FM<5, 0x24>;
|
def DSHD : SubwordSwap<"dshd", CPU64RegsOpnd>, SEB_FM<5, 0x24>;
|
||||||
|
|
||||||
def LEA_ADDiu64 : EffectiveAddress<"daddiu", CPU64Regs, mem_ea_64>, LW_FM<0x19>;
|
def LEA_ADDiu64 : EffectiveAddress<"daddiu", CPU64Regs, mem_ea_64>, LW_FM<0x19>;
|
||||||
|
|
||||||
}
|
}
|
||||||
let DecoderNamespace = "Mips64" in {
|
let DecoderNamespace = "Mips64" in {
|
||||||
def RDHWR64 : ReadHardware<CPU64Regs, HWRegs64>, RDHWR_FM;
|
def RDHWR64 : ReadHardware<CPU64Regs, HW64RegsOpnd>, RDHWR_FM;
|
||||||
|
|
||||||
def DEXT : ExtBase<"dext", CPU64Regs>, EXT_FM<3>;
|
def DEXT : ExtBase<"dext", CPU64RegsOpnd>, EXT_FM<3>;
|
||||||
let Pattern = []<dag> in {
|
let Pattern = []<dag> in {
|
||||||
def DEXTU : ExtBase<"dextu", CPU64Regs>, EXT_FM<2>;
|
def DEXTU : ExtBase<"dextu", CPU64RegsOpnd>, EXT_FM<2>;
|
||||||
def DEXTM : ExtBase<"dextm", CPU64Regs>, EXT_FM<1>;
|
def DEXTM : ExtBase<"dextm", CPU64RegsOpnd>, EXT_FM<1>;
|
||||||
}
|
}
|
||||||
def DINS : InsBase<"dins", CPU64Regs>, EXT_FM<7>;
|
def DINS : InsBase<"dins", CPU64RegsOpnd>, EXT_FM<7>;
|
||||||
let Pattern = []<dag> in {
|
let Pattern = []<dag> in {
|
||||||
def DINSU : InsBase<"dinsu", CPU64Regs>, EXT_FM<6>;
|
def DINSU : InsBase<"dinsu", CPU64RegsOpnd>, EXT_FM<6>;
|
||||||
def DINSM : InsBase<"dinsm", CPU64Regs>, EXT_FM<5>;
|
def DINSM : InsBase<"dinsm", CPU64RegsOpnd>, EXT_FM<5>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
|
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
|
||||||
@@ -304,7 +305,25 @@ def : MipsPat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>;
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Instruction aliases
|
// Instruction aliases
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
def : InstAlias<"move $dst,$src", (DADD CPU64Regs:$dst,CPU64Regs:$src,ZERO_64)>;
|
def : InstAlias<"move $dst,$src", (DADDu CPU64RegsOpnd:$dst,
|
||||||
|
CPU64RegsOpnd:$src,ZERO_64)>,
|
||||||
|
Requires<[HasMips64]>;
|
||||||
|
def : InstAlias<"and $rs, $rt, $imm",
|
||||||
|
(DANDi CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, uimm16_64:$imm)>,
|
||||||
|
Requires<[HasMips64]>;
|
||||||
|
def : InstAlias<"slt $rs, $rt, $imm",
|
||||||
|
(SLTi64 CPURegsOpnd:$rs, CPU64Regs:$rt, simm16_64:$imm)>,
|
||||||
|
Requires<[HasMips64]>;
|
||||||
|
def : InstAlias<"xor $rs, $rt, $imm",
|
||||||
|
(XORi64 CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, uimm16_64:$imm)>,
|
||||||
|
Requires<[HasMips64]>;
|
||||||
|
def : InstAlias<"not $rt, $rs", (NOR64 CPU64RegsOpnd:$rt, CPU64RegsOpnd:$rs, ZERO_64)>,
|
||||||
|
Requires<[HasMips64]>;
|
||||||
|
def : InstAlias<"j $rs", (JR64 CPU64Regs:$rs)>, Requires<[HasMips64]>;
|
||||||
|
def : InstAlias<"daddu $rs, $rt, $imm",
|
||||||
|
(DADDiu CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, simm16_64:$imm)>;
|
||||||
|
def : InstAlias<"dadd $rs, $rt, $imm",
|
||||||
|
(DADDi CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, simm16_64:$imm)>;
|
||||||
|
|
||||||
/// Move between CPU and coprocessor registers
|
/// Move between CPU and coprocessor registers
|
||||||
let DecoderNamespace = "Mips64" in {
|
let DecoderNamespace = "Mips64" in {
|
||||||
|
@@ -138,6 +138,16 @@ class MTC1_FT<string opstr, RegisterClass DstRC, RegisterClass SrcRC,
|
|||||||
InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"),
|
InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"),
|
||||||
[(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR>;
|
[(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR>;
|
||||||
|
|
||||||
|
class MFC1_FT_CCR<string opstr, RegisterClass DstRC, RegisterOperand SrcRC,
|
||||||
|
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
|
||||||
|
InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"),
|
||||||
|
[(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR>;
|
||||||
|
|
||||||
|
class MTC1_FT_CCR<string opstr, RegisterOperand DstRC, RegisterClass SrcRC,
|
||||||
|
InstrItinClass Itin, SDPatternOperator OpNode= null_frag> :
|
||||||
|
InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"),
|
||||||
|
[(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR>;
|
||||||
|
|
||||||
class LW_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
|
class LW_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
|
||||||
Operand MemOpnd, SDPatternOperator OpNode= null_frag> :
|
Operand MemOpnd, SDPatternOperator OpNode= null_frag> :
|
||||||
InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"),
|
InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"),
|
||||||
@@ -265,8 +275,8 @@ defm FSQRT : ABSS_M<"sqrt.d", IIFsqrtDouble, fsqrt>, ABSS_FM<0x4, 17>;
|
|||||||
// regardless of register aliasing.
|
// regardless of register aliasing.
|
||||||
|
|
||||||
/// Move Control Registers From/To CPU Registers
|
/// Move Control Registers From/To CPU Registers
|
||||||
def CFC1 : MFC1_FT<"cfc1", CPURegs, CCR, IIFmove>, MFC1_FM<2>;
|
def CFC1 : MFC1_FT_CCR<"cfc1", CPURegs, CCROpnd, IIFmove>, MFC1_FM<2>;
|
||||||
def CTC1 : MTC1_FT<"ctc1", CCR, CPURegs, IIFmove>, MFC1_FM<6>;
|
def CTC1 : MTC1_FT_CCR<"ctc1", CCROpnd, CPURegs, IIFmove>, MFC1_FM<6>;
|
||||||
def MFC1 : MFC1_FT<"mfc1", CPURegs, FGR32, IIFmove, bitconvert>, MFC1_FM<0>;
|
def MFC1 : MFC1_FT<"mfc1", CPURegs, FGR32, IIFmove, bitconvert>, MFC1_FM<0>;
|
||||||
def MTC1 : MTC1_FT<"mtc1", FGR32, CPURegs, IIFmove, bitconvert>, MFC1_FM<4>;
|
def MTC1 : MTC1_FT<"mtc1", FGR32, CPURegs, IIFmove, bitconvert>, MFC1_FM<4>;
|
||||||
def DMFC1 : MFC1_FT<"dmfc1", CPU64Regs, FGR64, IIFmove, bitconvert>, MFC1_FM<1>;
|
def DMFC1 : MFC1_FT<"dmfc1", CPU64Regs, FGR64, IIFmove, bitconvert>, MFC1_FM<1>;
|
||||||
@@ -437,7 +447,7 @@ def FCMP_D64 : CEQS_FT<"d", FGR64, IIFcmp, MipsFPCmp>, CEQS_FM<17>,
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Floating Point Pseudo-Instructions
|
// Floating Point Pseudo-Instructions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
def MOVCCRToCCR : PseudoSE<(outs CCR:$dst), (ins CCR:$src), []>;
|
def MOVCCRToCCR : PseudoSE<(outs CCR:$dst), (ins CCROpnd:$src), []>;
|
||||||
|
|
||||||
// This pseudo instr gets expanded into 2 mtc1 instrs after register
|
// This pseudo instr gets expanded into 2 mtc1 instrs after register
|
||||||
// allocation.
|
// allocation.
|
||||||
|
@@ -332,12 +332,12 @@ def addr :
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Arithmetic and logical instructions with 3 register operands.
|
// Arithmetic and logical instructions with 3 register operands.
|
||||||
class ArithLogicR<string opstr, RegisterClass RC, bit isComm = 0,
|
class ArithLogicR<string opstr, RegisterOperand RO, bit isComm = 0,
|
||||||
InstrItinClass Itin = NoItinerary,
|
InstrItinClass Itin = NoItinerary,
|
||||||
SDPatternOperator OpNode = null_frag>:
|
SDPatternOperator OpNode = null_frag>:
|
||||||
InstSE<(outs RC:$rd), (ins RC:$rs, RC:$rt),
|
InstSE<(outs RO:$rd), (ins RO:$rs, RO:$rt),
|
||||||
!strconcat(opstr, "\t$rd, $rs, $rt"),
|
!strconcat(opstr, "\t$rd, $rs, $rt"),
|
||||||
[(set RC:$rd, (OpNode RC:$rs, RC:$rt))], Itin, FrmR> {
|
[(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> {
|
||||||
let isCommutable = isComm;
|
let isCommutable = isComm;
|
||||||
let isReMaterializable = 1;
|
let isReMaterializable = 1;
|
||||||
string BaseOpcode;
|
string BaseOpcode;
|
||||||
@@ -345,27 +345,27 @@ class ArithLogicR<string opstr, RegisterClass RC, bit isComm = 0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Arithmetic and logical instructions with 2 register operands.
|
// Arithmetic and logical instructions with 2 register operands.
|
||||||
class ArithLogicI<string opstr, Operand Od, RegisterClass RC,
|
class ArithLogicI<string opstr, Operand Od, RegisterOperand RO,
|
||||||
SDPatternOperator imm_type = null_frag,
|
SDPatternOperator imm_type = null_frag,
|
||||||
SDPatternOperator OpNode = null_frag> :
|
SDPatternOperator OpNode = null_frag> :
|
||||||
InstSE<(outs RC:$rt), (ins RC:$rs, Od:$imm16),
|
InstSE<(outs RO:$rt), (ins RO:$rs, Od:$imm16),
|
||||||
!strconcat(opstr, "\t$rt, $rs, $imm16"),
|
!strconcat(opstr, "\t$rt, $rs, $imm16"),
|
||||||
[(set RC:$rt, (OpNode RC:$rs, imm_type:$imm16))], IIAlu, FrmI> {
|
[(set RO:$rt, (OpNode RO:$rs, imm_type:$imm16))], IIAlu, FrmI> {
|
||||||
let isReMaterializable = 1;
|
let isReMaterializable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arithmetic Multiply ADD/SUB
|
// Arithmetic Multiply ADD/SUB
|
||||||
class MArithR<string opstr, SDPatternOperator op = null_frag, bit isComm = 0> :
|
class MArithR<string opstr, SDPatternOperator op = null_frag, bit isComm = 0> :
|
||||||
InstSE<(outs), (ins CPURegs:$rs, CPURegs:$rt),
|
InstSE<(outs), (ins CPURegsOpnd:$rs, CPURegsOpnd:$rt),
|
||||||
!strconcat(opstr, "\t$rs, $rt"),
|
!strconcat(opstr, "\t$rs, $rt"),
|
||||||
[(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul, FrmR> {
|
[(op CPURegsOpnd:$rs, CPURegsOpnd:$rt, LO, HI)], IIImul, FrmR> {
|
||||||
let Defs = [HI, LO];
|
let Defs = [HI, LO];
|
||||||
let Uses = [HI, LO];
|
let Uses = [HI, LO];
|
||||||
let isCommutable = isComm;
|
let isCommutable = isComm;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logical
|
// Logical
|
||||||
class LogicNOR<string opstr, RegisterClass RC>:
|
class LogicNOR<string opstr, RegisterOperand RC>:
|
||||||
InstSE<(outs RC:$rd), (ins RC:$rs, RC:$rt),
|
InstSE<(outs RC:$rd), (ins RC:$rs, RC:$rt),
|
||||||
!strconcat(opstr, "\t$rd, $rs, $rt"),
|
!strconcat(opstr, "\t$rd, $rs, $rt"),
|
||||||
[(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu, FrmR> {
|
[(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu, FrmR> {
|
||||||
@@ -374,17 +374,17 @@ class LogicNOR<string opstr, RegisterClass RC>:
|
|||||||
|
|
||||||
// Shifts
|
// Shifts
|
||||||
class shift_rotate_imm<string opstr, Operand ImmOpnd,
|
class shift_rotate_imm<string opstr, Operand ImmOpnd,
|
||||||
RegisterClass RC, SDPatternOperator OpNode = null_frag,
|
RegisterOperand RC, SDPatternOperator OpNode = null_frag,
|
||||||
SDPatternOperator PF = null_frag> :
|
SDPatternOperator PF = null_frag> :
|
||||||
InstSE<(outs RC:$rd), (ins RC:$rt, ImmOpnd:$shamt),
|
InstSE<(outs RC:$rd), (ins RC:$rt, ImmOpnd:$shamt),
|
||||||
!strconcat(opstr, "\t$rd, $rt, $shamt"),
|
!strconcat(opstr, "\t$rd, $rt, $shamt"),
|
||||||
[(set RC:$rd, (OpNode RC:$rt, PF:$shamt))], IIAlu, FrmR>;
|
[(set RC:$rd, (OpNode RC:$rt, PF:$shamt))], IIAlu, FrmR>;
|
||||||
|
|
||||||
class shift_rotate_reg<string opstr, RegisterClass RC,
|
class shift_rotate_reg<string opstr, RegisterOperand RC,
|
||||||
SDPatternOperator OpNode = null_frag>:
|
SDPatternOperator OpNode = null_frag>:
|
||||||
InstSE<(outs RC:$rd), (ins CPURegs:$rs, RC:$rt),
|
InstSE<(outs RC:$rd), (ins CPURegsOpnd:$rs, RC:$rt),
|
||||||
!strconcat(opstr, "\t$rd, $rt, $rs"),
|
!strconcat(opstr, "\t$rd, $rt, $rs"),
|
||||||
[(set RC:$rd, (OpNode RC:$rt, CPURegs:$rs))], IIAlu, FrmR>;
|
[(set RC:$rd, (OpNode RC:$rt, CPURegsOpnd:$rs))], IIAlu, FrmR>;
|
||||||
|
|
||||||
// Load Upper Imediate
|
// Load Upper Imediate
|
||||||
class LoadUpper<string opstr, RegisterClass RC, Operand Imm>:
|
class LoadUpper<string opstr, RegisterClass RC, Operand Imm>:
|
||||||
@@ -498,15 +498,15 @@ class CBranchZero<string opstr, PatFrag cond_op, RegisterClass RC> :
|
|||||||
|
|
||||||
// SetCC
|
// SetCC
|
||||||
class SetCC_R<string opstr, PatFrag cond_op, RegisterClass RC> :
|
class SetCC_R<string opstr, PatFrag cond_op, RegisterClass RC> :
|
||||||
InstSE<(outs CPURegs:$rd), (ins RC:$rs, RC:$rt),
|
InstSE<(outs CPURegsOpnd:$rd), (ins RC:$rs, RC:$rt),
|
||||||
!strconcat(opstr, "\t$rd, $rs, $rt"),
|
!strconcat(opstr, "\t$rd, $rs, $rt"),
|
||||||
[(set CPURegs:$rd, (cond_op RC:$rs, RC:$rt))], IIAlu, FrmR>;
|
[(set CPURegsOpnd:$rd, (cond_op RC:$rs, RC:$rt))], IIAlu, FrmR>;
|
||||||
|
|
||||||
class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type,
|
class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type,
|
||||||
RegisterClass RC>:
|
RegisterClass RC>:
|
||||||
InstSE<(outs CPURegs:$rt), (ins RC:$rs, Od:$imm16),
|
InstSE<(outs CPURegsOpnd:$rt), (ins RC:$rs, Od:$imm16),
|
||||||
!strconcat(opstr, "\t$rt, $rs, $imm16"),
|
!strconcat(opstr, "\t$rt, $rs, $imm16"),
|
||||||
[(set CPURegs:$rt, (cond_op RC:$rs, imm_type:$imm16))], IIAlu, FrmI>;
|
[(set CPURegsOpnd:$rt, (cond_op RC:$rs, imm_type:$imm16))], IIAlu, FrmI>;
|
||||||
|
|
||||||
// Jump
|
// Jump
|
||||||
class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
|
class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
|
||||||
@@ -563,8 +563,8 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in {
|
|||||||
InstSE<(outs), (ins RC:$rs), !strconcat(opstr, "\t$rs"),
|
InstSE<(outs), (ins RC:$rs), !strconcat(opstr, "\t$rs"),
|
||||||
[(MipsJmpLink RC:$rs)], IIBranch, FrmR>;
|
[(MipsJmpLink RC:$rs)], IIBranch, FrmR>;
|
||||||
|
|
||||||
class BGEZAL_FT<string opstr, RegisterClass RC> :
|
class BGEZAL_FT<string opstr, RegisterOperand RO> :
|
||||||
InstSE<(outs), (ins RC:$rs, brtarget:$offset),
|
InstSE<(outs), (ins RO:$rs, brtarget:$offset),
|
||||||
!strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI>;
|
!strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI>;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -585,19 +585,19 @@ class SYNC_FT :
|
|||||||
NoItinerary, FrmOther>;
|
NoItinerary, FrmOther>;
|
||||||
|
|
||||||
// Mul, Div
|
// Mul, Div
|
||||||
class Mult<string opstr, InstrItinClass itin, RegisterClass RC,
|
class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
|
||||||
list<Register> DefRegs> :
|
list<Register> DefRegs> :
|
||||||
InstSE<(outs), (ins RC:$rs, RC:$rt), !strconcat(opstr, "\t$rs, $rt"), [],
|
InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rs, $rt"), [],
|
||||||
itin, FrmR> {
|
itin, FrmR> {
|
||||||
let isCommutable = 1;
|
let isCommutable = 1;
|
||||||
let Defs = DefRegs;
|
let Defs = DefRegs;
|
||||||
let neverHasSideEffects = 1;
|
let neverHasSideEffects = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Div<SDNode op, string opstr, InstrItinClass itin, RegisterClass RC,
|
class Div<SDNode op, string opstr, InstrItinClass itin, RegisterOperand RO,
|
||||||
list<Register> DefRegs> :
|
list<Register> DefRegs> :
|
||||||
InstSE<(outs), (ins RC:$rs, RC:$rt),
|
InstSE<(outs), (ins RO:$rs, RO:$rt),
|
||||||
!strconcat(opstr, "\t$$zero, $rs, $rt"), [(op RC:$rs, RC:$rt)], itin,
|
!strconcat(opstr, "\t$$zero, $rs, $rt"), [(op RO:$rs, RO:$rt)], itin,
|
||||||
FrmR> {
|
FrmR> {
|
||||||
let Defs = DefRegs;
|
let Defs = DefRegs;
|
||||||
}
|
}
|
||||||
@@ -623,14 +623,14 @@ class EffectiveAddress<string opstr, RegisterClass RC, Operand Mem> :
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Count Leading Ones/Zeros in Word
|
// Count Leading Ones/Zeros in Word
|
||||||
class CountLeading0<string opstr, RegisterClass RC>:
|
class CountLeading0<string opstr, RegisterOperand RO>:
|
||||||
InstSE<(outs RC:$rd), (ins RC:$rs), !strconcat(opstr, "\t$rd, $rs"),
|
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
|
||||||
[(set RC:$rd, (ctlz RC:$rs))], IIAlu, FrmR>,
|
[(set RO:$rd, (ctlz RO:$rs))], IIAlu, FrmR>,
|
||||||
Requires<[HasBitCount, HasStdEnc]>;
|
Requires<[HasBitCount, HasStdEnc]>;
|
||||||
|
|
||||||
class CountLeading1<string opstr, RegisterClass RC>:
|
class CountLeading1<string opstr, RegisterOperand RO>:
|
||||||
InstSE<(outs RC:$rd), (ins RC:$rs), !strconcat(opstr, "\t$rd, $rs"),
|
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
|
||||||
[(set RC:$rd, (ctlz (not RC:$rs)))], IIAlu, FrmR>,
|
[(set RO:$rd, (ctlz (not RO:$rs)))], IIAlu, FrmR>,
|
||||||
Requires<[HasBitCount, HasStdEnc]>;
|
Requires<[HasBitCount, HasStdEnc]>;
|
||||||
|
|
||||||
|
|
||||||
@@ -642,31 +642,31 @@ class SignExtInReg<string opstr, ValueType vt, RegisterClass RC> :
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Subword Swap
|
// Subword Swap
|
||||||
class SubwordSwap<string opstr, RegisterClass RC>:
|
class SubwordSwap<string opstr, RegisterOperand RO>:
|
||||||
InstSE<(outs RC:$rd), (ins RC:$rt), !strconcat(opstr, "\t$rd, $rt"), [],
|
InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [],
|
||||||
NoItinerary, FrmR> {
|
NoItinerary, FrmR> {
|
||||||
let Predicates = [HasSwap, HasStdEnc];
|
let Predicates = [HasSwap, HasStdEnc];
|
||||||
let neverHasSideEffects = 1;
|
let neverHasSideEffects = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Hardware
|
// Read Hardware
|
||||||
class ReadHardware<RegisterClass CPURegClass, RegisterClass HWRegClass> :
|
class ReadHardware<RegisterClass CPURegClass, RegisterOperand RO> :
|
||||||
InstSE<(outs CPURegClass:$rt), (ins HWRegClass:$rd), "rdhwr\t$rt, $rd", [],
|
InstSE<(outs CPURegClass:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [],
|
||||||
IIAlu, FrmR>;
|
IIAlu, FrmR>;
|
||||||
|
|
||||||
// Ext and Ins
|
// Ext and Ins
|
||||||
class ExtBase<string opstr, RegisterClass RC>:
|
class ExtBase<string opstr, RegisterOperand RO>:
|
||||||
InstSE<(outs RC:$rt), (ins RC:$rs, uimm16:$pos, size_ext:$size),
|
InstSE<(outs RO:$rt), (ins RO:$rs, uimm16:$pos, size_ext:$size),
|
||||||
!strconcat(opstr, " $rt, $rs, $pos, $size"),
|
!strconcat(opstr, " $rt, $rs, $pos, $size"),
|
||||||
[(set RC:$rt, (MipsExt RC:$rs, imm:$pos, imm:$size))], NoItinerary,
|
[(set RO:$rt, (MipsExt RO:$rs, imm:$pos, imm:$size))], NoItinerary,
|
||||||
FrmR> {
|
FrmR> {
|
||||||
let Predicates = [HasMips32r2, HasStdEnc];
|
let Predicates = [HasMips32r2, HasStdEnc];
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsBase<string opstr, RegisterClass RC>:
|
class InsBase<string opstr, RegisterOperand RO>:
|
||||||
InstSE<(outs RC:$rt), (ins RC:$rs, uimm16:$pos, size_ins:$size, RC:$src),
|
InstSE<(outs RO:$rt), (ins RO:$rs, uimm16:$pos, size_ins:$size, RO:$src),
|
||||||
!strconcat(opstr, " $rt, $rs, $pos, $size"),
|
!strconcat(opstr, " $rt, $rs, $pos, $size"),
|
||||||
[(set RC:$rt, (MipsIns RC:$rs, imm:$pos, imm:$size, RC:$src))],
|
[(set RO:$rt, (MipsIns RO:$rs, imm:$pos, imm:$size, RO:$src))],
|
||||||
NoItinerary, FrmR> {
|
NoItinerary, FrmR> {
|
||||||
let Predicates = [HasMips32r2, HasStdEnc];
|
let Predicates = [HasMips32r2, HasStdEnc];
|
||||||
let Constraints = "$src = $rt";
|
let Constraints = "$src = $rt";
|
||||||
@@ -699,15 +699,15 @@ multiclass AtomicCmpSwap32<PatFrag Op> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLBase<string opstr, RegisterClass RC, Operand Mem> :
|
class LLBase<string opstr, RegisterOperand RO, Operand Mem> :
|
||||||
InstSE<(outs RC:$rt), (ins Mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
|
InstSE<(outs RO:$rt), (ins Mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
|
||||||
[], NoItinerary, FrmI> {
|
[], NoItinerary, FrmI> {
|
||||||
let DecoderMethod = "DecodeMem";
|
let DecoderMethod = "DecodeMem";
|
||||||
let mayLoad = 1;
|
let mayLoad = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SCBase<string opstr, RegisterClass RC, Operand Mem> :
|
class SCBase<string opstr, RegisterOperand RO, Operand Mem> :
|
||||||
InstSE<(outs RC:$dst), (ins RC:$rt, Mem:$addr),
|
InstSE<(outs RO:$dst), (ins RO:$rt, Mem:$addr),
|
||||||
!strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
|
!strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
|
||||||
let DecoderMethod = "DecodeMem";
|
let DecoderMethod = "DecodeMem";
|
||||||
let mayStore = 1;
|
let mayStore = 1;
|
||||||
@@ -769,42 +769,42 @@ let usesCustomInserter = 1 in {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// Arithmetic Instructions (ALU Immediate)
|
/// Arithmetic Instructions (ALU Immediate)
|
||||||
def ADDiu : ArithLogicI<"addiu", simm16, CPURegs, immSExt16, add>,
|
def ADDiu : ArithLogicI<"addiu", simm16, CPURegsOpnd, immSExt16, add>,
|
||||||
ADDI_FM<0x9>, IsAsCheapAsAMove;
|
ADDI_FM<0x9>, IsAsCheapAsAMove;
|
||||||
def ADDi : ArithLogicI<"addi", simm16, CPURegs>, ADDI_FM<0x8>;
|
def ADDi : ArithLogicI<"addi", simm16, CPURegsOpnd>, ADDI_FM<0x8>;
|
||||||
def SLTi : SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>, SLTI_FM<0xa>;
|
def SLTi : SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>, SLTI_FM<0xa>;
|
||||||
def SLTiu : SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>, SLTI_FM<0xb>;
|
def SLTiu : SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>, SLTI_FM<0xb>;
|
||||||
def ANDi : ArithLogicI<"andi", uimm16, CPURegs, immZExt16, and>, ADDI_FM<0xc>;
|
def ANDi : ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>, ADDI_FM<0xc>;
|
||||||
def ORi : ArithLogicI<"ori", uimm16, CPURegs, immZExt16, or>, ADDI_FM<0xd>;
|
def ORi : ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>, ADDI_FM<0xd>;
|
||||||
def XORi : ArithLogicI<"xori", uimm16, CPURegs, immZExt16, xor>, ADDI_FM<0xe>;
|
def XORi : ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>, ADDI_FM<0xe>;
|
||||||
def LUi : LoadUpper<"lui", CPURegs, uimm16>, LUI_FM;
|
def LUi : LoadUpper<"lui", CPURegs, uimm16>, LUI_FM;
|
||||||
|
|
||||||
/// Arithmetic Instructions (3-Operand, R-Type)
|
/// Arithmetic Instructions (3-Operand, R-Type)
|
||||||
def ADDu : ArithLogicR<"addu", CPURegs, 1, IIAlu, add>, ADD_FM<0, 0x21>;
|
def ADDu : ArithLogicR<"addu", CPURegsOpnd, 1, IIAlu, add>, ADD_FM<0, 0x21>;
|
||||||
def SUBu : ArithLogicR<"subu", CPURegs, 0, IIAlu, sub>, ADD_FM<0, 0x23>;
|
def SUBu : ArithLogicR<"subu", CPURegsOpnd, 0, IIAlu, sub>, ADD_FM<0, 0x23>;
|
||||||
def MUL : ArithLogicR<"mul", CPURegs, 1, IIImul, mul>, ADD_FM<0x1c, 2>;
|
def MUL : ArithLogicR<"mul", CPURegsOpnd, 1, IIImul, mul>, ADD_FM<0x1c, 2>;
|
||||||
def ADD : ArithLogicR<"add", CPURegs>, ADD_FM<0, 0x20>;
|
def ADD : ArithLogicR<"add", CPURegsOpnd>, ADD_FM<0, 0x20>;
|
||||||
def SUB : ArithLogicR<"sub", CPURegs>, ADD_FM<0, 0x22>;
|
def SUB : ArithLogicR<"sub", CPURegsOpnd>, ADD_FM<0, 0x22>;
|
||||||
def SLT : SetCC_R<"slt", setlt, CPURegs>, ADD_FM<0, 0x2a>;
|
def SLT : SetCC_R<"slt", setlt, CPURegs>, ADD_FM<0, 0x2a>;
|
||||||
def SLTu : SetCC_R<"sltu", setult, CPURegs>, ADD_FM<0, 0x2b>;
|
def SLTu : SetCC_R<"sltu", setult, CPURegs>, ADD_FM<0, 0x2b>;
|
||||||
def AND : ArithLogicR<"and", CPURegs, 1, IIAlu, and>, ADD_FM<0, 0x24>;
|
def AND : ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>, ADD_FM<0, 0x24>;
|
||||||
def OR : ArithLogicR<"or", CPURegs, 1, IIAlu, or>, ADD_FM<0, 0x25>;
|
def OR : ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>, ADD_FM<0, 0x25>;
|
||||||
def XOR : ArithLogicR<"xor", CPURegs, 1, IIAlu, xor>, ADD_FM<0, 0x26>;
|
def XOR : ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>, ADD_FM<0, 0x26>;
|
||||||
def NOR : LogicNOR<"nor", CPURegs>, ADD_FM<0, 0x27>;
|
def NOR : LogicNOR<"nor", CPURegsOpnd>, ADD_FM<0, 0x27>;
|
||||||
|
|
||||||
/// Shift Instructions
|
/// Shift Instructions
|
||||||
def SLL : shift_rotate_imm<"sll", shamt, CPURegs, shl, immZExt5>, SRA_FM<0, 0>;
|
def SLL : shift_rotate_imm<"sll", shamt, CPURegsOpnd, shl, immZExt5>, SRA_FM<0, 0>;
|
||||||
def SRL : shift_rotate_imm<"srl", shamt, CPURegs, srl, immZExt5>, SRA_FM<2, 0>;
|
def SRL : shift_rotate_imm<"srl", shamt, CPURegsOpnd, srl, immZExt5>, SRA_FM<2, 0>;
|
||||||
def SRA : shift_rotate_imm<"sra", shamt, CPURegs, sra, immZExt5>, SRA_FM<3, 0>;
|
def SRA : shift_rotate_imm<"sra", shamt, CPURegsOpnd, sra, immZExt5>, SRA_FM<3, 0>;
|
||||||
def SLLV : shift_rotate_reg<"sllv", CPURegs, shl>, SRLV_FM<4, 0>;
|
def SLLV : shift_rotate_reg<"sllv", CPURegsOpnd, shl>, SRLV_FM<4, 0>;
|
||||||
def SRLV : shift_rotate_reg<"srlv", CPURegs, srl>, SRLV_FM<6, 0>;
|
def SRLV : shift_rotate_reg<"srlv", CPURegsOpnd, srl>, SRLV_FM<6, 0>;
|
||||||
def SRAV : shift_rotate_reg<"srav", CPURegs, sra>, SRLV_FM<7, 0>;
|
def SRAV : shift_rotate_reg<"srav", CPURegsOpnd, sra>, SRLV_FM<7, 0>;
|
||||||
|
|
||||||
// Rotate Instructions
|
// Rotate Instructions
|
||||||
let Predicates = [HasMips32r2, HasStdEnc] in {
|
let Predicates = [HasMips32r2, HasStdEnc] in {
|
||||||
def ROTR : shift_rotate_imm<"rotr", shamt, CPURegs, rotr, immZExt5>,
|
def ROTR : shift_rotate_imm<"rotr", shamt, CPURegsOpnd, rotr, immZExt5>,
|
||||||
SRA_FM<2, 1>;
|
SRA_FM<2, 1>;
|
||||||
def ROTRV : shift_rotate_reg<"rotrv", CPURegs, rotr>, SRLV_FM<6, 1>;
|
def ROTRV : shift_rotate_reg<"rotrv", CPURegsOpnd, rotr>, SRLV_FM<6, 1>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load and Store Instructions
|
/// Load and Store Instructions
|
||||||
@@ -828,13 +828,13 @@ def SYNC : SYNC_FT, SYNC_FM;
|
|||||||
|
|
||||||
/// Load-linked, Store-conditional
|
/// Load-linked, Store-conditional
|
||||||
let Predicates = [NotN64, HasStdEnc] in {
|
let Predicates = [NotN64, HasStdEnc] in {
|
||||||
def LL : LLBase<"ll", CPURegs, mem>, LW_FM<0x30>;
|
def LL : LLBase<"ll", CPURegsOpnd, mem>, LW_FM<0x30>;
|
||||||
def SC : SCBase<"sc", CPURegs, mem>, LW_FM<0x38>;
|
def SC : SCBase<"sc", CPURegsOpnd, mem>, LW_FM<0x38>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Predicates = [IsN64, HasStdEnc], DecoderNamespace = "Mips64" in {
|
let Predicates = [IsN64, HasStdEnc], DecoderNamespace = "Mips64" in {
|
||||||
def LL_P8 : LLBase<"ll", CPURegs, mem64>, LW_FM<0x30>;
|
def LL_P8 : LLBase<"ll", CPURegsOpnd, mem64>, LW_FM<0x30>;
|
||||||
def SC_P8 : SCBase<"sc", CPURegs, mem64>, LW_FM<0x38>;
|
def SC_P8 : SCBase<"sc", CPURegsOpnd, mem64>, LW_FM<0x38>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Jump and Branch Instructions
|
/// Jump and Branch Instructions
|
||||||
@@ -853,18 +853,18 @@ def BAL_BR: BAL_FT, BAL_FM;
|
|||||||
|
|
||||||
def JAL : JumpLink<"jal">, FJ<3>;
|
def JAL : JumpLink<"jal">, FJ<3>;
|
||||||
def JALR : JumpLinkReg<"jalr", CPURegs>, JALR_FM;
|
def JALR : JumpLinkReg<"jalr", CPURegs>, JALR_FM;
|
||||||
def BGEZAL : BGEZAL_FT<"bgezal", CPURegs>, BGEZAL_FM<0x11>;
|
def BGEZAL : BGEZAL_FT<"bgezal", CPURegsOpnd>, BGEZAL_FM<0x11>;
|
||||||
def BLTZAL : BGEZAL_FT<"bltzal", CPURegs>, BGEZAL_FM<0x10>;
|
def BLTZAL : BGEZAL_FT<"bltzal", CPURegsOpnd>, BGEZAL_FM<0x10>;
|
||||||
def TAILCALL : JumpFJ<calltarget, "j", MipsTailCall, imm>, FJ<2>, IsTailCall;
|
def TAILCALL : JumpFJ<calltarget, "j", MipsTailCall, imm>, FJ<2>, IsTailCall;
|
||||||
def TAILCALL_R : JumpFR<CPURegs, MipsTailCall>, MTLO_FM<8>, IsTailCall;
|
def TAILCALL_R : JumpFR<CPURegs, MipsTailCall>, MTLO_FM<8>, IsTailCall;
|
||||||
|
|
||||||
def RET : RetBase<CPURegs>, MTLO_FM<8>;
|
def RET : RetBase<CPURegs>, MTLO_FM<8>;
|
||||||
|
|
||||||
/// Multiply and Divide Instructions.
|
/// Multiply and Divide Instructions.
|
||||||
def MULT : Mult<"mult", IIImul, CPURegs, [HI, LO]>, MULT_FM<0, 0x18>;
|
def MULT : Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x18>;
|
||||||
def MULTu : Mult<"multu", IIImul, CPURegs, [HI, LO]>, MULT_FM<0, 0x19>;
|
def MULTu : Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x19>;
|
||||||
def SDIV : Div<MipsDivRem, "div", IIIdiv, CPURegs, [HI, LO]>, MULT_FM<0, 0x1a>;
|
def SDIV : Div<MipsDivRem, "div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>;
|
||||||
def UDIV : Div<MipsDivRemU, "divu", IIIdiv, CPURegs, [HI, LO]>,
|
def UDIV : Div<MipsDivRemU, "divu", IIIdiv, CPURegsOpnd, [HI, LO]>,
|
||||||
MULT_FM<0, 0x1b>;
|
MULT_FM<0, 0x1b>;
|
||||||
|
|
||||||
def MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
|
def MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
|
||||||
@@ -877,11 +877,11 @@ def SEB : SignExtInReg<"seb", i8, CPURegs>, SEB_FM<0x10, 0x20>;
|
|||||||
def SEH : SignExtInReg<"seh", i16, CPURegs>, SEB_FM<0x18, 0x20>;
|
def SEH : SignExtInReg<"seh", i16, CPURegs>, SEB_FM<0x18, 0x20>;
|
||||||
|
|
||||||
/// Count Leading
|
/// Count Leading
|
||||||
def CLZ : CountLeading0<"clz", CPURegs>, CLO_FM<0x20>;
|
def CLZ : CountLeading0<"clz", CPURegsOpnd>, CLO_FM<0x20>;
|
||||||
def CLO : CountLeading1<"clo", CPURegs>, CLO_FM<0x21>;
|
def CLO : CountLeading1<"clo", CPURegsOpnd>, CLO_FM<0x21>;
|
||||||
|
|
||||||
/// Word Swap Bytes Within Halfwords
|
/// Word Swap Bytes Within Halfwords
|
||||||
def WSBH : SubwordSwap<"wsbh", CPURegs>, SEB_FM<2, 0x20>;
|
def WSBH : SubwordSwap<"wsbh", CPURegsOpnd>, SEB_FM<2, 0x20>;
|
||||||
|
|
||||||
/// No operation.
|
/// No operation.
|
||||||
/// FIXME: NOP should be an alias of "sll $0, $0, 0".
|
/// FIXME: NOP should be an alias of "sll $0, $0, 0".
|
||||||
@@ -899,10 +899,10 @@ def MADDU : MArithR<"maddu", MipsMAddu, 1>, MULT_FM<0x1c, 1>;
|
|||||||
def MSUB : MArithR<"msub", MipsMSub>, MULT_FM<0x1c, 4>;
|
def MSUB : MArithR<"msub", MipsMSub>, MULT_FM<0x1c, 4>;
|
||||||
def MSUBU : MArithR<"msubu", MipsMSubu>, MULT_FM<0x1c, 5>;
|
def MSUBU : MArithR<"msubu", MipsMSubu>, MULT_FM<0x1c, 5>;
|
||||||
|
|
||||||
def RDHWR : ReadHardware<CPURegs, HWRegs>, RDHWR_FM;
|
def RDHWR : ReadHardware<CPURegs, HWRegsOpnd>, RDHWR_FM;
|
||||||
|
|
||||||
def EXT : ExtBase<"ext", CPURegs>, EXT_FM<0>;
|
def EXT : ExtBase<"ext", CPURegsOpnd>, EXT_FM<0>;
|
||||||
def INS : InsBase<"ins", CPURegs>, EXT_FM<4>;
|
def INS : InsBase<"ins", CPURegsOpnd>, EXT_FM<4>;
|
||||||
|
|
||||||
/// Move Control Registers From/To CPU Registers
|
/// Move Control Registers From/To CPU Registers
|
||||||
def MFC0_3OP : MFC3OP<(outs CPURegs:$rt), (ins CPURegs:$rd, uimm16:$sel),
|
def MFC0_3OP : MFC3OP<(outs CPURegs:$rt), (ins CPURegs:$rd, uimm16:$sel),
|
||||||
@@ -920,22 +920,25 @@ def MTC2_3OP : MFC3OP<(outs CPURegs:$rd, uimm16:$sel), (ins CPURegs:$rt),
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Instruction aliases
|
// Instruction aliases
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
def : InstAlias<"move $dst,$src", (ADD CPURegs:$dst,CPURegs:$src,ZERO)>;
|
def : InstAlias<"move $dst,$src", (ADDu CPURegsOpnd:$dst,
|
||||||
def : InstAlias<"bal $offset", (BGEZAL RA,brtarget:$offset)>;
|
CPURegsOpnd:$src,ZERO)>, Requires<[NotMips64]>;
|
||||||
def : InstAlias<"addu $rs,$rt,$imm",
|
def : InstAlias<"bal $offset", (BGEZAL RA, brtarget:$offset)>;
|
||||||
(ADDiu CPURegs:$rs,CPURegs:$rt,simm16:$imm)>;
|
def : InstAlias<"addu $rs, $rt, $imm",
|
||||||
def : InstAlias<"add $rs,$rt,$imm",
|
(ADDiu CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm)>;
|
||||||
(ADDi CPURegs:$rs,CPURegs:$rt,simm16:$imm)>;
|
def : InstAlias<"add $rs, $rt, $imm",
|
||||||
def : InstAlias<"and $rs,$rt,$imm",
|
(ADDi CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm)>;
|
||||||
(ANDi CPURegs:$rs,CPURegs:$rt,simm16:$imm)>;
|
def : InstAlias<"and $rs, $rt, $imm",
|
||||||
def : InstAlias<"j $rs", (JR CPURegs:$rs)>;
|
(ANDi CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm)>;
|
||||||
def : InstAlias<"not $rt,$rs", (NOR CPURegs:$rt,CPURegs:$rs,ZERO)>;
|
def : InstAlias<"j $rs", (JR CPURegs:$rs)>, Requires<[NotMips64]>;
|
||||||
def : InstAlias<"neg $rt,$rs", (SUB CPURegs:$rt,ZERO,CPURegs:$rs)>;
|
def : InstAlias<"not $rt, $rs", (NOR CPURegsOpnd:$rt, CPURegsOpnd:$rs, ZERO)>;
|
||||||
def : InstAlias<"negu $rt,$rs", (SUBu CPURegs:$rt,ZERO,CPURegs:$rs)>;
|
def : InstAlias<"neg $rt, $rs", (SUB CPURegsOpnd:$rt, ZERO, CPURegsOpnd:$rs)>;
|
||||||
def : InstAlias<"slt $rs,$rt,$imm",
|
def : InstAlias<"negu $rt, $rs", (SUBu CPURegsOpnd:$rt, ZERO,
|
||||||
(SLTi CPURegs:$rs,CPURegs:$rt,simm16:$imm)>;
|
CPURegsOpnd:$rs)>;
|
||||||
def : InstAlias<"xor $rs,$rt,$imm",
|
def : InstAlias<"slt $rs, $rt, $imm",
|
||||||
(XORi CPURegs:$rs,CPURegs:$rt,simm16:$imm)>;
|
(SLTi CPURegsOpnd:$rs, CPURegs:$rt, simm16:$imm)>;
|
||||||
|
def : InstAlias<"xor $rs, $rt, $imm",
|
||||||
|
(XORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm)>,
|
||||||
|
Requires<[NotMips64]>;
|
||||||
def : InstAlias<"mfc0 $rt, $rd", (MFC0_3OP CPURegs:$rt, CPURegs:$rd, 0)>;
|
def : InstAlias<"mfc0 $rt, $rd", (MFC0_3OP CPURegs:$rt, CPURegs:$rd, 0)>;
|
||||||
def : InstAlias<"mtc0 $rt, $rd", (MTC0_3OP CPURegs:$rd, 0, CPURegs:$rt)>;
|
def : InstAlias<"mtc0 $rt, $rd", (MTC0_3OP CPURegs:$rd, 0, CPURegs:$rt)>;
|
||||||
def : InstAlias<"mfc2 $rt, $rd", (MFC2_3OP CPURegs:$rt, CPURegs:$rd, 0)>;
|
def : InstAlias<"mfc2 $rt, $rd", (MFC2_3OP CPURegs:$rt, CPURegs:$rd, 0)>;
|
||||||
@@ -945,20 +948,20 @@ def : InstAlias<"mtc2 $rt, $rd", (MTC2_3OP CPURegs:$rd, 0, CPURegs:$rt)>;
|
|||||||
// Assembler Pseudo Instructions
|
// Assembler Pseudo Instructions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
class LoadImm32< string instr_asm, Operand Od, RegisterClass RC> :
|
class LoadImm32< string instr_asm, Operand Od, RegisterOperand RO> :
|
||||||
MipsAsmPseudoInst<(outs RC:$rt), (ins Od:$imm32),
|
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
|
||||||
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
||||||
def LoadImm32Reg : LoadImm32<"li", shamt,CPURegs>;
|
def LoadImm32Reg : LoadImm32<"li", shamt,CPURegsOpnd>;
|
||||||
|
|
||||||
class LoadAddress<string instr_asm, Operand MemOpnd, RegisterClass RC> :
|
class LoadAddress<string instr_asm, Operand MemOpnd, RegisterOperand RO> :
|
||||||
MipsAsmPseudoInst<(outs RC:$rt), (ins MemOpnd:$addr),
|
MipsAsmPseudoInst<(outs RO:$rt), (ins MemOpnd:$addr),
|
||||||
!strconcat(instr_asm, "\t$rt, $addr")> ;
|
!strconcat(instr_asm, "\t$rt, $addr")> ;
|
||||||
def LoadAddr32Reg : LoadAddress<"la", mem, CPURegs>;
|
def LoadAddr32Reg : LoadAddress<"la", mem, CPURegsOpnd>;
|
||||||
|
|
||||||
class LoadAddressImm<string instr_asm, Operand Od, RegisterClass RC> :
|
class LoadAddressImm<string instr_asm, Operand Od, RegisterOperand RO> :
|
||||||
MipsAsmPseudoInst<(outs RC:$rt), (ins Od:$imm32),
|
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
|
||||||
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
!strconcat(instr_asm, "\t$rt, $imm32")> ;
|
||||||
def LoadAddr32Imm : LoadAddressImm<"la", shamt,CPURegs>;
|
def LoadAddr32Imm : LoadAddressImm<"la", shamt,CPURegsOpnd>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1045,7 +1048,7 @@ def : WrapperPat<tglobaltlsaddr, ADDiu, CPURegs>;
|
|||||||
|
|
||||||
// Mips does not have "not", so we expand our way
|
// Mips does not have "not", so we expand our way
|
||||||
def : MipsPat<(not CPURegs:$in),
|
def : MipsPat<(not CPURegs:$in),
|
||||||
(NOR CPURegs:$in, ZERO)>;
|
(NOR CPURegsOpnd:$in, ZERO)>;
|
||||||
|
|
||||||
// extended loads
|
// extended loads
|
||||||
let Predicates = [NotN64, HasStdEnc] in {
|
let Predicates = [NotN64, HasStdEnc] in {
|
||||||
|
@@ -331,3 +331,48 @@ def HWRegs64 : RegisterClass<"Mips", [i64], 32, (add HWR29_64)>;
|
|||||||
|
|
||||||
// Accumulator Registers
|
// Accumulator Registers
|
||||||
def ACRegs : RegisterClass<"Mips", [i64], 64, (sequence "AC%u", 0, 3)>;
|
def ACRegs : RegisterClass<"Mips", [i64], 64, (sequence "AC%u", 0, 3)>;
|
||||||
|
|
||||||
|
def CPURegsAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "CPURegsAsm";
|
||||||
|
let ParserMethod = "parseCPURegs";
|
||||||
|
}
|
||||||
|
|
||||||
|
def CPU64RegsAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "CPU64RegsAsm";
|
||||||
|
let ParserMethod = "parseCPU64Regs";
|
||||||
|
}
|
||||||
|
|
||||||
|
def CCRAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "CCRAsm";
|
||||||
|
let ParserMethod = "parseCCRRegs";
|
||||||
|
}
|
||||||
|
|
||||||
|
def CPURegsOpnd : RegisterOperand<CPURegs, "printCPURegs"> {
|
||||||
|
let ParserMatchClass = CPURegsAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
def CPU64RegsOpnd : RegisterOperand<CPU64Regs, "printCPURegs"> {
|
||||||
|
let ParserMatchClass = CPU64RegsAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
def CCROpnd : RegisterOperand<CCR, "printCPURegs"> {
|
||||||
|
let ParserMatchClass = CCRAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
def HWRegsAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "HWRegsAsm";
|
||||||
|
let ParserMethod = "parseHWRegs";
|
||||||
|
}
|
||||||
|
|
||||||
|
def HW64RegsAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "HW64RegsAsm";
|
||||||
|
let ParserMethod = "parseHW64Regs";
|
||||||
|
}
|
||||||
|
|
||||||
|
def HWRegsOpnd : RegisterOperand<HWRegs, "printCPURegs"> {
|
||||||
|
let ParserMatchClass = HWRegsAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
def HW64RegsOpnd : RegisterOperand<HWRegs, "printCPURegs"> {
|
||||||
|
let ParserMatchClass = HW64RegsAsmOperand;
|
||||||
|
}
|
||||||
|
@@ -80,7 +80,7 @@
|
|||||||
# CHECK: subu $4, $3, $5 # encoding: [0x23,0x20,0x65,0x00]
|
# CHECK: subu $4, $3, $5 # encoding: [0x23,0x20,0x65,0x00]
|
||||||
# CHECK: sub $6, $zero, $7 # encoding: [0x22,0x30,0x07,0x00]
|
# CHECK: sub $6, $zero, $7 # encoding: [0x22,0x30,0x07,0x00]
|
||||||
# CHECK: subu $6, $zero, $7 # encoding: [0x23,0x30,0x07,0x00]
|
# CHECK: subu $6, $zero, $7 # encoding: [0x23,0x30,0x07,0x00]
|
||||||
# CHECK: add $7, $8, $zero # encoding: [0x20,0x38,0x00,0x01]
|
# CHECK: addu $7, $8, $zero # encoding: [0x21,0x38,0x00,0x01]
|
||||||
add $9,$6,$7
|
add $9,$6,$7
|
||||||
add $9,$6,17767
|
add $9,$6,17767
|
||||||
addu $9,$6,-15001
|
addu $9,$6,-15001
|
||||||
|
94
test/MC/Mips/mips64-alu-instructions.s
Normal file
94
test/MC/Mips/mips64-alu-instructions.s
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding -mcpu=mips64r2 | FileCheck %s
|
||||||
|
# Check that the assembler can handle the documented syntax
|
||||||
|
# for arithmetic and logical instructions.
|
||||||
|
# CHECK: .section __TEXT,__text,regular,pure_instructions
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Logical instructions
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# CHECK: and $9, $6, $7 # encoding: [0x24,0x48,0xc7,0x00]
|
||||||
|
# CHECK: andi $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x30]
|
||||||
|
# CHECK: andi $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x30]
|
||||||
|
# CHECK: clo $6, $7 # encoding: [0x21,0x30,0xe6,0x70]
|
||||||
|
# CHECK: clz $6, $7 # encoding: [0x20,0x30,0xe6,0x70]
|
||||||
|
# CHECK: ins $19, $9, 6, 7 # encoding: [0x84,0x61,0x33,0x7d]
|
||||||
|
# CHECK: nor $9, $6, $7 # encoding: [0x27,0x48,0xc7,0x00]
|
||||||
|
# CHECK: or $3, $3, $5 # encoding: [0x25,0x18,0x65,0x00]
|
||||||
|
# CHECK: ori $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x34]
|
||||||
|
# CHECK: rotr $9, $6, 7 # encoding: [0xc2,0x49,0x26,0x00]
|
||||||
|
# CHECK: rotrv $9, $6, $7 # encoding: [0x46,0x48,0xe6,0x00]
|
||||||
|
# CHECK: sll $4, $3, 7 # encoding: [0xc0,0x21,0x03,0x00]
|
||||||
|
# CHECK: sllv $2, $3, $5 # encoding: [0x04,0x10,0xa3,0x00]
|
||||||
|
# CHECK: slt $3, $3, $5 # encoding: [0x2a,0x18,0x65,0x00]
|
||||||
|
# CHECK: slti $3, $3, 103 # encoding: [0x67,0x00,0x63,0x28]
|
||||||
|
# CHECK: slti $3, $3, 103 # encoding: [0x67,0x00,0x63,0x28]
|
||||||
|
# CHECK: sltiu $3, $3, 103 # encoding: [0x67,0x00,0x63,0x2c]
|
||||||
|
# CHECK: sltu $3, $3, $5 # encoding: [0x2b,0x18,0x65,0x00]
|
||||||
|
# CHECK: sra $4, $3, 7 # encoding: [0xc3,0x21,0x03,0x00]
|
||||||
|
# CHECK: srav $2, $3, $5 # encoding: [0x07,0x10,0xa3,0x00]
|
||||||
|
# CHECK: srl $4, $3, 7 # encoding: [0xc2,0x21,0x03,0x00]
|
||||||
|
# CHECK: srlv $2, $3, $5 # encoding: [0x06,0x10,0xa3,0x00]
|
||||||
|
# CHECK: xor $3, $3, $5 # encoding: [0x26,0x18,0x65,0x00]
|
||||||
|
# CHECK: xori $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x38]
|
||||||
|
# CHECK: xori $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x38]
|
||||||
|
# CHECK: wsbh $6, $7 # encoding: [0xa0,0x30,0x07,0x7c]
|
||||||
|
# CHECK: nor $7, $8, $zero # encoding: [0x27,0x38,0x00,0x01]
|
||||||
|
and $9, $6, $7
|
||||||
|
and $9, $6, 17767
|
||||||
|
andi $9, $6, 17767
|
||||||
|
clo $6, $7
|
||||||
|
clz $6, $7
|
||||||
|
ins $19, $9, 6,7
|
||||||
|
nor $9, $6, $7
|
||||||
|
or $3, $3, $5
|
||||||
|
ori $9, $6, 17767
|
||||||
|
rotr $9, $6, 7
|
||||||
|
rotrv $9, $6, $7
|
||||||
|
sll $4, $3, 7
|
||||||
|
sllv $2, $3, $5
|
||||||
|
slt $3, $3, $5
|
||||||
|
slt $3, $3, 103
|
||||||
|
slti $3, $3, 103
|
||||||
|
sltiu $3, $3, 103
|
||||||
|
sltu $3, $3, $5
|
||||||
|
sra $4, $3, 7
|
||||||
|
srav $2, $3, $5
|
||||||
|
srl $4, $3, 7
|
||||||
|
srlv $2, $3, $5
|
||||||
|
xor $3, $3, $5
|
||||||
|
xor $9, $6, 17767
|
||||||
|
xori $9, $6, 17767
|
||||||
|
wsbh $6, $7
|
||||||
|
not $7 ,$8
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Arithmetic instructions
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# CHECK: dadd $9, $6, $7 # encoding: [0x2c,0x48,0xc7,0x00]
|
||||||
|
# CHECK: daddi $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x60]
|
||||||
|
# CHECK: daddiu $9, $6, -15001 # encoding: [0x67,0xc5,0xc9,0x64]
|
||||||
|
# CHECK: daddi $9, $6, 17767 # encoding: [0x67,0x45,0xc9,0x60]
|
||||||
|
# CHECK: daddiu $9, $6, -15001 # encoding: [0x67,0xc5,0xc9,0x64]
|
||||||
|
# CHECK: daddu $9, $6, $7 # encoding: [0x2d,0x48,0xc7,0x00]
|
||||||
|
# CHECK: madd $6, $7 # encoding: [0x00,0x00,0xc7,0x70]
|
||||||
|
# CHECK: maddu $6, $7 # encoding: [0x01,0x00,0xc7,0x70]
|
||||||
|
# CHECK: msub $6, $7 # encoding: [0x04,0x00,0xc7,0x70]
|
||||||
|
# CHECK: msubu $6, $7 # encoding: [0x05,0x00,0xc7,0x70]
|
||||||
|
# CHECK: mult $3, $5 # encoding: [0x18,0x00,0x65,0x00]
|
||||||
|
# CHECK: multu $3, $5 # encoding: [0x19,0x00,0x65,0x00]
|
||||||
|
# CHECK: dsubu $4, $3, $5 # encoding: [0x2f,0x20,0x65,0x00]
|
||||||
|
# CHECK: daddu $7, $8, $zero # encoding: [0x2d,0x38,0x00,0x01]
|
||||||
|
dadd $9,$6,$7
|
||||||
|
dadd $9,$6,17767
|
||||||
|
daddu $9,$6,-15001
|
||||||
|
daddi $9,$6,17767
|
||||||
|
daddiu $9,$6,-15001
|
||||||
|
daddu $9,$6,$7
|
||||||
|
madd $6,$7
|
||||||
|
maddu $6,$7
|
||||||
|
msub $6,$7
|
||||||
|
msubu $6,$7
|
||||||
|
mult $3,$5
|
||||||
|
multu $3,$5
|
||||||
|
dsubu $4,$3,$5
|
||||||
|
move $7,$8
|
Reference in New Issue
Block a user