[llvm] [Xtensa] Implement Xtensa MAC16 Option. (PR #130004)

Andrei Safronov via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 6 15:04:23 PST 2025


https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/130004

>From 298aeddf3a97c3357cadf523e4def702cf768c53 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 6 Mar 2025 10:56:44 +0300
Subject: [PATCH 1/2] [Xtensa] Implement Xtensa MAC16 Option.

---
 .../Disassembler/XtensaDisassembler.cpp       |  44 ++-
 llvm/lib/Target/Xtensa/XtensaDSPInstrInfo.td  | 353 ++++++++++++++++++
 llvm/lib/Target/Xtensa/XtensaFeatures.td      |   5 +
 llvm/lib/Target/Xtensa/XtensaInstrInfo.td     |   5 +
 llvm/lib/Target/Xtensa/XtensaRegisterInfo.td  |  14 +-
 llvm/lib/Target/Xtensa/XtensaSubtarget.h      |   2 +
 llvm/test/MC/Xtensa/xtensa-mac16.s            | 233 ++++++++++++
 7 files changed, 654 insertions(+), 2 deletions(-)
 create mode 100644 llvm/lib/Target/Xtensa/XtensaDSPInstrInfo.td
 create mode 100644 llvm/test/MC/Xtensa/xtensa-mac16.s

diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index b1027488904df..c1f6b39555223 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -73,8 +73,50 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
   return MCDisassembler::Success;
 }
 
+static const unsigned MRDecoderTable[] = {Xtensa::M0, Xtensa::M1, Xtensa::M2,
+                                          Xtensa::M3};
+
+static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                          uint64_t Address,
+                                          const void *Decoder) {
+  if (RegNo >= std::size(MRDecoderTable))
+    return MCDisassembler::Fail;
+
+  unsigned Reg = MRDecoderTable[RegNo];
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static const unsigned MR01DecoderTable[] = {Xtensa::M0, Xtensa::M1};
+
+static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const void *Decoder) {
+  if (RegNo > 2)
+    return MCDisassembler::Fail;
+
+  unsigned Reg = MR01DecoderTable[RegNo];
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
+static const unsigned MR23DecoderTable[] = {Xtensa::M2, Xtensa::M3};
+
+static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const void *Decoder) {
+  if ((RegNo < 2) || (RegNo > 3))
+    return MCDisassembler::Fail;
+
+  unsigned Reg = MR23DecoderTable[RegNo - 2];
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
 const MCPhysReg SRDecoderTable[] = {
-    Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};
+    Xtensa::SAR, 3,  Xtensa::ACCLO,      16, Xtensa::ACCHI,       17,
+    Xtensa::M0,  32, Xtensa::M1,         33, Xtensa::M2,          34,
+    Xtensa::M3,  35, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};
 
 static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
                                           uint64_t Address,
