[llvm] af70618 - [SPARC][IAS] Add complete set of v9 ASI load, store & swap forms

Brad Smith via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 5 01:51:26 PDT 2023


Author: Koakuma
Date: 2023-09-05T04:37:19-04:00
New Revision: af70618e968f17e6c91c425db8bc52bdc81c3a45

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

LOG: [SPARC][IAS] Add complete set of v9 ASI load, store & swap forms

This extends support for ASI-tagged loads, stores, and swaps with the new
stored-ASI form ([reg+imm] %asi) introduced in v9.

CAS instructions are handled differently by the (dis-)assembler, so it will be
handled in a separate patch.

Reviewed By: barannikov88

Differential Revision: https://reviews.llvm.org/D157233

Added: 
    llvm/test/MC/Disassembler/Sparc/sparc-mem-v9.txt
    llvm/test/MC/Sparc/sparc-mem-asi-instructions.s

Modified: 
    llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
    llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
    llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
    llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
    llvm/lib/Target/Sparc/SparcInstr64Bit.td
    llvm/lib/Target/Sparc/SparcInstrInfo.td
    llvm/test/MC/Sparc/sparc-atomic-instructions.s
    llvm/test/MC/Sparc/sparc-mem-instructions.s
    llvm/test/MC/Sparc/sparcv9-atomic-instructions.s
    llvm/test/MC/Sparc/sparcv9-instructions.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 4d64c394f2c6471..69476129abbff5e 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -12,6 +12,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCAsmMacro.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -88,6 +89,8 @@ class SparcAsmParser : public MCTargetAsmParser {
 
   OperandMatchResultTy parseMembarTag(OperandVector &Operands);
 
+  OperandMatchResultTy parseASITag(OperandVector &Operands);
+
   template <TailRelocKind Kind>
   OperandMatchResultTy parseTailRelocSym(OperandVector &Operands);
 
@@ -238,7 +241,8 @@ class SparcOperand : public MCParsedAsmOperand {
     k_Register,
     k_Immediate,
     k_MemoryReg,
-    k_MemoryImm
+    k_MemoryImm,
+    k_ASITag
   } Kind;
 
   SMLoc StartLoc, EndLoc;
@@ -268,6 +272,7 @@ class SparcOperand : public MCParsedAsmOperand {
     struct RegOp Reg;
     struct ImmOp Imm;
     struct MemOp Mem;
+    unsigned ASI;
   };
 
 public:
@@ -280,6 +285,7 @@ class SparcOperand : public MCParsedAsmOperand {
   bool isMEMrr() const { return Kind == k_MemoryReg; }
   bool isMEMri() const { return Kind == k_MemoryImm; }
   bool isMembarTag() const { return Kind == k_Immediate; }
+  bool isASITag() const { return Kind == k_ASITag; }
   bool isTailRelocSym() const { return Kind == k_Immediate; }
 
   bool isCallTarget() const {
@@ -359,6 +365,11 @@ class SparcOperand : public MCParsedAsmOperand {
     return Mem.Off;
   }
 
+  unsigned getASITag() const {
+    assert((Kind == k_ASITag) && "Invalid access!");
+    return ASI;
+  }
+
   /// getStartLoc - Get the location of the first token of this operand.
   SMLoc getStartLoc() const override {
     return StartLoc;
@@ -379,6 +390,9 @@ class SparcOperand : public MCParsedAsmOperand {
       OS << "Mem: " << getMemBase()
          << "+" << *getMemOff()
          << "\n"; break;
+    case k_ASITag:
+      OS << "ASI tag: " << getASITag() << "\n";
+      break;
     }
   }
 
@@ -430,6 +444,11 @@ class SparcOperand : public MCParsedAsmOperand {
     addExpr(Inst, Expr);
   }
 
+  void addASITagOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createImm(getASITag()));
+  }
+
   void addMembarTagOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     const MCExpr *Expr = getImm();
@@ -474,6 +493,15 @@ class SparcOperand : public MCParsedAsmOperand {
     return Op;
   }
 
+  static std::unique_ptr<SparcOperand> CreateASITag(unsigned Val, SMLoc S,
+                                                    SMLoc E) {
+    auto Op = std::make_unique<SparcOperand>(k_ASITag);
+    Op->ASI = Val;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
   static bool MorphToIntPairReg(SparcOperand &Op) {
     unsigned Reg = Op.getReg();
     assert(Op.Reg.Kind == rk_IntReg);
@@ -1080,6 +1108,29 @@ OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) {
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy SparcAsmParser::parseASITag(OperandVector &Operands) {
+  SMLoc S = Parser.getTok().getLoc();
+  SMLoc E = Parser.getTok().getEndLoc();
+  int64_t ASIVal = 0;
+
+  if (getParser().parseAbsoluteExpression(ASIVal)) {
+    Error(
+        S,
+        is64Bit()
+            ? "malformed ASI tag, must be %asi or a constant integer expression"
+            : "malformed ASI tag, must be a constant integer expression");
+    return MatchOperand_ParseFail;
+  }
+
+  if (!isUInt<8>(ASIVal)) {
+    Error(S, "invalid ASI number, must be between 0 and 255");
+    return MatchOperand_ParseFail;
+  }
+
+  Operands.push_back(SparcOperand::CreateASITag(ASIVal, S, E));
+  return MatchOperand_Success;
+}
+
 OperandMatchResultTy SparcAsmParser::parseCallTarget(OperandVector &Operands) {
   SMLoc S = Parser.getTok().getLoc();
   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
@@ -1154,13 +1205,49 @@ SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
     Parser.Lex(); // Eat the ]
 
     // Parse an optional address-space identifier after the address.
-    if (getLexer().is(AsmToken::Integer)) {
-      std::unique_ptr<SparcOperand> Op;
-      ResTy = parseSparcAsmOperand(Op, false);
-      if (ResTy != MatchOperand_Success || !Op)
-        return MatchOperand_ParseFail;
-      Operands.push_back(std::move(Op));
+    // This will be either an immediate constant expression, or, on 64-bit
+    // processors, the %asi register.
+    if (is64Bit() && getLexer().is(AsmToken::Percent)) {
+      SMLoc S = Parser.getTok().getLoc();
+      Parser.Lex(); // Eat the %.
+      const AsmToken Tok = Parser.getTok();
+      if (Tok.is(AsmToken::Identifier) && Tok.getString() == "asi") {
+        // Here we patch the MEM operand from [base + %g0] into [base + 0]
+        // as memory operations with ASI tag stored in %asi register needs
+        // to use immediate offset. We need to do this because Reg addressing
+        // will be parsed as Reg+G0 initially.
+        // This allows forms such as `ldxa [%o0] %asi, %o0` to parse correctly.
+        SparcOperand &OldMemOp = (SparcOperand &)*Operands[Operands.size() - 2];
+        if (OldMemOp.isMEMrr()) {
+          if (OldMemOp.getMemOffsetReg() != Sparc::G0) {
+            Error(S, "invalid operand for instruction");
+            return MatchOperand_ParseFail;
+          }
+          Operands[Operands.size() - 2] = SparcOperand::MorphToMEMri(
+              OldMemOp.getMemBase(),
+              SparcOperand::CreateImm(MCConstantExpr::create(0, getContext()),
+                                      OldMemOp.getStartLoc(),
+                                      OldMemOp.getEndLoc()));
+        }
+        Parser.Lex(); // Eat the identifier.
+        // In this context, we convert the register operand into
+        // a plain "%asi" token since the register access is already
+        // implicit in the instruction definition and encoding.
+        // See LoadASI/StoreASI in SparcInstrInfo.td.
+        Operands.push_back(SparcOperand::CreateToken("%asi", S));
+        return MatchOperand_Success;
+      }
+
+      Error(S,
+            "malformed ASI tag, must be %asi or a constant integer expression");
+      return MatchOperand_ParseFail;
     }
+
+    // If we're not at the end of statement and the next token is not a comma,
+    // then it is an immediate ASI value.
+    if (getLexer().isNot(AsmToken::EndOfStatement) &&
+        getLexer().isNot(AsmToken::Comma))
+      return parseASITag(Operands);
     return MatchOperand_Success;
   }
 

diff  --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
index ace59ee4d743c94..f1f7a171c9eaf7d 100644
--- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -306,8 +306,10 @@ DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
   {
     Result = decodeInstruction(DecoderTableSparcV832, Instr, Insn, Address, this, STI);
   }
-  if (Result != MCDisassembler::Fail)
+  if (Result != MCDisassembler::Fail) {
+    Size = 4;
     return Result;
+  }
 
   Result =
       decodeInstruction(DecoderTableSparc32, Instr, Insn, Address, this, STI);

diff  --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index 929c755e4821f69..c3150f4a72d04b0 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -251,3 +251,9 @@ void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum,
     }
   }
 }
+
+void SparcInstPrinter::printASITag(const MCInst *MI, int opNum,
+                                   const MCSubtargetInfo &STI, raw_ostream &O) {
+  unsigned Imm = MI->getOperand(opNum).getImm();
+  O << Imm;
+}

diff  --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
index cccdeadd816c7b5..5cc79a21943f467 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h
@@ -54,6 +54,8 @@ class SparcInstPrinter : public MCInstPrinter {
                    raw_ostream &OS);
   void printMembarTag(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
                       raw_ostream &O);
+  void printASITag(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
+                   raw_ostream &O);
 };
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index 078c08d8d4945f7..4b8793d1e7132f9 100644
--- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -239,7 +239,7 @@ def UDIVXri : F3_2<2, 0b001101,
 let Predicates = [Is64Bit] in {
 
 // 64-bit loads.
-defm LDX   : Load<"ldx", 0b001011, load, I64Regs, i64>;
+defm LDX   : LoadA<"ldx", 0b001011, 0b011011, load, I64Regs, i64>;
 
 let mayLoad = 1, isAsmParserOnly = 1 in {
   def TLS_LDXrr : F3_1<3, 0b001011,
@@ -282,10 +282,10 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)),  (LDrr ADDRrr:$addr)>;
 def : Pat<(i64 (extloadi32 ADDRri:$addr)),  (LDri ADDRri:$addr)>;
 
 // Sign-extending load of i32 into i64 is a new SPARC v9 instruction.
