[Sparc] Add support to disassemble sparc memory instructions.
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Sat, 1 Mar 2014 07:46:33 +0000 (07:46 +0000)
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Sat, 1 Mar 2014 07:46:33 +0000 (07:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202575 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
lib/Target/Sparc/SparcInstr64Bit.td
lib/Target/Sparc/SparcInstrInfo.td
test/MC/Disassembler/Sparc/sparc-mem.txt [new file with mode: 0644]

index 6233805431c16e92ce12904fff73ab5aab6e3cac..ae07e0b4f7479bf3916faff94682298fd4755c91 100644 (file)
@@ -174,6 +174,22 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder);
+static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                 const void *Decoder);
+static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder);
+static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder);
+static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn,
+                                   uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn,
+                                  uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn,
+                                   uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn,
+                                   uint64_t Address, const void *Decoder);
 
 #include "SparcGenDisassemblerTables.inc"
 
@@ -226,3 +242,97 @@ SparcDisassembler::getInstruction(MCInst &instr,
 
   return MCDisassembler::Fail;
 }
+
+
+typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
+                                   const void *Decoder);
+
+static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address,
+                              const void *Decoder,
+                              bool isLoad, DecodeFunc DecodeRD) {
+  unsigned rd = fieldFromInstruction(insn, 25, 5);
+  unsigned rs1 = fieldFromInstruction(insn, 14, 5);
+  bool isImm = fieldFromInstruction(insn, 13, 1);
+  unsigned rs2 = 0;
+  unsigned simm13 = 0;
+  if (isImm)
+    simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13));
+  else
+    rs2 = fieldFromInstruction(insn, 0, 5);
+
+  DecodeStatus status;
+  if (isLoad) {
+    status = DecodeRD(MI, rd, Address, Decoder);
+    if (status != MCDisassembler::Success)
+      return status;
+  }
+
+  // Decode rs1.
+  status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder);
+  if (status != MCDisassembler::Success)
+    return status;
+
+  // Decode imm|rs2.
+  if (isImm)
+    MI.addOperand(MCOperand::CreateImm(simm13));
+  else {
+    status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder);
+    if (status != MCDisassembler::Success)
+      return status;
+  }
+
+  if (!isLoad) {
+    status = DecodeRD(MI, rd, Address, Decoder);
+    if (status != MCDisassembler::Success)
+      return status;
+  }
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, true,
+                   DecodeIntRegsRegisterClass);
+}
+
+static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                 const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, true,
+                   DecodeFPRegsRegisterClass);
+}
+
+static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, true,
+                   DecodeDFPRegsRegisterClass);
+}
+
+static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, true,
+                   DecodeQFPRegsRegisterClass);
+}
+
+static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn,
+                                   uint64_t Address, const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, false,
+                   DecodeIntRegsRegisterClass);
+}
+
+static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, uint64_t Address,
+                                  const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, false,
+                   DecodeFPRegsRegisterClass);
+}
+
+static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn,
+                                   uint64_t Address, const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, false,
+                   DecodeDFPRegsRegisterClass);
+}
+
+static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn,
+                                   uint64_t Address, const void *Decoder) {
+  return DecodeMem(Inst, insn, Address, Decoder, false,
+                   DecodeQFPRegsRegisterClass);
+}
index a5b48f90340739ee93759b315eb168c94b79f88a..77b394dd7c99992f27270072d8747c99fd8ba1f5 100644 (file)
@@ -235,7 +235,8 @@ def UDIVXri : F3_2<2, 0b001101,
 let Predicates = [Is64Bit] in {
 
 // 64-bit loads.
-defm LDX   : Load<"ldx", 0b001011, load, I64Regs, i64>;
+let DecoderMethod = "DecodeLoadInt" in
+  defm LDX   : Load<"ldx", 0b001011, load, I64Regs, i64>;
 
 let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in
   def TLS_LDXrr : F3_1<3, 0b001011,
@@ -270,10 +271,12 @@ 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>;
+let DecoderMethod = "DecodeLoadInt" in
+  defm LDSW   : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>;
 
 // 64-bit stores.
-defm STX    : Store<"stx", 0b001110, store,  I64Regs, i64>;
+let DecoderMethod = "DecodeStoreInt" in
+  defm STX    : Store<"stx", 0b001110, store,  I64Regs, i64>;
 
 // Truncating stores from i64 are identical to the i32 stores.
 def : Pat<(truncstorei8  i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;
index ae10ca0bd413618f4d9ad30664669a944ab745ce..57b692562e4210ca07638ea57556d9421841bb7c 100644 (file)
@@ -387,28 +387,38 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1,
 }
 
 // Section B.1 - Load Integer Instructions, p. 90
-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>;
+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>;
+}
 
 // Section B.2 - Load Floating-point Instructions, p. 92
