[llvm-commits] [llvm] r144081 - in /llvm/trunk/lib/Target/Mips: MipsCodeEmitter.cpp MipsJITInfo.cpp

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Tue Nov 8 04:47:11 PST 2011


Author: bruno
Date: Tue Nov  8 06:47:11 2011
New Revision: 144081

URL: http://llvm.org/viewvc/llvm-project?rev=144081&view=rev
Log:
This patch handles unaligned loads and stores in Mips JIT. Mips backend
implements unaligned loads and stores with assembler macro-instructions
ulw, usw, ulh, ulhu, ush, and this patch emits corresponding instructions
instead of these macros. Since each unaligned load/store is expanded
into two corresponding loads/stores where offset for second load/store is
modified by +3 (for words) or +1 (for halfwords).

Patch by Petar Jovanovic and Sasa Stankovic.

Modified:
    llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp
    llvm/trunk/lib/Target/Mips/MipsJITInfo.cpp

Modified: llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp?rev=144081&r1=144080&r2=144081&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp Tue Nov  8 06:47:11 2011
@@ -108,6 +108,15 @@
     unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
     unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
     unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const;
+
+    int emitULW(const MachineInstr &MI);
+    int emitUSW(const MachineInstr &MI);
+    int emitULH(const MachineInstr &MI);
+    int emitULHu(const MachineInstr &MI);
+    int emitUSH(const MachineInstr &MI);
+
+    void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc,
+                                                            int Offset) const;
   };
 }
 
@@ -186,9 +195,15 @@
     return MipsRegisterInfo::getRegisterNumbering(MO.getReg());
   else if (MO.isImm())
     return static_cast<unsigned>(MO.getImm());
-  else if (MO.isGlobal())
-    emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true);
-  else if (MO.isSymbol())
+  else if (MO.isGlobal()) {
+    if (MI.getOpcode() == Mips::ULW || MI.getOpcode() == Mips::USW ||
+          MI.getOpcode() == Mips::ULH || MI.getOpcode() == Mips::ULHu)
+      emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 4);
+    else if (MI.getOpcode() == Mips::USH)
+      emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 8);
+    else
+      emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true);
+  } else if (MO.isSymbol())
     emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO));
   else if (MO.isCPI())
     emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO));
@@ -207,6 +222,14 @@
                              const_cast<GlobalValue *>(GV), 0, MayNeedFarStub));
 }
 
+void MipsCodeEmitter::emitGlobalAddressUnaligned(const GlobalValue *GV,
+                                           unsigned Reloc, int Offset) const {
+  MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
+                             const_cast<GlobalValue *>(GV), 0, false));
+  MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset() + Offset,
+                      Reloc, const_cast<GlobalValue *>(GV), 0, false));
+}
+
 void MipsCodeEmitter::
 emitExternalSymbolAddress(const char *ES, unsigned Reloc) const {
   MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
@@ -230,6 +253,103 @@
                                              Reloc, BB));
 }
 