-defm LDSW   : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>;
+defm LDSW   : LoadA<"ldsw", 0b001000, 0b011000, sextloadi32, I64Regs, i64>;
 
 // 64-bit stores.
-defm STX    : Store<"stx", 0b001110, store,  I64Regs, i64>;
+defm STX    : StoreA<"stx", 0b001110, 0b011110, store, I64Regs, i64>;
 
 // Truncating stores from i64 are identical to the i32 stores.
 def : Pat<(truncstorei8  i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;

diff  --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index c85c891d41a9047..6940a2a0266450d 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -183,6 +183,16 @@ def MembarTag : Operand<i32> {
   let ParserMatchClass = SparcMembarTagAsmOperand;
 }
 
+def SparcASITagAsmOperand : AsmOperandClass {
+  let Name = "ASITag";
+  let ParserMethod = "parseASITag";
+}
+
+def ASITag : Operand<i32> {
+  let PrintMethod = "printASITag";
+  let ParserMatchClass = SparcASITagAsmOperand;
+}
+
 // Branch targets have OtherVT type.
 def brtarget : Operand<OtherVT> {
   let EncoderMethod = "getBranchTargetOpValue";
@@ -421,19 +431,26 @@ multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
 
 // TODO: Instructions of the LoadASI class are currently asm only; hooking up
 // CodeGen's address spaces to use these is a future task.
-class LoadASI<string OpcStr, bits<6> Op3Val, RegisterClass RC> :
-  F3_1_asi<3, Op3Val, (outs RC:$rd), (ins (MEMrr $rs1, $rs2):$addr, i8imm:$asi),
-                !strconcat(OpcStr, "a [$addr] $asi, $rd"),
-                []>;
+multiclass LoadASI<string OpcStr, bits<6> Op3Val, RegisterClass RC> {
+  def rr  : F3_1_asi<3, Op3Val, (outs RC:$rd), (ins (MEMrr $rs1, $rs2):$addr, ASITag:$asi),
+                     !strconcat(OpcStr, "a [$addr] $asi, $rd"),
+                     []>;
+
+  let Predicates = [HasV9], Uses = [ASR3] in
+  def ri  : F3_2<3, Op3Val, (outs RC:$rd), (ins (MEMri $rs1, $simm13):$addr),
+                 !strconcat(OpcStr, "a [$addr] %asi, $rd"),
+                 []>;
+}
 
 // LoadA multiclass - As above, but also define alternate address space variant
 multiclass LoadA<string OpcStr, bits<6> Op3Val, bits<6> LoadAOp3Val,
                  SDPatternOperator OpNode, RegisterClass RC, ValueType Ty,
                  InstrItinClass itin = NoItinerary> :
              Load<OpcStr, Op3Val, OpNode, RC, Ty, itin> {
-  def Arr  : LoadASI<OpcStr, LoadAOp3Val, RC>;
+  defm A   : LoadASI<OpcStr, LoadAOp3Val, RC>;
 }
 
+
 // The LDSTUB instruction is supported for asm only.
 // It is unlikely that general-purpose code could make use of it.
 // CAS is preferred for sparc v9.
@@ -442,8 +459,12 @@ def LDSTUBrr : F3_1<3, 0b001101, (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$ad
 def LDSTUBri : F3_2<3, 0b001101, (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr),
                     "ldstub [$addr], $rd", []>;
 def LDSTUBArr : F3_1_asi<3, 0b011101, (outs IntRegs:$rd),
-                         (ins (MEMrr $rs1, $rs2):$addr, i8imm:$asi),
+                         (ins (MEMrr $rs1, $rs2):$addr, ASITag:$asi),
                          "ldstuba [$addr] $asi, $rd", []>;
+let Predicates = [HasV9], Uses = [ASR3] in
+def LDSTUBAri : F3_2<3, 0b011101, (outs IntRegs:$rd),
+                         (ins (MEMri $rs1, $simm13):$addr),
+                         "ldstuba [$addr] %asi, $rd", []>;
 
 // Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.
 multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
@@ -462,17 +483,24 @@ multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
 
 // TODO: Instructions of the StoreASI class are currently asm only; hooking up
 // CodeGen's address spaces to use these is a future task.
-class StoreASI<string OpcStr, bits<6> Op3Val, RegisterClass RC,
-               InstrItinClass itin = IIC_st> :
-  F3_1_asi<3, Op3Val, (outs), (ins (MEMrr $rs1, $rs2):$addr, RC:$rd, i8imm:$asi),
+multiclass StoreASI<string OpcStr, bits<6> Op3Val, RegisterClass RC,
+               InstrItinClass itin = IIC_st> {
+  def rr : F3_1_asi<3, Op3Val, (outs), (ins (MEMrr $rs1, $rs2):$addr, RC:$rd, ASITag:$asi),
            !strconcat(OpcStr, "a $rd, [$addr] $asi"),
            [],
            itin>;
 
+  let Predicates = [HasV9], Uses = [ASR3] in
+  def ri : F3_2<3, Op3Val, (outs), (ins (MEMri $rs1, $simm13):$addr, RC:$rd),
+           !strconcat(OpcStr, "a $rd, [$addr] %asi"),
+           [],
+           itin>;
+}
+
 multiclass StoreA<string OpcStr, bits<6> Op3Val, bits<6> StoreAOp3Val,
                   SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> :
              Store<OpcStr, Op3Val, OpNode, RC, Ty> {
-  def Arr : StoreASI<OpcStr, StoreAOp3Val, RC>;
+  defm A   : StoreASI<OpcStr, StoreAOp3Val, RC>;
 }
 
 //===----------------------------------------------------------------------===//
@@ -587,18 +615,21 @@ defm LD   : LoadA<"ld",   0b000000, 0b010000, load,        IntRegs, i32>;
 defm LDD : LoadA<"ldd", 0b000011, 0b010011, load, IntPair, v2i32, IIC_ldd>;
 
 // Section B.2 - Load Floating-point Instructions, p. 92
-defm LDF   : Load<"ld",  0b100000, load,    FPRegs,  f32, IIC_iu_or_fpu_instr>;
-def LDFArr : LoadASI<"ld",  0b110000, FPRegs>,
-             Requires<[HasV9]>;
+defm LDF     : Load<"ld",  0b100000, load,    FPRegs,  f32, IIC_iu_or_fpu_instr>;
+defm LDDF    : Load<"ldd", 0b100011, load,    DFPRegs, f64, IIC_ldd>;
 
-defm LDDF   : Load<"ldd", 0b100011, load,    DFPRegs, f64, IIC_ldd>;
-def LDDFArr : LoadASI<"ldd", 0b110011, DFPRegs>,
-              Requires<[HasV9]>;
-defm LDQF  : LoadA<"ldq", 0b100010, 0b110010, load, QFPRegs, f128>,
-             Requires<[HasV9, HasHardQuad]>;
+let DecoderNamespace = "SparcV9", Predicates = [HasV9] in {
+  defm LDFA    : LoadASI<"ld",  0b110000, FPRegs>;
+  defm LDDFA   : LoadASI<"ldd", 0b110011, DFPRegs>;
+  defm LDQF    : LoadA<"ldq", 0b100010, 0b110010, load, QFPRegs, f128>,
+                 Requires<[HasHardQuad]>;
+}
 
-defm LDC   : Load<"ld", 0b110000, load, CoprocRegs, i32>;
-defm LDDC   : Load<"ldd", 0b110011, load, CoprocPair, v2i32, IIC_ldd>;
+// Coprocessor instructions were removed in v9.
+let DecoderNamespace = "SparcV8", Predicates = [HasNoV9] in {
+  defm LDC    : Load<"ld", 0b110000, load, CoprocRegs, i32>;
+  defm LDDC   : Load<"ldd", 0b110011, load, CoprocPair, v2i32, IIC_ldd>;
+}
 
 let Defs = [CPSR] in {
   let rd = 0 in {
@@ -641,16 +672,20 @@ defm STD   : StoreA<"std", 0b000111, 0b010111, store, IntPair, v2i32>;
 
 // Section B.5 - Store Floating-point Instructions, p. 97
 defm STF    : Store<"st",  0b100100, store,         FPRegs,  f32>;
-def STFArr  : StoreASI<"st",  0b110100, FPRegs>,
-              Requires<[HasV9]>;
 defm STDF   : Store<"std", 0b100111, store,         DFPRegs, f64, IIC_std>;
-def STDFArr : StoreASI<"std", 0b110111, DFPRegs>,
-              Requires<[HasV9]>;
-defm STQF   : StoreA<"stq", 0b100110, 0b110110, store, QFPRegs, f128>,
-              Requires<[HasV9, HasHardQuad]>;
 
-defm STC   : Store<"st", 0b110100, store, CoprocRegs, i32>;
-defm STDC   : Store<"std", 0b110111, store, CoprocPair, v2i32, IIC_std>;
+let DecoderNamespace = "SparcV9", Predicates = [HasV9] in {
+  defm STFA  : StoreASI<"st",  0b110100, FPRegs>;
+  defm STDFA : StoreASI<"std", 0b110111, DFPRegs>;
+  defm STQF  : StoreA<"stq", 0b100110, 0b110110, store, QFPRegs, f128>,
+              Requires<[HasHardQuad]>;
+}
+
+// Coprocessor instructions were removed in v9.
+let DecoderNamespace = "SparcV8", Predicates = [HasNoV9] in {
+  defm STC   : Store<"st", 0b110100, store, CoprocRegs, i32>;
+  defm STDC   : Store<"std", 0b110111, store, CoprocPair, v2i32, IIC_std>;
+}
 
 let rd = 0 in {
   let Defs = [CPSR] in {
@@ -700,9 +735,14 @@ let Constraints = "$val = $rd" in {
                  "swap [$addr], $rd",
                  [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
   def SWAPArr : F3_1_asi<3, 0b011111,
-                 (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr, i8imm:$asi, IntRegs:$val),
+                 (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr, ASITag:$asi, IntRegs:$val),
                  "swapa [$addr] $asi, $rd",
                  [/*FIXME: pattern?*/]>;
+let Predicates = [HasV9], Uses = [ASR3] in
+  def SWAPAri : F3_2<3, 0b011111,
+                 (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr, IntRegs:$val),
+                 "swapa [$addr] %asi, $rd",
+                 [/*FIXME: pattern?*/]>;
 }
 
 
@@ -1687,7 +1727,7 @@ let Predicates = [HasLeonCASA], Constraints = "$swap = $rd", asi = 0b00001010 in
 let Predicates = [HasLeonCASA], Constraints = "$swap = $rd" in
   def CASArr: F3_1_asi<3, 0b111100,
                 (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
-                                     IntRegs:$swap, i8imm:$asi),
+                                     IntRegs:$swap, ASITag:$asi),
                  "casa [$rs1] $asi, $rs2, $rd", []>;
 
 // TODO: Add DAG sequence to lower these instructions. Currently, only provided

diff  --git a/llvm/test/MC/Disassembler/Sparc/sparc-mem-v9.txt b/llvm/test/MC/Disassembler/Sparc/sparc-mem-v9.txt
new file mode 100644
index 000000000000000..f7f5907af909269
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Sparc/sparc-mem-v9.txt
@@ -0,0 +1,31 @@
+# RUN: llvm-mc --disassemble %s -triple=sparcv9-unknown-linux | FileCheck %s
+
+# CHECK:     lduba [%i0+8] %asi, %o2
+0xd4,0x8e,0x20,0x08
+
+# CHECK:     lduha [%i0+8] %asi, %o2
+0xd4,0x96,0x20,0x08
+
+# CHECK:     lda [%i0+8] %asi, %o2
+0xd4,0x86,0x20,0x08
+
+# CHECK:     ldxa [%i0+8] %asi, %o2
+0xd4,0xde,0x20,0x08
+
+# CHECK:     ldstuba [%i0+8] %asi, %o2
+0xd4,0xee,0x20,0x08
+
+# CHECK:     swapa [%i0+8] %asi, %o2
+0xd4,0xfe,0x20,0x08
+
+# CHECK:     stba %o2, [%i0+8] %asi
+0xd4,0xae,0x20,0x08
+
+# CHECK:     stha %o2, [%i0+8] %asi
+0xd4,0xb6,0x20,0x08
+
+# CHECK:     sta %o2, [%i0+8] %asi
+0xd4,0xa6,0x20,0x08
+
+# CHECK:     stxa %o2, [%i0+8] %asi
+0xd4,0xf6,0x20,0x08

diff  --git a/llvm/test/MC/Sparc/sparc-atomic-instructions.s b/llvm/test/MC/Sparc/sparc-atomic-instructions.s
index 4ce19d5cdda02bd..ce92bf82d3ec603 100644
--- a/llvm/test/MC/Sparc/sparc-atomic-instructions.s
+++ b/llvm/test/MC/Sparc/sparc-atomic-instructions.s
@@ -13,6 +13,9 @@
         ! CHECK: swapa [%i0+%l6] 131, %o2   ! encoding: [0xd4,0xfe,0x10,0x76]
         swapa [%i0+%l6] 131, %o2
 
+        ! CHECK: swapa [%i0+%l6] 131, %o2   ! encoding: [0xd4,0xfe,0x10,0x76]
+        swapa [%i0+%l6] (130+1), %o2
+
         ! CHECK: ldstub [%i0+40], %g1 ! encoding: [0xc2,0x6e,0x20,0x28]
         ldstub [%i0+40], %g1
 
@@ -21,3 +24,6 @@
 
         ! CHECK: ldstuba [%i0+%i2] 131, %g1 ! encoding: [0xc2,0xee,0x10,0x7a]
         ldstuba [%i0+%i2] 131, %g1
+
+        ! CHECK: ldstuba [%i0+%i2] 131, %g1 ! encoding: [0xc2,0xee,0x10,0x7a]
+        ldstuba [%i0+%i2] (130+1), %g1

diff  --git a/llvm/test/MC/Sparc/sparc-mem-asi-instructions.s b/llvm/test/MC/Sparc/sparc-mem-asi-instructions.s
new file mode 100644
index 000000000000000..6bad7c4b7e7277b
--- /dev/null
+++ b/llvm/test/MC/Sparc/sparc-mem-asi-instructions.s
@@ -0,0 +1,49 @@
+! RUN: not llvm-mc %s -arch=sparc   -show-encoding 2>&1 | FileCheck %s --check-prefix=V8
+! RUN: not llvm-mc %s -arch=sparcv9 -show-encoding 2>&1 | FileCheck %s --check-prefix=V9
+
+! V8: error: malformed ASI tag, must be a constant integer expression
+! V8-NEXT: lduba [%i0] asi, %o2
+! V9: error: malformed ASI tag, must be %asi or a constant integer expression
+! V9-NEXT: lduba [%i0] asi, %o2
+lduba [%i0] asi, %o2
+
+! V8: error: malformed ASI tag, must be a constant integer expression
+! V8-NEXT: lduba [%i0] %g0, %o2
+! V9: error: malformed ASI tag, must be %asi or a constant integer expression
+! V9-NEXT: lduba [%i0] %g0, %o2
+lduba [%i0] %g0, %o2
+
+! V8: error: malformed ASI tag, must be a constant integer expression
+! V8-NEXT: lduba [%i0] %0, %o2
+! V9: error: malformed ASI tag, must be %asi or a constant integer expression
+! V9-NEXT: lduba [%i0] %0, %o2
+lduba [%i0] %0, %o2
+
+! V8: error: invalid ASI number, must be between 0 and 255
+! V8-NEXT: lduba [%i0] -1, %o2
+! V9: error: invalid ASI number, must be between 0 and 255
+! V9-NEXT: lduba [%i0] -1, %o2
+lduba [%i0] -1, %o2
+
+! V8: error: invalid ASI number, must be between 0 and 255
+! V8-NEXT: lduba [%i0] 256, %o2
+! V9: error: invalid ASI number, must be between 0 and 255
+! V9-NEXT: lduba [%i0] 256, %o2
+lduba [%i0] 256, %o2
+
+!! %asi register is only introduced in V9
+! V8: error: malformed ASI tag, must be a constant integer expression
+! V8-NEXT: lduba [%i0] %asi, %o2
+lduba [%i0] %asi, %o2
+
+!! [Reg+Imm] can't be used with immediate ASI forms.
+! V8: error: invalid operand for instruction
+! V8-NEXT: lduba [%i0+1] 255, %o2
+! V9: error: invalid operand for instruction
+! V9-NEXT: lduba [%i0+1] 255, %o2
+lduba [%i0+1] 255, %o2
+
+!! [Reg+Reg] can't be used with stored tag in %asi.
+! V9: error: invalid operand for instruction
+! V9-NEXT: lduba [%i0+%i1] %asi, %o2
+lduba [%i0+%i1] %asi, %o2

diff  --git a/llvm/test/MC/Sparc/sparc-mem-instructions.s b/llvm/test/MC/Sparc/sparc-mem-instructions.s
index 85ff8ce657ee926..cf88fcb5ba145fd 100644
--- a/llvm/test/MC/Sparc/sparc-mem-instructions.s
+++ b/llvm/test/MC/Sparc/sparc-mem-instructions.s
@@ -9,6 +9,8 @@
         ldsb [%g1], %o4
         ! CHECK: ldsba [%i0+%l6] 131, %o2  ! encoding: [0xd4,0xce,0x10,0x76]
         ldsba [%i0 + %l6] 131, %o2
+        ! CHECK: ldsba [%i0+%l6] 131, %o2  ! encoding: [0xd4,0xce,0x10,0x76]
+        ldsba [%i0 + %l6] (130+1), %o2
 
         ! CHECK: ldsh [%i0+%l6], %o2  ! encoding: [0xd4,0x56,0x00,0x16]
         ldsh [%i0 + %l6], %o2
@@ -18,6 +20,8 @@
         ldsh [%g1], %o4
         ! CHECK: ldsha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xd6,0x10,0x76]
         ldsha [%i0 + %l6] 131, %o2
+        ! CHECK: ldsha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xd6,0x10,0x76]
+        ldsha [%i0 + %l6] (130+1), %o2
 
         ! CHECK: ldub [%i0+%l6], %o2  ! encoding: [0xd4,0x0e,0x00,0x16]
         ldub [%i0 + %l6], %o2
@@ -27,6 +31,8 @@
         ldub [%g1], %o2
         ! CHECK: lduba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x8e,0x10,0x76]
         lduba [%i0 + %l6] 131, %o2
+        ! CHECK: lduba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x8e,0x10,0x76]
+        lduba [%i0 + %l6] (130+1), %o2
 
         ! CHECK: lduh [%i0+%l6], %o2  ! encoding: [0xd4,0x16,0x00,0x16]
         lduh [%i0 + %l6], %o2
@@ -36,6 +42,8 @@
         lduh [%g1], %o2
         ! CHECK: lduha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x96,0x10,0x76]
         lduha [%i0 + %l6] 131, %o2
+        ! CHECK: lduha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x96,0x10,0x76]
+        lduha [%i0 + %l6] (130+1), %o2
 
         ! CHECK: ld [%i0+%l6], %o2    ! encoding: [0xd4,0x06,0x00,0x16]
         ld [%i0 + %l6], %o2
@@ -45,6 +53,8 @@
         ld [%g1], %o2
         ! CHECK: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
         lda [%i0 + %l6] 131, %o2
+        ! CHECK: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
+        lda [%i0 + %l6] (130+1), %o2
 
         ! CHECK: ldd [%i0+%l6], %o2    ! encoding: [0xd4,0x1e,0x00,0x16]
         ldd [%i0 + %l6], %o2
@@ -54,6 +64,8 @@
         ldd [%g1], %o2
         ! CHECK: ldda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x9e,0x10,0x76]
         ldda [%i0 + %l6] 131, %o2