-defm LDF   : Load<"ld",  0b100000, load, FPRegs,  f32>;
-defm LDDF  : Load<"ldd", 0b100011, load, DFPRegs, f64>;
-defm LDQF  : Load<"ldq", 0b100010, load, QFPRegs, f128>,
-             Requires<[HasV9, HasHardQuad]>;
+let DecoderMethod = "DecodeLoadFP" in
+  defm LDF   : Load<"ld",  0b100000, load, FPRegs,  f32>;
+let DecoderMethod = "DecodeLoadDFP" in
+  defm LDDF  : Load<"ldd", 0b100011, load, DFPRegs, f64>;
+let DecoderMethod = "DecodeLoadQFP" in
+  defm LDQF  : Load<"ldq", 0b100010, load, QFPRegs, f128>,
+               Requires<[HasV9, HasHardQuad]>;
 
 // Section B.4 - Store Integer Instructions, p. 95
-defm STB   : Store<"stb", 0b000101, truncstorei8,  IntRegs, i32>;
-defm STH   : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>;
-defm ST    : Store<"st",  0b000100, store,         IntRegs, i32>;
+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>;
+}
 
 // Section B.5 - Store Floating-point Instructions, p. 97
-defm STF   : Store<"st",  0b100100, store,         FPRegs,  f32>;
-defm STDF  : Store<"std", 0b100111, store,         DFPRegs, f64>;
-defm STQF  : Store<"stq", 0b100110, store,         QFPRegs, f128>,
-             Requires<[HasV9, HasHardQuad]>;
+let DecoderMethod = "DecodeStoreFP" in
+  defm STF   : Store<"st",  0b100100, store,         FPRegs,  f32>;
+let DecoderMethod = "DecodeStoreDFP" in
+  defm STDF  : Store<"std", 0b100111, store,         DFPRegs, f64>;
+let DecoderMethod = "DecodeStoreQFP" in
+  defm STQF  : Store<"stq", 0b100110, store,         QFPRegs, f128>,
+               Requires<[HasV9, HasHardQuad]>;
 
 // Section B.9 - SETHI Instruction, p. 104
 def SETHIi: F2_1<0b100,
