Add support for half-word unaligned loads and stores.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137848 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 28358ab..9b7e191 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -77,17 +77,28 @@
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);
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index eb049f1..2ac7a26 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -218,8 +218,8 @@
}
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 {
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index a30761d..e41c78a 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -483,12 +483,18 @@
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