[llvm] r368160 - [Mips] Instruction `sc` now accepts symbol as an argument

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 7 05:21:26 PDT 2019


Author: atanasyan
Date: Wed Aug  7 05:21:26 2019
New Revision: 368160

URL: http://llvm.org/viewvc/llvm-project?rev=368160&view=rev
Log:
[Mips] Instruction `sc` now accepts symbol as an argument

Function MipsAsmParser::expandMemInst() did not properly handle
instruction `sc` with a symbol as an argument because first argument
would be counted twice. We add additional checks and handle this case
separately.

Patch by Mirko Brkusanin.

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

Added:
    llvm/trunk/test/MC/Mips/sym-sc.s
Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
    llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h

Modified: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=368160&r1=368159&r2=368160&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Wed Aug  7 05:21:26 2019
@@ -3581,7 +3581,6 @@ void MipsAsmParser::expandMemInst(MCInst
   assert(DstRegOp.isReg() && "expected register operand kind");
   const MCOperand &BaseRegOp = Inst.getOperand(1);
   assert(BaseRegOp.isReg() && "expected register operand kind");
-  const MCOperand &OffsetOp = Inst.getOperand(2);
 
   MipsTargetStreamer &TOut = getTargetStreamer();
   unsigned DstReg = DstRegOp.getReg();
@@ -3603,6 +3602,26 @@ void MipsAsmParser::expandMemInst(MCInst
       return;
   }
 
+  if (Inst.getNumOperands() > 3) {
+    const MCOperand &BaseRegOp = Inst.getOperand(2);
+    assert(BaseRegOp.isReg() && "expected register operand kind");
+    const MCOperand &ExprOp = Inst.getOperand(3);
+    assert(ExprOp.isExpr() && "expected expression oprand kind");
+
+    unsigned BaseReg = BaseRegOp.getReg();
+    const MCExpr *ExprOffset = ExprOp.getExpr();
+
+    MCOperand LoOperand = MCOperand::createExpr(
+        MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+    MCOperand HiOperand = MCOperand::createExpr(
+        MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+    TOut.emitSCWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+                             LoOperand, TmpReg, IDLoc, STI);
+    return;
+  }
+
+  const MCOperand &OffsetOp = Inst.getOperand(2);
+
   if (OffsetOp.isImm()) {
     int64_t LoOffset = OffsetOp.getImm() & 0xffff;
     int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
@@ -3628,35 +3647,39 @@ void MipsAsmParser::expandMemInst(MCInst
     return;
   }
 
-  assert(OffsetOp.isExpr() && "expected expression operand kind");
-  if (inPicMode()) {
-    // FIXME:
-    // a) Fix lw/sw $reg, symbol($reg) instruction expanding.
-    // b) If expression includes offset (sym + number), do not
-    //    encode the offset into a relocation. Take it in account
-    //    in the last load/store instruction.
-    // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
-    //    do not exceed 16-bit.
-    // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
-    //    of R_MIPS_GOT_DISP in appropriate cases to reduce number
-    //    of GOT entries.
-    expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(),
-                      IDLoc, Out, STI);
-    TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI);
-  } else {
-    const MCExpr *ExprOffset = OffsetOp.getExpr();
-    MCOperand LoOperand = MCOperand::createExpr(
-        MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
-    MCOperand HiOperand = MCOperand::createExpr(
-        MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
-
-    if (IsLoad)
-      TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
-                                 LoOperand, TmpReg, IDLoc, STI);
-    else
-      TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
-                                  LoOperand, TmpReg, IDLoc, STI);
+  if (OffsetOp.isExpr()) {
+    if (inPicMode()) {
+      // FIXME:
+      // a) Fix lw/sw $reg, symbol($reg) instruction expanding.
+      // b) If expression includes offset (sym + number), do not
+      //    encode the offset into a relocation. Take it in account
+      //    in the last load/store instruction.
+      // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
+      //    do not exceed 16-bit.
+      // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
+      //    of R_MIPS_GOT_DISP in appropriate cases to reduce number
+      //    of GOT entries.
+      expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(),
+                        IDLoc, Out, STI);
+      TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI);
+    } else {
+      const MCExpr *ExprOffset = OffsetOp.getExpr();
+      MCOperand LoOperand = MCOperand::createExpr(
+          MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+      MCOperand HiOperand = MCOperand::createExpr(
+          MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+
+      if (IsLoad)
+        TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+                                   LoOperand, TmpReg, IDLoc, STI);
+      else
+        TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg,
+                                    HiOperand, LoOperand, TmpReg, IDLoc, STI);
+    }
+    return;
   }