+        ! CHECK: ldda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x9e,0x10,0x76]
+        ldda [%i0 + %l6] (130+1), %o2
 
         ! CHECK: stb %o2, [%i0+%l6]   ! encoding: [0xd4,0x2e,0x00,0x16]
         stb %o2, [%i0 + %l6]
@@ -68,9 +80,15 @@
         ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
         stba %o2, [%i0 + %l6] 131
         ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
+        stba %o2, [%i0 + %l6] (130+1)
+        ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
         stuba %o2, [%i0 + %l6] 131
         ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
+        stuba %o2, [%i0 + %l6] (130+1)
+        ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
         stsba %o2, [%i0 + %l6] 131
+        ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
+        stsba %o2, [%i0 + %l6] (130+1)
 
         ! CHECK: sth %o2, [%i0+%l6]   ! encoding: [0xd4,0x36,0x00,0x16]
         sth %o2, [%i0 + %l6]
@@ -85,9 +103,15 @@
         ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
         stha %o2, [%i0 + %l6] 131
         ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
+        stha %o2, [%i0 + %l6] (130+1)
+        ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
         stuha %o2, [%i0 + %l6] 131
         ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
+        stuha %o2, [%i0 + %l6] (130+1)
+        ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
         stsha %o2, [%i0 + %l6] 131
+        ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
+        stsha %o2, [%i0 + %l6] (130+1)
 
         ! CHECK: st %o2, [%i0+%l6]    ! encoding: [0xd4,0x26,0x00,0x16]
         st %o2, [%i0 + %l6]
