mirror of
https://github.com/RPCSX/llvm.git
synced 2025-03-05 03:19:11 +00:00
Convert load/store over to being pattern matched
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24871 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
898101c15f
commit
7fd1edd32e
@ -181,7 +181,19 @@ namespace {
|
||||
unsigned RegNo = enumRegToMachineReg(CCReg);
|
||||
O << (0x80 >> RegNo);
|
||||
}
|
||||
|
||||
// The new addressing mode printers, currently empty
|
||||
void printMemRegImm(const MachineInstr *MI, unsigned OpNo) {
|
||||
printSymbolLo(MI, OpNo);
|
||||
O << '(';
|
||||
printOperand(MI, OpNo+1);
|
||||
O << ')';
|
||||
}
|
||||
void printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
|
||||
printOperand(MI, OpNo);
|
||||
O << ", ";
|
||||
printOperand(MI, OpNo+1);
|
||||
}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &F) = 0;
|
||||
virtual bool doFinalization(Module &M) = 0;
|
||||
};
|
||||
|
@ -68,15 +68,18 @@ namespace {
|
||||
/// specified condition code, returning the CR# of the expression.
|
||||
SDOperand SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC);
|
||||
|
||||
/// SelectAddr - Given the specified address, return the two operands for a
|
||||
/// load/store instruction, and return true if it should be an indexed [r+r]
|
||||
/// operation.
|
||||
bool SelectAddr(SDOperand Addr, SDOperand &Op1, SDOperand &Op2);
|
||||
/// SelectAddrImm - Returns true if the address N can be represented by
|
||||
/// a base register plus a signed 16-bit displacement [r+imm].
|
||||
bool SelectAddrImm(SDOperand N, SDOperand &Disp, SDOperand &Base);
|
||||
|
||||
/// SelectAddrIdx - Given the specified addressed, check to see if it can be
|
||||
/// represented as an indexed [r+r] operation. Returns false if it can
|
||||
/// be represented by [r+imm], which are preferred.
|
||||
bool SelectAddrIdx(SDOperand N, SDOperand &Base, SDOperand &Index);
|
||||
|
||||
/// SelectAddrIndexed - Given the specified addressed, force it to be
|
||||
/// represented as an indexed [r+r] operation, rather than possibly
|
||||
/// returning [r+imm] as SelectAddr may.
|
||||
void SelectAddrIndexed(SDOperand Addr, SDOperand &Op1, SDOperand &Op2);
|
||||
/// SelectAddrIdxOnly - Given the specified addressed, force it to be
|
||||
/// represented as an indexed [r+r] operation.
|
||||
bool SelectAddrIdxOnly(SDOperand N, SDOperand &Base, SDOperand &Index);
|
||||
|
||||
SDOperand BuildSDIVSequence(SDNode *N);
|
||||
SDOperand BuildUDIVSequence(SDNode *N);
|
||||
@ -400,65 +403,77 @@ SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// SelectAddr - Given the specified address, return the two operands for a
|
||||
/// load/store instruction, and return true if it should be an indexed [r+r]
|
||||
/// operation.
|
||||
bool PPCDAGToDAGISel::SelectAddr(SDOperand Addr, SDOperand &Op1,
|
||||
SDOperand &Op2) {
|
||||
unsigned imm = 0;
|
||||
if (Addr.getOpcode() == ISD::ADD) {
|
||||
if (isIntImmediate(Addr.getOperand(1), imm) && isInt16(imm)) {
|
||||
Op1 = getI32Imm(Lo16(imm));
|
||||
if (FrameIndexSDNode *FI =
|
||||
dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
|
||||
++FrameOff;
|
||||
Op2 = CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
|
||||
/// SelectAddrImm - Returns true if the address N can be represented by
|
||||
/// a base register plus a signed 16-bit displacement [r+imm].
|
||||
bool PPCDAGToDAGISel::SelectAddrImm(SDOperand N, SDOperand &Disp,
|
||||
SDOperand &Base) {
|
||||
if (N.getOpcode() == ISD::ADD) {
|
||||
unsigned imm = 0;
|
||||
if (isIntImmediate(N.getOperand(1), imm) && isInt16(imm)) {
|
||||
Disp = getI32Imm(Lo16(imm));
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
|
||||
Base = CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
|
||||
} else {
|
||||
Op2 = Select(Addr.getOperand(0));
|
||||
Base = Select(N.getOperand(0));
|
||||
}
|
||||
return false;
|
||||
} else if (Addr.getOperand(1).getOpcode() == PPCISD::Lo) {
|
||||
return true; // [r+i]
|
||||
} else if (N.getOperand(1).getOpcode() == PPCISD::Lo) {
|
||||
// Match LOAD (ADD (X, Lo(G))).
|
||||
assert(!cast<ConstantSDNode>(Addr.getOperand(1).getOperand(1))->getValue()
|
||||
assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue()
|
||||
&& "Cannot handle constant offsets yet!");
|
||||
Op1 = Addr.getOperand(1).getOperand(0); // The global address.
|
||||
assert(Op1.getOpcode() == ISD::TargetGlobalAddress ||
|
||||
Op1.getOpcode() == ISD::TargetConstantPool);
|
||||
Op2 = Select(Addr.getOperand(0));
|
||||
return false; // [&g+r]
|
||||
} else {
|
||||
Op1 = Select(Addr.getOperand(0));
|
||||
Op2 = Select(Addr.getOperand(1));
|
||||
return true; // [r+r]
|
||||
Disp = N.getOperand(1).getOperand(0); // The global address.
|
||||
assert(Disp.getOpcode() == ISD::TargetGlobalAddress ||
|
||||
Disp.getOpcode() == ISD::TargetConstantPool);
|
||||
Base = Select(N.getOperand(0));
|
||||
return true; // [&g+r]
|
||||
}
|
||||
return false; // [r+r]
|
||||
}
|
||||
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Addr))
|
||||
Op2 = CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
|
||||
Disp = getI32Imm(0);
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N))
|
||||
Base = CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
|
||||
else
|
||||
Op2 = Select(Addr);
|
||||
Op1 = getI32Imm(0);
|
||||
return false;
|
||||
Base = Select(N);
|
||||
return true; // [r+0]
|
||||
}
|
||||
|
||||
/// SelectAddrIndexed - Given the specified addressed, force it to be
|
||||
/// represented as an indexed [r+r] operation, rather than possibly
|
||||
/// returning [r+imm] as SelectAddr may.
|
||||
void PPCDAGToDAGISel::SelectAddrIndexed(SDOperand Addr, SDOperand &Op1,
|
||||
SDOperand &Op2) {
|
||||
if (Addr.getOpcode() == ISD::ADD) {
|
||||
Op1 = Select(Addr.getOperand(0));
|
||||
Op2 = Select(Addr.getOperand(1));
|
||||
return;
|
||||
/// SelectAddrIdx - Given the specified addressed, check to see if it can be
|
||||
/// represented as an indexed [r+r] operation. Returns false if it can
|
||||
/// be represented by [r+imm], which are preferred.
|
||||
bool PPCDAGToDAGISel::SelectAddrIdx(SDOperand N, SDOperand &Base,
|
||||
SDOperand &Index) {
|
||||
// Check to see if we can represent this as an [r+imm] address instead,
|
||||
// which will fail if the address is more profitably represented as an
|
||||
// [r+r] address.
|
||||
if (SelectAddrImm(N, Base, Index))
|
||||
return false;
|
||||
|
||||
if (N.getOpcode() == ISD::ADD) {
|
||||
Base = Select(N.getOperand(0));
|
||||
Index = Select(N.getOperand(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: This should be a CopyFromReg R0 rather than a load of 0.
|
||||
Base = CurDAG->getTargetNode(PPC::LI, MVT::i32, getI32Imm(0));
|
||||
Index = Select(N);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// SelectAddrIdxOnly - Given the specified addressed, force it to be
|
||||
/// represented as an indexed [r+r] operation.
|
||||
bool PPCDAGToDAGISel::SelectAddrIdxOnly(SDOperand N, SDOperand &Base,
|
||||
SDOperand &Index) {
|
||||
if (N.getOpcode() == ISD::ADD) {
|
||||
Base = Select(N.getOperand(0));
|
||||
Index = Select(N.getOperand(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Addr)) {
|
||||
Op1 = CurDAG->getTargetNode(PPC::LI, MVT::i32, getI32Imm(0));
|
||||
Op2 = CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32);
|
||||
return;
|
||||
}
|
||||
Op1 = CurDAG->getTargetNode(PPC::LI, MVT::i32, getI32Imm(0));
|
||||
Op2 = Select(Addr);
|
||||
// FIXME: This should be a CopyFromReg R0 rather than a load of 0.
|
||||
Base = CurDAG->getTargetNode(PPC::LI, MVT::i32, getI32Imm(0));
|
||||
Index = Select(N);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// SelectCC - Select a comparison of the specified values with the specified
|
||||
@ -997,95 +1012,6 @@ SDOperand PPCDAGToDAGISel::Select(SDOperand Op) {
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
}
|
||||
case ISD::LOAD:
|
||||
case ISD::EXTLOAD:
|
||||
case ISD::ZEXTLOAD:
|
||||
case ISD::SEXTLOAD: {
|
||||
SDOperand Op1, Op2;
|
||||
// If this is a vector load, then force this to be indexed addressing, since
|
||||
// altivec does not have immediate offsets for loads.
|
||||
bool isIdx = true;
|
||||
if (N->getOpcode() == ISD::LOAD && MVT::isVector(N->getValueType(0))) {
|
||||
SelectAddrIndexed(N->getOperand(1), Op1, Op2);
|
||||
} else {
|
||||
isIdx = SelectAddr(N->getOperand(1), Op1, Op2);
|
||||
}
|
||||
MVT::ValueType TypeBeingLoaded = (N->getOpcode() == ISD::LOAD) ?
|
||||
N->getValueType(0) : cast<VTSDNode>(N->getOperand(3))->getVT();
|
||||
|
||||
unsigned Opc;
|
||||
switch (TypeBeingLoaded) {
|
||||
default: N->dump(); assert(0 && "Cannot load this type!");
|
||||
case MVT::i1:
|
||||
case MVT::i8: Opc = isIdx ? PPC::LBZX : PPC::LBZ; break;
|
||||
case MVT::i16:
|
||||
if (N->getOpcode() == ISD::SEXTLOAD) { // SEXT load?
|
||||
Opc = isIdx ? PPC::LHAX : PPC::LHA;
|
||||
} else {
|
||||
Opc = isIdx ? PPC::LHZX : PPC::LHZ;
|
||||
}
|
||||
break;
|
||||
case MVT::i32: Opc = isIdx ? PPC::LWZX : PPC::LWZ; break;
|
||||
case MVT::f32: Opc = isIdx ? PPC::LFSX : PPC::LFS; break;
|
||||
case MVT::f64: Opc = isIdx ? PPC::LFDX : PPC::LFD; break;
|
||||
case MVT::v4f32: Opc = PPC::LVX; break;
|
||||
}
|
||||
|
||||
// If this is an f32 -> f64 load, emit the f32 load, then use an 'extending
|
||||
// copy'.
|
||||
if (TypeBeingLoaded != MVT::f32 || N->getOpcode() == ISD::LOAD) {
|
||||
return CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other,
|
||||
Op1, Op2, Select(N->getOperand(0))).
|
||||
getValue(Op.ResNo);
|
||||
} else {
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Op1);
|
||||
Ops.push_back(Op2);
|
||||
Ops.push_back(Select(N->getOperand(0)));
|
||||
SDOperand Res = CurDAG->getTargetNode(Opc, MVT::f32, MVT::Other, Ops);
|
||||
SDOperand Ext = CurDAG->getTargetNode(PPC::FMRSD, MVT::f64, Res);
|
||||
CodeGenMap[Op.getValue(0)] = Ext;
|
||||
CodeGenMap[Op.getValue(1)] = Res.getValue(1);
|
||||
if (Op.ResNo)
|
||||
return Res.getValue(1);
|
||||
else
|
||||
return Ext;
|
||||
}
|
||||
}
|
||||
case ISD::TRUNCSTORE:
|
||||
case ISD::STORE: {
|
||||
SDOperand AddrOp1, AddrOp2;
|
||||
// If this is a vector store, then force this to be indexed addressing,
|
||||
// since altivec does not have immediate offsets for stores.
|
||||
bool isIdx = true;
|
||||
if (N->getOpcode() == ISD::STORE &&
|
||||
MVT::isVector(N->getOperand(1).getValueType())) {
|
||||
SelectAddrIndexed(N->getOperand(2), AddrOp1, AddrOp2);
|
||||
} else {
|
||||
isIdx = SelectAddr(N->getOperand(2), AddrOp1, AddrOp2);
|
||||
}
|
||||
|
||||
unsigned Opc;
|
||||
if (N->getOpcode() == ISD::STORE) {
|
||||
switch (N->getOperand(1).getValueType()) {
|
||||
default: assert(0 && "unknown Type in store");
|
||||
case MVT::i32: Opc = isIdx ? PPC::STWX : PPC::STW; break;
|
||||
case MVT::f64: Opc = isIdx ? PPC::STFDX : PPC::STFD; break;
|
||||
case MVT::f32: Opc = isIdx ? PPC::STFSX : PPC::STFS; break;
|
||||
case MVT::v4f32: Opc = PPC::STVX;
|
||||
}
|
||||
} else { //ISD::TRUNCSTORE
|
||||
switch(cast<VTSDNode>(N->getOperand(4))->getVT()) {
|
||||
default: assert(0 && "unknown Type in store");
|
||||
case MVT::i8: Opc = isIdx ? PPC::STBX : PPC::STB; break;
|
||||
case MVT::i16: Opc = isIdx ? PPC::STHX : PPC::STH; break;
|
||||
}
|
||||
}
|
||||
|
||||
return CurDAG->SelectNodeTo(N, Opc, MVT::Other, Select(N->getOperand(1)),
|
||||
AddrOp1, AddrOp2, Select(N->getOperand(0)));
|
||||
}
|
||||
|
||||
case ISD::SELECT_CC: {
|
||||
ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();
|
||||
|
||||
|
@ -126,6 +126,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
|
||||
// FIXME: AltiVec supports a wide variety of packed types. For now, we're
|
||||
// bringing up support with just v4f32.
|
||||
addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass);
|
||||
addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass);
|
||||
}
|
||||
|
||||
setSetCCResultContents(ZeroOrOneSetCCResult);
|
||||
|
@ -165,6 +165,22 @@ def symbolLo: Operand<i32> {
|
||||
def crbitm: Operand<i8> {
|
||||
let PrintMethod = "printcrbitm";
|
||||
}
|
||||
// Address operands
|
||||
def memri : Operand<i32> {
|
||||
let PrintMethod = "printMemRegImm";
|
||||
let NumMIOperands = 2;
|
||||
let MIOperandInfo = (ops i32imm, GPRC);
|
||||
}
|
||||
def memrr : Operand<i32> {
|
||||
let PrintMethod = "printMemRegReg";
|
||||
let NumMIOperands = 2;
|
||||
let MIOperandInfo = (ops GPRC, GPRC);
|
||||
}
|
||||
|
||||
// Define X86 specific addressing mode.
|
||||
def iaddr : ComplexPattern<i32, 2, "SelectAddrImm", []>;
|
||||
def xaddr : ComplexPattern<i32, 2, "SelectAddrIdx", []>;
|
||||
def xoaddr : ComplexPattern<i32, 2, "SelectAddrIdxOnly",[]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PowerPC Instruction Predicate Definitions.
|
||||
@ -258,21 +274,21 @@ let isCall = 1,
|
||||
// register and an immediate are of this type.
|
||||
//
|
||||
let isLoad = 1 in {
|
||||
def LBZ : DForm_1<34, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
|
||||
"lbz $rD, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
def LHA : DForm_1<42, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
|
||||
"lha $rD, $disp($rA)", LdStLHA,
|
||||
[]>;
|
||||
def LHZ : DForm_1<40, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
|
||||
"lhz $rD, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
def LBZ : DForm_1<34, (ops GPRC:$rD, memri:$src),
|
||||
"lbz $rD, $src", LdStGeneral,
|
||||
[(set GPRC:$rD, (zextload iaddr:$src, i8))]>;
|
||||
def LHA : DForm_1<42, (ops GPRC:$rD, memri:$src),
|
||||
"lha $rD, $src", LdStLHA,
|
||||
[(set GPRC:$rD, (sextload iaddr:$src, i16))]>;
|
||||
def LHZ : DForm_1<40, (ops GPRC:$rD, memri:$src),
|
||||
"lhz $rD, $src", LdStGeneral,
|
||||
[(set GPRC:$rD, (zextload iaddr:$src, i16))]>;
|
||||
def LMW : DForm_1<46, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
|
||||
"lmw $rD, $disp($rA)", LdStLMW,
|
||||
[]>;
|
||||
def LWZ : DForm_1<32, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
|
||||
"lwz $rD, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
def LWZ : DForm_1<32, (ops GPRC:$rD, memri:$src),
|
||||
"lwz $rD, $src", LdStGeneral,
|
||||
[(set GPRC:$rD, (load iaddr:$src))]>;
|
||||
def LWZU : DForm_1<35, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
|
||||
"lwzu $rD, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
@ -309,15 +325,15 @@ let isStore = 1 in {
|
||||
def STMW : DForm_3<47, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
|
||||
"stmw $rS, $disp($rA)", LdStLMW,
|
||||
[]>;
|
||||
def STB : DForm_3<38, (ops GPRC:$rS, symbolLo:$disp, GPRC:$rA),
|
||||
"stb $rS, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
def STH : DForm_3<44, (ops GPRC:$rS, symbolLo:$disp, GPRC:$rA),
|
||||
"sth $rS, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
def STW : DForm_3<36, (ops GPRC:$rS, symbolLo:$disp, GPRC:$rA),
|
||||
"stw $rS, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
def STB : DForm_3<38, (ops GPRC:$rS, memri:$src),
|
||||
"stb $rS, $src", LdStGeneral,
|
||||
[(truncstore GPRC:$rS, iaddr:$src, i8)]>;
|
||||
def STH : DForm_3<44, (ops GPRC:$rS, memri:$src),
|
||||
"sth $rS, $src", LdStGeneral,
|
||||
[(truncstore GPRC:$rS, iaddr:$src, i16)]>;
|
||||
def STW : DForm_3<36, (ops GPRC:$rS, memri:$src),
|
||||
"stw $rS, $src", LdStGeneral,
|
||||
[(store GPRC:$rS, iaddr:$src)]>;
|
||||
def STWU : DForm_3<37, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
|
||||
"stwu $rS, $disp($rA)", LdStGeneral,
|
||||
[]>;
|
||||
@ -355,20 +371,20 @@ def CMPLWI : DForm_6_ext<10, (ops CRRC:$dst, GPRC:$src1, u16imm:$src2),
|
||||
def CMPLDI : DForm_6_ext<10, (ops CRRC:$dst, GPRC:$src1, u16imm:$src2),
|
||||
"cmpldi $dst, $src1, $src2", IntCompare>, isPPC64;
|
||||
let isLoad = 1 in {
|
||||
def LFS : DForm_8<48, (ops F4RC:$rD, symbolLo:$disp, GPRC:$rA),
|
||||
"lfs $rD, $disp($rA)", LdStLFDU,
|
||||
[]>;
|
||||
def LFD : DForm_8<50, (ops F8RC:$rD, symbolLo:$disp, GPRC:$rA),
|
||||
"lfd $rD, $disp($rA)", LdStLFD,
|
||||
[]>;
|
||||
def LFS : DForm_8<48, (ops F4RC:$rD, memri:$src),
|
||||
"lfs $rD, $src", LdStLFDU,
|
||||
[(set F4RC:$rD, (load iaddr:$src))]>;
|
||||
def LFD : DForm_8<50, (ops F8RC:$rD, memri:$src),
|
||||
"lfd $rD, $src", LdStLFD,
|
||||
[(set F8RC:$rD, (load iaddr:$src))]>;
|
||||
}
|
||||
let isStore = 1 in {
|
||||
def STFS : DForm_9<52, (ops F4RC:$rS, symbolLo:$disp, GPRC:$rA),
|
||||
"stfs $rS, $disp($rA)", LdStUX,
|
||||
[]>;
|
||||
def STFD : DForm_9<54, (ops F8RC:$rS, symbolLo:$disp, GPRC:$rA),
|
||||
"stfd $rS, $disp($rA)", LdStUX,
|
||||
[]>;
|
||||
def STFS : DForm_9<52, (ops F4RC:$rS, memri:$dst),
|
||||
"stfs $rS, $dst", LdStUX,
|
||||
[(store F4RC:$rS, iaddr:$dst)]>;
|
||||
def STFD : DForm_9<54, (ops F8RC:$rS, memri:$dst),
|
||||
"stfd $rS, $dst", LdStUX,
|
||||
[(store F8RC:$rS, iaddr:$dst)]>;
|
||||
}
|
||||
|
||||
// DS-Form instructions. Load/Store instructions available in PPC-64
|
||||
@ -394,24 +410,24 @@ def STDU : DSForm_2<62, 1, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
|
||||
// register and another register are of this type.
|
||||
//
|
||||
let isLoad = 1 in {
|
||||
def LBZX : XForm_1<31, 87, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lbzx $dst, $base, $index", LdStGeneral,
|
||||
[]>;
|
||||
def LHAX : XForm_1<31, 343, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lhax $dst, $base, $index", LdStLHA,
|
||||
[]>;
|
||||
def LHZX : XForm_1<31, 279, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lhzx $dst, $base, $index", LdStGeneral,
|
||||
[]>;
|
||||
def LWAX : XForm_1<31, 341, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lwax $dst, $base, $index", LdStLHA,
|
||||
[]>, isPPC64;
|
||||
def LWZX : XForm_1<31, 23, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lwzx $dst, $base, $index", LdStGeneral,
|
||||
[]>;
|
||||
def LDX : XForm_1<31, 21, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
|
||||
"ldx $dst, $base, $index", LdStLD,
|
||||
[]>, isPPC64;
|
||||
def LBZX : XForm_1<31, 87, (ops GPRC:$rD, memrr:$src),
|
||||
"lbzx $rD, $src", LdStGeneral,
|
||||
[(set GPRC:$rD, (zextload xaddr:$src, i8))]>;
|
||||
def LHAX : XForm_1<31, 343, (ops GPRC:$rD, memrr:$src),
|
||||
"lhax $rD, $src", LdStLHA,
|
||||
[(set GPRC:$rD, (sextload xaddr:$src, i16))]>;
|
||||
def LHZX : XForm_1<31, 279, (ops GPRC:$rD, memrr:$src),
|
||||
"lhzx $rD, $src", LdStGeneral,
|
||||
[(set GPRC:$rD, (zextload xaddr:$src, i16))]>;
|
||||
def LWAX : XForm_1<31, 341, (ops G8RC:$rD, memrr:$src),
|
||||
"lwax $rD, $src", LdStLHA,
|
||||
[(set G8RC:$rD, (sextload xaddr:$src, i32))]>, isPPC64;
|
||||
def LWZX : XForm_1<31, 23, (ops GPRC:$rD, memrr:$src),
|
||||
"lwzx $rD, $src", LdStGeneral,
|
||||
[(set GPRC:$rD, (load xaddr:$src))]>;
|
||||
def LDX : XForm_1<31, 21, (ops G8RC:$rD, memrr:$src),
|
||||
"ldx $rD, $src", LdStLD,
|
||||
[(set G8RC:$rD, (load xaddr:$src))]>, isPPC64;
|
||||
def LVEBX: XForm_1<31, 7, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
|
||||
"lvebx $vD, $base, $rA", LdStGeneral,
|
||||
[]>;
|
||||
@ -421,9 +437,9 @@ def LVEHX: XForm_1<31, 39, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
|
||||
def LVEWX: XForm_1<31, 71, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
|
||||
"lvewx $vD, $base, $rA", LdStGeneral,
|
||||
[]>;
|
||||
def LVX : XForm_1<31, 103, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
|
||||
"lvx $vD, $base, $rA", LdStGeneral,
|
||||
[]>;
|
||||
def LVX : XForm_1<31, 103, (ops VRRC:$vD, memrr:$src),
|
||||
"lvx $vD, $src", LdStGeneral,
|
||||
[(set VRRC:$vD, (load xoaddr:$src))]>;
|
||||
}
|
||||
def LVSL : XForm_1<31, 6, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
|
||||
"lvsl $vD, $base, $rA", LdStGeneral,
|
||||
@ -489,15 +505,15 @@ def SRAW : XForm_6<31, 792, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
|
||||
"sraw $rA, $rS, $rB", IntShift,
|
||||
[(set GPRC:$rA, (PPCsra GPRC:$rS, GPRC:$rB))]>;
|
||||
let isStore = 1 in {
|
||||
def STBX : XForm_8<31, 215, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
"stbx $rS, $rA, $rB", LdStGeneral,
|
||||
[]>;
|
||||
def STHX : XForm_8<31, 407, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
"sthx $rS, $rA, $rB", LdStGeneral,
|
||||
[]>;
|
||||
def STWX : XForm_8<31, 151, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
"stwx $rS, $rA, $rB", LdStGeneral,
|
||||
[]>;
|
||||
def STBX : XForm_8<31, 215, (ops GPRC:$rS, memrr:$dst),
|
||||
"stbx $rS, $dst", LdStGeneral,
|
||||
[(truncstore GPRC:$rS, xaddr:$dst, i8)]>;
|
||||
def STHX : XForm_8<31, 407, (ops GPRC:$rS, memrr:$dst),
|
||||
"sthx $rS, $dst", LdStGeneral,
|
||||
[(truncstore GPRC:$rS, xaddr:$dst, i16)]>;
|
||||
def STWX : XForm_8<31, 151, (ops GPRC:$rS, memrr:$dst),
|
||||
"stwx $rS, $dst", LdStGeneral,
|
||||
[(store GPRC:$rS, xaddr:$dst)]>;
|
||||
def STWUX : XForm_8<31, 183, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
"stwux $rS, $rA, $rB", LdStGeneral,
|
||||
[]>;
|
||||
@ -516,9 +532,9 @@ def STVEHX: XForm_8<31, 167, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
def STVEWX: XForm_8<31, 199, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
"stvewx $rS, $rA, $rB", LdStGeneral,
|
||||
[]>;
|
||||
def STVX : XForm_8<31, 231, (ops VRRC:$rS, GPRC:$rA, GPRC:$rB),
|
||||
"stvx $rS, $rA, $rB", LdStGeneral,
|
||||
[]>;
|
||||
def STVX : XForm_8<31, 231, (ops VRRC:$rS, memrr:$dst),
|
||||
"stvx $rS, $dst", LdStGeneral,
|
||||
[(store VRRC:$rS, xoaddr:$dst)]>;
|
||||
}
|
||||
def SRAWI : XForm_10<31, 824, (ops GPRC:$rA, GPRC:$rS, u5imm:$SH),
|
||||
"srawi $rA, $rS, $SH", IntShift,
|
||||
@ -555,12 +571,12 @@ def FCMPUD : XForm_17<63, 0, (ops CRRC:$crD, F8RC:$fA, F8RC:$fB),
|
||||
"fcmpu $crD, $fA, $fB", FPCompare>;
|
||||
|
||||
let isLoad = 1 in {
|
||||
def LFSX : XForm_25<31, 535, (ops F4RC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lfsx $dst, $base, $index", LdStLFDU,
|
||||
[]>;
|
||||
def LFDX : XForm_25<31, 599, (ops F8RC:$dst, GPRC:$base, GPRC:$index),
|
||||
"lfdx $dst, $base, $index", LdStLFDU,
|
||||
[]>;
|
||||
def LFSX : XForm_25<31, 535, (ops F4RC:$frD, memrr:$src),
|
||||
"lfsx $frD, $src", LdStLFDU,
|
||||
[(set F4RC:$frD, (load xaddr:$src))]>;
|
||||
def LFDX : XForm_25<31, 599, (ops F8RC:$frD, memrr:$src),
|
||||
"lfdx $frD, $src", LdStLFDU,
|
||||
[(set F8RC:$frD, (load xaddr:$src))]>;
|
||||
}
|
||||
def FCFID : XForm_26<63, 846, (ops F8RC:$frD, F8RC:$frB),
|
||||
"fcfid $frD, $frB", FPGeneral,
|
||||
@ -614,12 +630,15 @@ def FNEGD : XForm_26<63, 40, (ops F8RC:$frD, F8RC:$frB),
|
||||
|
||||
|
||||
let isStore = 1 in {
|
||||
def STFSX : XForm_28<31, 663, (ops F4RC:$frS, GPRC:$rA, GPRC:$rB),
|
||||
"stfsx $frS, $rA, $rB", LdStUX,
|
||||
[]>;
|
||||
def STFDX : XForm_28<31, 727, (ops F8RC:$frS, GPRC:$rA, GPRC:$rB),
|
||||
"stfdx $frS, $rA, $rB", LdStUX,
|
||||
def STFIWX: XForm_28<31, 983, (ops F4RC:$frS, memrr:$dst),
|
||||
"stfiwx $frS, $dst", LdStUX,
|
||||
[]>;
|
||||
def STFSX : XForm_28<31, 663, (ops F4RC:$frS, memrr:$dst),
|
||||
"stfsx $frS, $dst", LdStUX,
|
||||
[(store F4RC:$frS, xaddr:$dst)]>;
|
||||
def STFDX : XForm_28<31, 727, (ops F8RC:$frS, memrr:$dst),
|
||||
"stfdx $frS, $dst", LdStUX,
|
||||
[(store F8RC:$frS, xaddr:$dst)]>;
|
||||
}
|
||||
|
||||
// XL-Form instructions. condition register logical ops.
|
||||
@ -1012,6 +1031,27 @@ def : Pat<(srl GPRC:$rS, GPRC:$rB),
|
||||
def : Pat<(shl GPRC:$rS, GPRC:$rB),
|
||||
(SLW GPRC:$rS, GPRC:$rB)>;
|
||||
|
||||
def : Pat<(i32 (zextload iaddr:$src, i1)),
|
||||
(LBZ iaddr:$src)>;
|
||||
def : Pat<(i32 (zextload xaddr:$src, i1)),
|
||||
(LBZX xaddr:$src)>;
|
||||
def : Pat<(i32 (extload iaddr:$src, i1)),
|
||||
(LBZ iaddr:$src)>;
|
||||
def : Pat<(i32 (extload xaddr:$src, i1)),
|
||||
(LBZX xaddr:$src)>;
|
||||
def : Pat<(i32 (extload iaddr:$src, i8)),
|
||||
(LBZ iaddr:$src)>;
|
||||
def : Pat<(i32 (extload xaddr:$src, i8)),
|
||||
(LBZX xaddr:$src)>;
|
||||
def : Pat<(i32 (extload iaddr:$src, i16)),
|
||||
(LHZ iaddr:$src)>;
|
||||
def : Pat<(i32 (extload xaddr:$src, i16)),
|
||||
(LHZX xaddr:$src)>;
|
||||
def : Pat<(f64 (extload iaddr:$src, f32)),
|
||||
(FMRSD (LFS iaddr:$src))>;
|
||||
def : Pat<(f64 (extload xaddr:$src, f32)),
|
||||
(FMRSD (LFSX xaddr:$src))>;
|
||||
|
||||
// Same as above, but using a temporary. FIXME: implement temporaries :)
|
||||
/*
|
||||
def : Pattern<(xor GPRC:$in, imm:$imm),
|
||||
|
Loading…
x
Reference in New Issue
Block a user