Fix VLDMQ and VSTMQ instructions to use the correct encoding and address modes.

These instructions are only needed for codegen, so I've removed all the
explicit encoding bits for now; they should be set in the same way as the for
VLDMD and VSTMD whenever we add encodings for VFP.  The use of addrmode5
requires that the instructions be custom-selected so that the number of
registers can be set in the AM5Opc value.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99309 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bob Wilson 2010-03-23 18:54:46 +00:00
parent b2dc2df7d2
commit df9a4f0591
4 changed files with 61 additions and 32 deletions

View File

@ -745,7 +745,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
} else {
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQ)).
addReg(SrcReg, getKillRegState(isKill))
.addFrameIndex(FI).addImm(0).addMemOperand(MMO));
.addFrameIndex(FI)
.addImm(ARM_AM::getAM5Opc(ARM_AM::ia, 4))
.addMemOperand(MMO));
}
}
}
@ -793,7 +795,9 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
.addMemOperand(MMO));
} else {
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQ), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO));
.addFrameIndex(FI)
.addImm(ARM_AM::getAM5Opc(ARM_AM::ia, 4))
.addMemOperand(MMO));
}
}
}

View File

@ -1701,6 +1701,35 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
ResNode = SelectARMIndexedLoad(N);
if (ResNode)
return ResNode;
// VLDMQ must be custom-selected for "v2f64 load" to set the AM5Opc value.
if (Subtarget->hasVFP2() &&
N->getValueType(0).getSimpleVT().SimpleTy == MVT::v2f64) {
SDValue Chain = N->getOperand(0);
SDValue AM5Opc =
CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::ia, 4), MVT::i32);
SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
SDValue Ops[] = { N->getOperand(1), AM5Opc, Pred, PredReg, Chain };
return CurDAG->getMachineNode(ARM::VLDMQ, dl, MVT::v2f64, MVT::Other,
Ops, 5);
}
// Other cases are autogenerated.
break;
}
case ISD::STORE: {
// VSTMQ must be custom-selected for "v2f64 store" to set the AM5Opc value.
if (Subtarget->hasVFP2() &&
N->getOperand(1).getValueType().getSimpleVT().SimpleTy == MVT::v2f64) {
SDValue Chain = N->getOperand(0);
SDValue AM5Opc =
CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::ia, 4), MVT::i32);
SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
SDValue Ops[] = { N->getOperand(1), N->getOperand(2),
AM5Opc, Pred, PredReg, Chain };
return CurDAG->getMachineNode(ARM::VSTMQ, dl, MVT::Other, Ops, 6);
}
// Other cases are autogenerated.
break;
}

View File

@ -1503,12 +1503,6 @@ class NI<dag oops, dag iops, InstrItinClass itin, string opc, string asm,
pattern> {
}
class NI4<dag oops, dag iops, InstrItinClass itin, string opc,
string asm, list<dag> pattern>
: NeonXI<oops, iops, AddrMode4, IndexModeNone, itin, opc, asm, "",
pattern> {
}
class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
dag oops, dag iops, InstrItinClass itin,
string opc, string dt, string asm, string cstr, list<dag> pattern>

View File

@ -115,19 +115,20 @@ def h64imm : Operand<i64> {
// NEON load / store instructions
//===----------------------------------------------------------------------===//
// Use vldmia to load a Q register as a D register pair.
// This is equivalent to VLDMD except that it has a Q register operand.
def VLDMQ : NI4<(outs QPR:$dst), (ins addrmode4:$addr), IIC_fpLoadm,
"vldmia", "$addr, ${dst:dregpair}",
[(set QPR:$dst, (v2f64 (load addrmode4:$addr)))]> {
let Inst{27-25} = 0b110;
let Inst{24} = 0; // P bit
let Inst{23} = 1; // U bit
let Inst{20} = 1;
let Inst{11-8} = 0b1011;
}
let mayLoad = 1 in {
// Use vldmia to load a Q register as a D register pair.
// This is equivalent to VLDMD except that it has a Q register operand
// instead of a pair of D registers.
def VLDMQ
: AXDI5<(outs QPR:$dst), (ins addrmode5:$addr, pred:$p),
IndexModeNone, IIC_fpLoadm,
"vldm${addr:submode}${p}\t${addr:base}, ${dst:dregpair}", "", []>;
def VLDMQ_UPD
: AXDI5<(outs QPR:$dst, GPR:$wb), (ins addrmode5:$addr, pred:$p),
IndexModeUpd, IIC_fpLoadm,
"vldm${addr:submode}${p}\t${addr:base}!, ${dst:dregpair}",
"$addr.base = $wb", []>;
// Use vld1 to load a Q register as a D register pair.
// This alternative to VLDMQ allows an alignment to be specified.
// This is equivalent to VLD1q64 except that it has a Q register operand.
@ -140,19 +141,20 @@ def VLD1q_UPD
"${dst:dregpair}, $addr$offset", "$addr.addr = $wb", []>;
} // mayLoad = 1
// Use vstmia to store a Q register as a D register pair.
// This is equivalent to VSTMD except that it has a Q register operand.
def VSTMQ : NI4<(outs), (ins QPR:$src, addrmode4:$addr), IIC_fpStorem,
"vstmia", "$addr, ${src:dregpair}",
[(store (v2f64 QPR:$src), addrmode4:$addr)]> {
let Inst{27-25} = 0b110;
let Inst{24} = 0; // P bit
let Inst{23} = 1; // U bit
let Inst{20} = 0;
let Inst{11-8} = 0b1011;
}
let mayStore = 1 in {
// Use vstmia to store a Q register as a D register pair.
// This is equivalent to VSTMD except that it has a Q register operand
// instead of a pair of D registers.
def VSTMQ
: AXDI5<(outs), (ins QPR:$src, addrmode5:$addr, pred:$p),
IndexModeNone, IIC_fpStorem,
"vstm${addr:submode}${p}\t${addr:base}, ${src:dregpair}", "", []>;
def VSTMQ_UPD
: AXDI5<(outs GPR:$wb), (ins QPR:$src, addrmode5:$addr, pred:$p),
IndexModeUpd, IIC_fpStorem,
"vstm${addr:submode}${p}\t${addr:base}!, ${src:dregpair}",
"$addr.base = $wb", []>;
// Use vst1 to store a Q register as a D register pair.
// This alternative to VSTMQ allows an alignment to be specified.
// This is equivalent to VST1q64 except that it has a Q register operand.