Index: llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
===================================================================
--- llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -631,6 +631,15 @@
     Operands.push_back(SparcOperand::CreateToken("]",
                                                  Parser.getTok().getLoc()));
     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));
+    }
     return MatchOperand_Success;
   }
 
Index: llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
===================================================================
--- llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
+++ llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
@@ -279,6 +279,8 @@
   unsigned rd = fieldFromInstruction(insn, 25, 5);
   unsigned rs1 = fieldFromInstruction(insn, 14, 5);
   bool isImm = fieldFromInstruction(insn, 13, 1);
+  bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field)
+  unsigned asi = fieldFromInstruction(insn, 5, 8);
   unsigned rs2 = 0;
   unsigned simm13 = 0;
   if (isImm)
@@ -307,6 +309,9 @@
       return status;
   }
 
+  if (hasAsi)
+    MI.addOperand(MCOperand::createImm(asi));
+
   if (!isLoad) {
     status = DecodeRD(MI, rd, Address, Decoder);
     if (status != MCDisassembler::Success)
@@ -457,6 +462,8 @@
   unsigned rd = fieldFromInstruction(insn, 25, 5);
   unsigned rs1 = fieldFromInstruction(insn, 14, 5);
   unsigned isImm = fieldFromInstruction(insn, 13, 1);
+  bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field)
+  unsigned asi = fieldFromInstruction(insn, 5, 8);
   unsigned rs2 = 0;
   unsigned simm13 = 0;
   if (isImm)
@@ -482,5 +489,9 @@
     if (status != MCDisassembler::Success)
       return status;
   }
+
+  if (hasAsi)
+    MI.addOperand(MCOperand::createImm(asi));
+
   return MCDisassembler::Success;
 }
Index: llvm/trunk/lib/Target/Sparc/SparcInstr64Bit.td
===================================================================
--- llvm/trunk/lib/Target/Sparc/SparcInstr64Bit.td
+++ llvm/trunk/lib/Target/Sparc/SparcInstr64Bit.td
@@ -486,8 +486,8 @@
 }
 
 // ATOMICS.
-let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
-  def CASXrr: F3_1_asi<3, 0b111110, 0b10000000,
+let Predicates = [Is64Bit], Constraints = "$swap = $rd", asi = 0b10000000 in {
+  def CASXrr: F3_1_asi<3, 0b111110,
                 (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
                                      I64Regs:$swap),
                  "casx [$rs1], $rs2, $rd",
Index: llvm/trunk/lib/Target/Sparc/SparcInstrFormats.td
===================================================================
--- llvm/trunk/lib/Target/Sparc/SparcInstrFormats.td
+++ llvm/trunk/lib/Target/Sparc/SparcInstrFormats.td
@@ -113,8 +113,9 @@
 
 // Specific F3 classes: SparcV8 manual, page 44
 //
-class F3_1_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins,
+class F3_1_asi<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
            string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
+  bits<8> asi;
   bits<5> rs2;
 
   let op         = opVal;
@@ -126,8 +127,10 @@
 }
 
 class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr,
-       list<dag> pattern> : F3_1_asi<opVal, op3val, 0, outs, ins,
-                                                     asmstr, pattern>;
+       list<dag> pattern> : F3_1_asi<opVal, op3val, outs, ins,
+                                                     asmstr, pattern> {
+  let asi = 0;
+}
 
 class F3_2<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
            string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td
===================================================================
--- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td
+++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td
@@ -283,6 +283,17 @@
                  [(set Ty:$dst, (OpNode ADDRri:$addr))]>;
 }
 
+// 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> :
+             Load<OpcStr, Op3Val, OpNode, RC, Ty> {
+  // TODO: The LD*Arr instructions are currently asm only; hooking up
+  // CodeGen's address spaces to use these is a future task.
+  def Arr  : F3_1_asi<3, LoadAOp3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi),
+                !strconcat(OpcStr, "a [$addr] $asi, $dst"),
+                []>;
+}
+
 // Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.
 multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
            RegisterClass RC, ValueType Ty> {
@@ -296,6 +307,16 @@
                  [(OpNode Ty:$rd, ADDRri:$addr)]>;
 }
 
