OSDN Git Service

Add support for half-word unaligned loads and stores.
authorAkira Hatanaka <ahatanak@gmail.com>
Wed, 17 Aug 2011 18:49:18 +0000 (18:49 +0000)
committerAkira Hatanaka <ahatanak@gmail.com>
Wed, 17 Aug 2011 18:49:18 +0000 (18:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137848 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsISelLowering.cpp
lib/Target/Mips/MipsInstrInfo.td

index 28358ab..9b7e191 100644 (file)
@@ -77,17 +77,28 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
   MCInstLowering.Lower(MI, TmpInst0);
   
   // Convert aligned loads/stores to their unaligned counterparts.
-  // FIXME: expand other unaligned memory accesses too.
-  if ((Opc == Mips::LW || Opc == Mips::SW) && !MI->memoperands_empty() &&
-      (*MI->memoperands_begin())->getAlignment() < 4) {
-    MCInst Directive;
-    Directive.setOpcode(Mips::MACRO);
-    OutStreamer.EmitInstruction(Directive);
-    TmpInst0.setOpcode(Opc == Mips::LW ? Mips::ULW : Mips::USW);
-    OutStreamer.EmitInstruction(TmpInst0);
-    Directive.setOpcode(Mips::NOMACRO);
-    OutStreamer.EmitInstruction(Directive);
-    return;
+  if (!MI->memoperands_empty()) {
+    unsigned NaturalAlignment, UnalignedOpc;
+    
+    switch (Opc) {
+    case Mips::LW:  NaturalAlignment = 4; UnalignedOpc = Mips::ULW;  break;
+    case Mips::SW:  NaturalAlignment = 4; UnalignedOpc = Mips::USW;  break;
+    case Mips::LH:  NaturalAlignment = 2; UnalignedOpc = Mips::ULH;  break;
+    case Mips::LHu: NaturalAlignment = 2; UnalignedOpc = Mips::ULHu; break;
+    case Mips::SH:  NaturalAlignment = 2; UnalignedOpc = Mips::USH;  break;
+    default:        NaturalAlignment = 0;
+    }
+
+    if ((*MI->memoperands_begin())->getAlignment() < NaturalAlignment) {
+      MCInst Directive;
+      Directive.setOpcode(Mips::MACRO);
+      OutStreamer.EmitInstruction(Directive);
+      TmpInst0.setOpcode(UnalignedOpc);
+      OutStreamer.EmitInstruction(TmpInst0);
+      Directive.setOpcode(Mips::NOMACRO);
+      OutStreamer.EmitInstruction(Directive);
+      return;
+    }
   }
 
   OutStreamer.EmitInstruction(TmpInst0);
index eb049f1..2ac7a26 100644 (file)
@@ -218,8 +218,8 @@ MipsTargetLowering(MipsTargetMachine &TM)
 }
 
 bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const {
-  // FIXME: allow unaligned memory accesses for other types too.
-  return VT.getSimpleVT().SimpleTy == MVT::i32
+  MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
+  return SVT == MVT::i32 || SVT == MVT::i16
 }
 
 MVT::SimpleValueType MipsTargetLowering::getSetCCResultType(EVT VT) const {
index a30761d..e41c78a 100644 (file)
@@ -483,12 +483,18 @@ let usesCustomInserter = 1 in {
   def ATOMIC_CMP_SWAP_I32  : AtomicCmpSwap<atomic_cmp_swap_32, "32">;
 }
 
-// Unaligned memory load and store.
+// Unaligned loads and stores.
 // Replaces LW or SW during MCInstLowering if memory access is unaligned.
 def ULW :
   MipsPseudo<(outs CPURegs:$dst), (ins mem:$addr), "ulw\t$dst, $addr", []>;
+def ULH :
+  MipsPseudo<(outs CPURegs:$dst), (ins mem:$addr), "ulh\t$dst, $addr", []>;
+def ULHu :
+  MipsPseudo<(outs CPURegs:$dst), (ins mem:$addr), "ulhu\t$dst, $addr", []>;
 def USW : 
   MipsPseudo<(outs), (ins CPURegs:$dst, mem:$addr), "usw\t$dst, $addr", []>;
+def USH : 
+  MipsPseudo<(outs), (ins CPURegs:$dst, mem:$addr), "ush\t$dst, $addr", []>;
 
 //===----------------------------------------------------------------------===//
 // Instruction definition