[mips][msa] Fix issue with immediate fields of LD/ST instructions
authorMatheus Almeida <matheus.almeida@imgtec.com>
Thu, 5 Dec 2013 11:06:22 +0000 (11:06 +0000)
committerMatheus Almeida <matheus.almeida@imgtec.com>
Thu, 5 Dec 2013 11:06:22 +0000 (11:06 +0000)
not being correctly encoded/decoded.
In more detail, immediate fields of LD/ST instructions should be
divided/multiplied by the size of the data format before encoding and
after decoding, respectively.

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

lib/Target/Mips/Disassembler/MipsDisassembler.cpp
lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
lib/Target/Mips/MipsCodeEmitter.cpp
lib/Target/Mips/MipsInstrInfo.td
lib/Target/Mips/MipsMSAInstrInfo.td
test/MC/Mips/msa/test_mi10.s

index 60508a8c4fcb467a116684e0d4293781249884d6..c574f549a18e75df354e8377ac58af8041fcc13a 100644 (file)
@@ -565,7 +565,37 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
 
   Inst.addOperand(MCOperand::CreateReg(Reg));
   Inst.addOperand(MCOperand::CreateReg(Base));
-  Inst.addOperand(MCOperand::CreateImm(Offset));
+
+  // The immediate field of an LD/ST instruction is scaled which means it must
+  // be multiplied (when decoding) by the size (in bytes) of the instructions'
+  // data format.
+  // .b - 1 byte
+  // .h - 2 bytes
+  // .w - 4 bytes
+  // .d - 8 bytes
+  switch(Inst.getOpcode())
+  {
+  default:
+    assert (0 && "Unexpected instruction");
+    return MCDisassembler::Fail;
+    break;
+  case Mips::LD_B:
+  case Mips::ST_B:
+    Inst.addOperand(MCOperand::CreateImm(Offset));
+    break;
+  case Mips::LD_H:
+  case Mips::ST_H:
+    Inst.addOperand(MCOperand::CreateImm(Offset << 1));
+    break;
+  case Mips::LD_W:
+  case Mips::ST_W:
+    Inst.addOperand(MCOperand::CreateImm(Offset << 2));
+    break;
+  case Mips::LD_D:
+  case Mips::ST_D:
+    Inst.addOperand(MCOperand::CreateImm(Offset << 3));
+    break;
+  }
 
   return MCDisassembler::Success;
 }
index 66428bdfa74769c2b3d5a95ca017e81e8f0dc811..669e48a78b30217e3a94c7cd47229ec302014329 100644 (file)
@@ -107,6 +107,9 @@ public:
   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
                              SmallVectorImpl<MCFixup> &Fixups) const;
 
+  unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
+                             SmallVectorImpl<MCFixup> &Fixups) const;
+
   unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups) const;
   unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
@@ -480,6 +483,49 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   return getExprOpValue(MO.getExpr(),Fixups);
 }
 
+/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST
+/// instructions.
+unsigned
+MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
+                                     SmallVectorImpl<MCFixup> &Fixups) const {
+  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
+  assert(MI.getOperand(OpNo).isReg());
+  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
+  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
+
+  // The immediate field of an LD/ST instruction is scaled which means it must
+  // be divided (when encoding) by the size (in bytes) of the instructions'
+  // data format.
+  // .b - 1 byte
+  // .h - 2 bytes
+  // .w - 4 bytes
+  // .d - 8 bytes
+  switch(MI.getOpcode())
+  {
+  default:
+    assert (0 && "Unexpected instruction");
+    break;
+  case Mips::LD_B:
+  case Mips::ST_B:
+    // We don't need to scale the offset in this case
+    break;
+  case Mips::LD_H:
+  case Mips::ST_H:
+    OffBits >>= 1;
+    break;
+  case Mips::LD_W:
+  case Mips::ST_W:
+    OffBits >>= 2;
+    break;
+  case Mips::LD_D:
+  case Mips::ST_D:
+    OffBits >>= 3;
+    break;
+  }
+
+  return (OffBits & 0xFFFF) | RegBits;
+}
+
 /// getMemEncoding - Return binary encoding of memory related operand.
 /// If the offset operand requires relocation, record the relocation.
 unsigned
index ca4163d4e58c8b8eec163373492ff95939b715ec..76f604d660341ba57d74b44f0c58956abf008347 100644 (file)
@@ -112,6 +112,7 @@ private:
   unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const;
+  unsigned getMSAMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getLSAImmEncoding(const MachineInstr &MI, unsigned OpNo) const;
@@ -224,6 +225,12 @@ unsigned MipsCodeEmitter::getMemEncodingMMImm12(const MachineInstr &MI,
   return 0;
 }
 
