diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp index 731f9535ca251..0c9258ecd65ec 100644 --- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp +++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp @@ -73,6 +73,7 @@ class XtensaAsmParser : public MCTargetAsmParser { SMLoc &EndLoc) override { return ParseStatus::NoMatch; } + ParseStatus parsePCRelTarget(OperandVector &Operands); bool parseLiteralDirective(SMLoc L); @@ -89,6 +90,10 @@ class XtensaAsmParser : public MCTargetAsmParser { : MCTargetAsmParser(Options, STI, MII) { setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); } + + bool hasWindowed() const { + return getSTI().getFeatureBits()[Xtensa::FeatureWindowed]; + }; }; // Return true if Expr is in the range [MinValue, MaxValue]. @@ -181,6 +186,11 @@ struct XtensaOperand : public MCParsedAsmOperand { ((cast(getImm())->getValue() & 0x3) == 0); } + bool isentry_imm12() const { + return isImm(0, 32760) && + ((cast(getImm())->getValue() % 8) == 0); + } + bool isUimm4() const { return isImm(0, 15); } bool isUimm5() const { return isImm(0, 31); } @@ -198,6 +208,11 @@ struct XtensaOperand : public MCParsedAsmOperand { bool isImm32n_95() const { return isImm(-32, 95); } + bool isImm64n_4n() const { + return isImm(-64, -4) && + ((cast(getImm())->getValue() & 0x3) == 0); + } + bool isB4const() const { if (Kind != Immediate) return false; @@ -491,6 +506,12 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_InvalidImm32n_95: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected immediate in range [-32, 95]"); + case Match_InvalidImm64n_4n: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range [-64, -4]"); + case Match_InvalidImm8n_7: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range [-8, 7]"); case Match_InvalidShimm1_31: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected immediate in range [1, 31]"); @@ -515,6 +536,10 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected immediate in range [0, 60], first 2 bits " "should be zero"); + case Match_Invalidentry_imm12: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range [0, 32760], first 3 bits " + "should be zero"); } report_fatal_error("Unknown match type detected!"); @@ -601,6 +626,10 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands, getLexer().UnLex(Buf[0]); return ParseStatus::NoMatch; } + + if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits())) + return ParseStatus::NoMatch; + if (HadParens) Operands.push_back(XtensaOperand::createToken("(", FirstS)); SMLoc S = getLoc(); @@ -702,7 +731,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, if (RegNo == 0) RegNo = MatchRegisterAltName(RegName); - if (RegNo == 0) + if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits())) return Error(NameLoc, "invalid register name"); // Parse operand diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp index c11c4b7038bdb..7ad8a87ed599a 100644 --- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp +++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp @@ -57,7 +57,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() { createXtensaDisassembler); } -static const unsigned ARDecoderTable[] = { +const unsigned ARDecoderTable[] = { Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5, Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11, Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15}; @@ -73,17 +73,23 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, return MCDisassembler::Success; } -static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3}; +const unsigned SRDecoderTable[] = { + Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73}; static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, - const void *Decoder) { + const MCDisassembler *Decoder) { if (RegNo > 255) return MCDisassembler::Fail; for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) { if (SRDecoderTable[i + 1] == RegNo) { unsigned Reg = SRDecoderTable[i]; + + if (!Xtensa::checkRegister(Reg, + Decoder->getSubtargetInfo().getFeatureBits())) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -210,6 +216,29 @@ static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm, return MCDisassembler::Success; } +static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm, + int64_t Address, const void *Decoder) { + assert(isUInt<4>(Imm) && "Invalid immediate"); + Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm)); + return MCDisassembler::Success; +} + +static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm, + int64_t Address, + const void *Decoder) { + assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate"); + Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm))); + return MCDisassembler::Success; +} + +static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm, + int64_t Address, + const void *Decoder) { + assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate"); + Inst.addOperand(MCOperand::createImm(Imm)); + return MCDisassembler::Success; +} + static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder) { diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp index df8a0854f06f4..868c7f6c0b9c3 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp @@ -264,6 +264,28 @@ void XtensaInstPrinter::printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, printOperand(MI, OpNum, O); } +void XtensaInstPrinter::printImm8n_7_AsmOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + if (MI->getOperand(OpNum).isImm()) { + int64_t Value = MI->getOperand(OpNum).getImm(); + assert((Value >= -8 && Value <= 7) && + "Invalid argument, value must be in ranges <-8,7>"); + O << Value; + } else + printOperand(MI, OpNum, O); +} + +void XtensaInstPrinter::printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + if (MI->getOperand(OpNum).isImm()) { + int64_t Value = MI->getOperand(OpNum).getImm(); + assert((Value >= -64 && Value <= -4) & ((Value & 0x3) == 0) && + "Invalid argument, value must be in ranges <-64,-4>"); + O << Value; + } else + printOperand(MI, OpNum, O); +} + void XtensaInstPrinter::printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O) { if (MI->getOperand(OpNum).isImm()) { @@ -309,6 +331,18 @@ void XtensaInstPrinter::printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, printOperand(MI, OpNum, O); } +void XtensaInstPrinter::printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + if (MI->getOperand(OpNum).isImm()) { + int64_t Value = MI->getOperand(OpNum).getImm(); + assert((Value >= 0 && Value <= 32760) && + "Invalid argument, value must be multiples of eight in range " + "<0,32760>"); + O << Value; + } else + printOperand(MI, OpNum, O); +} + void XtensaInstPrinter::printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O) { if (MI->getOperand(OpNum).isImm()) { diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h index e5bc67869e103..630b4dd60108f 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h @@ -60,10 +60,13 @@ class XtensaInstPrinter : public MCInstPrinter { void printImm1_16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printImm1n_15_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printImm32n_95_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); + void printImm8n_7_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); + void printImm64n_4n_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printOffset8m8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printOffset8m16_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printOffset8m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printOffset4m32_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); + void printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); }; diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp index 51d4b8a9cc5fc..e6cdd3d0020fc 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp @@ -111,6 +111,18 @@ class XtensaMCCodeEmitter : public MCCodeEmitter { SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + uint32_t getImm8n_7OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + uint32_t getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + uint32_t getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; @@ -405,6 +417,46 @@ XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo, return Res; } +uint32_t +XtensaMCCodeEmitter::getImm8n_7OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + int32_t Res = static_cast(MO.getImm()); + + assert(((Res >= -8) && (Res <= 7)) && "Unexpected operand value!"); + + if (Res < 0) + return Res + 16; + + return Res; +} + +uint32_t +XtensaMCCodeEmitter::getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + int32_t Res = static_cast(MO.getImm()); + + assert(((Res >= -64) && (Res <= -4) && ((Res & 0x3) == 0)) && + "Unexpected operand value!"); + + return Res & 0x3f; +} + +uint32_t +XtensaMCCodeEmitter::getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + uint32_t res = static_cast(MO.getImm()); + + assert(((res & 0x7) == 0) && "Unexpected operand value!"); + + return res; +} + uint32_t XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp index fc23c2356825f..37dee072e5b3d 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp @@ -74,6 +74,19 @@ bool Xtensa::isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset) { return isValidAddrOffset(Scale, Offset); } +// Verify Special Register +bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits) { + switch (RegNo) { + case Xtensa::WINDOWBASE: + case Xtensa::WINDOWSTART: + return FeatureBits[Xtensa::FeatureWindowed]; + case Xtensa::NoRegister: + return false; + } + + return true; +} + static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT, const MCTargetOptions &Options) { diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h index 6be54867d84a7..649073b01f5c1 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.h @@ -19,12 +19,14 @@ namespace llvm { +class FeatureBitset; class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectTargetWriter; class MCObjectWriter; +class MCRegister; class MCRegisterInfo; class MCSubtargetInfo; class MCTargetOptions; @@ -52,6 +54,9 @@ bool isValidAddrOffset(int Scale, int64_t OffsetVal); // Check address offset for load/store instructions. bool isValidAddrOffsetForOpcode(unsigned Opcode, int64_t Offset); + +// Verify if it's correct to use a special register. +bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits); } // namespace Xtensa } // end namespace llvm diff --git a/llvm/lib/Target/Xtensa/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td index 460a15e808b3a..2c4bacbe8282b 100644 --- a/llvm/lib/Target/Xtensa/Xtensa.td +++ b/llvm/lib/Target/Xtensa/Xtensa.td @@ -17,10 +17,9 @@ include "llvm/Target/Target.td" //===----------------------------------------------------------------------===// // Subtarget Features. //===----------------------------------------------------------------------===// -def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true", - "Enable Density instructions">; -def HasDensity : Predicate<"Subtarget->hasDensity()">, - AssemblerPredicate<(all_of FeatureDensity)>; + +include "XtensaFeatures.td" + //===----------------------------------------------------------------------===// // Xtensa supported processors. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td new file mode 100644 index 0000000000000..6f24a674ae0ce --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td @@ -0,0 +1,14 @@ +//===----------------------------------------------------------------------===// +// Xtensa subtarget features. +//===----------------------------------------------------------------------===// + +// Xtensa ISA extensions (Xtensa Options). +def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true", + "Enable Density instructions">; +def HasDensity : Predicate<"Subtarget->hasDensity()">, + AssemblerPredicate<(all_of FeatureDensity)>; + +def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true", + "Enable Xtensa Windowed Register option">; +def HasWindowed : Predicate<"Subtarget->hasWindowed()">, + AssemblerPredicate<(all_of FeatureWindowed)>; diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td index 699d0d6cf8044..5ef795a0e5287 100644 --- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td @@ -678,3 +678,104 @@ let isReturn = 1, isTerminator = 1, let t = 0; } } + +//===----------------------------------------------------------------------===// +// Windowed instructions +//===----------------------------------------------------------------------===// + +def ENTRY : BRI12_Inst<0x06, 0x3, 0x0, (outs), (ins AR:$s, entry_imm12:$imm), + "entry\t$s, $imm", []>, Requires<[HasWindowed]> { + bits<15> imm; + + let imm12{11-0} = imm{14-3}; + let Defs = [SP]; +} + +let isCall = 1, Defs = [A0] in { + foreach i = {1,2,3} in { + defvar I = !mul(4, i); + + def CALL#I# : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), + "call"#I#"\t$offset", []>, Requires<[HasWindowed]> { + let n = i; + } + + def CALLX#I# : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), + "callx"#I#"\t$s", []>, Requires<[HasWindowed]> { + let m = 0x3; + let n = i; + let r = 0; + } + } +} + +def MOVSP : RRR_Inst<0x00, 0x00, 0x00, (outs AR:$t), (ins AR:$s), + "movsp\t$t, $s", []>, Requires<[HasWindowed]> { + let r = 0x01; +} + +let isReturn = 1, isTerminator = 1, + isBarrier = 1, Uses = [A0] in { + def RETW_N : RRRN_Inst<0x0D, (outs), (ins), + "retw.n", []>, Requires<[HasWindowed, HasDensity]> { + let r = 0x0F; + let s = 0; + let t = 1; + } + + def RETW : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins), + "retw", []>, Requires<[HasWindowed]> { + let m = 0x2; + let n = 0x1; + let s = 0; + let r = 0; + } +} + +def : InstAlias<"_retw", (RETW)>; +def : InstAlias<"_retw.n", (RETW_N)>; + +def S32E : RRI4_Inst<0x00, 0x09, (outs), (ins AR:$t, AR:$s, imm64n_4n:$imm), + "s32e\t$t, $s, $imm", []>, Requires<[HasWindowed]> { + bits<6> imm; + + let r = imm{5-2}; + let imm4 = 0x4; + let mayStore = 1; +} + +def L32E : RRI4_Inst<0x00, 0x09, (outs), (ins AR:$t, AR:$s, imm64n_4n:$imm), + "l32e\t$t, $s, $imm", []>, Requires<[HasWindowed]> { + bits<6> imm; + + let r = imm{5-2}; + let imm4 = 0x0; + let mayLoad = 1; +} + +def RFWU : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), + "rfwu", []>, Requires<[HasWindowed]> { + bits<4> imm; + + let r = 0x3; + let s = 0x5; + let t = 0x0; +} + +def RFWO : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), + "rfwo", []>, Requires<[HasWindowed]> { + bits<4> imm; + + let r = 0x3; + let s = 0x4; + let t = 0x0; +} + +def ROTW : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins imm8n_7:$imm), + "rotw\t$imm", []>, Requires<[HasWindowed]> { + bits<4> imm; + + let r = 0x8; + let s = 0x0; + let t = imm{3-0}; +} diff --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td index aa72fa0a56a6f..402e05a5c3dd1 100644 --- a/llvm/lib/Target/Xtensa/XtensaOperands.td +++ b/llvm/lib/Target/Xtensa/XtensaOperands.td @@ -37,6 +37,20 @@ def imm8_sh8 : Immediate= -32768 && Imm <= 32512 && ((Imm & let DecoderMethod = "decodeImm8_sh8Operand"; } +// imm8n_7 predicate - Immediate in the range [-8,7] +def Imm8n_7_AsmOperand: ImmAsmOperand<"Imm8n_7">; +def imm8n_7: Immediate= -8 && Imm <= 7; }], "Imm8n_7_AsmOperand"> { + let EncoderMethod = "getImm8n_7OpValue"; + let DecoderMethod = "decodeImm8n_7Operand"; +} + +// imm64n_4n predicate - Immediate in the range [-64,-4] +def Imm64n_4n_AsmOperand: ImmAsmOperand<"Imm64n_4n">; +def imm64n_4n: Immediate= -64 && Imm <= -4; }], "Imm64n_4n_AsmOperand"> { + let EncoderMethod = "getImm64n_4nOpValue"; + let DecoderMethod = "decodeImm64n_4nOperand"; +} + // imm12 predicate - Immediate in the range [-2048,2047] def Imm12_AsmOperand : ImmAsmOperand<"Imm12">; def imm12 : Immediate= -2048 && Imm <= 2047; }], "Imm12_AsmOperand"> { @@ -117,6 +131,13 @@ def offset4m32 : Immediate= 0 && Imm <= 60 && (Imm & 0x3 == 0); }], "Offset4m32_AsmOperand">; +// entry_imm12 predicate - Immediate in the range [0,32760], ENTRY parameter +def Entry_Imm12_AsmOperand: ImmAsmOperand<"entry_imm12">; +def entry_imm12: Immediate= 0 && Imm <= 32760 && (Imm % 8 == 0); }], "Entry_Imm12_AsmOperand"> { + let EncoderMethod = "getEntry_Imm12OpValue"; + let DecoderMethod = "decodeEntry_Imm12OpValue"; +} + // b4const predicate - Branch Immediate 4-bit signed operand def B4const_AsmOperand: ImmAsmOperand<"B4const">; def b4const: Immediate num, string n, list alt = []> : XtensaReg { // Shift Amount Register def SAR : SRReg<3, "sar", ["SAR","3"]>; -def SR : RegisterClass<"Xtensa", [i32], 32, (add SAR)>; +// Windowed Register Option registers +def WINDOWBASE : SRReg<72, "windowbase", ["WINDOWBASE", "72"]>; +def WINDOWSTART : SRReg<73, "windowstart", ["WINDOWSTART", "73"]>; + +def SR : RegisterClass<"Xtensa", [i32], 32, (add SAR, WINDOWBASE, WINDOWSTART)>; diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h index 948dcbc5278ea..dddc0f7ef605d 100644 --- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h +++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h @@ -36,9 +36,12 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo { SelectionDAGTargetInfo TSInfo; XtensaFrameLowering FrameLowering; - // Enabled Xtensa Density extension + // Enabled Xtensa Density Option bool HasDensity; + // Enabled Xtensa Windowed Register Option + bool HasWindowed; + XtensaSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); public: @@ -64,6 +67,8 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo { bool hasDensity() const { return HasDensity; } + bool hasWindowed() const { return HasWindowed; } + // Automatically generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); }; diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed.txt b/llvm/test/MC/Disassembler/Xtensa/windowed.txt new file mode 100644 index 0000000000000..34c51dd32b6be --- /dev/null +++ b/llvm/test/MC/Disassembler/Xtensa/windowed.txt @@ -0,0 +1,71 @@ +# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5 +# RUN: llvm-mc -triple=xtensa -mattr=+windowed -disassemble %s | FileCheck -check-prefixes=CHECK-WINDOWED %s +# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s + +## Verify that binary code is correctly disassembled with +## windowed register option enabled. Also verify that dissasembling without +## windowed register option generates warnings. + +[0x36,0x03,0x01] +# CHECK-WINDOWED: entry a3, 128 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x30,0x14,0x00] +# CHECK-WINDOWED: movsp a3, a4 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x15,0x10,0x00] +# CHECK-WINDOWED: call4 . +260 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x25,0x10,0x00] +# CHECK-WINDOWED: call8 . +260 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x35,0x10,0x00] +# CHECK-WINDOWED: call12 . +260 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0xd0,0x03,0x00] +# CHECK-WINDOWED: callx4 a3 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0xe0,0x03,0x00] +# CHECK-WINDOWED: callx8 a3 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0xf0,0x03,0x00] +# CHECK-WINDOWED: callx12 a3 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x90,0x00,0x00] +# CHECK-WINDOWED: retw +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x20,0x80,0x40] +# CHECK-WINDOWED: rotw 2 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x30,0xd4,0x09] +# CHECK-WINDOWED: l32e a3, a4, -12 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x30,0xd4,0x49] +# CHECK-WINDOWED: s32e a3, a4, -12 +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x00,0x34,0x00] +# CHECK-WINDOWED: rfwo +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x00,0x35,0x00] +# CHECK-WINDOWED: rfwu +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x30,0x48,0x61] +# CHECK-WINDOWED: xsr a3, windowbase +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0x30,0x49,0x61] +# CHECK-WINDOWED: xsr a3, windowstart +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt new file mode 100644 index 0000000000000..69d7d424d9682 --- /dev/null +++ b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt @@ -0,0 +1,11 @@ +# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5 +# RUN: llvm-mc -triple=xtensa -mattr=+windowed,+density -disassemble %s | FileCheck -check-prefixes=CHECK-WINDOWED-DENSITY %s +# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s + +## Verify that binary code is correctly disassembled with windowed register +## and code density options enabled. Also verify that +## dissasembling without these options generates warnings. + +[0x1d,0xf0] +# CHECK-WINDOWED-DENSITY: retw.n +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding diff --git a/llvm/test/MC/Xtensa/windowed.s b/llvm/test/MC/Xtensa/windowed.s new file mode 100644 index 0000000000000..3376469e3085b --- /dev/null +++ b/llvm/test/MC/Xtensa/windowed.s @@ -0,0 +1,105 @@ +# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+windowed \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +.align 4 +LBL0: + +# Instruction format BRI12 +# CHECK-INST: entry a3, 128 +# CHECK: encoding: [0x36,0x03,0x01] +entry a3, 128 + +# Instruction format RRR +# CHECK-INST: movsp a3, a4 +# CHECK: encoding: [0x30,0x14,0x00] +movsp a3, a4 + +# Instruction format CALL +# CHECK-INST: call4 LBL0 +# CHECK: encoding: [0bAA010101,A,A] +call4 LBL0 + +# Instruction format CALL +# CHECK-INST: call8 LBL0 +# CHECK: encoding: [0bAA100101,A,A] +call8 LBL0 + +# Instruction format CALL +# CHECK-INST: call12 LBL0 +# CHECK: encoding: [0bAA110101,A,A] +call12 LBL0 + +# Instruction format CALLX +# CHECK-INST: callx4 a3 +# CHECK: encoding: [0xd0,0x03,0x00] +callx4 a3 + +# Instruction format CALLX +# CHECK-INST: callx8 a3 +# CHECK: encoding: [0xe0,0x03,0x00] +callx8 a3 + +# Instruction format CALLX +# CHECK-INST: callx12 a3 +# CHECK: encoding: [0xf0,0x03,0x00] +callx12 a3 + +# Instruction format CALLX +# CHECK-INST: retw +# CHECK: encoding: [0x90,0x00,0x00] +retw + +# Instruction format CALLX +# CHECK-INST: retw +# CHECK: encoding: [0x90,0x00,0x00] +_retw + +# Instruction format RRR +# CHECK-INST: rotw 2 +# CHECK: encoding: [0x20,0x80,0x40] +rotw 2 + +# Instruction format RRI4 +# CHECK-INST: l32e a3, a4, -12 +# CHECK: encoding: [0x30,0xd4,0x09] +l32e a3, a4, -12 + +# Instruction format RRI4 +# CHECK-INST: s32e a3, a4, -12 +# CHECK: encoding: [0x30,0xd4,0x49] +s32e a3, a4, -12 + +# Instruction format RRR +# CHECK-INST: rfwo +# CHECK: encoding: [0x00,0x34,0x00] +rfwo + +# Instruction format RRR +# CHECK-INST: rfwu +# CHECK: encoding: [0x00,0x35,0x00] +rfwu + +# Instruction format RSR +# CHECK-INST: xsr a3, windowbase +# CHECK: # encoding: [0x30,0x48,0x61] +xsr a3, windowbase + +# CHECK-INST: xsr a3, windowbase +# CHECK: # encoding: [0x30,0x48,0x61] +xsr.windowbase a3 + +# CHECK-INST: xsr a3, windowbase +# CHECK: # encoding: [0x30,0x48,0x61] +xsr a3, 72 + +# CHECK-INST: xsr a3, windowstart +# CHECK: # encoding: [0x30,0x49,0x61] +xsr a3, windowstart + +# CHECK-INST: xsr a3, windowstart +# CHECK: # encoding: [0x30,0x49,0x61] +xsr.windowstart a3 + +# CHECK-INST: xsr a3, windowstart +# CHECK: # encoding: [0x30,0x49,0x61] +xsr a3, 73 diff --git a/llvm/test/MC/Xtensa/windowed_code_density.s b/llvm/test/MC/Xtensa/windowed_code_density.s new file mode 100644 index 0000000000000..e532657466fba --- /dev/null +++ b/llvm/test/MC/Xtensa/windowed_code_density.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+windowed,+density \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +.align 4 + +# Instruction format RRRN +# CHECK-INST: retw.n +# CHECK: encoding: [0x1d,0xf0] +retw.n + +# Instruction format RRRN +# CHECK-INST: retw.n +# CHECK: encoding: [0x1d,0xf0] +_retw.n diff --git a/llvm/test/MC/Xtensa/windowed_invalid.s b/llvm/test/MC/Xtensa/windowed_invalid.s new file mode 100644 index 0000000000000..958363093dd8e --- /dev/null +++ b/llvm/test/MC/Xtensa/windowed_invalid.s @@ -0,0 +1,35 @@ +// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5 +# RUN: not llvm-mc -triple xtensa --mattr=+windowed %s 2>&1 | FileCheck %s + +## Out of range immediates + + +# entry_imm12 + + +entry a3, -1 +// CHECK: :[[@LINE-1]]:11: error: expected immediate in range [0, 32760], first 3 bits should be zero + +# entry_imm12 + + +entry a3, 32764 +// CHECK: :[[@LINE-1]]:11: error: expected immediate in range [0, 32760], first 3 bits should be zero + +# entry_imm12 + + +entry a3, 4 +// CHECK: :[[@LINE-1]]:11: error: expected immediate in range [0, 32760], first 3 bits should be zero + +# imm8n_7 + + +rotw 100 +// CHECK: :[[@LINE-1]]:6: error: expected immediate in range [-8, 7] + +# imm64n_4n + + +l32e a3, a4, -100 +// CHECK: :[[@LINE-1]]:14: error: expected immediate in range [-64, -4]