@@ -97,6 +121,8 @@
         st %o2, [%g1]
         ! CHECK: sta %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xa6,0x10,0x76]
         sta %o2, [%i0 + %l6] 131
+        ! CHECK: sta %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xa6,0x10,0x76]
+        sta %o2, [%i0 + %l6] (130+1)
 
         ! CHECK: std %o2, [%i0+%l6]    ! encoding: [0xd4,0x3e,0x00,0x16]
         std %o2, [%i0 + %l6]
@@ -106,6 +132,8 @@
         std %o2, [%g1]
         ! CHECK: stda %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xbe,0x10,0x76]
         stda %o2, [%i0 + %l6] 131
+        ! CHECK: stda %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xbe,0x10,0x76]
+        stda %o2, [%i0 + %l6] (130+1)
 
         ! CHECK:  flush %g1+%g2         ! encoding: [0x81,0xd8,0x40,0x02]
         flush %g1 + %g2

diff  --git a/llvm/test/MC/Sparc/sparcv9-atomic-instructions.s b/llvm/test/MC/Sparc/sparcv9-atomic-instructions.s
index 449450f70f62b97..14f685c5f0a1108 100644
--- a/llvm/test/MC/Sparc/sparcv9-atomic-instructions.s
+++ b/llvm/test/MC/Sparc/sparcv9-atomic-instructions.s
@@ -12,6 +12,12 @@
         ! CHECK: membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore | #Lookaside | #MemIssue | #Sync  ! encoding: [0x81,0x43,0xe0,0x7f]
         membar #LoadLoad | #StoreLoad | #LoadStore | #StoreStore | #Lookaside | #MemIssue | #Sync
 
