Sparc: Add the "alternate address space" load/store instructions.
authorJames Y Knight <jyknight@google.com>
Mon, 18 May 2015 16:35:04 +0000 (16:35 +0000)
committerJames Y Knight <jyknight@google.com>
Mon, 18 May 2015 16:35:04 +0000 (16:35 +0000)
- Adds support for the asm syntax, which has an immediate integer
  "ASI" (address space identifier) appearing after an address, before
  a comma.

- Adds the various-width load, store, and swap in alternate address
  space instructions. (ldsba, ldsha, lduba, lduha, lda, stba, stha,
  sta, swapa)

This does not attempt to hook these instructions up to pointer address
spaces in LLVM, although that would probably be a reasonable thing to
do in the future.

Differential Revision: http://reviews.llvm.org/D8904

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237581 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
lib/Target/Sparc/SparcInstr64Bit.td
lib/Target/Sparc/SparcInstrFormats.td
lib/Target/Sparc/SparcInstrInfo.td
test/MC/Disassembler/Sparc/sparc-mem.txt
test/MC/Sparc/sparc-atomic-instructions.s
test/MC/Sparc/sparc-mem-instructions.s
test/MC/Sparc/sparcv9-atomic-instructions.s [new file with mode: 0644]

index de1066794306999bd5bd5879b9402f20b793a76a..84cb440e742c2ac99e28f8acf92039b4a3918c0e 100644 (file)
@@ -631,6 +631,15 @@ SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
     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 b3a60381a83507ade650e81bd1792225783d934c..3e56b9e9b8837dcd235949606fdef1d3934247bd 100644 (file)
@@ -279,6 +279,8 @@ static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address,
   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 @@ static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address,
       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 @@ static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address,
   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 @@ static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address,
     if (status != MCDisassembler::Success)
       return status;
   }
+
+  if (hasAsi)
+    MI.addOperand(MCOperand::createImm(asi));
+
   return MCDisassembler::Success;
 }
index 0eb6f08c8f3243bb53e4527d164eb190559b2b06..419e8ccb10244cd96d7d637cfbc4778081169884 100644 (file)
@@ -486,8 +486,8 @@ def SETHIXi : F2_1<0b100,
 }
 
 // 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 3b5e2389932b047107eda550d8e1fb76948455ac..4c97687b14db15300e010661351af42c577759f5 100644 (file)
@@ -113,8 +113,9 @@ class F3<dag outs, dag ins, string asmstr, list<dag> pattern>
 
 // 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_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins,
 }
 
 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 ea17174e11a3a5d848f3ed32e9afa5a3e6c61396..732ec36010014c99ab811ae68b6ca1d49541e43d 100644 (file)
@@ -283,6 +283,17 @@ multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
                  [(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 @@ multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
                  [(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 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1,
 
 // 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 @@ let DecoderMethod = "DecodeLoadQFP" in
 
 // 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 @@ let Constraints = "$val = $dst", DecoderMethod = "DecodeSWAP" in {
                  (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 f92e052650f298b1bd97a767c38b929118b01c8b..5f8886ef8b76e7435563ea1c1fb65f75c29b55fb 100644 (file)
 
 # 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 5c46067ea3bc91a2ab1508fba144ac4ee7beb311..17f97d4b535457eb85f9a075fccdbb4b6921ce41 100644 (file)
@@ -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 40ccd13e7ec27fcd5d3bded5443ef3d3e78f5074..ba4c0f2d104832158e40de181e960237d6fa48e7 100644 (file)
@@ -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
diff --git a/test/MC/Sparc/sparcv9-atomic-instructions.s b/test/MC/Sparc/sparcv9-atomic-instructions.s
new file mode 100644 (file)
index 0000000..40619a7
--- /dev/null
@@ -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