+int MipsCodeEmitter::emitUSW(const MachineInstr &MI) {
+  unsigned src = getMachineOpValue(MI, MI.getOperand(0));
+  unsigned base = getMachineOpValue(MI, MI.getOperand(1));
+  unsigned offset = getMachineOpValue(MI, MI.getOperand(2));
+  // swr src, offset(base)
+  // swl src, offset+3(base)
+  MCE.emitWordLE(
+    (0x2e << 26) | (base << 21) | (src << 16) | (offset & 0xffff));
+  MCE.emitWordLE(
+    (0x2a << 26) | (base << 21) | (src << 16) | ((offset+3) & 0xffff));
+  return 2;
+}
+
+int MipsCodeEmitter::emitULW(const MachineInstr &MI) {
+  unsigned dst = getMachineOpValue(MI, MI.getOperand(0));
+  unsigned base = getMachineOpValue(MI, MI.getOperand(1));
+  unsigned offset = getMachineOpValue(MI, MI.getOperand(2));
+  unsigned at = 1;
+  if (dst != base) {
+    // lwr dst, offset(base)
+    // lwl dst, offset+3(base)
+    MCE.emitWordLE(
+      (0x26 << 26) | (base << 21) | (dst << 16) | (offset & 0xffff));
+    MCE.emitWordLE(
+      (0x22 << 26) | (base << 21) | (dst << 16) | ((offset+3) & 0xffff));
+    return 2;
+  } else {
+    // lwr at, offset(base)
+    // lwl at, offset+3(base)
+    // addu dst, at, $zero
+    MCE.emitWordLE(
+      (0x26 << 26) | (base << 21) | (at << 16) | (offset & 0xffff));
+    MCE.emitWordLE(
+      (0x22 << 26) | (base << 21) | (at << 16) | ((offset+3) & 0xffff));
+    MCE.emitWordLE(
+      (0x0 << 26) | (at << 21) | (0x0 << 16) | (dst << 11) | (0x0 << 6) | 0x21);
+    return 3;
+  }
+}
+
+int MipsCodeEmitter::emitUSH(const MachineInstr &MI) {
+  unsigned src = getMachineOpValue(MI, MI.getOperand(0));
+  unsigned base = getMachineOpValue(MI, MI.getOperand(1));
+  unsigned offset = getMachineOpValue(MI, MI.getOperand(2));
+  unsigned at = 1;
+  // sb src, offset(base)
+  // srl at,src,8
+  // sb at, offset+1(base)
+  MCE.emitWordLE(
+    (0x28 << 26) | (base << 21) | (src << 16) | (offset & 0xffff));
+  MCE.emitWordLE(
+    (0x0 << 26) | (0x0 << 21) | (src << 16) | (at << 11) | (0x8 << 6) | 0x2);
+  MCE.emitWordLE(
+    (0x28 << 26) | (base << 21) | (at << 16) | ((offset+1) & 0xffff));
+  return 3;
+}
+
+int MipsCodeEmitter::emitULH(const MachineInstr &MI) {
+  unsigned dst = getMachineOpValue(MI, MI.getOperand(0));
+  unsigned base = getMachineOpValue(MI, MI.getOperand(1));
+  unsigned offset = getMachineOpValue(MI, MI.getOperand(2));
+  unsigned at = 1;
+  // lbu at, offset(base)
+  // lb dst, offset+1(base)
+  // sll dst,dst,8
+  // or dst,dst,at
+  MCE.emitWordLE(
+    (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff));
+  MCE.emitWordLE(
+    (0x20 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff));
+  MCE.emitWordLE(
+    (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0);
+  MCE.emitWordLE(
+    (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25);
+  return 4;
+}
+
+int MipsCodeEmitter::emitULHu(const MachineInstr &MI) {
+  unsigned dst = getMachineOpValue(MI, MI.getOperand(0));
+  unsigned base = getMachineOpValue(MI, MI.getOperand(1));
+  unsigned offset = getMachineOpValue(MI, MI.getOperand(2));
+  unsigned at = 1;
+  // lbu at, offset(base)
+  // lbu dst, offset+1(base)
+  // sll dst,dst,8
+  // or dst,dst,at
+  MCE.emitWordLE(
+    (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff));
+  MCE.emitWordLE(
+    (0x24 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff));
+  MCE.emitWordLE(
+    (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0);
+  MCE.emitWordLE(
+    (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25);
+  return 4;
+}
+
 void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) {
   DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI);
 
@@ -239,11 +359,27 @@
   if ((MI.getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo)
     return;
 
-  ++NumEmitted;  // Keep track of the # of mi's emitted
 
   switch (MI.getOpcode()) {
+  case Mips::USW:
+    NumEmitted += emitUSW(MI);
+    break;
+  case Mips::ULW:
+    NumEmitted += emitULW(MI);
+    break;
+  case Mips::ULH:
+    NumEmitted += emitULH(MI);
+    break;
+  case Mips::ULHu:
+    NumEmitted += emitULHu(MI);
+    break;
+  case Mips::USH:
+    NumEmitted += emitUSH(MI);
+    break;
+
   default:
     emitWordLE(getBinaryCodeForInstr(MI));
+    ++NumEmitted;  // Keep track of the # of mi's emitted
     break;
   }
 

Modified: llvm/trunk/lib/Target/Mips/MipsJITInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsJITInfo.cpp?rev=144081&r1=144080&r2=144081&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsJITInfo.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsJITInfo.cpp Tue Nov  8 06:47:11 2011
@@ -218,10 +218,16 @@
       *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
       break;
 
-    case Mips::reloc_mips_lo:
-      ResultPtr = ResultPtr & 0xffff;
+    case Mips::reloc_mips_lo: {
+      // Addend is needed for unaligned load/store instructions, where offset
+      // for the second load/store in the expanded instruction sequence must
+      // be modified by +1 or +3. Otherwise, Addend is 0.
+      int Addend = *((unsigned*) RelocPos) & 0xffff;
+      ResultPtr = (ResultPtr + Addend) & 0xffff;
+      *((unsigned*) RelocPos) &= 0xffff0000;
       *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
       break;
+    }
 
     default:
       llvm_unreachable("ERROR: Unknown Mips relocation.");





More information about the llvm-commits mailing list