+multiclass StoreA<string OpcStr, bits<6> Op3Val, bits<6> StoreAOp3Val,
+                  SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> :
+             Store<OpcStr, Op3Val, OpNode, RC, Ty> {
+  // TODO: The ST*Arr instructions are currently asm only; hooking up
+  // CodeGen's address spaces to use these is a future task.
+  def Arr  : F3_1_asi<3, StoreAOp3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi),
+                  !strconcat(OpcStr, "a $rd, [$addr] $asi"),
+                  []>;
+}
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -417,11 +438,11 @@
 
 // Section B.1 - Load Integer Instructions, p. 90
 let DecoderMethod = "DecodeLoadInt" in {
-  defm LDSB : Load<"ldsb", 0b001001, sextloadi8,  IntRegs, i32>;
-  defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>;
-  defm LDUB : Load<"ldub", 0b000001, zextloadi8,  IntRegs, i32>;
-  defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>;
-  defm LD   : Load<"ld",   0b000000, load,        IntRegs, i32>;
+  defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8,  IntRegs, i32>;
+  defm LDSH : LoadA<"ldsh", 0b001010, 0b011010, sextloadi16, IntRegs, i32>;
+  defm LDUB : LoadA<"ldub", 0b000001, 0b010001, zextloadi8,  IntRegs, i32>;
+  defm LDUH : LoadA<"lduh", 0b000010, 0b010010, zextloadi16, IntRegs, i32>;
+  defm LD   : LoadA<"ld",   0b000000, 0b010000, load,        IntRegs, i32>;
 }
 
 // Section B.2 - Load Floating-point Instructions, p. 92
@@ -435,9 +456,9 @@
 
 // Section B.4 - Store Integer Instructions, p. 95
 let DecoderMethod = "DecodeStoreInt" in {
-  defm STB   : Store<"stb", 0b000101, truncstorei8,  IntRegs, i32>;
-  defm STH   : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>;
-  defm ST    : Store<"st",  0b000100, store,         IntRegs, i32>;
+  defm STB   : StoreA<"stb", 0b000101, 0b010101, truncstorei8,  IntRegs, i32>;
+  defm STH   : StoreA<"sth", 0b000110, 0b010110, truncstorei16, IntRegs, i32>;
+  defm ST    : StoreA<"st",  0b000100, 0b010100, store,         IntRegs, i32>;
 }
 
 // Section B.5 - Store Floating-point Instructions, p. 97
@@ -1116,10 +1137,20 @@
                  (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val),
                  "swap [$addr], $dst",
                  [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
+  def SWAPArr : F3_1_asi<3, 0b011111,
+                 (outs IntRegs:$dst), (ins MEMrr:$addr, i8imm:$asi, IntRegs:$val),
+                 "swapa [$addr] $asi, $dst",
+                 [/*FIXME: pattern?*/]>;
 }
 
-let Predicates = [HasV9], Constraints = "$swap = $rd" in
-  def CASrr: F3_1_asi<3, 0b111100, 0b10000000,
+// TODO: Should add a CASArr variant. In fact, the CAS instruction,
+// unlike other instructions, only comes in a form which requires an
+// ASI be provided. The ASI value hardcoded here is ASI_PRIMARY, the
+// default unprivileged ASI for SparcV9.  (Also of note: some modern
+// SparcV8 implementations provide CASA as an extension, but require
+// the use of SparcV8's default ASI, 0xA ("User Data") instead.)
+let Predicates = [HasV9], Constraints = "$swap = $rd", asi = 0b10000000 in
+  def CASrr: F3_1_asi<3, 0b111100,
                 (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
                                      IntRegs:$swap),
                  "cas [$rs1], $rs2, $rd",
Index: llvm/trunk/test/MC/Disassembler/Sparc/sparc-mem.txt
===================================================================
--- llvm/trunk/test/MC/Disassembler/Sparc/sparc-mem.txt
+++ llvm/trunk/test/MC/Disassembler/Sparc/sparc-mem.txt
@@ -215,3 +215,9 @@
 
 # CHECK:     swap [%g1], %o2
 0xd4 0x78 0x40 0x00
+
+# CHECK:     swapa [%i0+%l6] 131, %o2
+0xd4 0xfe 0x10 0x76
+
+# CHECK:     swapa [%g1] 131, %o2
+0xd4 0xf8 0x50 0x60
Index: llvm/trunk/test/MC/Sparc/sparc-atomic-instructions.s
===================================================================
--- llvm/trunk/test/MC/Sparc/sparc-atomic-instructions.s
+++ llvm/trunk/test/MC/Sparc/sparc-atomic-instructions.s
@@ -1,7 +1,5 @@
 ! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
-
-        ! CHECK: membar 15             ! encoding: [0x81,0x43,0xe0,0x0f]
-        membar 15
+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
 
         ! CHECK: stbar                 ! encoding: [0x81,0x43,0xc0,0x00]
         stbar
@@ -12,8 +10,5 @@
         ! CHECK: swap [%i0+32], %o2    ! encoding: [0xd4,0x7e,0x20,0x20]
         swap [%i0+32], %o2
 