+
+  llvm_unreachable("unexpected operand type");
 }
 
 bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp?rev=368160&r1=368159&r2=368160&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp Wed Aug  7 05:21:26 2019
@@ -216,6 +216,19 @@ void MipsTargetStreamer::emitRRR(unsigne
   emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
 }
 
+void MipsTargetStreamer::emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
+                                  unsigned Reg2, MCOperand Op3, SMLoc IDLoc,
+                                  const MCSubtargetInfo *STI) {
+  MCInst TmpInst;
+  TmpInst.setOpcode(Opcode);
+  TmpInst.addOperand(MCOperand::createReg(Reg0));
+  TmpInst.addOperand(MCOperand::createReg(Reg1));
+  TmpInst.addOperand(MCOperand::createReg(Reg2));
+  TmpInst.addOperand(Op3);
+  TmpInst.setLoc(IDLoc);
+  getStreamer().EmitInstruction(TmpInst, *STI);
+}
+
 void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
                                  int16_t Imm, SMLoc IDLoc,
                                  const MCSubtargetInfo *STI) {
@@ -328,6 +341,36 @@ void MipsTargetStreamer::emitStoreWithSy
   emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
 }
 
+/// Emit a store instruction with an symbol offset.
+void MipsTargetStreamer::emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg,
+                                             unsigned BaseReg,
+                                             MCOperand &HiOperand,
+                                             MCOperand &LoOperand,
+                                             unsigned ATReg, SMLoc IDLoc,
+                                             const MCSubtargetInfo *STI) {
+  // sc $8, sym => lui $at, %hi(sym)
+  //               sc $8, %lo(sym)($at)
+
+  // Generate the base address in ATReg.
+  emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
+  if (!isMicroMips(STI) && isMipsR6(STI)) {
+    // For non-micromips r6 offset for 'sc' is not in the lower 16 bits so we
+    // put it in 'at'.
+    // sc $8, sym => lui $at, %hi(sym)
+    //               addiu $at, $at, %lo(sym)
+    //               sc $8, 0($at)
+    emitRRX(Mips::ADDiu, ATReg, ATReg, LoOperand, IDLoc, STI);
+    MCOperand Offset = MCOperand::createImm(0);
+    // Emit the store with the adjusted base and offset.
+    emitRRRX(Opcode, SrcReg, SrcReg, ATReg, Offset, IDLoc, STI);
+  } else {
+    if (BaseReg != Mips::ZERO)
+      emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
+    // Emit the store with the adjusted base and offset.
+    emitRRRX(Opcode, SrcReg, SrcReg, ATReg, LoOperand, IDLoc, STI);
+  }
+}
+
 /// Emit a load instruction with an immediate offset. DstReg and TmpReg are
 /// permitted to be the same register iff DstReg is distinct from BaseReg and
 /// DstReg is a GPR. It is the callers responsibility to identify such cases
@@ -388,6 +431,15 @@ void MipsTargetStreamer::emitLoadWithSym
   emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
 }
 
+bool MipsTargetStreamer::isMipsR6(const MCSubtargetInfo *STI) const {
+  return STI->getFeatureBits()[Mips::FeatureMips32r6] ||
+         STI->getFeatureBits()[Mips::FeatureMips64r6];
+}
+
+bool MipsTargetStreamer::isMicroMips(const MCSubtargetInfo *STI) const {
+  return STI->getFeatureBits()[Mips::FeatureMicroMips];
+}
+
 MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
                                              formatted_raw_ostream &OS)
     : MipsTargetStreamer(S), OS(OS) {}

Modified: llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h?rev=368160&r1=368159&r2=368160&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsTargetStreamer.h Wed Aug  7 05:21:26 2019
@@ -130,6 +130,8 @@ public:
                SMLoc IDLoc, const MCSubtargetInfo *STI);
   void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
                SMLoc IDLoc, const MCSubtargetInfo *STI);
+  void emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
+                MCOperand Op3, SMLoc IDLoc, const MCSubtargetInfo *STI);
   void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
                SMLoc IDLoc, const MCSubtargetInfo *STI);
   void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0,
@@ -158,6 +160,10 @@ public:
                               unsigned BaseReg, MCOperand &HiOperand,
                               MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
                               const MCSubtargetInfo *STI);
+  void emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg, unsigned BaseReg,
+                           MCOperand &HiOperand, MCOperand &LoOperand,
+                           unsigned ATReg, SMLoc IDLoc,
+                           const MCSubtargetInfo *STI);
   void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
                              int64_t Offset, unsigned TmpReg, SMLoc IDLoc,
                              const MCSubtargetInfo *STI);
@@ -185,6 +191,9 @@ public:
     return *ABI;
   }
 