+unsigned MipsCodeEmitter::getMSAMemEncoding(const MachineInstr &MI,
+                                            unsigned OpNo) const {
+  llvm_unreachable("Unimplemented function.");
+  return 0;
+}
+
 unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI,
                                              unsigned OpNo) const {
   // size is encoded as size-1.
index cc76f7edbc6d1d3f6fb54c27c59b7612dca966bb..307e0fb8cc1adaa2c9d90b8e685be841a2e96320 100644 (file)
@@ -302,8 +302,7 @@ def InvertedImOperand : Operand<i32> {
   let ParserMatchClass = MipsInvertedImmoperand;
 }
 
-// Address operand
-def mem : Operand<iPTR> {
+class mem_generic : Operand<iPTR> {
   let PrintMethod = "printMemOperand";
   let MIOperandInfo = (ops ptr_rc, simm16);
   let EncoderMethod = "getMemEncoding";
@@ -311,6 +310,14 @@ def mem : Operand<iPTR> {
   let OperandType = "OPERAND_MEMORY";
 }
 
+// Address operand
+def mem : mem_generic;
+
+// MSA specific address operand
+def mem_msa : mem_generic {
+  let EncoderMethod = "getMSAMemEncoding";
+}
+
 def mem_ea : Operand<iPTR> {
   let PrintMethod = "printMemOperandEA";
   let MIOperandInfo = (ops ptr_rc, simm16);
index 9089be2abcb4b998841fd2a5d9786f477d86b6f1..7a588f6e9501eb70d543dea95a00e0a598b65b7a 100644 (file)
@@ -2269,7 +2269,7 @@ class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", int_mips_insve_d,
 
 class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                    ValueType TyNode, RegisterOperand ROWD,
-                   Operand MemOpnd = mem, ComplexPattern Addr = addrRegImm,
+                   Operand MemOpnd = mem_msa, ComplexPattern Addr = addrRegImm,
                    InstrItinClass itin = NoItinerary> {
   dag OutOperandList = (outs ROWD:$wd);
   dag InOperandList = (ins MemOpnd:$addr);
@@ -2590,7 +2590,7 @@ class SRLRI_D_DESC : MSA_BIT_D_X_DESC_BASE<"srlri.d", int_mips_srlri_d,
 
 class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                    ValueType TyNode, RegisterOperand ROWD,
-                   Operand MemOpnd = mem, ComplexPattern Addr = addrRegImm,
+                   Operand MemOpnd = mem_msa, ComplexPattern Addr = addrRegImm,
                    InstrItinClass itin = NoItinerary> {
   dag OutOperandList = (outs);
   dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr);
index 80257cda8516978f170baed6d3cbbff65f409ad2..94711ebaa7f5c3454dd027ddecd6f486118c3e48 100644 (file)
@@ -2,29 +2,83 @@
 #
 # RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa -arch=mips -filetype=obj -o - | llvm-objdump -d -triple=mipsel-unknown-linux -mattr=+msa -arch=mips - | FileCheck %s -check-prefix=CHECKOBJDUMP
 #
-# CHECK:        ld.b    $w2, 1($7)              # encoding: [0x78,0x01,0x38,0xa0]
-# CHECK:        ld.h    $w16, -9($zero)         # encoding: [0x7b,0xf7,0x04,0x21]
-# CHECK:        ld.w    $w13, -6($4)            # encoding: [0x7b,0xfa,0x23,0x62]
-# CHECK:        ld.d    $w1, -5($16)            # encoding: [0x7b,0xfb,0x80,0x63]
-# CHECK:        st.b    $w29, 1($14)            # encoding: [0x78,0x01,0x77,0x64]
-# CHECK:        st.h    $w6, -1($8)             # encoding: [0x7b,0xff,0x41,0xa5]
-# CHECK:        st.w    $w18, 8($15)            # encoding: [0x78,0x08,0x7c,0xa6]
-# CHECK:        st.d    $w3, -14($18)           # encoding: [0x7b,0xf2,0x90,0xe7]
-
-# CHECKOBJDUMP:        ld.b    $w2, 1($7)
-# CHECKOBJDUMP:        ld.h    $w16, -9($zero)
-# CHECKOBJDUMP:        ld.w    $w13, -6($4)
-# CHECKOBJDUMP:        ld.d    $w1, -5($16)
-# CHECKOBJDUMP:        st.b    $w29, 1($14)
-# CHECKOBJDUMP:        st.h    $w6, -1($8)
-# CHECKOBJDUMP:        st.w    $w18, 8($15)
-# CHECKOBJDUMP:        st.d    $w3, -14($18)
-
-                ld.b    $w2, 1($7)
-                ld.h    $w16, -9($zero)
-                ld.w    $w13, -6($4)
-                ld.d    $w1, -5($16)
-                st.b    $w29, 1($14)
-                st.h    $w6, -1($8)
-                st.w    $w18, 8($15)
-                st.d    $w3, -14($18)
+# CHECK:        ld.b $w0, -512($1)              # encoding: [0x7a,0x00,0x08,0x20]
+# CHECK:        ld.b $w1, 0($2)                 # encoding: [0x78,0x00,0x10,0x60]
+# CHECK:        ld.b $w2, 511($3)               # encoding: [0x79,0xff,0x18,0xa0]
+
+# CHECK:        ld.h $w3, -1024($4)             # encoding: [0x7a,0x00,0x20,0xe1]
+# CHECK:        ld.h $w4, -512($5)              # encoding: [0x7b,0x00,0x29,0x21]
+# CHECK:        ld.h $w5, 0($6)                 # encoding: [0x78,0x00,0x31,0x61]
+# CHECK:        ld.h $w6, 512($7)               # encoding: [0x79,0x00,0x39,0xa1]
+# CHECK:        ld.h $w7, 1022($8)              # encoding: [0x79,0xff,0x41,0xe1]
+
+# CHECK:        ld.w $w8, -2048($9)             # encoding: [0x7a,0x00,0x4a,0x22]
+# CHECK:        ld.w $w9, -1024($10)            # encoding: [0x7b,0x00,0x52,0x62]
+# CHECK:        ld.w $w10, -512($11)            # encoding: [0x7b,0x80,0x5a,0xa2]
+# CHECK:        ld.w $w11, 512($12)             # encoding: [0x78,0x80,0x62,0xe2]
+# CHECK:        ld.w $w12, 1024($13)            # encoding: [0x79,0x00,0x6b,0x22]
+# CHECK:        ld.w $w13, 2044($14)            # encoding: [0x79,0xff,0x73,0x62]
+
+# CHECK:        ld.d $w14, -4096($15)           # encoding: [0x7a,0x00,0x7b,0xa3]
+# CHECK:        ld.d $w15, -2048($16)           # encoding: [0x7b,0x00,0x83,0xe3]
+# CHECK:        ld.d $w16, -1024($17)           # encoding: [0x7b,0x80,0x8c,0x23]
+# CHECK:        ld.d $w17, -512($18)            # encoding: [0x7b,0xc0,0x94,0x63]
+# CHECK:        ld.d $w18, 0($19)               # encoding: [0x78,0x00,0x9c,0xa3]
+# CHECK:        ld.d $w19, 512($20)             # encoding: [0x78,0x40,0xa4,0xe3]
+# CHECK:        ld.d $w20, 1024($21)            # encoding: [0x78,0x80,0xad,0x23]
+# CHECK:        ld.d $w21, 2048($22)            # encoding: [0x79,0x00,0xb5,0x63]
+# CHECK:        ld.d $w22, 4088($23)            # encoding: [0x79,0xff,0xbd,0xa3]
+
+# CHECKOBJDUMP:        ld.b $w0, -512($1)
+# CHECKOBJDUMP:        ld.b $w1, 0($2)
+# CHECKOBJDUMP:        ld.b $w2, 511($3)
+
+# CHECKOBJDUMP:        ld.h $w3, -1024($4)
+# CHECKOBJDUMP:        ld.h $w4, -512($5)
+# CHECKOBJDUMP:        ld.h $w5, 0($6)
+# CHECKOBJDUMP:        ld.h $w6, 512($7)
+# CHECKOBJDUMP:        ld.h $w7, 1022($8)
+
+# CHECKOBJDUMP:        ld.w $w8, -2048($9)
+# CHECKOBJDUMP:        ld.w $w9, -1024($10)
+# CHECKOBJDUMP:        ld.w $w10, -512($11)
+# CHECKOBJDUMP:        ld.w $w11, 512($12)
+# CHECKOBJDUMP:        ld.w $w12, 1024($13)
+# CHECKOBJDUMP:        ld.w $w13, 2044($14)
+
+# CHECKOBJDUMP:        ld.d $w14, -4096($15)
+# CHECKOBJDUMP:        ld.d $w15, -2048($16)
+# CHECKOBJDUMP:        ld.d $w16, -1024($17)
+# CHECKOBJDUMP:        ld.d $w17, -512($18)
+# CHECKOBJDUMP:        ld.d $w18, 0($19)
+# CHECKOBJDUMP:        ld.d $w19, 512($20)
+# CHECKOBJDUMP:        ld.d $w20, 1024($21)
+# CHECKOBJDUMP:        ld.d $w21, 2048($22)
+# CHECKOBJDUMP:        ld.d $w22, 4088($23)
+
+        ld.b $w0, -512($1)
+        ld.b $w1, 0($2)
+        ld.b $w2, 511($3)
+
+        ld.h $w3, -1024($4)
+        ld.h $w4, -512($5)
+        ld.h $w5, 0($6)
+        ld.h $w6, 512($7)
+        ld.h $w7, 1022($8)
+
+        ld.w $w8, -2048($9)
+        ld.w $w9, -1024($10)
+        ld.w $w10, -512($11)
+        ld.w $w11, 512($12)
+        ld.w $w12, 1024($13)
+        ld.w $w13, 2044($14)
+
+        ld.d $w14, -4096($15)
+        ld.d $w15, -2048($16)
+        ld.d $w16, -1024($17)
+        ld.d $w17, -512($18)
+        ld.d $w18, 0($19)
+        ld.d $w19, 512($20)
+        ld.d $w20, 1024($21)
+        ld.d $w21, 2048($22)
+        ld.d $w22, 4088($23)