-        ! CHECK: cas [%i0], %l6, %o2   ! encoding: [0xd5,0xe6,0x10,0x16]
-        cas [%i0], %l6, %o2
-
-        ! CHECK: casx [%i0], %l6, %o2  ! encoding: [0xd5,0xf6,0x10,0x16]
-        casx [%i0], %l6, %o2
+        ! CHECK: swapa [%i0+%l6] 131, %o2   ! encoding: [0xd4,0xfe,0x10,0x76]
+        swapa [%i0+%l6] 131, %o2
Index: llvm/trunk/test/MC/Sparc/sparc-mem-instructions.s
===================================================================
--- llvm/trunk/test/MC/Sparc/sparc-mem-instructions.s
+++ llvm/trunk/test/MC/Sparc/sparc-mem-instructions.s
@@ -7,6 +7,8 @@
         ldsb [%i0 + 32], %o2
         ! CHECK: ldsb [%g1], %o4      ! encoding: [0xd8,0x48,0x40,0x00]
         ldsb [%g1], %o4
+        ! CHECK: ldsba [%i0+%l6] 131, %o2  ! encoding: [0xd4,0xce,0x10,0x76]
+        ldsba [%i0 + %l6] 131, %o2
 
         ! CHECK: ldsh [%i0+%l6], %o2  ! encoding: [0xd4,0x56,0x00,0x16]
         ldsh [%i0 + %l6], %o2
@@ -14,6 +16,8 @@
         ldsh [%i0 + 32], %o2
         ! CHECK: ldsh [%g1], %o4      ! encoding: [0xd8,0x50,0x40,0x00]
         ldsh [%g1], %o4
+        ! CHECK: ldsha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xd6,0x10,0x76]
+        ldsha [%i0 + %l6] 131, %o2
 
         ! CHECK: ldub [%i0+%l6], %o2  ! encoding: [0xd4,0x0e,0x00,0x16]
         ldub [%i0 + %l6], %o2
@@ -21,6 +25,8 @@
         ldub [%i0 + 32], %o2
         ! CHECK: ldub [%g1], %o2      ! encoding: [0xd4,0x08,0x40,0x00]
         ldub [%g1], %o2
+        ! CHECK: lduba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x8e,0x10,0x76]
+        lduba [%i0 + %l6] 131, %o2
 
         ! CHECK: lduh [%i0+%l6], %o2  ! encoding: [0xd4,0x16,0x00,0x16]
         lduh [%i0 + %l6], %o2
@@ -28,6 +34,8 @@
         lduh [%i0 + 32], %o2
         ! CHECK: lduh [%g1], %o2      ! encoding: [0xd4,0x10,0x40,0x00]
         lduh [%g1], %o2
+        ! CHECK: lduha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x96,0x10,0x76]
+        lduha [%i0 + %l6] 131, %o2
 
         ! CHECK: ld [%i0+%l6], %o2    ! encoding: [0xd4,0x06,0x00,0x16]
         ld [%i0 + %l6], %o2
@@ -35,6 +43,8 @@
         ld [%i0 + 32], %o2
         ! CHECK: ld [%g1], %o2        ! encoding: [0xd4,0x00,0x40,0x00]
         ld [%g1], %o2
+        ! CHECK: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
+        lda [%i0 + %l6] 131, %o2
 
         ! CHECK: stb %o2, [%i0+%l6]   ! encoding: [0xd4,0x2e,0x00,0x16]
         stb %o2, [%i0 + %l6]
@@ -42,6 +52,8 @@
         stb %o2, [%i0 + 32]
         ! CHECK: stb %o2, [%g1]       ! encoding: [0xd4,0x28,0x40,0x00]
         stb %o2, [%g1]
+        ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
+        stba %o2, [%i0 + %l6] 131
 
         ! CHECK: sth %o2, [%i0+%l6]   ! encoding: [0xd4,0x36,0x00,0x16]
         sth %o2, [%i0 + %l6]
@@ -49,6 +61,8 @@
         sth %o2, [%i0 + 32]
         ! CHECK: sth %o2, [%g1]       ! encoding: [0xd4,0x30,0x40,0x00]
         sth %o2, [%g1]
+        ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
+        stha %o2, [%i0 + %l6] 131
 
         ! CHECK: st %o2, [%i0+%l6]    ! encoding: [0xd4,0x26,0x00,0x16]
         st %o2, [%i0 + %l6]
@@ -56,3 +70,5 @@
         st %o2, [%i0 + 32]
         ! CHECK: st %o2, [%g1]        ! encoding: [0xd4,0x20,0x40,0x00]
         st %o2, [%g1]
+        ! CHECK: sta %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xa6,0x10,0x76]
+        sta %o2, [%i0 + %l6] 131
Index: llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s
===================================================================
--- llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s
+++ llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s
@@ -0,0 +1,10 @@
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+        ! CHECK: membar 15             ! encoding: [0x81,0x43,0xe0,0x0f]
+        membar 15
+
+        ! CHECK: cas [%i0], %l6, %o2   ! encoding: [0xd5,0xe6,0x10,0x16]
+        cas [%i0], %l6, %o2
+
+        ! CHECK: casx [%i0], %l6, %o2  ! encoding: [0xd5,0xf6,0x10,0x16]
+        casx [%i0], %l6, %o2