+  bool isMipsR6(const MCSubtargetInfo *STI) const;
+  bool isMicroMips(const MCSubtargetInfo *STI) const;
+
 protected:
   llvm::Optional<MipsABIInfo> ABI;
   MipsABIFlagsSection ABIFlagsSection;

Added: llvm/trunk/test/MC/Mips/sym-sc.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/sym-sc.s?rev=368160&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/sym-sc.s (added)
+++ llvm/trunk/test/MC/Mips/sym-sc.s Wed Aug  7 05:21:26 2019
@@ -0,0 +1,74 @@
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips2 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r2 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips3 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips64 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips64r2 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r6 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPSR6
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips64r6 %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPSR6
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r2 -mattr=+micromips %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefixes=MICROMIPS,MICROMIPSR2
+# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r6 -mattr=+micromips %s -o - \
+# RUN:   | llvm-objdump -d -r - | FileCheck %s --check-prefixes=MICROMIPS,MICROMIPSR6
+
+# MIPS:         0:  e0 6c 00 00    sc   $12, 0($3)
+# MIPSR6:       0:  7c 6c 00 26    sc   $12, 0($3)
+# MICROMIPS:    0:  61 83 b0 00    sc   $12, 0($3)
+sc $12, 0($3)
+
+# MIPS:         4:  e0 6c 00 04    sc   $12, 4($3)
+# MIPSR6:       4:  7c 6c 02 26    sc   $12, 4($3)
+# MICROMIPS:    4:  61 83 b0 04    sc   $12, 4($3)
+sc $12, 4($3)
+
+# MIPS:          8:  3c 01 00 00    lui  $1, 0
+# MIPS:         00000008:  R_MIPS_HI16  symbol
+# MIPS:          c:  e0 2c 00 00    sc   $12, 0($1)
+# MIPS:         0000000c:  R_MIPS_LO16  symbol
+
+# MIPSR6:        8: 3c 01 00 00     aui    $1, $zero, 0
+# MIPSR6:			  00000008:  R_MIPS_HI16	symbol
+# MIPSR6:        c: 24 21 00 00     addiu  $1, $1, 0
+# MIPSR6:			  0000000c:  R_MIPS_LO16	symbol
+# MIPSR6:       10: 7c 2c 00 26     sc     $12, 0($1)
+
+# MICROMIPSR2:   8:  41 a1 00 00    lui  $1, 0
+# MICROMIPSR2:  00000008:  R_MICROMIPS_HI16  symbol
+# MICROMIPSR2:   c:  61 81 b0 00    sc   $12, 0($1)
+# MICROMIPSR2:  0000000c:  R_MICROMIPS_LO16  symbol
+
+# MICROMIPSR6:   8:  3c 01 00 00    lh   $zero, 0($1)
+# MICROMIPSR6:  00000008:  R_MICROMIPS_HI16  symbol
+# MICROMIPSR6:   c:  61 81 b0 00    sc   $12, 0($1)
+# MICROMIPSR6:  0000000c:  R_MICROMIPS_LO16  symbol
+sc $12, symbol
+
+# MIPS:         10:  3c 01 00 00    lui  $1, 0
+# MIPS:         00000010:  R_MIPS_HI16  symbol
+# MIPS:         14:  e0 2c 00 08    sc   $12, 8($1)
+# MIPS:         00000014:  R_MIPS_LO16  symbol
+
+# MIPSR6:       14: 3c 01 00 00     aui    $1, $zero, 0
+# MIPSR6:       00000014:  R_MIPS_HI16	symbol
+# MIPSR6:       18: 24 21 00 08     addiu  $1, $1, 8
+# MIPSR6:       00000018:  R_MIPS_LO16	symbol
+# MIPSR6:       1c: 7c 2c 00 26     sc     $12, 0($1)
+
+# MICROMIPSR2:  10:  41 a1 00 00    lui  $1, 0
+# MICROMIPSR2:  00000010:  R_MICROMIPS_HI16  symbol
+# MICROMIPSR2:  14:  61 81 b0 08    sc   $12, 8($1)
+# MICROMIPSR2:  00000014:  R_MICROMIPS_LO16  symbol
+
+# MICROMIPSR6:  10:  3c 01 00 00    lh   $zero, 0($1)
+# MICROMIPSR6:  00000010:  R_MICROMIPS_HI16  symbol
+# MICROMIPSR6:  14:  61 81 b0 08    sc   $12, 8($1)
+# MICROMIPSR6:  00000014:  R_MICROMIPS_LO16  symbol
+sc $12, symbol + 8




More information about the llvm-commits mailing list