+        ! CHECK: swapa [%i0+6] %asi, %o2   ! encoding: [0xd4,0xfe,0x20,0x06]
+        swapa [%i0+6] %asi, %o2
+
+        ! CHECK: ldstuba [%i0+2] %asi, %g1 ! encoding: [0xc2,0xee,0x20,0x02]
+        ldstuba [%i0+2] %asi, %g1
+
         ! CHECK: cas [%i0], %l6, %o2   ! encoding: [0xd5,0xe6,0x10,0x16]
         cas [%i0], %l6, %o2
 

diff  --git a/llvm/test/MC/Sparc/sparcv9-instructions.s b/llvm/test/MC/Sparc/sparcv9-instructions.s
index 2a90d4dc0387d42..f5d1231ccee2126 100644
--- a/llvm/test/MC/Sparc/sparcv9-instructions.s
+++ b/llvm/test/MC/Sparc/sparcv9-instructions.s
@@ -52,43 +52,83 @@
         ! V8-NEXT: lduwa [%i0 + %l6] 131, %o2
         ! V9: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
         lduwa [%i0 + %l6] 131, %o2
+        ! V8:      error: invalid instruction mnemonic
+        ! V8-NEXT: lduwa [%i0 + %l6] (130+1), %o2
+        ! V9: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
+        lduwa [%i0 + %l6] (130+1), %o2
+
+        ! V9: ldsw [%i0+%l6], %o2    ! encoding: [0xd4,0x46,0x00,0x16]
+        ldsw [%i0 + %l6], %o2
+        ! V9: ldsw [%i0+32], %o2     ! encoding: [0xd4,0x46,0x20,0x20]
+        ldsw [%i0 + 32], %o2
+        ! V9: ldsw [%g1], %o2        ! encoding: [0xd4,0x40,0x40,0x00]
+        ldsw [%g1], %o2
+        ! V9: ldswa [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xc6,0x10,0x76]
+        ldswa [%i0 + %l6] 131, %o2
+        ! V9: ldswa [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xc6,0x10,0x76]
+        ldswa [%i0 + %l6] (130+1), %o2
 
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: lda [%l0] 0xf0, %f29
         ! V9: lda [%l0] 240, %f29             ! encoding: [0xfb,0x84,0x1e,0x00]
         lda [%l0] 0xf0, %f29