diff --git a/llvm/lib/Target/Xtensa/XtensaDSPInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaDSPInstrInfo.td
new file mode 100644
index 0000000000000..d80df46320643
--- /dev/null
+++ b/llvm/lib/Target/Xtensa/XtensaDSPInstrInfo.td
@@ -0,0 +1,353 @@
+//===- XtensaDSPInstrInfo.td - Xtensa Target Description ---*- tablegen -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the Xtensa DSP instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+// Multiply
+class UMUL_AA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x07, (outs), (ins AR:$s, AR:$t),
+             instrAsm#"\t$s, $t", []>, Requires<[HasMAC16]> {
+  let r = 0;
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def UMUL_AA_LL : UMUL_AA<0x00, "umul.aa.ll">;
+def UMUL_AA_HL : UMUL_AA<0x01, "umul.aa.hl">;
+def UMUL_AA_LH : UMUL_AA<0x02, "umul.aa.lh">;
+def UMUL_AA_HH : UMUL_AA<0x03, "umul.aa.hh">;
+
+class MUL_AA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x07, (outs), (ins AR:$s, AR:$t),
+             instrAsm#"\t$s, $t", []>, Requires<[HasMAC16]> {
+  let r = 0;
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MUL_AA_LL : MUL_AA<0x04, "mul.aa.ll">;
+def MUL_AA_HL : MUL_AA<0x05, "mul.aa.hl">;
+def MUL_AA_LH : MUL_AA<0x06, "mul.aa.lh">;
+def MUL_AA_HH : MUL_AA<0x07, "mul.aa.hh">;
+
+class MUL_AD<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x03, (outs), (ins AR:$s, MR23:$y),
+             instrAsm#"\t$s, $y", []>, Requires<[HasMAC16]> {
+  bits<2> y;
+
+  let r = 0;
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MUL_AD_LL : MUL_AD<0x04, "mul.ad.ll">;
+def MUL_AD_HL : MUL_AD<0x05, "mul.ad.hl">;
+def MUL_AD_LH : MUL_AD<0x06, "mul.ad.lh">;
+def MUL_AD_HH : MUL_AD<0x07, "mul.ad.hh">;
+
+class MUL_DA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x06, (outs), (ins MR01:$x, AR:$t),
+             instrAsm#"\t$x, $t", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = 0;
+  let s = 0;
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MUL_DA_LL : MUL_DA<0x04, "mul.da.ll">;
+def MUL_DA_HL : MUL_DA<0x05, "mul.da.hl">;
+def MUL_DA_LH : MUL_DA<0x06, "mul.da.lh">;
+def MUL_DA_HH : MUL_DA<0x07, "mul.da.hh">;
+
+class MUL_DD<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x02, (outs), (ins MR01:$x, MR23:$y),
+             instrAsm#"\t$x, $y", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+  bits<2> y;
+
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = 0;
+  let s = 0;
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MUL_DD_LL : MUL_DD<0x04, "mul.dd.ll">;
+def MUL_DD_HL : MUL_DD<0x05, "mul.dd.hl">;
+def MUL_DD_LH : MUL_DD<0x06, "mul.dd.lh">;
+def MUL_DD_HH : MUL_DD<0x07, "mul.dd.hh">;
+
+class MULA_AA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x07, (outs), (ins AR:$s, AR:$t),
+             instrAsm#"\t$s, $t", []>, Requires<[HasMAC16]> {
+  let r = 0;
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_AA_LL : MULA_AA<0x08, "mula.aa.ll">;
+def MULA_AA_HL : MULA_AA<0x09, "mula.aa.hl">;
+def MULA_AA_LH : MULA_AA<0x0A, "mula.aa.lh">;
+def MULA_AA_HH : MULA_AA<0x0B, "mula.aa.hh">;
+
+class MULA_AD<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x03, (outs), (ins AR:$s, MR23:$y),
+             instrAsm#"\t$s, $y", []>, Requires<[HasMAC16]> {
+  bits<2> y;
+
+  let r = 0;
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_AD_LL : MULA_AD<0x08, "mula.ad.ll">;
+def MULA_AD_HL : MULA_AD<0x09, "mula.ad.hl">;
+def MULA_AD_LH : MULA_AD<0x0A, "mula.ad.lh">;
+def MULA_AD_HH : MULA_AD<0x0B, "mula.ad.hh">;
+
+class MULA_DA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x06, (outs), (ins MR01:$x, AR:$t),
+             instrAsm#"\t$x, $t", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = 0;
+  let s = 0;
+
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_DA_LL : MULA_DA<0x08, "mula.da.ll">;
+def MULA_DA_HL : MULA_DA<0x09, "mula.da.hl">;
+def MULA_DA_LH : MULA_DA<0x0A, "mula.da.lh">;
+def MULA_DA_HH : MULA_DA<0x0B, "mula.da.hh">;
+
+class MULA_DD<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x02, (outs), (ins MR01:$x, MR23:$y),
+             instrAsm#"\t$x, $y", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+  bits<2> y;
+
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = 0;
+  let s = 0;
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_DD_LL : MULA_DD<0x08, "mula.dd.ll">;
+def MULA_DD_HL : MULA_DD<0x09, "mula.dd.hl">;
+def MULA_DD_LH : MULA_DD<0x0A, "mula.dd.lh">;
+def MULA_DD_HH : MULA_DD<0x0B, "mula.dd.hh">;
+
+class MULS_AA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x07, (outs), (ins AR:$s, AR:$t),
+             instrAsm#"\t$s, $t", []>, Requires<[HasMAC16]> {
+  let r = 0;
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULS_AA_LL : MULS_AA<0x0C, "muls.aa.ll">;
+def MULS_AA_HL : MULS_AA<0x0D, "muls.aa.hl">;
+def MULS_AA_LH : MULS_AA<0x0E, "muls.aa.lh">;
+def MULS_AA_HH : MULS_AA<0x0F, "muls.aa.hh">;
+
+class MULS_AD<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x03, (outs), (ins AR:$s, MR23:$y),
+             instrAsm#"\t$s, $y", []>, Requires<[HasMAC16]> {
+  bits<2> y;
+
+  let r = 0;
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULS_AD_LL : MULS_AD<0x0C, "muls.ad.ll">;
+def MULS_AD_HL : MULS_AD<0x0D, "muls.ad.hl">;
+def MULS_AD_LH : MULS_AD<0x0E, "muls.ad.lh">;
+def MULS_AD_HH : MULS_AD<0x0F, "muls.ad.hh">;
+
+class MULS_DA<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x06, (outs), (ins MR01:$x, AR:$t),
+             instrAsm#"\t$x, $t", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = 0;
+  let s = 0;
+
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULS_DA_LL : MULS_DA<0x0C, "muls.da.ll">;
+def MULS_DA_HL : MULS_DA<0x0D, "muls.da.hl">;
+def MULS_DA_LH : MULS_DA<0x0E, "muls.da.lh">;
+def MULS_DA_HH : MULS_DA<0x0F, "muls.da.hh">;
+
+class MULS_DD<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x02, (outs), (ins MR01:$x, MR23:$y),
+             instrAsm#"\t$x, $y", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+  bits<2> y;
+
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = 0;
+  let s = 0;
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULS_DD_LL : MULS_DD<0x0C, "muls.dd.ll">;
+def MULS_DD_HL : MULS_DD<0x0D, "muls.dd.hl">;
+def MULS_DD_LH : MULS_DD<0x0E, "muls.dd.lh">;
+def MULS_DD_HH : MULS_DD<0x0F, "muls.dd.hh">;
+
+//===----------------------------------------------------------------------===//
+// Multiply-accumulate with load
+
+class MULA_DA_LDDEC<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x05, (outs MR:$w, AR:$d), (ins AR:$s, MR01:$x, AR:$t),
+             instrAsm#"\t $w, $s, $x, $t", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+  bits<2> w;
+
+  let Constraints = "$s = $d";
+  let mayLoad = 1;
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = w{1-0};
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_DA_LL_LDDEC : MULA_DA_LDDEC<0x08, "mula.da.ll.lddec">;
+def MULA_DA_HL_LDDEC : MULA_DA_LDDEC<0x09, "mula.da.hl.lddec">;
+def MULA_DA_LH_LDDEC : MULA_DA_LDDEC<0x0A, "mula.da.lh.lddec">;
+def MULA_DA_HH_LDDEC : MULA_DA_LDDEC<0x0B, "mula.da.hh.lddec">;
+
+class MULA_DA_LDINC<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x04, (outs MR:$w, AR:$d), (ins AR:$s, MR:$x, AR:$t),
+             instrAsm#"\t $w, $s, $x, $t", []>, Requires<[HasMAC16]> {
+  bits<1> x;
+  bits<2> w;
+
+  let Constraints = "$s = $d";
+  let mayLoad = 1;
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = w{1-0};
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_DA_LL_LDINC: MULA_DA_LDINC<0x08, "mula.da.ll.ldinc">;
+def MULA_DA_HL_LDINC: MULA_DA_LDINC<0x09, "mula.da.hl.ldinc">;
+def MULA_DA_LH_LDINC: MULA_DA_LDINC<0x0A, "mula.da.lh.ldinc">;
+def MULA_DA_HH_LDINC: MULA_DA_LDINC<0x0B, "mula.da.hh.ldinc">;
+
+class MULA_DD_LDDEC<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x01, (outs MR:$w, AR:$d), (ins AR:$s, MR01:$x, MR23:$y),
+             instrAsm#"\t $w, $s, $x, $y", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+  bits<2> y;
+  bits<2> w;
+
+  let Constraints = "$s = $d";
+  let mayLoad = 1;
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = w{1-0};
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_DD_LL_LDDEC : MULA_DD_LDDEC<0x08, "mula.dd.ll.lddec">;
+def MULA_DD_HL_LDDEC : MULA_DD_LDDEC<0x09, "mula.dd.hl.lddec">;
+def MULA_DD_LH_LDDEC : MULA_DD_LDDEC<0x0A, "mula.dd.lh.lddec">;
+def MULA_DD_HH_LDDEC : MULA_DD_LDDEC<0x0B, "mula.dd.hh.lddec">;
+
+class MULA_DD_LDINC<bits<4> oper1, string instrAsm>
+  : RRR_Inst<0x04, oper1, 0x00, (outs MR:$w, AR:$d), (ins AR:$s, MR01:$x, MR23:$y),
+             instrAsm#"\t $w, $s, $x, $y", []>, Requires<[HasMAC16]> {
+  bits<2> x;
+  bits<2> y;
+  bits<2> w;
+
+  let Constraints = "$s = $d";
+  let mayLoad = 1;
+  let r{3} = 0;
+  let r{2} = x{0};
+  let r{1-0} = w{1-0};
+  let t{3} = 0;
+  let t{2} = y{0};
+  let t{1-0} = 0;
+  let Uses = [ACCLO, ACCHI];
+  let Defs = [M1, M2, ACCLO, ACCHI];
+}
+
+def MULA_DD_LL_LDINC : MULA_DD_LDINC<0x08, "mula.dd.ll.ldinc">;
+def MULA_DD_HL_LDINC : MULA_DD_LDINC<0x09, "mula.dd.hl.ldinc">;
+def MULA_DD_LH_LDINC : MULA_DD_LDINC<0x0A, "mula.dd.lh.ldinc">;
+def MULA_DD_HH_LDINC : MULA_DD_LDINC<0x0B, "mula.dd.hh.ldinc">;
+
+def LDDEC : RRR_Inst<0x04, 0x00, 0x09, (outs MR:$w, AR:$d), (ins AR:$s),
+                    "lddec\t $w, $s", []>, Requires<[HasMAC16]> {
+  bits<2> w;
+
+  let Constraints = "$s = $d";
+  let mayLoad = 1;
+  let r{3-2} = 0;
+  let r{1-0} = w{1-0};
+  let t = 0x00;
+}
+
+def LDINC : RRR_Inst<0x04, 0x00, 0x08, (outs MR:$w, AR:$d), (ins AR:$s),
+                    "ldinc\t $w, $s", []>, Requires<[HasMAC16]> {
+  bits<2> w;
+
+  let Constraints = "$s = $d";
+  let mayLoad = 1;
+  let r{3-2} = 0;
+  let r{1-0} = w{1-0};
+  let t = 0;
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td
index b0cbeb9456796..184828cd253f3 100644
--- a/llvm/lib/Target/Xtensa/XtensaFeatures.td
+++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td
@@ -13,6 +13,11 @@ def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
 def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
                   AssemblerPredicate<(all_of FeatureWindowed)>;
 
+def FeatureMAC16 : SubtargetFeature<"mac16", "HasMAC16", "true",
+                                    "Enable Xtensa MAC16 instructions">;
+def HasMAC16 : Predicate<"Subtarget->hasMAC16()">,
+               AssemblerPredicate<(all_of FeatureMAC16)>;
+
 def FeatureBoolean          : SubtargetFeature<"bool", "HasBoolean", "true",
                                                "Enable Xtensa Boolean extension">;
 def HasBoolean              : Predicate<"Subtarget->hasBoolean()">,
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index e52dcbf1377c5..1f397e3ecac35 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -849,3 +849,8 @@ let Constraints = "$dr = $r, at earlyclobber $dr" in {
   def MOVT : RRR_Inst<0x00, 0x03, 0x0D, (outs AR:$dr), (ins AR:$r, AR:$s, BR:$t),
                    "movt\t$r, $s, $t", []>, Requires<[HasBoolean]>;
 }
+
+//===----------------------------------------------------------------------===//
+// DSP Instructions
+//===----------------------------------------------------------------------===//
+include "XtensaDSPInstrInfo.td"
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
index 920354ff41ba5..2934018318406 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
@@ -83,7 +83,19 @@ def BREG : SRReg<4, "br", ["BR","4"]>;
 def WINDOWBASE : SRReg<72, "windowbase", ["WINDOWBASE", "72"]>;
 def WINDOWSTART : SRReg<73, "windowstart", ["WINDOWSTART", "73"]>;
 
-def SR :  RegisterClass<"Xtensa", [i32], 32, (add SAR, BREG,
+// MAC16 Option registers
+def ACCLO : SRReg<16, "acclo", ["ACCLO", "16"]>;
+def ACCHI : SRReg<17, "acchi", ["ACCHI", "17"]>;
+def M0    : SRReg<32, "m0", ["M0", "32"]>;
+def M1    : SRReg<33, "m1", ["M1", "33"]>;
+def M2    : SRReg<34, "m2", ["M2", "34"]>;
+def M3    : SRReg<35, "m3", ["M3", "35"]>;
+
+def MR01 :  RegisterClass<"Xtensa", [i32], 32, (add M0, M1)>;
+def MR23 :  RegisterClass<"Xtensa", [i32], 32, (add M2, M3)>;
+def MR   :  RegisterClass<"Xtensa", [i32], 32, (add MR01, MR23)>;
+
+def SR :  RegisterClass<"Xtensa", [i32], 32, (add SAR, BREG, MR,
   WINDOWBASE, WINDOWSTART)>;
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index 962bed2c2e36f..770f73905b337 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -66,6 +66,8 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
 
   bool hasDensity() const { return HasDensity; }
 
+  bool hasMAC16() const { return HasMAC16; }
+
   bool hasWindowed() const { return HasWindowed; }
 
   bool hasBoolean() const { return HasBoolean; }
diff --git a/llvm/test/MC/Xtensa/xtensa-mac16.s b/llvm/test/MC/Xtensa/xtensa-mac16.s
new file mode 100644
index 0000000000000..15200751ec8a0
--- /dev/null
+++ b/llvm/test/MC/Xtensa/xtensa-mac16.s
@@ -0,0 +1,233 @@
+# RUN: llvm-mc %s -triple=xtensa -mattr=+mac16 -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align	4
+LBL0:
+
+# CHECK-INST: umul.aa.ll	a2, a3
+# CHECK: encoding: [0x34,0x02,0x70]
+	umul.aa.ll	a2, a3
+# CHECK-INST: umul.aa.lh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x72]
+	umul.aa.lh	a2, a3
+# CHECK-INST: umul.aa.hl	a2, a3
+# CHECK: encoding: [0x34,0x02,0x71]
+	umul.aa.hl	a2, a3
+# CHECK-INST: umul.aa.hh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x73]
+	umul.aa.hh	a2, a3
+
+# CHECK-INST: mul.aa.ll	a2, a3
+# CHECK: encoding: [0x34,0x02,0x74]
+	mul.aa.ll	a2, a3
+# CHECK-INST: mul.aa.lh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x76]
+	mul.aa.lh	a2, a3
+# CHECK-INST: mul.aa.hl	a2, a3
+# CHECK: encoding: [0x34,0x02,0x75]
+	mul.aa.hl	a2, a3
+# CHECK-INST: mul.aa.hh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x77]
+	mul.aa.hh	a2, a3
+
+# CHECK-INST: mul.ad.ll	a2, m2
+# CHECK: encoding: [0x04,0x02,0x34]
+	mul.ad.ll	a2, m2
+# CHECK-INST: mul.ad.lh	a2, m2
+# CHECK: encoding: [0x04,0x02,0x36]
+	mul.ad.lh	a2, m2
+# CHECK-INST: mul.ad.hl	a2, m2
+# CHECK: encoding: [0x04,0x02,0x35]
+	mul.ad.hl	a2, m2
+# CHECK-INST: mul.ad.hh	a2, m2
+# CHECK: encoding: [0x04,0x02,0x37]
+	mul.ad.hh	a2, m2
+
+# CHECK-INST: mul.da.ll	m1, a3
+# CHECK: encoding: [0x34,0x40,0x64]
+	mul.da.ll	m1, a3
+# CHECK-INST: mul.da.lh	m1, a3
+# CHECK: encoding: [0x34,0x40,0x66]
+	mul.da.lh	m1, a3
+# CHECK-INST: mul.da.hl	m1, a3
+# CHECK: encoding: [0x34,0x40,0x65]
+	mul.da.hl	m1, a3
+# CHECK-INST: mul.da.hh	m1, a3
+# CHECK: encoding: [0x34,0x40,0x67]
+	mul.da.hh	m1, a3
+
+# CHECK-INST: mul.dd.ll	m1, m2
+# CHECK: encoding: [0x04,0x40,0x24]
+	mul.dd.ll	m1, m2
+# CHECK-INST: mul.dd.lh	m1, m2
+# CHECK: encoding: [0x04,0x40,0x26]
+	mul.dd.lh	m1, m2
+# CHECK-INST: mul.dd.hl	m1, m2
+# CHECK: encoding: [0x04,0x40,0x25]
+	mul.dd.hl	m1, m2
+# CHECK-INST: mul.dd.hh	m1, m2
+# CHECK: encoding: [0x04,0x40,0x27]
+	mul.dd.hh	m1, m2
+
+# CHECK-INST: mula.aa.ll	a2, a3
+# CHECK: encoding: [0x34,0x02,0x78]
+	mula.aa.ll	a2, a3
+# CHECK-INST: mula.aa.lh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x7a]
+	mula.aa.lh	a2, a3
+# CHECK-INST: mula.aa.hl	a2, a3
+# CHECK: encoding: [0x34,0x02,0x79]
+	mula.aa.hl	a2, a3
+# CHECK-INST: mula.aa.hh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x7b]
+	mula.aa.hh	a2, a3
+
+# CHECK-INST: mula.ad.ll	a2, m2
+# CHECK: encoding: [0x04,0x02,0x38]
+	mula.ad.ll	a2, m2
+# CHECK-INST: mula.ad.lh	a2, m2
+# CHECK: encoding: [0x04,0x02,0x3a]
+	mula.ad.lh	a2, m2
+# CHECK-INST: mula.ad.hl	a2, m2
+# CHECK: encoding: [0x04,0x02,0x39]
+	mula.ad.hl	a2, m2
+# CHECK-INST: mula.ad.hh	a2, m2
+# CHECK: encoding: [0x04,0x02,0x3b]
+	mula.ad.hh	a2, m2
+
+# CHECK-INST: mula.da.ll	m1, a3
+# CHECK: encoding: [0x34,0x40,0x68]
+	mula.da.ll	m1, a3
+# CHECK-INST: mula.da.lh	m1, a3
+# CHECK: encoding: [0x34,0x40,0x6a]
+	mula.da.lh	m1, a3
+# CHECK-INST: mula.da.hl	m1, a3
+# CHECK: encoding: [0x34,0x40,0x69]
+	mula.da.hl	m1, a3
+# CHECK-INST: mula.da.hh	m1, a3
+# CHECK: encoding: [0x34,0x40,0x6b]
+	mula.da.hh	m1, a3
+
+# CHECK-INST: mula.dd.ll	m1, m2
+# CHECK: encoding: [0x04,0x40,0x28]
+	mula.dd.ll	m1, m2
+# CHECK-INST: mula.dd.lh	m1, m2
+# CHECK: encoding: [0x04,0x40,0x2a]
+	mula.dd.lh	m1, m2
+# CHECK-INST: mula.dd.hl	m1, m2
+# CHECK: encoding: [0x04,0x40,0x29]
+	mula.dd.hl	m1, m2
+# CHECK-INST: mula.dd.hh	m1, m2
+# CHECK: encoding: [0x04,0x40,0x2b]
+	mula.dd.hh	m1, m2
+
+# CHECK-INST: muls.aa.ll	a2, a3
+# CHECK: encoding: [0x34,0x02,0x7c]
+	muls.aa.ll	a2, a3
+# CHECK-INST: muls.aa.lh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x7e]
+	muls.aa.lh	a2, a3
+# CHECK-INST: muls.aa.hl	a2, a3
+# CHECK: encoding: [0x34,0x02,0x7d]
+	muls.aa.hl	a2, a3
+# CHECK-INST: muls.aa.hh	a2, a3
+# CHECK: encoding: [0x34,0x02,0x7f]
+	muls.aa.hh	a2, a3
+
+# CHECK-INST: muls.ad.ll	a2, m2
+# CHECK: encoding: [0x04,0x02,0x3c]
+	muls.ad.ll	a2, m2
+# CHECK-INST: muls.ad.lh	a2, m2
+# CHECK: encoding: [0x04,0x02,0x3e]
+	muls.ad.lh	a2, m2
+# CHECK-INST: muls.ad.hl	a2, m2
+# CHECK: encoding: [0x04,0x02,0x3d]
+	muls.ad.hl	a2, m2
+# CHECK-INST: muls.ad.hh	a2, m2
+# CHECK: encoding: [0x04,0x02,0x3f]
+	muls.ad.hh	a2, m2
+
+# CHECK-INST: muls.da.ll	m1, a3
+# CHECK: encoding: [0x34,0x40,0x6c]
+	muls.da.ll	m1, a3
+# CHECK-INST: muls.da.lh	m1, a3
+# CHECK: encoding: [0x34,0x40,0x6e]
+	muls.da.lh	m1, a3
+# CHECK-INST: muls.da.hl	m1, a3
+# CHECK: encoding: [0x34,0x40,0x6d]
+	muls.da.hl	m1, a3
+# CHECK-INST: muls.da.hh	m1, a3
+# CHECK: encoding: [0x34,0x40,0x6f]
+	muls.da.hh	m1, a3
+
+# CHECK-INST: muls.dd.ll	m1, m2
+# CHECK: encoding: [0x04,0x40,0x2c]
+	muls.dd.ll	m1, m2
+# CHECK-INST: muls.dd.lh	m1, m2
+# CHECK: encoding: [0x04,0x40,0x2e]
+	muls.dd.lh	m1, m2
+# CHECK-INST: muls.dd.hl	m1, m2
+# CHECK: encoding: [0x04,0x40,0x2d]
+	muls.dd.hl	m1, m2
+# CHECK-INST: muls.dd.hh	m1, m2
+# CHECK: encoding: [0x04,0x40,0x2f]
+	muls.dd.hh	m1, m2
+
+# CHECK-INST: mula.da.ll.lddec	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x58]
+	mula.da.ll.lddec	 m1, a8, m0, a3
+# CHECK-INST: mula.da.hl.lddec	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x59]
+	mula.da.hl.lddec	 m1, a8, m0, a3
+# CHECK-INST: mula.da.lh.lddec	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x5a]
+	mula.da.lh.lddec	 m1, a8, m0, a3
+# CHECK-INST: mula.da.hh.lddec	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x5b]
+	mula.da.hh.lddec	 m1, a8, m0, a3
+
+# CHECK-INST: mula.dd.ll.lddec	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x18]
+	mula.dd.ll.lddec	 m1, a8, m0, m2
+# CHECK-INST: mula.dd.hl.lddec	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x19]
+	mula.dd.hl.lddec	 m1, a8, m0, m2
+# CHECK-INST: mula.dd.lh.lddec	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x1a]
+	mula.dd.lh.lddec	 m1, a8, m0, m2
+# CHECK-INST: mula.dd.hh.lddec	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x1b]
+	mula.dd.hh.lddec	 m1, a8, m0, m2
+
+# CHECK-INST: mula.da.ll.ldinc	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x48]
+	mula.da.ll.ldinc	 m1, a8, m0, a3
+# CHECK-INST: mula.da.hl.ldinc	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x49]
+	mula.da.hl.ldinc	 m1, a8, m0, a3
+# CHECK-INST: mula.da.lh.ldinc	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x4a]
+	mula.da.lh.ldinc	 m1, a8, m0, a3
+# CHECK-INST: mula.da.hh.ldinc	 m1, a8, m0, a3
+# CHECK: encoding: [0x34,0x18,0x4b]
+	mula.da.hh.ldinc	 m1, a8, m0, a3
+
+# CHECK-INST: mula.dd.ll.ldinc	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x08]
+	mula.dd.ll.ldinc	 m1, a8, m0, m2
+# CHECK-INST: mula.dd.hl.ldinc	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x09]
+	mula.dd.hl.ldinc	 m1, a8, m0, m2
+# CHECK-INST: mula.dd.lh.ldinc	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x0a]
+	mula.dd.lh.ldinc	 m1, a8, m0, m2
+# CHECK-INST: mula.dd.hh.ldinc	 m1, a8, m0, m2
+# CHECK: encoding: [0x04,0x18,0x0b]
+	mula.dd.hh.ldinc	 m1, a8, m0, m2
+
+# CHECK-INST: lddec	 m0, a8
+# CHECK: encoding: [0x04,0x08,0x90]
+	lddec	 m0, a8
+# CHECK-INST: ldinc	 m0, a8
+# CHECK: encoding: [0x04,0x08,0x80]
+	ldinc	 m0, a8

>From f1e3f333d39f316b76eb7b8950880e7a45e7d475 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Fri, 7 Mar 2025 02:02:45 +0300
Subject: [PATCH 2/2] [Xtensa] Minor fixes.

---
 .../Xtensa/Disassembler/XtensaDisassembler.cpp   | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index c1f6b39555223..b949b893953fe 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -73,8 +73,8 @@ static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
   return MCDisassembler::Success;
 }
 
-static const unsigned MRDecoderTable[] = {Xtensa::M0, Xtensa::M1, Xtensa::M2,
-                                          Xtensa::M3};
+static const MCPhysReg MRDecoderTable[] = {Xtensa::M0, Xtensa::M1, Xtensa::M2,
+                                           Xtensa::M3};
 
 static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,
                                           uint64_t Address,
@@ -82,12 +82,12 @@ static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,
   if (RegNo >= std::size(MRDecoderTable))
     return MCDisassembler::Fail;
 
-  unsigned Reg = MRDecoderTable[RegNo];
+  MCPhysReg Reg = MRDecoderTable[RegNo];
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }
 
-static const unsigned MR01DecoderTable[] = {Xtensa::M0, Xtensa::M1};
+static const MCPhysReg MR01DecoderTable[] = {Xtensa::M0, Xtensa::M1};
 
 static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo,
                                             uint64_t Address,
@@ -95,20 +95,20 @@ static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo,
   if (RegNo > 2)
     return MCDisassembler::Fail;
 
-  unsigned Reg = MR01DecoderTable[RegNo];
+  MCPhysReg Reg = MR01DecoderTable[RegNo];
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }
 
-static const unsigned MR23DecoderTable[] = {Xtensa::M2, Xtensa::M3};
+static const MCPhysReg MR23DecoderTable[] = {Xtensa::M2, Xtensa::M3};
 
 static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
                                             uint64_t Address,
                                             const void *Decoder) {
-  if ((RegNo < 2) || (RegNo > 3))
+  if (RegNo != 2 && RegNo != 3)
     return MCDisassembler::Fail;
 
-  unsigned Reg = MR23DecoderTable[RegNo - 2];
+  MCPhysReg Reg = MR23DecoderTable[RegNo - 2];
   Inst.addOperand(MCOperand::createReg(Reg));
   return MCDisassembler::Success;
 }



More information about the llvm-commits mailing list