From bb3de6f2aebb098189232c62c6b5619d75058f63 Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Thu, 26 Dec 2024 02:19:15 +0300 Subject: [PATCH 1/4] [Xtensa] Implement Windowed Register Option. --- .../Xtensa/AsmParser/XtensaAsmParser.cpp | 16 +++ .../Disassembler/XtensaDisassembler.cpp | 29 ++++- .../Xtensa/MCTargetDesc/XtensaInstPrinter.cpp | 34 +++++ .../Xtensa/MCTargetDesc/XtensaInstPrinter.h | 3 + .../MCTargetDesc/XtensaMCCodeEmitter.cpp | 52 ++++++++ llvm/lib/Target/Xtensa/Xtensa.td | 10 +- llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 121 ++++++++++++++++++ llvm/lib/Target/Xtensa/XtensaOperands.td | 21 +++ llvm/lib/Target/Xtensa/XtensaRegisterInfo.td | 6 +- llvm/lib/Target/Xtensa/XtensaSubtarget.h | 5 + llvm/test/MC/Disassembler/Xtensa/windowed.txt | 64 +++++++++ .../Xtensa/windowed_code_density.txt | 12 ++ llvm/test/MC/Xtensa/windowed.s | 80 ++++++++++++ llvm/test/MC/Xtensa/windowed_code_density.s | 14 ++ llvm/test/MC/Xtensa/windowed_invalid.s | 15 +++ 15 files changed, 478 insertions(+), 4 deletions(-) create mode 100644 llvm/test/MC/Disassembler/Xtensa/windowed.txt create mode 100644 llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt create mode 100644 llvm/test/MC/Xtensa/windowed.s create mode 100644 llvm/test/MC/Xtensa/windowed_code_density.s create mode 100644 llvm/test/MC/Xtensa/windowed_invalid.s diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp index 731f9535ca251..fc1f214efe667 100644 --- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp +++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp @@ -181,6 +181,8 @@ struct XtensaOperand : public MCParsedAsmOperand { ((cast(getImm())->getValue() & 0x3) == 0); } + bool isentry_imm12() const { return isImm(0, 32760); } + bool isUimm4() const { return isImm(0, 15); } bool isUimm5() const { return isImm(0, 31); } @@ -198,6 +200,11 @@ struct XtensaOperand : public MCParsedAsmOperand { bool isImm32n_95() const { return isImm(-32, 95); } + bool isImm64n_4n() const { + return isImm(-64, -4) && + ((dyn_cast(getImm())->getValue() & 0x3) == 0); + } + bool isB4const() const { if (Kind != Immediate) return false; @@ -491,6 +498,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 +528,9 @@ 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]"); } report_fatal_error("Unknown match type detected!"); diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp index c11c4b7038bdb..1f4197f573ce6 100644 --- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp +++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp @@ -73,7 +73,8 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, return MCDisassembler::Success; } -static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3}; +static const unsigned SRDecoderTable[] = { + Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73}; static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, @@ -210,6 +211,32 @@ 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"); + if (Imm > 7) + Inst.addOperand(MCOperand::createImm(Imm - 16)); + else + Inst.addOperand(MCOperand::createImm(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/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td index 460a15e808b3a..d6dedb6c760ab 100644 --- a/llvm/lib/Target/Xtensa/Xtensa.td +++ b/llvm/lib/Target/Xtensa/Xtensa.td @@ -18,9 +18,15 @@ include "llvm/Target/Target.td" // Subtarget Features. //===----------------------------------------------------------------------===// def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true", - "Enable Density instructions">; + "Enable Density instructions">; def HasDensity : Predicate<"Subtarget->hasDensity()">, - AssemblerPredicate<(all_of FeatureDensity)>; + AssemblerPredicate<(all_of FeatureDensity)>; + +def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true", + "Enable Xtensa Windowed Register option">; +def HasWindowed : Predicate<"Subtarget->hasWindowed()">, + AssemblerPredicate<(all_of FeatureWindowed)>; + //===----------------------------------------------------------------------===// // Xtensa supported processors. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td index 699d0d6cf8044..d09c4264dd166 100644 --- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td @@ -678,3 +678,124 @@ 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 { + def CALL4 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), + "call4\t$offset", []>, Requires<[HasWindowed]> { + let n = 1; + } + + def CALL8 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), + "call8\t$offset", []>, Requires<[HasWindowed]> { + let n = 2; + } + + def CALL12 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), + "call12\t$offset", []>, Requires<[HasWindowed]> { + let n = 3; + } + + def CALLX4 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), + "callx4\t$s", []>, Requires<[HasWindowed]> { + let m = 0x3; + let n = 0x1; + let r = 0; + } + + def CALLX8 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), + "callx8\t$s", []>, Requires<[HasWindowed]> { + let m = 0x3; + let n = 0x2; + let r = 0; + } + + def CALLX12 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), + "callx12\t$s", []>, Requires<[HasWindowed]> { + let m = 0x3; + let n = 0x3; + 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..dd12bd2390499 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 & 0x3 == 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..1cdd0f9f5baf7 100644 --- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h +++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h @@ -39,6 +39,9 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo { // Enabled Xtensa Density extension 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..880a691af9ddf --- /dev/null +++ b/llvm/test/MC/Disassembler/Xtensa/windowed.txt @@ -0,0 +1,64 @@ +# 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 +# code density option enabled. Also verify that dissasembling without +# density 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 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..376677595ac3d --- /dev/null +++ b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt @@ -0,0 +1,12 @@ +# 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 +# code density option enabled. Also verify that dissasembling without +# density option 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..38e36b225723a --- /dev/null +++ b/llvm/test/MC/Xtensa/windowed.s @@ -0,0 +1,80 @@ +# 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 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..169096b09caba --- /dev/null +++ b/llvm/test/MC/Xtensa/windowed_invalid.s @@ -0,0 +1,15 @@ +# 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] + +# 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] From d36e6d20dc30e0d6fff5ea689525da5b2acea111 Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Sun, 29 Dec 2024 17:54:50 +0300 Subject: [PATCH 2/4] [Xtensa] Fix Windowed Option tests and AsmParser. --- .../Xtensa/AsmParser/XtensaAsmParser.cpp | 37 ++++++++++++-- .../Disassembler/XtensaDisassembler.cpp | 29 +++++++++-- llvm/lib/Target/Xtensa/Xtensa.td | 11 +---- llvm/lib/Target/Xtensa/XtensaFeatures.td | 14 ++++++ llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 48 ++++++------------- llvm/lib/Target/Xtensa/XtensaOperands.td | 2 +- llvm/test/MC/Disassembler/Xtensa/windowed.txt | 12 ++++- .../Xtensa/windowed_code_density.txt | 6 +-- llvm/test/MC/Xtensa/windowed.s | 25 ++++++++++ llvm/test/MC/Xtensa/windowed_invalid.s | 10 +++- 10 files changed, 136 insertions(+), 58 deletions(-) create mode 100644 llvm/lib/Target/Xtensa/XtensaFeatures.td diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp index fc1f214efe667..fc8140aeb7ead 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; } + bool checkRegister(MCRegister RegNo); 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,7 +186,10 @@ struct XtensaOperand : public MCParsedAsmOperand { ((cast(getImm())->getValue() & 0x3) == 0); } - bool isentry_imm12() const { return isImm(0, 32760); } + bool isentry_imm12() const { + return isImm(0, 32760) && + ((cast(getImm())->getValue() % 8) == 0); + } bool isUimm4() const { return isImm(0, 15); } @@ -202,7 +210,7 @@ struct XtensaOperand : public MCParsedAsmOperand { bool isImm64n_4n() const { return isImm(-64, -4) && - ((dyn_cast(getImm())->getValue() & 0x3) == 0); + ((cast(getImm())->getValue() & 0x3) == 0); } bool isB4const() const { @@ -530,7 +538,8 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, "should be zero"); case Match_Invalidentry_imm12: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected immediate in range [0, 32760]"); + "expected immediate in range [0, 32760], first 3 bits " + "should be zero"); } report_fatal_error("Unknown match type detected!"); @@ -617,6 +626,10 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands, getLexer().UnLex(Buf[0]); return ParseStatus::NoMatch; } + + if (!checkRegister(RegNo)) + return ParseStatus::NoMatch; + if (HadParens) Operands.push_back(XtensaOperand::createToken("(", FirstS)); SMLoc S = getLoc(); @@ -718,7 +731,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, if (RegNo == 0) RegNo = MatchRegisterAltName(RegName); - if (RegNo == 0) + if (!checkRegister(RegNo)) return Error(NameLoc, "invalid register name"); // Parse operand @@ -842,6 +855,22 @@ ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) { return ParseStatus::NoMatch; } +// Verify Special Register +bool XtensaAsmParser::checkRegister(MCRegister RegNo) { + bool Res = true; + + switch (RegNo) { + case Xtensa::WINDOWBASE: + case Xtensa::WINDOWSTART: + Res = hasWindowed(); + break; + case Xtensa::NoRegister: + Res = false; + } + + return Res; +} + // Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() { RegisterMCAsmParser X(getTheXtensaTarget()); diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp index 1f4197f573ce6..0cab74e104f6d 100644 --- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp +++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp @@ -73,18 +73,42 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, return MCDisassembler::Success; } +// Verify SR +bool CheckRegister(unsigned RegNo, MCSubtargetInfo STI) { + bool Res = true; + + switch (RegNo) { + case Xtensa::WINDOWBASE: + case Xtensa::WINDOWSTART: + Res = STI.getFeatureBits()[Xtensa::FeatureWindowed]; + break; + default: + Res = false; + break; + } + + return Res; +} + static 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 llvm::MCSubtargetInfo STI = + ((const MCDisassembler *)Decoder)->getSubtargetInfo(); + 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 (!CheckRegister(Reg, STI)) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -214,10 +238,7 @@ static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm, static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder) { assert(isUInt<4>(Imm) && "Invalid immediate"); - if (Imm > 7) - Inst.addOperand(MCOperand::createImm(Imm - 16)); - else - Inst.addOperand(MCOperand::createImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm)); return MCDisassembler::Success; } diff --git a/llvm/lib/Target/Xtensa/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td index d6dedb6c760ab..2c4bacbe8282b 100644 --- a/llvm/lib/Target/Xtensa/Xtensa.td +++ b/llvm/lib/Target/Xtensa/Xtensa.td @@ -17,15 +17,8 @@ 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)>; - -def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true", - "Enable Xtensa Windowed Register option">; -def HasWindowed : Predicate<"Subtarget->hasWindowed()">, - AssemblerPredicate<(all_of FeatureWindowed)>; + +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 d09c4264dd166..5ef795a0e5287 100644 --- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td @@ -692,40 +692,20 @@ def ENTRY : BRI12_Inst<0x06, 0x3, 0x0, (outs), (ins AR:$s, entry_imm12:$imm), } let isCall = 1, Defs = [A0] in { - def CALL4 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), - "call4\t$offset", []>, Requires<[HasWindowed]> { - let n = 1; - } - - def CALL8 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), - "call8\t$offset", []>, Requires<[HasWindowed]> { - let n = 2; - } - - def CALL12 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), - "call12\t$offset", []>, Requires<[HasWindowed]> { - let n = 3; - } - - def CALLX4 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), - "callx4\t$s", []>, Requires<[HasWindowed]> { - let m = 0x3; - let n = 0x1; - let r = 0; - } - - def CALLX8 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), - "callx8\t$s", []>, Requires<[HasWindowed]> { - let m = 0x3; - let n = 0x2; - let r = 0; - } - - def CALLX12 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), - "callx12\t$s", []>, Requires<[HasWindowed]> { - let m = 0x3; - let n = 0x3; - let r = 0; + 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; + } } } diff --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td index dd12bd2390499..402e05a5c3dd1 100644 --- a/llvm/lib/Target/Xtensa/XtensaOperands.td +++ b/llvm/lib/Target/Xtensa/XtensaOperands.td @@ -133,7 +133,7 @@ def offset4m32 : Immediate; -def entry_imm12: Immediate= 0 && Imm <= 32760 && (Imm & 0x3 == 0); }], "Entry_Imm12_AsmOperand"> { +def entry_imm12: Immediate= 0 && Imm <= 32760 && (Imm % 8 == 0); }], "Entry_Imm12_AsmOperand"> { let EncoderMethod = "getEntry_Imm12OpValue"; let DecoderMethod = "decodeEntry_Imm12OpValue"; } diff --git a/llvm/test/MC/Disassembler/Xtensa/windowed.txt b/llvm/test/MC/Disassembler/Xtensa/windowed.txt index 880a691af9ddf..69f588efd73de 100644 --- a/llvm/test/MC/Disassembler/Xtensa/windowed.txt +++ b/llvm/test/MC/Disassembler/Xtensa/windowed.txt @@ -3,8 +3,8 @@ #------------------------------------------------------------------------------ # Verify that binary code is correctly disassembled with -# code density option enabled. Also verify that dissasembling without -# density option generates warnings. +# windowed register option enabled. Also verify that dissasembling without +# windowed register option generates warnings. #------------------------------------------------------------------------------ [0x36,0x03,0x01] @@ -62,3 +62,11 @@ [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 index 376677595ac3d..1b8c87e643f5d 100644 --- a/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt +++ b/llvm/test/MC/Disassembler/Xtensa/windowed_code_density.txt @@ -2,9 +2,9 @@ # 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 -# code density option enabled. Also verify that dissasembling without -# density option generates warnings. +# 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] diff --git a/llvm/test/MC/Xtensa/windowed.s b/llvm/test/MC/Xtensa/windowed.s index 38e36b225723a..3376469e3085b 100644 --- a/llvm/test/MC/Xtensa/windowed.s +++ b/llvm/test/MC/Xtensa/windowed.s @@ -78,3 +78,28 @@ rfwo # 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_invalid.s b/llvm/test/MC/Xtensa/windowed_invalid.s index 169096b09caba..d2d59e1157605 100644 --- a/llvm/test/MC/Xtensa/windowed_invalid.s +++ b/llvm/test/MC/Xtensa/windowed_invalid.s @@ -4,7 +4,15 @@ # entry_imm12 entry a3, -1 -# CHECK: :[[#@LINE-1]]:11: error: expected immediate in range [0, 32760] +# 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 From f7ddb6089bf5fd1845653d91aec60241fd14c8fb Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Fri, 10 Jan 2025 04:01:55 +0300 Subject: [PATCH 3/4] [Xtensa] Fix checkRegister function. --- .../Xtensa/AsmParser/XtensaAsmParser.cpp | 9 +++------ .../Disassembler/XtensaDisassembler.cpp | 20 ++++++++----------- llvm/lib/Target/Xtensa/XtensaSubtarget.h | 2 +- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp index fc8140aeb7ead..30ec849cc348b 100644 --- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp +++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp @@ -857,18 +857,15 @@ ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) { // Verify Special Register bool XtensaAsmParser::checkRegister(MCRegister RegNo) { - bool Res = true; - switch (RegNo) { case Xtensa::WINDOWBASE: case Xtensa::WINDOWSTART: - Res = hasWindowed(); - break; + return hasWindowed(); case Xtensa::NoRegister: - Res = false; + return false; } - return Res; + return true; } // Force static initialization. diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp index 0cab74e104f6d..863d71b95cdec 100644 --- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp +++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp @@ -74,20 +74,19 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, } // Verify SR -bool CheckRegister(unsigned RegNo, MCSubtargetInfo STI) { - bool Res = true; +bool checkRegister(unsigned RegNo, const MCDisassembler *Decoder) { + const FeatureBitset &FeatureBits = + Decoder->getSubtargetInfo().getFeatureBits(); switch (RegNo) { case Xtensa::WINDOWBASE: case Xtensa::WINDOWSTART: - Res = STI.getFeatureBits()[Xtensa::FeatureWindowed]; - break; + return FeatureBits[Xtensa::FeatureWindowed]; default: - Res = false; - break; + return false; } - return Res; + return true; } static const unsigned SRDecoderTable[] = { @@ -95,10 +94,7 @@ static const unsigned SRDecoderTable[] = { static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, - const void *Decoder) { - const llvm::MCSubtargetInfo STI = - ((const MCDisassembler *)Decoder)->getSubtargetInfo(); - + const MCDisassembler *Decoder) { if (RegNo > 255) return MCDisassembler::Fail; @@ -106,7 +102,7 @@ static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, if (SRDecoderTable[i + 1] == RegNo) { unsigned Reg = SRDecoderTable[i]; - if (!CheckRegister(Reg, STI)) + if (!checkRegister(Reg, Decoder)) return MCDisassembler::Fail; Inst.addOperand(MCOperand::createReg(Reg)); diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h index 1cdd0f9f5baf7..dddc0f7ef605d 100644 --- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h +++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h @@ -36,7 +36,7 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo { SelectionDAGTargetInfo TSInfo; XtensaFrameLowering FrameLowering; - // Enabled Xtensa Density extension + // Enabled Xtensa Density Option bool HasDensity; // Enabled Xtensa Windowed Register Option From 79e9b3b7784b8638b1ed1e8d33db3e2aaca471d5 Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Tue, 21 Jan 2025 03:12:13 +0300 Subject: [PATCH 4/4] [Xtensa] Move checkRegister function to XtensaUtils. --- .../Xtensa/AsmParser/XtensaAsmParser.cpp | 20 ++++--------------- .../Disassembler/XtensaDisassembler.cpp | 19 ++---------------- llvm/lib/Target/Xtensa/XtensaUtils.cpp | 13 ++++++++++++ llvm/lib/Target/Xtensa/XtensaUtils.h | 6 ++++++ 4 files changed, 25 insertions(+), 33 deletions(-) diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp index 30ec849cc348b..c15fc64c762f0 100644 --- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp +++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp @@ -12,6 +12,7 @@ #include "MCTargetDesc/XtensaMCTargetDesc.h" #include "MCTargetDesc/XtensaTargetStreamer.h" #include "TargetInfo/XtensaTargetInfo.h" +#include "XtensaUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" @@ -73,7 +74,7 @@ class XtensaAsmParser : public MCTargetAsmParser { SMLoc &EndLoc) override { return ParseStatus::NoMatch; } - bool checkRegister(MCRegister RegNo); + ParseStatus parsePCRelTarget(OperandVector &Operands); bool parseLiteralDirective(SMLoc L); @@ -627,7 +628,7 @@ ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands, return ParseStatus::NoMatch; } - if (!checkRegister(RegNo)) + if (!checkRegister(RegNo, getSTI().getFeatureBits())) return ParseStatus::NoMatch; if (HadParens) @@ -731,7 +732,7 @@ bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info, if (RegNo == 0) RegNo = MatchRegisterAltName(RegName); - if (!checkRegister(RegNo)) + if (!checkRegister(RegNo, getSTI().getFeatureBits())) return Error(NameLoc, "invalid register name"); // Parse operand @@ -855,19 +856,6 @@ ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) { return ParseStatus::NoMatch; } -// Verify Special Register -bool XtensaAsmParser::checkRegister(MCRegister RegNo) { - switch (RegNo) { - case Xtensa::WINDOWBASE: - case Xtensa::WINDOWSTART: - return hasWindowed(); - case Xtensa::NoRegister: - return false; - } - - return true; -} - // Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() { RegisterMCAsmParser X(getTheXtensaTarget()); diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp index 863d71b95cdec..63ab455c3d8c8 100644 --- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp +++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp @@ -14,6 +14,7 @@ #include "MCTargetDesc/XtensaMCTargetDesc.h" #include "TargetInfo/XtensaTargetInfo.h" +#include "XtensaUtils.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDecoderOps.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -73,22 +74,6 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, return MCDisassembler::Success; } -// Verify SR -bool checkRegister(unsigned RegNo, const MCDisassembler *Decoder) { - const FeatureBitset &FeatureBits = - Decoder->getSubtargetInfo().getFeatureBits(); - - switch (RegNo) { - case Xtensa::WINDOWBASE: - case Xtensa::WINDOWSTART: - return FeatureBits[Xtensa::FeatureWindowed]; - default: - return false; - } - - return true; -} - static const unsigned SRDecoderTable[] = { Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73}; @@ -102,7 +87,7 @@ static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, if (SRDecoderTable[i + 1] == RegNo) { unsigned Reg = SRDecoderTable[i]; - if (!checkRegister(Reg, Decoder)) + if (!checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits())) return MCDisassembler::Fail; Inst.addOperand(MCOperand::createReg(Reg)); diff --git a/llvm/lib/Target/Xtensa/XtensaUtils.cpp b/llvm/lib/Target/Xtensa/XtensaUtils.cpp index 98e424f6ea440..7db5ec84a497e 100644 --- a/llvm/lib/Target/Xtensa/XtensaUtils.cpp +++ b/llvm/lib/Target/Xtensa/XtensaUtils.cpp @@ -56,4 +56,17 @@ bool isValidAddrOffset(MachineInstr &MI, int64_t Offset) { return isValidAddrOffset(Scale, Offset); } +// Verify Special Register +bool 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; +} + } // namespace llvm diff --git a/llvm/lib/Target/Xtensa/XtensaUtils.h b/llvm/lib/Target/Xtensa/XtensaUtils.h index 2b0ac37a6971a..d56452307d12c 100644 --- a/llvm/lib/Target/Xtensa/XtensaUtils.h +++ b/llvm/lib/Target/Xtensa/XtensaUtils.h @@ -17,11 +17,17 @@ #include "llvm/CodeGen/MachineInstr.h" namespace llvm { + +class FeatureBitset; + // Check address offset for load/store instructions. // The offset should be multiple of scale. bool isValidAddrOffset(int Scale, int64_t OffsetVal); // Check address offset for load/store instructions. bool isValidAddrOffset(MachineInstr &MI, int64_t Offset); + +// Verify if it's correct to use a special register. +bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits); } // namespace llvm #endif // LLVM_LIB_TARGET_XTENSA_XTENSAUTILS_H