[llvm] [Xtensa] Implement support of the ESP32S2 target. (PR #200130)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 11 01:09:05 PDT 2026
https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/200130
>From 11e39cd3865bf9076d5a4de5783a8b896d2a630b Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 28 May 2026 11:21:02 +0300
Subject: [PATCH 1/4] [Xtensa] Implement support of the ESP32S2 target.
---
.../llvm/TargetParser/XtensaTargetParser.def | 6 ++++
.../llvm/TargetParser/XtensaTargetParser.h | 3 +-
.../Xtensa/AsmParser/XtensaAsmParser.cpp | 5 +++
.../Disassembler/XtensaDisassembler.cpp | 8 +++++
.../Xtensa/MCTargetDesc/XtensaInstPrinter.cpp | 11 ++++++
.../Xtensa/MCTargetDesc/XtensaInstPrinter.h | 1 +
.../MCTargetDesc/XtensaMCCodeEmitter.cpp | 16 +++++++++
.../MCTargetDesc/XtensaMCTargetDesc.cpp | 8 +++++
llvm/lib/Target/Xtensa/XtensaFeatures.td | 5 +++
llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 34 +++++++++++++++++++
llvm/lib/Target/Xtensa/XtensaOperands.td | 7 ++++
llvm/lib/Target/Xtensa/XtensaProcessors.td | 5 +++
llvm/lib/Target/Xtensa/XtensaRegisterInfo.td | 6 +++-
llvm/lib/Target/Xtensa/XtensaSubtarget.h | 1 +
llvm/test/CodeGen/Xtensa/cpus.ll | 9 +++++
15 files changed, 123 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/TargetParser/XtensaTargetParser.def b/llvm/include/llvm/TargetParser/XtensaTargetParser.def
index b0afe6f161770..65a2fbacd1028 100644
--- a/llvm/include/llvm/TargetParser/XtensaTargetParser.def
+++ b/llvm/include/llvm/TargetParser/XtensaTargetParser.def
@@ -50,6 +50,7 @@ XTENSA_FEATURE(XF_TIMERS3, "timers3")
XTENSA_FEATURE(XF_PRID, "prid")
XTENSA_FEATURE(XF_REGPROTECT, "regprotect")
XTENSA_FEATURE(XF_MISCSR, "miscsr")
+XTENSA_FEATURE(XF_ESP32S2OPS, "esp32s2ops")
#undef XTENSA_FEATURE
@@ -69,6 +70,11 @@ XTENSA_CPU(ESP32, {"esp32"},
XF_THREADPTR | XF_DIV32 | XF_DATACACHE | XF_DEBUG | XF_EXCEPTION | XF_HIGHPRIINTERRUPTS |
XF_HIGHPRIINTERRUPTSLEVEL7 | XF_COPROCESSOR | XF_INTERRUPT | XF_RVECTOR | XF_TIMERS3 | XF_PRID |
XF_REGPROTECT | XF_MISCSR))
+XTENSA_CPU(ESP32S2, {"esp32s2"},
+ (XF_DENSITY | XF_WINDOWED | XF_SEXT | XF_NSA | XF_MUL16 | XF_MUL32 | XF_MUL32HIGH |
+ XF_THREADPTR | XF_DIV32 | XF_DATACACHE | XF_DEBUG | XF_EXCEPTION | XF_HIGHPRIINTERRUPTS |
+ XF_HIGHPRIINTERRUPTSLEVEL7 | XF_COPROCESSOR | XF_INTERRUPT | XF_RVECTOR | XF_TIMERS3 | XF_PRID |
+ XF_REGPROTECT | XF_MISCSR | XF_MINMAX | XF_CLAMPS | XF_ESP32S2OPS))
#undef XTENSA_CPU
diff --git a/llvm/include/llvm/TargetParser/XtensaTargetParser.h b/llvm/include/llvm/TargetParser/XtensaTargetParser.h
index 41369b1d64499..cc08558e6f5d6 100644
--- a/llvm/include/llvm/TargetParser/XtensaTargetParser.h
+++ b/llvm/include/llvm/TargetParser/XtensaTargetParser.h
@@ -64,7 +64,8 @@ enum XtensaFeatureKind : uint64_t {
XF_TIMERS3 = 1ULL << 33,
XF_PRID = 1ULL << 34,
XF_REGPROTECT = 1ULL << 35,
- XF_MISCSR = 1ULL << 36
+ XF_MISCSR = 1ULL << 36,
+ XF_ESP32S2OPS = 1ULL << 37
};
CPUKind parseCPUKind(StringRef CPU);
diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index dc33295c16f28..f2714d9b3e21c 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -282,6 +282,8 @@ struct XtensaOperand : public MCParsedAsmOperand {
bool isimm7_22() const { return isImm(7, 22); }
+ bool isSelect_256() const { return isImm(0, 255); }
+
/// getStartLoc - Gets location of the first token of this operand
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
@@ -544,6 +546,9 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_Invalidimm7_22:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range [7, 22]");
+ case Match_InvalidSelect_256:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range [0, 255]");
}
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 7d22a0489a951..807a2d6d35fdc 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -415,6 +415,14 @@ static DecodeStatus decodeImm7_22Operand(MCInst &Inst, uint64_t Imm,
return MCDisassembler::Success;
}
+static DecodeStatus decodeSelect_256Operand(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ assert(isUInt<8>(Imm) && "Invalid immediate");
+ Inst.addOperand(MCOperand::createImm(Imm));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,
int64_t Address, const void *Decoder) {
assert(isUInt<12>(Imm) && "Invalid immediate");
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index f1c11d47bc8b9..8cd41e3f81636 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -439,3 +439,14 @@ void XtensaInstPrinter::printImm7_22_AsmOperand(const MCInst *MI, int OpNum,
} else
printOperand(MI, OpNum, O);
}
+
+void XtensaInstPrinter::printSelect_256_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 <= 255) &&
+ "Invalid argument, value must be in range [0,255]");
+ O << Value;
+ } else
+ printOperand(MI, OpNum, O);
+}
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
index e25e36ed61ccf..657996dd607e6 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h
@@ -77,6 +77,7 @@ class XtensaInstPrinter : public MCInstPrinter {
void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printImm7_22_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
+ void printSelect_256_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 5977a276b1236..5aaa0f855da8d 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -142,6 +142,10 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
uint32_t getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+
+ uint8_t getSelect_256OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
};
} // namespace
@@ -606,4 +610,16 @@ XtensaMCCodeEmitter::getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
return res;
}
+
+uint8_t
+XtensaMCCodeEmitter::getSelect_256OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ uint8_t Res = static_cast<uint8_t>(MO.getImm());
+
+ assert(((Res >= 0) && (Res <= 255)) && "Unexpected operand value!");
+
+ return Res;
+}
#include "XtensaGenMCCodeEmitter.inc"
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index 8ccf8c83c0921..1dbec6565853d 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -203,6 +203,10 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
case Xtensa::ATOMCTL:
case Xtensa::SCOMPARE1:
return FeatureBits[Xtensa::FeatureS32C1I];
+ return FeatureBits[Xtensa::FeatureWindowed];
+ case Xtensa::GPIO_OUT:
+ case Xtensa::EXPSTATE:
+ return FeatureBits[Xtensa::FeatureESP32S2Ops];
case Xtensa::NoRegister:
return false;
}
@@ -226,6 +230,10 @@ MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
UserReg = Xtensa::F64S;
} else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) {
UserReg = Xtensa::THREADPTR;
+ } else if (MRI.getEncodingValue(Xtensa::GPIO_OUT) == Code) {
+ UserReg = Xtensa::GPIO_OUT;
+ } else if (MRI.getEncodingValue(Xtensa::EXPSTATE) == Code) {
+ UserReg = Xtensa::EXPSTATE;
}
return UserReg;
diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td
index d6f3ef0f15e32..5b0732bf78ad3 100644
--- a/llvm/lib/Target/Xtensa/XtensaFeatures.td
+++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td
@@ -163,3 +163,8 @@ def FeatureDFPAccel : SubtargetFeature<"dfpaccel", "HasDFPAccel", "true",
"Enable Xtensa Double Precision FP acceleration">;
def HasDFPAccel : Predicate<"Subtarget->hasDFPAccel()">,
AssemblerPredicate<(all_of FeatureDFPAccel)>;
+
+def FeatureESP32S2Ops : SubtargetFeature<"esp32s2ops", "HasESP32S2Ops", "true",
+ "Support Xtensa esp32-s2 ISA extension">;
+def HasESP32S2Ops : Predicate<"Subtarget->hasESP32S2Ops()">,
+ AssemblerPredicate<(all_of FeatureESP32S2Ops)>;
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 632c6a2fba1b6..90e20b7cd6334 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -1540,6 +1540,40 @@ let usesCustomInserter = 1, Predicates = [HasS32C1I] in {
[(set AR:$dst, (atomic_cmp_swap_i32 AR:$ptr, AR:$cmp, AR:$swap))]>;
}
+//===----------------------------------------------------------------------===//
+// Xtensa ESP32S2 Instructions
+//===----------------------------------------------------------------------===//
+let Predicates = [HasESP32S2Ops] in {
+ def WR_MASK_GPIO_OUT : RRR_Inst<0x0, 0x06, 0x0, (outs), (ins AR:$s, AR:$t),
+ "wr_mask_gpio_out\t$s, $t", []> {
+ let r = 0x2;
+ }
+
+ def SET_BIT_GPIO_OUT : RRR_Inst<0x0, 0x06, 0x0, (outs), (ins select_256:$imm),
+ "set_bit_gpio_out\t$imm", []> {
+ bits<8> imm;
+
+ let r = 0x1;
+ let s = imm{7-4};
+ let t = imm{3-0};
+ }
+
+ def CLR_BIT_GPIO_OUT : RRR_Inst<0x0, 0x06, 0x0, (outs), (ins select_256:$imm),
+ "clr_bit_gpio_out\t$imm", []> {
+ bits<8> imm;
+
+ let r = 0x0;
+ let s = imm{7-4};
+ let t = imm{3-0};
+ }
+
+ def GET_GPIO_IN : RRR_Inst<0x0, 0x06, 0x0, (outs AR:$t), (ins),
+ "get_gpio_in\t$t", []> {
+ let r = 0x3;
+ let s = 0x0;
+ }
+}
+
//===----------------------------------------------------------------------===//
// DSP Instructions
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Xtensa/XtensaOperands.td b/llvm/lib/Target/Xtensa/XtensaOperands.td
index d0f454736e500..76629f107d4b5 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperands.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperands.td
@@ -175,6 +175,13 @@ def imm7_22: Immediate<i32, [{ return Imm >= 7 && Imm <= 22; }], "Imm7_22_AsmOpe
let DecoderMethod = "decodeImm7_22Operand";
}
+// select_256 predicate - Immediate in the range [0,255]
+def Select_256_AsmOperand: ImmAsmOperand<"Select_256">;
+def select_256: Immediate<i32, [{ return Imm >= 0 && Imm <= 255; }], "Select_256_AsmOperand"> {
+ let EncoderMethod = "getSelect_256OpValue";
+ let DecoderMethod = "decodeSelect_256Operand";
+}
+
//===----------------------------------------------------------------------===//
// Memory address operands
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Xtensa/XtensaProcessors.td b/llvm/lib/Target/Xtensa/XtensaProcessors.td
index 0faf07d99aaf7..b977de596762c 100644
--- a/llvm/lib/Target/Xtensa/XtensaProcessors.td
+++ b/llvm/lib/Target/Xtensa/XtensaProcessors.td
@@ -25,3 +25,8 @@ def : Proc<"esp32", [FeatureDensity, FeatureSingleFloat, FeatureLoop, FeatureMAC
def : Proc<"esp8266", [FeatureDensity, FeatureNSA, FeatureMul16, FeatureMul32, FeatureExtendedL32R, FeatureDebug, FeatureException,
FeatureHighPriInterrupts, FeatureHighPriInterruptsLevel3, FeatureInterrupt, FeatureRelocatableVector, FeatureTimers1,
FeatureRegionProtection, FeaturePRID]>;
+
+def : Proc<"esp32s2", [FeatureDensity, FeatureWindowed, FeatureSEXT, FeatureNSA, FeatureMul16, FeatureMul32, FeatureMul32High, FeatureTHREADPTR,
+ FeatureDiv32, FeatureDataCache, FeatureDebug, FeatureException, FeatureHighPriInterrupts, FeatureHighPriInterruptsLevel7,
+ FeatureCoprocessor, FeatureInterrupt, FeatureRelocatableVector, FeatureTimers3, FeaturePRID, FeatureRegionProtection,
+ FeatureMiscSR, FeatureMINMAX, FeatureCLAMPS, FeatureESP32S2Ops]>;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
index d1f2c6b8e43a3..29d1ca06d324f 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
@@ -240,6 +240,10 @@ class URReg<bits<8> num, string n, list<string> alt = []> : XtensaReg<n> {
let AltNames = alt;
}
+// ESP32S2 registers
+def GPIO_OUT : URReg<0, "gpio_out", ["GPIO_OUT"]>;
+def EXPSTATE : URReg<230, "expstate", ["EXPSTATE"]>;
+
// Thread Pointer register
def THREADPTR : URReg<231, "threadptr", ["THREADPTR"]>;
@@ -252,7 +256,7 @@ def F64R_HI : URReg<235, "f64r_hi", ["F64R_HI"]>;
def F64S : URReg<236, "f64s", ["F64S"]>;
def UR : RegisterClass<"Xtensa", [i32], 32, (add
- THREADPTR, FCR, FSR, F64R_LO, F64R_HI, F64S)>;
+ GPIO_OUT, EXPSTATE, THREADPTR, FCR, FSR, F64R_LO, F64R_HI, F64S)>;
//===----------------------------------------------------------------------===//
// Floating-Point registers
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index 6a5201b6f6f32..cbe5d9a720501 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -94,6 +94,7 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
bool hasInterrupt() const { return HasInterrupt; }
bool hasException() const { return HasException; }
bool hasTHREADPTR() const { return HasTHREADPTR; }
+ bool hasESP32S2Ops() const { return HasESP32S2Ops; }
bool isWindowedABI() const { return hasWindowed(); }
// Automatically generated by tblgen.
diff --git a/llvm/test/CodeGen/Xtensa/cpus.ll b/llvm/test/CodeGen/Xtensa/cpus.ll
index d04ee16882381..d59ef0e7a90da 100644
--- a/llvm/test/CodeGen/Xtensa/cpus.ll
+++ b/llvm/test/CodeGen/Xtensa/cpus.ll
@@ -3,6 +3,7 @@
; RUN: llc < %s --mtriple=xtensa --mcpu=esp8266 2>&1 | FileCheck -check-prefix=XTENSA-ESP8266 %s
; RUN: llc < %s --mtriple=xtensa --mcpu=esp32 2>&1 | FileCheck -check-prefix=XTENSA-ESP32 %s
+; RUN: llc < %s --mtriple=xtensa --mcpu=esp32s2 2>&1 | FileCheck -check-prefix=XTENSA-ESP32S2 %s
; RUN: llc < %s --mtriple=xtensa --mcpu=generic 2>&1 | FileCheck -check-prefix=XTENSA-GENERIC %s
define i32 @f(i32 %z) {
@@ -20,6 +21,14 @@ define i32 @f(i32 %z) {
; XTENSA-ESP32-NEXT: movi a2, 0
; XTENSA-ESP32-NEXT: retw.n
;
+; XTENSA-ESP32S2-LABEL: f:
+; XTENSA-ESP32S2: .cfi_startproc
+; XTENSA-ESP32S2-NEXT: # %bb.0:
+; XTENSA-ESP32S2-NEXT: entry a1, 32
+; XTENSA-ESP32S2-NEXT: .cfi_def_cfa_offset 32
+; XTENSA-ESP32S2-NEXT: movi.n a2, 0
+; XTENSA-ESP32S2-NEXT: retw.n
+;
; XTENSA-GENERIC-LABEL: f:
; XTENSA-GENERIC: .cfi_startproc
; XTENSA-GENERIC-NEXT: # %bb.0:
>From 91d8e345f608265edf61c406ab5f2758d4e7a6e3 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 11 Jun 2026 01:06:54 +0300
Subject: [PATCH 2/4] [Xtensa] Minor fixes.
Minor fixes of the check immediate. Also fixed test.
---
llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp | 3 +--
llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp | 2 +-
llvm/test/CodeGen/Xtensa/cpus.ll | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index 8cd41e3f81636..4540f16f34801 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -314,8 +314,7 @@ void XtensaInstPrinter::printOffset8m8_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 <= 255) &&
- "Invalid argument, value must be in range [0,255]");
+ assert(isUInt<8> && "Invalid argument, value must be in range [0,255]");
O << Value;
} else
printOperand(MI, OpNum, O);
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 5aaa0f855da8d..b35e5e3e03b07 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -618,7 +618,7 @@ XtensaMCCodeEmitter::getSelect_256OpValue(const MCInst &MI, unsigned OpNo,
const MCOperand &MO = MI.getOperand(OpNo);
uint8_t Res = static_cast<uint8_t>(MO.getImm());
- assert(((Res >= 0) && (Res <= 255)) && "Unexpected operand value!");
+ assert(isUInt<8> && "Unexpected operand value!");
return Res;
}
diff --git a/llvm/test/CodeGen/Xtensa/cpus.ll b/llvm/test/CodeGen/Xtensa/cpus.ll
index d59ef0e7a90da..95ae845888e5c 100644
--- a/llvm/test/CodeGen/Xtensa/cpus.ll
+++ b/llvm/test/CodeGen/Xtensa/cpus.ll
@@ -26,7 +26,7 @@ define i32 @f(i32 %z) {
; XTENSA-ESP32S2-NEXT: # %bb.0:
; XTENSA-ESP32S2-NEXT: entry a1, 32
; XTENSA-ESP32S2-NEXT: .cfi_def_cfa_offset 32
-; XTENSA-ESP32S2-NEXT: movi.n a2, 0
+; XTENSA-ESP32S2-NEXT: movi a2, 0
; XTENSA-ESP32S2-NEXT: retw.n
;
; XTENSA-GENERIC-LABEL: f:
>From 2bf9195e835c9ec803dda5f86e1a5f76a3630864 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 11 Jun 2026 03:20:32 +0300
Subject: [PATCH 3/4] [Xtensa] Remove EXPSTATE register and renmae GPIO_OUT
register.
---
.../Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp | 9 +++------
llvm/lib/Target/Xtensa/XtensaRegisterInfo.td | 5 ++---
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index 1dbec6565853d..cb8c3aca3502c 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -204,8 +204,7 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
case Xtensa::SCOMPARE1:
return FeatureBits[Xtensa::FeatureS32C1I];
return FeatureBits[Xtensa::FeatureWindowed];
- case Xtensa::GPIO_OUT:
- case Xtensa::EXPSTATE:
+ case Xtensa::GPIO_OUT_S2:
return FeatureBits[Xtensa::FeatureESP32S2Ops];
case Xtensa::NoRegister:
return false;
@@ -230,10 +229,8 @@ MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
UserReg = Xtensa::F64S;
} else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) {
UserReg = Xtensa::THREADPTR;
- } else if (MRI.getEncodingValue(Xtensa::GPIO_OUT) == Code) {
- UserReg = Xtensa::GPIO_OUT;
- } else if (MRI.getEncodingValue(Xtensa::EXPSTATE) == Code) {
- UserReg = Xtensa::EXPSTATE;
+ } else if (MRI.getEncodingValue(Xtensa::GPIO_OUT_S2) == Code) {
+ UserReg = Xtensa::GPIO_OUT_S2;
}
return UserReg;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
index 29d1ca06d324f..6c4f35e832f3f 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
@@ -241,8 +241,7 @@ class URReg<bits<8> num, string n, list<string> alt = []> : XtensaReg<n> {
}
// ESP32S2 registers
-def GPIO_OUT : URReg<0, "gpio_out", ["GPIO_OUT"]>;
-def EXPSTATE : URReg<230, "expstate", ["EXPSTATE"]>;
+def GPIO_OUT_S2 : URReg<0, "gpio_out", ["GPIO_OUT"]>;
// Thread Pointer register
def THREADPTR : URReg<231, "threadptr", ["THREADPTR"]>;
@@ -256,7 +255,7 @@ def F64R_HI : URReg<235, "f64r_hi", ["F64R_HI"]>;
def F64S : URReg<236, "f64s", ["F64S"]>;
def UR : RegisterClass<"Xtensa", [i32], 32, (add
- GPIO_OUT, EXPSTATE, THREADPTR, FCR, FSR, F64R_LO, F64R_HI, F64S)>;
+ GPIO_OUT_S2, THREADPTR, FCR, FSR, F64R_LO, F64R_HI, F64S)>;
//===----------------------------------------------------------------------===//
// Floating-Point registers
>From fe6ed6989b04b960cd25142c48297b9322772fcc Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 11 Jun 2026 11:05:35 +0300
Subject: [PATCH 4/4] [Xtensa] Add test for esp32s2 target specific
instructions.
---
llvm/test/MC/xtensa-esp32s2-valid.s | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 llvm/test/MC/xtensa-esp32s2-valid.s
diff --git a/llvm/test/MC/xtensa-esp32s2-valid.s b/llvm/test/MC/xtensa-esp32s2-valid.s
new file mode 100644
index 0000000000000..4fef46023b30f
--- /dev/null
+++ b/llvm/test/MC/xtensa-esp32s2-valid.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc %s -triple=xtensa -mattr=+esp32s2ops -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align 4
+LBL0:
+
+# CHECK-INST: clr_bit_gpio_out 52
+# CHECK: encoding: [0x40,0x03,0x06]
+clr_bit_gpio_out 52
+
+# CHECK-INST: get_gpio_in a2
+# CHECK: encoding: [0x20,0x30,0x06]
+get_gpio_in a2
+
+# CHECK-INST: set_bit_gpio_out 18
+# CHECK: encoding: [0x20,0x11,0x06]
+set_bit_gpio_out 18
+
+# CHECK-INST: wr_mask_gpio_out a3, a2
+# CHECK: encoding: [0x20,0x23,0x06]
+wr_mask_gpio_out a3, a2
More information about the llvm-commits
mailing list