diff --git a/test/MC/Disassembler/Sparc/sparc-mem.txt b/test/MC/Disassembler/Sparc/sparc-mem.txt
new file mode 100644 (file)
index 0000000..3722247
--- /dev/null
@@ -0,0 +1,154 @@
+# RUN: llvm-mc --disassemble %s -triple=sparcv9-unknown-linux | FileCheck %s
+
+# CHECK:      ldsb [%i0+%l6], %o2
+0xd4 0x4e 0x00 0x16
+
+# CHECK:      ldsb [%i0+32], %o2
+0xd4 0x4e 0x20 0x20
+
+# CHECK:      ldsb [%g1], %o4
+0xd8 0x48 0x60 0x00
+
+# CHECK:      ldsh [%i0+%l6], %o2
+0xd4 0x56 0x00 0x16
+
+# CHECK:      ldsh [%i0+32], %o2
+0xd4 0x56 0x20 0x20
+
+# CHECK:      ldsh [%g1], %o4
+0xd8 0x50 0x60 0x00
+
+# CHECK:      ldub [%i0+%l6], %o2
+0xd4 0x0e 0x00 0x16
+
+# CHECK:      ldub [%i0+32], %o2
+0xd4 0x0e 0x20 0x20
+
+# CHECK:      ldub [%g1], %o2
+0xd4 0x08 0x60 0x00
+
+# CHECK:      lduh [%i0+%l6], %o2
+0xd4 0x16 0x00 0x16
+
+# CHECK:      lduh [%i0+32], %o2
+0xd4 0x16 0x20 0x20
+
+# CHECK:      lduh [%g1], %o2
+0xd4 0x10 0x60 0x00
+
+# CHECK:      ld [%i0+%l6], %o2
+0xd4 0x06 0x00 0x16
+
+# CHECK:      ld [%i0+32], %o2
+0xd4 0x06 0x20 0x20
+
+# CHECK:      ld [%g1], %o2
+0xd4 0x00 0x60 0x00
+
+# CHECK:     ld [%i0+%l6], %f2
+0xc5 0x06 0x00 0x16
+
+# CHECK:     ld [%i0+32], %f2
+0xc5 0x06 0x20 0x20
+
+# CHECK:     ld [%g1], %f2
+0xc5 0x00 0x60 0x00
+
+# CHECK:     ldd [%i0+%l6], %f2
+0xc5 0x1e 0x00 0x16
+
+# CHECK:     ldd [%i0+32], %f2
+0xc5 0x1e 0x20 0x20
+
+# CHECK:     ldd [%g1], %f2
+0xc5 0x18 0x60 0x00
+
+# CHECK:     ldq [%i0+%l6], %f4
+0xc9 0x16 0x00 0x16
+
+# CHECK:     ldq [%i0+32], %f4
+0xc9 0x16 0x20 0x20
+
+# CHECK:     ldq [%g1], %f4
+0xc9 0x10 0x60 0x00
+
+# CHECK:     ldx [%i0+%l6], %o2
+0xd4 0x5e 0x00 0x16
+
+# CHECK:     ldx [%i0+32], %o2
+0xd4 0x5e 0x20 0x20
+
+# CHECK:     ldx [%g1], %o2
+0xd4 0x58 0x60 0x00
+
+# CHECK:     ldsw [%i0+%l6], %o2
+0xd4 0x46 0x00 0x16
+
+# CHECK:     ldsw [%i0+32], %o2
+0xd4 0x46 0x20 0x20
+
+# CHECK:     ldsw [%g1], %o2
+0xd4 0x40 0x60 0x00
+
+# CHECK:      stb %o2, [%i0+%l6]
+0xd4 0x2e 0x00 0x16
+
+# CHECK:      stb %o2, [%i0+32]
+0xd4 0x2e 0x20 0x20
+
+# CHECK:      stb %o2, [%g1]
+0xd4 0x28 0x60 0x00
+
+# CHECK:      sth %o2, [%i0+%l6]
+0xd4 0x36 0x00 0x16
+
+# CHECK:      sth %o2, [%i0+32]
+0xd4 0x36 0x20 0x20
+
+# CHECK:      sth %o2, [%g1]
+0xd4 0x30 0x60 0x00
+
+# CHECK:      st %o2, [%i0+%l6]
+0xd4 0x26 0x00 0x16
+
+# CHECK:      st %o2, [%i0+32]
+0xd4 0x26 0x20 0x20
+
+# CHECK:      st %o2, [%g1]
+0xd4 0x20 0x60 0x00
+
+# CHECK:      st %f2, [%i0+%l6]
+0xc5 0x26 0x00 0x16
+
+# CHECK:      st %f2, [%i0+32]
+0xc5 0x26 0x20 0x20
+
+# CHECK:      st %f2, [%g1]
+0xc5 0x20 0x60 0x00
+
+# CHECK:      std %f2, [%i0+%l6]
+0xc5 0x3e 0x00 0x16
+
+# CHECK:      std %f2, [%i0+32]
+0xc5 0x3e 0x20 0x20
+
+# CHECK:      std %f2, [%g1]
+0xc5 0x38 0x60 0x00
+
+# CHECK:      stq %f4, [%i0+%l6]
+0xc9 0x36 0x00 0x16
+
+# CHECK:      stq %f4, [%i0+32]
+0xc9 0x36 0x20 0x20
+
+# CHECK:      stq %f4, [%g1]
+0xc9 0x30 0x60 0x00
+
+# CHECK:      stx %o2, [%i0+%l6]
+0xd4 0x76 0x00 0x16
+
+# CHECK:      stx %o2, [%i0+32]
+0xd4 0x76 0x20 0x20
+
+# CHECK:      stx %o2, [%g1]
+0xd4 0x70 0x60 0x00