Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[SPARC][IAS] Add definitions for OSA 2011 instructions #138403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: users/koachan/spr/main.sparcias-add-definitions-for-osa-2011-instructions
Choose a base branch
Loading
from

Conversation

koachan
Copy link
Contributor

@koachan koachan commented May 3, 2025

No description provided.

Created using spr 1.3.5
@llvmbot
Copy link
Member

llvmbot commented May 3, 2025

@llvm/pr-subscribers-backend-sparc

@llvm/pr-subscribers-llvm-binary-utilities

Author: Koakuma (koachan)

Changes

Patch is 56.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138403.diff

15 Files Affected:

  • (modified) llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def (+1)
  • (modified) llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp (+9)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp (+15)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp (+2)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h (+5-1)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp (+39)
  • (modified) llvm/lib/Target/Sparc/Sparc.td (+4-1)
  • (modified) llvm/lib/Target/Sparc/SparcInstrAliases.td (+65)
  • (modified) llvm/lib/Target/Sparc/SparcInstrFormats.td (+43)
  • (modified) llvm/lib/Target/Sparc/SparcInstrInfo.td (+16)
  • (modified) llvm/lib/Target/Sparc/SparcInstrUAOSA.td (+105-1)
  • (modified) llvm/test/MC/Disassembler/Sparc/sparc-ua-osa.txt (+176-1)
  • (added) llvm/test/MC/Sparc/sparc-osa2011.s (+274)
  • (removed) llvm/test/MC/Sparc/sparc64-bpr-offset.s (-31)
  • (added) llvm/test/MC/Sparc/sparc64-branch-offset.s (+267)
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
index 7e01a4a8a0a06..b87949ab199b5 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
@@ -87,3 +87,4 @@ ELF_RELOC(R_SPARC_GOTDATA_LOX10,  81)
 ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22,  82)
 ELF_RELOC(R_SPARC_GOTDATA_OP_LOX10,  83)
 ELF_RELOC(R_SPARC_GOTDATA_OP,     84)
+ELF_RELOC(R_SPARC_WDISP10, 88)
diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index 828d638723587..c42e173379a39 100644
--- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -261,6 +261,8 @@ DecodeCoprocPairRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address,
 
 static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, uint64_t Address,
                                const MCDisassembler *Decoder);
+static DecodeStatus DecodeSIMM5(MCInst &Inst, unsigned insn, uint64_t Address,
+                                const MCDisassembler *Decoder);
 static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address,
                                  const MCDisassembler *Decoder);
 
@@ -340,6 +342,13 @@ static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, uint64_t Address,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeSIMM5(MCInst &MI, unsigned insn, uint64_t Address,
+                                const MCDisassembler *Decoder) {
+  assert(isUInt<5>(insn));
+  MI.addOperand(MCOperand::createImm(SignExtend64<5>(insn)));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address,
                                  const MCDisassembler *Decoder) {
   assert(isUInt<13>(insn));
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index cc8b86e6135b5..d37724699be5d 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -50,6 +50,15 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     return (d16hi << 20) | d16lo;
   }
 
+  case Sparc::fixup_sparc_br10: {
+    // 7.17 Compare and Branch
+    // Inst{20-19} = d10hi;
+    // Inst{12-5}  = d10lo;
+    unsigned d10hi = (Value >> 10) & 0x3;
+    unsigned d10lo = (Value >> 2) & 0xff;
+    return (d10hi << 19) | (d10lo << 5);
+  }
+
   case Sparc::fixup_sparc_hix22:
     return (~Value >> 10) & 0x3fffff;
 
