diff --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp --- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp +++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp @@ -67,9 +67,14 @@ // 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 &Operand); + // Split the mnemonic stripping conditional code and quantifiers + StringRef splitMnemonic(StringRef Name, SMLoc NameLoc, + OperandVector *Operands); public: VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, @@ -121,8 +126,12 @@ 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; @@ -147,6 +156,10 @@ const MCExpr *Offset; }; + struct CCOp { + unsigned CCVal; + }; + struct MImmOp { const MCExpr *Val; bool M0Flag; @@ -157,6 +170,7 @@ struct RegOp Reg; struct ImmOp Imm; struct MemOp Mem; + struct CCOp CC; struct MImmOp MImm; }; @@ -174,9 +188,9 @@ 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; @@ -216,7 +230,8 @@ } 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; } @@ -235,18 +250,25 @@ 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; @@ -290,6 +312,17 @@ 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; @@ -354,11 +387,23 @@ } 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 { @@ -398,6 +443,15 @@ return Op; } + static std::unique_ptr CreateCCOp(unsigned CCVal, SMLoc S, + SMLoc E) { + auto Op = std::make_unique(k_CCOp); + Op->CC.CCVal = CCVal; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static std::unique_ptr CreateMImm(const MCExpr *Val, bool Flag, SMLoc S, SMLoc E) { auto Op = std::make_unique(k_MImmOp); @@ -427,6 +481,28 @@ } static std::unique_ptr + MorphToMEMri(unsigned Base, std::unique_ptr 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 + MorphToMEMzi(std::unique_ptr 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 MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr Op) { const MCExpr *Imm = Op->getImm(); Op->Kind = k_MemoryRegRegImm; @@ -564,15 +640,72 @@ 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"); } @@ -580,7 +713,7 @@ 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"); } @@ -703,6 +836,96 @@ 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 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"); diff --git a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp --- a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp +++ b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp @@ -131,8 +131,18 @@ 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" @@ -218,6 +228,28 @@ 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) { @@ -272,9 +304,89 @@ 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); +} diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp @@ -65,6 +65,10 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + private: FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; void @@ -112,6 +116,16 @@ return 0; } +uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) + return VECondCodeToVal( + static_cast(getMachineOpValue(MI, MO, Fixups, STI))); + return 0; +} + #define ENABLE_INSTR_PREDICATE_VERIFIER #include "VEGenMCCodeEmitter.inc" diff --git a/llvm/lib/Target/VE/VE.h b/llvm/lib/Target/VE/VE.h --- a/llvm/lib/Target/VE/VE.h +++ b/llvm/lib/Target/VE/VE.h @@ -15,6 +15,7 @@ #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" @@ -39,30 +40,31 @@ 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 @@ -103,6 +105,153 @@ 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(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(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"); } diff --git a/llvm/lib/Target/VE/VEInstrInfo.cpp b/llvm/lib/Target/VE/VEInstrInfo.cpp --- a/llvm/lib/Target/VE/VEInstrInfo.cpp +++ b/llvm/lib/Target/VE/VEInstrInfo.cpp @@ -41,29 +41,53 @@ 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"); } diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td --- a/llvm/lib/Target/VE/VEInstrInfo.td +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -95,6 +95,11 @@ return CurDAG->getTargetConstant(VECC, SDLoc(N), MVT::i32); }]>; +def CCOP : SDNodeXFormgetTargetConstant(N->getZExtValue(), + SDLoc(N), MVT::i32); +}]>; + //===----------------------------------------------------------------------===// // Feature predicates. //===----------------------------------------------------------------------===// @@ -261,9 +266,11 @@ // 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 { @@ -290,8 +297,14 @@ } // Operand for printing out a condition code. -let PrintMethod = "printCCOperand" in - def CCOp : Operand; +def CCOpAsmOperand : AsmOperandClass { let Name = "CCOp"; } +def CCOp : Operand, ImmLeaf= 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 { @@ -586,13 +599,14 @@ } multiclass BCm opc, RegisterClass RC, Operand immOp> { + let DecoderMethod = "DecodeBranchCondition" in defm r : BCtgm; - let cy = 0 in + let DecoderMethod = "DecodeBranchCondition", cy = 0 in defm i : BCtgm; - let cy = 0, sy = 0, + let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0, cf = 15 /* AT */, isBarrier = 1 in defm a : BCtgm; - let cy = 0, sy = 0, + let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0, cf = 0 /* AF */ in defm na : BCtgm; } @@ -1044,7 +1058,7 @@ 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. diff --git a/llvm/test/MC/VE/BC.s b/llvm/test/MC/VE/BC.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/VE/BC.s @@ -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) diff --git a/llvm/test/MC/VE/BCR.s b/llvm/test/MC/VE/BCR.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/VE/BCR.s @@ -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 diff --git a/llvm/test/MC/VE/BSIC.s b/llvm/test/MC/VE/BSIC.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/VE/BSIC.s @@ -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)