+        ! V8:      error: instruction requires a CPU feature not currently enabled
+        ! V8-NEXT: lda [%l0] (0xef+0x01), %f29
+        ! V9: lda [%l0] 240, %f29             ! encoding: [0xfb,0x84,0x1e,0x00]
+        lda [%l0] (0xef+0x01), %f29
 
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: ldda [%l0] 0xf0, %f48
         ! V9: ldda [%l0] 240, %f48            ! encoding: [0xe3,0x9c,0x1e,0x00]
         ldda [%l0] 0xf0, %f48
+        ! V8:      error: instruction requires a CPU feature not currently enabled
+        ! V8-NEXT: ldda [%l0] (0xef+0x01), %f48
+        ! V9: ldda [%l0] 240, %f48            ! encoding: [0xe3,0x9c,0x1e,0x00]
+        ldda [%l0] (0xef+0x01), %f48
 
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: ldqa [%l0] 0xf0, %f48
+        ! V9: ldqa [%l0] 240, %f48            ! encoding: [0xe3,0x94,0x1e,0x00]
+        ldqa [%l0] 0xf0, %f48
         ! V8:      error: instruction requires a CPU feature not currently enabled
-        ! V8-NEXT: ldq [%l0], %f48
+        ! V8-NEXT: ldqa [%l0] (0xef+0x01), %f48
         ! V9: ldqa [%l0] 240, %f48            ! encoding: [0xe3,0x94,0x1e,0x00]
