Several fixes and enhancements to the PPC32 backend.

1. Fix an illegal argument to getClassB when deciding whether or not to
   sign extend a byte load.

2. Initial addition of isLoad and isStore flags to the instruction .td file
   for eventual use in a scheduler.

3. Rewrite of how constants are handled in emitSimpleBinaryOperation so
   that we can emit the PowerPC shifted immediate instructions far more
   often.  This allows us to emit the following code:

int foo(int x) { return x | 0x00F0000; }

_foo:
.LBB_foo_0:     ; entry
        ; IMPLICIT_DEF
        oris r3, r3, 15
        blr


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16826 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2004-10-07 22:30:03 +00:00
parent cb90de37a7
commit b816f0298d
3 changed files with 158 additions and 151 deletions

View File

@ -32,6 +32,8 @@
using namespace llvm;
namespace {
Statistic<> ShiftedImm("ppc-codegen", "Number of shifted immediates used");
/// TypeClass - Used by the PowerPC backend to group LLVM types by their basic
/// PPC Representation.
///
@ -315,8 +317,19 @@ namespace {
void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator IP,
Value *Src, const Type *DestTy, unsigned TargetReg);
/// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
/// and constant expression support.
/// emitBinaryConstOperation - Used by several functions to emit simple
/// arithmetic and logical operations with constants on a register rather
/// than a Value.
///
void emitBinaryConstOperation(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
unsigned Op0Reg, ConstantInt *Op1,
unsigned Opcode, unsigned DestReg);
/// emitSimpleBinaryOperation - Implement simple binary operators for
/// integral types. OperatorClass is one of: 0 for Add, 1 for Sub,
/// 2 for And, 3 for Or, 4 for Xor.
///
void emitSimpleBinaryOperation(MachineBasicBlock *BB,
MachineBasicBlock::iterator IP,
@ -389,13 +402,6 @@ namespace {
void emitUCOM(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
unsigned LHS, unsigned RHS);
/// emitAdd - A convenience function to emit the necessary code to add a
/// constant signed value to a register.
///
void emitAdd(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
unsigned Op0Reg, ConstantSInt *Op1, unsigned DestReg);
/// makeAnotherReg - This method returns the next register number we haven't
/// yet used.
///
@ -434,7 +440,8 @@ namespace {
/// canUseAsImmediateForOpcode - This method returns whether a ConstantInt
/// is okay to use as an immediate argument to a certain binary operation
bool canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Opcode);
bool canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Opcode,
bool Shifted);
/// getFixedSizedAllocaFI - Return the frame index for a fixed sized alloca
/// that is to be statically allocated with the initial stack frame
@ -481,34 +488,41 @@ unsigned PPC32ISel::getReg(Value *V, MachineBasicBlock *MBB,
/// canUseAsImmediateForOpcode - This method returns whether a ConstantInt
/// is okay to use as an immediate argument to a certain binary operator.
/// The shifted argument determines if the immediate is suitable to be used with
/// the PowerPC instructions such as addis which concatenate 16 bits of the
/// immediate with 16 bits of zeroes.
///
/// Operator is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, 4 for Xor.
bool PPC32ISel::canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Operator) {
bool PPC32ISel::canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Opcode,
bool Shifted) {
ConstantSInt *Op1Cs;
ConstantUInt *Op1Cu;
// For shifted immediates, any value with the low halfword cleared may be used
if (Shifted) {
if (((int32_t)CI->getRawValue() & 0x0000FFFF) == 0) {
++ShiftedImm;
return true;
}
return false;
}
// ADDI, Compare, and non-indexed Load take SIMM
bool cond1 = (Operator == 0)
bool cond1 = (Opcode < 2)
&& ((int32_t)CI->getRawValue() <= 32767)
&& ((int32_t)CI->getRawValue() >= -32768);
// SUBI takes -SIMM since it is a mnemonic for ADDI
bool cond2 = (Operator == 1)
&& ((int32_t)CI->getRawValue() <= 32768)
&& ((int32_t)CI->getRawValue() >= -32767);
// ANDIo, ORI, and XORI take unsigned values
bool cond3 = (Operator >= 2)
bool cond2 = (Opcode >= 2)
&& (Op1Cs = dyn_cast<ConstantSInt>(CI))
&& (Op1Cs->getValue() >= 0)
&& (Op1Cs->getValue() <= 65535);
// ANDIo, ORI, and XORI take UIMMs, so they can be larger
bool cond4 = (Operator >= 2)
bool cond3 = (Opcode >= 2)
&& (Op1Cu = dyn_cast<ConstantUInt>(CI))
&& (Op1Cu->getValue() <= 65535);
if (cond1 || cond2 || cond3 || cond4)
if (cond1 || cond2 || cond3)
return true;
return false;
@ -606,7 +620,7 @@ void PPC32ISel::copyConstantToRegister(MachineBasicBlock *MBB,
} else {
unsigned Temp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC::LIS, 1, Temp).addSImm(uval >> 16);
BuildMI(*MBB, IP, PPC::ORI, 2, R).addReg(Temp).addImm(uval);
BuildMI(*MBB, IP, PPC::ORI, 2, R).addReg(Temp).addImm(uval & 0xFFFF);
}
return;
} else if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(C)) {
@ -616,7 +630,7 @@ void PPC32ISel::copyConstantToRegister(MachineBasicBlock *MBB,
} else {
unsigned Temp = makeAnotherReg(Type::IntTy);
BuildMI(*MBB, IP, PPC::LIS, 1, Temp).addSImm(sval >> 16);
BuildMI(*MBB, IP, PPC::ORI, 2, R).addReg(Temp).addImm(sval);
BuildMI(*MBB, IP, PPC::ORI, 2, R).addReg(Temp).addImm(sval & 0xFFFF);
}
return;
}
@ -1047,7 +1061,7 @@ unsigned PPC32ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
unsigned OpClass = (CompTy->isSigned()) ? 0 : 2;
// Treat compare like ADDI for the purposes of immediate suitability
if (canUseAsImmediateForOpcode(CI, OpClass)) {
if (canUseAsImmediateForOpcode(CI, OpClass, false)) {
BuildMI(*MBB, IP, OpcodeImm, 2, PPC::CR0).addReg(Op0r).addSImm(Op1v);
} else {
unsigned Op1r = getReg(Op1, MBB, IP);
@ -2012,39 +2026,94 @@ void PPC32ISel::emitBinaryFPOperation(MachineBasicBlock *BB,
BuildMI(*BB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
}
// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
// returns zero when the input is not exactly a power of two.
static unsigned ExactLog2(unsigned Val) {
if (Val == 0 || (Val & (Val-1))) return 0;
unsigned Count = 0;
while (Val != 1) {
Val >>= 1;
++Count;
}
return Count;
}
/// emitBinaryConstOperation - Implement simple binary operators for integral
/// types with a constant operand. Opcode is one of: 0 for Add, 1 for Sub,
/// 2 for And, 3 for Or, 4 for Xor, and 5 for Subtract-From.
///
void PPC32ISel::emitBinaryConstOperation(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
unsigned Op0Reg, ConstantInt *Op1,
unsigned Opcode, unsigned DestReg) {
static const unsigned OpTab[] = {
PPC::ADD, PPC::SUB, PPC::AND, PPC::OR, PPC::XOR, PPC::SUBF
};
static const unsigned ImmOpTab[2][6] = {
{ PPC::ADDI, PPC::ADDI, PPC::ANDIo, PPC::ORI, PPC::XORI, PPC::SUBFIC },
{ PPC::ADDIS, PPC::ADDIS, PPC::ANDISo, PPC::ORIS, PPC::XORIS, PPC::SUBFIC }
};
// Handle subtract now by inverting the constant value
ConstantInt *CI = Op1;
if (Opcode == 1) {
ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op1);
CI = ConstantSInt::get(Op1->getType(), -CSI->getValue());
}
// xor X, -1 -> not X
if (Opcode == 4) {
ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op1);
ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1);
if ((CSI && CSI->isAllOnesValue()) || (CUI && CUI->isAllOnesValue())) {
BuildMI(*MBB, IP, PPC::NOR, 2, DestReg).addReg(Op0Reg).addReg(Op0Reg);
return;
}
}
// For Add, Sub, and SubF the instruction takes a signed immediate. For And,
// Or, and Xor, the instruction takes an unsigned immediate. There is no
// shifted immediate form of SubF so disallow its opcode for those constants.
if (canUseAsImmediateForOpcode(CI, Opcode, false)) {
if (Opcode < 2 || Opcode == 5)
BuildMI(*MBB, IP, ImmOpTab[0][Opcode], 2, DestReg).addReg(Op0Reg)
.addSImm(Op1->getRawValue());
else
BuildMI(*MBB, IP, ImmOpTab[0][Opcode], 2, DestReg).addReg(Op0Reg)
.addZImm(Op1->getRawValue());
} else if (canUseAsImmediateForOpcode(CI, Opcode, true) && (Opcode < 5)) {
if (Opcode < 2)
BuildMI(*MBB, IP, ImmOpTab[1][Opcode], 2, DestReg).addReg(Op0Reg)
.addSImm(Op1->getRawValue() >> 16);
else
BuildMI(*MBB, IP, ImmOpTab[1][Opcode], 2, DestReg).addReg(Op0Reg)
.addZImm(Op1->getRawValue() >> 16);
} else {
unsigned Op1Reg = getReg(Op1, MBB, IP);
BuildMI(*MBB, IP, OpTab[Opcode], 2, DestReg).addReg(Op0Reg).addReg(Op1Reg);
}
}
/// emitSimpleBinaryOperation - Implement simple binary operators for integral
/// types... OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for
/// Or, 4 for Xor.
///
/// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
/// and constant expression support.
///
void PPC32ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
Value *Op0, Value *Op1,
unsigned OperatorClass,
unsigned DestReg) {
unsigned Class = getClassB(Op0->getType());
// Arithmetic and Bitwise operators
static const unsigned OpcodeTab[] = {
PPC::ADD, PPC::SUB, PPC::AND, PPC::OR, PPC::XOR
};
static const unsigned ImmOpcodeTab[] = {
PPC::ADDI, PPC::SUBI, PPC::ANDIo, PPC::ORI, PPC::XORI
};
static const unsigned RImmOpcodeTab[] = {
PPC::ADDI, PPC::SUBFIC, PPC::ANDIo, PPC::ORI, PPC::XORI
};
// Otherwise, code generate the full operation with a constant.
static const unsigned BottomTab[] = {
PPC::ADDC, PPC::SUBC, PPC::AND, PPC::OR, PPC::XOR
};
static const unsigned TopTab[] = {
PPC::ADDE, PPC::SUBFE, PPC::AND, PPC::OR, PPC::XOR
static const unsigned LongOpTab[2][5] = {
{ PPC::ADDC, PPC::SUBC, PPC::AND, PPC::OR, PPC::XOR },
{ PPC::ADDE, PPC::SUBFE, PPC::AND, PPC::OR, PPC::XOR }
};
unsigned Class = getClassB(Op0->getType());
if (Class == cFP32 || Class == cFP64) {
assert(OperatorClass < 2 && "No logical ops for FP!");
emitBinaryFPOperation(MBB, IP, Op0, Op1, OperatorClass, DestReg);
@ -2068,78 +2137,21 @@ void PPC32ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
}
// Special case: op <const int>, Reg
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
// sub 0, X -> subfic
if (OperatorClass == 1 && canUseAsImmediateForOpcode(CI, 0)) {
unsigned Op1r = getReg(Op1, MBB, IP);
int imm = CI->getRawValue() & 0xFFFF;
if (Class == cLong) {
BuildMI(*MBB, IP, PPC::SUBFIC, 2, DestReg+1).addReg(Op1r+1)
.addSImm(imm);
BuildMI(*MBB, IP, PPC::SUBFZE, 1, DestReg).addReg(Op1r);
} else {
BuildMI(*MBB, IP, PPC::SUBFIC, 2, DestReg).addReg(Op1r).addSImm(imm);
}
return;
}
// If it is easy to do, swap the operands and emit an immediate op
if (Class != cLong && OperatorClass != 1 &&
canUseAsImmediateForOpcode(CI, OperatorClass)) {
unsigned Op1r = getReg(Op1, MBB, IP);
int imm = CI->getRawValue() & 0xFFFF;
if (OperatorClass < 2)
BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
.addSImm(imm);
else
BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
.addZImm(imm);
return;
}
}
// Special case: op Reg, <const int>
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
unsigned Op0r = getReg(Op0, MBB, IP);
// xor X, -1 -> not X
if (OperatorClass == 4 && Op1C->isAllOnesValue()) {
BuildMI(*MBB, IP, PPC::NOR, 2, DestReg).addReg(Op0r).addReg(Op0r);
if (Class == cLong) // Invert the low part too
BuildMI(*MBB, IP, PPC::NOR, 2, DestReg+1).addReg(Op0r+1)
.addReg(Op0r+1);
return;
}
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
if (Class != cLong) {
if (canUseAsImmediateForOpcode(Op1C, OperatorClass)) {
int immediate = Op1C->getRawValue() & 0xFFFF;
if (OperatorClass < 2)
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
.addSImm(immediate);
else
BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
.addZImm(immediate);
} else {
unsigned Op1r = getReg(Op1, MBB, IP);
BuildMI(*MBB, IP, OpcodeTab[OperatorClass], 2, DestReg).addReg(Op0r)
.addReg(Op1r);
}
unsigned Opcode = (OperatorClass == 1) ? 5 : OperatorClass;
unsigned Op1r = getReg(Op1, MBB, IP);
emitBinaryConstOperation(MBB, IP, Op1r, CI, Opcode, DestReg);
return;
}
// Special case: op Reg, <const int>
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
if (Class != cLong) {
unsigned Op0r = getReg(Op0, MBB, IP);
emitBinaryConstOperation(MBB, IP, Op0r, CI, OperatorClass, DestReg);
return;
}
unsigned Op1r = getReg(Op1, MBB, IP);
BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
.addReg(Op1r+1);
BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg).addReg(Op0r)
.addReg(Op1r);
return;
}
// We couldn't generate an immediate variant of the op, load both halves into
// registers and emit the appropriate opcode.
unsigned Op0r = getReg(Op0, MBB, IP);
@ -2149,26 +2161,14 @@ void PPC32ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
unsigned Opcode = OpcodeTab[OperatorClass];
BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
} else {
BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
BuildMI(*MBB, IP, LongOpTab[0][OperatorClass], 2, DestReg+1).addReg(Op0r+1)
.addReg(Op1r+1);
BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg).addReg(Op0r)
BuildMI(*MBB, IP, LongOpTab[1][OperatorClass], 2, DestReg).addReg(Op0r)
.addReg(Op1r);
}
return;
}
// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
// returns zero when the input is not exactly a power of two.
static unsigned ExactLog2(unsigned Val) {
if (Val == 0 || (Val & (Val-1))) return 0;
unsigned Count = 0;
while (Val != 1) {
Val >>= 1;
++Count;
}
return Count;
}
/// doMultiply - Emit appropriate instructions to multiply together the
/// Values Op0 and Op1, and put the result in DestReg.
///
@ -2258,7 +2258,7 @@ void PPC32ISel::doMultiplyConst(MachineBasicBlock *MBB,
// If 32 bits or less and immediate is in right range, emit mul by immediate
if (Class == cByte || Class == cShort || Class == cInt) {
if (canUseAsImmediateForOpcode(CI, 0)) {
if (canUseAsImmediateForOpcode(CI, 0, false)) {
unsigned Op0r = getReg(Op0, MBB, IP);
unsigned imm = CI->getRawValue() & 0xFFFF;
BuildMI(*MBB, IP, PPC::MULLI, 2, DestReg).addReg(Op0r).addSImm(imm);
@ -2423,7 +2423,7 @@ void PPC32ISel::emitDivRemOperation(MachineBasicBlock *MBB,
unsigned TmpReg1 = makeAnotherReg(Op0->getType());
unsigned TmpReg2 = makeAnotherReg(Op0->getType());
emitDivRemOperation(MBB, IP, Op0, Op1, true, TmpReg1);
if (CI && canUseAsImmediateForOpcode(CI, 0)) {
if (CI && canUseAsImmediateForOpcode(CI, 0, false)) {
BuildMI(*MBB, IP, PPC::MULLI, 2, TmpReg2).addReg(TmpReg1)
.addSImm(CI->getRawValue());
} else {
@ -2639,7 +2639,7 @@ static bool LoadNeedsSignExtend(LoadInst &LI) {
if (isa<SetCondInst>(*I))
continue;
if (StoreInst *SI = dyn_cast<StoreInst>(*I))
if (cByte == getClassB(SI->getType()))
if (cByte == getClassB(SI->getOperand(0)->getType()))
continue;
AllUsesAreStoresOrSetCC = false;
break;
@ -3392,21 +3392,6 @@ void PPC32ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
emitGEPOperation(BB, BB->end(), &I, false);
}
/// emitAdd - A convenience function to emit the necessary code to add a
/// constant signed value to a register.
///
void PPC32ISel::emitAdd(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
unsigned Op0Reg, ConstantSInt *Op1, unsigned DestReg) {
if (canUseAsImmediateForOpcode(Op1, 0)) {
BuildMI(*MBB, IP, PPC::ADDI, 2, DestReg).addReg(Op0Reg)
.addSImm(Op1->getValue());
} else {
unsigned Op1Reg = getReg(Op1, MBB, IP);
BuildMI(*MBB, IP, PPC::ADD, 2, DestReg).addReg(Op0Reg).addReg(Op1Reg);
}
}
/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
/// constant expression GEP support.
///
@ -3490,7 +3475,7 @@ void PPC32ISel::emitGEPOperation(MachineBasicBlock *MBB,
unsigned TmpReg1 = makeAnotherReg(Type::IntTy);
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
doMultiplyConst(MBB, IP, TmpReg1, cgo.index, cgo.size);
emitAdd(MBB, IP, TmpReg1, cgo.offset, TmpReg2);
emitBinaryConstOperation(MBB, IP, TmpReg1, cgo.offset, 0, TmpReg2);
if (indexReg == 0)
indexReg = TmpReg2;
@ -3513,13 +3498,13 @@ void PPC32ISel::emitGEPOperation(MachineBasicBlock *MBB,
// store can try and use it as an immediate.
if (GEPIsFolded) {
if (indexReg == 0) {
if (!canUseAsImmediateForOpcode(remainder, 0)) {
if (!canUseAsImmediateForOpcode(remainder, 0, false)) {
indexReg = getReg(remainder, MBB, IP);
remainder = 0;
}
} else {
unsigned TmpReg = makeAnotherReg(Type::IntTy);
emitAdd(MBB, IP, indexReg, remainder, TmpReg);
emitBinaryConstOperation(MBB, IP, indexReg, remainder, 0, TmpReg);
indexReg = TmpReg;
remainder = 0;
}
@ -3536,7 +3521,7 @@ void PPC32ISel::emitGEPOperation(MachineBasicBlock *MBB,
BuildMI(*MBB, IP, PPC::ADD, 2, TmpReg).addReg(indexReg).addReg(basePtrReg);
basePtrReg = TmpReg;
}
emitAdd(MBB, IP, basePtrReg, remainder, TargetReg);
emitBinaryConstOperation(MBB, IP, basePtrReg, remainder, 0, TargetReg);
}
/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
@ -3606,7 +3591,6 @@ void PPC32ISel::visitMallocInst(MallocInst &I) {
TM.CalledFunctions.insert(mallocFn);
}
/// visitFreeInst - Free instructions are code gen'd to call the free libc
/// function.
///

View File

@ -1664,8 +1664,9 @@ void PPC64ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
static const unsigned OpcodeTab[] = {
PPC::ADD, PPC::SUB, PPC::AND, PPC::OR, PPC::XOR
};
// FIXME: Convert this to the version from PPC32ISel
static const unsigned ImmOpcodeTab[] = {
PPC::ADDI, PPC::SUBI, PPC::ANDIo, PPC::ORI, PPC::XORI
PPC::ADDI, PPC::ADDI, PPC::ANDIo, PPC::ORI, PPC::XORI
};
static const unsigned RImmOpcodeTab[] = {
PPC::ADDI, PPC::SUBFIC, PPC::ANDIo, PPC::ORI, PPC::XORI

View File

@ -44,8 +44,10 @@ def symbolLo: Operand<i32> {
// Pseudo-instructions:
def PHI : Pseudo<(ops), "; PHI">;
let isLoad = 1 in {
def ADJCALLSTACKDOWN : Pseudo<(ops), "; ADJCALLSTACKDOWN">;
def ADJCALLSTACKUP : Pseudo<(ops), "; ADJCALLSTACKUP">;
}
def IMPLICIT_DEF : Pseudo<(ops), "; IMPLICIT_DEF">;
def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label">;
@ -82,6 +84,7 @@ let isBranch = 1, isTerminator = 1, isCall = 1,
// D-Form instructions. Most instructions that perform an operation on a
// register and an immediate are of this type.
//
let isLoad = 1 in {
def LBZ : DForm_1<35, 0, 0, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
"lbz $rD, $disp($rA)">;
def LHA : DForm_1<42, 0, 0, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
@ -92,6 +95,7 @@ def LMW : DForm_1<46, 0, 0, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
"lmw $rD, $disp($rA)">;
def LWZ : DForm_1<32, 0, 0, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lwz $rD, $disp($rA)">;
}
def ADDI : DForm_2<14, 0, 0, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addi $rD, $rA, $imm">;
def ADDIC : DForm_2<12, 0, 0, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
@ -108,12 +112,11 @@ def MULLI : DForm_2< 7, 0, 0, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"mulli $rD, $rA, $imm">;
def SUBFIC : DForm_2< 8, 0, 0, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"subfic $rD, $rA, $imm">;
def SUBI : DForm_2<14, 0, 0, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"subi $rD, $rA, $imm">;
def LI : DForm_2_r0<14, 0, 0, (ops GPRC:$rD, s16imm:$imm),
"li $rD, $imm">;
def LIS : DForm_2_r0<15, 0, 0, (ops GPRC:$rD, s16imm:$imm),
"lis $rD, $imm">;
let isStore = 1 in {
def STMW : DForm_3<47, 0, 0, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stmw $rS, $disp($rA)">;
def STB : DForm_3<38, 0, 0, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
@ -128,9 +131,13 @@ def STW : DForm_3<36, 0, 0, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stw $rS, $disp($rA)">;
def STWU : DForm_3<37, 0, 0, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stwu $rS, $disp($rA)">;
}
def ANDIo : DForm_4<28, 0, 0,
(ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"andi. $dst, $src1, $src2">;
def ANDISo : DForm_4<29, 0, 0,
(ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"andis. $dst, $src1, $src2">;
def ORI : DForm_4<24, 0, 0,
(ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"ori $dst, $src1, $src2">;
@ -159,30 +166,38 @@ def CMPLWI : DForm_6_ext<10, 0, 0,
def CMPLDI : DForm_6_ext<10, 1, 0,
(ops CRRC:$dst, GPRC:$src1, u16imm:$src2),
"cmpldi $dst, $src1, $src2">;
let isLoad = 1 in {
def LFS : DForm_8<48, 0, 0, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lfs $rD, $disp($rA)">;
def LFD : DForm_8<50, 0, 0, (ops GPRC:$rD, symbolLo:$disp, GPRC:$rA),
"lfd $rD, $disp($rA)">;
}
let isStore = 1 in {
def STFS : DForm_9<52, 0, 0, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stfs $rS, $disp($rA)">;
def STFD : DForm_9<54, 0, 0, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stfd $rS, $disp($rA)">;
}
// DS-Form instructions. Load/Store instructions available in PPC-64
//
let isLoad = 1 in {
def LWA : DSForm_1<58, 2, 1, 0, (ops GPRC:$rT, s16imm:$DS, GPRC:$rA),
"lwa $rT, $DS($rA)">;
def LD : DSForm_2<58, 0, 1, 0, (ops GPRC:$rT, s16imm:$DS, GPRC:$rA),
"ld $rT, $DS($rA)">;
}
let isStore = 1 in {
def STD : DSForm_2<62, 0, 1, 0, (ops GPRC:$rT, s16imm:$DS, GPRC:$rA),
"std $rT, $DS($rA)">;
def STDU : DSForm_2<62, 1, 1, 0, (ops GPRC:$rT, s16imm:$DS, GPRC:$rA),
"stdu $rT, $DS($rA)">;
}
// X-Form instructions. Most instructions that perform an operation on a
// register and another register are of this type.
//
let isLoad = 1 in {
def LBZX : XForm_1<31, 87, 0, 0, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lbzx $dst, $base, $index">;
def LHAX : XForm_1<31, 343, 0, 0, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
@ -195,6 +210,7 @@ def LWZX : XForm_1<31, 23, 0, 0, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"lwzx $dst, $base, $index">;
def LDX : XForm_1<31, 21, 1, 0, (ops GPRC:$dst, GPRC:$base, GPRC:$index),
"ldx $dst, $base, $index">;
}
def MFCR : XForm_5<31, 19, 0, 0, (ops GPRC:$dst), "mfcr $dst">;
def AND : XForm_6<31, 28, 0, 0, 0, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"and $rA, $rS, $rB">;
@ -226,6 +242,7 @@ def SRAW : XForm_6<31, 792, 0, 0, 0, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"sraw $rA, $rS, $rB">;
def XOR : XForm_6<31, 316, 0, 0, 0, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"xor $rA, $rS, $rB">;
let isStore = 1 in {
def STBX : XForm_8<31, 215, 0, 0, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stbx $rS, $rA, $rB">;
def STHX : XForm_8<31, 407, 0, 0, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
@ -238,6 +255,7 @@ def STDX : XForm_8<31, 149, 1, 0, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stdx $rS, $rA, $rB">;
def STDUX : XForm_8<31, 181, 1, 0, (ops GPRC:$rS, GPRC:$rA, GPRC:$rB),
"stdux $rS, $rA, $rB">;
}
def SRAWI : XForm_10<31, 824, 0, 0, 0, (ops GPRC:$rA, GPRC:$rS, u5imm:$SH),
"srawi $rA, $rS, $SH">;
def CNTLZW : XForm_11<31, 26, 0, 0, 0, (ops GPRC:$rA, GPRC:$rS),
@ -268,10 +286,12 @@ def CMPLD : XForm_16_ext<31, 32, 1, 0,
"cmpld $crD, $rA, $rB">;
def FCMPU : XForm_17<63, 0, 0, 0, (ops CRRC:$crD, FPRC:$fA, FPRC:$fB),
"fcmpu $crD, $fA, $fB">;
let isLoad = 1 in {
def LFSX : XForm_25<31, 535, 0, 0, (ops FPRC:$dst, GPRC:$base, GPRC:$index),
"lfsx $dst, $base, $index">;
def LFDX : XForm_25<31, 599, 0, 0, (ops FPRC:$dst, GPRC:$base, GPRC:$index),
"lfdx $dst, $base, $index">;
}
def FCFID : XForm_26<63, 846, 0, 1, 0, (ops FPRC:$frD, FPRC:$frB),
"fcfid $frD, $frB">;
def FCTIDZ : XForm_26<63, 815, 0, 1, 0, (ops FPRC:$frD, FPRC:$frB),
@ -284,10 +304,12 @@ def FNEG : XForm_26<63, 80, 0, 0, 0, (ops FPRC:$frD, FPRC:$frB),
"fneg $frD, $frB">;
def FRSP : XForm_26<63, 12, 0, 0, 0, (ops FPRC:$frD, FPRC:$frB),
"frsp $frD, $frB">;
let isStore = 1 in {
def STFSX : XForm_28<31, 663, 0, 0, (ops FPRC:$frS, GPRC:$rA, GPRC:$rB),
"stfsx $frS, $rA, $rB">;
def STFDX : XForm_28<31, 727, 0, 0, (ops FPRC:$frS, GPRC:$rA, GPRC:$rB),
"stfdx $frS, $rA, $rB">;
}
// XL-Form instructions. condition register logical ops.
//