@@ -162,11 +171,13 @@ namespace {
 
     MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override {
       const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
+          // clang-format off
         // name                    offset bits  flags
         { "fixup_sparc_call30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br19",      13,     19,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br16",       0,     32,  MCFixupKindInfo::FKF_IsPCRel },
+        { "fixup_sparc_br10",       0,     32,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_13",        19,     13,  0 },
         { "fixup_sparc_hi22",      10,     22,  0 },
         { "fixup_sparc_lo10",      22,     10,  0 },
@@ -205,14 +216,17 @@ namespace {
         { "fixup_sparc_gotdata_hix22",  0,  0,  0 },
         { "fixup_sparc_gotdata_lox10",  0,  0,  0 },
         { "fixup_sparc_gotdata_op",     0,  0,  0 },
+          // clang-format on
       };
 
       const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
+          // clang-format off
         // name                    offset bits  flags
         { "fixup_sparc_call30",     0,     30,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br16",      32,      0,  MCFixupKindInfo::FKF_IsPCRel },
+        { "fixup_sparc_br10",      32,      0,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_13",         0,     13,  0 },
         { "fixup_sparc_hi22",       0,     22,  0 },
         { "fixup_sparc_lo10",       0,     10,  0 },
@@ -251,6 +265,7 @@ namespace {
         { "fixup_sparc_gotdata_hix22",  0,  0,  0 },
         { "fixup_sparc_gotdata_lox10",  0,  0,  0 },
         { "fixup_sparc_gotdata_op",     0,  0,  0 },
+          // clang-format on
       };
 
       // Fixup kinds from .reloc directive are like R_SPARC_NONE. They do
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
index f95e5ac1664e6..6b6d352c7736b 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -84,6 +84,8 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
     case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19;
     case Sparc::fixup_sparc_br16:
       return ELF::R_SPARC_WDISP16;
+    case Sparc::fixup_sparc_br10:
+      return ELF::R_SPARC_WDISP10;
     case Sparc::fixup_sparc_pc22:    return ELF::R_SPARC_PC22;
     case Sparc::fixup_sparc_pc10:    return ELF::R_SPARC_PC10;
     case Sparc::fixup_sparc_wplt30:  return ELF::R_SPARC_WPLT30;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
index 3b91326589894..ec8f78cd63812 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
@@ -11,6 +11,7 @@
 
 #include "llvm/MC/MCFixup.h"
 
+// clang-format off
 namespace llvm {
   namespace Sparc {
     enum Fixups {
@@ -28,6 +29,9 @@ namespace llvm {
       /// fixup_sparc_bpr  - 16-bit fixup for bpr
       fixup_sparc_br16,
 
+      /// fixup_sparc_br10  - 10-bit fixup for cbcond
+      fixup_sparc_br10,
+
       /// fixup_sparc_13 - 13-bit fixup
       fixup_sparc_13,
 
@@ -112,5 +116,5 @@ namespace llvm {
     };
   }
 }
-
+// clang-format on
 #endif
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
index 0c9ba6a8a297c..06721db60cdd6 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
@@ -71,6 +71,9 @@ class SparcMCCodeEmitter : public MCCodeEmitter {
   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
+  unsigned getSImm5OpValue(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
   unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,
                             SmallVectorImpl<MCFixup> &Fixups,
                             const MCSubtargetInfo &STI) const;
@@ -80,6 +83,9 @@ class SparcMCCodeEmitter : public MCCodeEmitter {
   unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const;
+  unsigned getCompareAndBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                                            SmallVectorImpl<MCFixup> &Fixups,
+                                            const MCSubtargetInfo &STI) const;
 };
 
 } // end anonymous namespace
@@ -141,6 +147,26 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   return 0;
 }
 
+unsigned SparcMCCodeEmitter::getSImm5OpValue(const MCInst &MI, unsigned OpNo,
+                                             SmallVectorImpl<MCFixup> &Fixups,
+                                             const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+
+  if (MO.isImm())
+    return MO.getImm();
+
+  assert(MO.isExpr() &&
+         "getSImm5OpValue expects only expressions or an immediate");
+
+  const MCExpr *Expr = MO.getExpr();
+
+  // Constant value, no fixup is needed
+  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
+    return CE->getValue();
+
+  llvm_unreachable("simm5 operands can only be used with constants!");
+}
+
 unsigned
 SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
                                      SmallVectorImpl<MCFixup> &Fixups,
@@ -239,6 +265,19 @@ getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+unsigned SparcMCCodeEmitter::getCompareAndBranchTargetOpValue(
+    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
+    const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm())
+    return getMachineOpValue(MI, MO, Fixups, STI);
+
+  Fixups.push_back(
+      MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br10));
+
+  return 0;
+}
+
 #include "SparcGenMCCodeEmitter.inc"
 
 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td
index 93c3098bd89fe..6e6c887e60e12 100644
--- a/llvm/lib/Target/Sparc/Sparc.td
+++ b/llvm/lib/Target/Sparc/Sparc.td
@@ -55,6 +55,9 @@ def FeatureUA2005
 def FeatureUA2007
   : SubtargetFeature<"ua2007", "IsUA2007", "true",
                      "Enable UltraSPARC Architecture 2007 extensions">;
+def FeatureOSA2011
+  : SubtargetFeature<"osa2011", "IsOSA2011", "true",
+                     "Enable Oracle SPARC Architecture 2011 extensions">;
 def FeatureLeon
   : SubtargetFeature<"leon", "IsLeon", "true",
                      "Enable LEON extensions">;
@@ -166,7 +169,7 @@ def : Proc<"niagara3",        [FeatureV9, FeatureV8Deprecated, UsePopc,
                                FeatureUA2005, FeatureUA2007]>;
 def : Proc<"niagara4",        [FeatureV9, FeatureV8Deprecated, UsePopc,
                                FeatureVIS, FeatureVIS2, FeatureVIS3,
-                               FeatureUA2005, FeatureUA2007]>;
+                               FeatureUA2005, FeatureUA2007, FeatureOSA2011]>;
 
 // LEON 2 FT generic
 def : Processor<"leon2", LEON2Itineraries,
diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td
index 590395c16965b..fa2c62101d30e 100644
--- a/llvm/lib/Target/Sparc/SparcInstrAliases.td
+++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td
@@ -331,6 +331,25 @@ multiclass reg_cond_alias<string rcond, int condVal> {
                             Requires<[Is64Bit]>;
 }
 
+// Instruction aliases for compare-and-branch.
+multiclass cwb_cond_alias<string cond, int condVal> {
+  def : InstAlias<!strconcat(!strconcat("cwb", cond), " $rs1, $rs2, $imm"),
+                  (CWBCONDrr cbtarget:$imm, condVal, IntRegs:$rs1, IntRegs:$rs2)>,
+                  Requires<[HasOSA2011]>;
+  def : InstAlias<!strconcat(!strconcat("cwb", cond), " $rs1, $simm5, $imm"),
+                  (CWBCONDri cbtarget:$imm, condVal, IntRegs:$rs1, simm5Op:$simm5)>,
+                  Requires<[HasOSA2011]>;
+}
+
+multiclass cxb_cond_alias<string cond, int condVal> {
+  def : InstAlias<!strconcat(!strconcat("cxb", cond), " $rs1, $rs2, $imm"),
+                  (CXBCONDrr cbtarget:$imm, condVal, IntRegs:$rs1, IntRegs:$rs2)>,
+                  Requires<[HasOSA2011]>;
+  def : InstAlias<!strconcat(!strconcat("cxb", cond), " $rs1, $simm5, $imm"),
+                  (CXBCONDri cbtarget:$imm, condVal, IntRegs:$rs1, simm5Op:$simm5)>,
+                  Requires<[HasOSA2011]>;
+}
+
 defm : int_cond_alias<"a",    0b1000>;
 defm : int_cond_alias<"n",    0b0000>;
 defm : int_cond_alias<"ne",   0b1001>;
@@ -408,6 +427,46 @@ defm : reg_cond_alias<"ne",   0b101>;
 defm : reg_cond_alias<"gz",   0b110>;
 defm : reg_cond_alias<"gez",  0b111>;
 
+defm : cwb_cond_alias<"ne",   0b1001>;
+defm : cwb_cond_alias<"e",    0b0001>;
+defm : cwb_cond_alias<"g",    0b1010>;
+defm : cwb_cond_alias<"le",   0b0010>;
+defm : cwb_cond_alias<"ge",   0b1011>;
+defm : cwb_cond_alias<"l",    0b0011>;
+defm : cwb_cond_alias<"gu",   0b1100>;
+defm : cwb_cond_alias<"leu",  0b0100>;
+defm : cwb_cond_alias<"cc",   0b1101>;
+defm : cwb_cond_alias<"cs",   0b0101>;
+defm : cwb_cond_alias<"pos",  0b1110>;
+defm : cwb_cond_alias<"neg",  0b0110>;
+defm : cwb_cond_alias<"vc",   0b1111>;
+defm : cwb_cond_alias<"vs",   0b0111>;
+let EmitPriority = 0 in
+{
+  defm : cwb_cond_alias<"geu",  0b1101>; // same as cc
+  defm : cwb_cond_alias<"lu",   0b0101>; // same as cs
+}
+
+defm : cxb_cond_alias<"ne",   0b1001>;
+defm : cxb_cond_alias<"e",    0b0001>;
+defm : cxb_cond_alias<"g",    0b1010>;
+defm : cxb_cond_alias<"le",   0b0010>;
+defm : cxb_cond_alias<"ge",   0b1011>;
+defm : cxb_cond_alias<"l",    0b0011>;
+defm : cxb_cond_alias<"gu",   0b1100>;
+defm : cxb_cond_alias<"leu",  0b0100>;
+defm : cxb_cond_alias<"cc",   0b1101>;
+defm : cxb_cond_alias<"cs",   0b0101>;
+defm : cxb_cond_alias<"pos",  0b1110>;
+defm : cxb_cond_alias<"neg",  0b0110>;
+defm : cxb_cond_alias<"vc",   0b1111>;
+defm : cxb_cond_alias<"vs",   0b0111>;
+let EmitPriority = 0 in
+{
+  defm : cxb_cond_alias<"geu",  0b1101>; // same as cc
+  defm : cxb_cond_alias<"lu",   0b0101>; // same as cs
+}
+
 // Section A.3 Synthetic Instructions
 
 // Most are marked as Emit=0, so that they are not used for disassembly. This is
@@ -665,3 +724,9 @@ def : InstAlias<"signx $rs1, $rd", (SRArr IntRegs:$rd, IntRegs:$rs1, G0), 0>, Re
 
 // sir -> sir 0
 def : InstAlias<"sir", (SIR 0), 0>;
+
+// pause reg_or_imm -> wrasr %g0, reg_or_imm, %asr27
+let Predicates = [HasOSA2011] in {
+def : InstAlias<"pause $rs2", (WRASRrr ASR27, G0, IntRegs:$rs2), 1>;
+def : InstAlias<"pause $simm13", (WRASRri ASR27, G0, simm13Op:$simm13), 1>;
+} // Predicates = [HasOSA2011]
diff --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td
index 2998f53ef2dbc..fe10bb443348a 100644
--- a/llvm/lib/Target/Sparc/SparcInstrFormats.td
+++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td
@@ -102,6 +102,49 @@ class F2_4<bit annul, bit pred, dag outs, dag ins,
   let Inst{13-0}  = imm16{13-0};
 }
 
+class F2_5<bit cc, dag outs, dag ins, string asmstr,
+           list<dag> pattern = [], InstrItinClass itin = NoItinerary>
+   : InstSP<outs, ins, asmstr, pattern, itin> {
+  bits<10> imm10;
+  bits<5>  rs1;
+  bits<5>  rs2;
+  bits<4>  cond;
+
+  let op          = 0; // op = 0
+
+  let Inst{29}    = cond{3};
+  let Inst{28}    = 1;
+  let Inst{27-25} = cond{2-0};
+  let Inst{24-22} = 0b011;
+  let Inst{21}    = cc;
+  let Inst{20-19} = imm10{9-8};
+  let Inst{18-14} = rs1;
+  let Inst{13}    = 0; // i = 0
+  let Inst{12-5}  = imm10{7-0};
+  let Inst{4-0}   = rs2;
+}
+
+class F2_6<bit cc, dag outs, dag ins, string asmstr,
+           list<dag> pattern = [], InstrItinClass itin = NoItinerary>
+   : InstSP<outs, ins, asmstr, pattern, itin> {
+  bits<10> imm10;
+  bits<5>  rs1;
+  bits<5>  simm5;
+  bits<4>  cond;
+
+  let op          = 0; // op = 0
+
+  let Inst{29}    = cond{3};
+  let Inst{28}    = 1;
+  let Inst{27-25} = cond{2-0};
+  let Inst{24-22} = 0b011;
+  let Inst{21}    = cc;
+  let Inst{20-19} = imm10{9-8};
+  let Inst{18-14} = rs1;
+  let Inst{13}    = 1; // i = 1
+  let Inst{12-5}  = imm10{7-0};
+  let Inst{4-0}   = simm5;
+}
 
 //===----------------------------------------------------------------------===//
 // Format #3 instruction classes in the Sparc
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 057eafd734e71..c14d72b33c08c 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -55,6 +55,10 @@ def HasUA2005 : Predicate<"Subtarget->isUA2005()">,
 def HasUA2007 : Predicate<"Subtarget->isUA2007()">,
                 AssemblerPredicate<(all_of FeatureUA2007)>;
 
+// HasOSA2011 - This is true when the target processor has OSA 2011 extensions.
+def HasOSA2011 : Predicate<"Subtarget->isOSA2011()">,
+                AssemblerPredicate<(all_of FeatureOSA2011)>;
+
 // HasHardQuad - This is true when the target processor supports quad floating
 // point instructions.
 def HasHardQuad : Predicate<"Subtarget->hasHardQuad()">;
@@ -93,6 +97,8 @@ def UseDeprecatedInsts : Predicate<"Subtarget->useV8DeprecatedInsts()">;
 // FIXME these should have AsmOperandClass.
 def uimm3 : PatLeaf<(imm), [{ return isUInt<3>(N->getZExtValue()); }]>;
 
+def simm5  : PatLeaf<(imm), [{ return isInt<5>(N->getSExtValue()); }]>;
+
 def simm10  : PatLeaf<(imm), [{ return isInt<10>(N->getSExtValue()); }]>;
 
 def simm11  : PatLeaf<(imm), [{ return isInt<11>(N->getSExtValue()); }]>;
@@ -231,6 +237,10 @@ def bprtarget16 : Operand<OtherVT> {
   let EncoderMethod = "getBranchOnRegTargetOpValue";
 }
 
+def cbtarget : Operand<OtherVT> {
+  let EncoderMethod = "getCompareAndBranchTargetOpValue";
+}
+
 def SparcCallTargetAsmOperand : AsmOperandClass {
   let Name = "CallTarget";
   let ParserMethod = "parseCallTarget";
@@ -242,6 +252,12 @@ def calltarget : Operand<i32> {
   let ParserMatchClass = SparcCallTargetAsmOperand;
 }
 
+def simm5Op : Operand<iPTR> {
+  let OperandType = "OPERAND_IMMEDIATE";
+  let DecoderMethod = "DecodeSIMM5";
+  let EncoderMethod = "getSImm5OpValue";
+}
+
 def simm13Op : Operand<iPTR> {
   let OperandType = "OPERAND_IMMEDIATE";
   let DecoderMethod = "DecodeSIMM13";
diff --git a/llvm/lib/Target/Sparc/SparcInstrUAOSA.td b/llvm/lib/Target/Sparc/SparcInstrUAOSA.td
index a1bfcc3dbb652..4da489d23fe43 100644
--- a/llvm/lib/Target/Sparc/SparcInstrUAOSA.td
+++ b/llvm/lib/Target/Sparc/SparcInstrUAOSA.td
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file contains instruction formats, definitions and patterns needed for
-// UA 2005 and UA 2007 instructions on SPARC.
+// UA 2005, UA 2007, and OSA 2011 instructions on SPARC.
 //===----------------------------------------------------------------------===//
 
 // Convenience template for 4-operand instructions
@@ -16,6 +16,21 @@ class FourOp<string OpcStr, bits<6> op3val, bits<4> op5val,
       : F3_4<op3val, op5val, (outs RC:$rd), (ins RC:$rs1, RC:$rs2, RC:$rs3),
         !strconcat(OpcStr, " $rs1, $rs2, $rs3, $rd")>;
 
+class FourOpImm<string OpcStr, bits<6> op3val, bits<4> op5val,
+        RegisterClass RC>
+      : F3_4<op3val, op5val, (outs RC:$rd), (ins RC:$rs1, RC:$rs2, simm5Op:$rs3),
+        !strconcat(OpcStr, " $rs1, $rs2, $rs3, $rd")>;
+
+/// F2_56 multiclass - Define a F2_5/F2_6 pattern in one shot.
+multiclass F2_56<string OpcStr, bits<1> cc> {
+  def rr  : F2_5<cc, (outs),
+                 (ins cbtarget:$imm10, CCOp:$cond, IntRegs:$rs1, IntRegs:$rs2),
+                 !strconcat(OpcStr, "$cond $rs1, $rs2, $imm10")>;
+  def ri  : F2_6<cc, (outs),
+                 (ins cbtarget:$imm10, CCOp:$cond, IntRegs:$rs1, simm5Op:$simm5),
+                 !strconcat(OpcStr, "$cond $rs1, $simm5, $imm10")>;
+}
+
 // UltraSPARC Architecture 2005 Instructions
 let Predicates = [HasUA2005] in {
 let hasSideEffects = 1 in
@@ -38,3 +53,92 @@ def FNMADDD : FourOp<"fnmaddd", 0b110111, 0b1110, DFPRegs>;
 def FNMSUBS : FourOp<"fnmsubs", 0b110111, 0b1001, FPRegs>;
 def FNMSUBD : FourOp<"fnmsubd", 0b110111, 0b1010, DFPRegs>;
 } // Predicates = [HasUA2007]
+
+// Oracle SPARC Architecture 2011 Instructions
+let Predicates = [HasOSA2011] in {
+let isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in {
+defm CWBCOND : F2_56<"cwb", 0>;
+defm CXBCOND : F2_56<"cxb", 1>;
+}
+
+def FPMADDX   : FourOp<"fpmaddx", 0b110111, 0b0000, DFPRegs>;
+def FPMADDXHI : FourOp<"fpmaddxhi", 0b110111, 0b0100, DFPRegs>;
+
+def AES_EROUND01 : FourOp<"aes_eround01", 0b011001, 0b0000, DFPRegs>;
+def AES_EROUND23 : FourOp<"aes_eround23", 0b011001, 0b0001, DFPRegs>;
+def AES_DROUND01 : FourOp<"aes_dround01", 0b011001, 0b0010, DFPRegs>;
+def AES_DROUND23 : FourOp<"aes_dround23", 0b011001, 0b0011, DFPRegs>;
+def AES_EROUND01_LAST : FourOp<"aes_eround01_l", 0b011001, 0b0100, DFPRegs>;
+def AES_EROUND23_LAST : FourOp<"aes_eround23_l", 0b011001, 0b0101, DFPRegs>;
+def AES_DROUND01_LAST : FourOp<"aes_dround01_l", 0b011001, 0b0110, D...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented May 3, 2025

@llvm/pr-subscribers-mc

Author: Koakuma (koachan)

Changes

Patch is 56.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138403.diff

15 Files Affected:

  • (modified) llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def (+1)
  • (modified) llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp (+9)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp (+15)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp (+2)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h (+5-1)
  • (modified) llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp (+39)
  • (modified) llvm/lib/Target/Sparc/Sparc.td (+4-1)
  • (modified) llvm/lib/Target/Sparc/SparcInstrAliases.td (+65)
  • (modified) llvm/lib/Target/Sparc/SparcInstrFormats.td (+43)
  • (modified) llvm/lib/Target/Sparc/SparcInstrInfo.td (+16)
  • (modified) llvm/lib/Target/Sparc/SparcInstrUAOSA.td (+105-1)
  • (modified) llvm/test/MC/Disassembler/Sparc/sparc-ua-osa.txt (+176-1)
  • (added) llvm/test/MC/Sparc/sparc-osa2011.s (+274)
  • (removed) llvm/test/MC/Sparc/sparc64-bpr-offset.s (-31)
  • (added) llvm/test/MC/Sparc/sparc64-branch-offset.s (+267)
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
index 7e01a4a8a0a06..b87949ab199b5 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/Sparc.def
@@ -87,3 +87,4 @@ ELF_RELOC(R_SPARC_GOTDATA_LOX10,  81)
 ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22,  82)
 ELF_RELOC(R_SPARC_GOTDATA_OP_LOX10,  83)
 ELF_RELOC(R_SPARC_GOTDATA_OP,     84)
+ELF_RELOC(R_SPARC_WDISP10, 88)
diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index 828d638723587..c42e173379a39 100644
--- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -261,6 +261,8 @@ DecodeCoprocPairRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address,
 
 static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, uint64_t Address,
                                const MCDisassembler *Decoder);
+static DecodeStatus DecodeSIMM5(MCInst &Inst, unsigned insn, uint64_t Address,
+                                const MCDisassembler *Decoder);
 static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address,
                                  const MCDisassembler *Decoder);
 
@@ -340,6 +342,13 @@ static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, uint64_t Address,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeSIMM5(MCInst &MI, unsigned insn, uint64_t Address,
+                                const MCDisassembler *Decoder) {
+  assert(isUInt<5>(insn));
+  MI.addOperand(MCOperand::createImm(SignExtend64<5>(insn)));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address,
                                  const MCDisassembler *Decoder) {
   assert(isUInt<13>(insn));
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index cc8b86e6135b5..d37724699be5d 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -50,6 +50,15 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     return (d16hi << 20) | d16lo;
   }
 
+  case Sparc::fixup_sparc_br10: {
+    // 7.17 Compare and Branch
+    // Inst{20-19} = d10hi;
+    // Inst{12-5}  = d10lo;
+    unsigned d10hi = (Value >> 10) & 0x3;
+    unsigned d10lo = (Value >> 2) & 0xff;
+    return (d10hi << 19) | (d10lo << 5);
+  }
+
   case Sparc::fixup_sparc_hix22:
     return (~Value >> 10) & 0x3fffff;
 
@@ -162,11 +171,13 @@ namespace {
 
     MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override {
       const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
+          // clang-format off
         // name                    offset bits  flags
         { "fixup_sparc_call30",     2,     30,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br22",      10,     22,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br19",      13,     19,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br16",       0,     32,  MCFixupKindInfo::FKF_IsPCRel },
+        { "fixup_sparc_br10",       0,     32,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_13",        19,     13,  0 },
         { "fixup_sparc_hi22",      10,     22,  0 },
         { "fixup_sparc_lo10",      22,     10,  0 },
@@ -205,14 +216,17 @@ namespace {
         { "fixup_sparc_gotdata_hix22",  0,  0,  0 },
         { "fixup_sparc_gotdata_lox10",  0,  0,  0 },
         { "fixup_sparc_gotdata_op",     0,  0,  0 },
+          // clang-format on
       };
 
       const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
+          // clang-format off
         // name                    offset bits  flags
         { "fixup_sparc_call30",     0,     30,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br22",       0,     22,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br19",       0,     19,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_br16",      32,      0,  MCFixupKindInfo::FKF_IsPCRel },
+        { "fixup_sparc_br10",      32,      0,  MCFixupKindInfo::FKF_IsPCRel },
         { "fixup_sparc_13",         0,     13,  0 },
         { "fixup_sparc_hi22",       0,     22,  0 },
         { "fixup_sparc_lo10",       0,     10,  0 },
@@ -251,6 +265,7 @@ namespace {
         { "fixup_sparc_gotdata_hix22",  0,  0,  0 },
         { "fixup_sparc_gotdata_lox10",  0,  0,  0 },
         { "fixup_sparc_gotdata_op",     0,  0,  0 },
+          // clang-format on
       };
 
       // Fixup kinds from .reloc directive are like R_SPARC_NONE. They do
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
index f95e5ac1664e6..6b6d352c7736b 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -84,6 +84,8 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx,
     case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19;
     case Sparc::fixup_sparc_br16:
       return ELF::R_SPARC_WDISP16;
+    case Sparc::fixup_sparc_br10:
+      return ELF::R_SPARC_WDISP10;
     case Sparc::fixup_sparc_pc22:    return ELF::R_SPARC_PC22;
     case Sparc::fixup_sparc_pc10:    return ELF::R_SPARC_PC10;
     case Sparc::fixup_sparc_wplt30:  return ELF::R_SPARC_WPLT30;
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
index 3b91326589894..ec8f78cd63812 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
@@ -11,6 +11,7 @@
 
 #include "llvm/MC/MCFixup.h"
 
+// clang-format off
 namespace llvm {
   namespace Sparc {
     enum Fixups {
@@ -28,6 +29,9 @@ namespace llvm {
       /// fixup_sparc_bpr  - 16-bit fixup for bpr
       fixup_sparc_br16,
 
+      /// fixup_sparc_br10  - 10-bit fixup for cbcond
+      fixup_sparc_br10,
+
       /// fixup_sparc_13 - 13-bit fixup
       fixup_sparc_13,
 
@@ -112,5 +116,5 @@ namespace llvm {
     };
   }
 }
-
+// clang-format on
 #endif
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
index 0c9ba6a8a297c..06721db60cdd6 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
@@ -71,6 +71,9 @@ class SparcMCCodeEmitter : public MCCodeEmitter {
   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
+  unsigned getSImm5OpValue(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
   unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,
                             SmallVectorImpl<MCFixup> &Fixups,
                             const MCSubtargetInfo &STI) const;
@@ -80,6 +83,9 @@ class SparcMCCodeEmitter : public MCCodeEmitter {
   unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const;
+  unsigned getCompareAndBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                                            SmallVectorImpl<MCFixup> &Fixups,
+                                            const MCSubtargetInfo &STI) const;
 };
 
 } // end anonymous namespace
@@ -141,6 +147,26 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   return 0;
 }
 
+unsigned SparcMCCodeEmitter::getSImm5OpValue(const MCInst &MI, unsigned OpNo,
+                                             SmallVectorImpl<MCFixup> &Fixups,
+                                             const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+
+  if (MO.isImm())
+    return MO.getImm();
+
+  assert(MO.isExpr() &&
+         "getSImm5OpValue expects only expressions or an immediate");
+
+  const MCExpr *Expr = MO.getExpr();
+
+  // Constant value, no fixup is needed
+  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
+    return CE->getValue();
+
+  llvm_unreachable("simm5 operands can only be used with constants!");
+}
+
 unsigned
 SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,
                                      SmallVectorImpl<MCFixup> &Fixups,
@@ -239,6 +265,19 @@ getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+unsigned SparcMCCodeEmitter::getCompareAndBranchTargetOpValue(
+    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
+    const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm())
+    return getMachineOpValue(MI, MO, Fixups, STI);
+
+  Fixups.push_back(
+      MCFixup::create(0, MO.getExpr(), (MCFixupKind)Sparc::fixup_sparc_br10));
+
+  return 0;
+}
+
 #include "SparcGenMCCodeEmitter.inc"
 
 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td
index 93c3098bd89fe..6e6c887e60e12 100644
--- a/llvm/lib/Target/Sparc/Sparc.td
+++ b/llvm/lib/Target/Sparc/Sparc.td
@@ -55,6 +55,9 @@ def FeatureUA2005
 def FeatureUA2007
   : SubtargetFeature<"ua2007", "IsUA2007", "true",
                      "Enable UltraSPARC Architecture 2007 extensions">;
+def FeatureOSA2011
+  : SubtargetFeature<"osa2011", "IsOSA2011", "true",
+                     "Enable Oracle SPARC Architecture 2011 extensions">;
 def FeatureLeon
   : SubtargetFeature<"leon", "IsLeon", "true",
                      "Enable LEON extensions">;
@@ -166,7 +169,7 @@ def : Proc<"niagara3",        [FeatureV9, FeatureV8Deprecated, UsePopc,
                                FeatureUA2005, FeatureUA2007]>;
 def : Proc<"niagara4",        [FeatureV9, FeatureV8Deprecated, UsePopc,
                                FeatureVIS, FeatureVIS2, FeatureVIS3,
-                               FeatureUA2005, FeatureUA2007]>;
+                               FeatureUA2005, FeatureUA2007, FeatureOSA2011]>;
 
 // LEON 2 FT generic
 def : Processor<"leon2", LEON2Itineraries,
diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td
index 590395c16965b..fa2c62101d30e 100644
--- a/llvm/lib/Target/Sparc/SparcInstrAliases.td
+++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td
@@ -331,6 +331,25 @@ multiclass reg_cond_alias<string rcond, int condVal> {
                             Requires<[Is64Bit]>;
 }
 
+// Instruction aliases for compare-and-branch.
+multiclass cwb_cond_alias<string cond, int condVal> {
+  def : InstAlias<!strconcat(!strconcat("cwb", cond), " $rs1, $rs2, $imm"),
+                  (CWBCONDrr cbtarget:$imm, condVal, IntRegs:$rs1, IntRegs:$rs2)>,
+                  Requires<[HasOSA2011]>;
+  def : InstAlias<!strconcat(!strconcat("cwb", cond), " $rs1, $simm5, $imm"),
+                  (CWBCONDri cbtarget:$imm, condVal, IntRegs:$rs1, simm5Op:$simm5)>,
+                  Requires<[HasOSA2011]>;
+}
+
+multiclass cxb_cond_alias<string cond, int condVal> {
+  def : InstAlias<!strconcat(!strconcat("cxb", cond), " $rs1, $rs2, $imm"),
+                  (CXBCONDrr cbtarget:$imm, condVal, IntRegs:$rs1, IntRegs:$rs2)>,
+                  Requires<[HasOSA2011]>;
+  def : InstAlias<!strconcat(!strconcat("cxb", cond), " $rs1, $simm5, $imm"),
+                  (CXBCONDri cbtarget:$imm, condVal, IntRegs:$rs1, simm5Op:$simm5)>,
+                  Requires<[HasOSA2011]>;
+}
+
 defm : int_cond_alias<"a",    0b1000>;
 defm : int_cond_alias<"n",    0b0000>;
 defm : int_cond_alias<"ne",   0b1001>;
@@ -408,6 +427,46 @@ defm : reg_cond_alias<"ne",   0b101>;
 defm : reg_cond_alias<"gz",   0b110>;
 defm : reg_cond_alias<"gez",  0b111>;
 
+defm : cwb_cond_alias<"ne",   0b1001>;
+defm : cwb_cond_alias<"e",    0b0001>;
+defm : cwb_cond_alias<"g",    0b1010>;
+defm : cwb_cond_alias<"le",   0b0010>;
+defm : cwb_cond_alias<"ge",   0b1011>;
+defm : cwb_cond_alias<"l",    0b0011>;
+defm : cwb_cond_alias<"gu",   0b1100>;
+defm : cwb_cond_alias<"leu",  0b0100>;
+defm : cwb_cond_alias<"cc",   0b1101>;
+defm : cwb_cond_alias<"cs",   0b0101>;
+defm : cwb_cond_alias<"pos",  0b1110>;
+defm : cwb_cond_alias<"neg",  0b0110>;
+defm : cwb_cond_alias<"vc",   0b1111>;
+defm : cwb_cond_alias<"vs",   0b0111>;
+let EmitPriority = 0 in
+{
+  defm : cwb_cond_alias<"geu",  0b1101>; // same as cc
+  defm : cwb_cond_alias<"lu",   0b0101>; // same as cs
+}
+
+defm : cxb_cond_alias<"ne",   0b1001>;
+defm : cxb_cond_alias<"e",    0b0001>;
+defm : cxb_cond_alias<"g",    0b1010>;
+defm : cxb_cond_alias<"le",   0b0010>;
+defm : cxb_cond_alias<"ge",   0b1011>;
+defm : cxb_cond_alias<"l",    0b0011>;
+defm : cxb_cond_alias<"gu",   0b1100>;
+defm : cxb_cond_alias<"leu",  0b0100>;
+defm : cxb_cond_alias<"cc",   0b1101>;
+defm : cxb_cond_alias<"cs",   0b0101>;
+defm : cxb_cond_alias<"pos",  0b1110>;
+defm : cxb_cond_alias<"neg",  0b0110>;
+defm : cxb_cond_alias<"vc",   0b1111>;
+defm : cxb_cond_alias<"vs",   0b0111>;
+let EmitPriority = 0 in
+{
+  defm : cxb_cond_alias<"geu",  0b1101>; // same as cc
+  defm : cxb_cond_alias<"lu",   0b0101>; // same as cs
+}
+
 // Section A.3 Synthetic Instructions
 
 // Most are marked as Emit=0, so that they are not used for disassembly. This is
@@ -665,3 +724,9 @@ def : InstAlias<"signx $rs1, $rd", (SRArr IntRegs:$rd, IntRegs:$rs1, G0), 0>, Re
 
 // sir -> sir 0
 def : InstAlias<"sir", (SIR 0), 0>;
+
+// pause reg_or_imm -> wrasr %g0, reg_or_imm, %asr27
+let Predicates = [HasOSA2011] in {
+def : InstAlias<"pause $rs2", (WRASRrr ASR27, G0, IntRegs:$rs2), 1>;
+def : InstAlias<"pause $simm13", (WRASRri ASR27, G0, simm13Op:$simm13), 1>;
+} // Predicates = [HasOSA2011]
diff --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td
index 2998f53ef2dbc..fe10bb443348a 100644
--- a/llvm/lib/Target/Sparc/SparcInstrFormats.td
+++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td
@@ -102,6 +102,49 @@ class F2_4<bit annul, bit pred, dag outs, dag ins,
   let Inst{13-0}  = imm16{13-0};
 }
 
+class F2_5<bit cc, dag outs, dag ins, string asmstr,
+           list<dag> pattern = [], InstrItinClass itin = NoItinerary>
+   : InstSP<outs, ins, asmstr, pattern, itin> {
+  bits<10> imm10;
+  bits<5>  rs1;
+  bits<5>  rs2;
+  bits<4>  cond;
+
+  let op          = 0; // op = 0
+
+  let Inst{29}    = cond{3};
+  let Inst{28}    = 1;
+  let Inst{27-25} = cond{2-0};
+  let Inst{24-22} = 0b011;
+  let Inst{21}    = cc;
+  let Inst{20-19} = imm10{9-8};
+  let Inst{18-14} = rs1;
+  let Inst{13}    = 0; // i = 0
+  let Inst{12-5}  = imm10{7-0};
+  let Inst{4-0}   = rs2;
+}
+
+class F2_6<bit cc, dag outs, dag ins, string asmstr,
+           list<dag> pattern = [], InstrItinClass itin = NoItinerary>
+   : InstSP<outs, ins, asmstr, pattern, itin> {
+  bits<10> imm10;
+  bits<5>  rs1;
+  bits<5>  simm5;
+  bits<4>  cond;
+
+  let op          = 0; // op = 0
+
+  let Inst{29}    = cond{3};
+  let Inst{28}    = 1;
+  let Inst{27-25} = cond{2-0};
+  let Inst{24-22} = 0b011;
+  let Inst{21}    = cc;
+  let Inst{20-19} = imm10{9-8};
+  let Inst{18-14} = rs1;
+  let Inst{13}    = 1; // i = 1
+  let Inst{12-5}  = imm10{7-0};
+  let Inst{4-0}   = simm5;
+}
 
 //===----------------------------------------------------------------------===//
 // Format #3 instruction classes in the Sparc
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 057eafd734e71..c14d72b33c08c 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -55,6 +55,10 @@ def HasUA2005 : Predicate<"Subtarget->isUA2005()">,
 def HasUA2007 : Predicate<"Subtarget->isUA2007()">,
                 AssemblerPredicate<(all_of FeatureUA2007)>;
 
+// HasOSA2011 - This is true when the target processor has OSA 2011 extensions.
+def HasOSA2011 : Predicate<"Subtarget->isOSA2011()">,
+                AssemblerPredicate<(all_of FeatureOSA2011)>;
+
 // HasHardQuad - This is true when the target processor supports quad floating
 // point instructions.
 def HasHardQuad : Predicate<"Subtarget->hasHardQuad()">;
@@ -93,6 +97,8 @@ def UseDeprecatedInsts : Predicate<"Subtarget->useV8DeprecatedInsts()">;
 // FIXME these should have AsmOperandClass.
 def uimm3 : PatLeaf<(imm), [{ return isUInt<3>(N->getZExtValue()); }]>;
 
+def simm5  : PatLeaf<(imm), [{ return isInt<5>(N->getSExtValue()); }]>;
+
 def simm10  : PatLeaf<(imm), [{ return isInt<10>(N->getSExtValue()); }]>;
 
 def simm11  : PatLeaf<(imm), [{ return isInt<11>(N->getSExtValue()); }]>;
@@ -231,6 +237,10 @@ def bprtarget16 : Operand<OtherVT> {
   let EncoderMethod = "getBranchOnRegTargetOpValue";
 }
 
+def cbtarget : Operand<OtherVT> {
+  let EncoderMethod = "getCompareAndBranchTargetOpValue";
+}
+
 def SparcCallTargetAsmOperand : AsmOperandClass {
   let Name = "CallTarget";
   let ParserMethod = "parseCallTarget";
@@ -242,6 +252,12 @@ def calltarget : Operand<i32> {
   let ParserMatchClass = SparcCallTargetAsmOperand;
 }
 
+def simm5Op : Operand<iPTR> {
+  let OperandType = "OPERAND_IMMEDIATE";
+  let DecoderMethod = "DecodeSIMM5";
+  let EncoderMethod = "getSImm5OpValue";
+}
+
 def simm13Op : Operand<iPTR> {
   let OperandType = "OPERAND_IMMEDIATE";
   let DecoderMethod = "DecodeSIMM13";
diff --git a/llvm/lib/Target/Sparc/SparcInstrUAOSA.td b/llvm/lib/Target/Sparc/SparcInstrUAOSA.td
index a1bfcc3dbb652..4da489d23fe43 100644
--- a/llvm/lib/Target/Sparc/SparcInstrUAOSA.td
+++ b/llvm/lib/Target/Sparc/SparcInstrUAOSA.td
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file contains instruction formats, definitions and patterns needed for
-// UA 2005 and UA 2007 instructions on SPARC.
+// UA 2005, UA 2007, and OSA 2011 instructions on SPARC.
 //===----------------------------------------------------------------------===//
 
 // Convenience template for 4-operand instructions
@@ -16,6 +16,21 @@ class FourOp<string OpcStr, bits<6> op3val, bits<4> op5val,
       : F3_4<op3val, op5val, (outs RC:$rd), (ins RC:$rs1, RC:$rs2, RC:$rs3),
         !strconcat(OpcStr, " $rs1, $rs2, $rs3, $rd")>;
 
+class FourOpImm<string OpcStr, bits<6> op3val, bits<4> op5val,
+        RegisterClass RC>
+      : F3_4<op3val, op5val, (outs RC:$rd), (ins RC:$rs1, RC:$rs2, simm5Op:$rs3),
+        !strconcat(OpcStr, " $rs1, $rs2, $rs3, $rd")>;
+
+/// F2_56 multiclass - Define a F2_5/F2_6 pattern in one shot.
+multiclass F2_56<string OpcStr, bits<1> cc> {
+  def rr  : F2_5<cc, (outs),
+                 (ins cbtarget:$imm10, CCOp:$cond, IntRegs:$rs1, IntRegs:$rs2),
+                 !strconcat(OpcStr, "$cond $rs1, $rs2, $imm10")>;
+  def ri  : F2_6<cc, (outs),
+                 (ins cbtarget:$imm10, CCOp:$cond, IntRegs:$rs1, simm5Op:$simm5),
+                 !strconcat(OpcStr, "$cond $rs1, $simm5, $imm10")>;
+}
+
 // UltraSPARC Architecture 2005 Instructions
 let Predicates = [HasUA2005] in {
 let hasSideEffects = 1 in
@@ -38,3 +53,92 @@ def FNMADDD : FourOp<"fnmaddd", 0b110111, 0b1110, DFPRegs>;
 def FNMSUBS : FourOp<"fnmsubs", 0b110111, 0b1001, FPRegs>;
 def FNMSUBD : FourOp<"fnmsubd", 0b110111, 0b1010, DFPRegs>;
 } // Predicates = [HasUA2007]
+
+// Oracle SPARC Architecture 2011 Instructions
+let Predicates = [HasOSA2011] in {
+let isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in {
+defm CWBCOND : F2_56<"cwb", 0>;
+defm CXBCOND : F2_56<"cxb", 1>;
+}
+
+def FPMADDX   : FourOp<"fpmaddx", 0b110111, 0b0000, DFPRegs>;
+def FPMADDXHI : FourOp<"fpmaddxhi", 0b110111, 0b0100, DFPRegs>;
+
+def AES_EROUND01 : FourOp<"aes_eround01", 0b011001, 0b0000, DFPRegs>;
+def AES_EROUND23 : FourOp<"aes_eround23", 0b011001, 0b0001, DFPRegs>;
+def AES_DROUND01 : FourOp<"aes_dround01", 0b011001, 0b0010, DFPRegs>;
+def AES_DROUND23 : FourOp<"aes_dround23", 0b011001, 0b0011, DFPRegs>;
+def AES_EROUND01_LAST : FourOp<"aes_eround01_l", 0b011001, 0b0100, DFPRegs>;
+def AES_EROUND23_LAST : FourOp<"aes_eround23_l", 0b011001, 0b0101, DFPRegs>;
+def AES_DROUND01_LAST : FourOp<"aes_dround01_l", 0b011001, 0b0110, D...
[truncated]

@koachan koachan requested review from brad0, rorth and s-barannikov May 3, 2025 13:57
def FPMADDX : FourOp<"fpmaddx", 0b110111, 0b0000, DFPRegs>;
def FPMADDXHI : FourOp<"fpmaddxhi", 0b110111, 0b0100, DFPRegs>;

def AES_EROUND01 : FourOp<"aes_eround01", 0b011001, 0b0000, DFPRegs>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contrary to my comments in other PRs in the stack, I think it is fine to put these instructions in a separate file, as it is a new "class" of instructions (cryptography). I wouldn't bind them to a specific extension name though, something like SparcInstrInfoCrypto.td maybe?

Not a strong objection (in other PRs too), it is a personal PoV.

Created using spr 1.3.5
@koachan koachan requested a review from s-barannikov May 11, 2025 14:11
Created using spr 1.3.5
@brad0
Copy link
Contributor

brad0 commented May 16, 2025

cc @s-barannikov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.