summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsMCInstLower.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanak@gmail.com>2011-08-16 03:51:51 +0000
committerAkira Hatanaka <ahatanak@gmail.com>2011-08-16 03:51:51 +0000
commit614051a1c534aff052152b0162a414b3271e8fca (patch)
tree019e11b687f2e95ffdc968669d1f325272883b90 /lib/Target/Mips/MipsMCInstLower.cpp
parent8957481e6a3a4217499f739bae24401576ade078 (diff)
downloadllvm-614051a1c534aff052152b0162a414b3271e8fca.tar.gz
llvm-614051a1c534aff052152b0162a414b3271e8fca.tar.bz2
llvm-614051a1c534aff052152b0162a414b3271e8fca.tar.xz
Fix handling of double precision loads and stores when Mips1 is targeted.
Mips1 does not support double precision loads or stores, therefore two single precision loads or stores must be used in place of these instructions. This patch treats double precision loads and stores as if they are legal instructions until MCInstLowering, instead of generating the single precision instructions during instruction selection or Prolog/Epilog code insertion. Without the changes made in this patch, llc produces code that has the same problem described in r137484 or bails out when MipsInstrInfo::storeRegToStackSlot or loadRegFromStackSlot is called before register allocation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137711 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Mips/MipsMCInstLower.cpp')
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index 16ec41ef51..58e1844305 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -83,6 +83,50 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
Ctx));
}
+// If target is Mips1, expand double precision load/store to two single
+// precision loads/stores.
+//
+// ldc1 $f0, lo($CPI0_0)($5) gets expanded to the following two instructions:
+// (little endian)
+// lwc1 $f0, lo($CPI0_0)($5) and
+// lwc1 $f1, lo($CPI0_0+4)($5)
+// (big endian)
+// lwc1 $f1, lo($CPI0_0)($5) and
+// lwc1 $f0, lo($CPI0_0+4)($5)
+void MipsMCInstLower::LowerMips1F64LoadStore(const MachineInstr *MI,
+ unsigned Opc,
+ SmallVector<MCInst, 4>& MCInsts,
+ bool isLittle,
+ const unsigned *SubReg) const {
+ MCInst InstLo, InstHi, DelaySlot;
+ unsigned SingleOpc = (Opc == Mips::LDC1 ? Mips::LWC1 : Mips::SWC1);
+ unsigned RegLo = isLittle ? *SubReg : *(SubReg + 1);
+ unsigned RegHi = isLittle ? *(SubReg + 1) : *SubReg;
+ const MachineOperand &MO1 = MI->getOperand(1);
+ const MachineOperand &MO2 = MI->getOperand(2);
+
+ InstLo.setOpcode(SingleOpc);
+ InstLo.addOperand(MCOperand::CreateReg(RegLo));
+ InstLo.addOperand(LowerOperand(MO1));
+ InstLo.addOperand(LowerOperand(MO2));
+ MCInsts.push_back(InstLo);
+
+ InstHi.setOpcode(SingleOpc);
+ InstHi.addOperand(MCOperand::CreateReg(RegHi));
+ InstHi.addOperand(LowerOperand(MO1));
+ if (MO2.isImm())// The offset of addr operand is an immediate: e.g. 0($sp)
+ InstHi.addOperand(MCOperand::CreateImm(MO2.getImm() + 4));
+ else// Otherwise, the offset must be a symbol: e.g. lo($CPI0_0)($5)
+ InstHi.addOperand(LowerSymbolOperand(MO2, MO2.getType(), 4));
+ MCInsts.push_back(InstHi);
+
+ // Need to insert a NOP in LWC1's delay slot.
+ if (SingleOpc == Mips::LWC1) {
+ DelaySlot.setOpcode(Mips::NOP);
+ MCInsts.push_back(DelaySlot);
+ }
+}
+
MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const {
MachineOperandType MOTy = MO.getType();