[llvm] 312d6b4 - [AArch64] Implement assembler support for new SVE SEH unwind opcodes. (#137895)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 2 15:14:28 PDT 2025


Author: Eli Friedman
Date: 2025-05-02T15:14:25-07:00
New Revision: 312d6b488ef9d7c0e4d649827820db7285e36406

URL: https://github.com/llvm/llvm-project/commit/312d6b488ef9d7c0e4d649827820db7285e36406
DIFF: https://github.com/llvm/llvm-project/commit/312d6b488ef9d7c0e4d649827820db7285e36406.diff

LOG: [AArch64] Implement assembler support for new SVE SEH unwind opcodes. (#137895)

In order to support the AArch64 ABI, Microsoft has extended the unwinder
to support additional opcodes. (Updated documentation at
https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling .)

First in a series of patches to support SVE on Windows.

Added: 
    

Modified: 
    llvm/include/llvm/Support/Win64EH.h
    llvm/lib/MC/MCWin64EH.cpp
    llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
    llvm/test/MC/AArch64/seh.s
    llvm/test/tools/llvm-readobj/COFF/arm64-win-error1.s
    llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
    llvm/tools/llvm-readobj/ARMWinEHPrinter.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/Win64EH.h b/llvm/include/llvm/Support/Win64EH.h
index 8a9be15373917..ec3413b31ee4a 100644
--- a/llvm/include/llvm/Support/Win64EH.h
+++ b/llvm/include/llvm/Support/Win64EH.h
@@ -75,6 +75,9 @@ enum UnwindOpcodes {
   UOP_SaveAnyRegDPX,
   UOP_SaveAnyRegQX,
   UOP_SaveAnyRegQPX,
+  UOP_AllocZ,
+  UOP_SaveZReg,
+  UOP_SavePReg,
 
   // The following set of unwind opcodes is for ARM.  They are documented at
   // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling

diff  --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index bd5cf354659b6..e21f7756bda7a 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -421,6 +421,9 @@ static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
     case Win64EH::UOP_PACSignLR:
       Count += 1;
       break;
+    case Win64EH::UOP_AllocZ:
+      Count += 2;
+      break;
     case Win64EH::UOP_SaveAnyRegI:
     case Win64EH::UOP_SaveAnyRegIP:
     case Win64EH::UOP_SaveAnyRegD:
@@ -433,6 +436,8 @@ static uint32_t ARM64CountOfUnwindCodes(ArrayRef<WinEH::Instruction> Insns) {
     case Win64EH::UOP_SaveAnyRegDPX:
     case Win64EH::UOP_SaveAnyRegQX:
     case Win64EH::UOP_SaveAnyRegQPX:
+    case Win64EH::UOP_SaveZReg:
+    case Win64EH::UOP_SavePReg:
       Count += 3;
       break;
     }
@@ -640,6 +645,37 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer,
     streamer.emitInt8(b);
     break;
   }
+  case Win64EH::UOP_AllocZ: {
+    b = 0xDF;
+    streamer.emitInt8(b);
+    b = inst.Offset;
+    streamer.emitInt8(b);
+    break;
+  }
+  case Win64EH::UOP_SaveZReg: {
+    assert(inst.Register >= 8 && inst.Register <= 23);
+    assert(inst.Offset < 256);
+    b = 0xE7;
+    streamer.emitInt8(b);
+    reg = inst.Register - 8;
+    b = ((inst.Offset & 0xC0) >> 1) | reg;
+    streamer.emitInt8(b);
+    b = 0xC0 | (inst.Offset & 0x3F);
+    streamer.emitInt8(b);
+    break;
+  }
+  case Win64EH::UOP_SavePReg: {
+    assert(inst.Register >= 4 && inst.Register <= 15);
+    assert(inst.Offset < 256);
+    b = 0xE7;
+    streamer.emitInt8(b);
+    reg = inst.Register;
+    b = ((inst.Offset & 0xC0) >> 1) | 0x10 | reg;
+    streamer.emitInt8(b);
+    b = 0xC0 | (inst.Offset & 0x3F);
+    streamer.emitInt8(b);
+    break;
+  }
   }
 }
 