+        ldqa [%l0] (0xef+0x01), %f48
+        ! V8:      error: instruction requires a CPU feature not currently enabled
+        ! V8-NEXT: ldq [%l0], %f48
         ! V9: ldq [%l0], %f48                 ! encoding: [0xe3,0x14,0x00,0x00]
-        ldqa [%l0] 0xf0, %f48
         ldq [%l0], %f48
 
+
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: sta %f29, [%l0] 0xf0
         ! V9: sta %f29, [%l0] 240             ! encoding: [0xfb,0xa4,0x1e,0x00]
         sta %f29, [%l0] 0xf0
+        ! V8:      error: instruction requires a CPU feature not currently enabled
+        ! V8-NEXT: sta %f29, [%l0] (0xef+0x01)
+        ! V9: sta %f29, [%l0] 240             ! encoding: [0xfb,0xa4,0x1e,0x00]
+        sta %f29, [%l0] (0xef+0x01)
 
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: stda %f48, [%l0] 0xf0
         ! V9: stda %f48, [%l0] 240            ! encoding: [0xe3,0xbc,0x1e,0x00]
         stda %f48, [%l0] 0xf0
+        ! V8:      error: instruction requires a CPU feature not currently enabled
+        ! V8-NEXT: stda %f48, [%l0] (0xef+0x01)
+        ! V9: stda %f48, [%l0] 240            ! encoding: [0xe3,0xbc,0x1e,0x00]
+        stda %f48, [%l0] (0xef+0x01)
 
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: stqa %f48, [%l0] 0xf0
+        ! V9: stqa %f48, [%l0] 240            ! encoding: [0xe3,0xb4,0x1e,0x00]
+        stqa %f48, [%l0] 0xf0
         ! V8:      error: instruction requires a CPU feature not currently enabled
