// Custom parse functions for VE specific operands.
OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
+ OperandMatchResultTy parseMEMAsOperand(OperandVector &Operands);
+ OperandMatchResultTy parseCCOpOperand(OperandVector &Operands);
OperandMatchResultTy parseMImmOperand(OperandVector &Operands);
OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
+ // Split the mnemonic stripping conditional code and quantifiers
+ StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
+ OperandVector *Operands);
public:
VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
k_MemoryRegImmImm, // base=reg, index=imm, disp=imm
k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
- k_MImmOp, // Special immediate value of sequential bit stream
- // of 0 or 1.
+ // SX-Aurora AS form is disp(base).
+ 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;
SMLoc StartLoc, EndLoc;
const MCExpr *Offset;
};
+ struct CCOp {
+ unsigned CCVal;
+ };
+
struct MImmOp {
const MCExpr *Val;
bool M0Flag;
struct RegOp Reg;
struct ImmOp Imm;
struct MemOp Mem;
+ struct CCOp CC;
struct MImmOp MImm;
};
bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }
bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }
bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }
- // isMEMri and isMEMzi will be implemented later.
- bool isMEMri() const { return false; }
- bool isMEMzi() const { return false; }
+ bool isMEMri() const { return Kind == k_MemoryRegImm; }
+ bool isMEMzi() const { return Kind == k_MemoryZeroImm; }
+ bool isCCOp() const { return Kind == k_CCOp; }
bool isSImm7() {
if (!isImm())
return false;
}
unsigned getMemBase() const {
- assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm) &&
+ assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
+ Kind == k_MemoryRegImm) &&
"Invalid access!");
return Mem.Base;
}
const MCExpr *getMemOffset() const {
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!");
return Mem.Offset;
}
void setMemOffset(const MCExpr *off) {
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!");
Mem.Offset = off;
}
+ unsigned getCCVal() const {
+ assert((Kind == k_CCOp) && "Invalid access!");
+ return CC.CCVal;
+ }
+
const MCExpr *getMImmVal() const {
assert((Kind == k_MImmOp) && "Invalid access!");
return MImm.Val;
assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
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:
OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1") << "\n";
break;
}
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 {
- // 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 {
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,
SMLoc S, SMLoc E) {
auto Op = std::make_unique<VEOperand>(k_MImmOp);
}
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>
MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {
const MCExpr *Imm = Op->getImm();
Op->Kind = k_MemoryRegRegImm;
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,
SMLoc NameLoc, OperandVector &Operands) {
-
- // First operand in MCInst is instruction mnemonic.
- Operands.push_back(VEOperand::CreateToken(Name, NameLoc));
+ // Split name to first token and the rest, e.g. "bgt.l.t" to "b", "gt", and
+ // ".l.t". We treat "b" as a mnemonic, "gt" as first operand, and ".l.t"
+ // as second operand.
+ StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand.
- if (parseOperand(Operands, Name) != MatchOperand_Success) {
+ if (parseOperand(Operands, Mnemonic) != MatchOperand_Success) {
SMLoc Loc = getLexer().getLoc();
return Error(Loc, "unexpected token");
}
while (getLexer().is(AsmToken::Comma)) {
Parser.Lex(); // Eat the comma.
// Parse and remember the operand.
- if (parseOperand(Operands, Name) != MatchOperand_Success) {
+ if (parseOperand(Operands, Mnemonic) != MatchOperand_Success) {
SMLoc Loc = getLexer().getLoc();
return Error(Loc, "unexpected token");
}
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) {
LLVM_DEBUG(dbgs() << "parseMImmOperand\n");
const void *Decoder);
static DecodeStatus DecodeStoreF32(MCInst &Inst, uint64_t insn,
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,
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"
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,
const void *Decoder, bool isLoad,
DecodeFunc DecodeSX) {
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,
const void *Decoder) {
uint64_t tgt = SignExtend64<7>(insn);
MI.addOperand(MCOperand::createImm(tgt));
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);
+}
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
private:
FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
void
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
#include "VEGenMCCodeEmitter.inc"
#define LLVM_LIB_TARGET_VE_VE_H
#include "MCTargetDesc/VEMCTargetDesc.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
namespace VECC {
enum CondCode {
// Integer comparison
- CC_IG = 0, // Greater
- CC_IL = 1, // Less
+ CC_IG = 0, // Greater
+ CC_IL = 1, // Less
CC_INE = 2, // Not Equal
CC_IEQ = 3, // Equal
CC_IGE = 4, // Greater or Equal
CC_ILE = 5, // Less or Equal
// Floating point comparison
- CC_AF = 0 + 6, // Never
- CC_G = 1 + 6, // Greater
- CC_L = 2 + 6, // Less
- CC_NE = 3 + 6, // Not Equal
- CC_EQ = 4 + 6, // Equal
- CC_GE = 5 + 6, // Greater or Equal
- CC_LE = 6 + 6, // Less or Equal
- CC_NUM = 7 + 6, // Number
- CC_NAN = 8 + 6, // NaN
- CC_GNAN = 9 + 6, // Greater or NaN
- CC_LNAN = 10 + 6, // Less or NaN
+ CC_AF = 0 + 6, // Never
+ CC_G = 1 + 6, // Greater
+ CC_L = 2 + 6, // Less
+ CC_NE = 3 + 6, // Not Equal
+ CC_EQ = 4 + 6, // Equal
+ CC_GE = 5 + 6, // Greater or Equal
+ CC_LE = 6 + 6, // Less or Equal
+ CC_NUM = 7 + 6, // Number
+ CC_NAN = 8 + 6, // NaN
+ CC_GNAN = 9 + 6, // Greater or NaN
+ CC_LNAN = 10 + 6, // Less or NaN
CC_NENAN = 11 + 6, // Not Equal or NaN
CC_EQNAN = 12 + 6, // Equal or NaN
CC_GENAN = 13 + 6, // Greater 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
case VECC::CC_GENAN: return "genan";
case VECC::CC_LENAN: return "lenan";
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");
}
static bool IsIntegerCC(unsigned CC) { return (CC < VECC::CC_AF); }
static VECC::CondCode GetOppositeBranchCondition(VECC::CondCode CC) {
- switch(CC) {
- case VECC::CC_IG: return VECC::CC_ILE;
- case VECC::CC_IL: return VECC::CC_IGE;
- case VECC::CC_INE: return VECC::CC_IEQ;
- case VECC::CC_IEQ: return VECC::CC_INE;
- case VECC::CC_IGE: return VECC::CC_IL;
- case VECC::CC_ILE: return VECC::CC_IG;
- case VECC::CC_AF: return VECC::CC_AT;
- case VECC::CC_G: return VECC::CC_LENAN;
- case VECC::CC_L: return VECC::CC_GENAN;
- case VECC::CC_NE: return VECC::CC_EQNAN;
- case VECC::CC_EQ: 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;
+ switch (CC) {
+ case VECC::CC_IG:
+ return VECC::CC_ILE;
+ case VECC::CC_IL:
+ return VECC::CC_IGE;
+ case VECC::CC_INE:
+ return VECC::CC_IEQ;
+ case VECC::CC_IEQ:
+ return VECC::CC_INE;
+ case VECC::CC_IGE:
+ return VECC::CC_IL;
+ case VECC::CC_ILE:
+ return VECC::CC_IG;
+ case VECC::CC_AF:
+ return VECC::CC_AT;
+ case VECC::CC_G:
+ return VECC::CC_LENAN;
+ case VECC::CC_L:
+ return VECC::CC_GENAN;
+ case VECC::CC_NE:
+ return VECC::CC_EQNAN;
+ case VECC::CC_EQ:
+ 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");
}
return CurDAG->getTargetConstant(VECC, SDLoc(N), MVT::i32);
}]>;
+def CCOP : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(N->getZExtValue(),
+ SDLoc(N), MVT::i32);
+}]>;
+
//===----------------------------------------------------------------------===//
// Feature predicates.
//===----------------------------------------------------------------------===//
// AS assembly instruction format:
def VEMEMriAsmOperand : AsmOperandClass {
let Name = "MEMri";
+ let ParserMethod = "parseMEMAsOperand";
}
def VEMEMziAsmOperand : AsmOperandClass {
let Name = "MEMzi";
+ let ParserMethod = "parseMEMAsOperand";
}
// AS generic assembly instruction format:
def MEMriASX : Operand<iPTR> {
}
// Operand for printing out a condition code.
-let PrintMethod = "printCCOperand" in
- def CCOp : Operand<i32>;
+def CCOpAsmOperand : AsmOperandClass { let Name = "CCOp"; }
+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.
def RDOp : Operand<i32> {
}
multiclass BCm<string opcStr, string opcStrAt, string opcStrAf, bits<8> opc,
RegisterClass RC, Operand immOp> {
+ let DecoderMethod = "DecodeBranchCondition" in
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)>;
- let cy = 0, sy = 0,
+ let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0,
cf = 15 /* AT */, isBarrier = 1 in
defm a : BCtgm<opcStrAt, "", opc, (ins)>;
- let cy = 0, sy = 0,
+ let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0,
cf = 0 /* AF */ in
defm na : BCtgm<opcStrAf, "", opc, (ins)>;
}
defm BRCFS : BCRm<"br${cf}.s", "br.s", "braf.s", 0x18, F32, simm7fp>;
// 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>;
// Call instruction is a special case of BSIC.
--- /dev/null
+# 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)
--- /dev/null
+# 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
--- /dev/null
+# 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)