@@ -1016,6 +1052,11 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
       // "add x29, sp, #N" doesn't show up in the canonical pattern (except for
       // N=0, which is UOP_SetFP).
       return false;
+    case Win64EH::UOP_AllocZ:
+    case Win64EH::UOP_SaveZReg:
+    case Win64EH::UOP_SavePReg:
+      // Canonical prologues don't support spilling SVE registers.
+      return false;
     case Win64EH::UOP_TrapFrame:
     case Win64EH::UOP_Context:
     case Win64EH::UOP_ECContext:

diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index e178c5027571a..bcd5fde3b8e27 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -230,6 +230,9 @@ class AArch64AsmParser : public MCTargetAsmParser {
   bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
   bool parseDirectiveSEHPACSignLR(SMLoc L);
   bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
+  bool parseDirectiveSEHAllocZ(SMLoc L);
+  bool parseDirectiveSEHSaveZReg(SMLoc L);
+  bool parseDirectiveSEHSavePReg(SMLoc L);
   bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
   bool parseDirectiveAeabiAArch64Attr(SMLoc L);
 
@@ -7111,6 +7114,12 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
       parseDirectiveSEHSaveAnyReg(Loc, false, true);
     else if (IDVal == ".seh_save_any_reg_px")
       parseDirectiveSEHSaveAnyReg(Loc, true, true);
+    else if (IDVal == ".seh_allocz")
+      parseDirectiveSEHAllocZ(Loc);
+    else if (IDVal == ".seh_save_zreg")
+      parseDirectiveSEHSaveZReg(Loc);
+    else if (IDVal == ".seh_save_preg")
+      parseDirectiveSEHSavePReg(Loc);
     else
       return true;
   } else if (IsELF) {
@@ -7856,6 +7865,54 @@ bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
   return false;
 }
 
+/// parseDirectiveAllocZ
+/// ::= .seh_allocz
+bool AArch64AsmParser::parseDirectiveSEHAllocZ(SMLoc L) {
+  int64_t Offset;
+  if (parseImmExpr(Offset))
+    return true;
+  getTargetStreamer().emitARM64WinCFIAllocZ(Offset);
+  return false;
+}
+
+/// parseDirectiveSEHSaveZReg
+/// ::= .seh_save_zreg
+bool AArch64AsmParser::parseDirectiveSEHSaveZReg(SMLoc L) {
+  MCRegister RegNum;
+  StringRef Kind;
+  int64_t Offset;
+  ParseStatus Res =
+      tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
+  if (!Res.isSuccess())
+    return true;
+  if (check(RegNum < AArch64::Z8 || RegNum > AArch64::Z23, L,
+            "expected register in range z8 to z23"))
+    return true;
+  if (parseComma() || parseImmExpr(Offset))
+    return true;
+  getTargetStreamer().emitARM64WinCFISaveZReg(RegNum - AArch64::Z0, Offset);
+  return false;
+}
+
+/// parseDirectiveSEHSavePReg
+/// ::= .seh_save_preg
+bool AArch64AsmParser::parseDirectiveSEHSavePReg(SMLoc L) {
+  MCRegister RegNum;
+  StringRef Kind;
+  int64_t Offset;
+  ParseStatus Res =
+      tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
+  if (!Res.isSuccess())
+    return true;
+  if (check(RegNum < AArch64::P4 || RegNum > AArch64::P15, L,
+            "expected register in range p4 to p15"))
+    return true;
+  if (parseComma() || parseImmExpr(Offset))
+    return true;
+  getTargetStreamer().emitARM64WinCFISavePReg(RegNum - AArch64::P0, Offset);
+  return false;
+}
+
 bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
   // Expecting 3 AsmToken::Identifier after '.aeabi_subsection', a name and 2
   // parameters, e.g.: .aeabi_subsection (1)aeabi_feature_and_bits, (2)optional,

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index b12a12436db81..cc607e863d190 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -150,6 +150,15 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer {
   void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override {
     OS << "\t.seh_save_any_reg_px\tq" << Reg << ", " << Offset << "\n";
   }
+  void emitARM64WinCFIAllocZ(int Offset) override {
+    OS << "\t.seh_allocz\t" << Offset << "\n";
+  }
+  void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) override {
+    OS << "\t.seh_save_zreg\tz" << Reg << ", " << Offset << "\n";
+  }
+  void emitARM64WinCFISavePReg(unsigned Reg, int Offset) override {
+    OS << "\t.seh_save_preg\tp" << Reg << ", " << Offset << "\n";
+  }
 
   void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value,
                      std::string String) override {

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 43e099f919999..1427427b951a8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -93,6 +93,9 @@ class AArch64TargetStreamer : public MCTargetStreamer {
   virtual void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) {}
   virtual void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) {}
   virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) {}
