forked from OSchip/llvm-project
[VE] Support branch instructions in MC layer
Summary: Add regression tests of asmparser, mccodeemitter, and disassembler for branch instructions. In order to support them, we enhance asmparser by adding splitting mnemonic mechanism, e.g. "bgt.l.t" into "b", "gt", and ".l.t", and parsing mechanism for AS style memory addressing. We also implment encoding and decoding mechanism for branch instructions. Differential Revision: https://reviews.llvm.org/D81215
This commit is contained in:
parent
39ff53984d
commit
117c0d7c1c
|
@ -67,9 +67,14 @@ class VEAsmParser : public MCTargetAsmParser {
|
||||||
|
|
||||||
// Custom parse functions for VE specific operands.
|
// Custom parse functions for VE specific operands.
|
||||||
OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
|
OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
|
||||||
|
OperandMatchResultTy parseMEMAsOperand(OperandVector &Operands);
|
||||||
|
OperandMatchResultTy parseCCOpOperand(OperandVector &Operands);
|
||||||
OperandMatchResultTy parseMImmOperand(OperandVector &Operands);
|
OperandMatchResultTy parseMImmOperand(OperandVector &Operands);
|
||||||
OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
|
OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
|
||||||
OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
|
OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
|
||||||
|
// Split the mnemonic stripping conditional code and quantifiers
|
||||||
|
StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
|
||||||
|
OperandVector *Operands);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
|
VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
|
||||||
|
@ -121,8 +126,12 @@ private:
|
||||||
k_MemoryRegImmImm, // base=reg, index=imm, disp=imm
|
k_MemoryRegImmImm, // base=reg, index=imm, disp=imm
|
||||||
k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
|
k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
|
||||||
k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
|
k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
|
||||||
k_MImmOp, // Special immediate value of sequential bit stream
|
// SX-Aurora AS form is disp(base).
|
||||||
// of 0 or 1.
|
k_MemoryRegImm, // base=reg, disp=imm
|
||||||
|
k_MemoryZeroImm, // base=0, disp=imm
|
||||||
|
// Other special cases for Aurora VE
|
||||||
|
k_CCOp, // condition code
|
||||||
|
k_MImmOp, // Special immediate value of sequential bit stream of 0 or 1.
|
||||||
} Kind;
|
} Kind;
|
||||||
|
|
||||||
SMLoc StartLoc, EndLoc;
|
SMLoc StartLoc, EndLoc;
|
||||||
|
@ -147,6 +156,10 @@ private:
|
||||||
const MCExpr *Offset;
|
const MCExpr *Offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CCOp {
|
||||||
|
unsigned CCVal;
|
||||||
|
};
|
||||||
|
|
||||||
struct MImmOp {
|
struct MImmOp {
|
||||||
const MCExpr *Val;
|
const MCExpr *Val;
|
||||||
bool M0Flag;
|
bool M0Flag;
|
||||||
|
@ -157,6 +170,7 @@ private:
|
||||||
struct RegOp Reg;
|
struct RegOp Reg;
|
||||||
struct ImmOp Imm;
|
struct ImmOp Imm;
|
||||||
struct MemOp Mem;
|
struct MemOp Mem;
|
||||||
|
struct CCOp CC;
|
||||||
struct MImmOp MImm;
|
struct MImmOp MImm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -174,9 +188,9 @@ public:
|
||||||
bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }
|
bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }
|
||||||
bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }
|
bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }
|
||||||
bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }
|
bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }
|
||||||
// isMEMri and isMEMzi will be implemented later.
|
bool isMEMri() const { return Kind == k_MemoryRegImm; }
|
||||||
bool isMEMri() const { return false; }
|
bool isMEMzi() const { return Kind == k_MemoryZeroImm; }
|
||||||
bool isMEMzi() const { return false; }
|
bool isCCOp() const { return Kind == k_CCOp; }
|
||||||
bool isSImm7() {
|
bool isSImm7() {
|
||||||
if (!isImm())
|
if (!isImm())
|
||||||
return false;
|
return false;
|
||||||
|
@ -216,7 +230,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getMemBase() const {
|
unsigned getMemBase() const {
|
||||||
assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm) &&
|
assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
|
||||||
|
Kind == k_MemoryRegImm) &&
|
||||||
"Invalid access!");
|
"Invalid access!");
|
||||||
return Mem.Base;
|
return Mem.Base;
|
||||||
}
|
}
|
||||||
|
@ -235,18 +250,25 @@ public:
|
||||||
|
|
||||||
const MCExpr *getMemOffset() const {
|
const MCExpr *getMemOffset() const {
|
||||||
assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
|
assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
|
||||||
Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm) &&
|
Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm ||
|
||||||
|
Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) &&
|
||||||
"Invalid access!");
|
"Invalid access!");
|
||||||
return Mem.Offset;
|
return Mem.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMemOffset(const MCExpr *off) {
|
void setMemOffset(const MCExpr *off) {
|
||||||
assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
|
assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
|
||||||
Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm) &&
|
Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm ||
|
||||||
|
Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) &&
|
||||||
"Invalid access!");
|
"Invalid access!");
|
||||||
Mem.Offset = off;
|
Mem.Offset = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned getCCVal() const {
|
||||||
|
assert((Kind == k_CCOp) && "Invalid access!");
|
||||||
|
return CC.CCVal;
|
||||||
|
}
|
||||||
|
|
||||||
const MCExpr *getMImmVal() const {
|
const MCExpr *getMImmVal() const {
|
||||||
assert((Kind == k_MImmOp) && "Invalid access!");
|
assert((Kind == k_MImmOp) && "Invalid access!");
|
||||||
return MImm.Val;
|
return MImm.Val;
|
||||||
|
@ -290,6 +312,17 @@ public:
|
||||||
assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
|
assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
|
||||||
OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
|
OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
|
||||||
break;
|
break;
|
||||||
|
case k_MemoryRegImm:
|
||||||
|
assert(getMemOffset() != nullptr);
|
||||||
|
OS << "Mem: #" << getMemBase() << "+" << *getMemOffset() << "\n";
|
||||||
|
break;
|
||||||
|
case k_MemoryZeroImm:
|
||||||
|
assert(getMemOffset() != nullptr);
|
||||||
|
OS << "Mem: 0+" << *getMemOffset() << "\n";
|
||||||
|
break;
|
||||||
|
case k_CCOp:
|
||||||
|
OS << "CCOp: " << getCCVal() << "\n";
|
||||||
|
break;
|
||||||
case k_MImmOp:
|
case k_MImmOp:
|
||||||
OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1") << "\n";
|
OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1") << "\n";
|
||||||
break;
|
break;
|
||||||
|
@ -354,11 +387,23 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMEMriOperands(MCInst &Inst, unsigned N) const {
|
void addMEMriOperands(MCInst &Inst, unsigned N) const {
|
||||||
// FIXME: implement
|
assert(N == 2 && "Invalid number of operands!");
|
||||||
|
|
||||||
|
Inst.addOperand(MCOperand::createReg(getMemBase()));
|
||||||
|
addExpr(Inst, getMemOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMEMziOperands(MCInst &Inst, unsigned N) const {
|
void addMEMziOperands(MCInst &Inst, unsigned N) const {
|
||||||
// FIXME: implement
|
assert(N == 2 && "Invalid number of operands!");
|
||||||
|
|
||||||
|
Inst.addOperand(MCOperand::createImm(0));
|
||||||
|
addExpr(Inst, getMemOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCCOpOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
|
||||||
|
Inst.addOperand(MCOperand::createImm(getCCVal()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMImmOperands(MCInst &Inst, unsigned N) const {
|
void addMImmOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
@ -398,6 +443,15 @@ public:
|
||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<VEOperand> CreateCCOp(unsigned CCVal, SMLoc S,
|
||||||
|
SMLoc E) {
|
||||||
|
auto Op = std::make_unique<VEOperand>(k_CCOp);
|
||||||
|
Op->CC.CCVal = CCVal;
|
||||||
|
Op->StartLoc = S;
|
||||||
|
Op->EndLoc = E;
|
||||||
|
return Op;
|
||||||
|
}
|
||||||
|
|
||||||
static std::unique_ptr<VEOperand> CreateMImm(const MCExpr *Val, bool Flag,
|
static std::unique_ptr<VEOperand> CreateMImm(const MCExpr *Val, bool Flag,
|
||||||
SMLoc S, SMLoc E) {
|
SMLoc S, SMLoc E) {
|
||||||
auto Op = std::make_unique<VEOperand>(k_MImmOp);
|
auto Op = std::make_unique<VEOperand>(k_MImmOp);
|
||||||
|
@ -426,6 +480,28 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<VEOperand>
|
||||||
|
MorphToMEMri(unsigned Base, std::unique_ptr<VEOperand> Op) {
|
||||||
|
const MCExpr *Imm = Op->getImm();
|
||||||
|
Op->Kind = k_MemoryRegImm;
|
||||||
|
Op->Mem.Base = Base;
|
||||||
|
Op->Mem.IndexReg = 0;
|
||||||
|
Op->Mem.Index = nullptr;
|
||||||
|
Op->Mem.Offset = Imm;
|
||||||
|
return Op;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<VEOperand>
|
||||||
|
MorphToMEMzi(std::unique_ptr<VEOperand> Op) {
|
||||||
|
const MCExpr *Imm = Op->getImm();
|
||||||
|
Op->Kind = k_MemoryZeroImm;
|
||||||
|
Op->Mem.Base = 0;
|
||||||
|
Op->Mem.IndexReg = 0;
|
||||||
|
Op->Mem.Index = nullptr;
|
||||||
|
Op->Mem.Offset = Imm;
|
||||||
|
return Op;
|
||||||
|
}
|
||||||
|
|
||||||
static std::unique_ptr<VEOperand>
|
static std::unique_ptr<VEOperand>
|
||||||
MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {
|
MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {
|
||||||
const MCExpr *Imm = Op->getImm();
|
const MCExpr *Imm = Op->getImm();
|
||||||
|
@ -564,15 +640,72 @@ VEAsmParser::tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
|
||||||
return MatchOperand_NoMatch;
|
return MatchOperand_NoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static StringRef parseCC(StringRef Name, unsigned Prefix, unsigned Suffix,
|
||||||
|
bool IntegerCC, bool OmitCC, SMLoc NameLoc,
|
||||||
|
OperandVector *Operands) {
|
||||||
|
// Parse instructions with a conditional code. For example, 'bne' is
|
||||||
|
// converted into two operands 'b' and 'ne'.
|
||||||
|
StringRef Cond = Name.slice(Prefix, Suffix);
|
||||||
|
VECC::CondCode CondCode =
|
||||||
|
IntegerCC ? stringToVEICondCode(Cond) : stringToVEFCondCode(Cond);
|
||||||
|
|
||||||
|
// If OmitCC is enabled, CC_AT and CC_AF is treated as a part of mnemonic.
|
||||||
|
if (CondCode != VECC::UNKNOWN &&
|
||||||
|
(!OmitCC || (CondCode != VECC::CC_AT && CondCode != VECC::CC_AF))) {
|
||||||
|
StringRef SuffixStr = Name.substr(Suffix);
|
||||||
|
// Push "b".
|
||||||
|
Name = Name.slice(0, Prefix);
|
||||||
|
Operands->push_back(VEOperand::CreateToken(Name, NameLoc));
|
||||||
|
// Push $cond part.
|
||||||
|
SMLoc CondLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Prefix);
|
||||||
|
SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Suffix);
|
||||||
|
Operands->push_back(VEOperand::CreateCCOp(CondCode, CondLoc, SuffixLoc));
|
||||||
|
// push suffix like ".l.t"
|
||||||
|
if (!SuffixStr.empty())
|
||||||
|
Operands->push_back(VEOperand::CreateToken(SuffixStr, SuffixLoc));
|
||||||
|
} else {
|
||||||
|
Operands->push_back(VEOperand::CreateToken(Name, NameLoc));
|
||||||
|
}
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the mnemonic into ASM operand, conditional code and instruction
|
||||||
|
// qualifier (half-word, byte).
|
||||||
|
StringRef VEAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
|
||||||
|
OperandVector *Operands) {
|
||||||
|
// Create the leading tokens for the mnemonic
|
||||||
|
StringRef Mnemonic = Name;
|
||||||
|
|
||||||
|
if (Name[0] == 'b') {
|
||||||
|
// Match b?? or br??.
|
||||||
|
size_t Start = 1;
|
||||||
|
size_t Next = Name.find('.');
|
||||||
|
// Adjust position of CondCode.
|
||||||
|
if (Name.size() > 1 && Name[1] == 'r')
|
||||||
|
Start = 2;
|
||||||
|
// Check suffix.
|
||||||
|
bool ICC = true;
|
||||||
|
if (Next + 1 < Name.size() &&
|
||||||
|
(Name[Next + 1] == 'd' || Name[Next + 1] == 's'))
|
||||||
|
ICC = false;
|
||||||
|
Mnemonic = parseCC(Name, Start, Next, ICC, true, NameLoc, Operands);
|
||||||
|
} else {
|
||||||
|
Operands->push_back(VEOperand::CreateToken(Mnemonic, NameLoc));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mnemonic;
|
||||||
|
}
|
||||||
|
|
||||||
bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||||
SMLoc NameLoc, OperandVector &Operands) {
|
SMLoc NameLoc, OperandVector &Operands) {
|
||||||
|
// Split name to first token and the rest, e.g. "bgt.l.t" to "b", "gt", and
|
||||||
// First operand in MCInst is instruction mnemonic.
|
// ".l.t". We treat "b" as a mnemonic, "gt" as first operand, and ".l.t"
|
||||||
Operands.push_back(VEOperand::CreateToken(Name, NameLoc));
|
// as second operand.
|
||||||
|
StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
|
||||||
|
|
||||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||||
// Read the first operand.
|
// Read the first operand.
|
||||||
if (parseOperand(Operands, Name) != MatchOperand_Success) {
|
if (parseOperand(Operands, Mnemonic) != MatchOperand_Success) {
|
||||||
SMLoc Loc = getLexer().getLoc();
|
SMLoc Loc = getLexer().getLoc();
|
||||||
return Error(Loc, "unexpected token");
|
return Error(Loc, "unexpected token");
|
||||||
}
|
}
|
||||||
|
@ -580,7 +713,7 @@ bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||||
while (getLexer().is(AsmToken::Comma)) {
|
while (getLexer().is(AsmToken::Comma)) {
|
||||||
Parser.Lex(); // Eat the comma.
|
Parser.Lex(); // Eat the comma.
|
||||||
// Parse and remember the operand.
|
// Parse and remember the operand.
|
||||||
if (parseOperand(Operands, Name) != MatchOperand_Success) {
|
if (parseOperand(Operands, Mnemonic) != MatchOperand_Success) {
|
||||||
SMLoc Loc = getLexer().getLoc();
|
SMLoc Loc = getLexer().getLoc();
|
||||||
return Error(Loc, "unexpected token");
|
return Error(Loc, "unexpected token");
|
||||||
}
|
}
|
||||||
|
@ -703,6 +836,96 @@ OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
|
||||||
return MatchOperand_Success;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OperandMatchResultTy VEAsmParser::parseMEMAsOperand(OperandVector &Operands) {
|
||||||
|
LLVM_DEBUG(dbgs() << "parseMEMAsOperand\n");
|
||||||
|
const AsmToken &Tok = Parser.getTok();
|
||||||
|
SMLoc S = Tok.getLoc();
|
||||||
|
SMLoc E = Tok.getEndLoc();
|
||||||
|
// Parse AS format
|
||||||
|
// disp
|
||||||
|
// disp(, base)
|
||||||
|
// disp(base)
|
||||||
|
// disp()
|
||||||
|
// (, base)
|
||||||
|
// (base)
|
||||||
|
// base
|
||||||
|
|
||||||
|
unsigned BaseReg = VE::NoRegister;
|
||||||
|
std::unique_ptr<VEOperand> Offset;
|
||||||
|
switch (getLexer().getKind()) {
|
||||||
|
default:
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
|
||||||
|
case AsmToken::Minus:
|
||||||
|
case AsmToken::Integer:
|
||||||
|
case AsmToken::Dot: {
|
||||||
|
const MCExpr *EVal;
|
||||||
|
if (!getParser().parseExpression(EVal, E))
|
||||||
|
Offset = VEOperand::CreateImm(EVal, S, E);
|
||||||
|
else
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case AsmToken::Percent:
|
||||||
|
if (ParseRegister(BaseReg, S, E))
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
Offset =
|
||||||
|
VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AsmToken::LParen:
|
||||||
|
// empty disp (= 0)
|
||||||
|
Offset =
|
||||||
|
VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (getLexer().getKind()) {
|
||||||
|
default:
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
|
case AsmToken::EndOfStatement:
|
||||||
|
case AsmToken::Comma:
|
||||||
|
Operands.push_back(BaseReg != VE::NoRegister
|
||||||
|
? VEOperand::MorphToMEMri(BaseReg, std::move(Offset))
|
||||||
|
: VEOperand::MorphToMEMzi(std::move(Offset)));
|
||||||
|
return MatchOperand_Success;
|
||||||
|
|
||||||
|
case AsmToken::LParen:
|
||||||
|
if (BaseReg != VE::NoRegister)
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
Parser.Lex(); // Eat the (
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (getLexer().getKind()) {
|
||||||
|
default:
|
||||||
|
if (ParseRegister(BaseReg, S, E))
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AsmToken::Comma:
|
||||||
|
Parser.Lex(); // Eat the ,
|
||||||
|
if (ParseRegister(BaseReg, S, E))
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AsmToken::RParen:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Parser.getTok().is(AsmToken::RParen))
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
|
||||||
|
Parser.Lex(); // Eat the )
|
||||||
|
Operands.push_back(BaseReg != VE::NoRegister
|
||||||
|
? VEOperand::MorphToMEMri(BaseReg, std::move(Offset))
|
||||||
|
: VEOperand::MorphToMEMzi(std::move(Offset)));
|
||||||
|
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
OperandMatchResultTy VEAsmParser::parseMImmOperand(OperandVector &Operands) {
|
OperandMatchResultTy VEAsmParser::parseMImmOperand(OperandVector &Operands) {
|
||||||
LLVM_DEBUG(dbgs() << "parseMImmOperand\n");
|
LLVM_DEBUG(dbgs() << "parseMImmOperand\n");
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,18 @@ static DecodeStatus DecodeLoadF32(MCInst &Inst, uint64_t insn, uint64_t Address,
|
||||||
const void *Decoder);
|
const void *Decoder);
|
||||||
static DecodeStatus DecodeStoreF32(MCInst &Inst, uint64_t insn,
|
static DecodeStatus DecodeStoreF32(MCInst &Inst, uint64_t insn,
|
||||||
uint64_t Address, const void *Decoder);
|
uint64_t Address, const void *Decoder);
|
||||||
|
static DecodeStatus DecodeCall(MCInst &Inst, uint64_t insn, uint64_t Address,
|
||||||
|
const void *Decoder);
|
||||||
static DecodeStatus DecodeSIMM7(MCInst &Inst, uint64_t insn, uint64_t Address,
|
static DecodeStatus DecodeSIMM7(MCInst &Inst, uint64_t insn, uint64_t Address,
|
||||||
const void *Decoder);
|
const void *Decoder);
|
||||||
|
static DecodeStatus DecodeCCOperand(MCInst &Inst, uint64_t insn,
|
||||||
|
uint64_t Address, const void *Decoder);
|
||||||
|
static DecodeStatus DecodeBranchCondition(MCInst &Inst, uint64_t insn,
|
||||||
|
uint64_t Address,
|
||||||
|
const void *Decoder);
|
||||||
|
static DecodeStatus DecodeBranchConditionAlways(MCInst &Inst, uint64_t insn,
|
||||||
|
uint64_t Address,
|
||||||
|
const void *Decoder);
|
||||||
|
|
||||||
#include "VEGenDisassemblerTables.inc"
|
#include "VEGenDisassemblerTables.inc"
|
||||||
|
|
||||||
|
@ -218,6 +228,28 @@ static DecodeStatus DecodeASX(MCInst &MI, uint64_t insn, uint64_t Address,
|
||||||
return MCDisassembler::Success;
|
return MCDisassembler::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DecodeStatus DecodeAS(MCInst &MI, uint64_t insn, uint64_t Address,
|
||||||
|
const void *Decoder) {
|
||||||
|
unsigned sz = fieldFromInstruction(insn, 32, 7);
|
||||||
|
bool cz = fieldFromInstruction(insn, 39, 1);
|
||||||
|
uint64_t simm32 = SignExtend64<32>(fieldFromInstruction(insn, 0, 32));
|
||||||
|
DecodeStatus status;
|
||||||
|
|
||||||
|
// Decode sz.
|
||||||
|
if (cz) {
|
||||||
|
status = DecodeI64RegisterClass(MI, sz, Address, Decoder);
|
||||||
|
if (status != MCDisassembler::Success)
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
MI.addOperand(MCOperand::createImm(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode simm32.
|
||||||
|
MI.addOperand(MCOperand::createImm(simm32));
|
||||||
|
|
||||||
|
return MCDisassembler::Success;
|
||||||
|
}
|
||||||
|
|
||||||
static DecodeStatus DecodeMem(MCInst &MI, uint64_t insn, uint64_t Address,
|
static DecodeStatus DecodeMem(MCInst &MI, uint64_t insn, uint64_t Address,
|
||||||
const void *Decoder, bool isLoad,
|
const void *Decoder, bool isLoad,
|
||||||
DecodeFunc DecodeSX) {
|
DecodeFunc DecodeSX) {
|
||||||
|
@ -272,9 +304,89 @@ static DecodeStatus DecodeStoreF32(MCInst &Inst, uint64_t insn,
|
||||||
return DecodeMem(Inst, insn, Address, Decoder, false, DecodeF32RegisterClass);
|
return DecodeMem(Inst, insn, Address, Decoder, false, DecodeF32RegisterClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DecodeStatus DecodeCall(MCInst &Inst, uint64_t insn, uint64_t Address,
|
||||||
|
const void *Decoder) {
|
||||||
|
return DecodeMem(Inst, insn, Address, Decoder, true, DecodeI64RegisterClass);
|
||||||
|
}
|
||||||
|
|
||||||
static DecodeStatus DecodeSIMM7(MCInst &MI, uint64_t insn, uint64_t Address,
|
static DecodeStatus DecodeSIMM7(MCInst &MI, uint64_t insn, uint64_t Address,
|
||||||
const void *Decoder) {
|
const void *Decoder) {
|
||||||
uint64_t tgt = SignExtend64<7>(insn);
|
uint64_t tgt = SignExtend64<7>(insn);
|
||||||
MI.addOperand(MCOperand::createImm(tgt));
|
MI.addOperand(MCOperand::createImm(tgt));
|
||||||
return MCDisassembler::Success;
|
return MCDisassembler::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isIntegerBCKind(MCInst &MI) {
|
||||||
|
|
||||||
|
#define BCm_kind(NAME) \
|
||||||
|
case NAME##rri: \
|
||||||
|
case NAME##rzi: \
|
||||||
|
case NAME##iri: \
|
||||||
|
case NAME##izi: \
|
||||||
|
case NAME##rri_nt: \
|
||||||
|
case NAME##rzi_nt: \
|
||||||
|
case NAME##iri_nt: \
|
||||||
|
case NAME##izi_nt: \
|
||||||
|
case NAME##rri_t: \
|
||||||
|
case NAME##rzi_t: \
|
||||||
|
case NAME##iri_t: \
|
||||||
|
case NAME##izi_t:
|
||||||
|
|
||||||
|
#define BCRm_kind(NAME) \
|
||||||
|
case NAME##rr: \
|
||||||
|
case NAME##ir: \
|
||||||
|
case NAME##rr_nt: \
|
||||||
|
case NAME##ir_nt: \
|
||||||
|
case NAME##rr_t: \
|
||||||
|
case NAME##ir_t:
|
||||||
|
|
||||||
|
{
|
||||||
|
using namespace llvm::VE;
|
||||||
|
switch (MI.getOpcode()) {
|
||||||
|
BCm_kind(BCFL) BCm_kind(BCFW) BCRm_kind(BRCFL)
|
||||||
|
BCRm_kind(BRCFW) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef BCm_kind
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode CC Operand field.
|
||||||
|
static DecodeStatus DecodeCCOperand(MCInst &MI, uint64_t cf, uint64_t Address,
|
||||||
|
const void *Decoder) {
|
||||||
|
MI.addOperand(MCOperand::createImm(VEValToCondCode(cf, isIntegerBCKind(MI))));
|
||||||
|
return MCDisassembler::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode branch condition instruction and CCOperand field in it.
|
||||||
|
static DecodeStatus DecodeBranchCondition(MCInst &MI, uint64_t insn,
|
||||||
|
uint64_t Address,
|
||||||
|
const void *Decoder) {
|
||||||
|
unsigned cf = fieldFromInstruction(insn, 48, 4);
|
||||||
|
bool cy = fieldFromInstruction(insn, 47, 1);
|
||||||
|
unsigned sy = fieldFromInstruction(insn, 40, 7);
|
||||||
|
|
||||||
|
// Decode cf.
|
||||||
|
MI.addOperand(MCOperand::createImm(VEValToCondCode(cf, isIntegerBCKind(MI))));
|
||||||
|
|
||||||
|
// Decode sy.
|
||||||
|
DecodeStatus status;
|
||||||
|
if (cy) {
|
||||||
|
status = DecodeI64RegisterClass(MI, sy, Address, Decoder);
|
||||||
|
if (status != MCDisassembler::Success)
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
MI.addOperand(MCOperand::createImm(SignExtend32<7>(sy)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode MEMri.
|
||||||
|
return DecodeAS(MI, insn, Address, Decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DecodeStatus DecodeBranchConditionAlways(MCInst &MI, uint64_t insn,
|
||||||
|
uint64_t Address,
|
||||||
|
const void *Decoder) {
|
||||||
|
// Decode MEMri.
|
||||||
|
return DecodeAS(MI, insn, Address, Decoder);
|
||||||
|
}
|
||||||
|
|
|
@ -65,6 +65,10 @@ public:
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
const MCSubtargetInfo &STI) const;
|
const MCSubtargetInfo &STI) const;
|
||||||
|
|
||||||
|
uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
|
const MCSubtargetInfo &STI) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
|
FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
|
||||||
void
|
void
|
||||||
|
@ -112,6 +116,16 @@ unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
|
const MCSubtargetInfo &STI) const {
|
||||||
|
const MCOperand &MO = MI.getOperand(OpNo);
|
||||||
|
if (MO.isImm())
|
||||||
|
return VECondCodeToVal(
|
||||||
|
static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define ENABLE_INSTR_PREDICATE_VERIFIER
|
#define ENABLE_INSTR_PREDICATE_VERIFIER
|
||||||
#include "VEGenMCCodeEmitter.inc"
|
#include "VEGenMCCodeEmitter.inc"
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define LLVM_LIB_TARGET_VE_VE_H
|
#define LLVM_LIB_TARGET_VE_VE_H
|
||||||
|
|
||||||
#include "MCTargetDesc/VEMCTargetDesc.h"
|
#include "MCTargetDesc/VEMCTargetDesc.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
|
@ -63,6 +64,7 @@ enum CondCode {
|
||||||
CC_GENAN = 13 + 6, // Greater or Equal or NaN
|
CC_GENAN = 13 + 6, // Greater or Equal or NaN
|
||||||
CC_LENAN = 14 + 6, // Less or Equal or NaN
|
CC_LENAN = 14 + 6, // Less or Equal or NaN
|
||||||
CC_AT = 15 + 6, // Always
|
CC_AT = 15 + 6, // Always
|
||||||
|
UNKNOWN
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Enums corresponding to VE Rounding Mode. These values must be kept in
|
// Enums corresponding to VE Rounding Mode. These values must be kept in
|
||||||
|
@ -103,6 +105,153 @@ inline static const char *VECondCodeToString(VECC::CondCode CC) {
|
||||||
case VECC::CC_GENAN: return "genan";
|
case VECC::CC_GENAN: return "genan";
|
||||||
case VECC::CC_LENAN: return "lenan";
|
case VECC::CC_LENAN: return "lenan";
|
||||||
case VECC::CC_AT: return "at";
|
case VECC::CC_AT: return "at";
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Invalid cond code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static VECC::CondCode stringToVEICondCode(StringRef S) {
|
||||||
|
return StringSwitch<VECC::CondCode>(S)
|
||||||
|
.Case("gt", VECC::CC_IG)
|
||||||
|
.Case("lt", VECC::CC_IL)
|
||||||
|
.Case("ne", VECC::CC_INE)
|
||||||
|
.Case("eq", VECC::CC_IEQ)
|
||||||
|
.Case("ge", VECC::CC_IGE)
|
||||||
|
.Case("le", VECC::CC_ILE)
|
||||||
|
.Case("af", VECC::CC_AF)
|
||||||
|
.Case("at", VECC::CC_AT)
|
||||||
|
.Case("", VECC::CC_AT)
|
||||||
|
.Default(VECC::UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static VECC::CondCode stringToVEFCondCode(StringRef S) {
|
||||||
|
return StringSwitch<VECC::CondCode>(S)
|
||||||
|
.Case("gt", VECC::CC_G)
|
||||||
|
.Case("lt", VECC::CC_L)
|
||||||
|
.Case("ne", VECC::CC_NE)
|
||||||
|
.Case("eq", VECC::CC_EQ)
|
||||||
|
.Case("ge", VECC::CC_GE)
|
||||||
|
.Case("le", VECC::CC_LE)
|
||||||
|
.Case("num", VECC::CC_NUM)
|
||||||
|
.Case("nan", VECC::CC_NAN)
|
||||||
|
.Case("gtnan", VECC::CC_GNAN)
|
||||||
|
.Case("ltnan", VECC::CC_LNAN)
|
||||||
|
.Case("nenan", VECC::CC_NENAN)
|
||||||
|
.Case("eqnan", VECC::CC_EQNAN)
|
||||||
|
.Case("genan", VECC::CC_GENAN)
|
||||||
|
.Case("lenan", VECC::CC_LENAN)
|
||||||
|
.Case("af", VECC::CC_AF)
|
||||||
|
.Case("at", VECC::CC_AT)
|
||||||
|
.Case("", VECC::CC_AT)
|
||||||
|
.Default(VECC::UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static unsigned VECondCodeToVal(VECC::CondCode CC) {
|
||||||
|
switch (CC) {
|
||||||
|
case VECC::CC_IG:
|
||||||
|
return 1;
|
||||||
|
case VECC::CC_IL:
|
||||||
|
return 2;
|
||||||
|
case VECC::CC_INE:
|
||||||
|
return 3;
|
||||||
|
case VECC::CC_IEQ:
|
||||||
|
return 4;
|
||||||
|
case VECC::CC_IGE:
|
||||||
|
return 5;
|
||||||
|
case VECC::CC_ILE:
|
||||||
|
return 6;
|
||||||
|
case VECC::CC_AF:
|
||||||
|
return 0;
|
||||||
|
case VECC::CC_G:
|
||||||
|
return 1;
|
||||||
|
case VECC::CC_L:
|
||||||
|
return 2;
|
||||||
|
case VECC::CC_NE:
|
||||||
|
return 3;
|
||||||
|
case VECC::CC_EQ:
|
||||||
|
return 4;
|
||||||
|
case VECC::CC_GE:
|
||||||
|
return 5;
|
||||||
|
case VECC::CC_LE:
|
||||||
|
return 6;
|
||||||
|
case VECC::CC_NUM:
|
||||||
|
return 7;
|
||||||
|
case VECC::CC_NAN:
|
||||||
|
return 8;
|
||||||
|
case VECC::CC_GNAN:
|
||||||
|
return 9;
|
||||||
|
case VECC::CC_LNAN:
|
||||||
|
return 10;
|
||||||
|
case VECC::CC_NENAN:
|
||||||
|
return 11;
|
||||||
|
case VECC::CC_EQNAN:
|
||||||
|
return 12;
|
||||||
|
case VECC::CC_GENAN:
|
||||||
|
return 13;
|
||||||
|
case VECC::CC_LENAN:
|
||||||
|
return 14;
|
||||||
|
case VECC::CC_AT:
|
||||||
|
return 15;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Invalid cond code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static VECC::CondCode VEValToCondCode(unsigned Val, bool IsInteger) {
|
||||||
|
if (IsInteger) {
|
||||||
|
switch (Val) {
|
||||||
|
case 0:
|
||||||
|
return VECC::CC_AF;
|
||||||
|
case 1:
|
||||||
|
return VECC::CC_IG;
|
||||||
|
case 2:
|
||||||
|
return VECC::CC_IL;
|
||||||
|
case 3:
|
||||||
|
return VECC::CC_INE;
|
||||||
|
case 4:
|
||||||
|
return VECC::CC_IEQ;
|
||||||
|
case 5:
|
||||||
|
return VECC::CC_IGE;
|
||||||
|
case 6:
|
||||||
|
return VECC::CC_ILE;
|
||||||
|
case 15:
|
||||||
|
return VECC::CC_AT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (Val) {
|
||||||
|
case 0:
|
||||||
|
return VECC::CC_AF;
|
||||||
|
case 1:
|
||||||
|
return VECC::CC_G;
|
||||||
|
case 2:
|
||||||
|
return VECC::CC_L;
|
||||||
|
case 3:
|
||||||
|
return VECC::CC_NE;
|
||||||
|
case 4:
|
||||||
|
return VECC::CC_EQ;
|
||||||
|
case 5:
|
||||||
|
return VECC::CC_GE;
|
||||||
|
case 6:
|
||||||
|
return VECC::CC_LE;
|
||||||
|
case 7:
|
||||||
|
return VECC::CC_NUM;
|
||||||
|
case 8:
|
||||||
|
return VECC::CC_NAN;
|
||||||
|
case 9:
|
||||||
|
return VECC::CC_GNAN;
|
||||||
|
case 10:
|
||||||
|
return VECC::CC_LNAN;
|
||||||
|
case 11:
|
||||||
|
return VECC::CC_NENAN;
|
||||||
|
case 12:
|
||||||
|
return VECC::CC_EQNAN;
|
||||||
|
case 13:
|
||||||
|
return VECC::CC_GENAN;
|
||||||
|
case 14:
|
||||||
|
return VECC::CC_LENAN;
|
||||||
|
case 15:
|
||||||
|
return VECC::CC_AT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
llvm_unreachable("Invalid cond code");
|
llvm_unreachable("Invalid cond code");
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,28 +42,52 @@ static bool IsIntegerCC(unsigned CC) { return (CC < VECC::CC_AF); }
|
||||||
|
|
||||||
static VECC::CondCode GetOppositeBranchCondition(VECC::CondCode CC) {
|
static VECC::CondCode GetOppositeBranchCondition(VECC::CondCode CC) {
|
||||||
switch (CC) {
|
switch (CC) {
|
||||||
case VECC::CC_IG: return VECC::CC_ILE;
|
case VECC::CC_IG:
|
||||||
case VECC::CC_IL: return VECC::CC_IGE;
|
return VECC::CC_ILE;
|
||||||
case VECC::CC_INE: return VECC::CC_IEQ;
|
case VECC::CC_IL:
|
||||||
case VECC::CC_IEQ: return VECC::CC_INE;
|
return VECC::CC_IGE;
|
||||||
case VECC::CC_IGE: return VECC::CC_IL;
|
case VECC::CC_INE:
|
||||||
case VECC::CC_ILE: return VECC::CC_IG;
|
return VECC::CC_IEQ;
|
||||||
case VECC::CC_AF: return VECC::CC_AT;
|
case VECC::CC_IEQ:
|
||||||
case VECC::CC_G: return VECC::CC_LENAN;
|
return VECC::CC_INE;
|
||||||
case VECC::CC_L: return VECC::CC_GENAN;
|
case VECC::CC_IGE:
|
||||||
case VECC::CC_NE: return VECC::CC_EQNAN;
|
return VECC::CC_IL;
|
||||||
case VECC::CC_EQ: return VECC::CC_NENAN;
|
case VECC::CC_ILE:
|
||||||
case VECC::CC_GE: return VECC::CC_LNAN;
|
return VECC::CC_IG;
|
||||||
case VECC::CC_LE: return VECC::CC_GNAN;
|
case VECC::CC_AF:
|
||||||
case VECC::CC_NUM: return VECC::CC_NAN;
|
return VECC::CC_AT;
|
||||||
case VECC::CC_NAN: return VECC::CC_NUM;
|
case VECC::CC_G:
|
||||||
case VECC::CC_GNAN: return VECC::CC_LE;
|
return VECC::CC_LENAN;
|
||||||
case VECC::CC_LNAN: return VECC::CC_GE;
|
case VECC::CC_L:
|
||||||
case VECC::CC_NENAN: return VECC::CC_EQ;
|
return VECC::CC_GENAN;
|
||||||
case VECC::CC_EQNAN: return VECC::CC_NE;
|
case VECC::CC_NE:
|
||||||
case VECC::CC_GENAN: return VECC::CC_L;
|
return VECC::CC_EQNAN;
|
||||||
case VECC::CC_LENAN: return VECC::CC_G;
|
case VECC::CC_EQ:
|
||||||
case VECC::CC_AT: return VECC::CC_AF;
|
return VECC::CC_NENAN;
|
||||||
|
case VECC::CC_GE:
|
||||||
|
return VECC::CC_LNAN;
|
||||||
|
case VECC::CC_LE:
|
||||||
|
return VECC::CC_GNAN;
|
||||||
|
case VECC::CC_NUM:
|
||||||
|
return VECC::CC_NAN;
|
||||||
|
case VECC::CC_NAN:
|
||||||
|
return VECC::CC_NUM;
|
||||||
|
case VECC::CC_GNAN:
|
||||||
|
return VECC::CC_LE;
|
||||||
|
case VECC::CC_LNAN:
|
||||||
|
return VECC::CC_GE;
|
||||||
|
case VECC::CC_NENAN:
|
||||||
|
return VECC::CC_EQ;
|
||||||
|
case VECC::CC_EQNAN:
|
||||||
|
return VECC::CC_NE;
|
||||||
|
case VECC::CC_GENAN:
|
||||||
|
return VECC::CC_L;
|
||||||
|
case VECC::CC_LENAN:
|
||||||
|
return VECC::CC_G;
|
||||||
|
case VECC::CC_AT:
|
||||||
|
return VECC::CC_AF;
|
||||||
|
case VECC::UNKNOWN:
|
||||||
|
return VECC::UNKNOWN;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Invalid cond code");
|
llvm_unreachable("Invalid cond code");
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,11 @@ def fcond2ccSwap : SDNodeXForm<cond, [{
|
||||||
return CurDAG->getTargetConstant(VECC, SDLoc(N), MVT::i32);
|
return CurDAG->getTargetConstant(VECC, SDLoc(N), MVT::i32);
|
||||||
}]>;
|
}]>;
|
||||||
|
|
||||||
|
def CCOP : SDNodeXForm<imm, [{
|
||||||
|
return CurDAG->getTargetConstant(N->getZExtValue(),
|
||||||
|
SDLoc(N), MVT::i32);
|
||||||
|
}]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Feature predicates.
|
// Feature predicates.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -261,9 +266,11 @@ def MEMzii : Operand<iPTR> {
|
||||||
// AS assembly instruction format:
|
// AS assembly instruction format:
|
||||||
def VEMEMriAsmOperand : AsmOperandClass {
|
def VEMEMriAsmOperand : AsmOperandClass {
|
||||||
let Name = "MEMri";
|
let Name = "MEMri";
|
||||||
|
let ParserMethod = "parseMEMAsOperand";
|
||||||
}
|
}
|
||||||
def VEMEMziAsmOperand : AsmOperandClass {
|
def VEMEMziAsmOperand : AsmOperandClass {
|
||||||
let Name = "MEMzi";
|
let Name = "MEMzi";
|
||||||
|
let ParserMethod = "parseMEMAsOperand";
|
||||||
}
|
}
|
||||||
// AS generic assembly instruction format:
|
// AS generic assembly instruction format:
|
||||||
def MEMriASX : Operand<iPTR> {
|
def MEMriASX : Operand<iPTR> {
|
||||||
|
@ -290,8 +297,14 @@ def calltarget : Operand<i64> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operand for printing out a condition code.
|
// Operand for printing out a condition code.
|
||||||
let PrintMethod = "printCCOperand" in
|
def CCOpAsmOperand : AsmOperandClass { let Name = "CCOp"; }
|
||||||
def CCOp : Operand<i32>;
|
def CCOp : Operand<i32>, ImmLeaf<i32, [{
|
||||||
|
return Imm >= 0 && Imm < 22; }], CCOP> {
|
||||||
|
let PrintMethod = "printCCOperand";
|
||||||
|
let DecoderMethod = "DecodeCCOperand";
|
||||||
|
let EncoderMethod = "getCCOpValue";
|
||||||
|
let ParserMatchClass = CCOpAsmOperand;
|
||||||
|
}
|
||||||
|
|
||||||
// Operand for printing out a rounding mode code.
|
// Operand for printing out a rounding mode code.
|
||||||
def RDOp : Operand<i32> {
|
def RDOp : Operand<i32> {
|
||||||
|
@ -586,13 +599,14 @@ multiclass BCtgm<string opcStr, string cmpStr, bits<8> opc, dag cond> {
|
||||||
}
|
}
|
||||||
multiclass BCm<string opcStr, string opcStrAt, string opcStrAf, bits<8> opc,
|
multiclass BCm<string opcStr, string opcStrAt, string opcStrAf, bits<8> opc,
|
||||||
RegisterClass RC, Operand immOp> {
|
RegisterClass RC, Operand immOp> {
|
||||||
|
let DecoderMethod = "DecodeBranchCondition" in
|
||||||
defm r : BCtgm<opcStr, "$comp, ", opc, (ins CCOp:$cond, RC:$comp)>;
|
defm r : BCtgm<opcStr, "$comp, ", opc, (ins CCOp:$cond, RC:$comp)>;
|
||||||
let cy = 0 in
|
let DecoderMethod = "DecodeBranchCondition", cy = 0 in
|
||||||
defm i : BCtgm<opcStr, "$comp, ", opc, (ins CCOp:$cond, immOp:$comp)>;
|
defm i : BCtgm<opcStr, "$comp, ", opc, (ins CCOp:$cond, immOp:$comp)>;
|
||||||
let cy = 0, sy = 0,
|
let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0,
|
||||||
cf = 15 /* AT */, isBarrier = 1 in
|
cf = 15 /* AT */, isBarrier = 1 in
|
||||||
defm a : BCtgm<opcStrAt, "", opc, (ins)>;
|
defm a : BCtgm<opcStrAt, "", opc, (ins)>;
|
||||||
let cy = 0, sy = 0,
|
let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0,
|
||||||
cf = 0 /* AF */ in
|
cf = 0 /* AF */ in
|
||||||
defm na : BCtgm<opcStrAf, "", opc, (ins)>;
|
defm na : BCtgm<opcStrAf, "", opc, (ins)>;
|
||||||
}
|
}
|
||||||
|
@ -1044,7 +1058,7 @@ let cx = 1, cx2 = 1 in
|
||||||
defm BRCFS : BCRm<"br${cf}.s", "br.s", "braf.s", 0x18, F32, simm7fp>;
|
defm BRCFS : BCRm<"br${cf}.s", "br.s", "braf.s", 0x18, F32, simm7fp>;
|
||||||
|
|
||||||
// Section 8.8.5 - BSIC (Branch and Save IC)
|
// Section 8.8.5 - BSIC (Branch and Save IC)
|
||||||
let isCall = 1, hasSideEffects = 0 in
|
let isCall = 1, hasSideEffects = 0, DecoderMethod = "DecodeCall" in
|
||||||
defm BSIC : RMm<"bsic", 0x08, I64>;
|
defm BSIC : RMm<"bsic", 0x08, I64>;
|
||||||
|
|
||||||
// Call instruction is a special case of BSIC.
|
// Call instruction is a special case of BSIC.
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
# RUN: llvm-mc -triple=ve --show-encoding < %s \
|
||||||
|
# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
|
||||||
|
# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
|
||||||
|
# RUN: | FileCheck %s --check-prefixes=CHECK-INST
|
||||||
|
|
||||||
|
# CHECK-INST: b.l 8199
|
||||||
|
# CHECK-ENCODING: encoding: [0x07,0x20,0x00,0x00,0x00,0x00,0x0f,0x19]
|
||||||
|
b.l 8199
|
||||||
|
|
||||||
|
# CHECK-INST: b.l.t 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x00,0x3f,0x19]
|
||||||
|
b.l.t 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: baf.l.nt -1(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0xff,0xff,0xff,0xff,0x8b,0x00,0x20,0x19]
|
||||||
|
baf.l.nt -1(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: b.w.t 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x00,0x3f,0x1b]
|
||||||
|
b.w.t 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: baf.d.nt -1(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0xff,0xff,0xff,0xff,0x8b,0x00,0x20,0x1c]
|
||||||
|
baf.d.nt -1(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: b.s.t 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x00,0xbf,0x1c]
|
||||||
|
b.s.t 20(,%s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bgt.d %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x01,0x1c]
|
||||||
|
bgt.d %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bgt.l.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0x31,0x19]
|
||||||
|
bgt.l.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: bgt.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x21,0x1c]
|
||||||
|
bgt.d.nt %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: blt.w.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0x32,0x1b]
|
||||||
|
blt.w.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: blt.s.nt %s20, (, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x8b,0x94,0xa2,0x1c]
|
||||||
|
blt.s.nt %s20, (, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bne.l.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0x33,0x19]
|
||||||
|
bne.l.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: bne.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x23,0x1c]
|
||||||
|
bne.d.nt %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: beq.w.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0x34,0x1b]
|
||||||
|
beq.w.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: beq.s.nt %s20, (, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x8b,0x94,0xa4,0x1c]
|
||||||
|
beq.s.nt %s20, (,%s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bge.l.t 63, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x3f,0x35,0x19]
|
||||||
|
bge.l.t 63, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: bge.d.nt -64, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x40,0x25,0x1c]
|
||||||
|
bge.d.nt -64, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: ble.w.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0x36,0x1b]
|
||||||
|
ble.w.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: ble.s.nt %s20, (, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x8b,0x94,0xa6,0x1c]
|
||||||
|
ble.s.nt %s20, (,%s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bnum.s.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0xb7,0x1c]
|
||||||
|
bnum.s.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: bnum.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x27,0x1c]
|
||||||
|
bnum.d.nt %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bnan.s.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0xb8,0x1c]
|
||||||
|
bnan.s.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: bnan.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x28,0x1c]
|
||||||
|
bnan.d.nt %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bgtnan.s.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0xb9,0x1c]
|
||||||
|
bgtnan.s.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: bltnan.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x2a,0x1c]
|
||||||
|
bltnan.d.nt %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bnenan.s.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0xbb,0x1c]
|
||||||
|
bnenan.s.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: beqnan.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x2c,0x1c]
|
||||||
|
beqnan.d.nt %s20, 20(, %s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bgenan.s.t %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x00,0x94,0xbd,0x1c]
|
||||||
|
bgenan.s.t %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: blenan.d.nt %s20, 20(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x94,0x2e,0x1c]
|
||||||
|
blenan.d.nt %s20, 20(, %s11)
|
|
@ -0,0 +1,72 @@
|
||||||
|
# RUN: llvm-mc -triple=ve --show-encoding < %s \
|
||||||
|
# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
|
||||||
|
# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
|
||||||
|
# RUN: | FileCheck %s --check-prefixes=CHECK-INST
|
||||||
|
|
||||||
|
# CHECK-INST: br.l 8199
|
||||||
|
# CHECK-ENCODING: encoding: [0x07,0x20,0x00,0x00,0x00,0x00,0x0f,0x18]
|
||||||
|
br.l 8199
|
||||||
|
|
||||||
|
# CHECK-INST: br.w.t -224
|
||||||
|
# CHECK-ENCODING: encoding: [0x20,0xff,0xff,0xff,0x00,0x00,0xbf,0x18]
|
||||||
|
br.w.t -224
|
||||||
|
|
||||||
|
# CHECK-INST: braf.d.nt 224
|
||||||
|
# CHECK-ENCODING: encoding: [0xe0,0x00,0x00,0x00,0x00,0x00,0x60,0x18]
|
||||||
|
braf.d.nt 224
|
||||||
|
|
||||||
|
# CHECK-INST: brgt.s 23, %s20, 224
|
||||||
|
# CHECK-ENCODING: encoding: [0xe0,0x00,0x00,0x00,0x94,0x17,0xc1,0x18]
|
||||||
|
brgt.s 23, %s20, 224
|
||||||
|
|
||||||
|
# CHECK-INST: brlt.l.t 23, %s20, -224
|
||||||
|
# CHECK-ENCODING: encoding: [0x20,0xff,0xff,0xff,0x94,0x17,0x32,0x18]
|
||||||
|
brlt.l.t 23, %s20, -224
|
||||||
|
|
||||||
|
# CHECK-INST: brne.w.nt 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0xa3,0x18]
|
||||||
|
brne.w.nt 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: breq.d 23, %s20, -224
|
||||||
|
# CHECK-ENCODING: encoding: [0x20,0xff,0xff,0xff,0x94,0x17,0x44,0x18]
|
||||||
|
breq.d 23, %s20, -224
|
||||||
|
|
||||||
|
# CHECK-INST: brge.s.t 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0xf5,0x18]
|
||||||
|
brge.s.t 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brle.l.nt 23, %s20, 224
|
||||||
|
# CHECK-ENCODING: encoding: [0xe0,0x00,0x00,0x00,0x94,0x17,0x26,0x18]
|
||||||
|
brle.l.nt 23, %s20, 224
|
||||||
|
|
||||||
|
# CHECK-INST: brnum.d 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0x47,0x18]
|
||||||
|
brnum.d 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brnan.s.t 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0xf8,0x18]
|
||||||
|
brnan.s.t 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brgtnan.d.nt 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0x69,0x18]
|
||||||
|
brgtnan.d.nt 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brltnan.s 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0xca,0x18]
|
||||||
|
brltnan.s 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brnenan.d.t 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0x7b,0x18]
|
||||||
|
brnenan.d.t 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: breqnan.s.nt 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0xec,0x18]
|
||||||
|
breqnan.s.nt 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brgenan.d 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0x4d,0x18]
|
||||||
|
brgenan.d 23, %s20, 8192
|
||||||
|
|
||||||
|
# CHECK-INST: brlenan.s.t 23, %s20, 8192
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x20,0x00,0x00,0x94,0x17,0xfe,0x18]
|
||||||
|
brlenan.s.t 23, %s20, 8192
|
|
@ -0,0 +1,28 @@
|
||||||
|
# RUN: llvm-mc -triple=ve --show-encoding < %s \
|
||||||
|
# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
|
||||||
|
# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
|
||||||
|
# RUN: | FileCheck %s --check-prefixes=CHECK-INST
|
||||||
|
|
||||||
|
# CHECK-INST: bsic %s11, 23
|
||||||
|
# CHECK-ENCODING: encoding: [0x17,0x00,0x00,0x00,0x00,0x00,0x0b,0x08]
|
||||||
|
bsic %s11, 23
|
||||||
|
|
||||||
|
# CHECK-INST: bsic %s63, 324(, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x44,0x01,0x00,0x00,0x8b,0x00,0x3f,0x08]
|
||||||
|
bsic %s63, 324(,%s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bsic %s11, 324(%s10)
|
||||||
|
# CHECK-ENCODING: encoding: [0x44,0x01,0x00,0x00,0x00,0x8a,0x0b,0x08]
|
||||||
|
bsic %s11, 324(%s10 )
|
||||||
|
|
||||||
|
# CHECK-INST: bsic %s11, 324(%s13, %s11)
|
||||||
|
# CHECK-ENCODING: encoding: [0x44,0x01,0x00,0x00,0x8b,0x8d,0x0b,0x08]
|
||||||
|
bsic %s11, 324 (%s13,%s11)
|
||||||
|
|
||||||
|
# CHECK-INST: bsic %s11, (%s10)
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x00,0x8a,0x0b,0x08]
|
||||||
|
bsic %s11, (%s10)
|
||||||
|
|
||||||
|
# CHECK-INST: bsic %s11, (, %s12)
|
||||||
|
# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x8c,0x00,0x0b,0x08]
|
||||||
|
bsic %s11, (,%s12)
|
Loading…
Reference in New Issue