mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-19 17:47:38 +00:00
The tLDR et al instructions were emitting either a reg/reg or reg/imm
instruction based on the t_addrmode_s# mode and what it returned. There is some obvious badness to this. In particular, it's hard to do MC-encoding when the instruction may change out from underneath you after the t_addrmode_s# variable is finally resolved. The solution is to revert a long-ago change that merged the reg/reg and reg/imm versions. There is the addition of several new addressing modes. They no longer have extraneous operands associated with them. I.e., if it's reg/reg we don't have to have a dummy zero immediate tacked on to the SDNode. There are some obvious cleanups here, which will happen shortly. llvm-svn: 121747
This commit is contained in:
parent
6a2bed92f5
commit
61720b79f9
@ -1129,13 +1129,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
}
|
||||
{
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(ARM::tSTR);
|
||||
TmpInst.setOpcode(ARM::tSTRi);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(ValReg));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
|
||||
// The offset immediate is #4. The operand value is scaled by 4 for the
|
||||
// tSTR instruction.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(1));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
// Predicate.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
@ -1312,13 +1311,12 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
unsigned ScratchReg = MI->getOperand(1).getReg();
|
||||
{
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(ARM::tLDR);
|
||||
TmpInst.setOpcode(ARM::tLDRi);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
|
||||
// The offset immediate is #8. The operand value is scaled by 4 for the
|
||||
// tSTR instruction.
|
||||
// tLDR instruction.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(2));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
// Predicate.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
@ -1336,11 +1334,10 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
}
|
||||
{
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(ARM::tLDR);
|
||||
TmpInst.setOpcode(ARM::tLDRi);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(ScratchReg));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
|
||||
TmpInst.addOperand(MCOperand::CreateImm(1));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
// Predicate.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
@ -1348,10 +1345,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
}
|
||||
{
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(ARM::tLDR);
|
||||
TmpInst.setOpcode(ARM::tLDRr);
|
||||
TmpInst.addOperand(MCOperand::CreateReg(ARM::R7));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(SrcReg));
|
||||
TmpInst.addOperand(MCOperand::CreateImm(0));
|
||||
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||
// Predicate.
|
||||
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||
|
@ -193,7 +193,7 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getTAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op)
|
||||
unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm12OpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
@ -265,6 +265,8 @@ namespace {
|
||||
const { return 0; }
|
||||
uint32_t getAddrModeSOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
uint32_t getAddrModeISOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
uint32_t getAddrModePCOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
|
||||
|
@ -130,18 +130,24 @@ public:
|
||||
bool SelectAddrModePC(SDValue N, SDValue &Offset,
|
||||
SDValue &Label);
|
||||
|
||||
// Thumb Addressing Modes:
|
||||
bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
|
||||
bool SelectThumbAddrModeRI5(SDValue N, unsigned Scale,
|
||||
SDValue &Base, SDValue &OffImm,
|
||||
SDValue &Offset);
|
||||
bool SelectThumbAddrModeS1(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm, SDValue &Offset);
|
||||
bool SelectThumbAddrModeS2(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm, SDValue &Offset);
|
||||
bool SelectThumbAddrModeS4(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm, SDValue &Offset);
|
||||
bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset,
|
||||
unsigned Scale);
|
||||
bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset);
|
||||
bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset);
|
||||
bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset);
|
||||
bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
|
||||
SDValue &OffImm);
|
||||
bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm);
|
||||
bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm);
|
||||
bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm);
|
||||
bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm);
|
||||
|
||||
// Thumb 2 Addressing Modes:
|
||||
bool SelectT2ShifterOperandReg(SDValue N,
|
||||
SDValue &BaseReg, SDValue &Opc);
|
||||
bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
|
||||
@ -872,9 +878,16 @@ bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
|
||||
MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thumb Addressing Modes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
|
||||
SDValue &Base, SDValue &Offset){
|
||||
// FIXME dl should come from the parent load or store, not the address
|
||||
@ -893,13 +906,13 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
|
||||
}
|
||||
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N,
|
||||
unsigned Scale, SDValue &Base,
|
||||
SDValue &OffImm, SDValue &Offset) {
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base,
|
||||
SDValue &Offset, unsigned Scale) {
|
||||
if (Scale == 4) {
|
||||
SDValue TmpBase, TmpOffImm;
|
||||
if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
|
||||
return false; // We want to select tLDRspi / tSTRspi instead.
|
||||
|
||||
if (N.getOpcode() == ARMISD::Wrapper &&
|
||||
N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
|
||||
return false; // We want to select tLDRpci instead.
|
||||
@ -907,14 +920,13 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N,
|
||||
|
||||
if (N.getOpcode() != ISD::ADD) {
|
||||
if (N.getOpcode() == ARMISD::Wrapper &&
|
||||
!(Subtarget->useMovt() &&
|
||||
N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
|
||||
(!Subtarget->useMovt() ||
|
||||
N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress))
|
||||
Base = N.getOperand(0);
|
||||
} else
|
||||
else
|
||||
Base = N;
|
||||
|
||||
Offset = CurDAG->getRegister(0, MVT::i32);
|
||||
OffImm = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -925,6 +937,68 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N,
|
||||
(RHSR && RHSR->getReg() == ARM::SP)) {
|
||||
Base = N;
|
||||
Offset = CurDAG->getRegister(0, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
int RHSC = (int)RHS->getZExtValue();
|
||||
|
||||
if ((RHSC & (Scale - 1)) == 0) { // The constant is implicitly multiplied.
|
||||
RHSC /= Scale;
|
||||
|
||||
if (RHSC >= 0 && RHSC < 32)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Base = N.getOperand(0);
|
||||
Offset = N.getOperand(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N,
|
||||
SDValue &Base,
|
||||
SDValue &Offset) {
|
||||
return SelectThumbAddrModeRI(N, Base, Offset, 1);
|
||||
}
|
||||
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N,
|
||||
SDValue &Base,
|
||||
SDValue &Offset) {
|
||||
return SelectThumbAddrModeRI(N, Base, Offset, 2);
|
||||
}
|
||||
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N,
|
||||
SDValue &Base,
|
||||
SDValue &Offset) {
|
||||
return SelectThumbAddrModeRI(N, Base, Offset, 4);
|
||||
}
|
||||
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
|
||||
SDValue &Base, SDValue &OffImm) {
|
||||
if (Scale == 4) {
|
||||
SDValue TmpBase, TmpOffImm;
|
||||
if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm))
|
||||
return false; // We want to select tLDRspi / tSTRspi instead.
|
||||
|
||||
if (N.getOpcode() == ARMISD::Wrapper &&
|
||||
N.getOperand(0).getOpcode() == ISD::TargetConstantPool)
|
||||
return false; // We want to select tLDRpci instead.
|
||||
}
|
||||
|
||||
if (N.getOpcode() != ISD::ADD) {
|
||||
if (N.getOpcode() == ARMISD::Wrapper &&
|
||||
!(Subtarget->useMovt() &&
|
||||
N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) {
|
||||
Base = N.getOperand(0);
|
||||
} else {
|
||||
Base = N;
|
||||
}
|
||||
|
||||
OffImm = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
@ -932,11 +1006,12 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N,
|
||||
// If the RHS is + imm5 * scale, fold into addr mode.
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
int RHSC = (int)RHS->getZExtValue();
|
||||
if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied.
|
||||
|
||||
if ((RHSC & (Scale - 1)) == 0) { // The constant is implicitly multiplied.
|
||||
RHSC /= Scale;
|
||||
|
||||
if (RHSC >= 0 && RHSC < 32) {
|
||||
Base = N.getOperand(0);
|
||||
Offset = CurDAG->getRegister(0, MVT::i32);
|
||||
OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
@ -944,27 +1019,26 @@ ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue N,
|
||||
}
|
||||
|
||||
Base = N.getOperand(0);
|
||||
Offset = N.getOperand(1);
|
||||
OffImm = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue N,
|
||||
SDValue &Base, SDValue &OffImm,
|
||||
SDValue &Offset) {
|
||||
return SelectThumbAddrModeRI5(N, 1, Base, OffImm, Offset);
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm) {
|
||||
return SelectThumbAddrModeImm5S(N, 4, Base, OffImm);
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue N,
|
||||
SDValue &Base, SDValue &OffImm,
|
||||
SDValue &Offset) {
|
||||
return SelectThumbAddrModeRI5(N, 2, Base, OffImm, Offset);
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm) {
|
||||
return SelectThumbAddrModeImm5S(N, 2, Base, OffImm);
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue N,
|
||||
SDValue &Base, SDValue &OffImm,
|
||||
SDValue &Offset) {
|
||||
return SelectThumbAddrModeRI5(N, 4, Base, OffImm, Offset);
|
||||
bool
|
||||
ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
|
||||
SDValue &OffImm) {
|
||||
return SelectThumbAddrModeImm5S(N, 1, Base, OffImm);
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
|
||||
@ -1003,6 +1077,12 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thumb 2 Addressing Modes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg,
|
||||
SDValue &Opc) {
|
||||
if (DisableShifterOp)
|
||||
|
@ -94,8 +94,13 @@ def t_blxtarget : Operand<i32> {
|
||||
let EncoderMethod = "getThumbBLXTargetOpValue";
|
||||
}
|
||||
|
||||
def MemModeThumbAsmOperand : AsmOperandClass {
|
||||
let Name = "MemModeThumb";
|
||||
def MemModeRegThumbAsmOperand : AsmOperandClass {
|
||||
let Name = "MemModeRegThumb";
|
||||
let SuperClasses = [];
|
||||
}
|
||||
|
||||
def MemModeImmThumbAsmOperand : AsmOperandClass {
|
||||
let Name = "MemModeImmThumb";
|
||||
let SuperClasses = [];
|
||||
}
|
||||
|
||||
@ -103,42 +108,64 @@ def MemModeThumbAsmOperand : AsmOperandClass {
|
||||
//
|
||||
def t_addrmode_rr : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
|
||||
let EncoderMethod = "getTAddrModeRegRegOpValue";
|
||||
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
|
||||
let PrintMethod = "printThumbAddrModeRROperand";
|
||||
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
|
||||
}
|
||||
|
||||
// t_addrmode_s4 := reg + reg
|
||||
// reg + imm5 * 4
|
||||
// t_addrmode_rrs := reg + reg
|
||||
//
|
||||
def t_addrmode_s4 : Operand<i32>,
|
||||
ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
|
||||
let EncoderMethod = "getAddrModeSOpValue";
|
||||
let PrintMethod = "printThumbAddrModeS4Operand";
|
||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
|
||||
let ParserMatchClass = MemModeThumbAsmOperand;
|
||||
def t_addrmode_rrs1 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> {
|
||||
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
|
||||
let PrintMethod = "printThumbAddrModeRROperand";
|
||||
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
|
||||
let ParserMatchClass = MemModeRegThumbAsmOperand;
|
||||
}
|
||||
|
||||
// t_addrmode_s2 := reg + reg
|
||||
// reg + imm5 * 2
|
||||
//
|
||||
def t_addrmode_s2 : Operand<i32>,
|
||||
ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
|
||||
let EncoderMethod = "getAddrModeSOpValue";
|
||||
let PrintMethod = "printThumbAddrModeS2Operand";
|
||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
|
||||
let ParserMatchClass = MemModeThumbAsmOperand;
|
||||
def t_addrmode_rrs2 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> {
|
||||
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
|
||||
let PrintMethod = "printThumbAddrModeRROperand";
|
||||
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
|
||||
let ParserMatchClass = MemModeRegThumbAsmOperand;
|
||||
}
|
||||
def t_addrmode_rrs4 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> {
|
||||
let EncoderMethod = "getThumbAddrModeRegRegOpValue";
|
||||
let PrintMethod = "printThumbAddrModeRROperand";
|
||||
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
|
||||
let ParserMatchClass = MemModeRegThumbAsmOperand;
|
||||
}
|
||||
|
||||
// t_addrmode_s1 := reg + reg
|
||||
// reg + imm5
|
||||
// t_addrmode_is4 := reg + imm5 * 4
|
||||
//
|
||||
def t_addrmode_s1 : Operand<i32>,
|
||||
ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
|
||||
let EncoderMethod = "getAddrModeSOpValue";
|
||||
let PrintMethod = "printThumbAddrModeS1Operand";
|
||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
|
||||
let ParserMatchClass = MemModeThumbAsmOperand;
|
||||
def t_addrmode_is4 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> {
|
||||
let EncoderMethod = "getAddrModeISOpValue";
|
||||
let PrintMethod = "printThumbAddrModeImm5S4Operand";
|
||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
|
||||
let ParserMatchClass = MemModeImmThumbAsmOperand;
|
||||
}
|
||||
|
||||
// t_addrmode_is2 := reg + imm5 * 2
|
||||
//
|
||||
def t_addrmode_is2 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> {
|
||||
let EncoderMethod = "getAddrModeISOpValue";
|
||||
let PrintMethod = "printThumbAddrModeImm5S2Operand";
|
||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
|
||||
let ParserMatchClass = MemModeImmThumbAsmOperand;
|
||||
}
|
||||
|
||||
// t_addrmode_is1 := reg + imm5
|
||||
//
|
||||
def t_addrmode_is1 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> {
|
||||
let EncoderMethod = "getAddrModeISOpValue";
|
||||
let PrintMethod = "printThumbAddrModeImm5S1Operand";
|
||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
|
||||
let ParserMatchClass = MemModeImmThumbAsmOperand;
|
||||
}
|
||||
|
||||
// t_addrmode_sp := sp + imm8 * 4
|
||||
@ -148,14 +175,14 @@ def t_addrmode_sp : Operand<i32>,
|
||||
let EncoderMethod = "getAddrModeThumbSPOpValue";
|
||||
let PrintMethod = "printThumbAddrModeSPOperand";
|
||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||
let ParserMatchClass = MemModeThumbAsmOperand;
|
||||
let ParserMatchClass = MemModeImmThumbAsmOperand;
|
||||
}
|
||||
|
||||
// t_addrmode_pc := <label> => pc + imm8 * 4
|
||||
//
|
||||
def t_addrmode_pc : Operand<i32> {
|
||||
let EncoderMethod = "getAddrModePCOpValue";
|
||||
let ParserMatchClass = MemModeThumbAsmOperand;
|
||||
let ParserMatchClass = MemModeImmThumbAsmOperand;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -580,41 +607,41 @@ def tTRAP : TI<(outs), (ins), IIC_Br,
|
||||
//
|
||||
|
||||
let canFoldAsLoad = 1, isReMaterializable = 1 in
|
||||
def tLDR : // A8.6.60
|
||||
T1pILdStEncode<0b100, (outs tGPR:$Rt), (ins t_addrmode_s4:$addr),
|
||||
def tLDRr : // A8.6.60
|
||||
T1pILdStEncode<0b100, (outs tGPR:$Rt), (ins t_addrmode_rrs4:$addr),
|
||||
AddrModeT1_4, IIC_iLoad_r,
|
||||
"ldr", "\t$Rt, $addr",
|
||||
[(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>;
|
||||
[(set tGPR:$Rt, (load t_addrmode_rrs4:$addr))]>;
|
||||
|
||||
def tLDRi : // A8.6.57
|
||||
T1pILdStEncodeImm<0b0110, 1, (outs tGPR:$Rt), (ins t_addrmode_s4:$addr),
|
||||
T1pILdStEncodeImm<0b0110, 1, (outs tGPR:$Rt), (ins t_addrmode_is4:$addr),
|
||||
AddrModeT1_4, IIC_iLoad_r,
|
||||
"ldr", "\t$Rt, $addr",
|
||||
[]>;
|
||||
[(set tGPR:$Rt, (load t_addrmode_is4:$addr))]>;
|
||||
|
||||
def tLDRB : // A8.6.64
|
||||
T1pILdStEncode<0b110, (outs tGPR:$Rt), (ins t_addrmode_s1:$addr),
|
||||
def tLDRBr : // A8.6.64
|
||||
T1pILdStEncode<0b110, (outs tGPR:$Rt), (ins t_addrmode_rrs1:$addr),
|
||||
AddrModeT1_1, IIC_iLoad_bh_r,
|
||||
"ldrb", "\t$Rt, $addr",
|
||||
[(set tGPR:$Rt, (zextloadi8 t_addrmode_s1:$addr))]>;
|
||||
[(set tGPR:$Rt, (zextloadi8 t_addrmode_rrs1:$addr))]>;
|
||||
|
||||
def tLDRBi : // A8.6.61
|
||||
T1pILdStEncodeImm<0b0111, 1, (outs tGPR:$Rt), (ins t_addrmode_s1:$addr),
|
||||
T1pILdStEncodeImm<0b0111, 1, (outs tGPR:$Rt), (ins t_addrmode_is1:$addr),
|
||||
AddrModeT1_1, IIC_iLoad_bh_r,
|
||||
"ldrb", "\t$Rt, $addr",
|
||||
[]>;
|
||||
[(set tGPR:$Rt, (zextloadi8 t_addrmode_is1:$addr))]>;
|
||||
|
||||
def tLDRH : // A8.6.76
|
||||
T1pILdStEncode<0b101, (outs tGPR:$dst), (ins t_addrmode_s2:$addr),
|
||||
def tLDRHr : // A8.6.76
|
||||
T1pILdStEncode<0b101, (outs tGPR:$Rt), (ins t_addrmode_rrs2:$addr),
|
||||
AddrModeT1_2, IIC_iLoad_bh_r,
|
||||
"ldrh", "\t$dst, $addr",
|
||||
[(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
|
||||
"ldrh", "\t$Rt, $addr",
|
||||
[(set tGPR:$Rt, (zextloadi16 t_addrmode_rrs2:$addr))]>;
|
||||
|
||||
def tLDRHi : // A8.6.73
|
||||
T1pILdStEncodeImm<0b1000, 1, (outs tGPR:$Rt), (ins t_addrmode_s2:$addr),
|
||||
T1pILdStEncodeImm<0b1000, 1, (outs tGPR:$Rt), (ins t_addrmode_is2:$addr),
|
||||
AddrModeT1_2, IIC_iLoad_bh_r,
|
||||
"ldrh", "\t$Rt, $addr",
|
||||
[]>;
|
||||
[(set tGPR:$Rt, (zextloadi16 t_addrmode_is2:$addr))]>;
|
||||
|
||||
let AddedComplexity = 10 in
|
||||
def tLDRSB : // A8.6.80
|
||||
@ -676,45 +703,45 @@ def tLDRcp : T1pIs<(outs tGPR:$Rt), (ins i32imm:$addr), IIC_iLoad_i,
|
||||
let Inst{7-0} = addr;
|
||||
}
|
||||
|
||||
def tSTR : // A8.6.194
|
||||
T1pILdStEncode<0b000, (outs), (ins tGPR:$src, t_addrmode_s4:$addr),
|
||||
def tSTRr : // A8.6.194
|
||||
T1pILdStEncode<0b000, (outs), (ins tGPR:$Rt, t_addrmode_rrs4:$addr),
|
||||
AddrModeT1_4, IIC_iStore_r,
|
||||
"str", "\t$src, $addr",
|
||||
[(store tGPR:$src, t_addrmode_s4:$addr)]>;
|
||||
"str", "\t$Rt, $addr",
|
||||
[(store tGPR:$Rt, t_addrmode_rrs4:$addr)]>;
|
||||
|
||||
def tSTRi : // A8.6.192
|
||||
T1pILdStEncodeImm<0b0110, 0, (outs), (ins tGPR:$Rt, t_addrmode_s4:$addr),
|
||||
T1pILdStEncodeImm<0b0110, 0, (outs), (ins tGPR:$Rt, t_addrmode_is4:$addr),
|
||||
AddrModeT1_4, IIC_iStore_r,
|
||||
"str", "\t$Rt, $addr",
|
||||
[]>;
|
||||
[(store tGPR:$Rt, t_addrmode_is4:$addr)]>;
|
||||
|
||||
def tSTRB : // A8.6.197
|
||||
T1pILdStEncode<0b010, (outs), (ins tGPR:$src, t_addrmode_s1:$addr),
|
||||
def tSTRBr : // A8.6.197
|
||||
T1pILdStEncode<0b010, (outs), (ins tGPR:$Rt, t_addrmode_rrs1:$addr),
|
||||
AddrModeT1_1, IIC_iStore_bh_r,
|
||||
"strb", "\t$src, $addr",
|
||||
[(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
|
||||
"strb", "\t$Rt, $addr",
|
||||
[(truncstorei8 tGPR:$Rt, t_addrmode_rrs1:$addr)]>;
|
||||
|
||||
def tSTRBi : // A8.6.195
|
||||
T1pILdStEncodeImm<0b0111, 0, (outs), (ins tGPR:$Rt, t_addrmode_s1:$addr),
|
||||
T1pILdStEncodeImm<0b0111, 0, (outs), (ins tGPR:$Rt, t_addrmode_is1:$addr),
|
||||
AddrModeT1_1, IIC_iStore_bh_r,
|
||||
"strb", "\t$Rt, $addr",
|
||||
[]>;
|
||||
[(truncstorei8 tGPR:$Rt, t_addrmode_is1:$addr)]>;
|
||||
|
||||
def tSTRH : // A8.6.207
|
||||
T1pILdStEncode<0b001, (outs), (ins tGPR:$src, t_addrmode_s2:$addr),
|
||||
def tSTRHr : // A8.6.207
|
||||
T1pILdStEncode<0b001, (outs), (ins tGPR:$Rt, t_addrmode_rrs2:$addr),
|
||||
AddrModeT1_2, IIC_iStore_bh_r,
|
||||
"strh", "\t$src, $addr",
|
||||
[(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
|
||||
"strh", "\t$Rt, $addr",
|
||||
[(truncstorei16 tGPR:$Rt, t_addrmode_rrs2:$addr)]>;
|
||||
|
||||
def tSTRHi : // A8.6.205
|
||||
T1pILdStEncodeImm<0b1000, 0, (outs), (ins tGPR:$Rt, t_addrmode_s2:$addr),
|
||||
T1pILdStEncodeImm<0b1000, 0, (outs), (ins tGPR:$Rt, t_addrmode_is2:$addr),
|
||||
AddrModeT1_2, IIC_iStore_bh_r,
|
||||
"strh", "\t$Rt, $addr",
|
||||
[]>;
|
||||
[(truncstorei16 tGPR:$Rt, t_addrmode_is2:$addr)]>;
|
||||
|
||||
def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i,
|
||||
"str", "\t$Rt, $addr",
|
||||
[(store tGPR:$Rt, t_addrmode_sp:$addr)]>,
|
||||
"str", "\t$Rt, $addr",
|
||||
[(store tGPR:$Rt, t_addrmode_sp:$addr)]>,
|
||||
T1LdStSP<{0,?,?}> {
|
||||
bits<3> Rt;
|
||||
bits<8> addr;
|
||||
@ -1390,27 +1417,32 @@ def : Tv5Pat<(ARMcall GPR:$dst), (tBLXr_r9 GPR:$dst)>,
|
||||
Requires<[IsThumb, HasV5T, IsDarwin]>;
|
||||
|
||||
// zextload i1 -> zextload i8
|
||||
def : T1Pat<(zextloadi1 t_addrmode_s1:$addr),
|
||||
(tLDRB t_addrmode_s1:$addr)>;
|
||||
def : T1Pat<(zextloadi1 t_addrmode_rrs1:$addr),
|
||||
(tLDRBr t_addrmode_rrs1:$addr)>;
|
||||
def : T1Pat<(zextloadi1 t_addrmode_is1:$addr),
|
||||
(tLDRBi t_addrmode_is1:$addr)>;
|
||||
|
||||
// extload -> zextload
|
||||
def : T1Pat<(extloadi1 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
|
||||
def : T1Pat<(extloadi8 t_addrmode_s1:$addr), (tLDRB t_addrmode_s1:$addr)>;
|
||||
def : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>;
|
||||
def : T1Pat<(extloadi1 t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>;
|
||||
def : T1Pat<(extloadi1 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>;
|
||||
def : T1Pat<(extloadi8 t_addrmode_rrs1:$addr), (tLDRBr t_addrmode_rrs1:$addr)>;
|
||||
def : T1Pat<(extloadi8 t_addrmode_is1:$addr), (tLDRBi t_addrmode_is1:$addr)>;
|
||||
def : T1Pat<(extloadi16 t_addrmode_rrs2:$addr), (tLDRHr t_addrmode_rrs2:$addr)>;
|
||||
def : T1Pat<(extloadi16 t_addrmode_is2:$addr), (tLDRHi t_addrmode_is2:$addr)>;
|
||||
|
||||
// If it's impossible to use [r,r] address mode for sextload, select to
|
||||
// ldr{b|h} + sxt{b|h} instead.
|
||||
def : T1Pat<(sextloadi8 t_addrmode_s1:$addr),
|
||||
(tSXTB (tLDRB t_addrmode_s1:$addr))>,
|
||||
def : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr),
|
||||
(tSXTB (tLDRBr t_addrmode_rrs1:$addr))>,
|
||||
Requires<[IsThumb, IsThumb1Only, HasV6]>;
|
||||
def : T1Pat<(sextloadi16 t_addrmode_s2:$addr),
|
||||
(tSXTH (tLDRH t_addrmode_s2:$addr))>,
|
||||
def : T1Pat<(sextloadi16 t_addrmode_rrs2:$addr),
|
||||
(tSXTH (tLDRHr t_addrmode_rrs2:$addr))>,
|
||||
Requires<[IsThumb, IsThumb1Only, HasV6]>;
|
||||
|
||||
def : T1Pat<(sextloadi8 t_addrmode_s1:$addr),
|
||||
(tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>;
|
||||
def : T1Pat<(sextloadi16 t_addrmode_s1:$addr),
|
||||
(tASRri (tLSLri (tLDRH t_addrmode_s1:$addr), 16), 16)>;
|
||||
def : T1Pat<(sextloadi8 t_addrmode_rrs1:$addr),
|
||||
(tASRri (tLSLri (tLDRBr t_addrmode_rrs1:$addr), 24), 24)>;
|
||||
def : T1Pat<(sextloadi16 t_addrmode_rrs1:$addr),
|
||||
(tASRri (tLSLri (tLDRHr t_addrmode_rrs1:$addr), 16), 16)>;
|
||||
|
||||
// Large immediate handling.
|
||||
|
||||
|
@ -144,9 +144,9 @@ public:
|
||||
uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
/// getTAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand.
|
||||
uint32_t getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
/// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand.
|
||||
uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups)const;
|
||||
|
||||
/// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2'
|
||||
/// operand.
|
||||
@ -207,9 +207,9 @@ public:
|
||||
uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
/// getAddrModeSOpValue - Encode the t_addrmode_s# operands.
|
||||
uint32_t getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &) const;
|
||||
/// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
|
||||
uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &) const;
|
||||
|
||||
/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
|
||||
uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
@ -559,12 +559,16 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
Fixups);
|
||||
}
|
||||
|
||||
/// getTAddrModeRegRegOpValue - Return encoding info for 'reg + reg' operand.
|
||||
/// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg'
|
||||
/// operand.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &) const {
|
||||
// [Rn, Rm]
|
||||
// {5-3} = Rm
|
||||
// {2-0} = Rn
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx);
|
||||
const MCOperand &MO2 = MI.getOperand(OpIdx+1);
|
||||
const MCOperand &MO2 = MI.getOperand(OpIdx + 1);
|
||||
unsigned Rn = getARMRegisterNumbering(MO1.getReg());
|
||||
unsigned Rm = getARMRegisterNumbering(MO2.getReg());
|
||||
return (Rm << 3) | Rn;
|
||||
@ -796,27 +800,17 @@ getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return MO1.getImm() & 0xff;
|
||||
}
|
||||
|
||||
/// getAddrModeSOpValue - Encode the t_addrmode_s# operands.
|
||||
/// getAddrModeISOpValue - Encode the t_addrmode_is# operands.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &) const {
|
||||
// [Rn, Rm]
|
||||
// {5-3} = Rm
|
||||
// {2-0} = Rn
|
||||
//
|
||||
getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &) const {
|
||||
// [Rn, #imm]
|
||||
// {7-3} = imm5
|
||||
// {2-0} = Rn
|
||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
|
||||
const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
|
||||
unsigned Rn = getARMRegisterNumbering(MO.getReg());
|
||||
unsigned Imm5 = MO1.getImm();
|
||||
|
||||
if (MO2.getReg() != 0)
|
||||
// Is an immediate.
|
||||
Imm5 = getARMRegisterNumbering(MO2.getReg());
|
||||
|
||||
return ((Imm5 & 0x1f) << 3) | Rn;
|
||||
}
|
||||
|
||||
|
@ -236,11 +236,16 @@ public:
|
||||
int64_t Value = CE->getValue();
|
||||
return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
|
||||
}
|
||||
bool isMemModeThumb() const {
|
||||
bool isMemModeRegThumb() const {
|
||||
if (!isMemory() || (!Mem.OffsetIsReg && !Mem.Offset) || Mem.Writeback)
|
||||
return false;
|
||||
return !Mem.Offset || !isa<MCConstantExpr>(Mem.Offset);
|
||||
}
|
||||
bool isMemModeImmThumb() const {
|
||||
if (!isMemory() || (!Mem.OffsetIsReg && !Mem.Offset) || Mem.Writeback)
|
||||
return false;
|
||||
|
||||
if (!Mem.Offset) return true;
|
||||
if (!Mem.Offset) return false;
|
||||
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
||||
if (!CE) return false;
|
||||
@ -324,19 +329,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void addMemModeThumbOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 3 && isMemModeThumb() && "Invalid number of operands!");
|
||||
void addMemModeRegThumbOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && isMemModeRegThumb() && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
|
||||
}
|
||||
|
||||
if (Mem.Offset) {
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
||||
assert(CE && "Non-constant mode offset operand!");
|
||||
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
|
||||
Inst.addOperand(MCOperand::CreateReg(0));
|
||||
} else {
|
||||
Inst.addOperand(MCOperand::CreateImm(0));
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
|
||||
}
|
||||
void addMemModeImmThumbOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && isMemModeImmThumb() && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
||||
assert(CE && "Non-constant mode offset operand!");
|
||||
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
|
||||
}
|
||||
|
||||
virtual void dump(raw_ostream &OS) const;
|
||||
|
@ -482,17 +482,7 @@ void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
|
||||
void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
O << ", " << getRegisterName(MO2.getReg()) << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O,
|
||||
unsigned Scale) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
||||
|
||||
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
||||
printOperand(MI, Op, O);
|
||||
@ -500,36 +490,50 @@ void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
|
||||
}
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (MO3.getReg())
|
||||
O << ", " << getRegisterName(MO3.getReg());
|
||||
else if (unsigned ImmOffs = MO2.getImm())
|
||||
if (unsigned RegNum = MO2.getReg())
|
||||
O << ", " << getRegisterName(RegNum);
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
|
||||
unsigned Op,
|
||||
raw_ostream &O,
|
||||
unsigned Scale) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
||||
|
||||
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
||||
printOperand(MI, Op, O);
|
||||
return;
|
||||
}
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs * Scale;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
printThumbAddrModeRI5Operand(MI, Op, O, 1);
|
||||
void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
|
||||
unsigned Op,
|
||||
raw_ostream &O) {
|
||||
printThumbAddrModeImm5SOperand(MI, Op, O, 1);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
printThumbAddrModeRI5Operand(MI, Op, O, 2);
|
||||
void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
|
||||
unsigned Op,
|
||||
raw_ostream &O) {
|
||||
printThumbAddrModeImm5SOperand(MI, Op, O, 2);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
printThumbAddrModeRI5Operand(MI, Op, O, 4);
|
||||
void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
|
||||
unsigned Op,
|
||||
raw_ostream &O) {
|
||||
printThumbAddrModeImm5SOperand(MI, Op, O, 4);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs*4;
|
||||
O << "]";
|
||||
printThumbAddrModeImm5SOperand(MI, Op, O, 4);
|
||||
}
|
||||
|
||||
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
|
||||
|
@ -59,14 +59,14 @@ public:
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O, unsigned Scale);
|
||||
void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeImm5SOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O, unsigned Scale);
|
||||
void printThumbAddrModeImm5S1Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeImm5S2Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeImm5S4Operand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O);
|
||||
|
||||
|
@ -644,13 +644,11 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
*this, dl);
|
||||
}
|
||||
|
||||
MI.setDesc(TII.get(ARM::tLDR));
|
||||
MI.setDesc(TII.get(ARM::tLDRr));
|
||||
MI.getOperand(i).ChangeToRegister(TmpReg, false, false, true);
|
||||
if (UseRR)
|
||||
// Use [reg, reg] addrmode.
|
||||
MI.addOperand(MachineOperand::CreateReg(FrameReg, false));
|
||||
else // tLDR has an extra register operand.
|
||||
MI.addOperand(MachineOperand::CreateReg(0, false));
|
||||
} else if (Desc.mayStore()) {
|
||||
VReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
|
||||
bool UseRR = false;
|
||||
@ -666,14 +664,13 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
} else
|
||||
emitThumbRegPlusImmediate(MBB, II, VReg, FrameReg, Offset, TII,
|
||||
*this, dl);
|
||||
MI.setDesc(TII.get(ARM::tSTR));
|
||||
MI.setDesc(TII.get(ARM::tSTRr));
|
||||
MI.getOperand(i).ChangeToRegister(VReg, false, false, true);
|
||||
if (UseRR) // Use [reg, reg] addrmode.
|
||||
MI.addOperand(MachineOperand::CreateReg(FrameReg, false));
|
||||
else // tSTR has an extra register operand.
|
||||
MI.addOperand(MachineOperand::CreateReg(0, false));
|
||||
} else
|
||||
} else {
|
||||
assert(false && "Unexpected opcode!");
|
||||
}
|
||||
|
||||
// Add predicate back if it's needed.
|
||||
if (MI.getDesc().isPredicable()) {
|
||||
|
@ -105,19 +105,19 @@ namespace {
|
||||
// FIXME: Clean this up after splitting each Thumb load / store opcode
|
||||
// into multiple ones.
|
||||
{ ARM::t2LDRi12,ARM::tLDRi, ARM::tLDRspi, 5, 8, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRs, ARM::tLDR, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRs, ARM::tLDRr, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRBi12,ARM::tLDRBi, 0, 5, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRBs, ARM::tLDRB, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRBs, ARM::tLDRBr, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRHi12,ARM::tLDRHi, 0, 5, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRHs, ARM::tLDRH, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRHs, ARM::tLDRHr, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRi12,ARM::tSTRi, ARM::tSTRspi, 5, 8, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRs, ARM::tSTR, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRs, ARM::tSTRr, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRBi12,ARM::tSTRBi, 0, 5, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRBs, ARM::tSTRB, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRBs, ARM::tSTRBr, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRHi12,ARM::tSTRHi, 0, 5, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRHs, ARM::tSTRH, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
{ ARM::t2STRHs, ARM::tSTRHr, 0, 0, 0, 1, 0, 0,0, 1 },
|
||||
|
||||
{ ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 1 },
|
||||
{ ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 },
|
||||
@ -273,7 +273,6 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
bool HasShift = false;
|
||||
bool HasOffReg = true;
|
||||
bool isLdStMul = false;
|
||||
bool InsertImmOffset = true;
|
||||
unsigned Opc = Entry.NarrowOpc1;
|
||||
unsigned OpNum = 3; // First 'rest' of operands.
|
||||
uint8_t ImmLimit = Entry.Imm1Limit;
|
||||
@ -282,39 +281,41 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
default:
|
||||
llvm_unreachable("Unexpected Thumb2 load / store opcode!");
|
||||
case ARM::t2LDRi12:
|
||||
case ARM::t2STRi12: {
|
||||
unsigned BaseReg = MI->getOperand(1).getReg();
|
||||
if (BaseReg == ARM::SP) {
|
||||
case ARM::t2STRi12:
|
||||
if (MI->getOperand(1).getReg() == ARM::SP) {
|
||||
Opc = Entry.NarrowOpc2;
|
||||
ImmLimit = Entry.Imm2Limit;
|
||||
HasOffReg = false;
|
||||
}
|
||||
|
||||
Scale = 4;
|
||||
if (MI->getOperand(2).isImm())
|
||||
|
||||
if (MI->getOperand(2).isImm()) {
|
||||
HasImmOffset = true;
|
||||
else {
|
||||
HasOffReg = false;
|
||||
} else {
|
||||
if (Entry.WideOpc == ARM::t2LDRi12) {
|
||||
Opc = ARM::tLDRpci;
|
||||
OpNum = 2;
|
||||
}
|
||||
|
||||
HasImmOffset = false;
|
||||
InsertImmOffset = false;
|
||||
HasBaseReg = false;
|
||||
HasOffReg = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARM::t2LDRBi12:
|
||||
case ARM::t2STRBi12:
|
||||
if (MI->getOperand(2).isImm())
|
||||
if (MI->getOperand(2).isImm()) {
|
||||
HasImmOffset = true;
|
||||
else {
|
||||
HasOffReg = false;
|
||||
} else {
|
||||
if (Entry.WideOpc == ARM::t2LDRBi12) {
|
||||
Opc = ARM::tLDRpci;
|
||||
OpNum = 2;
|
||||
}
|
||||
|
||||
HasImmOffset = false;
|
||||
InsertImmOffset = false;
|
||||
HasBaseReg = false;
|
||||
HasOffReg = false;
|
||||
}
|
||||
@ -322,15 +323,16 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
case ARM::t2LDRHi12:
|
||||
case ARM::t2STRHi12:
|
||||
Scale = 2;
|
||||
if (MI->getOperand(2).isImm())
|
||||
if (MI->getOperand(2).isImm()) {
|
||||
HasImmOffset = true;
|
||||
else {
|
||||
HasOffReg = false;
|
||||
} else {
|
||||
if (Entry.WideOpc == ARM::t2LDRHi12) {
|
||||
Opc = ARM::tLDRpci;
|
||||
OpNum = 2;
|
||||
}
|
||||
|
||||
HasImmOffset = false;
|
||||
InsertImmOffset = false;
|
||||
HasBaseReg = false;
|
||||
HasOffReg = false;
|
||||
}
|
||||
@ -351,6 +353,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
unsigned BaseReg = MI->getOperand(0).getReg();
|
||||
if (!isARMLowRegister(BaseReg) || Entry.WideOpc != ARM::t2LDMIA)
|
||||
return false;
|
||||
|
||||
// For the non-writeback version (this one), the base register must be
|
||||
// one of the registers being loaded.
|
||||
bool isOK = false;
|
||||
@ -360,6 +363,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isOK)
|
||||
return false;
|
||||
|
||||
@ -381,6 +385,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
case ARM::t2STMIA_UPD:
|
||||
case ARM::t2STMDB_UPD: {
|
||||
OpNum = 0;
|
||||
|
||||
unsigned BaseReg = MI->getOperand(1).getReg();
|
||||
if (BaseReg == ARM::SP &&
|
||||
(Entry.WideOpc == ARM::t2LDMIA_UPD ||
|
||||
@ -392,6 +397,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
Entry.WideOpc != ARM::t2STMIA_UPD)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isLdStMul = true;
|
||||
break;
|
||||
}
|
||||
@ -402,6 +408,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
if (HasShift) {
|
||||
OffsetReg = MI->getOperand(2).getReg();
|
||||
OffsetKill = MI->getOperand(2).isKill();
|
||||
|
||||
if (MI->getOperand(3).getImm())
|
||||
// Thumb1 addressing mode doesn't support shift.
|
||||
return false;
|
||||
@ -411,24 +418,24 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
if (HasImmOffset) {
|
||||
OffsetImm = MI->getOperand(2).getImm();
|
||||
unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale;
|
||||
if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset)
|
||||
|
||||
if ((OffsetImm & (Scale - 1)) || OffsetImm > MaxOffset)
|
||||
// Make sure the immediate field fits.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the 16-bit load / store instruction.
|
||||
// FIXME: Thumb1 addressing mode encode both immediate and register offset.
|
||||
DebugLoc dl = MI->getDebugLoc();
|
||||
MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc));
|
||||
if (!isLdStMul) {
|
||||
MIB.addOperand(MI->getOperand(0));
|
||||
if (HasBaseReg) MIB.addOperand(MI->getOperand(1));
|
||||
if (InsertImmOffset && Opc != ARM::tLDRSB && Opc != ARM::tLDRSH) {
|
||||
// tLDRSB and tLDRSH do not have an immediate offset field. On the other
|
||||
// hand, it must have an offset register.
|
||||
// FIXME: Remove this special case.
|
||||
MIB.addImm(OffsetImm/Scale);
|
||||
}
|
||||
|
||||
if (HasBaseReg)
|
||||
MIB.addOperand(MI->getOperand(1));
|
||||
|
||||
if (HasImmOffset)
|
||||
MIB.addImm(OffsetImm / Scale);
|
||||
|
||||
assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!");
|
||||
|
||||
if (HasOffReg)
|
||||
|
@ -629,9 +629,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
|
||||
// R, I
|
||||
MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
|
||||
MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R
|
||||
MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R
|
||||
MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R
|
||||
MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS"); // R, R
|
||||
MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS"); // R, R
|
||||
MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS"); // R, R
|
||||
MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS"); // R, I
|
||||
MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS"); // R, I
|
||||
MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS"); // R, I
|
||||
MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
|
||||
MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
|
||||
MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I
|
||||
@ -841,9 +844,8 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
|
||||
operandTypes.addEntry("kOperandTypeARMSPRRegisterList");
|
||||
operandTypes.addEntry("kOperandTypeARMTBAddrMode");
|
||||
operandTypes.addEntry("kOperandTypeThumbITMask");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeS1");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeS2");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeS4");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeRegS");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeImmS");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
|
||||
operandTypes.addEntry("kOperandTypeThumbAddrModePC");
|
||||
|
Loading…
Reference in New Issue
Block a user