+  virtual void emitARM64WinCFIAllocZ(int Offset) {}
+  virtual void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) {}
+  virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset) {}
 
   /// Build attributes implementation
   virtual void
@@ -182,6 +185,9 @@ class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
   void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) override;
   void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) override;
   void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override;
+  void emitARM64WinCFIAllocZ(int Offset) override;
+  void emitARM64WinCFISaveZReg(unsigned Reg, int Offset) override;
+  void emitARM64WinCFISavePReg(unsigned Reg, int Offset) override;
 
 private:
   void emitARM64WinUnwindCode(unsigned UnwindCode, int Reg, int Offset);

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
index fb8a3e1215d90..c03bc386ae349 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp
@@ -284,6 +284,20 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegQPX(unsigned Reg,
   emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQPX, Reg, Offset);
 }
 
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFIAllocZ(int Offset) {
+  emitARM64WinUnwindCode(Win64EH::UOP_AllocZ, 0, Offset);
+}
+
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveZReg(unsigned Reg,
+                                                           int Offset) {
+  emitARM64WinUnwindCode(Win64EH::UOP_SaveZReg, Reg, Offset);
+}
+
+void AArch64TargetWinCOFFStreamer::emitARM64WinCFISavePReg(unsigned Reg,
+                                                           int Offset) {
+  emitARM64WinUnwindCode(Win64EH::UOP_SavePReg, Reg, Offset);
+}
+
 MCStreamer *
 llvm::createAArch64WinCOFFStreamer(MCContext &Context,
                                    std::unique_ptr<MCAsmBackend> &&MAB,

diff  --git a/llvm/test/MC/AArch64/seh.s b/llvm/test/MC/AArch64/seh.s
index 5ad4fba2bf6b4..5e194568f62dd 100644
--- a/llvm/test/MC/AArch64/seh.s
+++ b/llvm/test/MC/AArch64/seh.s
@@ -20,7 +20,7 @@
 // CHECK-NEXT:   }
 // CHECK:        Section {
 // CHECK:          Name: .xdata
-// CHECK:          RawDataSize: 92
+// CHECK:          RawDataSize: 100
 // CHECK:          RelocationCount: 1
 // CHECK:          Characteristics [
 // CHECK-NEXT:       ALIGN_4BYTES
@@ -41,7 +41,7 @@
 
 // CHECK-NEXT: Relocations [
 // CHECK-NEXT:   Section (4) .xdata {
-// CHECK-NEXT:     0x50 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
+// CHECK-NEXT:     0x58 IMAGE_REL_ARM64_ADDR32NB __C_specific_handler
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Section (5) .pdata {
 // CHECK-NEXT:     0x0 IMAGE_REL_ARM64_ADDR32NB .text
@@ -54,8 +54,11 @@
 // CHECK-NEXT:     Function: func
 // CHECK-NEXT:     ExceptionRecord: .xdata
 // CHECK-NEXT:     ExceptionData {
-// CHECK-NEXT:       FunctionLength: 156
+// CHECK-NEXT:       FunctionLength: 172
 // CHECK:            Prologue [
+// CHECK-NEXT:         0xe716c3            ; str p6, [sp, #3, mul vl]
+// CHECK-NEXT:         0xe703c5            ; str z11, [sp, #5, mul vl]
+// CHECK-NEXT:         0xdf05              ; addvl sp, #-5
 // CHECK-NEXT:         0xe76983            ; stp q9, q10, [sp, #-64]!
 // CHECK-NEXT:         0xe73d83            ; str q29, [sp, #-64]!
 // CHECK-NEXT:         0xe76243            ; stp d2, d3, [sp, #-64]!
@@ -96,8 +99,8 @@
 // CHECK-NEXT:       ]
 // CHECK-NEXT:       EpilogueScopes [
 // CHECK-NEXT:         EpilogueScope {
-// CHECK-NEXT:           StartOffset: 37
-// CHECK-NEXT:           EpilogueStartIndex: 69
+// CHECK-NEXT:           StartOffset: 41
+// CHECK-NEXT:           EpilogueStartIndex: 77
 // CHECK-NEXT:           Opcodes [
 // CHECK-NEXT:             0x01                ; add sp, #16
 // CHECK-NEXT:             0xe4                ; end
@@ -193,6 +196,13 @@ func:
     .seh_save_any_reg_x q29, 64
     nop
     .seh_save_any_reg_px q9, 64
+    nop
+    .seh_allocz 5
+    nop
+    .seh_save_zreg z11, 5
+    nop
+    .seh_save_preg p6, 3
+    nop
     .seh_endprologue
     nop
     .seh_startepilogue

diff  --git a/llvm/test/tools/llvm-readobj/COFF/arm64-win-error1.s b/llvm/test/tools/llvm-readobj/COFF/arm64-win-error1.s
index 4cf35902739b6..d17d93fcddfe8 100644
--- a/llvm/test/tools/llvm-readobj/COFF/arm64-win-error1.s
+++ b/llvm/test/tools/llvm-readobj/COFF/arm64-win-error1.s
@@ -6,7 +6,7 @@
 // RUN:   | llvm-readobj --unwind - | FileCheck %s
 
 // CHECK:     Prologue [
-// CHECK:        0xdf                ; Bad opcode!
+// CHECK:        0xef                ; Bad opcode!
 // CHECK:        0xff                ; Bad opcode!
 // CHECK:        0xd600              ; stp x19, lr, [sp, #0]
 // CHECK:        0x01                ; sub sp, #16
@@ -49,6 +49,6 @@
 	.long		0x10800012
 	.long 		0x8
 	.long 		0xe
-	.long 		0x00d6ffdf
+	.long 		0x00d6ffef
 	.long 		0xe3e3e401
 

diff  --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 08baa037eab27..ebee841e8acf2 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -160,6 +160,7 @@ const Decoder::RingEntry Decoder::Ring64[] = {
     {0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x},
     {0xfe, 0xdc, 2, &Decoder::opcode_save_freg},
     {0xff, 0xde, 2, &Decoder::opcode_save_freg_x},
+    {0xff, 0xdf, 2, &Decoder::opcode_alloc_z},
     {0xff, 0xe0, 4, &Decoder::opcode_alloc_l},
     {0xff, 0xe1, 1, &Decoder::opcode_setfp},
     {0xff, 0xe2, 2, &Decoder::opcode_addfp},
@@ -167,7 +168,7 @@ const Decoder::RingEntry Decoder::Ring64[] = {
     {0xff, 0xe4, 1, &Decoder::opcode_end},
     {0xff, 0xe5, 1, &Decoder::opcode_end_c},
     {0xff, 0xe6, 1, &Decoder::opcode_save_next},
-    {0xff, 0xe7, 3, &Decoder::opcode_save_any_reg},
+    {0xff, 0xe7, 3, &Decoder::opcode_e7},
     {0xff, 0xe8, 1, &Decoder::opcode_trap_frame},
     {0xff, 0xe9, 1, &Decoder::opcode_machine_frame},
     {0xff, 0xea, 1, &Decoder::opcode_context},
@@ -805,6 +806,16 @@ bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_alloc_z(const uint8_t *OC, unsigned &Offset,
+                             unsigned Length, bool Prologue) {
+  unsigned Off = OC[Offset + 1];
+  SW.startLine() << format("0x%02x%02x              ; addvl sp, #%d\n",
+                           OC[Offset], OC[Offset + 1],
+                           Prologue ? -(int)Off : (int)Off);
+  Offset += 2;
+  return false;
+}
+
 bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset,
                              unsigned Length, bool Prologue) {
   unsigned Off =
@@ -871,6 +882,24 @@ bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_e7(const uint8_t *OC, unsigned &Offset, unsigned Length,
+                        bool Prologue) {
+  // The e7 opcode has unusual decoding rules; write out the logic.
+  if ((OC[Offset + 1] & 0x80) == 0x80) {
+    SW.getOStream() << "reserved encoding\n";
+    Offset += 3;
+    return false;
+  }
+
+  if ((OC[Offset + 2] & 0xC0) == 0xC0) {
+    if ((OC[Offset + 1] & 0x10) == 0)
+      return opcode_save_zreg(OC, Offset, Length, Prologue);
+    return opcode_save_preg(OC, Offset, Length, Prologue);
+  }
+
+  return opcode_save_any_reg(OC, Offset, Length, Prologue);
+}
+
 bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,
                                   unsigned Length, bool Prologue) {
   // Whether the instruction has writeback
@@ -948,6 +977,30 @@ bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,
   return false;
 }
 
+bool Decoder::opcode_save_zreg(const uint8_t *OC, unsigned &Offset,
+                               unsigned Length, bool Prologue) {
+  uint32_t Reg = (OC[Offset + 1] & 0x0F) + 8;
+  uint32_t Off = ((OC[Offset + 1] & 0x60) << 1) | (OC[Offset + 2] & 0x3F);
+  SW.startLine() << format(
+      "0x%02x%02x%02x            ; %s z%u, [sp, #%u, mul vl]\n", OC[Offset],
+      OC[Offset + 1], OC[Offset + 2],
+      static_cast<const char *>(Prologue ? "str" : "ldr"), Reg, Off);
+  Offset += 3;
+  return false;
+}
+
+bool Decoder::opcode_save_preg(const uint8_t *OC, unsigned &Offset,
+                               unsigned Length, bool Prologue) {
+  uint32_t Reg = (OC[Offset + 1] & 0x0F);
+  uint32_t Off = ((OC[Offset + 1] & 0x60) << 1) | (OC[Offset + 2] & 0x3F);
+  SW.startLine() << format(
+      "0x%02x%02x%02x            ; %s p%u, [sp, #%u, mul vl]\n", OC[Offset],
+      OC[Offset + 1], OC[Offset + 2],
+      static_cast<const char *>(Prologue ? "str" : "ldr"), Reg, Off);
+  Offset += 3;
+  return false;
+}
+
 bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,
                                 unsigned Length, bool Prologue) {
   SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);

diff  --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index fa5b31dd87b4b..b412c4a8ae231 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -107,6 +107,8 @@ class Decoder {
                         unsigned Length, bool Prologue);
   bool opcode_save_freg_x(const uint8_t *Opcodes, unsigned &Offset,
                           unsigned Length, bool Prologue);
+  bool opcode_alloc_z(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
+                      bool Prologue);
   bool opcode_alloc_l(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
                       bool Prologue);
   bool opcode_setfp(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
@@ -121,6 +123,12 @@ class Decoder {
                     bool Prologue);
   bool opcode_save_next(const uint8_t *Opcodes, unsigned &Offset,
                         unsigned Length, bool Prologue);
+  bool opcode_e7(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
+                 bool Prologue);
+  bool opcode_save_zreg(const uint8_t *Opcodes, unsigned &Offset,
+                        unsigned Length, bool Prologue);
+  bool opcode_save_preg(const uint8_t *Opcodes, unsigned &Offset,
+                        unsigned Length, bool Prologue);
   bool opcode_save_any_reg(const uint8_t *Opcodes, unsigned &Offset,
                            unsigned Length, bool Prologue);
   bool opcode_trap_frame(const uint8_t *Opcodes, unsigned &Offset,


        


More information about the llvm-commits mailing list