-        ! V8-NEXT: stq %f48, [%l0]
+        ! V8-NEXT: stqa %f48, [%l0] (0xef+0x01)
         ! V9: stqa %f48, [%l0] 240            ! encoding: [0xe3,0xb4,0x1e,0x00]
+        stqa %f48, [%l0] (0xef+0x01)
+        ! V8:      error: instruction requires a CPU feature not currently enabled
+        ! V8-NEXT: stq %f48, [%l0]
         ! V9: stq %f48, [%l0]                 ! encoding: [0xe3,0x34,0x00,0x00]
-        stqa %f48, [%l0] 0xf0
         stq %f48, [%l0]
 
         ! V8:      error: instruction requires a CPU feature not currently enabled
@@ -101,6 +141,11 @@
         ! V9: ldx [%g2+%i5], %fsr   ! encoding: [0xc3,0x08,0x80,0x1d]
         ldx [%g2 + %i5],%fsr
 
+        ! V9: ldxa [%g2+%i5] 131, %g0   ! encoding: [0xc0,0xd8,0x90,0x7d]
+        ldxa [%g2 + %i5] 131, %g0
+        ! V9: ldxa [%g2+%i5] 131, %g0   ! encoding: [0xc0,0xd8,0x90,0x7d]
+        ldxa [%g2 + %i5] (130+1), %g0
+
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: stx %fsr,[%g2 + 20]
         ! V9: stx %fsr, [%g2+20]    ! encoding: [0xc3,0x28,0xa0,0x14]
@@ -111,6 +156,11 @@
         ! V9: stx %fsr, [%g2+%i5]   ! encoding: [0xc3,0x28,0x80,0x1d]
         stx %fsr,[%g2 + %i5]
 
+        ! V9: stxa %g0, [%g2+%i5] 131   ! encoding: [0xc0,0xf0,0x90,0x7d]
+        stxa %g0, [%g2 + %i5] 131
+        ! V9: stxa %g0, [%g2+%i5] 131   ! encoding: [0xc0,0xf0,0x90,0x7d]
+        stxa %g0, [%g2 + %i5] (130+1)
+
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: wrpr %g6,%i6,%tpc
         ! V9: wrpr %g6, %fp, %tpc        ! encoding: [0x81,0x91,0x80,0x1e]
@@ -446,6 +496,16 @@
         ! V9: st %o1, [%o0]             ! encoding: [0xd2,0x22,0x00,0x00]
         stw %o1, [%o0]
 
+        !! SPARCv9 provides a new variant of ASI-tagged memory accesses.
+        ! V9: ldxa [%g2] %asi, %g0    ! encoding: [0xc0,0xd8,0xa0,0x00]
+        ldxa [%g2] %asi, %g0
+        ! V9: stxa %g0, [%g2] %asi    ! encoding: [0xc0,0xf0,0xa0,0x00]
+        stxa %g0, [%g2] %asi
+        ! V9: ldxa [%g2+5] %asi, %g0    ! encoding: [0xc0,0xd8,0xa0,0x05]
+        ldxa [%g2 + 5] %asi, %g0
+        ! V9: stxa %g0, [%g2+5] %asi    ! encoding: [0xc0,0xf0,0xa0,0x05]
+        stxa %g0, [%g2 + 5] %asi
+
         ! V8:      error: instruction requires a CPU feature not currently enabled
         ! V8-NEXT: prefetch  [ %i1 + 0xf80 ], 1
         ! V9: prefetch  [%i1+3968], 1  ! encoding: [0xc3,0x6e,0x6f,0x80]


        


More information about the llvm-commits mailing list