mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-24 08:24:33 +00:00
Add PredicateOperand to all ARM instructions that have the condition field.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37066 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -614,8 +614,9 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
|
void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
|
||||||
int CC = (int)MI->getOperand(opNum).getImmedValue();
|
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImmedValue();
|
||||||
O << ARMCondCodeToString((ARMCC::CondCodes)CC);
|
if (CC != ARMCC::AL)
|
||||||
|
O << ARMCondCodeToString(CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
|
void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
|
||||||
|
@ -1265,9 +1265,9 @@ bool ARMConstantIslands::UndoLRSpillRestore() {
|
|||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) {
|
||||||
MachineInstr *MI = PushPopMIs[i];
|
MachineInstr *MI = PushPopMIs[i];
|
||||||
if (MI->getNumOperands() == 1) {
|
|
||||||
if (MI->getOpcode() == ARM::tPOP_RET &&
|
if (MI->getOpcode() == ARM::tPOP_RET &&
|
||||||
MI->getOperand(0).getReg() == ARM::PC)
|
MI->getOperand(0).getReg() == ARM::PC &&
|
||||||
|
MI->getNumExplicitOperands() == 1) {
|
||||||
BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
|
BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
|
||||||
MI->eraseFromParent();
|
MI->eraseFromParent();
|
||||||
MadeChange = true;
|
MadeChange = true;
|
||||||
|
@ -524,6 +524,11 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDOperand Op,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getDefaultPred - Returns a ARMCC::AL immediate node.
|
||||||
|
static inline SDOperand getDefaultPred(SelectionDAG *CurDAG) {
|
||||||
|
return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
||||||
SDNode *N = Op.Val;
|
SDNode *N = Op.Val;
|
||||||
@ -559,9 +564,10 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
|||||||
CPIdx,
|
CPIdx,
|
||||||
CurDAG->getRegister(0, MVT::i32),
|
CurDAG->getRegister(0, MVT::i32),
|
||||||
CurDAG->getTargetConstant(0, MVT::i32),
|
CurDAG->getTargetConstant(0, MVT::i32),
|
||||||
|
getDefaultPred(CurDAG),
|
||||||
CurDAG->getEntryNode()
|
CurDAG->getEntryNode()
|
||||||
};
|
};
|
||||||
ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 4);
|
ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 5);
|
||||||
}
|
}
|
||||||
ReplaceUses(Op, SDOperand(ResNode, 0));
|
ReplaceUses(Op, SDOperand(ResNode, 0));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -573,10 +579,14 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
|||||||
case ISD::FrameIndex: {
|
case ISD::FrameIndex: {
|
||||||
// Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
|
// Selects to ADDri FI, 0 which in turn will become ADDri SP, imm.
|
||||||
int FI = cast<FrameIndexSDNode>(N)->getIndex();
|
int FI = cast<FrameIndexSDNode>(N)->getIndex();
|
||||||
unsigned Opc = Subtarget->isThumb() ? ARM::tADDrSPi : ARM::ADDri;
|
|
||||||
SDOperand TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
|
SDOperand TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
|
||||||
return CurDAG->SelectNodeTo(N, Opc, MVT::i32, TFI,
|
if (Subtarget->isThumb())
|
||||||
|
return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
|
||||||
CurDAG->getTargetConstant(0, MVT::i32));
|
CurDAG->getTargetConstant(0, MVT::i32));
|
||||||
|
else
|
||||||
|
return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, TFI,
|
||||||
|
CurDAG->getTargetConstant(0, MVT::i32),
|
||||||
|
getDefaultPred(CurDAG));
|
||||||
}
|
}
|
||||||
case ISD::ADD: {
|
case ISD::ADD: {
|
||||||
// Select add sp, c to tADDhirr.
|
// Select add sp, c to tADDhirr.
|
||||||
@ -606,35 +616,39 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
|||||||
AddToISelQueue(V);
|
AddToISelQueue(V);
|
||||||
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
|
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
|
||||||
SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
|
SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
|
||||||
CurDAG->getTargetConstant(ShImm, MVT::i32)
|
CurDAG->getTargetConstant(ShImm, MVT::i32),
|
||||||
|
getDefaultPred(CurDAG)
|
||||||
};
|
};
|
||||||
return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 4);
|
return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 5);
|
||||||
}
|
}
|
||||||
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
|
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
|
||||||
SDOperand V = Op.getOperand(0);
|
SDOperand V = Op.getOperand(0);
|
||||||
AddToISelQueue(V);
|
AddToISelQueue(V);
|
||||||
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1));
|
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1));
|
||||||
SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
|
SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
|
||||||
CurDAG->getTargetConstant(ShImm, MVT::i32)
|
CurDAG->getTargetConstant(ShImm, MVT::i32),
|
||||||
|
getDefaultPred(CurDAG)
|
||||||
};
|
};
|
||||||
return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 4);
|
return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARMISD::FMRRD:
|
case ARMISD::FMRRD:
|
||||||
AddToISelQueue(Op.getOperand(0));
|
AddToISelQueue(Op.getOperand(0));
|
||||||
return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32,
|
return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32,
|
||||||
Op.getOperand(0));
|
Op.getOperand(0), getDefaultPred(CurDAG));
|
||||||
case ARMISD::MULHILOU:
|
case ARMISD::MULHILOU:
|
||||||
AddToISelQueue(Op.getOperand(0));
|
AddToISelQueue(Op.getOperand(0));
|
||||||
AddToISelQueue(Op.getOperand(1));
|
AddToISelQueue(Op.getOperand(1));
|
||||||
return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32,
|
return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32,
|
||||||
Op.getOperand(0), Op.getOperand(1));
|
Op.getOperand(0), Op.getOperand(1),
|
||||||
|
getDefaultPred(CurDAG));
|
||||||
case ARMISD::MULHILOS:
|
case ARMISD::MULHILOS:
|
||||||
AddToISelQueue(Op.getOperand(0));
|
AddToISelQueue(Op.getOperand(0));
|
||||||
AddToISelQueue(Op.getOperand(1));
|
AddToISelQueue(Op.getOperand(1));
|
||||||
return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32,
|
return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32,
|
||||||
Op.getOperand(0), Op.getOperand(1));
|
Op.getOperand(0), Op.getOperand(1),
|
||||||
|
getDefaultPred(CurDAG));
|
||||||
case ISD::LOAD: {
|
case ISD::LOAD: {
|
||||||
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
||||||
ISD::MemIndexedMode AM = LD->getAddressingMode();
|
ISD::MemIndexedMode AM = LD->getAddressingMode();
|
||||||
@ -674,9 +688,9 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
|
|||||||
AddToISelQueue(Chain);
|
AddToISelQueue(Chain);
|
||||||
AddToISelQueue(Base);
|
AddToISelQueue(Base);
|
||||||
AddToISelQueue(Offset);
|
AddToISelQueue(Offset);
|
||||||
SDOperand Ops[] = { Base, Offset, AMOpc, Chain };
|
SDOperand Ops[]= { Base, Offset, AMOpc, getDefaultPred(CurDAG), Chain };
|
||||||
return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32,
|
return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32,
|
||||||
MVT::Other, Ops, 4);
|
MVT::Other, Ops, 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Other cases are autogenerated.
|
// Other cases are autogenerated.
|
||||||
|
@ -52,7 +52,8 @@ bool ARMInstrInfo::isMoveInstr(const MachineInstr &MI,
|
|||||||
return true;
|
return true;
|
||||||
case ARM::MOVr:
|
case ARM::MOVr:
|
||||||
case ARM::tMOVr:
|
case ARM::tMOVr:
|
||||||
assert(MI.getNumOperands() >= 2 && MI.getOperand(0).isRegister() &&
|
assert(MI.getInstrDescriptor()->numOperands >= 2 &&
|
||||||
|
MI.getOperand(0).isRegister() &&
|
||||||
MI.getOperand(1).isRegister() &&
|
MI.getOperand(1).isRegister() &&
|
||||||
"Invalid ARM MOV instruction");
|
"Invalid ARM MOV instruction");
|
||||||
SrcReg = MI.getOperand(1).getReg();
|
SrcReg = MI.getOperand(1).getReg();
|
||||||
@ -188,15 +189,17 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
|||||||
MachineInstr *UpdateMI = NULL;
|
MachineInstr *UpdateMI = NULL;
|
||||||
MachineInstr *MemMI = NULL;
|
MachineInstr *MemMI = NULL;
|
||||||
unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
|
unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
|
||||||
unsigned NumOps = MI->getNumOperands();
|
const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
|
||||||
bool isLoad = (MI->getInstrDescriptor()->Flags & M_LOAD_FLAG) != 0;
|
unsigned NumOps = TID->numOperands;
|
||||||
|
bool isLoad = (TID->Flags & M_LOAD_FLAG) != 0;
|
||||||
const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0);
|
const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0);
|
||||||
const MachineOperand &Base = MI->getOperand(2);
|
const MachineOperand &Base = MI->getOperand(2);
|
||||||
const MachineOperand &Offset = MI->getOperand(NumOps-2);
|
const MachineOperand &Offset = MI->getOperand(NumOps-3);
|
||||||
unsigned WBReg = WB.getReg();
|
unsigned WBReg = WB.getReg();
|
||||||
unsigned BaseReg = Base.getReg();
|
unsigned BaseReg = Base.getReg();
|
||||||
unsigned OffReg = Offset.getReg();
|
unsigned OffReg = Offset.getReg();
|
||||||
unsigned OffImm = MI->getOperand(NumOps-1).getImm();
|
unsigned OffImm = MI->getOperand(NumOps-2).getImm();
|
||||||
|
ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm();
|
||||||
switch (AddrMode) {
|
switch (AddrMode) {
|
||||||
default:
|
default:
|
||||||
assert(false && "Unknown indexed op!");
|
assert(false && "Unknown indexed op!");
|
||||||
@ -211,15 +214,15 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
|||||||
// add more than 1 instruction. Abandon!
|
// add more than 1 instruction. Abandon!
|
||||||
return NULL;
|
return NULL;
|
||||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
|
UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
|
||||||
.addReg(BaseReg).addImm(SOImmVal);
|
.addReg(BaseReg).addImm(SOImmVal).addImm(Pred);
|
||||||
} else if (Amt != 0) {
|
} else if (Amt != 0) {
|
||||||
ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
|
ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
|
||||||
unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
|
unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
|
||||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
|
UpdateMI = BuildMI(get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
|
||||||
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc);
|
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc).addImm(Pred);
|
||||||
} else
|
} else
|
||||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
||||||
.addReg(BaseReg).addReg(OffReg);
|
.addReg(BaseReg).addReg(OffReg).addImm(Pred);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARMII::AddrMode3 : {
|
case ARMII::AddrMode3 : {
|
||||||
@ -228,10 +231,10 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
|||||||
if (OffReg == 0)
|
if (OffReg == 0)
|
||||||
// Immediate is 8-bits. It's guaranteed to fit in a so_imm operand.
|
// Immediate is 8-bits. It's guaranteed to fit in a so_imm operand.
|
||||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
|
UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
|
||||||
.addReg(BaseReg).addImm(Amt);
|
.addReg(BaseReg).addImm(Amt).addImm(Pred);
|
||||||
else
|
else
|
||||||
UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
|
||||||
.addReg(BaseReg).addReg(OffReg);
|
.addReg(BaseReg).addReg(OffReg).addImm(Pred);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,19 +243,19 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
|||||||
if (isPre) {
|
if (isPre) {
|
||||||
if (isLoad)
|
if (isLoad)
|
||||||
MemMI = BuildMI(get(MemOpc), MI->getOperand(0).getReg())
|
MemMI = BuildMI(get(MemOpc), MI->getOperand(0).getReg())
|
||||||
.addReg(WBReg).addReg(0).addImm(0);
|
.addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
|
||||||
else
|
else
|
||||||
MemMI = BuildMI(get(MemOpc)).addReg(MI->getOperand(1).getReg())
|
MemMI = BuildMI(get(MemOpc)).addReg(MI->getOperand(1).getReg())
|
||||||
.addReg(WBReg).addReg(0).addImm(0);
|
.addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
|
||||||
NewMIs.push_back(MemMI);
|
NewMIs.push_back(MemMI);
|
||||||
NewMIs.push_back(UpdateMI);
|
NewMIs.push_back(UpdateMI);
|
||||||
} else {
|
} else {
|
||||||
if (isLoad)
|
if (isLoad)
|
||||||
MemMI = BuildMI(get(MemOpc), MI->getOperand(0).getReg())
|
MemMI = BuildMI(get(MemOpc), MI->getOperand(0).getReg())
|
||||||
.addReg(BaseReg).addReg(0).addImm(0);
|
.addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
|
||||||
else
|
else
|
||||||
MemMI = BuildMI(get(MemOpc)).addReg(MI->getOperand(1).getReg())
|
MemMI = BuildMI(get(MemOpc)).addReg(MI->getOperand(1).getReg())
|
||||||
.addReg(BaseReg).addReg(0).addImm(0);
|
.addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
|
||||||
if (WB.isDead())
|
if (WB.isDead())
|
||||||
UpdateMI->getOperand(0).setIsDead();
|
UpdateMI->getOperand(0).setIsDead();
|
||||||
NewMIs.push_back(UpdateMI);
|
NewMIs.push_back(UpdateMI);
|
||||||
@ -437,7 +440,8 @@ unsigned ARM::GetInstSize(MachineInstr *MI) {
|
|||||||
const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo();
|
const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo();
|
||||||
|
|
||||||
// Basic size info comes from the TSFlags field.
|
// Basic size info comes from the TSFlags field.
|
||||||
unsigned TSFlags = MI->getInstrDescriptor()->TSFlags;
|
const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
|
||||||
|
unsigned TSFlags = TID->TSFlags;
|
||||||
|
|
||||||
switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
|
switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
|
||||||
default:
|
default:
|
||||||
@ -463,7 +467,8 @@ unsigned ARM::GetInstSize(MachineInstr *MI) {
|
|||||||
case ARM::tBR_JTr: {
|
case ARM::tBR_JTr: {
|
||||||
// These are jumptable branches, i.e. a branch followed by an inlined
|
// These are jumptable branches, i.e. a branch followed by an inlined
|
||||||
// jumptable. The size is 4 + 4 * number of entries.
|
// jumptable. The size is 4 + 4 * number of entries.
|
||||||
unsigned JTI = MI->getOperand(MI->getNumOperands()-2).getJumpTableIndex();
|
unsigned NumOps = TID->numOperands;
|
||||||
|
unsigned JTI = MI->getOperand(NumOps-3).getJumpTableIndex();
|
||||||
MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
|
MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
|
||||||
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
|
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
|
||||||
assert(JTI < JT.size());
|
assert(JTI < JT.size());
|
||||||
|
@ -340,7 +340,7 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im,
|
class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||||
dag ops, string asmstr, string cstr>
|
string cstr>
|
||||||
: Instruction {
|
: Instruction {
|
||||||
let Namespace = "ARM";
|
let Namespace = "ARM";
|
||||||
|
|
||||||
@ -354,58 +354,59 @@ class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im,
|
|||||||
IndexMode IM = im;
|
IndexMode IM = im;
|
||||||
bits<2> IndexModeBits = IM.Value;
|
bits<2> IndexModeBits = IM.Value;
|
||||||
|
|
||||||
dag OperandList = ops;
|
|
||||||
let AsmString = asmstr;
|
|
||||||
let Constraints = cstr;
|
let Constraints = cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PseudoInst<dag ops, string asm, list<dag> pattern>
|
class PseudoInst<dag ops, string asm, list<dag> pattern>
|
||||||
: InstARM<0, AddrModeNone, SizeSpecial, IndexModeNone, ops, asm, ""> {
|
: InstARM<0, AddrModeNone, SizeSpecial, IndexModeNone, ""> {
|
||||||
|
let OperandList = ops;
|
||||||
|
let AsmString = asm;
|
||||||
let Pattern = pattern;
|
let Pattern = pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
class I<dag ops, AddrMode am, SizeFlagVal sz, IndexMode im,
|
// Almost all ARM instructions are predicatable.
|
||||||
string asm, string cstr, list<dag> pattern>
|
class I<dag oprnds, AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||||
|
string opc, string asm, string cstr, list<dag> pattern>
|
||||||
// FIXME: Set all opcodes to 0 for now.
|
// FIXME: Set all opcodes to 0 for now.
|
||||||
: InstARM<0, am, sz, im, ops, asm, cstr> {
|
: InstARM<0, am, sz, im, cstr> {
|
||||||
|
let OperandList = !con(oprnds, (ops pred:$p));
|
||||||
|
let AsmString = !strconcat(opc, !strconcat("$p", asm));
|
||||||
let Pattern = pattern;
|
let Pattern = pattern;
|
||||||
list<Predicate> Predicates = [IsARM];
|
list<Predicate> Predicates = [IsARM];
|
||||||
}
|
}
|
||||||
|
|
||||||
class AI<dag ops, string asm, list<dag> pattern>
|
class AI<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrModeNone, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrModeNone, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class AI1<dag ops, string asm, list<dag> pattern>
|
class AI1<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode1, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode1, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class AI2<dag ops, string asm, list<dag> pattern>
|
class AI2<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode2, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode2, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class AI3<dag ops, string asm, list<dag> pattern>
|
class AI3<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode3, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode3, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class AI4<dag ops, string asm, list<dag> pattern>
|
class AI4<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode4, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode4, Size4Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class AIx2<dag ops, string asm, list<dag> pattern>
|
class AI1x2<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrModeNone, Size8Bytes, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode1, Size8Bytes, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class AI1x2<dag ops, string asm, list<dag> pattern>
|
|
||||||
: I<ops, AddrMode1, Size8Bytes, IndexModeNone, asm, "", pattern>;
|
|
||||||
|
|
||||||
// Pre-indexed ops
|
// Pre-indexed ops
|
||||||
class AI2pr<dag ops, string asm, string cstr, list<dag> pattern>
|
class AI2pr<dag ops, string opc, string asm, string cstr, list<dag> pattern>
|
||||||
: I<ops, AddrMode2, Size4Bytes, IndexModePre, asm, cstr, pattern>;
|
: I<ops, AddrMode2, Size4Bytes, IndexModePre, opc, asm, cstr, pattern>;
|
||||||
class AI3pr<dag ops, string asm, string cstr, list<dag> pattern>
|
class AI3pr<dag ops, string opc, string asm, string cstr, list<dag> pattern>
|
||||||
: I<ops, AddrMode3, Size4Bytes, IndexModePre, asm, cstr, pattern>;
|
: I<ops, AddrMode3, Size4Bytes, IndexModePre, opc, asm, cstr, pattern>;
|
||||||
|
|
||||||
// Post-indexed ops
|
// Post-indexed ops
|
||||||
class AI2po<dag ops, string asm, string cstr, list<dag> pattern>
|
class AI2po<dag ops, string opc, string asm, string cstr, list<dag> pattern>
|
||||||
: I<ops, AddrMode2, Size4Bytes, IndexModePost, asm, cstr, pattern>;
|
: I<ops, AddrMode2, Size4Bytes, IndexModePost, opc, asm, cstr, pattern>;
|
||||||
class AI3po<dag ops, string asm, string cstr, list<dag> pattern>
|
class AI3po<dag ops, string opc, string asm, string cstr, list<dag> pattern>
|
||||||
: I<ops, AddrMode3, Size4Bytes, IndexModePost, asm, cstr, pattern>;
|
: I<ops, AddrMode3, Size4Bytes, IndexModePost, opc, asm, cstr, pattern>;
|
||||||
|
|
||||||
// BR_JT instructions
|
// BR_JT instructions
|
||||||
class JTI<dag ops, string asm, list<dag> pattern>
|
class JTI<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrModeNone, SizeSpecial, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrModeNone, SizeSpecial, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class JTI1<dag ops, string asm, list<dag> pattern>
|
class JTI1<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode1, SizeSpecial, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode1, SizeSpecial, IndexModeNone, opc, asm, "", pattern>;
|
||||||
class JTI2<dag ops, string asm, list<dag> pattern>
|
class JTI2<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode2, SizeSpecial, IndexModeNone, asm, "", pattern>;
|
: I<ops, AddrMode2, SizeSpecial, IndexModeNone, opc, asm, "", pattern>;
|
||||||
|
|
||||||
|
|
||||||
class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
|
class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
|
||||||
@ -416,13 +417,13 @@ class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
|
|||||||
/// binop that produces a value.
|
/// binop that produces a value.
|
||||||
multiclass AI1_bin_irs<string opc, PatFrag opnode> {
|
multiclass AI1_bin_irs<string opc, PatFrag opnode> {
|
||||||
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||||
!strconcat(opc, " $dst, $a, $b"),
|
opc, " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
|
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
|
||||||
def rr : AI1<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def rr : AI1<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, " $dst, $a, $b"),
|
opc, " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
|
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
|
||||||
def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||||
!strconcat(opc, " $dst, $a, $b"),
|
opc, " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
|
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,23 +431,23 @@ multiclass AI1_bin_irs<string opc, PatFrag opnode> {
|
|||||||
/// Similar to AI1_bin_irs except the instruction does not produce a result.
|
/// Similar to AI1_bin_irs except the instruction does not produce a result.
|
||||||
multiclass AI1_bin0_irs<string opc, PatFrag opnode> {
|
multiclass AI1_bin0_irs<string opc, PatFrag opnode> {
|
||||||
def ri : AI1<(ops GPR:$a, so_imm:$b),
|
def ri : AI1<(ops GPR:$a, so_imm:$b),
|
||||||
!strconcat(opc, " $a, $b"),
|
opc, " $a, $b",
|
||||||
[(opnode GPR:$a, so_imm:$b)]>;
|
[(opnode GPR:$a, so_imm:$b)]>;
|
||||||
def rr : AI1<(ops GPR:$a, GPR:$b),
|
def rr : AI1<(ops GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, " $a, $b"),
|
opc, " $a, $b",
|
||||||
[(opnode GPR:$a, GPR:$b)]>;
|
[(opnode GPR:$a, GPR:$b)]>;
|
||||||
def rs : AI1<(ops GPR:$a, so_reg:$b),
|
def rs : AI1<(ops GPR:$a, so_reg:$b),
|
||||||
!strconcat(opc, " $a, $b"),
|
opc, " $a, $b",
|
||||||
[(opnode GPR:$a, so_reg:$b)]>;
|
[(opnode GPR:$a, so_reg:$b)]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AI1_bin_is - Defines a set of (op r, {so_imm|so_reg}) patterns for a binop.
|
/// AI1_bin_is - Defines a set of (op r, {so_imm|so_reg}) patterns for a binop.
|
||||||
multiclass AI1_bin_is<string opc, PatFrag opnode> {
|
multiclass AI1_bin_is<string opc, PatFrag opnode> {
|
||||||
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b),
|
||||||
!strconcat(opc, " $dst, $a, $b"),
|
opc, " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
|
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
|
||||||
def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b),
|
||||||
!strconcat(opc, " $dst, $a, $b"),
|
opc, " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
|
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,13 +455,13 @@ multiclass AI1_bin_is<string opc, PatFrag opnode> {
|
|||||||
/// ops.
|
/// ops.
|
||||||
multiclass AI1_unary_irs<string opc, PatFrag opnode> {
|
multiclass AI1_unary_irs<string opc, PatFrag opnode> {
|
||||||
def i : AI1<(ops GPR:$dst, so_imm:$a),
|
def i : AI1<(ops GPR:$dst, so_imm:$a),
|
||||||
!strconcat(opc, " $dst, $a"),
|
opc, " $dst, $a",
|
||||||
[(set GPR:$dst, (opnode so_imm:$a))]>;
|
[(set GPR:$dst, (opnode so_imm:$a))]>;
|
||||||
def r : AI1<(ops GPR:$dst, GPR:$a),
|
def r : AI1<(ops GPR:$dst, GPR:$a),
|
||||||
!strconcat(opc, " $dst, $a"),
|
opc, " $dst, $a",
|
||||||
[(set GPR:$dst, (opnode GPR:$a))]>;
|
[(set GPR:$dst, (opnode GPR:$a))]>;
|
||||||
def s : AI1<(ops GPR:$dst, so_reg:$a),
|
def s : AI1<(ops GPR:$dst, so_reg:$a),
|
||||||
!strconcat(opc, " $dst, $a"),
|
opc, " $dst, $a",
|
||||||
[(set GPR:$dst, (opnode so_reg:$a))]>;
|
[(set GPR:$dst, (opnode so_reg:$a))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,10 +469,10 @@ multiclass AI1_unary_irs<string opc, PatFrag opnode> {
|
|||||||
/// register and one whose operand is a register rotated by 8/16/24.
|
/// register and one whose operand is a register rotated by 8/16/24.
|
||||||
multiclass AI_unary_rrot<string opc, PatFrag opnode> {
|
multiclass AI_unary_rrot<string opc, PatFrag opnode> {
|
||||||
def r : AI<(ops GPR:$dst, GPR:$Src),
|
def r : AI<(ops GPR:$dst, GPR:$Src),
|
||||||
!strconcat(opc, " $dst, $Src"),
|
opc, " $dst, $Src",
|
||||||
[(set GPR:$dst, (opnode GPR:$Src))]>, Requires<[IsARM, HasV6]>;
|
[(set GPR:$dst, (opnode GPR:$Src))]>, Requires<[IsARM, HasV6]>;
|
||||||
def r_rot : AI<(ops GPR:$dst, GPR:$Src, i32imm:$rot),
|
def r_rot : AI<(ops GPR:$dst, GPR:$Src, i32imm:$rot),
|
||||||
!strconcat(opc, " $dst, $Src, ror $rot"),
|
opc, " $dst, $Src, ror $rot",
|
||||||
[(set GPR:$dst, (opnode (rotr GPR:$Src, rot_imm:$rot)))]>,
|
[(set GPR:$dst, (opnode (rotr GPR:$Src, rot_imm:$rot)))]>,
|
||||||
Requires<[IsARM, HasV6]>;
|
Requires<[IsARM, HasV6]>;
|
||||||
}
|
}
|
||||||
@ -480,16 +481,39 @@ multiclass AI_unary_rrot<string opc, PatFrag opnode> {
|
|||||||
/// register and one whose operand is a register rotated by 8/16/24.
|
/// register and one whose operand is a register rotated by 8/16/24.
|
||||||
multiclass AI_bin_rrot<string opc, PatFrag opnode> {
|
multiclass AI_bin_rrot<string opc, PatFrag opnode> {
|
||||||
def rr : AI<(ops GPR:$dst, GPR:$LHS, GPR:$RHS),
|
def rr : AI<(ops GPR:$dst, GPR:$LHS, GPR:$RHS),
|
||||||
!strconcat(opc, " $dst, $LHS, $RHS"),
|
opc, " $dst, $LHS, $RHS",
|
||||||
[(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>,
|
[(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>,
|
||||||
Requires<[IsARM, HasV6]>;
|
Requires<[IsARM, HasV6]>;
|
||||||
def rr_rot : AI<(ops GPR:$dst, GPR:$LHS, GPR:$RHS, i32imm:$rot),
|
def rr_rot : AI<(ops GPR:$dst, GPR:$LHS, GPR:$RHS, i32imm:$rot),
|
||||||
!strconcat(opc, " $dst, $LHS, $RHS, ror $rot"),
|
opc, " $dst, $LHS, $RHS, ror $rot",
|
||||||
[(set GPR:$dst, (opnode GPR:$LHS,
|
[(set GPR:$dst, (opnode GPR:$LHS,
|
||||||
(rotr GPR:$RHS, rot_imm:$rot)))]>,
|
(rotr GPR:$RHS, rot_imm:$rot)))]>,
|
||||||
Requires<[IsARM, HasV6]>;
|
Requires<[IsARM, HasV6]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special cases.
|
||||||
|
class XI<dag oprnds, AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||||
|
string asm, string cstr, list<dag> pattern>
|
||||||
|
// FIXME: Set all opcodes to 0 for now.
|
||||||
|
: InstARM<0, am, sz, im, cstr> {
|
||||||
|
let OperandList = oprnds;
|
||||||
|
let AsmString = asm;
|
||||||
|
let Pattern = pattern;
|
||||||
|
list<Predicate> Predicates = [IsARM];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXI<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrModeNone, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
||||||
|
class AXI1<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrMode1, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
||||||
|
class AXI2<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrMode2, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
||||||
|
class AXI4<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrMode4, Size4Bytes, IndexModeNone, asm, "", pattern>;
|
||||||
|
|
||||||
|
class AXIx2<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrModeNone, Size8Bytes, IndexModeNone, asm, "", pattern>;
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Instructions
|
// Instructions
|
||||||
@ -499,7 +523,7 @@ multiclass AI_bin_rrot<string opc, PatFrag opnode> {
|
|||||||
// Miscellaneous Instructions.
|
// Miscellaneous Instructions.
|
||||||
//
|
//
|
||||||
def IMPLICIT_DEF_GPR :
|
def IMPLICIT_DEF_GPR :
|
||||||
PseudoInst<(ops GPR:$rD),
|
PseudoInst<(ops GPR:$rD, pred:$p),
|
||||||
"@ IMPLICIT_DEF_GPR $rD",
|
"@ IMPLICIT_DEF_GPR $rD",
|
||||||
[(set GPR:$rD, (undef))]>;
|
[(set GPR:$rD, (undef))]>;
|
||||||
|
|
||||||
@ -513,12 +537,12 @@ PseudoInst<(ops cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size),
|
|||||||
"${instid:label} ${cpidx:cpentry}", []>;
|
"${instid:label} ${cpidx:cpentry}", []>;
|
||||||
|
|
||||||
def ADJCALLSTACKUP :
|
def ADJCALLSTACKUP :
|
||||||
PseudoInst<(ops i32imm:$amt),
|
PseudoInst<(ops i32imm:$amt, pred:$p),
|
||||||
"@ ADJCALLSTACKUP $amt",
|
"@ ADJCALLSTACKUP $amt",
|
||||||
[(ARMcallseq_end imm:$amt)]>, Imp<[SP],[SP]>;
|
[(ARMcallseq_end imm:$amt)]>, Imp<[SP],[SP]>;
|
||||||
|
|
||||||
def ADJCALLSTACKDOWN :
|
def ADJCALLSTACKDOWN :
|
||||||
PseudoInst<(ops i32imm:$amt),
|
PseudoInst<(ops i32imm:$amt, pred:$p),
|
||||||
"@ ADJCALLSTACKDOWN $amt",
|
"@ ADJCALLSTACKDOWN $amt",
|
||||||
[(ARMcallseq_start imm:$amt)]>, Imp<[SP],[SP]>;
|
[(ARMcallseq_start imm:$amt)]>, Imp<[SP],[SP]>;
|
||||||
|
|
||||||
@ -527,12 +551,12 @@ PseudoInst<(ops i32imm:$line, i32imm:$col, i32imm:$file),
|
|||||||
".loc $file, $line, $col",
|
".loc $file, $line, $col",
|
||||||
[(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>;
|
[(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>;
|
||||||
|
|
||||||
def PICADD : AI1<(ops GPR:$dst, GPR:$a, pclabel:$cp),
|
def PICADD : AXI1<(ops GPR:$dst, GPR:$a, pclabel:$cp, pred:$p),
|
||||||
"$cp:\n\tadd $dst, pc, $a",
|
"$cp:\n\tadd$p $dst, pc, $a",
|
||||||
[(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>;
|
[(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>;
|
||||||
let AddedComplexity = 10 in
|
let AddedComplexity = 10 in
|
||||||
def PICLD : AI2<(ops GPR:$dst, addrmodepc:$addr),
|
def PICLD : AXI2<(ops GPR:$dst, addrmodepc:$addr, pred:$p),
|
||||||
"${addr:label}:\n\tldr $dst, $addr",
|
"${addr:label}:\n\tldr$p $dst, $addr",
|
||||||
[(set GPR:$dst, (load addrmodepc:$addr))]>;
|
[(set GPR:$dst, (load addrmodepc:$addr))]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -540,53 +564,53 @@ def PICLD : AI2<(ops GPR:$dst, addrmodepc:$addr),
|
|||||||
//
|
//
|
||||||
|
|
||||||
let isReturn = 1, isTerminator = 1 in
|
let isReturn = 1, isTerminator = 1 in
|
||||||
def BX_RET : AI<(ops), "bx lr", [(ARMretflag)]>;
|
def BX_RET : AI<(ops), "bx", " lr", [(ARMretflag)]>;
|
||||||
|
|
||||||
// FIXME: remove when we have a way to marking a MI with these properties.
|
// FIXME: remove when we have a way to marking a MI with these properties.
|
||||||
let isLoad = 1, isReturn = 1, isTerminator = 1 in
|
let isLoad = 1, isReturn = 1, isTerminator = 1 in
|
||||||
def LDM_RET : AI4<(ops addrmode4:$addr, reglist:$dst1, variable_ops),
|
def LDM_RET : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops),
|
||||||
"ldm${addr:submode} $addr, $dst1",
|
"ldm${p}${addr:submode} $addr, $dst1",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
let isCall = 1, noResults = 1,
|
let isCall = 1, noResults = 1,
|
||||||
Defs = [R0, R1, R2, R3, R12, LR,
|
Defs = [R0, R1, R2, R3, R12, LR,
|
||||||
D0, D1, D2, D3, D4, D5, D6, D7] in {
|
D0, D1, D2, D3, D4, D5, D6, D7] in {
|
||||||
def BL : AI<(ops i32imm:$func, variable_ops),
|
def BL : AXI<(ops i32imm:$func, pred:$p, variable_ops),
|
||||||
"bl ${func:call}",
|
"bl$p ${func:call}",
|
||||||
[(ARMcall tglobaladdr:$func)]>;
|
[(ARMcall tglobaladdr:$func)]>;
|
||||||
// ARMv5T and above
|
// ARMv5T and above
|
||||||
def BLX : AI<(ops GPR:$dst, variable_ops),
|
def BLX : AXI<(ops GPR:$dst, pred:$p, variable_ops),
|
||||||
"blx $dst",
|
"blx$p $dst",
|
||||||
[(ARMcall GPR:$dst)]>, Requires<[IsARM, HasV5T]>;
|
[(ARMcall GPR:$dst)]>, Requires<[IsARM, HasV5T]>;
|
||||||
let Uses = [LR] in {
|
let Uses = [LR] in {
|
||||||
// ARMv4T
|
// ARMv4T
|
||||||
def BX : AIx2<(ops GPR:$dst, variable_ops),
|
def BX : AXIx2<(ops GPR:$dst, pred:$p, variable_ops),
|
||||||
"mov lr, pc\n\tbx $dst",
|
"mov$p lr, pc\n\tbx$p $dst",
|
||||||
[(ARMcall_nolink GPR:$dst)]>;
|
[(ARMcall_nolink GPR:$dst)]>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in {
|
||||||
def B : AI<(ops brtarget:$dst), "b $dst",
|
// B can changed into a Bcc, but it is not "predicated".
|
||||||
|
def B : AXI<(ops brtarget:$dst), "b $dst",
|
||||||
[(br bb:$dst)]>;
|
[(br bb:$dst)]>;
|
||||||
|
|
||||||
|
def Bcc : AXI<(ops brtarget:$dst, ccop:$cc), "b$cc $dst",
|
||||||
|
[(ARMbrcond bb:$dst, imm:$cc)]>;
|
||||||
|
|
||||||
def BR_JTr : JTI<(ops GPR:$dst, jtblock_operand:$jt, i32imm:$id),
|
def BR_JTr : JTI<(ops GPR:$dst, jtblock_operand:$jt, i32imm:$id),
|
||||||
"mov pc, $dst \n$jt",
|
"mov", " pc, $dst \n$jt",
|
||||||
[(ARMbrjt GPR:$dst, tjumptable:$jt, imm:$id)]>;
|
[(ARMbrjt GPR:$dst, tjumptable:$jt, imm:$id)]>;
|
||||||
def BR_JTm : JTI2<(ops addrmode2:$dst, jtblock_operand:$jt, i32imm:$id),
|
def BR_JTm : JTI2<(ops addrmode2:$dst, jtblock_operand:$jt, i32imm:$id),
|
||||||
"ldr pc, $dst \n$jt",
|
"ldr", " pc, $dst \n$jt",
|
||||||
[(ARMbrjt (i32 (load addrmode2:$dst)), tjumptable:$jt,
|
[(ARMbrjt (i32 (load addrmode2:$dst)), tjumptable:$jt,
|
||||||
imm:$id)]>;
|
imm:$id)]>;
|
||||||
def BR_JTadd : JTI1<(ops GPR:$dst, GPR:$idx, jtblock_operand:$jt, i32imm:$id),
|
def BR_JTadd : JTI1<(ops GPR:$dst, GPR:$idx, jtblock_operand:$jt, i32imm:$id),
|
||||||
"add pc, $dst, $idx \n$jt",
|
"add", " pc, $dst, $idx \n$jt",
|
||||||
[(ARMbrjt (add GPR:$dst, GPR:$idx), tjumptable:$jt,
|
[(ARMbrjt (add GPR:$dst, GPR:$idx), tjumptable:$jt,
|
||||||
imm:$id)]>;
|
imm:$id)]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in
|
|
||||||
def Bcc : AI<(ops brtarget:$dst, ccop:$cc), "b$cc $dst",
|
|
||||||
[(ARMbrcond bb:$dst, imm:$cc)]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Load / store Instructions.
|
// Load / store Instructions.
|
||||||
//
|
//
|
||||||
@ -594,117 +618,117 @@ let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in
|
|||||||
// Load
|
// Load
|
||||||
let isLoad = 1 in {
|
let isLoad = 1 in {
|
||||||
def LDR : AI2<(ops GPR:$dst, addrmode2:$addr),
|
def LDR : AI2<(ops GPR:$dst, addrmode2:$addr),
|
||||||
"ldr $dst, $addr",
|
"ldr", " $dst, $addr",
|
||||||
[(set GPR:$dst, (load addrmode2:$addr))]>;
|
[(set GPR:$dst, (load addrmode2:$addr))]>;
|
||||||
|
|
||||||
// Special LDR for loads from non-pc-relative constpools.
|
// Special LDR for loads from non-pc-relative constpools.
|
||||||
let isReMaterializable = 1 in
|
let isReMaterializable = 1 in
|
||||||
def LDRcp : AI2<(ops GPR:$dst, addrmode2:$addr),
|
def LDRcp : AI2<(ops GPR:$dst, addrmode2:$addr),
|
||||||
"ldr $dst, $addr", []>;
|
"ldr", " $dst, $addr", []>;
|
||||||
|
|
||||||
// Loads with zero extension
|
// Loads with zero extension
|
||||||
def LDRH : AI3<(ops GPR:$dst, addrmode3:$addr),
|
def LDRH : AI3<(ops GPR:$dst, addrmode3:$addr),
|
||||||
"ldrh $dst, $addr",
|
"ldrh", " $dst, $addr",
|
||||||
[(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>;
|
[(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>;
|
||||||
|
|
||||||
def LDRB : AI2<(ops GPR:$dst, addrmode2:$addr),
|
def LDRB : AI2<(ops GPR:$dst, addrmode2:$addr),
|
||||||
"ldrb $dst, $addr",
|
"ldrb", " $dst, $addr",
|
||||||
[(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>;
|
[(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>;
|
||||||
|
|
||||||
// Loads with sign extension
|
// Loads with sign extension
|
||||||
def LDRSH : AI3<(ops GPR:$dst, addrmode3:$addr),
|
def LDRSH : AI3<(ops GPR:$dst, addrmode3:$addr),
|
||||||
"ldrsh $dst, $addr",
|
"ldrsh", " $dst, $addr",
|
||||||
[(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>;
|
[(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>;
|
||||||
|
|
||||||
def LDRSB : AI3<(ops GPR:$dst, addrmode3:$addr),
|
def LDRSB : AI3<(ops GPR:$dst, addrmode3:$addr),
|
||||||
"ldrsb $dst, $addr",
|
"ldrsb", " $dst, $addr",
|
||||||
[(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>;
|
[(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>;
|
||||||
|
|
||||||
// Load doubleword
|
// Load doubleword
|
||||||
def LDRD : AI3<(ops GPR:$dst, addrmode3:$addr),
|
def LDRD : AI3<(ops GPR:$dst, addrmode3:$addr),
|
||||||
"ldrd $dst, $addr",
|
"ldrd", " $dst, $addr",
|
||||||
[]>, Requires<[IsARM, HasV5T]>;
|
[]>, Requires<[IsARM, HasV5T]>;
|
||||||
|
|
||||||
// Indexed loads
|
// Indexed loads
|
||||||
def LDR_PRE : AI2pr<(ops GPR:$dst, GPR:$base_wb, addrmode2:$addr),
|
def LDR_PRE : AI2pr<(ops GPR:$dst, GPR:$base_wb, addrmode2:$addr),
|
||||||
"ldr $dst, $addr!", "$addr.base = $base_wb", []>;
|
"ldr", " $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||||
|
|
||||||
def LDR_POST : AI2po<(ops GPR:$dst, GPR:$base_wb, GPR:$base, am2offset:$offset),
|
def LDR_POST : AI2po<(ops GPR:$dst, GPR:$base_wb, GPR:$base, am2offset:$offset),
|
||||||
"ldr $dst, [$base], $offset", "$base = $base_wb", []>;
|
"ldr", " $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRH_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr),
|
def LDRH_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr),
|
||||||
"ldrh $dst, $addr!", "$addr.base = $base_wb", []>;
|
"ldrh", " $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRH_POST : AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset),
|
def LDRH_POST : AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset),
|
||||||
"ldrh $dst, [$base], $offset", "$base = $base_wb", []>;
|
"ldrh", " $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRB_PRE : AI2pr<(ops GPR:$dst, GPR:$base_wb, addrmode2:$addr),
|
def LDRB_PRE : AI2pr<(ops GPR:$dst, GPR:$base_wb, addrmode2:$addr),
|
||||||
"ldrb $dst, $addr!", "$addr.base = $base_wb", []>;
|
"ldrb", " $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRB_POST : AI2po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am2offset:$offset),
|
def LDRB_POST : AI2po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am2offset:$offset),
|
||||||
"ldrb $dst, [$base], $offset", "$base = $base_wb", []>;
|
"ldrb", " $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRSH_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr),
|
def LDRSH_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr),
|
||||||
"ldrsh $dst, $addr!", "$addr.base = $base_wb", []>;
|
"ldrsh", " $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRSH_POST: AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset),
|
def LDRSH_POST: AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset),
|
||||||
"ldrsh $dst, [$base], $offset", "$base = $base_wb", []>;
|
"ldrsh", " $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRSB_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr),
|
def LDRSB_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr),
|
||||||
"ldrsb $dst, $addr!", "$addr.base = $base_wb", []>;
|
"ldrsb", " $dst, $addr!", "$addr.base = $base_wb", []>;
|
||||||
|
|
||||||
def LDRSB_POST: AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset),
|
def LDRSB_POST: AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset),
|
||||||
"ldrsb $dst, [$base], $offset", "$base = $base_wb", []>;
|
"ldrsb", " $dst, [$base], $offset", "$base = $base_wb", []>;
|
||||||
} // isLoad
|
} // isLoad
|
||||||
|
|
||||||
// Store
|
// Store
|
||||||
let isStore = 1 in {
|
let isStore = 1 in {
|
||||||
def STR : AI2<(ops GPR:$src, addrmode2:$addr),
|
def STR : AI2<(ops GPR:$src, addrmode2:$addr),
|
||||||
"str $src, $addr",
|
"str", " $src, $addr",
|
||||||
[(store GPR:$src, addrmode2:$addr)]>;
|
[(store GPR:$src, addrmode2:$addr)]>;
|
||||||
|
|
||||||
// Stores with truncate
|
// Stores with truncate
|
||||||
def STRH : AI3<(ops GPR:$src, addrmode3:$addr),
|
def STRH : AI3<(ops GPR:$src, addrmode3:$addr),
|
||||||
"strh $src, $addr",
|
"strh", " $src, $addr",
|
||||||
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
|
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
|
||||||
|
|
||||||
def STRB : AI2<(ops GPR:$src, addrmode2:$addr),
|
def STRB : AI2<(ops GPR:$src, addrmode2:$addr),
|
||||||
"strb $src, $addr",
|
"strb", " $src, $addr",
|
||||||
[(truncstorei8 GPR:$src, addrmode2:$addr)]>;
|
[(truncstorei8 GPR:$src, addrmode2:$addr)]>;
|
||||||
|
|
||||||
// Store doubleword
|
// Store doubleword
|
||||||
def STRD : AI3<(ops GPR:$src, addrmode3:$addr),
|
def STRD : AI3<(ops GPR:$src, addrmode3:$addr),
|
||||||
"strd $src, $addr",
|
"strd", " $src, $addr",
|
||||||
[]>, Requires<[IsARM, HasV5T]>;
|
[]>, Requires<[IsARM, HasV5T]>;
|
||||||
|
|
||||||
// Indexed stores
|
// Indexed stores
|
||||||
def STR_PRE : AI2pr<(ops GPR:$base_wb, GPR:$src, GPR:$base, am2offset:$offset),
|
def STR_PRE : AI2pr<(ops GPR:$base_wb, GPR:$src, GPR:$base, am2offset:$offset),
|
||||||
"str $src, [$base, $offset]!", "$base = $base_wb",
|
"str", " $src, [$base, $offset]!", "$base = $base_wb",
|
||||||
[(set GPR:$base_wb,
|
[(set GPR:$base_wb,
|
||||||
(pre_store GPR:$src, GPR:$base, am2offset:$offset))]>;
|
(pre_store GPR:$src, GPR:$base, am2offset:$offset))]>;
|
||||||
|
|
||||||
def STR_POST : AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
def STR_POST : AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
||||||
"str $src, [$base], $offset", "$base = $base_wb",
|
"str", " $src, [$base], $offset", "$base = $base_wb",
|
||||||
[(set GPR:$base_wb,
|
[(set GPR:$base_wb,
|
||||||
(post_store GPR:$src, GPR:$base, am2offset:$offset))]>;
|
(post_store GPR:$src, GPR:$base, am2offset:$offset))]>;
|
||||||
|
|
||||||
def STRH_PRE : AI3pr<(ops GPR:$base_wb, GPR:$src, GPR:$base,am3offset:$offset),
|
def STRH_PRE : AI3pr<(ops GPR:$base_wb, GPR:$src, GPR:$base,am3offset:$offset),
|
||||||
"strh $src, [$base, $offset]!", "$base = $base_wb",
|
"strh", " $src, [$base, $offset]!", "$base = $base_wb",
|
||||||
[(set GPR:$base_wb,
|
[(set GPR:$base_wb,
|
||||||
(pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>;
|
(pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>;
|
||||||
|
|
||||||
def STRH_POST: AI3po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am3offset:$offset),
|
def STRH_POST: AI3po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am3offset:$offset),
|
||||||
"strh $src, [$base], $offset", "$base = $base_wb",
|
"strh", " $src, [$base], $offset", "$base = $base_wb",
|
||||||
[(set GPR:$base_wb, (post_truncsti16 GPR:$src,
|
[(set GPR:$base_wb, (post_truncsti16 GPR:$src,
|
||||||
GPR:$base, am3offset:$offset))]>;
|
GPR:$base, am3offset:$offset))]>;
|
||||||
|
|
||||||
def STRB_PRE : AI2pr<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
def STRB_PRE : AI2pr<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
||||||
"strb $src, [$base, $offset]!", "$base = $base_wb",
|
"strb", " $src, [$base, $offset]!", "$base = $base_wb",
|
||||||
[(set GPR:$base_wb, (pre_truncsti8 GPR:$src,
|
[(set GPR:$base_wb, (pre_truncsti8 GPR:$src,
|
||||||
GPR:$base, am2offset:$offset))]>;
|
GPR:$base, am2offset:$offset))]>;
|
||||||
|
|
||||||
def STRB_POST: AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
def STRB_POST: AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
||||||
"strb $src, [$base], $offset", "$base = $base_wb",
|
"strb", " $src, [$base], $offset", "$base = $base_wb",
|
||||||
[(set GPR:$base_wb, (post_truncsti8 GPR:$src,
|
[(set GPR:$base_wb, (post_truncsti8 GPR:$src,
|
||||||
GPR:$base, am2offset:$offset))]>;
|
GPR:$base, am2offset:$offset))]>;
|
||||||
} // isStore
|
} // isStore
|
||||||
@ -714,13 +738,13 @@ def STRB_POST: AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset),
|
|||||||
//
|
//
|
||||||
|
|
||||||
let isLoad = 1 in
|
let isLoad = 1 in
|
||||||
def LDM : AI4<(ops addrmode4:$addr, reglist:$dst1, variable_ops),
|
def LDM : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops),
|
||||||
"ldm${addr:submode} $addr, $dst1",
|
"ldm${p}${addr:submode} $addr, $dst1",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
let isStore = 1 in
|
let isStore = 1 in
|
||||||
def STM : AI4<(ops addrmode4:$addr, reglist:$src1, variable_ops),
|
def STM : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$src1, variable_ops),
|
||||||
"stm${addr:submode} $addr, $src1",
|
"stm${p}${addr:submode} $addr, $src1",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -728,28 +752,27 @@ def STM : AI4<(ops addrmode4:$addr, reglist:$src1, variable_ops),
|
|||||||
//
|
//
|
||||||
|
|
||||||
def MOVr : AI1<(ops GPR:$dst, GPR:$src),
|
def MOVr : AI1<(ops GPR:$dst, GPR:$src),
|
||||||
"mov $dst, $src", []>;
|
"mov", " $dst, $src", []>;
|
||||||
def MOVs : AI1<(ops GPR:$dst, so_reg:$src),
|
def MOVs : AI1<(ops GPR:$dst, so_reg:$src),
|
||||||
"mov $dst, $src", [(set GPR:$dst, so_reg:$src)]>;
|
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>;
|
||||||
|
|
||||||
let isReMaterializable = 1 in
|
let isReMaterializable = 1 in
|
||||||
def MOVi : AI1<(ops GPR:$dst, so_imm:$src),
|
def MOVi : AI1<(ops GPR:$dst, so_imm:$src),
|
||||||
"mov $dst, $src", [(set GPR:$dst, so_imm:$src)]>;
|
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>;
|
||||||
|
|
||||||
// These aren't really mov instructions, but we have to define them this way
|
// These aren't really mov instructions, but we have to define them this way
|
||||||
// due to flag operands.
|
// due to flag operands.
|
||||||
|
|
||||||
def MOVsrl_flag : AI1<(ops GPR:$dst, GPR:$src),
|
def MOVsrl_flag : AI1<(ops GPR:$dst, GPR:$src),
|
||||||
"movs $dst, $src, lsr #1",
|
"movs", " $dst, $src, lsr #1",
|
||||||
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>;
|
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>;
|
||||||
def MOVsra_flag : AI1<(ops GPR:$dst, GPR:$src),
|
def MOVsra_flag : AI1<(ops GPR:$dst, GPR:$src),
|
||||||
"movs $dst, $src, asr #1",
|
"movs", " $dst, $src, asr #1",
|
||||||
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>;
|
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>;
|
||||||
def MOVrx : AI1<(ops GPR:$dst, GPR:$src),
|
def MOVrx : AI1<(ops GPR:$dst, GPR:$src),
|
||||||
"mov $dst, $src, rrx",
|
"mov", " $dst, $src, rrx",
|
||||||
[(set GPR:$dst, (ARMrrx GPR:$src))]>;
|
[(set GPR:$dst, (ARMrrx GPR:$src))]>;
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Extend Instructions.
|
// Extend Instructions.
|
||||||
//
|
//
|
||||||
@ -831,12 +854,12 @@ defm EOR : AI1_bin_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>>;
|
|||||||
defm BIC : AI1_bin_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
|
defm BIC : AI1_bin_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
|
||||||
|
|
||||||
def MVNr : AI<(ops GPR:$dst, GPR:$src),
|
def MVNr : AI<(ops GPR:$dst, GPR:$src),
|
||||||
"mvn $dst, $src", [(set GPR:$dst, (not GPR:$src))]>;
|
"mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>;
|
||||||
def MVNs : AI<(ops GPR:$dst, so_reg:$src),
|
def MVNs : AI<(ops GPR:$dst, so_reg:$src),
|
||||||
"mvn $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>;
|
"mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>;
|
||||||
let isReMaterializable = 1 in
|
let isReMaterializable = 1 in
|
||||||
def MVNi : AI<(ops GPR:$dst, so_imm:$imm),
|
def MVNi : AI<(ops GPR:$dst, so_imm:$imm),
|
||||||
"mvn $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>;
|
"mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>;
|
||||||
|
|
||||||
def : ARMPat<(and GPR:$src, so_imm_not:$imm),
|
def : ARMPat<(and GPR:$src, so_imm_not:$imm),
|
||||||
(BICri GPR:$src, so_imm_not:$imm)>;
|
(BICri GPR:$src, so_imm_not:$imm)>;
|
||||||
@ -848,13 +871,13 @@ def : ARMPat<(and GPR:$src, so_imm_not:$imm),
|
|||||||
// AI_orr - Defines a (op r, r) pattern.
|
// AI_orr - Defines a (op r, r) pattern.
|
||||||
class AI_orr<string opc, SDNode opnode>
|
class AI_orr<string opc, SDNode opnode>
|
||||||
: AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
: AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, " $dst, $a, $b"),
|
opc, " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
|
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
|
||||||
|
|
||||||
// AI_oorr - Defines a (op (op r, r), r) pattern.
|
// AI_oorr - Defines a (op (op r, r), r) pattern.
|
||||||
class AI_oorr<string opc, SDNode opnode1, SDNode opnode2>
|
class AI_oorr<string opc, SDNode opnode1, SDNode opnode2>
|
||||||
: AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
: AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
||||||
!strconcat(opc, " $dst, $a, $b, $c"),
|
opc, " $dst, $a, $b, $c",
|
||||||
[(set GPR:$dst, (opnode1 (opnode2 GPR:$a, GPR:$b), GPR:$c))]>;
|
[(set GPR:$dst, (opnode1 (opnode2 GPR:$a, GPR:$b), GPR:$c))]>;
|
||||||
|
|
||||||
def MUL : AI_orr<"mul", mul>;
|
def MUL : AI_orr<"mul", mul>;
|
||||||
@ -862,24 +885,24 @@ def MLA : AI_oorr<"mla", add, mul>;
|
|||||||
|
|
||||||
// Extra precision multiplies with low / high results
|
// Extra precision multiplies with low / high results
|
||||||
def SMULL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
def SMULL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||||
"smull $ldst, $hdst, $a, $b",
|
"smull", " $ldst, $hdst, $a, $b",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
def UMULL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
def UMULL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||||
"umull $ldst, $hdst, $a, $b",
|
"umull", " $ldst, $hdst, $a, $b",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
// Multiply + accumulate
|
// Multiply + accumulate
|
||||||
def SMLAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
def SMLAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||||
"smlal $ldst, $hdst, $a, $b",
|
"smlal", " $ldst, $hdst, $a, $b",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
def UMLAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
def UMLAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||||
"umlal $ldst, $hdst, $a, $b",
|
"umlal", " $ldst, $hdst, $a, $b",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
def UMAAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
def UMAAL : AI<(ops GPR:$ldst, GPR:$hdst, GPR:$a, GPR:$b),
|
||||||
"umaal $ldst, $hdst, $a, $b",
|
"umaal", " $ldst, $hdst, $a, $b",
|
||||||
[]>, Requires<[IsARM, HasV6]>;
|
[]>, Requires<[IsARM, HasV6]>;
|
||||||
|
|
||||||
// Most significant word multiply
|
// Most significant word multiply
|
||||||
@ -888,38 +911,38 @@ def SMMLA : AI_oorr<"smmla", add, mulhs>, Requires<[IsARM, HasV6]>;
|
|||||||
|
|
||||||
|
|
||||||
def SMMLS : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
def SMMLS : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$c),
|
||||||
"smmls $dst, $a, $b, $c",
|
"smmls", " $dst, $a, $b, $c",
|
||||||
[(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>,
|
[(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>,
|
||||||
Requires<[IsARM, HasV6]>;
|
Requires<[IsARM, HasV6]>;
|
||||||
|
|
||||||
multiclass AI_smul<string opc, PatFrag opnode> {
|
multiclass AI_smul<string opc, PatFrag opnode> {
|
||||||
def BB : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def BB : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, "bb $dst, $a, $b"),
|
!strconcat(opc, "bb"), " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
|
[(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
|
||||||
(sext_inreg GPR:$b, i16)))]>,
|
(sext_inreg GPR:$b, i16)))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def BT : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def BT : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, "bt $dst, $a, $b"),
|
!strconcat(opc, "bt"), " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
|
[(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
|
||||||
(sra GPR:$b, 16)))]>,
|
(sra GPR:$b, 16)))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def TB : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def TB : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, "tb $dst, $a, $b"),
|
!strconcat(opc, "tb"), " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode (sra GPR:$a, 16),
|
[(set GPR:$dst, (opnode (sra GPR:$a, 16),
|
||||||
(sext_inreg GPR:$b, i16)))]>,
|
(sext_inreg GPR:$b, i16)))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def TT : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def TT : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, "tt $dst, $a, $b"),
|
!strconcat(opc, "tt"), " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (opnode (sra GPR:$a, 16),
|
[(set GPR:$dst, (opnode (sra GPR:$a, 16),
|
||||||
(sra GPR:$b, 16)))]>,
|
(sra GPR:$b, 16)))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def WB : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def WB : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, "wb $dst, $a, $b"),
|
!strconcat(opc, "wb"), " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (sra (opnode GPR:$a,
|
[(set GPR:$dst, (sra (opnode GPR:$a,
|
||||||
(sext_inreg GPR:$b, i16)), 16))]>,
|
(sext_inreg GPR:$b, i16)), 16))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def WT : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
def WT : AI<(ops GPR:$dst, GPR:$a, GPR:$b),
|
||||||
!strconcat(opc, "wt $dst, $a, $b"),
|
!strconcat(opc, "wt"), " $dst, $a, $b",
|
||||||
[(set GPR:$dst, (sra (opnode GPR:$a,
|
[(set GPR:$dst, (sra (opnode GPR:$a,
|
||||||
(sra GPR:$b, 16)), 16))]>,
|
(sra GPR:$b, 16)), 16))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
@ -927,34 +950,34 @@ multiclass AI_smul<string opc, PatFrag opnode> {
|
|||||||
|
|
||||||
multiclass AI_smla<string opc, PatFrag opnode> {
|
multiclass AI_smla<string opc, PatFrag opnode> {
|
||||||
def BB : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
def BB : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
||||||
!strconcat(opc, "bb $dst, $a, $b, $acc"),
|
!strconcat(opc, "bb"), " $dst, $a, $b, $acc",
|
||||||
[(set GPR:$dst, (add GPR:$acc,
|
[(set GPR:$dst, (add GPR:$acc,
|
||||||
(opnode (sext_inreg GPR:$a, i16),
|
(opnode (sext_inreg GPR:$a, i16),
|
||||||
(sext_inreg GPR:$b, i16))))]>,
|
(sext_inreg GPR:$b, i16))))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def BT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
def BT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
||||||
!strconcat(opc, "bt $dst, $a, $b, $acc"),
|
!strconcat(opc, "bt"), " $dst, $a, $b, $acc",
|
||||||
[(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16),
|
[(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16),
|
||||||
(sra GPR:$b, 16))))]>,
|
(sra GPR:$b, 16))))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def TB : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
def TB : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
||||||
!strconcat(opc, "tb $dst, $a, $b, $acc"),
|
!strconcat(opc, "tb"), " $dst, $a, $b, $acc",
|
||||||
[(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, 16),
|
[(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, 16),
|
||||||
(sext_inreg GPR:$b, i16))))]>,
|
(sext_inreg GPR:$b, i16))))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def TT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
def TT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
||||||
!strconcat(opc, "tt $dst, $a, $b, $acc"),
|
!strconcat(opc, "tt"), " $dst, $a, $b, $acc",
|
||||||
[(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, 16),
|
[(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, 16),
|
||||||
(sra GPR:$b, 16))))]>,
|
(sra GPR:$b, 16))))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
|
|
||||||
def WB : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
def WB : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
||||||
!strconcat(opc, "wb $dst, $a, $b, $acc"),
|
!strconcat(opc, "wb"), " $dst, $a, $b, $acc",
|
||||||
[(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
|
[(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
|
||||||
(sext_inreg GPR:$b, i16)), 16)))]>,
|
(sext_inreg GPR:$b, i16)), 16)))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
def WT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
def WT : AI<(ops GPR:$dst, GPR:$a, GPR:$b, GPR:$acc),
|
||||||
!strconcat(opc, "wt $dst, $a, $b, $acc"),
|
!strconcat(opc, "wt"), " $dst, $a, $b, $acc",
|
||||||
[(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
|
[(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
|
||||||
(sra GPR:$b, 16)), 16)))]>,
|
(sra GPR:$b, 16)), 16)))]>,
|
||||||
Requires<[IsARM, HasV5TE]>;
|
Requires<[IsARM, HasV5TE]>;
|
||||||
@ -971,15 +994,15 @@ defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
|
|||||||
//
|
//
|
||||||
|
|
||||||
def CLZ : AI<(ops GPR:$dst, GPR:$src),
|
def CLZ : AI<(ops GPR:$dst, GPR:$src),
|
||||||
"clz $dst, $src",
|
"clz", " $dst, $src",
|
||||||
[(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]>;
|
[(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]>;
|
||||||
|
|
||||||
def REV : AI<(ops GPR:$dst, GPR:$src),
|
def REV : AI<(ops GPR:$dst, GPR:$src),
|
||||||
"rev $dst, $src",
|
"rev", " $dst, $src",
|
||||||
[(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]>;
|
[(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]>;
|
||||||
|
|
||||||
def REV16 : AI<(ops GPR:$dst, GPR:$src),
|
def REV16 : AI<(ops GPR:$dst, GPR:$src),
|
||||||
"rev16 $dst, $src",
|
"rev16", " $dst, $src",
|
||||||
[(set GPR:$dst,
|
[(set GPR:$dst,
|
||||||
(or (and (srl GPR:$src, 8), 0xFF),
|
(or (and (srl GPR:$src, 8), 0xFF),
|
||||||
(or (and (shl GPR:$src, 8), 0xFF00),
|
(or (and (shl GPR:$src, 8), 0xFF00),
|
||||||
@ -988,7 +1011,7 @@ def REV16 : AI<(ops GPR:$dst, GPR:$src),
|
|||||||
Requires<[IsARM, HasV6]>;
|
Requires<[IsARM, HasV6]>;
|
||||||
|
|
||||||
def REVSH : AI<(ops GPR:$dst, GPR:$src),
|
def REVSH : AI<(ops GPR:$dst, GPR:$src),
|
||||||
"revsh $dst, $src",
|
"revsh", " $dst, $src",
|
||||||
[(set GPR:$dst,
|
[(set GPR:$dst,
|
||||||
(sext_inreg
|
(sext_inreg
|
||||||
(or (srl (and GPR:$src, 0xFF00), 8),
|
(or (srl (and GPR:$src, 0xFF00), 8),
|
||||||
@ -996,7 +1019,7 @@ def REVSH : AI<(ops GPR:$dst, GPR:$src),
|
|||||||
Requires<[IsARM, HasV6]>;
|
Requires<[IsARM, HasV6]>;
|
||||||
|
|
||||||
def PKHBT : AI<(ops GPR:$dst, GPR:$src1, GPR:$src2, i32imm:$shamt),
|
def PKHBT : AI<(ops GPR:$dst, GPR:$src1, GPR:$src2, i32imm:$shamt),
|
||||||
"pkhbt $dst, $src1, $src2, LSL $shamt",
|
"pkhbt", " $dst, $src1, $src2, LSL $shamt",
|
||||||
[(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
|
[(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
|
||||||
(and (shl GPR:$src2, (i32 imm:$shamt)),
|
(and (shl GPR:$src2, (i32 imm:$shamt)),
|
||||||
0xFFFF0000)))]>,
|
0xFFFF0000)))]>,
|
||||||
@ -1010,7 +1033,7 @@ def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
|
|||||||
|
|
||||||
|
|
||||||
def PKHTB : AI<(ops GPR:$dst, GPR:$src1, GPR:$src2, i32imm:$shamt),
|
def PKHTB : AI<(ops GPR:$dst, GPR:$src1, GPR:$src2, i32imm:$shamt),
|
||||||
"pkhtb $dst, $src1, $src2, ASR $shamt",
|
"pkhtb", " $dst, $src1, $src2, ASR $shamt",
|
||||||
[(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
|
[(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
|
||||||
(and (sra GPR:$src2, imm16_31:$shamt),
|
(and (sra GPR:$src2, imm16_31:$shamt),
|
||||||
0xFFFF)))]>, Requires<[IsARM, HasV6]>;
|
0xFFFF)))]>, Requires<[IsARM, HasV6]>;
|
||||||
@ -1046,17 +1069,17 @@ def : ARMPat<(ARMcmpNZ GPR:$src, so_imm_neg:$imm),
|
|||||||
|
|
||||||
|
|
||||||
// Conditional moves
|
// Conditional moves
|
||||||
def MOVCCr : AI<(ops GPR:$dst, GPR:$false, GPR:$true, ccop:$cc),
|
def MOVCCr : AXI<(ops GPR:$dst, GPR:$false, GPR:$true, ccop:$cc),
|
||||||
"mov$cc $dst, $true",
|
"mov$cc $dst, $true",
|
||||||
[(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc))]>,
|
[(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
|
|
||||||
def MOVCCs : AI<(ops GPR:$dst, GPR:$false, so_reg:$true, ccop:$cc),
|
def MOVCCs : AXI<(ops GPR:$dst, GPR:$false, so_reg:$true, ccop:$cc),
|
||||||
"mov$cc $dst, $true",
|
"mov$cc $dst, $true",
|
||||||
[(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true,imm:$cc))]>,
|
[(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true,imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
|
|
||||||
def MOVCCi : AI<(ops GPR:$dst, GPR:$false, so_imm:$true, ccop:$cc),
|
def MOVCCi : AXI<(ops GPR:$dst, GPR:$false, so_imm:$true, ccop:$cc),
|
||||||
"mov$cc $dst, $true",
|
"mov$cc $dst, $true",
|
||||||
[(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true,imm:$cc))]>,
|
[(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true,imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
@ -1064,18 +1087,18 @@ def MOVCCi : AI<(ops GPR:$dst, GPR:$false, so_imm:$true, ccop:$cc),
|
|||||||
|
|
||||||
// LEApcrel - Load a pc-relative address into a register without offending the
|
// LEApcrel - Load a pc-relative address into a register without offending the
|
||||||
// assembler.
|
// assembler.
|
||||||
def LEApcrel : AI1<(ops GPR:$dst, i32imm:$label),
|
def LEApcrel : AXI1<(ops GPR:$dst, i32imm:$label, pred:$p),
|
||||||
!strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
|
!strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
|
||||||
"${:private}PCRELL${:uid}+8))\n"),
|
"${:private}PCRELL${:uid}+8))\n"),
|
||||||
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
||||||
"add $dst, pc, #PCRELV${:uid}")),
|
"add$p $dst, pc, #PCRELV${:uid}")),
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
def LEApcrelJT : AI1<(ops GPR:$dst, i32imm:$label, i32imm:$id),
|
def LEApcrelJT : AXI1<(ops GPR:$dst, i32imm:$label, i32imm:$id, pred:$p),
|
||||||
!strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
|
!strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
|
||||||
"${:private}PCRELL${:uid}+8))\n"),
|
"${:private}PCRELL${:uid}+8))\n"),
|
||||||
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
||||||
"add $dst, pc, #PCRELV${:uid}")),
|
"add$p $dst, pc, #PCRELV${:uid}")),
|
||||||
[]>;
|
[]>;
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// TLS Instructions
|
// TLS Instructions
|
||||||
@ -1085,7 +1108,7 @@ def LEApcrelJT : AI1<(ops GPR:$dst, i32imm:$label, i32imm:$id),
|
|||||||
let isCall = 1,
|
let isCall = 1,
|
||||||
Defs = [R0, R12, LR] in {
|
Defs = [R0, R12, LR] in {
|
||||||
def TPsoft : AI<(ops),
|
def TPsoft : AI<(ops),
|
||||||
"bl __aeabi_read_tp",
|
"bl", " __aeabi_read_tp",
|
||||||
[(set R0, ARMthread_pointer)]>;
|
[(set R0, ARMthread_pointer)]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,7 +1127,7 @@ def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
|
|||||||
// Two piece so_imms.
|
// Two piece so_imms.
|
||||||
let isReMaterializable = 1 in
|
let isReMaterializable = 1 in
|
||||||
def MOVi2pieces : AI1x2<(ops GPR:$dst, so_imm2part:$src),
|
def MOVi2pieces : AI1x2<(ops GPR:$dst, so_imm2part:$src),
|
||||||
"mov $dst, $src",
|
"mov", " $dst, $src",
|
||||||
[(set GPR:$dst, so_imm2part:$src)]>;
|
[(set GPR:$dst, so_imm2part:$src)]>;
|
||||||
|
|
||||||
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
|
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
|
||||||
|
@ -32,7 +32,9 @@ class ThumbV5Pat<dag pattern, dag result> : Pat<pattern, result> {
|
|||||||
class ThumbI<dag ops, AddrMode am, SizeFlagVal sz,
|
class ThumbI<dag ops, AddrMode am, SizeFlagVal sz,
|
||||||
string asm, string cstr, list<dag> pattern>
|
string asm, string cstr, list<dag> pattern>
|
||||||
// FIXME: Set all opcodes to 0 for now.
|
// FIXME: Set all opcodes to 0 for now.
|
||||||
: InstARM<0, am, sz, IndexModeNone, ops, asm, cstr> {
|
: InstARM<0, am, sz, IndexModeNone, cstr> {
|
||||||
|
let OperandList = ops;
|
||||||
|
let AsmString = asm;
|
||||||
let Pattern = pattern;
|
let Pattern = pattern;
|
||||||
list<Predicate> Predicates = [IsThumb];
|
list<Predicate> Predicates = [IsThumb];
|
||||||
}
|
}
|
||||||
@ -157,6 +159,16 @@ def t_addrmode_sp : Operand<i32>,
|
|||||||
// Miscellaneous Instructions.
|
// Miscellaneous Instructions.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
def tADJCALLSTACKUP :
|
||||||
|
PseudoInst<(ops i32imm:$amt),
|
||||||
|
"@ tADJCALLSTACKUP $amt",
|
||||||
|
[(ARMcallseq_end imm:$amt)]>, Imp<[SP],[SP]>, Requires<[IsThumb]>;
|
||||||
|
|
||||||
|
def tADJCALLSTACKDOWN :
|
||||||
|
PseudoInst<(ops i32imm:$amt),
|
||||||
|
"@ tADJCALLSTACKDOWN $amt",
|
||||||
|
[(ARMcallseq_start imm:$amt)]>, Imp<[SP],[SP]>, Requires<[IsThumb]>;
|
||||||
|
|
||||||
def tPICADD : TIt<(ops GPR:$dst, GPR:$lhs, pclabel:$cp),
|
def tPICADD : TIt<(ops GPR:$dst, GPR:$lhs, pclabel:$cp),
|
||||||
"$cp:\n\tadd $dst, pc",
|
"$cp:\n\tadd $dst, pc",
|
||||||
[(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>;
|
[(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>;
|
||||||
|
@ -16,25 +16,49 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// ARM Float Instruction
|
// ARM Float Instruction
|
||||||
class ASI<dag ops, string asm, list<dag> pattern> : AI<ops, asm, pattern> {
|
class ASI<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
|
: AI<ops, opc, asm, pattern> {
|
||||||
// TODO: Mark the instructions with the appropriate subtarget info.
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
}
|
}
|
||||||
|
|
||||||
class ASI5<dag ops, string asm, list<dag> pattern>
|
class ASI5<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode5, Size4Bytes, IndexModeNone, asm, "", pattern> {
|
: I<ops, AddrMode5, Size4Bytes, IndexModeNone, opc, asm, "", pattern> {
|
||||||
// TODO: Mark the instructions with the appropriate subtarget info.
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARM Double Instruction
|
// ARM Double Instruction
|
||||||
class ADI<dag ops, string asm, list<dag> pattern> : AI<ops, asm, pattern> {
|
class ADI<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
|
: AI<ops, opc, asm, pattern> {
|
||||||
// TODO: Mark the instructions with the appropriate subtarget info.
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
}
|
}
|
||||||
|
|
||||||
class ADI5<dag ops, string asm, list<dag> pattern>
|
class ADI5<dag ops, string opc, string asm, list<dag> pattern>
|
||||||
: I<ops, AddrMode5, Size4Bytes, IndexModeNone, asm, "", pattern> {
|
: I<ops, AddrMode5, Size4Bytes, IndexModeNone, opc, asm, "", pattern> {
|
||||||
// TODO: Mark the instructions with the appropriate subtarget info.
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special cases.
|
||||||
|
class AXSI<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrModeNone, Size4Bytes, IndexModeNone, asm, "", pattern> {
|
||||||
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXSI5<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrMode5, Size4Bytes, IndexModeNone, asm, "", pattern> {
|
||||||
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXDI<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrModeNone, Size4Bytes, IndexModeNone, asm, "", pattern> {
|
||||||
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
|
}
|
||||||
|
|
||||||
|
class AXDI5<dag ops, string asm, list<dag> pattern>
|
||||||
|
: XI<ops, AddrMode5, Size4Bytes, IndexModeNone, asm, "", pattern> {
|
||||||
|
// TODO: Mark the instructions with the appropriate subtarget info.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def SDT_FTOI :
|
def SDT_FTOI :
|
||||||
SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;
|
SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;
|
||||||
def SDT_ITOF :
|
def SDT_ITOF :
|
||||||
@ -60,21 +84,21 @@ def arm_fmdrr : SDNode<"ARMISD::FMDRR", SDT_FMDRR>;
|
|||||||
|
|
||||||
let isLoad = 1 in {
|
let isLoad = 1 in {
|
||||||
def FLDD : ADI5<(ops DPR:$dst, addrmode5:$addr),
|
def FLDD : ADI5<(ops DPR:$dst, addrmode5:$addr),
|
||||||
"fldd $dst, $addr",
|
"fldd", " $dst, $addr",
|
||||||
[(set DPR:$dst, (load addrmode5:$addr))]>;
|
[(set DPR:$dst, (load addrmode5:$addr))]>;
|
||||||
|
|
||||||
def FLDS : ASI5<(ops SPR:$dst, addrmode5:$addr),
|
def FLDS : ASI5<(ops SPR:$dst, addrmode5:$addr),
|
||||||
"flds $dst, $addr",
|
"flds", " $dst, $addr",
|
||||||
[(set SPR:$dst, (load addrmode5:$addr))]>;
|
[(set SPR:$dst, (load addrmode5:$addr))]>;
|
||||||
} // isLoad
|
} // isLoad
|
||||||
|
|
||||||
let isStore = 1 in {
|
let isStore = 1 in {
|
||||||
def FSTD : ADI5<(ops DPR:$src, addrmode5:$addr),
|
def FSTD : ADI5<(ops DPR:$src, addrmode5:$addr),
|
||||||
"fstd $src, $addr",
|
"fstd", " $src, $addr",
|
||||||
[(store DPR:$src, addrmode5:$addr)]>;
|
[(store DPR:$src, addrmode5:$addr)]>;
|
||||||
|
|
||||||
def FSTS : ASI5<(ops SPR:$src, addrmode5:$addr),
|
def FSTS : ASI5<(ops SPR:$src, addrmode5:$addr),
|
||||||
"fsts $src, $addr",
|
"fsts", " $src, $addr",
|
||||||
[(store SPR:$src, addrmode5:$addr)]>;
|
[(store SPR:$src, addrmode5:$addr)]>;
|
||||||
} // isStore
|
} // isStore
|
||||||
|
|
||||||
@ -83,22 +107,22 @@ def FSTS : ASI5<(ops SPR:$src, addrmode5:$addr),
|
|||||||
//
|
//
|
||||||
|
|
||||||
let isLoad = 1 in {
|
let isLoad = 1 in {
|
||||||
def FLDMD : ADI5<(ops addrmode5:$addr, reglist:$dst1, variable_ops),
|
def FLDMD : AXDI5<(ops addrmode5:$addr, pred:$p, reglist:$dst1, variable_ops),
|
||||||
"fldm${addr:submode}d ${addr:base}, $dst1",
|
"fldm${p}${addr:submode}d ${addr:base}, $dst1",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
def FLDMS : ASI5<(ops addrmode5:$addr, reglist:$dst1, variable_ops),
|
def FLDMS : AXSI5<(ops addrmode5:$addr, pred:$p, reglist:$dst1, variable_ops),
|
||||||
"fldm${addr:submode}s ${addr:base}, $dst1",
|
"fldm${p}${addr:submode}s ${addr:base}, $dst1",
|
||||||
[]>;
|
[]>;
|
||||||
} // isLoad
|
} // isLoad
|
||||||
|
|
||||||
let isStore = 1 in {
|
let isStore = 1 in {
|
||||||
def FSTMD : ADI5<(ops addrmode5:$addr, reglist:$src1, variable_ops),
|
def FSTMD : AXDI5<(ops addrmode5:$addr, pred:$p, reglist:$src1, variable_ops),
|
||||||
"fstm${addr:submode}d ${addr:base}, $src1",
|
"fstm${p}${addr:submode}d ${addr:base}, $src1",
|
||||||
[]>;
|
[]>;
|
||||||
|
|
||||||
def FSTMS : ASI5<(ops addrmode5:$addr, reglist:$src1, variable_ops),
|
def FSTMS : AXSI5<(ops addrmode5:$addr, pred:$p, reglist:$src1, variable_ops),
|
||||||
"fstm${addr:submode}s ${addr:base}, $src1",
|
"fstm${p}${addr:submode}s ${addr:base}, $src1",
|
||||||
[]>;
|
[]>;
|
||||||
} // isStore
|
} // isStore
|
||||||
|
|
||||||
@ -109,43 +133,43 @@ def FSTMS : ASI5<(ops addrmode5:$addr, reglist:$src1, variable_ops),
|
|||||||
//
|
//
|
||||||
|
|
||||||
def FADDD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
def FADDD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
||||||
"faddd $dst, $a, $b",
|
"faddd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>;
|
[(set DPR:$dst, (fadd DPR:$a, DPR:$b))]>;
|
||||||
|
|
||||||
def FADDS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
def FADDS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
||||||
"fadds $dst, $a, $b",
|
"fadds", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fadd SPR:$a, SPR:$b))]>;
|
[(set SPR:$dst, (fadd SPR:$a, SPR:$b))]>;
|
||||||
|
|
||||||
def FCMPED : ADI<(ops DPR:$a, DPR:$b),
|
def FCMPED : ADI<(ops DPR:$a, DPR:$b),
|
||||||
"fcmped $a, $b",
|
"fcmped", " $a, $b",
|
||||||
[(arm_cmpfp DPR:$a, DPR:$b)]>;
|
[(arm_cmpfp DPR:$a, DPR:$b)]>;
|
||||||
|
|
||||||
def FCMPES : ASI<(ops SPR:$a, SPR:$b),
|
def FCMPES : ASI<(ops SPR:$a, SPR:$b),
|
||||||
"fcmpes $a, $b",
|
"fcmpes", " $a, $b",
|
||||||
[(arm_cmpfp SPR:$a, SPR:$b)]>;
|
[(arm_cmpfp SPR:$a, SPR:$b)]>;
|
||||||
|
|
||||||
def FDIVD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
def FDIVD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
||||||
"fdivd $dst, $a, $b",
|
"fdivd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>;
|
[(set DPR:$dst, (fdiv DPR:$a, DPR:$b))]>;
|
||||||
|
|
||||||
def FDIVS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
def FDIVS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
||||||
"fdivs $dst, $a, $b",
|
"fdivs", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fdiv SPR:$a, SPR:$b))]>;
|
[(set SPR:$dst, (fdiv SPR:$a, SPR:$b))]>;
|
||||||
|
|
||||||
def FMULD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
def FMULD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
||||||
"fmuld $dst, $a, $b",
|
"fmuld", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>;
|
[(set DPR:$dst, (fmul DPR:$a, DPR:$b))]>;
|
||||||
|
|
||||||
def FMULS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
def FMULS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
||||||
"fmuls $dst, $a, $b",
|
"fmuls", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fmul SPR:$a, SPR:$b))]>;
|
[(set SPR:$dst, (fmul SPR:$a, SPR:$b))]>;
|
||||||
|
|
||||||
def FNMULD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
def FNMULD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
||||||
"fnmuld $dst, $a, $b",
|
"fnmuld", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]>;
|
[(set DPR:$dst, (fneg (fmul DPR:$a, DPR:$b)))]>;
|
||||||
|
|
||||||
def FNMULS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
def FNMULS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
||||||
"fnmuls $dst, $a, $b",
|
"fnmuls", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]>;
|
[(set SPR:$dst, (fneg (fmul SPR:$a, SPR:$b)))]>;
|
||||||
|
|
||||||
// Match reassociated forms only if not sign dependent rounding.
|
// Match reassociated forms only if not sign dependent rounding.
|
||||||
@ -156,11 +180,11 @@ def : Pat<(fmul (fneg SPR:$a), SPR:$b),
|
|||||||
|
|
||||||
|
|
||||||
def FSUBD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
def FSUBD : ADI<(ops DPR:$dst, DPR:$a, DPR:$b),
|
||||||
"fsubd $dst, $a, $b",
|
"fsubd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fsub DPR:$a, DPR:$b))]>;
|
[(set DPR:$dst, (fsub DPR:$a, DPR:$b))]>;
|
||||||
|
|
||||||
def FSUBS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
def FSUBS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
||||||
"fsubs $dst, $a, $b",
|
"fsubs", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fsub SPR:$a, SPR:$b))]>;
|
[(set SPR:$dst, (fsub SPR:$a, SPR:$b))]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -168,82 +192,82 @@ def FSUBS : ASI<(ops SPR:$dst, SPR:$a, SPR:$b),
|
|||||||
//
|
//
|
||||||
|
|
||||||
def FABSD : ADI<(ops DPR:$dst, DPR:$a),
|
def FABSD : ADI<(ops DPR:$dst, DPR:$a),
|
||||||
"fabsd $dst, $a",
|
"fabsd", " $dst, $a",
|
||||||
[(set DPR:$dst, (fabs DPR:$a))]>;
|
[(set DPR:$dst, (fabs DPR:$a))]>;
|
||||||
|
|
||||||
def FABSS : ASI<(ops SPR:$dst, SPR:$a),
|
def FABSS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"fabss $dst, $a",
|
"fabss", " $dst, $a",
|
||||||
[(set SPR:$dst, (fabs SPR:$a))]>;
|
[(set SPR:$dst, (fabs SPR:$a))]>;
|
||||||
|
|
||||||
def FCMPEZD : ADI<(ops DPR:$a),
|
def FCMPEZD : ADI<(ops DPR:$a),
|
||||||
"fcmpezd $a",
|
"fcmpezd", " $a",
|
||||||
[(arm_cmpfp0 DPR:$a)]>;
|
[(arm_cmpfp0 DPR:$a)]>;
|
||||||
|
|
||||||
def FCMPEZS : ASI<(ops SPR:$a),
|
def FCMPEZS : ASI<(ops SPR:$a),
|
||||||
"fcmpezs $a",
|
"fcmpezs", " $a",
|
||||||
[(arm_cmpfp0 SPR:$a)]>;
|
[(arm_cmpfp0 SPR:$a)]>;
|
||||||
|
|
||||||
def FCVTDS : ADI<(ops DPR:$dst, SPR:$a),
|
def FCVTDS : ADI<(ops DPR:$dst, SPR:$a),
|
||||||
"fcvtds $dst, $a",
|
"fcvtds", " $dst, $a",
|
||||||
[(set DPR:$dst, (fextend SPR:$a))]>;
|
[(set DPR:$dst, (fextend SPR:$a))]>;
|
||||||
|
|
||||||
def FCVTSD : ADI<(ops SPR:$dst, DPR:$a),
|
def FCVTSD : ADI<(ops SPR:$dst, DPR:$a),
|
||||||
"fcvtsd $dst, $a",
|
"fcvtsd", " $dst, $a",
|
||||||
[(set SPR:$dst, (fround DPR:$a))]>;
|
[(set SPR:$dst, (fround DPR:$a))]>;
|
||||||
|
|
||||||
def FCPYD : ADI<(ops DPR:$dst, DPR:$a),
|
def FCPYD : ADI<(ops DPR:$dst, DPR:$a),
|
||||||
"fcpyd $dst, $a",
|
"fcpyd", " $dst, $a",
|
||||||
[/*(set DPR:$dst, DPR:$a)*/]>;
|
[/*(set DPR:$dst, DPR:$a)*/]>;
|
||||||
|
|
||||||
def FCPYS : ASI<(ops SPR:$dst, SPR:$a),
|
def FCPYS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"fcpys $dst, $a",
|
"fcpys", " $dst, $a",
|
||||||
[/*(set SPR:$dst, SPR:$a)*/]>;
|
[/*(set SPR:$dst, SPR:$a)*/]>;
|
||||||
|
|
||||||
def FNEGD : ADI<(ops DPR:$dst, DPR:$a),
|
def FNEGD : ADI<(ops DPR:$dst, DPR:$a),
|
||||||
"fnegd $dst, $a",
|
"fnegd", " $dst, $a",
|
||||||
[(set DPR:$dst, (fneg DPR:$a))]>;
|
[(set DPR:$dst, (fneg DPR:$a))]>;
|
||||||
|
|
||||||
def FNEGS : ASI<(ops SPR:$dst, SPR:$a),
|
def FNEGS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"fnegs $dst, $a",
|
"fnegs", " $dst, $a",
|
||||||
[(set SPR:$dst, (fneg SPR:$a))]>;
|
[(set SPR:$dst, (fneg SPR:$a))]>;
|
||||||
|
|
||||||
def FSQRTD : ADI<(ops DPR:$dst, DPR:$a),
|
def FSQRTD : ADI<(ops DPR:$dst, DPR:$a),
|
||||||
"fsqrtd $dst, $a",
|
"fsqrtd", " $dst, $a",
|
||||||
[(set DPR:$dst, (fsqrt DPR:$a))]>;
|
[(set DPR:$dst, (fsqrt DPR:$a))]>;
|
||||||
|
|
||||||
def FSQRTS : ASI<(ops SPR:$dst, SPR:$a),
|
def FSQRTS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"fsqrts $dst, $a",
|
"fsqrts", " $dst, $a",
|
||||||
[(set SPR:$dst, (fsqrt SPR:$a))]>;
|
[(set SPR:$dst, (fsqrt SPR:$a))]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// FP <-> GPR Copies. Int <-> FP Conversions.
|
// FP <-> GPR Copies. Int <-> FP Conversions.
|
||||||
//
|
//
|
||||||
|
|
||||||
def IMPLICIT_DEF_SPR : PseudoInst<(ops SPR:$rD),
|
def IMPLICIT_DEF_SPR : PseudoInst<(ops SPR:$rD, pred:$p),
|
||||||
"@ IMPLICIT_DEF_SPR $rD",
|
"@ IMPLICIT_DEF_SPR $rD",
|
||||||
[(set SPR:$rD, (undef))]>;
|
[(set SPR:$rD, (undef))]>;
|
||||||
def IMPLICIT_DEF_DPR : PseudoInst<(ops DPR:$rD),
|
def IMPLICIT_DEF_DPR : PseudoInst<(ops DPR:$rD, pred:$p),
|
||||||
"@ IMPLICIT_DEF_DPR $rD",
|
"@ IMPLICIT_DEF_DPR $rD",
|
||||||
[(set DPR:$rD, (undef))]>;
|
[(set DPR:$rD, (undef))]>;
|
||||||
|
|
||||||
def FMRS : ASI<(ops GPR:$dst, SPR:$src),
|
def FMRS : ASI<(ops GPR:$dst, SPR:$src),
|
||||||
"fmrs $dst, $src",
|
"fmrs", " $dst, $src",
|
||||||
[(set GPR:$dst, (bitconvert SPR:$src))]>;
|
[(set GPR:$dst, (bitconvert SPR:$src))]>;
|
||||||
|
|
||||||
def FMSR : ASI<(ops SPR:$dst, GPR:$src),
|
def FMSR : ASI<(ops SPR:$dst, GPR:$src),
|
||||||
"fmsr $dst, $src",
|
"fmsr", " $dst, $src",
|
||||||
[(set SPR:$dst, (bitconvert GPR:$src))]>;
|
[(set SPR:$dst, (bitconvert GPR:$src))]>;
|
||||||
|
|
||||||
|
|
||||||
def FMRRD : ADI<(ops GPR:$dst1, GPR:$dst2, DPR:$src),
|
def FMRRD : ADI<(ops GPR:$dst1, GPR:$dst2, DPR:$src),
|
||||||
"fmrrd $dst1, $dst2, $src",
|
"fmrrd", " $dst1, $dst2, $src",
|
||||||
[/* FIXME: Can't write pattern for multiple result instr*/]>;
|
[/* FIXME: Can't write pattern for multiple result instr*/]>;
|
||||||
|
|
||||||
// FMDHR: GPR -> SPR
|
// FMDHR: GPR -> SPR
|
||||||
// FMDLR: GPR -> SPR
|
// FMDLR: GPR -> SPR
|
||||||
|
|
||||||
def FMDRR : ADI<(ops DPR:$dst, GPR:$src1, GPR:$src2),
|
def FMDRR : ADI<(ops DPR:$dst, GPR:$src1, GPR:$src2),
|
||||||
"fmdrr $dst, $src1, $src2",
|
"fmdrr", " $dst, $src1, $src2",
|
||||||
[(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>;
|
[(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>;
|
||||||
|
|
||||||
// FMRDH: SPR -> GPR
|
// FMRDH: SPR -> GPR
|
||||||
@ -254,7 +278,7 @@ def FMDRR : ADI<(ops DPR:$dst, GPR:$src1, GPR:$src2),
|
|||||||
// FMSRR: GPR -> SPR
|
// FMSRR: GPR -> SPR
|
||||||
|
|
||||||
|
|
||||||
def FMSTAT : ASI<(ops), "fmstat", [(arm_fmstat)]>;
|
def FMSTAT : ASI<(ops), "fmstat", "", [(arm_fmstat)]>;
|
||||||
|
|
||||||
// FMXR: GPR -> VFP Sstem reg
|
// FMXR: GPR -> VFP Sstem reg
|
||||||
|
|
||||||
@ -262,38 +286,38 @@ def FMSTAT : ASI<(ops), "fmstat", [(arm_fmstat)]>;
|
|||||||
// Int to FP:
|
// Int to FP:
|
||||||
|
|
||||||
def FSITOD : ADI<(ops DPR:$dst, SPR:$a),
|
def FSITOD : ADI<(ops DPR:$dst, SPR:$a),
|
||||||
"fsitod $dst, $a",
|
"fsitod", " $dst, $a",
|
||||||
[(set DPR:$dst, (arm_sitof SPR:$a))]>;
|
[(set DPR:$dst, (arm_sitof SPR:$a))]>;
|
||||||
|
|
||||||
def FSITOS : ASI<(ops SPR:$dst, SPR:$a),
|
def FSITOS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"fsitos $dst, $a",
|
"fsitos", " $dst, $a",
|
||||||
[(set SPR:$dst, (arm_sitof SPR:$a))]>;
|
[(set SPR:$dst, (arm_sitof SPR:$a))]>;
|
||||||
|
|
||||||
def FUITOD : ADI<(ops DPR:$dst, SPR:$a),
|
def FUITOD : ADI<(ops DPR:$dst, SPR:$a),
|
||||||
"fuitod $dst, $a",
|
"fuitod", " $dst, $a",
|
||||||
[(set DPR:$dst, (arm_uitof SPR:$a))]>;
|
[(set DPR:$dst, (arm_uitof SPR:$a))]>;
|
||||||
|
|
||||||
def FUITOS : ASI<(ops SPR:$dst, SPR:$a),
|
def FUITOS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"fuitos $dst, $a",
|
"fuitos", " $dst, $a",
|
||||||
[(set SPR:$dst, (arm_uitof SPR:$a))]>;
|
[(set SPR:$dst, (arm_uitof SPR:$a))]>;
|
||||||
|
|
||||||
// FP to Int:
|
// FP to Int:
|
||||||
// Always set Z bit in the instruction, i.e. "round towards zero" variants.
|
// Always set Z bit in the instruction, i.e. "round towards zero" variants.
|
||||||
|
|
||||||
def FTOSIZD : ADI<(ops SPR:$dst, DPR:$a),
|
def FTOSIZD : ADI<(ops SPR:$dst, DPR:$a),
|
||||||
"ftosizd $dst, $a",
|
"ftosizd", " $dst, $a",
|
||||||
[(set SPR:$dst, (arm_ftosi DPR:$a))]>;
|
[(set SPR:$dst, (arm_ftosi DPR:$a))]>;
|
||||||
|
|
||||||
def FTOSIZS : ASI<(ops SPR:$dst, SPR:$a),
|
def FTOSIZS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"ftosizs $dst, $a",
|
"ftosizs", " $dst, $a",
|
||||||
[(set SPR:$dst, (arm_ftosi SPR:$a))]>;
|
[(set SPR:$dst, (arm_ftosi SPR:$a))]>;
|
||||||
|
|
||||||
def FTOUIZD : ADI<(ops SPR:$dst, DPR:$a),
|
def FTOUIZD : ADI<(ops SPR:$dst, DPR:$a),
|
||||||
"ftouizd $dst, $a",
|
"ftouizd", " $dst, $a",
|
||||||
[(set SPR:$dst, (arm_ftoui DPR:$a))]>;
|
[(set SPR:$dst, (arm_ftoui DPR:$a))]>;
|
||||||
|
|
||||||
def FTOUIZS : ASI<(ops SPR:$dst, SPR:$a),
|
def FTOUIZS : ASI<(ops SPR:$dst, SPR:$a),
|
||||||
"ftouizs $dst, $a",
|
"ftouizs", " $dst, $a",
|
||||||
[(set SPR:$dst, (arm_ftoui SPR:$a))]>;
|
[(set SPR:$dst, (arm_ftoui SPR:$a))]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -301,42 +325,42 @@ def FTOUIZS : ASI<(ops SPR:$dst, SPR:$a),
|
|||||||
//
|
//
|
||||||
|
|
||||||
def FMACD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
def FMACD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
||||||
"fmacd $dst, $a, $b",
|
"fmacd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
|
[(set DPR:$dst, (fadd (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FMACS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
def FMACS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
||||||
"fmacs $dst, $a, $b",
|
"fmacs", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fadd (fmul SPR:$a, SPR:$b), SPR:$dstin))]>,
|
[(set SPR:$dst, (fadd (fmul SPR:$a, SPR:$b), SPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FMSCD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
def FMSCD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
||||||
"fmscd $dst, $a, $b",
|
"fmscd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
|
[(set DPR:$dst, (fsub (fmul DPR:$a, DPR:$b), DPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FMSCS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
def FMSCS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
||||||
"fmscs $dst, $a, $b",
|
"fmscs", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fsub (fmul SPR:$a, SPR:$b), SPR:$dstin))]>,
|
[(set SPR:$dst, (fsub (fmul SPR:$a, SPR:$b), SPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FNMACD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
def FNMACD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
||||||
"fnmacd $dst, $a, $b",
|
"fnmacd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
|
[(set DPR:$dst, (fadd (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FNMACS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
def FNMACS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
||||||
"fnmacs $dst, $a, $b",
|
"fnmacs", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>,
|
[(set SPR:$dst, (fadd (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FNMSCD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
def FNMSCD : ADI<(ops DPR:$dst, DPR:$dstin, DPR:$a, DPR:$b),
|
||||||
"fnmscd $dst, $a, $b",
|
"fnmscd", " $dst, $a, $b",
|
||||||
[(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
|
[(set DPR:$dst, (fsub (fneg (fmul DPR:$a, DPR:$b)), DPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
def FNMSCS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
def FNMSCS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
||||||
"fnmscs $dst, $a, $b",
|
"fnmscs", " $dst, $a, $b",
|
||||||
[(set SPR:$dst, (fsub (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>,
|
[(set SPR:$dst, (fsub (fneg (fmul SPR:$a, SPR:$b)), SPR:$dstin))]>,
|
||||||
RegConstraint<"$dstin = $dst">;
|
RegConstraint<"$dstin = $dst">;
|
||||||
|
|
||||||
@ -344,22 +368,22 @@ def FNMSCS : ASI<(ops SPR:$dst, SPR:$dstin, SPR:$a, SPR:$b),
|
|||||||
// FP Conditional moves.
|
// FP Conditional moves.
|
||||||
//
|
//
|
||||||
|
|
||||||
def FCPYDcc : ADI<(ops DPR:$dst, DPR:$false, DPR:$true, ccop:$cc),
|
def FCPYDcc : AXDI<(ops DPR:$dst, DPR:$false, DPR:$true, ccop:$cc),
|
||||||
"fcpyd$cc $dst, $true",
|
"fcpyd$cc $dst, $true",
|
||||||
[(set DPR:$dst, (ARMcmov DPR:$false, DPR:$true, imm:$cc))]>,
|
[(set DPR:$dst, (ARMcmov DPR:$false, DPR:$true, imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
|
|
||||||
def FCPYScc : ASI<(ops SPR:$dst, SPR:$false, SPR:$true, ccop:$cc),
|
def FCPYScc : AXSI<(ops SPR:$dst, SPR:$false, SPR:$true, ccop:$cc),
|
||||||
"fcpys$cc $dst, $true",
|
"fcpys$cc $dst, $true",
|
||||||
[(set SPR:$dst, (ARMcmov SPR:$false, SPR:$true, imm:$cc))]>,
|
[(set SPR:$dst, (ARMcmov SPR:$false, SPR:$true, imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
|
|
||||||
def FNEGDcc : ADI<(ops DPR:$dst, DPR:$false, DPR:$true, ccop:$cc),
|
def FNEGDcc : AXDI<(ops DPR:$dst, DPR:$false, DPR:$true, ccop:$cc),
|
||||||
"fnegd$cc $dst, $true",
|
"fnegd$cc $dst, $true",
|
||||||
[(set DPR:$dst, (ARMcneg DPR:$false, DPR:$true, imm:$cc))]>,
|
[(set DPR:$dst, (ARMcneg DPR:$false, DPR:$true, imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
|
|
||||||
def FNEGScc : ASI<(ops SPR:$dst, SPR:$false, SPR:$true, ccop:$cc),
|
def FNEGScc : AXSI<(ops SPR:$dst, SPR:$false, SPR:$true, ccop:$cc),
|
||||||
"fnegs$cc $dst, $true",
|
"fnegs$cc $dst, $true",
|
||||||
[(set SPR:$dst, (ARMcneg SPR:$false, SPR:$true, imm:$cc))]>,
|
[(set SPR:$dst, (ARMcneg SPR:$false, SPR:$true, imm:$cc))]>,
|
||||||
RegConstraint<"$false = $dst">;
|
RegConstraint<"$false = $dst">;
|
||||||
|
@ -66,8 +66,8 @@ namespace {
|
|||||||
|
|
||||||
SmallVector<MachineBasicBlock::iterator, 4>
|
SmallVector<MachineBasicBlock::iterator, 4>
|
||||||
MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
|
MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
|
||||||
int Opcode, unsigned Size, unsigned Scratch,
|
int Opcode, unsigned Size, ARMCC::CondCodes Pred,
|
||||||
MemOpQueue &MemOps);
|
unsigned Scratch, MemOpQueue &MemOps);
|
||||||
|
|
||||||
void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
|
void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
|
||||||
bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
|
bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
|
||||||
@ -112,7 +112,7 @@ static int getLoadStoreMultipleOpcode(int Opcode) {
|
|||||||
/// It returns true if the transformation is done.
|
/// It returns true if the transformation is done.
|
||||||
static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||||
int Offset, unsigned Base, bool BaseKill, int Opcode,
|
int Offset, unsigned Base, bool BaseKill, int Opcode,
|
||||||
unsigned Scratch,
|
ARMCC::CondCodes Pred, unsigned Scratch,
|
||||||
SmallVector<std::pair<unsigned, bool>, 8> &Regs,
|
SmallVector<std::pair<unsigned, bool>, 8> &Regs,
|
||||||
const TargetInstrInfo *TII) {
|
const TargetInstrInfo *TII) {
|
||||||
// Only a single register to load / store. Don't bother.
|
// Only a single register to load / store. Don't bother.
|
||||||
@ -156,7 +156,7 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|||||||
return false; // Probably not worth it then.
|
return false; // Probably not worth it then.
|
||||||
|
|
||||||
BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase)
|
BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase)
|
||||||
.addReg(Base, false, false, BaseKill).addImm(ImmedOffset);
|
.addReg(Base, false, false, BaseKill).addImm(ImmedOffset).addImm(Pred);
|
||||||
Base = NewBase;
|
Base = NewBase;
|
||||||
BaseKill = true; // New base is always killed right its use.
|
BaseKill = true; // New base is always killed right its use.
|
||||||
}
|
}
|
||||||
@ -166,9 +166,10 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|||||||
Opcode = getLoadStoreMultipleOpcode(Opcode);
|
Opcode = getLoadStoreMultipleOpcode(Opcode);
|
||||||
MachineInstrBuilder MIB = (isAM4)
|
MachineInstrBuilder MIB = (isAM4)
|
||||||
? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
|
? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
|
||||||
.addImm(ARM_AM::getAM4ModeImm(Mode))
|
.addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred)
|
||||||
: BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
|
: BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
|
||||||
.addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs));
|
.addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs))
|
||||||
|
.addImm(Pred);
|
||||||
for (unsigned i = 0; i != NumRegs; ++i)
|
for (unsigned i = 0; i != NumRegs; ++i)
|
||||||
MIB = MIB.addReg(Regs[i].first, isDef, false, Regs[i].second);
|
MIB = MIB.addReg(Regs[i].first, isDef, false, Regs[i].second);
|
||||||
|
|
||||||
@ -180,9 +181,9 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
|||||||
SmallVector<MachineBasicBlock::iterator, 4>
|
SmallVector<MachineBasicBlock::iterator, 4>
|
||||||
ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
||||||
unsigned Base, int Opcode, unsigned Size,
|
unsigned Base, int Opcode, unsigned Size,
|
||||||
unsigned Scratch, MemOpQueue &MemOps) {
|
ARMCC::CondCodes Pred, unsigned Scratch,
|
||||||
|
MemOpQueue &MemOps) {
|
||||||
SmallVector<MachineBasicBlock::iterator, 4> Merges;
|
SmallVector<MachineBasicBlock::iterator, 4> Merges;
|
||||||
SmallVector<std::pair<unsigned,bool>, 8> Regs;
|
|
||||||
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||||
int Offset = MemOps[SIndex].Offset;
|
int Offset = MemOps[SIndex].Offset;
|
||||||
int SOffset = Offset;
|
int SOffset = Offset;
|
||||||
@ -191,6 +192,8 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
|||||||
unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
|
unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
|
||||||
unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
|
unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
|
||||||
bool isKill = MemOps[SIndex].MBBI->getOperand(0).isKill();
|
bool isKill = MemOps[SIndex].MBBI->getOperand(0).isKill();
|
||||||
|
|
||||||
|
SmallVector<std::pair<unsigned,bool>, 8> Regs;
|
||||||
Regs.push_back(std::make_pair(PReg, isKill));
|
Regs.push_back(std::make_pair(PReg, isKill));
|
||||||
for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
|
for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
|
||||||
int NewOffset = MemOps[i].Offset;
|
int NewOffset = MemOps[i].Offset;
|
||||||
@ -206,7 +209,8 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
|||||||
PRegNum = RegNum;
|
PRegNum = RegNum;
|
||||||
} else {
|
} else {
|
||||||
// Can't merge this in. Try merge the earlier ones first.
|
// Can't merge this in. Try merge the earlier ones first.
|
||||||
if (mergeOps(MBB, ++Loc, SOffset, Base, false, Opcode,Scratch,Regs,TII)) {
|
if (mergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Pred, Scratch,
|
||||||
|
Regs, TII)) {
|
||||||
Merges.push_back(prior(Loc));
|
Merges.push_back(prior(Loc));
|
||||||
for (unsigned j = SIndex; j < i; ++j) {
|
for (unsigned j = SIndex; j < i; ++j) {
|
||||||
MBB.erase(MemOps[j].MBBI);
|
MBB.erase(MemOps[j].MBBI);
|
||||||
@ -214,7 +218,7 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SmallVector<MachineBasicBlock::iterator, 4> Merges2 =
|
SmallVector<MachineBasicBlock::iterator, 4> Merges2 =
|
||||||
MergeLDR_STR(MBB, i, Base, Opcode, Size, Scratch, MemOps);
|
MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, Scratch, MemOps);
|
||||||
Merges.append(Merges2.begin(), Merges2.end());
|
Merges.append(Merges2.begin(), Merges2.end());
|
||||||
return Merges;
|
return Merges;
|
||||||
}
|
}
|
||||||
@ -226,7 +230,8 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1;
|
bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1;
|
||||||
if (mergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode,Scratch,Regs, TII)) {
|
if (mergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Pred, Scratch,
|
||||||
|
Regs, TII)) {
|
||||||
Merges.push_back(prior(Loc));
|
Merges.push_back(prior(Loc));
|
||||||
for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
|
for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
|
||||||
MBB.erase(MemOps[i].MBBI);
|
MBB.erase(MemOps[i].MBBI);
|
||||||
@ -237,20 +242,29 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
|||||||
return Merges;
|
return Merges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getInstrPredicate - If instruction is predicated, returns its predicate
|
||||||
|
/// condition, otherwise returns AL.
|
||||||
|
static ARMCC::CondCodes getInstrPredicate(MachineInstr *MI) {
|
||||||
|
MachineOperand *PredMO = MI->findFirstPredOperand();
|
||||||
|
return PredMO ? (ARMCC::CondCodes)PredMO->getImmedValue() : ARMCC::AL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
|
static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
|
||||||
unsigned Bytes) {
|
unsigned Bytes, ARMCC::CondCodes Pred) {
|
||||||
return (MI && MI->getOpcode() == ARM::SUBri &&
|
return (MI && MI->getOpcode() == ARM::SUBri &&
|
||||||
MI->getOperand(0).getReg() == Base &&
|
MI->getOperand(0).getReg() == Base &&
|
||||||
MI->getOperand(1).getReg() == Base &&
|
MI->getOperand(1).getReg() == Base &&
|
||||||
ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes);
|
ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes &&
|
||||||
|
getInstrPredicate(MI) == Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
|
static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
|
||||||
unsigned Bytes) {
|
unsigned Bytes, ARMCC::CondCodes Pred) {
|
||||||
return (MI && MI->getOpcode() == ARM::ADDri &&
|
return (MI && MI->getOpcode() == ARM::ADDri &&
|
||||||
MI->getOperand(0).getReg() == Base &&
|
MI->getOperand(0).getReg() == Base &&
|
||||||
MI->getOperand(1).getReg() == Base &&
|
MI->getOperand(1).getReg() == Base &&
|
||||||
ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes);
|
ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes &&
|
||||||
|
getInstrPredicate(MI) == Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
|
static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
|
||||||
@ -266,7 +280,7 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
|
|||||||
return 8;
|
return 8;
|
||||||
case ARM::LDM:
|
case ARM::LDM:
|
||||||
case ARM::STM:
|
case ARM::STM:
|
||||||
return (MI->getNumOperands() - 2) * 4;
|
return (MI->getNumOperands() - 3) * 4;
|
||||||
case ARM::FLDMS:
|
case ARM::FLDMS:
|
||||||
case ARM::FSTMS:
|
case ARM::FSTMS:
|
||||||
case ARM::FLDMD:
|
case ARM::FLDMD:
|
||||||
@ -292,6 +306,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
MachineInstr *MI = MBBI;
|
MachineInstr *MI = MBBI;
|
||||||
unsigned Base = MI->getOperand(0).getReg();
|
unsigned Base = MI->getOperand(0).getReg();
|
||||||
unsigned Bytes = getLSMultipleTransferSize(MI);
|
unsigned Bytes = getLSMultipleTransferSize(MI);
|
||||||
|
ARMCC::CondCodes Pred = getInstrPredicate(MI);
|
||||||
int Opcode = MI->getOpcode();
|
int Opcode = MI->getOpcode();
|
||||||
bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::STM;
|
bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::STM;
|
||||||
|
|
||||||
@ -301,7 +316,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
// Can't use the updating AM4 sub-mode if the base register is also a dest
|
// Can't use the updating AM4 sub-mode if the base register is also a dest
|
||||||
// register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined.
|
// register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined.
|
||||||
for (unsigned i = 2, e = MI->getNumOperands(); i != e; ++i) {
|
for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
if (MI->getOperand(i).getReg() == Base)
|
if (MI->getOperand(i).getReg() == Base)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -310,12 +325,12 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin()) {
|
||||||
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
||||||
if (Mode == ARM_AM::ia &&
|
if (Mode == ARM_AM::ia &&
|
||||||
isMatchingDecrement(PrevMBBI, Base, Bytes)) {
|
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true));
|
||||||
MBB.erase(PrevMBBI);
|
MBB.erase(PrevMBBI);
|
||||||
return true;
|
return true;
|
||||||
} else if (Mode == ARM_AM::ib &&
|
} else if (Mode == ARM_AM::ib &&
|
||||||
isMatchingDecrement(PrevMBBI, Base, Bytes)) {
|
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true));
|
||||||
MBB.erase(PrevMBBI);
|
MBB.erase(PrevMBBI);
|
||||||
return true;
|
return true;
|
||||||
@ -325,12 +340,12 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.end()) {
|
if (MBBI != MBB.end()) {
|
||||||
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
||||||
if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
|
if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
|
||||||
isMatchingIncrement(NextMBBI, Base, Bytes)) {
|
isMatchingIncrement(NextMBBI, Base, Bytes, Pred)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
||||||
MBB.erase(NextMBBI);
|
MBB.erase(NextMBBI);
|
||||||
return true;
|
return true;
|
||||||
} else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
|
} else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
|
||||||
isMatchingDecrement(NextMBBI, Base, Bytes)) {
|
isMatchingDecrement(NextMBBI, Base, Bytes, Pred)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
|
||||||
MBB.erase(NextMBBI);
|
MBB.erase(NextMBBI);
|
||||||
return true;
|
return true;
|
||||||
@ -346,7 +361,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin()) {
|
||||||
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
||||||
if (Mode == ARM_AM::ia &&
|
if (Mode == ARM_AM::ia &&
|
||||||
isMatchingDecrement(PrevMBBI, Base, Bytes)) {
|
isMatchingDecrement(PrevMBBI, Base, Bytes, Pred)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset));
|
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset));
|
||||||
MBB.erase(PrevMBBI);
|
MBB.erase(PrevMBBI);
|
||||||
return true;
|
return true;
|
||||||
@ -356,7 +371,7 @@ static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
|||||||
if (MBBI != MBB.end()) {
|
if (MBBI != MBB.end()) {
|
||||||
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
||||||
if (Mode == ARM_AM::ia &&
|
if (Mode == ARM_AM::ia &&
|
||||||
isMatchingIncrement(NextMBBI, Base, Bytes)) {
|
isMatchingIncrement(NextMBBI, Base, Bytes, Pred)) {
|
||||||
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset));
|
MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset));
|
||||||
MBB.erase(NextMBBI);
|
MBB.erase(NextMBBI);
|
||||||
}
|
}
|
||||||
@ -414,16 +429,17 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
if (isLd && MI->getOperand(0).getReg() == Base)
|
if (isLd && MI->getOperand(0).getReg() == Base)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
ARMCC::CondCodes Pred = getInstrPredicate(MI);
|
||||||
bool DoMerge = false;
|
bool DoMerge = false;
|
||||||
ARM_AM::AddrOpc AddSub = ARM_AM::add;
|
ARM_AM::AddrOpc AddSub = ARM_AM::add;
|
||||||
unsigned NewOpc = 0;
|
unsigned NewOpc = 0;
|
||||||
if (MBBI != MBB.begin()) {
|
if (MBBI != MBB.begin()) {
|
||||||
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
|
||||||
if (isMatchingDecrement(PrevMBBI, Base, Bytes)) {
|
if (isMatchingDecrement(PrevMBBI, Base, Bytes, Pred)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
AddSub = ARM_AM::sub;
|
AddSub = ARM_AM::sub;
|
||||||
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
||||||
} else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes)) {
|
} else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes, Pred)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
|
||||||
}
|
}
|
||||||
@ -433,11 +449,11 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
if (!DoMerge && MBBI != MBB.end()) {
|
if (!DoMerge && MBBI != MBB.end()) {
|
||||||
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
MachineBasicBlock::iterator NextMBBI = next(MBBI);
|
||||||
if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes)) {
|
if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes, Pred)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
AddSub = ARM_AM::sub;
|
AddSub = ARM_AM::sub;
|
||||||
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
||||||
} else if (isMatchingIncrement(NextMBBI, Base, Bytes)) {
|
} else if (isMatchingIncrement(NextMBBI, Base, Bytes, Pred)) {
|
||||||
DoMerge = true;
|
DoMerge = true;
|
||||||
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
|
||||||
}
|
}
|
||||||
@ -457,20 +473,22 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
// LDR_PRE, LDR_POST;
|
// LDR_PRE, LDR_POST;
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc), MI->getOperand(0).getReg())
|
BuildMI(MBB, MBBI, TII->get(NewOpc), MI->getOperand(0).getReg())
|
||||||
.addReg(Base, true)
|
.addReg(Base, true)
|
||||||
.addReg(Base).addReg(0).addImm(Offset);
|
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred);
|
||||||
else
|
else
|
||||||
|
// FLDMS, FLDMD
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base, false, false, BaseKill)
|
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base, false, false, BaseKill)
|
||||||
.addImm(Offset).addReg(MI->getOperand(0).getReg(), true);
|
.addImm(Offset).addImm(Pred).addReg(MI->getOperand(0).getReg(), true);
|
||||||
} else {
|
} else {
|
||||||
MachineOperand &MO = MI->getOperand(0);
|
MachineOperand &MO = MI->getOperand(0);
|
||||||
if (isAM2)
|
if (isAM2)
|
||||||
// STR_PRE, STR_POST;
|
// STR_PRE, STR_POST;
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc), Base)
|
BuildMI(MBB, MBBI, TII->get(NewOpc), Base)
|
||||||
.addReg(MO.getReg(), false, false, MO.isKill())
|
.addReg(MO.getReg(), false, false, MO.isKill())
|
||||||
.addReg(Base).addReg(0).addImm(Offset);
|
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
|
// FSTMS, FSTMD
|
||||||
.addImm(Offset).addReg(MO.getReg(), false, false, MO.isKill());
|
BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base).addImm(Offset)
|
||||||
|
.addImm(Pred).addReg(MO.getReg(), false, false, MO.isKill());
|
||||||
}
|
}
|
||||||
MBB.erase(MBBI);
|
MBB.erase(MBBI);
|
||||||
|
|
||||||
@ -521,6 +539,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
unsigned CurrBase = 0;
|
unsigned CurrBase = 0;
|
||||||
int CurrOpc = -1;
|
int CurrOpc = -1;
|
||||||
unsigned CurrSize = 0;
|
unsigned CurrSize = 0;
|
||||||
|
ARMCC::CondCodes CurrPred = ARMCC::AL;
|
||||||
unsigned Position = 0;
|
unsigned Position = 0;
|
||||||
|
|
||||||
RS->enterBasicBlock(&MBB);
|
RS->enterBasicBlock(&MBB);
|
||||||
@ -536,8 +555,9 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||||
unsigned Size = getLSMultipleTransferSize(MBBI);
|
unsigned Size = getLSMultipleTransferSize(MBBI);
|
||||||
unsigned Base = MBBI->getOperand(1).getReg();
|
unsigned Base = MBBI->getOperand(1).getReg();
|
||||||
unsigned OffIdx = MBBI->getNumOperands()-1;
|
ARMCC::CondCodes Pred = getInstrPredicate(MBBI);
|
||||||
unsigned OffField = MBBI->getOperand(OffIdx).getImm();
|
const TargetInstrDescriptor *TID = MBBI->getInstrDescriptor();
|
||||||
|
unsigned OffField = MBBI->getOperand(TID->numOperands-2).getImm();
|
||||||
int Offset = isAM2
|
int Offset = isAM2
|
||||||
? ARM_AM::getAM2Offset(OffField) : ARM_AM::getAM5Offset(OffField) * 4;
|
? ARM_AM::getAM2Offset(OffField) : ARM_AM::getAM5Offset(OffField) * 4;
|
||||||
if (isAM2) {
|
if (isAM2) {
|
||||||
@ -562,6 +582,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
CurrBase = Base;
|
CurrBase = Base;
|
||||||
CurrOpc = Opcode;
|
CurrOpc = Opcode;
|
||||||
CurrSize = Size;
|
CurrSize = Size;
|
||||||
|
CurrPred = Pred;
|
||||||
MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
|
MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
|
||||||
NumMemOps++;
|
NumMemOps++;
|
||||||
Advance = true;
|
Advance = true;
|
||||||
@ -571,7 +592,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
Advance = true;
|
Advance = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrOpc == Opcode && CurrBase == Base) {
|
if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
|
||||||
// Continue adding to the queue.
|
// Continue adding to the queue.
|
||||||
if (Offset > MemOps.back().Offset) {
|
if (Offset > MemOps.back().Offset) {
|
||||||
MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
|
MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
|
||||||
@ -617,7 +638,8 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
|
|
||||||
// Merge ops.
|
// Merge ops.
|
||||||
SmallVector<MachineBasicBlock::iterator,4> MBBII =
|
SmallVector<MachineBasicBlock::iterator,4> MBBII =
|
||||||
MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, Scratch, MemOps);
|
MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, CurrPred,
|
||||||
|
Scratch, MemOps);
|
||||||
|
|
||||||
// Try folding preceeding/trailing base inc/dec into the generated
|
// Try folding preceeding/trailing base inc/dec into the generated
|
||||||
// LDM/STM ops.
|
// LDM/STM ops.
|
||||||
@ -639,6 +661,8 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
|||||||
|
|
||||||
CurrBase = 0;
|
CurrBase = 0;
|
||||||
CurrOpc = -1;
|
CurrOpc = -1;
|
||||||
|
CurrSize = 0;
|
||||||
|
CurrPred = ARMCC::AL;
|
||||||
if (NumMemOps) {
|
if (NumMemOps) {
|
||||||
MemOps.clear();
|
MemOps.clear();
|
||||||
NumMemOps = 0;
|
NumMemOps = 0;
|
||||||
|
@ -144,14 +144,14 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|||||||
.addFrameIndex(FI).addImm(0);
|
.addFrameIndex(FI).addImm(0);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg, false, false, true)
|
BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg, false, false, true)
|
||||||
.addFrameIndex(FI).addReg(0).addImm(0);
|
.addFrameIndex(FI).addReg(0).addImm(0).addImm((int64_t)ARMCC::AL);
|
||||||
} else if (RC == ARM::DPRRegisterClass) {
|
} else if (RC == ARM::DPRRegisterClass) {
|
||||||
BuildMI(MBB, I, TII.get(ARM::FSTD)).addReg(SrcReg, false, false, true)
|
BuildMI(MBB, I, TII.get(ARM::FSTD)).addReg(SrcReg, false, false, true)
|
||||||
.addFrameIndex(FI).addImm(0);
|
.addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL);
|
||||||
} else {
|
} else {
|
||||||
assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
|
assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
|
||||||
BuildMI(MBB, I, TII.get(ARM::FSTS)).addReg(SrcReg, false, false, true)
|
BuildMI(MBB, I, TII.get(ARM::FSTS)).addReg(SrcReg, false, false, true)
|
||||||
.addFrameIndex(FI).addImm(0);
|
.addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,14 +167,14 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|||||||
.addFrameIndex(FI).addImm(0);
|
.addFrameIndex(FI).addImm(0);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, I, TII.get(ARM::LDR), DestReg)
|
BuildMI(MBB, I, TII.get(ARM::LDR), DestReg)
|
||||||
.addFrameIndex(FI).addReg(0).addImm(0);
|
.addFrameIndex(FI).addReg(0).addImm(0).addImm((int64_t)ARMCC::AL);
|
||||||
} else if (RC == ARM::DPRRegisterClass) {
|
} else if (RC == ARM::DPRRegisterClass) {
|
||||||
BuildMI(MBB, I, TII.get(ARM::FLDD), DestReg)
|
BuildMI(MBB, I, TII.get(ARM::FLDD), DestReg)
|
||||||
.addFrameIndex(FI).addImm(0);
|
.addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL);
|
||||||
} else {
|
} else {
|
||||||
assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
|
assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
|
||||||
BuildMI(MBB, I, TII.get(ARM::FLDS), DestReg)
|
BuildMI(MBB, I, TII.get(ARM::FLDS), DestReg)
|
||||||
.addFrameIndex(FI).addImm(0);
|
.addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,12 +185,17 @@ void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
|||||||
if (RC == ARM::GPRRegisterClass) {
|
if (RC == ARM::GPRRegisterClass) {
|
||||||
MachineFunction &MF = *MBB.getParent();
|
MachineFunction &MF = *MBB.getParent();
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||||
BuildMI(MBB, I, TII.get(AFI->isThumbFunction() ? ARM::tMOVr : ARM::MOVr),
|
if (AFI->isThumbFunction())
|
||||||
DestReg).addReg(SrcReg);
|
BuildMI(MBB, I, TII.get(ARM::tMOVr), DestReg).addReg(SrcReg);
|
||||||
|
else
|
||||||
|
BuildMI(MBB, I, TII.get(ARM::MOVr), DestReg).addReg(SrcReg)
|
||||||
|
.addImm((int64_t)ARMCC::AL);
|
||||||
} else if (RC == ARM::SPRRegisterClass)
|
} else if (RC == ARM::SPRRegisterClass)
|
||||||
BuildMI(MBB, I, TII.get(ARM::FCPYS), DestReg).addReg(SrcReg);
|
BuildMI(MBB, I, TII.get(ARM::FCPYS), DestReg).addReg(SrcReg)
|
||||||
|
.addImm((int64_t)ARMCC::AL);
|
||||||
else if (RC == ARM::DPRRegisterClass)
|
else if (RC == ARM::DPRRegisterClass)
|
||||||
BuildMI(MBB, I, TII.get(ARM::FCPYD), DestReg).addReg(SrcReg);
|
BuildMI(MBB, I, TII.get(ARM::FCPYD), DestReg).addReg(SrcReg)
|
||||||
|
.addImm((int64_t)ARMCC::AL);
|
||||||
else
|
else
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -199,7 +204,7 @@ void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
|||||||
/// specified immediate.
|
/// specified immediate.
|
||||||
static void emitLoadConstPool(MachineBasicBlock &MBB,
|
static void emitLoadConstPool(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator &MBBI,
|
MachineBasicBlock::iterator &MBBI,
|
||||||
unsigned DestReg, int Val,
|
unsigned DestReg, ARMCC::CondCodes Pred, int Val,
|
||||||
const TargetInstrInfo &TII, bool isThumb) {
|
const TargetInstrInfo &TII, bool isThumb) {
|
||||||
MachineFunction &MF = *MBB.getParent();
|
MachineFunction &MF = *MBB.getParent();
|
||||||
MachineConstantPool *ConstantPool = MF.getConstantPool();
|
MachineConstantPool *ConstantPool = MF.getConstantPool();
|
||||||
@ -209,7 +214,7 @@ static void emitLoadConstPool(MachineBasicBlock &MBB,
|
|||||||
BuildMI(MBB, MBBI, TII.get(ARM::tLDRcp), DestReg).addConstantPoolIndex(Idx);
|
BuildMI(MBB, MBBI, TII.get(ARM::tLDRcp), DestReg).addConstantPoolIndex(Idx);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, MBBI, TII.get(ARM::LDRcp), DestReg).addConstantPoolIndex(Idx)
|
BuildMI(MBB, MBBI, TII.get(ARM::LDRcp), DestReg).addConstantPoolIndex(Idx)
|
||||||
.addReg(0).addImm(0);
|
.addReg(0).addImm(0).addImm((unsigned)Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMRegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
void ARMRegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||||
@ -217,7 +222,9 @@ void ARMRegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
|||||||
unsigned DestReg,
|
unsigned DestReg,
|
||||||
const MachineInstr *Orig) const {
|
const MachineInstr *Orig) const {
|
||||||
if (Orig->getOpcode() == ARM::MOVi2pieces) {
|
if (Orig->getOpcode() == ARM::MOVi2pieces) {
|
||||||
emitLoadConstPool(MBB, I, DestReg, Orig->getOperand(1).getImmedValue(),
|
emitLoadConstPool(MBB, I, DestReg,
|
||||||
|
(ARMCC::CondCodes)Orig->getOperand(2).getImmedValue(),
|
||||||
|
Orig->getOperand(1).getImmedValue(),
|
||||||
TII, false);
|
TII, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -247,14 +254,15 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI,
|
|||||||
switch (Opc) {
|
switch (Opc) {
|
||||||
default: break;
|
default: break;
|
||||||
case ARM::MOVr: {
|
case ARM::MOVr: {
|
||||||
|
unsigned Pred = MI->getOperand(2).getImmedValue();
|
||||||
if (OpNum == 0) { // move -> store
|
if (OpNum == 0) { // move -> store
|
||||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||||
NewMI = BuildMI(TII.get(ARM::STR)).addReg(SrcReg).addFrameIndex(FI)
|
NewMI = BuildMI(TII.get(ARM::STR)).addReg(SrcReg).addFrameIndex(FI)
|
||||||
.addReg(0).addImm(0);
|
.addReg(0).addImm(0).addImm(Pred);
|
||||||
} else { // move -> load
|
} else { // move -> load
|
||||||
unsigned DstReg = MI->getOperand(0).getReg();
|
unsigned DstReg = MI->getOperand(0).getReg();
|
||||||
NewMI = BuildMI(TII.get(ARM::LDR), DstReg).addFrameIndex(FI).addReg(0)
|
NewMI = BuildMI(TII.get(ARM::LDR), DstReg).addFrameIndex(FI).addReg(0)
|
||||||
.addImm(0);
|
.addImm(0).addImm(Pred);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -277,24 +285,28 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARM::FCPYS: {
|
case ARM::FCPYS: {
|
||||||
|
unsigned Pred = MI->getOperand(2).getImmedValue();
|
||||||
if (OpNum == 0) { // move -> store
|
if (OpNum == 0) { // move -> store
|
||||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||||
NewMI = BuildMI(TII.get(ARM::FSTS)).addReg(SrcReg).addFrameIndex(FI)
|
NewMI = BuildMI(TII.get(ARM::FSTS)).addReg(SrcReg).addFrameIndex(FI)
|
||||||
.addImm(0);
|
.addImm(0).addImm(Pred);
|
||||||
} else { // move -> load
|
} else { // move -> load
|
||||||
unsigned DstReg = MI->getOperand(0).getReg();
|
unsigned DstReg = MI->getOperand(0).getReg();
|
||||||
NewMI = BuildMI(TII.get(ARM::FLDS), DstReg).addFrameIndex(FI).addImm(0);
|
NewMI = BuildMI(TII.get(ARM::FLDS), DstReg).addFrameIndex(FI)
|
||||||
|
.addImm(0).addImm(Pred);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARM::FCPYD: {
|
case ARM::FCPYD: {
|
||||||
|
unsigned Pred = MI->getOperand(2).getImmedValue();
|
||||||
if (OpNum == 0) { // move -> store
|
if (OpNum == 0) { // move -> store
|
||||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||||
NewMI = BuildMI(TII.get(ARM::FSTD)).addReg(SrcReg).addFrameIndex(FI)
|
NewMI = BuildMI(TII.get(ARM::FSTD)).addReg(SrcReg).addFrameIndex(FI)
|
||||||
.addImm(0);
|
.addImm(0).addImm(Pred);
|
||||||
} else { // move -> load
|
} else { // move -> load
|
||||||
unsigned DstReg = MI->getOperand(0).getReg();
|
unsigned DstReg = MI->getOperand(0).getReg();
|
||||||
NewMI = BuildMI(TII.get(ARM::FLDD), DstReg).addFrameIndex(FI).addImm(0);
|
NewMI = BuildMI(TII.get(ARM::FLDD), DstReg).addFrameIndex(FI)
|
||||||
|
.addImm(0).addImm(Pred);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -415,6 +427,7 @@ static
|
|||||||
void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
|
void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator &MBBI,
|
MachineBasicBlock::iterator &MBBI,
|
||||||
unsigned DestReg, unsigned BaseReg,
|
unsigned DestReg, unsigned BaseReg,
|
||||||
|
ARMCC::CondCodes Pred,
|
||||||
int NumBytes, const TargetInstrInfo &TII) {
|
int NumBytes, const TargetInstrInfo &TII) {
|
||||||
bool isSub = NumBytes < 0;
|
bool isSub = NumBytes < 0;
|
||||||
if (isSub) NumBytes = -NumBytes;
|
if (isSub) NumBytes = -NumBytes;
|
||||||
@ -433,7 +446,8 @@ void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
// Build the new ADD / SUB.
|
// Build the new ADD / SUB.
|
||||||
BuildMI(MBB, MBBI, TII.get(isSub ? ARM::SUBri : ARM::ADDri), DestReg)
|
BuildMI(MBB, MBBI, TII.get(isSub ? ARM::SUBri : ARM::ADDri), DestReg)
|
||||||
.addReg(BaseReg, false, false, true).addImm(SOImmVal);
|
.addReg(BaseReg, false, false, true).addImm(SOImmVal)
|
||||||
|
.addImm((unsigned)Pred);
|
||||||
BaseReg = DestReg;
|
BaseReg = DestReg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,7 +512,7 @@ void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
|
|||||||
BuildMI(MBB, MBBI, TII.get(ARM::tNEG), LdReg)
|
BuildMI(MBB, MBBI, TII.get(ARM::tNEG), LdReg)
|
||||||
.addReg(LdReg, false, false, true);
|
.addReg(LdReg, false, false, true);
|
||||||
} else
|
} else
|
||||||
emitLoadConstPool(MBB, MBBI, LdReg, NumBytes, TII, true);
|
emitLoadConstPool(MBB, MBBI, LdReg, ARMCC::AL, NumBytes, TII, true);
|
||||||
|
|
||||||
// Emit add / sub.
|
// Emit add / sub.
|
||||||
int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
|
int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
|
||||||
@ -618,11 +632,12 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
|||||||
|
|
||||||
static
|
static
|
||||||
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
|
||||||
int NumBytes, bool isThumb, const TargetInstrInfo &TII) {
|
ARMCC::CondCodes Pred, int NumBytes, bool isThumb,
|
||||||
|
const TargetInstrInfo &TII) {
|
||||||
if (isThumb)
|
if (isThumb)
|
||||||
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII);
|
emitThumbRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII);
|
||||||
else
|
else
|
||||||
emitARMRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, NumBytes, TII);
|
emitARMRegPlusImmediate(MBB, MBBI, ARM::SP, ARM::SP, Pred, NumBytes, TII);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMRegisterInfo::
|
void ARMRegisterInfo::
|
||||||
@ -643,11 +658,15 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|||||||
Amount = (Amount+Align-1)/Align*Align;
|
Amount = (Amount+Align-1)/Align*Align;
|
||||||
|
|
||||||
// Replace the pseudo instruction with a new instruction...
|
// Replace the pseudo instruction with a new instruction...
|
||||||
if (Old->getOpcode() == ARM::ADJCALLSTACKDOWN) {
|
unsigned Opc = Old->getOpcode();
|
||||||
emitSPUpdate(MBB, I, -Amount, AFI->isThumbFunction(), TII);
|
bool isThumb = AFI->isThumbFunction();
|
||||||
|
ARMCC::CondCodes Pred = isThumb
|
||||||
|
? ARMCC::AL : (ARMCC::CondCodes)Old->getOperand(1).getImmedValue();
|
||||||
|
if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
|
||||||
|
emitSPUpdate(MBB, I, Pred, -Amount, isThumb, TII);
|
||||||
} else {
|
} else {
|
||||||
assert(Old->getOpcode() == ARM::ADJCALLSTACKUP);
|
assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
|
||||||
emitSPUpdate(MBB, I, Amount, AFI->isThumbFunction(), TII);
|
emitSPUpdate(MBB, I, Pred, Amount, isThumb, TII);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -925,7 +944,7 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
if (FrameReg == ARM::SP)
|
if (FrameReg == ARM::SP)
|
||||||
emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,Offset,false,TII);
|
emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,Offset,false,TII);
|
||||||
else {
|
else {
|
||||||
emitLoadConstPool(MBB, II, TmpReg, Offset, TII, true);
|
emitLoadConstPool(MBB, II, TmpReg, ARMCC::AL, Offset, TII, true);
|
||||||
UseRR = true;
|
UseRR = true;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -960,7 +979,7 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
if (FrameReg == ARM::SP)
|
if (FrameReg == ARM::SP)
|
||||||
emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,Offset,false,TII);
|
emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,Offset,false,TII);
|
||||||
else {
|
else {
|
||||||
emitLoadConstPool(MBB, II, TmpReg, Offset, TII, true);
|
emitLoadConstPool(MBB, II, TmpReg, ARMCC::AL, Offset, TII, true);
|
||||||
UseRR = true;
|
UseRR = true;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -990,7 +1009,10 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
if (ScratchReg == 0)
|
if (ScratchReg == 0)
|
||||||
// No register is "free". Scavenge a register.
|
// No register is "free". Scavenge a register.
|
||||||
ScratchReg = RS->scavengeRegister(&ARM::GPRRegClass, II, SPAdj);
|
ScratchReg = RS->scavengeRegister(&ARM::GPRRegClass, II, SPAdj);
|
||||||
emitARMRegPlusImmediate(MBB, II, ScratchReg, FrameReg,
|
MachineOperand *MO = MI.findFirstPredOperand();
|
||||||
|
ARMCC::CondCodes Pred = MO ?
|
||||||
|
(ARMCC::CondCodes)MO->getImmedValue() : ARMCC::AL;
|
||||||
|
emitARMRegPlusImmediate(MBB, II, ScratchReg, FrameReg, Pred,
|
||||||
isSub ? -Offset : Offset, TII);
|
isSub ? -Offset : Offset, TII);
|
||||||
MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
|
MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true);
|
||||||
}
|
}
|
||||||
@ -1293,11 +1315,11 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|||||||
int FramePtrSpillFI = 0;
|
int FramePtrSpillFI = 0;
|
||||||
|
|
||||||
if (VARegSaveSize)
|
if (VARegSaveSize)
|
||||||
emitSPUpdate(MBB, MBBI, -VARegSaveSize, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, -VARegSaveSize, isThumb, TII);
|
||||||
|
|
||||||
if (!AFI->hasStackFrame()) {
|
if (!AFI->hasStackFrame()) {
|
||||||
if (NumBytes != 0)
|
if (NumBytes != 0)
|
||||||
emitSPUpdate(MBB, MBBI, -NumBytes, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, -NumBytes, isThumb, TII);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1337,24 +1359,27 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|||||||
|
|
||||||
if (!isThumb) {
|
if (!isThumb) {
|
||||||
// Build the new SUBri to adjust SP for integer callee-save spill area 1.
|
// Build the new SUBri to adjust SP for integer callee-save spill area 1.
|
||||||
emitSPUpdate(MBB, MBBI, -GPRCS1Size, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, -GPRCS1Size, isThumb, TII);
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, 1, STI);
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, 1, STI);
|
||||||
} else if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH)
|
} else if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tPUSH)
|
||||||
++MBBI;
|
++MBBI;
|
||||||
|
|
||||||
// Darwin ABI requires FP to point to the stack slot that contains the
|
// Darwin ABI requires FP to point to the stack slot that contains the
|
||||||
// previous FP.
|
// previous FP.
|
||||||
if (STI.isTargetDarwin() || hasFP(MF))
|
if (STI.isTargetDarwin() || hasFP(MF)) {
|
||||||
|
MachineInstrBuilder MIB =
|
||||||
BuildMI(MBB, MBBI, TII.get(isThumb ? ARM::tADDrSPi : ARM::ADDri),FramePtr)
|
BuildMI(MBB, MBBI, TII.get(isThumb ? ARM::tADDrSPi : ARM::ADDri),FramePtr)
|
||||||
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
.addFrameIndex(FramePtrSpillFI).addImm(0);
|
||||||
|
if (!isThumb) MIB.addImm(ARMCC::AL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isThumb) {
|
if (!isThumb) {
|
||||||
// Build the new SUBri to adjust SP for integer callee-save spill area 2.
|
// Build the new SUBri to adjust SP for integer callee-save spill area 2.
|
||||||
emitSPUpdate(MBB, MBBI, -GPRCS2Size, false, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, -GPRCS2Size, false, TII);
|
||||||
|
|
||||||
// Build the new SUBri to adjust SP for FP callee-save spill area.
|
// Build the new SUBri to adjust SP for FP callee-save spill area.
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, 2, STI);
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::STR, 2, STI);
|
||||||
emitSPUpdate(MBB, MBBI, -DPRCSSize, false, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, -DPRCSSize, false, TII);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine starting offsets of spill areas.
|
// Determine starting offsets of spill areas.
|
||||||
@ -1371,7 +1396,7 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
|||||||
// Insert it after all the callee-save spills.
|
// Insert it after all the callee-save spills.
|
||||||
if (!isThumb)
|
if (!isThumb)
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::FSTD, 3, STI);
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::FSTD, 3, STI);
|
||||||
emitSPUpdate(MBB, MBBI, -NumBytes, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, -NumBytes, isThumb, TII);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(STI.isTargetELF() && hasFP(MF)) {
|
if(STI.isTargetELF() && hasFP(MF)) {
|
||||||
@ -1414,7 +1439,7 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|||||||
int NumBytes = (int)MFI->getStackSize();
|
int NumBytes = (int)MFI->getStackSize();
|
||||||
if (!AFI->hasStackFrame()) {
|
if (!AFI->hasStackFrame()) {
|
||||||
if (NumBytes != 0)
|
if (NumBytes != 0)
|
||||||
emitSPUpdate(MBB, MBBI, NumBytes, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, NumBytes, isThumb, TII);
|
||||||
} else {
|
} else {
|
||||||
// Unwind MBBI to point to first LDR / FLDD.
|
// Unwind MBBI to point to first LDR / FLDD.
|
||||||
const unsigned *CSRegs = getCalleeSavedRegs();
|
const unsigned *CSRegs = getCalleeSavedRegs();
|
||||||
@ -1444,9 +1469,9 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|||||||
&MBB.front() != MBBI &&
|
&MBB.front() != MBBI &&
|
||||||
prior(MBBI)->getOpcode() == ARM::tPOP) {
|
prior(MBBI)->getOpcode() == ARM::tPOP) {
|
||||||
MachineBasicBlock::iterator PMBBI = prior(MBBI);
|
MachineBasicBlock::iterator PMBBI = prior(MBBI);
|
||||||
emitSPUpdate(MBB, PMBBI, NumBytes, isThumb, TII);
|
emitSPUpdate(MBB, PMBBI, ARMCC::AL, NumBytes, isThumb, TII);
|
||||||
} else
|
} else
|
||||||
emitSPUpdate(MBB, MBBI, NumBytes, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, NumBytes, isThumb, TII);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Darwin ABI requires FP to point to the stack slot that contains the
|
// Darwin ABI requires FP to point to the stack slot that contains the
|
||||||
@ -1461,24 +1486,28 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|||||||
hasFP(MF))
|
hasFP(MF))
|
||||||
if (NumBytes)
|
if (NumBytes)
|
||||||
BuildMI(MBB, MBBI, TII.get(ARM::SUBri), ARM::SP).addReg(FramePtr)
|
BuildMI(MBB, MBBI, TII.get(ARM::SUBri), ARM::SP).addReg(FramePtr)
|
||||||
.addImm(NumBytes);
|
.addImm(NumBytes).addImm((unsigned)ARMCC::AL);
|
||||||
else
|
else
|
||||||
BuildMI(MBB, MBBI, TII.get(ARM::MOVr), ARM::SP).addReg(FramePtr);
|
BuildMI(MBB, MBBI, TII.get(ARM::MOVr), ARM::SP).addReg(FramePtr)
|
||||||
|
.addImm((unsigned)ARMCC::AL);
|
||||||
} else if (NumBytes) {
|
} else if (NumBytes) {
|
||||||
emitSPUpdate(MBB, MBBI, NumBytes, false, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, NumBytes, false, TII);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move SP to start of integer callee save spill area 2.
|
// Move SP to start of integer callee save spill area 2.
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::FLDD, 3, STI);
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::FLDD, 3, STI);
|
||||||
emitSPUpdate(MBB, MBBI, AFI->getDPRCalleeSavedAreaSize(), false, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, AFI->getDPRCalleeSavedAreaSize(),
|
||||||
|
false, TII);
|
||||||
|
|
||||||
// Move SP to start of integer callee save spill area 1.
|
// Move SP to start of integer callee save spill area 1.
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, 2, STI);
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, 2, STI);
|
||||||
emitSPUpdate(MBB, MBBI, AFI->getGPRCalleeSavedArea2Size(), false, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, AFI->getGPRCalleeSavedArea2Size(),
|
||||||
|
false, TII);
|
||||||
|
|
||||||
// Move SP to SP upon entry to the function.
|
// Move SP to SP upon entry to the function.
|
||||||
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, 1, STI);
|
movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, 1, STI);
|
||||||
emitSPUpdate(MBB, MBBI, AFI->getGPRCalleeSavedArea1Size(), false, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, AFI->getGPRCalleeSavedArea1Size(),
|
||||||
|
false, TII);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1488,7 +1517,7 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
|
|||||||
// FIXME: Verify this is still ok when R3 is no longer being reserved.
|
// FIXME: Verify this is still ok when R3 is no longer being reserved.
|
||||||
BuildMI(MBB, MBBI, TII.get(ARM::tPOP)).addReg(ARM::R3);
|
BuildMI(MBB, MBBI, TII.get(ARM::tPOP)).addReg(ARM::R3);
|
||||||
|
|
||||||
emitSPUpdate(MBB, MBBI, VARegSaveSize, isThumb, TII);
|
emitSPUpdate(MBB, MBBI, ARMCC::AL, VARegSaveSize, isThumb, TII);
|
||||||
|
|
||||||
if (isThumb) {
|
if (isThumb) {
|
||||||
BuildMI(MBB, MBBI, TII.get(ARM::tBX_RET_vararg)).addReg(ARM::R3);
|
BuildMI(MBB, MBBI, TII.get(ARM::tBX_RET_vararg)).addReg(ARM::R3);
|
||||||
|
Reference in New Issue
Block a user