Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -84,6 +84,8 @@ return getSTI().getTargetTriple().getArch() == Triple::sparcv9; } + bool isREX() const { return getSTI().getFeatureBits()[Sparc::FeatureREX]; } + bool expandSET(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -229,6 +231,62 @@ bool isMEMrr() const { return Kind == k_MemoryReg; } bool isMEMri() const { return Kind == k_MemoryImm; } + bool isMEMREXr() const { + return Kind == k_MemoryReg && Mem.OffsetReg == Sparc::G0 && + SparcMCRegisterClasses[SP::RexIntRegsRegClassID].contains(Mem.Base); + } + + bool isConstant() const { + if (Kind != k_Immediate) + return false; + return Imm.Val->getKind() == MCExpr::Constant; + } + + bool isBrTarget8() const { + if (Kind != k_Immediate) + return false; + if (Imm.Val->getKind() == MCExpr::SymbolRef) + return true; + if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) + return !(CE->getValue() & 1) && isInt<9>(CE->getValue()); + return false; + } + + bool isBrTarget24() const { + if (Kind != k_Immediate) + return false; + if (Imm.Val->getKind() == MCExpr::SymbolRef) + return true; + if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) + return !(CE->getValue() & 1) && isInt<25>(CE->getValue()); + return false; + } + + bool isNImm13() const { + return isConstant() && (getConstant() < 0) && isInt<13>(getConstant()); + } + + bool isSImm21() const { return isConstant() && isInt<21>(getConstant()); } + + bool isSImm5() const { return isConstant() && isInt<5>(getConstant()); } + + bool isImm3() const { return isConstant() && isUInt<3>(getConstant()); } + + bool isImm5() const { return isConstant() && isUInt<5>(getConstant()); } + + bool isMEMfi() const { + if (Kind != k_MemoryImm) + return false; + const MCConstantExpr *CE = dyn_cast(getMemOff()); + if (!CE) + return false; + return (Mem.Base == Sparc::I0 || Mem.Base == Sparc::O0 || + Mem.Base == Sparc::I6 || Mem.Base == Sparc::O6) && + ((CE->getValue() & ~0x7c) == 0); + } + + bool isMEMffi() const { return isMEMfi() && Mem.Base != Sparc::O0; } + bool isIntReg() const { return (Kind == k_Register && Reg.Kind == rk_IntReg); } @@ -242,6 +300,29 @@ || Reg.Kind == rk_DoubleReg)); } + bool isRexIntReg() const { + const MCRegisterClass &RC = + SparcMCRegisterClasses[SP::RexIntRegsRegClassID]; + return (Kind == k_Register && RC.contains(getReg())); + } + + bool isRexFPReg() const { + const MCRegisterClass &RC = SparcMCRegisterClasses[SP::RexFPRegsRegClassID]; + return (Kind == k_Register && RC.contains(getReg())); + } + + bool isRexDFPReg() const { + const MCRegisterClass &RC = + SparcMCRegisterClasses[SP::RexDFPRegsRegClassID]; + return (Kind == k_Register && RC.contains(getReg())); + } + + bool isRexIntPairReg() const { + const MCRegisterClass &RC = + SparcMCRegisterClasses[SP::RexIntPairRegClassID]; + return (Kind == k_Register && RC.contains(getReg())); + } + bool isCoprocReg() const { return (Kind == k_Register && Reg.Kind == rk_CoprocReg); } @@ -256,6 +337,11 @@ return Reg.RegNum; } + int64_t getConstant() const { + assert(Imm.Val->getKind() == MCExpr::Constant); + return cast(Imm.Val)->getValue(); + } + const MCExpr *getImm() const { assert((Kind == k_Immediate) && "Invalid access!"); return Imm.Val; @@ -338,6 +424,13 @@ addExpr(Inst, Expr); } + void addMEMREXrOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::createReg(getMemBase())); + assert(getMemOffsetReg() == Sparc::G0 && "Invalid offset"); + } + static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { auto Op = make_unique(k_Token); Op->Tok.Data = Str.data(); @@ -784,6 +877,12 @@ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1); Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E)); ResTy = MatchOperand_Success; + } else if (isREX() && (Mnemonic == "rld32" || Mnemonic == "rld32pc")) { + std::unique_ptr Op; + ResTy = parseSparcAsmOperand(Op); + if (ResTy != MatchOperand_Success || !Op || !Op->isImm()) + return MatchOperand_ParseFail; + Operands.push_back(std::move(Op)); } else { ResTy = parseMEMOperand(Operands); } @@ -911,7 +1010,7 @@ OperandMatchResultTy SparcAsmParser::parseBranchModifiers(OperandVector &Operands) { - // parse (,a|,pn|,pt)+ + // parse (,a|,pn|,pt|,l)+ while (getLexer().is(AsmToken::Comma)) { @@ -920,7 +1019,8 @@ if (!getLexer().is(AsmToken::Identifier)) return MatchOperand_ParseFail; StringRef modName = Parser.getTok().getString(); - if (modName == "a" || modName == "pn" || modName == "pt") { + if (modName == "a" || modName == "pn" || modName == "pt" || + modName == "l") { Operands.push_back(SparcOperand::CreateToken(modName, Parser.getTok().getLoc())); Parser.Lex(); // eat the identifier. @@ -1278,6 +1378,9 @@ if (Op.isFloatOrDoubleReg()) { switch (Kind) { default: break; + case MCK_RexDFPReg: + if (!Op.isRexFPReg()) + break; case MCK_DFPRegs: if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op)) return MCTargetAsmParser::Match_Success; @@ -1288,9 +1391,19 @@ break; } } - if (Op.isIntReg() && Kind == MCK_IntPair) { - if (SparcOperand::MorphToIntPairReg(Op)) - return MCTargetAsmParser::Match_Success; + + if (Op.isIntReg()) { + switch (Kind) { + default: + break; + case MCK_RexIntPairReg: + if (!Op.isRexIntReg()) + break; + case MCK_IntPair: + if (SparcOperand::MorphToIntPairReg(Op)) + return MCTargetAsmParser::Match_Success; + break; + } } if (Op.isCoprocReg() && Kind == MCK_CoprocPair) { if (SparcOperand::MorphToCoprocPairReg(Op)) Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp =================================================================== --- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -167,6 +167,8 @@ switch (MI->getOpcode()) { default: break; case SP::FBCOND: + case SP::RFBCOND: + case SP::RFLBCOND: case SP::FBCONDA: case SP::BPFCC: case SP::BPFCCA: Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -23,6 +23,8 @@ switch (Kind) { default: llvm_unreachable("Unknown fixup kind!"); + case Sparc::fixup_sparc_32: + case Sparc::fixup_sparc_disp32: case FK_Data_1: case FK_Data_2: case FK_Data_4: @@ -45,6 +47,12 @@ case Sparc::fixup_sparc_br16_14: return (Value >> 2) & 0x3fff; + case Sparc::fixup_sparc_br8: + return ((Value >> 1) & 0xff) << 16; + + case Sparc::fixup_sparc_br24: + return ((Value >> 9) & 0xffff) | ((Value >> 1) & 0xff) << 16; + case Sparc::fixup_sparc_pc22: case Sparc::fixup_sparc_got22: case Sparc::fixup_sparc_tls_gd_hi22: @@ -150,7 +158,11 @@ { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, { "fixup_sparc_tls_ie_add", 0, 0, 0 }, { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, - { "fixup_sparc_tls_le_lox10", 0, 0, 0 } + { "fixup_sparc_tls_le_lox10", 0, 0, 0 }, + { "fixup_sparc_32", 0, 32, 0 }, + { "fixup_sparc_pc32", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br8", 8, 8, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br24", 8, 24, MCFixupKindInfo::FKF_IsPCRel }, }; const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = { @@ -189,7 +201,11 @@ { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, { "fixup_sparc_tls_ie_add", 0, 0, 0 }, { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, - { "fixup_sparc_tls_le_lox10", 0, 0, 0 } + { "fixup_sparc_tls_le_lox10", 0, 0, 0 }, + { "fixup_sparc_32", 0, 32, 0 }, + { "fixup_sparc_pc32", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br8", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br24", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, }; if (Kind < FirstTargetFixupKind) @@ -255,13 +271,16 @@ } bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { - // Cannot emit NOP with size not multiple of 32 bits. - if (Count % 4 != 0) - return false; - uint64_t NumNops = Count / 4; - for (uint64_t i = 0; i != NumNops; ++i) - OW->write32(0x01000000); + // Can only emit NOP with size multiple of 32 or 16 bits. + if (Count % 4 == 0) { + uint64_t NumNops = Count / 4; + for (uint64_t i = 0; i != NumNops; ++i) + OW->write32(0x01000000); + } else if (Count % 2 == 0) + OW->WriteZeros(Count); + else + return false; return true; } Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -62,6 +62,7 @@ case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; + case Sparc::fixup_sparc_disp32: return ELF::R_SPARC_DISP32; } } @@ -105,6 +106,7 @@ case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD; case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22; case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10; + case Sparc::fixup_sparc_32: return ELF::R_SPARC_32; } return ELF::R_SPARC_NONE; Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -87,6 +87,13 @@ fixup_sparc_tls_le_hix22, fixup_sparc_tls_le_lox10, + fixup_sparc_32, + fixup_sparc_disp32, + + /// fixups for REX branches + fixup_sparc_br8, + fixup_sparc_br24, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "SparcMCExpr.h" #include "MCTargetDesc/SparcFixupKinds.h" +#include "SparcMCExpr.h" #include "SparcMCTargetDesc.h" #include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -22,7 +23,6 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" @@ -45,6 +45,10 @@ ~SparcMCCodeEmitter() override {} + bool isREX(const MCSubtargetInfo &STI) const { + return STI.getFeatureBits()[Sparc::FeatureREX]; + } + void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; @@ -67,12 +71,30 @@ unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getADDRfiOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getRexShortBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getRexLongBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getImm32OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getRexIntRegEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getRexFPRegEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; private: uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; @@ -93,14 +115,31 @@ verifyInstructionPredicates(MI, computeAvailableFeatures(STI.getFeatureBits())); - unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); + uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); + + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + + // Get byte count of instruction + unsigned Size = Desc.getSize(); if (Ctx.getAsmInfo()->isLittleEndian()) { // Output the bits in little-endian byte order. - support::endian::Writer(OS).write(Bits); + if (Size == 4) + support::endian::Writer(OS).write(Bits); + else if (Size == 6) { + support::endian::Writer(OS).write(Bits); + support::endian::Writer(OS).write(Bits >> 32); + } else if (Size == 2) + support::endian::Writer(OS).write(Bits); } else { // Output the bits in big-endian byte order. - support::endian::Writer(OS).write(Bits); + if (Size == 4) + support::endian::Writer(OS).write(Bits); + else if (Size == 6) { + support::endian::Writer(OS).write(Bits >> 32); + support::endian::Writer(OS).write(Bits); + } else if (Size == 2) + support::endian::Writer(OS).write(Bits); } unsigned tlsOpNo = 0; switch (MI.getOpcode()) { @@ -154,7 +193,9 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isReg() || MO.isImm()) + if (MO.isImm()) + return MO.getImm() >> 2; + if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI); if (MI.getOpcode() == SP::TLS_CALL) { @@ -179,7 +220,13 @@ fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; } - Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind)); + const MCExpr *FixupExpression = MO.getExpr(); + + if (isREX(STI)) + FixupExpression = MCBinaryExpr::createAdd( + MO.getExpr(), MCConstantExpr::create(+2, Ctx), Ctx); + + Fixups.push_back(MCFixup::create(0, FixupExpression, fixupKind)); return 0; } @@ -197,10 +244,78 @@ return 0; } -unsigned SparcMCCodeEmitter:: -getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { +unsigned +SparcMCCodeEmitter::getADDRfiOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO1 = MI.getOperand(OpNo); + const MCOperand &MO2 = MI.getOperand(OpNo + 1); + unsigned RegVal; + unsigned EncodedValue; + + switch (MO1.getReg()) { + case SP::I6: // FP + RegVal = 0; + break; + case SP::O6: // SP + RegVal = 1; + break; + case SP::I0: + RegVal = 2; + break; + case SP::O0: + RegVal = 3; + break; + default: + llvm_unreachable("Unsupported register"); + } + + EncodedValue = RegVal << 5; + EncodedValue |= MO2.getImm() >> 2; + + return EncodedValue; +} + +unsigned SparcMCCodeEmitter::getRexShortBranchTargetOpValue( + const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + assert(!MO.isReg()); + + if (MO.isImm()) { + unsigned value = getMachineOpValue(MI, MO, Fixups, STI); + assert(!(value & 1)); + return value >> 1; + } + + Fixups.push_back( + MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br8)); + return 0; +} + +unsigned SparcMCCodeEmitter::getRexLongBranchTargetOpValue( + const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + assert(!MO.isReg()); + + if (MO.isImm()) { + unsigned value = getMachineOpValue(MI, MO, Fixups, STI); + assert(!(value & 1)); + return value >> 1; + } + + Fixups.push_back( + MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br24)); + return 0; +} + +unsigned SparcMCCodeEmitter::getBranchPredTargetOpValue( + const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpNo); if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); @@ -225,5 +340,54 @@ return 0; } +unsigned SparcMCCodeEmitter::getImm32OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isImm()) + return MO.getImm(); + + assert(MO.isExpr()); + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back( + MCFixup::create(2, Expr, (MCFixupKind)Sparc::fixup_sparc_32)); + return 0; +} + +static const unsigned RexIntRegsMapping[32] = { + 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 20, 21, 22, 23, + 16, 17, 18, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + +static const unsigned RexFloatRegsMapping[32] = { + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 4, 5, 6, 7, + 0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + +unsigned +SparcMCCodeEmitter::getRexIntRegEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isReg()); + + unsigned regval = Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + return RexIntRegsMapping[regval]; +} + +unsigned +SparcMCCodeEmitter::getRexFPRegEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isReg()); + + unsigned regval = Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + return RexFloatRegsMapping[regval]; +} + #define ENABLE_INSTR_PREDICATE_VERIFIER + #include "SparcGenMCCodeEmitter.inc" Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -55,7 +55,8 @@ VK_Sparc_TLS_IE_LDX, VK_Sparc_TLS_IE_ADD, VK_Sparc_TLS_LE_HIX22, - VK_Sparc_TLS_LE_LOX10 + VK_Sparc_TLS_LE_LOX10, + VK_Sparc_32 }; private: Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -79,7 +79,7 @@ case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; break; case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break; case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break; - } + case VK_Sparc_32: closeParen = false; break;} return closeParen; } @@ -152,6 +152,9 @@ case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add; case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22; case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10; + case VK_Sparc_32: return Sparc::fixup_sparc_32; + case VK_Sparc_R_DISP32: return Sparc::fixup_sparc_disp32; + } } Index: lib/Target/Sparc/Sparc.td =================================================================== --- lib/Target/Sparc/Sparc.td +++ lib/Target/Sparc/Sparc.td @@ -38,6 +38,9 @@ def FeatureLeon : SubtargetFeature<"leon", "IsLeon", "true", "Enable LEON extensions">; +def FeatureREX + : SubtargetFeature<"rex", "IsREX", "true", + "Enable REX instruction set extension">; def FeatureHardQuad : SubtargetFeature<"hard-quad-float", "HasHardQuad", "true", Index: lib/Target/Sparc/SparcInstrAliases.td =================================================================== --- lib/Target/Sparc/SparcInstrAliases.td +++ lib/Target/Sparc/SparcInstrAliases.td @@ -67,6 +67,14 @@ def : InstAlias; + // rb $imm + def : InstAlias; + + // rb,l $imm + def : InstAlias; + // b,a $imm def : InstAlias; @@ -208,6 +216,14 @@ def : InstAlias; + // rfb $imm + def : InstAlias; + + // rfb,l $imm + def : InstAlias; + // fb,a $imm def : InstAlias; Index: lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- lib/Target/Sparc/SparcInstrInfo.td +++ lib/Target/Sparc/SparcInstrInfo.td @@ -67,6 +67,9 @@ // will pick deprecated instructions. def UseDeprecatedInsts : Predicate<"Subtarget->useDeprecatedV8Instructions()">; +// True when generating code using the REX instruction set extension. +def IsREX : Predicate<"Subtarget->isREX()">; + //===----------------------------------------------------------------------===// // Instruction Pattern Stuff //===----------------------------------------------------------------------===// @@ -1689,4 +1692,5 @@ include "SparcInstr64Bit.td" include "SparcInstrVIS.td" +include "SparcInstrRex.td" include "SparcInstrAliases.td" Index: lib/Target/Sparc/SparcInstrRex.td =================================================================== --- /dev/null +++ lib/Target/Sparc/SparcInstrRex.td @@ -0,0 +1,603 @@ +//===----------------------- SparcInstrRex.td - REX -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains instruction formats, definitions and patterns needed for +// the REX instruction set extension. +// +// A full description of the REX instruction set is available at +// http://www.gaisler.com/doc/antn/GRLIB-TN-0001.pdf. +// +//===----------------------------------------------------------------------===// + +class InstRex pattern> + : Instruction { + let Namespace = "SP"; + + let Predicates = [IsREX]; + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; + + let DecoderNamespace = "SparcRex"; + field bits<48> SoftFail = 0; +} + +// Base class for 16-bit REX instructions +class InstRex16 pattern> + : InstRex { + field bits<16> Inst; + let Size = 2; + bits<2> op; + let Inst{15-14} = op; +} + +// Base class for 32-bit REX instructions +class InstRex32 pattern> + : InstRex { + field bits<32> Inst; + let Size = 4; + bits<2> op; + let Inst{31-30} = op; +} + +// Base class for 48-bit REX instructions +class InstRex48 rop4, Operand immop, + Operand regop, list pattern> + : InstRex<(outs regop:$rd), (ins immop:$imm32), asmstr, pattern> { + field bits<48> Inst; + bits<32> imm32; + bits<4> rd; + let Size = 6; + let Inst{47-46} = 0b10; + let Inst{45-42} = rd; + let Inst{41} = 1; + let Inst{40-37} = 0b1111; + let Inst{36-32} = rop4; + let Inst{31-0} = imm32; +} + +// For 16-bit REX instruction with rs and rd operands +class RexFR opval, bits<1> imm, bits<4> rop3val, + bits<1> rop3lval, dag outs, dag ins, string asmstr, + list pattern> + : InstRex16 { + bits<4> rs; + bits<4> rd; + let op = opval; + let Inst{13-10} = rd; + let Inst{9} = imm; + let Inst{8-5} = rop3val; + let Inst{4} = rop3lval; + let Inst{3-0} = rs; +} + +// For 16-bit REX instruction with immediate and rd operands +class RexFI opval, bits<1> imm, bits<4> rop3val, + dag outs, dag ins, string asmstr, + list pattern> + : InstRex16 { + bits<4> rd; + bits<5> imm5; + let op = opval; + let Inst{13-10} = rd; + let Inst{9} = imm; + let Inst{8-5} = rop3val; + let Inst{4-0} = imm5; +} + +// For 16-bit REX instruction with only rd operand +class RexFO opval, bits<1> imm, bits<4> rop3val, bits<5> rop4val, + dag outs, dag ins, string asmstr, list pattern> + : InstRex16 { + bits<4> rd; + let op = opval; + let Inst{13-10} = rd; + let Inst{9} = imm; + let Inst{8-5} = rop3val; + let Inst{4-0} = rop4val; +} + +// For 16-bit REX instructions with fixed register + immediate and rd operands +class RexFF isStore, bits<1> isFloat, + dag outs, dag ins, string asmstr, list pattern> + : InstRex16 { + bits<4> rd; + bits<2> rs; + bits<7> addr; + let op = 0b11; + let Inst{13-10} = rd; + let Inst{9} = 0b1; + let Inst{8} = isStore; + let Inst{7-6} = addr{6-5}; + let Inst{5} = isFloat; + let Inst{4-0} = addr{4-0}; +} + +// Asm operands + +class ImmAsmOperandClass : AsmOperandClass { + let RenderMethod = "addImmOperands"; +} + +class RegAsmOperandClass : AsmOperandClass { + let RenderMethod = "addRegOperands"; +} + +def Imm5AsmOperand : ImmAsmOperandClass { let Name = "Imm5"; } +def SImm5AsmOperand : ImmAsmOperandClass { let Name = "SImm5"; } +def Imm3AsmOperand : ImmAsmOperandClass { let Name = "Imm3"; } +def NImm13AsmOperand : ImmAsmOperandClass { let Name = "NImm13"; } +def SImm21AsmOperand : ImmAsmOperandClass { let Name = "SImm21"; } +def BrTarget8AsmOperand : ImmAsmOperandClass { let Name = "BrTarget8"; } +def BrTarget24AsmOperand : ImmAsmOperandClass { let Name = "BrTarget24"; } + +def RexMEMfiAsmOperand : AsmOperandClass { + let Name = "MEMfi"; + let RenderMethod = "addMEMriOperands"; +} +def RexMEMffiAsmOperand : AsmOperandClass { + let Name = "MEMffi"; + let RenderMethod = "addMEMriOperands"; +} + +def RexMEMREXrAsmOperand : AsmOperandClass { let Name = "MEMREXr"; } +def RexIntRegAsmOperand : RegAsmOperandClass { let Name = "RexIntReg"; } +def RexIntPairAsmOperand : RegAsmOperandClass { let Name = "RexIntPairReg"; } +def RexFPRegAsmOperand : RegAsmOperandClass { let Name = "RexFPReg"; } +def RexDFPRegAsmOperand : RegAsmOperandClass { let Name = "RexDFPReg"; } +def IntRegAsRexAsmOperand : RegAsmOperandClass { let Name = "IntReg"; } + +// Operands + +def IntRegsAsRex : Operand { + let MIOperandInfo = (ops IntRegs); + let EncoderMethod = "getRexIntRegEncoding"; + let ParserMatchClass = IntRegAsRexAsmOperand; +} + +def RexIntRegsOp : Operand { + let MIOperandInfo = (ops RexIntRegs); + let EncoderMethod = "getRexIntRegEncoding"; + let ParserMatchClass = RexIntRegAsmOperand; +} + +def RexIntPairOp : Operand { + let MIOperandInfo = (ops RexIntPair); + let EncoderMethod = "getRexIntRegEncoding"; + let ParserMatchClass = RexIntPairAsmOperand; +} + +def RexFPRegsOp : Operand { + let MIOperandInfo = (ops RexFPRegs); + let EncoderMethod = "getRexFPRegEncoding"; + let ParserMatchClass = RexFPRegAsmOperand; +} + +def RexDFPRegsOp : Operand { + let MIOperandInfo = (ops RexDFPRegs); + let EncoderMethod = "getRexFPRegEncoding"; + let ParserMatchClass = RexDFPRegAsmOperand; +} + +def ADDRr : Operand { + let MIOperandInfo = (ops RexIntRegsOp:$rs); + let ParserMatchClass = RexMEMREXrAsmOperand; + let EncoderMethod = "getRexIntRegEncoding"; +} + +class RegImmOperand : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops RexIntRegsOp:$rs, i32imm:$imm5); + let EncoderMethod = "getADDRfiOpValue"; +} + +def ADDRfi : RegImmOperand { let ParserMatchClass = RexMEMfiAsmOperand; } +def ADDRffi : RegImmOperand { let ParserMatchClass = RexMEMffiAsmOperand; } + +def Imm3Op : Operand { let ParserMatchClass = Imm3AsmOperand; } +def Imm5Op : Operand { let ParserMatchClass = Imm5AsmOperand; } +def SImm5Op : Operand { let ParserMatchClass = SImm5AsmOperand; } +def NImm13Op : Operand { let ParserMatchClass = NImm13AsmOperand; } +def SImm21Op : Operand { let ParserMatchClass = SImm21AsmOperand; } +def Imm32Op : Operand { let EncoderMethod = "getImm32OpValue"; } + +// Instructions + +// Section 6.2.1 - SAVEREX and ADDREX + +class EnterREX op3val> + : F3<(outs IntRegs:$rd), + (ins IntRegs:$rs1, NImm13Op : $nimm13 ), + !strconcat(OpcStr, " $rs1, $nimm13, $rd"), []> { + bits<13> nimm13; + let op = 0b10; + let op3 = op3val; + let Inst{13} = 0; + let Inst{12-0} = nimm13; +} + +def SAVEREX : EnterREX<"saverex", 0b111100>; +def ADDREX : EnterREX<"addrex", 0b000000>; + +// Section 6.3.1 - Branch on Integer Condition Codes - Short + +def brtarget8 : Operand { + let EncoderMethod = "getRexShortBranchTargetOpValue"; + let ParserMatchClass = BrTarget8AsmOperand; +} + +class RexBranch pattern> + : InstRex16<(outs), ins, asmstr, pattern> { + bits<8> disp8; + bits<4> cond; + let op = 0b00; + let Inst{9} = 0; + let Inst{8} = isFloat; + let Inst{13-10} = cond; + let Inst{7-0} = disp8; + let isBranch = 1; + let isTerminator = 1; +} + +let cond = 8, isBarrier = 1 in +def RBA : RexBranch<0, (ins brtarget8:$disp8), + "rba\t$disp8", + []>; + +let Uses = [ICC] in +def RBCOND : RexBranch<0, (ins brtarget8:$disp8, CCOp:$cond), + "rb$cond\t$disp8", + []>; + +// Section 6.3.2 - Branch on Floating-Point Condition Codes - Short + +let Uses = [FCC0] in +def RFBCOND : RexBranch<1, (ins brtarget8:$disp8, CCOp:$cond), + "rfb$cond\t$disp8", + []>; + +// Section 6.3.3 - Arithmetic operations - Accumulator with register + +let Constraints = "$rd = $rsc" in +class RexArith rop3, bits<1> rop3l, list pattern> + : RexFR<0b10, 0b0, rop3, rop3l, (outs RexIntRegsOp:$rd), + (ins RexIntRegsOp:$rs, RexIntRegsOp:$rsc), + !strconcat(OpcStr, "\t$rs, $rd"), pattern>; + +let isCommutable = 1 in { + def RADD : RexArith<"radd", 0b0000, 0b0, + []>; + def RAND : RexArith<"rand", 0b0010, 0b0, + []>; + def ROR : RexArith<"ror", 0b0100, 0b0, + []>; + def RXOR : RexArith<"rxor", 0b0110, 0b0, + []>; +} + +def RSUB : RexArith<"rsub", 0b0001, 0b0, + []>; +def RANDN : RexArith<"randn", 0b1010, 0b0, + []>; +def RORN : RexArith<"rorn", 0b1100, 0b0, + []>; +def RSLL : RexArith<"rsll", 0b1011, 0b0, + []>; +def RSRL : RexArith<"rsrl", 0b1101, 0b0, + []>; + +let Defs = [ICC] in { + let isCommutable = 1 in { + def RADDCC : RexArith<"raddcc", 0b0000, 0b1, + []>; + def RANDCC : RexArith<"randcc", 0b0010, 0b1, []>; + def RORCC : RexArith<"rorcc", 0b0100, 0b1, []>; + def RXORCC : RexArith<"rxorcc", 0b0110, 0b1, []>; + } + + def RSUBCC : RexArith<"rsubcc", 0b0001, 0b1, + []>; + def RANDNCC : RexArith<"randncc", 0b1010, 0b1, []>; + def RORNCC : RexArith<"rorncc", 0b1100, 0b1, []>; +} + +// Section 6.3.4 - Arithmetic operations - Accumulator with immediate + +let Constraints = "$rd = $rs" in +class RexArithImm rop3, Operand immop, + list pattern> + : RexFI<0b10, 0b1, rop3, + (outs RexIntRegsOp:$rd), + (ins RexIntRegsOp:$rs, immop:$imm5), + !strconcat(OpcStr, "\t$imm5, $rd"), + pattern>; + +let Defs = [ICC] in +def RADDCCi : RexArithImm<"raddcc", 0b0000, SImm5Op, + []>; +def RSLLi : RexArithImm<"rsll", 0b1011, Imm5Op, + []>; +def RSRLi : RexArithImm<"rsrl", 0b1101, Imm5Op, + []>; + +// Section 6.3.5 - Comparison with register + +let Defs = [ICC], isCompare = 1 in +def RCMPrr : RexFR<0b10, 0b0, 0b1011, 0b1, + (outs), (ins RexIntRegsOp:$rs, RexIntRegsOp:$rd), + "rcmp\t$rd, $rs", + []>; + +// Section 6.3.6 - Comparison with immediate + +let Defs = [ICC], isCompare = 1 in +def RCMPri : RexFI<0b10, 0b1, 0b1000, + (outs), (ins RexIntRegsOp:$rd, SImm5Op:$imm5), + "rcmp\t$rd, $imm5", + []>; + +// Section 6.3.7 - Constant assignment + +class RexConstant op3val, + Operand immop, list pattern> + : RexFI<0b10, 0b1, op3val, + (outs RexIntRegsOp:$rd), + (ins immop:$imm5 ), + !strconcat(OpcStr, "\t$imm5, $rd"), + pattern>; + +def RSET5 : RexConstant<"rset5", 0b0001, SImm5Op, + []>; +def RONE : RexConstant<"rone", 0b0101, Imm5Op, + []>; + +// Section 6.3.8 - Bit-mask operations + +let Constraints = "$rd = $rs" in +class RexBitmask op3val, list pattern> + : RexFI<0b10, 0b1, op3val, (outs RexIntRegsOp:$rd), + (ins Imm5Op:$imm5, RexIntRegsOp:$rs ), + !strconcat(OpcStr, "\t$imm5, $rd"), pattern>; + +def RSETBIT : RexBitmask<"rsetbit", 0b0100, + []>; +def RCLRBIT : RexBitmask<"rclrbit", 0b1010, + []>; +def RINVBIT : RexBitmask<"rinvbit", 0b0110, + []>; +def RMASKLO : RexBitmask<"rmasklo", 0b0010, + []>; + +let Defs = [ICC] in +def RTSTBIT : RexFI<0b10, 0b1, 0b0011, (outs), (ins Imm5Op:$imm5, + RexIntRegsOp:$rd), + "rtstbit\t$imm5, $rd", + []>; + +// Section 6.3.9 - Register to register copy + +def RMOV : InstRex16<(outs IntRegsAsRex:$rd), + (ins IntRegsAsRex:$rs), + "rmov\t$rs, $rd", + []> { + bits<5> rd; + bits<5> rs; + let op = 0b10; + let Inst{13-10} = rd{3-0}; + let Inst{9} = 0; + let Inst{8-6} = 0b100; + let Inst{5} = rd{4}; + let Inst{4} = rs{4}; + let Inst{3-0} = rs{3-0}; +} + +// Section 6.3.10 - Negation + +let Constraints = "$rs = $rd" in +class RexNeg rop4val, list pattern> + : RexFO<0b10, 0b1, 0b1110, rop4val, + (outs RexIntRegsOp:$rd), + (ins RexIntRegsOp:$rs), + !strconcat(OpcStr, "\t$rd"), + pattern>; + +def RNEG : RexNeg<"rneg", 0b00100, []>; +def RNOT : RexNeg<"rnot", 0b00101, []>; + +// Section 6.3.11 - Return instructions + +class RetInst rop4> + : RexFO<0b10, 0b1, 0b1110, rop4, (outs), (ins Imm5Op:$offset), + asmstr, []> { + let rd = 0b0000; + let isReturn = 1; + let isTerminator = 1; + let isBarrier = 1; +} + +let Uses=[I7] in +def RRETREST : RetInst<"rretrest", 0b00000>; +let Uses=[O7] in +def RRETL : RetInst<"rretl", 0b00001>; + +// Section 6.3.12 and 6.3.14 - Load/Store 8/16/32/64-bit - One register +// With or without auto-incrementing + +multiclass RexStore rop3val, SDPatternOperator OpNode, + Operand RegOp, ValueType Ty> { + +def r: RexFR<0b11, 0, rop3val, 0, + (outs), (ins ADDRr:$rs, RegOp:$rd), + !strconcat(OpcStr, "\t$rd, [$rs]"), + []>; + +let Constraints = "$rs = $rd2" in +def inc : RexFR<0b11, 0, rop3val, 1, + (outs ADDRr:$rd2), (ins ADDRr:$rs, RegOp:$rd ), + !strconcat(OpcStr, "inc\t$rd, [$rs]"), + []>; +} + +defm RST : RexStore<"rst", 0b1000, store, RexIntRegsOp, i32>; +defm RSTB : RexStore<"rstb", 0b1010, truncstorei8, RexIntRegsOp, i32>; +defm RSTH : RexStore<"rsth", 0b1100, truncstorei16, RexIntRegsOp, i32>; +defm RSTD : RexStore<"rstd", 0b1110, store, RexIntPairOp, v2i32>; +defm RSTF : RexStore<"rstf", 0b1001, store, RexFPRegsOp, f32>; +defm RSTDF : RexStore<"rstdf", 0b1101, store, RexDFPRegsOp, f64>; + +multiclass RexLoad rop3val, SDPatternOperator OpNode, + Operand RegOp, ValueType Ty> { + +def r: RexFR<0b11, 0, rop3val, 0, + (outs RegOp:$rd), (ins ADDRr:$rs), + !strconcat(OpcStr, "\t[$rs], $rd"), + []>; + +let Constraints = "$rs = $rd2" in +def inc : RexFR<0b11, 0, rop3val, 1, + (outs RegOp:$rd, ADDRr:$rd2), (ins ADDRr:$rs), + !strconcat(OpcStr, "inc\t[$rs], $rd"), + []>; +} + +defm RLD : RexLoad<"rld", 0b0000, load, RexIntRegsOp, i32>; +defm RLDUB : RexLoad<"rldub", 0b0010, zextloadi8, RexIntRegsOp, i32>; +defm RLDUH : RexLoad<"rlduh", 0b0100, zextloadi16, RexIntRegsOp, i32>; +defm RLDD : RexLoad<"rldd", 0b0110, load, RexIntPairOp, v2i32>; +defm RLDF : RexLoad<"rldf", 0b0001, load, RexFPRegsOp, f32>; +defm RLDDF : RexLoad<"rlddf", 0b0101, load, RexDFPRegsOp, f64>; + +// Section 6.3.13 - Load/Store 32-bit - Fixed register plus immediate + +class RexStoreFI isFloat, + Operand RegImmOp, Operand RegOp> + : RexFF<1, isFloat, (outs), (ins RegImmOp:$addr, RegOp:$rd), OpcStr, []>; + +let mayStore = 1 in { +def RSTfi : RexStoreFI<"rst\t$rd, [$addr]", 0, ADDRfi, RexIntRegsOp>; +def RSTFfi : RexStoreFI<"rstf\t$rd, [$addr]", 1, ADDRffi, RexFPRegsOp>; +} + +class RexLoadFI isFloat, + Operand RegImmOp, Operand RegOp> + : RexFF<0, isFloat, (outs RegOp:$rd), (ins RegImmOp:$addr), OpcStr, []>; + +let mayLoad = 1 in { +def RLDfi : RexLoadFI<"rld\t[$addr], $rd", 0, ADDRfi, RexIntRegsOp>; +def RLDFfi : RexLoadFI<"rldf\t[$addr], $rd", 1, ADDRffi, RexFPRegsOp>; +} + +// Section 6.3.15 - Miscellaneous operations + +class RexMisc rop4val, dag outs, dag ins> : + RexFO<0b10, 0b1, 0b1110, rop4val, outs, ins, OpStr, []>; + +let Defs = [O6], Uses = [O6] in { +def RPUSH : RexMisc<"rpush\t$rd", 0b00010, (outs), (ins RexIntRegsOp:$rd)>; +def RPOP : RexMisc<"rpop\t$rd", 0b00011, (outs RexIntRegsOp:$rd), (ins)>; +} + +def RTA : RexMisc<"rta\t$rd", 0b00110, (outs), (ins Imm3Op:$rd)>; + +let rd = 0b0000 in +def RLEAVE : RexMisc<"rleave", 0b00111, (outs), (ins)>; + +def RGETPC : RexMisc<"rgetpc\t$rd", 0b01001, (outs RexIntRegsOp:$rd), (ins)>; + +def RNOP : InstRex16<(outs), (ins), "rnop", []> { + let op = 0b00; + let Inst{13-0} = 0; +} + +// Section 6.4.1 - Branch on integer condition codes - Long + +def brtarget24 : Operand { + let EncoderMethod = "getRexLongBranchTargetOpValue"; + let ParserMatchClass = BrTarget24AsmOperand; +} + +class RexLongBranch pattern> + : InstRex32<(outs), ins, asmstr, pattern> { + bits<24> disp24; + bits<4> cond; + let op = 0b00; + let Inst{25} = 1; + let Inst{24} = isFloat; + let Inst{29-26} = cond; + let Inst{23-16} = disp24{7-0}; + let Inst{15-0} = disp24{23-8}; + let isBranch = 1; + let isTerminator = 1; +} + +let cond = 8, isBarrier = 1 in +def RBAL : RexLongBranch<0, (ins brtarget24:$disp24), + "rba,l\t$disp24", + []>; + +let Uses = [ICC] in +def RLBCOND : RexLongBranch<0, (ins brtarget24:$disp24, CCOp:$cond), + "rb$cond,l\t$disp24", + []>; + +// Section 6.4.2 - Branch on floating-point condition codes - Long + +let Uses = [FCC0] in +def RFLBCOND : RexLongBranch<1, (ins brtarget24:$disp24, CCOp:$cond), + "rfb$cond,l\t$disp24", + []>; + +// Section 6.4.3 - Call and link + +let isTerminator = 1, isBarrier = 1, isBranch = 1, isIndirectBranch = 1, + rd = 8, simm13 = 1, isCodeGenOnly = 1, Predicates = [IsREX], + AddedComplexity = 60 in +def BINDr : F3_2<2, 0b111000, + (outs), (ins IntRegs:$rs1), + "rjmp\t$rs1", + []>; + +// Section 6.4.4 - Constant assignment + +def RSET21 : InstRex32<(outs RexIntRegsOp:$rd), + (ins SImm21Op:$imm21 ), + "rset21\t$imm21, $rd", + []> { + bits<4> rd; + bits<21> imm21; + let op = 0b10; + let Inst{29-26} = rd; + let Inst{25} = 1; + let Inst{24-21} = 0b0111; + let Inst{20-16} = imm21{4-0}; + let Inst{15-0} = imm21{20-5}; +} + +// Section 6.4.5 - Generic format 3 SPARC operations + +// Section 6.4.6 - Floating point operations + +// Section 6.5.1 - Set 32-bit constant + +def RSET32 : InstRex48<"rset32\t$imm32, $rd", 0b01000, + Imm32Op, RexIntRegsOp, + []>; +def RSET32PC : InstRex48<"rset32pc $imm32, $rd", 0b01001, + Imm32Op, RexIntRegsOp, + []>; + +// Section 6.5.2 - Load from 32-bit address + +def RLD32 : InstRex48<"rld32\t[$imm32], $rd", 0b01010, + Imm32Op, RexIntRegsOp, + []>; +def RLD32PC : InstRex48<"rld32pc\t[$imm32], $rd", 0b01011, + Imm32Op,RexIntRegsOp, + []>; Index: lib/Target/Sparc/SparcRegisterInfo.td =================================================================== --- lib/Target/Sparc/SparcRegisterInfo.td +++ lib/Target/Sparc/SparcRegisterInfo.td @@ -331,7 +331,6 @@ (sequence "L%u", 0, 7), (sequence "O%u", 0, 7))>; - // Should be in the same order as IntRegs. def IntPair : RegisterClass<"SP", [v2i32], 64, (add I0_I1, I2_I3, I4_I5, I6_I7, @@ -376,3 +375,22 @@ def PRRegs : RegisterClass<"SP", [i64], 64, (add TPC, TNPC, TSTATE, TT, TICK, TBA, PSTATE, TL, PIL, CWP, CANSAVE, CANRESTORE, CLEANWIN, OTHERWIN, WSTATE)>; + +// Reduced register set used by REX +def RexIntRegs : RegisterClass<"SP", [i32], 32, + (add (sequence "I%u", 0, 7), + (sequence "L%u", 4, 7), + (sequence "O%u", 0, 3))>; + +def RexIntPair : RegisterClass<"SP", [v2i32], 64, + (add I0_I1, I2_I3, I4_I5, I6_I7, + L4_L5, L6_L7, + O0_O1, O2_O3)>; + +def RexFPRegs : RegisterClass<"SP", [f32], 32, + (add (sequence "F%u", 0, 7), + (sequence "F%u", 12, 19))>; + +def RexDFPRegs : RegisterClass<"SP", [f64], 64, + (add (sequence "D%u", 0, 3), + (sequence "D%u", 6, 9))>; Index: lib/Target/Sparc/SparcSubtarget.h =================================================================== --- lib/Target/Sparc/SparcSubtarget.h +++ lib/Target/Sparc/SparcSubtarget.h @@ -32,6 +32,7 @@ class SparcSubtarget : public SparcGenSubtargetInfo { Triple TargetTriple; virtual void anchor(); + bool IsREX; bool IsV9; bool IsLeon; bool V8DeprecatedInsts; @@ -81,6 +82,7 @@ bool isVIS() const { return IsVIS; } bool isVIS2() const { return IsVIS2; } bool isVIS3() const { return IsVIS3; } + bool isREX() const { return IsREX; } bool useDeprecatedV8Instructions() const { return V8DeprecatedInsts; } bool hasHardQuad() const { return HasHardQuad; } bool usePopc() const { return UsePopc; } Index: lib/Target/Sparc/SparcSubtarget.cpp =================================================================== --- lib/Target/Sparc/SparcSubtarget.cpp +++ lib/Target/Sparc/SparcSubtarget.cpp @@ -35,6 +35,7 @@ HasHardQuad = false; UsePopc = false; UseSoftFloat = false; + IsREX = false; // Leon features HasLeonCasa = false; Index: test/MC/Sparc/invalid-rex-instructions.s =================================================================== --- /dev/null +++ test/MC/Sparc/invalid-rex-instructions.s @@ -0,0 +1,137 @@ + ! RUN: not llvm-mc %s -arch=sparc -mattr=+rex -show-encoding 2>&1 | FileCheck %s + +// New SPARC instructions + +// Section 6.2.1 - SAVEREX and ADDREX + + ! CHECK: error: invalid operand for instruction + saverex %sp, 0, %sp + + ! CHECK: error: invalid operand for instruction + saverex %sp, -4097, %sp + + ! CHECK: error: invalid operand for instruction + addrex %sp, 0, %sp + + ! CHECK: error: invalid operand for instruction + addrex %sp, -4097, %sp + +// REX instructions + +// Section 6.3.1 - Branch on Integer Condition Codes - Short + + ! CHECK: error: invalid operand for instruction + rbleu 256 + + ! CHECK: error: invalid operand for instruction + rbleu -257 + + ! CHECK: error: invalid operand for instruction + rbleu 3 + +// Section 6.3.2 - Branch on Floating-Point Condition Codes - Short + + ! CHECK: error: invalid operand for instruction + rfbule 256 + + ! CHECK: error: invalid operand for instruction + rfbule -257 + + ! CHECK: error: invalid operand for instruction + rfbule 3 + +// Section 6.3.3 - Arithmetic operations - Accumulator with register + + ! CHECK: error: invalid operand for instruction + rand %sp, %o0 + +// Section 6.3.4 - Arithmetic operations - Accumulator with immediate + + ! CHECK: error: invalid operand for instruction + raddcc 16, %l4 + + ! CHECK: error: invalid operand for instruction + raddcc -17, %l4 + + ! CHECK: error: invalid operand for instruction + rsll 32, %l5 + + ! CHECK: error: invalid operand for instruction + rsll -1, %l5 + +// Section 6.3.5 - Comparison with register + +// Section 6.3.6 - Comparison with immediate + +// Section 6.3.7 - Constant assignment + +// Section 6.3.8 - Bit-mask operations + +// Section 6.3.9 - Register to register copy + +// Section 6.3.10 - Negation + +// Section 6.3.11 - Return instructions + +// Section 6.3.12 - Load/Store - 8/16/32/64 - one register + + ! CHECK: error: invalid operand for instruction + rldub [%g1], %o1 + + ! CHECK: error: invalid operand for instruction + rldd [%i0], %i1 + + ! CHECK: error: invalid operand for instruction + rlddf [%i0], %f1 + +// Section 6.3.13 - Load/Store - 8/16/32/64 - fixed register plus immediate + + ! CHECK: error: invalid operand for instruction + rld [%i1 + 4], %i0 + ! CHECK: error: invalid operand for instruction + rldf [%o0 + 4], %f0 + ! CHECK: error: invalid operand for instruction + rldf [%sp + 1], %f0 + ! CHECK: error: invalid operand for instruction + rldf [%sp - 4], %f0 + ! CHECK: error: invalid operand for instruction + rldf [%sp + 128], %f0 + +// Section 6.3.14 - Load/Store - 8/16/32/64 - one register - auto-incrementing + +// Section 6.3.15 - Miscellaneous operations - no source operands + + ! CHECK: error: invalid operand for instruction + rta -1 + ! CHECK: error: invalid operand for instruction + rta 8 + +// Section 6.4.1 - Branch on integer condition codes - long + + ! CHECK: error: invalid operand for instruction + rbleu,l 16777216 + + ! CHECK: error: invalid operand for instruction + rbleu,l -16777218 + + ! CHECK: error: invalid operand for instruction + rbleu,l 3 + +// Section 6.4.2 - Branch on floating-point condition codes - long + +// Section 6.4.3 - Call and link + +// Section 6.4.4 - Constant assignment + + ! CHECK: error: invalid operand for instruction + rset21 1048576, %l4 + ! CHECK: error: invalid operand for instruction + rset21 -1048577, %l4 + +// Section 6.4.5 - Generic format 3 SPARC operation + +// Section 6.4.6 - Floating-point operations + +// Section 6.5.1 - Set 32-bit constant + +// Section 6.5.2 - Load from 32-bit address Index: test/MC/Sparc/rex-instructions.s =================================================================== --- /dev/null +++ test/MC/Sparc/rex-instructions.s @@ -0,0 +1,475 @@ + ! RUN: llvm-mc %s -arch=sparc -mattr=+rex -show-encoding | FileCheck %s + ! RUN: llvm-mc %s -arch=sparc -mattr=+rex -filetype=obj + +// New SPARC instructions + +// Section 6.2.1 - SAVEREX and ADDREX + + ! CHECK: saverex %sp, -20, %sp ! encoding: [0x9d,0xe3,0x9f,0xec] + saverex %sp, -20, %sp + + ! CHECK: saverex %sp, -4096, %sp ! encoding: [0x9d,0xe3,0x90,0x00] + saverex %sp, -4096, %sp + + ! CHECK: addrex %sp, -20, %sp ! encoding: [0x9c,0x03,0x9f,0xec] + addrex %sp, -20, %sp + +// REX instructions + +// Section 6.3.1 - Branch on Integer Condition Codes - Short + +.BB0: + + ! CHECK: rbleu 10 ! encoding: [0x10,0x05] + rbleu 10 + + ! CHECK: rbleu -10 ! encoding: [0x10,0xfb] + rbleu -10 + + ! CHECK: rbleu 254 ! encoding: [0x10,0x7f] + rbleu 254 + + ! CHECK: rbleu -256 ! encoding: [0x10,0x80] + rbleu -256 + + ! CHECK: rbleu .BB0 ! encoding: [0x10,A] + ! CHECK-NEXT ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br8 + rbleu .BB0 + + ! CHECK: rba 10 ! encoding: [0x20,0x05] + rba 10 + ! CHECK: rbn 10 ! encoding: [0x00,0x05] + rbn 10 + ! CHECK: rbne 10 ! encoding: [0x24,0x05] + rbne 10 + ! CHECK: rbe 10 ! encoding: [0x04,0x05] + rbe 10 + ! CHECK: rbg 10 ! encoding: [0x28,0x05] + rbg 10 + ! CHECK: rble 10 ! encoding: [0x08,0x05] + rble 10 + ! CHECK: rbge 10 ! encoding: [0x2c,0x05] + rbge 10 + ! CHECK: rbl 10 ! encoding: [0x0c,0x05] + rbl 10 + ! CHECK: rbgu 10 ! encoding: [0x30,0x05] + rbgu 10 + ! CHECK: rbleu 10 ! encoding: [0x10,0x05] + rbleu 10 + ! CHECK: rbcc 10 ! encoding: [0x34,0x05] + rbcc 10 + ! CHECK: rbcs 10 ! encoding: [0x14,0x05] + rbcs 10 + ! CHECK: rbpos 10 ! encoding: [0x38,0x05] + rbpos 10 + ! CHECK: rbneg 10 ! encoding: [0x18,0x05] + rbneg 10 + ! CHECK: rbvc 10 ! encoding: [0x3c,0x05] + rbvc 10 + ! CHECK: rbvs 10 ! encoding: [0x1c,0x05] + rbvs 10 + +// Section 6.3.2 - Branch on Floating-Point Condition Codes - Short + + ! CHECK: rfbule 10 ! encoding: [0x39,0x05] + rfbule 10 + + ! CHECK: rfbule -10 ! encoding: [0x39,0xfb] + rfbule -10 + + ! CHECK: rfbule 254 ! encoding: [0x39,0x7f] + rfbule 254 + + ! CHECK: rfbule -256 ! encoding: [0x39,0x80] + rfbule -256 + + ! CHECK: rfbule .BB0 ! encoding: [0x39,A] + ! CHECK-NEXT ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br8 + rfbule .BB0 + + ! CHECK: rfba 10 ! encoding: [0x21,0x05] + rfba 10 + ! CHECK: rfbn 10 ! encoding: [0x01,0x05] + rfbn 10 + ! CHECK: rfbu 10 ! encoding: [0x1d,0x05] + rfbu 10 + ! CHECK: rfbg 10 ! encoding: [0x19,0x05] + rfbg 10 + ! CHECK: rfbug 10 ! encoding: [0x15,0x05] + rfbug 10 + ! CHECK: rfbl 10 ! encoding: [0x11,0x05] + rfbl 10 + ! CHECK: rfbul 10 ! encoding: [0x0d,0x05] + rfbul 10 + ! CHECK: rfblg 10 ! encoding: [0x09,0x05] + rfblg 10 + ! CHECK: rfbne 10 ! encoding: [0x05,0x05] + rfbne 10 + ! CHECK: rfbe 10 ! encoding: [0x25,0x05] + rfbe 10 + ! CHECK: rfbue 10 ! encoding: [0x29,0x05] + rfbue 10 + ! CHECK: rfbge 10 ! encoding: [0x2d,0x05] + rfbge 10 + ! CHECK: rfbuge 10 ! encoding: [0x31,0x05] + rfbuge 10 + ! CHECK: rfble 10 ! encoding: [0x35,0x05] + rfble 10 + ! CHECK: rfbo 10 ! encoding: [0x3d,0x05] + rfbo 10 + +// Section 6.3.3 - Arithmetic operations - Accumulator with register + + ! CHECK: radd %o0, %i7 ! encoding: [0xbc,0x00] + radd %o0, %i7 + ! CHECK: raddcc %o1, %fp ! encoding: [0xb8,0x11] + raddcc %o1, %i6 + ! CHECK: rsub %o2, %i5 ! encoding: [0xb4,0x22] + rsub %o2, %i5 + ! CHECK: rsubcc %o3, %i4 ! encoding: [0xb0,0x33] + rsubcc %o3, %i4 + ! CHECK: rand %l4, %i3 ! encoding: [0xac,0x44] + rand %l4, %i3 + ! CHECK: randcc %l5, %i2 ! encoding: [0xa8,0x55] + randcc %l5, %i2 + ! CHECK: randn %l6, %i1 ! encoding: [0xa5,0x46] + randn %l6, %i1 + ! CHECK: randncc %l7, %i0 ! encoding: [0xa1,0x57] + randncc %l7, %i0 + ! CHECK: ror %i0, %l7 ! encoding: [0x9c,0x88] + ror %i0, %l7 + ! CHECK: rorcc %i1, %l6 ! encoding: [0x98,0x99] + rorcc %i1, %l6 + ! CHECK: rorn %i2, %l5 ! encoding: [0x95,0x8a] + rorn %i2, %l5 + ! CHECK: rorncc %i3, %l4 ! encoding: [0x91,0x9b] + rorncc %i3, %l4 + ! CHECK: rxor %i4, %o3 ! encoding: [0x8c,0xcc] + rxor %i4, %o3 + ! CHECK: rxorcc %i5, %o2 ! encoding: [0x88,0xdd] + rxorcc %i5, %o2 + ! CHECK: rsll %fp, %o1 ! encoding: [0x85,0x6e] + rsll %i6, %o1 + ! CHECK: rsrl %i7, %o0 ! encoding: [0x81,0xaf] + rsrl %i7, %o0 + +// Section 6.3.4 - Arithmetic operations - Accumulator with immediate + + ! CHECK: raddcc 10, %l4 ! encoding: [0x92,0x0a] + raddcc 10, %l4 + + ! CHECK: raddcc 15, %l4 ! encoding: [0x92,0x0f] + raddcc 15, %l4 + + ! CHECK: raddcc -16, %l4 ! encoding: [0x92,0x10] + raddcc -16, %l4 + + ! CHECK: rsll 4, %l5 ! encoding: [0x97,0x64] + rsll 4, %l5 + + ! CHECK: rsll 31, %l5 ! encoding: [0x97,0x7f] + rsll 31, %l5 + + ! CHECK: rsrl 2, %l6 ! encoding: [0x9b,0xa2] + rsrl 2, %l6 + +// Section 6.3.5 - Comparison with register + + ! CHECK: rcmp %l6, %o1 ! encoding: [0x99,0x71] + rcmp %l6, %o1 + +// Section 6.3.6 - Comparison with immediate + + ! CHECK: rcmp %l4, 10 ! encoding: [0x93,0x0a] + rcmp %l4, 10 + +// Section 6.3.7 - Constant assignment + + ! CHECK: rset5 10, %o1 ! encoding: [0x86,0x2a] + rset5 10, %o1 + + ! CHECK: rone 4, %o1 ! encoding: [0x86,0xa4] + rone 4, %o1 + +// Section 6.3.8 - Bit-mask operations + + ! CHECK: rsetbit 13, %o3 ! encoding: [0x8e,0x8d] + rsetbit 13, %o3 + + ! CHECK: rclrbit 13, %o3 ! encoding: [0x8f,0x4d] + rclrbit 13, %o3 + + ! CHECK: rinvbit 13, %o3 ! encoding: [0x8e,0xcd] + rinvbit 13, %o3 + + ! CHECK: rmasklo 13, %o3 ! encoding: [0x8e,0x4d] + rmasklo 13, %o3 + + ! CHECK: rtstbit 13, %o3 ! encoding: [0x8e,0x6d] + rtstbit 13, %o3 + +// Section 6.3.9 - Register to register copy + + ! CHECK: rmov %o2, %g3 ! encoding: [0xad,0x22] + rmov %o2, %g3 + +// Section 6.3.10 - Negation + + ! CHECK: rneg %o3 ! encoding: [0x8f,0xc4] + rneg %o3 + + ! CHECK: rnot %o3 ! encoding: [0x8f,0xc5] + rnot %o3 + +// Section 6.3.11 - Return instructions + + ! CHECK: rretrest ! encoding: [0x83,0xc0] + rretrest + + ! CHECK: rretl ! encoding: [0x83,0xc1] + rretl + +// Section 6.3.12 - Load/Store - 8/16/32/64 - one register + + ! CHECK: rld [%o3], %l4 ! encoding: [0xd0,0x03] + rld [%o3], %l4 + ! CHECK: rldub [%o3], %l4 ! encoding: [0xd0,0x43] + rldub [%o3], %l4 + ! CHECK: rlduh [%o3], %l4 ! encoding: [0xd0,0x83] + rlduh [%o3], %l4 + ! CHECK: rldd [%o3], %l4 ! encoding: [0xd0,0xc3] + rldd [%o3], %l4 + ! CHECK: rldf [%o3], %f1 ! encoding: [0xe4,0x23] + rldf [%o3], %f1 + ! CHECK: rlddf [%o3], %f2 ! encoding: [0xe8,0xa3] + rlddf [%o3], %f2 + + ! CHECK: rst %l4, [%o3] ! encoding: [0xd1,0x03] + rst %l4, [%o3] + ! CHECK: rstb %l4, [%o3] ! encoding: [0xd1,0x43] + rstb %l4, [%o3] + ! CHECK: rsth %l4, [%o3] ! encoding: [0xd1,0x83] + rsth %l4, [%o3] + ! CHECK: rstd %l4, [%o3] ! encoding: [0xd1,0xc3] + rstd %l4, [%o3] + ! CHECK: rstf %f1, [%o3] ! encoding: [0xe5,0x23] + rstf %f1, [%o3] + ! CHECK: rstdf %f4, [%l4] ! encoding: [0xf1,0xa4] + rstdf %f4, [%l4] + +// Section 6.3.13 - Load/Store - 8/16/32/64 - fixed register plus immediate + + ! CHECK: rld [%i0+124], %l4 ! encoding: [0xd2,0x9f] + rld [%i0+124], %l4 + ! CHECK: rld [%i0+40], %l4 ! encoding: [0xd2,0x8a] + rld [%i0+40], %l4 + ! CHECK: rld [%o0+40], %l4 ! encoding: [0xd2,0xca] + rld [%o0+40], %l4 + ! CHECK: rld [%fp+40], %l4 ! encoding: [0xd2,0x0a] + rld [%fp+40], %l4 + ! CHECK: rld [%sp+40], %l4 ! encoding: [0xd2,0x4a] + rld [%sp+40], %l4 + ! CHECK: rldf [%i0+40], %f1 ! encoding: [0xe6,0xaa] + rldf [%i0+40], %f1 + ! CHECK: rldf [%fp+40], %f1 ! encoding: [0xe6,0x2a] + rldf [%fp+40], %f1 + ! CHECK: rldf [%sp+40], %f1 ! encoding: [0xe6,0x6a] + rldf [%sp+40], %f1 + + ! CHECK: rst %l4, [%i0+40] ! encoding: [0xd3,0x8a] + rst %l4, [%i0+40] + ! CHECK: rst %l4, [%o0+40] ! encoding: [0xd3,0xca] + rst %l4, [%o0+40] + ! CHECK: rst %l4, [%fp+40] ! encoding: [0xd3,0x0a] + rst %l4, [%fp+40] + ! CHECK: rst %l4, [%sp+40] ! encoding: [0xd3,0x4a] + rst %l4, [%sp+40] + ! CHECK: rstf %f1, [%i0+40] ! encoding: [0xe7,0xaa] + rstf %f1, [%i0+40] + ! CHECK: rstf %f1, [%fp+40] ! encoding: [0xe7,0x2a] + rstf %f1, [%fp+40] + ! CHECK: rstf %f1, [%sp+40] ! encoding: [0xe7,0x6a] + rstf %f1, [%sp+40] + +// Section 6.3.14 - Load/Store - 8/16/32/64 - one register - auto-incrementing + + ! CHECK: rldinc [%o3], %l4 ! encoding: [0xd0,0x13] + rldinc [%o3], %l4 + ! CHECK: rldubinc [%o3], %l4 ! encoding: [0xd0,0x53] + rldubinc [%o3], %l4 + ! CHECK: rlduhinc [%o3], %l4 ! encoding: [0xd0,0x93] + rlduhinc [%o3], %l4 + ! CHECK: rlddinc [%o3], %l4 ! encoding: [0xd0,0xd3] + rlddinc [%o3], %l4 + ! CHECK: rldfinc [%o3], %f1 ! encoding: [0xe4,0x33] + rldfinc [%o3], %f1 + ! CHECK: rlddfinc [%o3], %f2 ! encoding: [0xe8,0xb3] + rlddfinc [%o3], %f2 + + ! CHECK: rstinc %l4, [%o3] ! encoding: [0xd1,0x13] + rstinc %l4, [%o3] + ! CHECK: rstbinc %l4, [%o3] ! encoding: [0xd1,0x53] + rstbinc %l4, [%o3] + ! CHECK: rsthinc %l4, [%o3] ! encoding: [0xd1,0x93] + rsthinc %l4, [%o3] + ! CHECK: rstdinc %l4, [%o3] ! encoding: [0xd1,0xd3] + rstdinc %l4, [%o3] + ! CHECK: rstfinc %f1, [%o3] ! encoding: [0xe5,0x33] + rstfinc %f1, [%o3] + ! CHECK: rstdfinc %f4, [%l4] ! encoding: [0xf1,0xb4] + rstdfinc %f4, [%l4] + +// Section 6.3.15 - Miscellaneous operations - no source operands + + ! CHECK: rpush %l4 ! encoding: [0x93,0xc2] + rpush %l4 + + ! CHECK: rpop %l4 ! encoding: [0x93,0xc3] + rpop %l4 + + ! CHECK: rta 5 ! encoding: [0x97,0xc6] + rta 5 + + ! CHECK: rleave ! encoding: [0x83,0xc7] + rleave + + ! CHECK: rgetpc %l4 ! encoding: [0x93,0xc9] + rgetpc %l4 + +// Section 6.4.1 - Branch on integer condition codes - long + + ! CHECK: rbleu,l 50000 ! encoding: [0x12,0xa8,0x00,0x61] + rbleu,l 50000 + + ! CHECK: rbleu,l -50000 ! encoding: [0x12,0x58,0xff,0x9e] + rbleu,l -50000 + + ! CHECK: rbleu,l .BB0 ! encoding: [0x12,A,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br24 + rbleu,l .BB0 + + ! CHECK: rba,l 50000 ! encoding: [0x22,0xa8,0x00,0x61] + rba,l 50000 + ! CHECK: rbn,l 50000 ! encoding: [0x02,0xa8,0x00,0x61] + rbn,l 50000 + ! CHECK: rbne,l 50000 ! encoding: [0x26,0xa8,0x00,0x61] + rbne,l 50000 + ! CHECK: rbe,l 50000 ! encoding: [0x06,0xa8,0x00,0x61] + rbe,l 50000 + ! CHECK: rbg,l 50000 ! encoding: [0x2a,0xa8,0x00,0x61] + rbg,l 50000 + ! CHECK: rble,l 50000 ! encoding: [0x0a,0xa8,0x00,0x61] + rble,l 50000 + ! CHECK: rbge,l 50000 ! encoding: [0x2e,0xa8,0x00,0x61] + rbge,l 50000 + ! CHECK: rbl,l 50000 ! encoding: [0x0e,0xa8,0x00,0x61] + rbl,l 50000 + ! CHECK: rbgu,l 50000 ! encoding: [0x32,0xa8,0x00,0x61] + rbgu,l 50000 + ! CHECK: rbleu,l 50000 ! encoding: [0x12,0xa8,0x00,0x61] + rbleu,l 50000 + ! CHECK: rbcc,l 50000 ! encoding: [0x36,0xa8,0x00,0x61] + rbcc,l 50000 + ! CHECK: rbcs,l 50000 ! encoding: [0x16,0xa8,0x00,0x61] + rbcs,l 50000 + ! CHECK: rbpos,l 50000 ! encoding: [0x3a,0xa8,0x00,0x61] + rbpos,l 50000 + ! CHECK: rbneg,l 50000 ! encoding: [0x1a,0xa8,0x00,0x61] + rbneg,l 50000 + ! CHECK: rbvc,l 50000 ! encoding: [0x3e,0xa8,0x00,0x61] + rbvc,l 50000 + ! CHECK: rbvs,l 50000 ! encoding: [0x1e,0xa8,0x00,0x61] + rbvs,l 50000 + +// Section 6.4.2 - Branch on floating-point condition codes - long + + ! CHECK: rfbule,l 50000 ! encoding: [0x3b,0xa8,0x00,0x61] + rfbule,l 50000 + + ! CHECK: rfbule,l -50000 ! encoding: [0x3b,0x58,0xff,0x9e] + rfbule,l -50000 + + ! CHECK: rfbule,l .BB0 ! encoding: [0x3b,A,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br24 + rfbule,l .BB0 + + ! CHECK: rfba,l 50000 ! encoding: [0x23,0xa8,0x00,0x61] + rfba,l 50000 + ! CHECK: rfbn,l 50000 ! encoding: [0x03,0xa8,0x00,0x61] + rfbn,l 50000 + ! CHECK: rfbu,l 50000 ! encoding: [0x1f,0xa8,0x00,0x61] + rfbu,l 50000 + ! CHECK: rfbg,l 50000 ! encoding: [0x1b,0xa8,0x00,0x61] + rfbg,l 50000 + ! CHECK: rfbug,l 50000 ! encoding: [0x17,0xa8,0x00,0x61] + rfbug,l 50000 + ! CHECK: rfbl,l 50000 ! encoding: [0x13,0xa8,0x00,0x61] + rfbl,l 50000 + ! CHECK: rfbul,l 50000 ! encoding: [0x0f,0xa8,0x00,0x61] + rfbul,l 50000 + ! CHECK: rfblg,l 50000 ! encoding: [0x0b,0xa8,0x00,0x61] + rfblg,l 50000 + ! CHECK: rfbne,l 50000 ! encoding: [0x07,0xa8,0x00,0x61] + rfbne,l 50000 + ! CHECK: rfbe,l 50000 ! encoding: [0x27,0xa8,0x00,0x61] + rfbe,l 50000 + ! CHECK: rfbue,l 50000 ! encoding: [0x2b,0xa8,0x00,0x61] + rfbue,l 50000 + ! CHECK: rfbge,l 50000 ! encoding: [0x2f,0xa8,0x00,0x61] + rfbge,l 50000 + ! CHECK: rfbuge,l 50000 ! encoding: [0x33,0xa8,0x00,0x61] + rfbuge,l 50000 + ! CHECK: rfble,l 50000 ! encoding: [0x37,0xa8,0x00,0x61] + rfble,l 50000 + ! CHECK: rfbo,l 50000 ! encoding: [0x3f,0xa8,0x00,0x61] + rfbo,l 50000 + +// Section 6.4.3 - Call and link + + ! CHECK: call 50000 ! encoding: [0x40,0x00,0x30,0xd4] + call 50000 + + ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: foo+2, kind: fixup_sparc_call30 + call foo + +// Section 6.4.4 - Constant assignment + + ! CHECK: rset21 50000, %l4 ! encoding: [0x92,0xf0,0x06,0x1a] + rset21 50000, %l4 + +// Section 6.4.5 - Generic format 3 SPARC operation + +// Section 6.4.6 - Floating-point operations + +// Section 6.5.1 - Set 32-bit constant + + ! CHECK: rset32 50000, %l4 ! encoding: [0x93,0xe8,0x00,0x00,0xc3,0x50] + rset32 50000, %l4 + + ! CHECK: rset32 foo, %l4 ! encoding: [0x93,0xe8,A,A,A,A] + ! fixup A - offset: 2, value: foo, kind: fixup_sparc_32 + rset32 foo, %l4 + + ! CHECK: rset32pc 50000, %l4 ! encoding: [0x93,0xe9,0x00,0x00,0xc3,0x50] + rset32pc 50000, %l4 + + ! CHECK: rset32pc foo, %l4 ! encoding: [0x93,0xe9,A,A,A,A] + ! fixup A - offset: 2, value: foo, kind: fixup_sparc_disp32 + rset32pc foo, %l4 + +// Section 6.5.2 - Load from 32-bit address + + ! CHECK: rld32 [50000], %l4 ! encoding: [0x93,0xea,0x00,0x00,0xc3,0x50] + rld32 [50000], %l4 + + ! CHECK: rld32 [foo], %l4 ! encoding: [0x93,0xea,A,A,A,A] + ! fixup A - offset: 2, value: foo, kind: fixup_sparc_32 + rld32 [foo], %l4 + + ! CHECK: rld32pc [50000], %l4 ! encoding: [0x93,0xeb,0x00,0x00,0xc3,0x50] + rld32pc [50000], %l4 + + ! CHECK: rld32pc [foo], %l4 ! encoding: [0x93,0xeb,A,A,A,A] + ! fixup A - offset: 2, value: foo, kind: fixup_sparc_disp32 + rld32pc [foo], %l4 Index: test/MC/Sparc/rex-nop-data.s =================================================================== --- /dev/null +++ test/MC/Sparc/rex-nop-data.s @@ -0,0 +1,9 @@ +! RUN: llvm-mc %s -arch=sparc -mattr=rex -filetype=obj | llvm-readobj -s -sd | FileCheck %s + +! CHECK: 0000: B4CD0000 00000000 00000000 00000000 +! CHECK: 0010: B4CD + +foo: + rxor %i5, %i5 + .align 16 + rxor %i5, %i5