mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-24 21:25:41 +00:00
Split up the ARM so_reg ComplexPattern into so_reg_reg and so_reg_imm, allowing us to distinguish the encodings that use shifted registers from those that use shifted immediates. This is necessary to allow the fixed-length decoder to distinguish things like BICS vs LDRH.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135693 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a305fe7545
commit
92a202213b
@ -172,7 +172,7 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
|
||||
unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
|
||||
UpdateMI = BuildMI(MF, MI->getDebugLoc(),
|
||||
get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
|
||||
get(isSub ? ARM::SUBrsi : ARM::ADDrsi), WBReg)
|
||||
.addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
|
||||
.addImm(Pred).addReg(0).addReg(0);
|
||||
} else
|
||||
|
@ -741,7 +741,8 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
case ARM::MOVCCs: {
|
||||
case ARM::MOVCCsi:
|
||||
case ARM::MOVCCsr: {
|
||||
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs),
|
||||
(MI.getOperand(1).getReg()))
|
||||
.addReg(MI.getOperand(2).getReg(),
|
||||
|
@ -90,13 +90,20 @@ public:
|
||||
bool hasNoVMLxHazardUse(SDNode *N) const;
|
||||
bool isShifterOpProfitable(const SDValue &Shift,
|
||||
ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt);
|
||||
bool SelectShifterOperandReg(SDValue N, SDValue &A,
|
||||
bool SelectRegShifterOperand(SDValue N, SDValue &A,
|
||||
SDValue &B, SDValue &C,
|
||||
bool CheckProfitability = true);
|
||||
bool SelectImmShifterOperand(SDValue N, SDValue &A,
|
||||
SDValue &B, SDValue &C,
|
||||
bool CheckProfitability = true);
|
||||
bool SelectShiftShifterOperandReg(SDValue N, SDValue &A,
|
||||
SDValue &B, SDValue &C) {
|
||||
// Don't apply the profitability check
|
||||
return SelectShifterOperandReg(N, A, B, C, false);
|
||||
if (SelectImmShifterOperand(N, A, B, C, false))
|
||||
return true;
|
||||
else if (SelectRegShifterOperand(N, A, B, C, false))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm);
|
||||
@ -365,7 +372,7 @@ bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift,
|
||||
return ShOpcVal == ARM_AM::lsl && ShAmt == 2;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N,
|
||||
bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N,
|
||||
SDValue &BaseReg,
|
||||
SDValue &ShReg,
|
||||
SDValue &Opc,
|
||||
@ -381,19 +388,43 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N,
|
||||
|
||||
BaseReg = N.getOperand(0);
|
||||
unsigned ShImmVal = 0;
|
||||
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
ShReg = CurDAG->getRegister(0, MVT::i32);
|
||||
ShImmVal = RHS->getZExtValue() & 31;
|
||||
} else {
|
||||
ShReg = N.getOperand(1);
|
||||
if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
|
||||
return false;
|
||||
}
|
||||
ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
|
||||
if (!RHS) return false;
|
||||
ShReg = CurDAG->getRegister(0, MVT::i32);
|
||||
ShImmVal = RHS->getZExtValue() & 31;
|
||||
Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
|
||||
MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N,
|
||||
SDValue &BaseReg,
|
||||
SDValue &ShReg,
|
||||
SDValue &Opc,
|
||||
bool CheckProfitability) {
|
||||
if (DisableShifterOp)
|
||||
return false;
|
||||
|
||||
ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode());
|
||||
|
||||
// Don't match base register only case. That is matched to a separate
|
||||
// lower complexity pattern with explicit register operand.
|
||||
if (ShOpcVal == ARM_AM::no_shift) return false;
|
||||
|
||||
BaseReg = N.getOperand(0);
|
||||
unsigned ShImmVal = 0;
|
||||
ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1));
|
||||
if (RHS) return false;
|
||||
|
||||
ShReg = N.getOperand(1);
|
||||
if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal))
|
||||
return false;
|
||||
Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
|
||||
MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N,
|
||||
SDValue &Base,
|
||||
SDValue &OffImm) {
|
||||
@ -2036,10 +2067,16 @@ SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal,
|
||||
SDValue CPTmp0;
|
||||
SDValue CPTmp1;
|
||||
SDValue CPTmp2;
|
||||
if (SelectShifterOperandReg(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
|
||||
if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
|
||||
SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
|
||||
SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
|
||||
return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7);
|
||||
return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 7);
|
||||
}
|
||||
|
||||
if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) {
|
||||
SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32);
|
||||
SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag };
|
||||
return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -2309,7 +2346,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
||||
return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
|
||||
} else {
|
||||
SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
|
||||
return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
|
||||
return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7);
|
||||
}
|
||||
}
|
||||
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
|
||||
@ -2325,7 +2362,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
||||
return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6);
|
||||
} else {
|
||||
SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
|
||||
return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
|
||||
return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5224,15 +5224,19 @@ struct AddSubFlagsOpcodePair {
|
||||
static AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = {
|
||||
{ARM::ADCSri, ARM::ADCri},
|
||||
{ARM::ADCSrr, ARM::ADCrr},
|
||||
{ARM::ADCSrs, ARM::ADCrs},
|
||||
{ARM::ADCSrsi, ARM::ADCrsi},
|
||||
{ARM::ADCSrsr, ARM::ADCrsr},
|
||||
{ARM::SBCSri, ARM::SBCri},
|
||||
{ARM::SBCSrr, ARM::SBCrr},
|
||||
{ARM::SBCSrs, ARM::SBCrs},
|
||||
{ARM::SBCSrsi, ARM::SBCrsi},
|
||||
{ARM::SBCSrsr, ARM::SBCrsr},
|
||||
{ARM::RSBSri, ARM::RSBri},
|
||||
{ARM::RSBSrr, ARM::RSBrr},
|
||||
{ARM::RSBSrs, ARM::RSBrs},
|
||||
{ARM::RSBSrsi, ARM::RSBrsi},
|
||||
{ARM::RSBSrsr, ARM::RSBrsr},
|
||||
{ARM::RSCSri, ARM::RSCri},
|
||||
{ARM::RSCSrs, ARM::RSCrs},
|
||||
{ARM::RSCSrsi, ARM::RSCrsi},
|
||||
{ARM::RSCSrsr, ARM::RSCrsr},
|
||||
{ARM::t2ADCSri, ARM::t2ADCri},
|
||||
{ARM::t2ADCSrr, ARM::t2ADCrr},
|
||||
{ARM::t2ADCSrs, ARM::t2ADCrs},
|
||||
|
@ -423,15 +423,29 @@ def ShiftedRegAsmOperand : AsmOperandClass {
|
||||
let Name = "ShiftedReg";
|
||||
}
|
||||
|
||||
// shifter_operand operands: so_reg and so_imm.
|
||||
def so_reg : Operand<i32>, // reg reg imm
|
||||
ComplexPattern<i32, 3, "SelectShifterOperandReg",
|
||||
[shl,srl,sra,rotr]> {
|
||||
def ShiftedImmAsmOperand : AsmOperandClass {
|
||||
let Name = "ShiftedImm";
|
||||
}
|
||||
|
||||
// shifter_operand operands: so_reg_reg, so_reg_imm, and so_imm.
|
||||
def so_reg_reg : Operand<i32>, // reg reg imm
|
||||
ComplexPattern<i32, 3, "SelectRegShifterOperand",
|
||||
[shl, srl, sra, rotr]> {
|
||||
let EncoderMethod = "getSORegOpValue";
|
||||
let PrintMethod = "printSORegOperand";
|
||||
let ParserMatchClass = ShiftedRegAsmOperand;
|
||||
let MIOperandInfo = (ops GPR, GPR, shift_imm);
|
||||
}
|
||||
|
||||
def so_reg_imm : Operand<i32>, // reg imm
|
||||
ComplexPattern<i32, 3, "SelectImmShifterOperand",
|
||||
[shl, srl, sra, rotr]> {
|
||||
let EncoderMethod = "getSORegOpValue";
|
||||
let PrintMethod = "printSORegOperand";
|
||||
let ParserMatchClass = ShiftedImmAsmOperand;
|
||||
let MIOperandInfo = (ops GPR, GPR, shift_imm);
|
||||
}
|
||||
|
||||
// FIXME: Does this need to be distinct from so_reg?
|
||||
def shift_so_reg : Operand<i32>, // reg reg imm
|
||||
ComplexPattern<i32, 3, "SelectShiftShifterOperandReg",
|
||||
@ -755,16 +769,37 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{3-0} = Rm;
|
||||
}
|
||||
def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
|
||||
|
||||
def rsi : AsI1<opcod, (outs GPR:$Rd),
|
||||
(ins GPR:$Rn, so_reg_imm:$shift), DPSoRegFrm,
|
||||
iis, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
|
||||
def rsr : AsI1<opcod, (outs GPR:$Rd),
|
||||
(ins GPR:$Rn, so_reg_reg:$shift), DPSoRegFrm,
|
||||
iis, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
|
||||
// Assembly aliases for optional destination operand when it's the same
|
||||
@ -780,10 +815,16 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
|
||||
cc_out:$s)>,
|
||||
Requires<[IsARM]>;
|
||||
def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
|
||||
(!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn,
|
||||
so_reg:$shift, pred:$p,
|
||||
(!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
|
||||
so_reg_imm:$shift, pred:$p,
|
||||
cc_out:$s)>,
|
||||
Requires<[IsARM]>;
|
||||
def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
|
||||
(!cast<Instruction>(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn,
|
||||
so_reg_reg:$shift, pred:$p,
|
||||
cc_out:$s)>,
|
||||
Requires<[IsARM]>;
|
||||
|
||||
}
|
||||
|
||||
/// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the
|
||||
@ -818,9 +859,10 @@ multiclass AI1_bin_s_irs<bits<4> opcod, string opc,
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{3-0} = Rm;
|
||||
}
|
||||
def rs : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
|
||||
def rsi : AI1<opcod, (outs GPR:$Rd),
|
||||
(ins GPR:$Rn, so_reg_imm:$shift), DPSoRegFrm,
|
||||
iis, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
@ -828,7 +870,27 @@ multiclass AI1_bin_s_irs<bits<4> opcod, string opc,
|
||||
let Inst{20} = 1;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
|
||||
def rsr : AI1<opcod, (outs GPR:$Rd),
|
||||
(ins GPR:$Rn, so_reg_reg:$shift), DPSoRegFrm,
|
||||
iis, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{20} = 1;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -864,17 +926,37 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc,
|
||||
let Inst{11-4} = 0b00000000;
|
||||
let Inst{3-0} = Rm;
|
||||
}
|
||||
def rs : AI1<opcod, (outs), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm, iis,
|
||||
def rsi : AI1<opcod, (outs),
|
||||
(ins GPR:$Rn, so_reg_imm:$shift), DPSoRegFrm, iis,
|
||||
opc, "\t$Rn, $shift",
|
||||
[(opnode GPR:$Rn, so_reg:$shift)]> {
|
||||
[(opnode GPR:$Rn, so_reg_imm:$shift)]> {
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{20} = 1;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = 0b0000;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
def rsr : AI1<opcod, (outs),
|
||||
(ins GPR:$Rn, so_reg_reg:$shift), DPSoRegFrm, iis,
|
||||
opc, "\t$Rn, $shift",
|
||||
[(opnode GPR:$Rn, so_reg_reg:$shift)]> {
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{20} = 1;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = 0b0000;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1009,17 +1091,37 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
}
|
||||
def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
|
||||
def rsi : AsI1<opcod, (outs GPR:$Rd),
|
||||
(ins GPR:$Rn, so_reg_imm:$shift),
|
||||
DPSoRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>,
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]>,
|
||||
Requires<[IsARM]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
def rsr : AsI1<opcod, (outs GPR:$Rd),
|
||||
(ins GPR:$Rn, so_reg_reg:$shift),
|
||||
DPSoRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]>,
|
||||
Requires<[IsARM]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
}
|
||||
// Assembly aliases for optional destination operand when it's the same
|
||||
@ -1035,8 +1137,13 @@ multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
|
||||
cc_out:$s)>,
|
||||
Requires<[IsARM]>;
|
||||
def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
|
||||
(!cast<Instruction>(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn,
|
||||
so_reg:$shift, pred:$p,
|
||||
(!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
|
||||
so_reg_imm:$shift, pred:$p,
|
||||
cc_out:$s)>,
|
||||
Requires<[IsARM]>;
|
||||
def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
|
||||
(!cast<Instruction>(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn,
|
||||
so_reg_reg:$shift, pred:$p,
|
||||
cc_out:$s)>,
|
||||
Requires<[IsARM]>;
|
||||
}
|
||||
@ -1053,9 +1160,12 @@ multiclass AI1_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
|
||||
let isCommutable = Commutable;
|
||||
}
|
||||
def rs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
|
||||
def rsi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
|
||||
4, IIC_iALUsr,
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>;
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]>;
|
||||
def rsr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
|
||||
4, IIC_iALUsr,
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]>;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2338,16 +2448,34 @@ def RSBrr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
|
||||
let Inst{19-16} = Rn;
|
||||
}
|
||||
|
||||
def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
|
||||
def RSBrsi : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
|
||||
DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (sub so_reg:$shift, GPR:$Rn))]> {
|
||||
[(set GPR:$Rd, (sub so_reg_imm:$shift, GPR:$Rn))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
|
||||
def RSBrsr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
|
||||
DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (sub so_reg_reg:$shift, GPR:$Rn))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
|
||||
// RSB with 's' bit set.
|
||||
@ -2359,9 +2487,12 @@ def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
|
||||
def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
|
||||
4, IIC_iALUr,
|
||||
[/* For disassembly only; pattern left blank */]>;
|
||||
def RSBSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
|
||||
def RSBSrsi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
|
||||
4, IIC_iALUsr,
|
||||
[(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]>;
|
||||
[(set GPR:$Rd, (subc so_reg_imm:$shift, GPR:$Rn))]>;
|
||||
def RSBSrsr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
|
||||
4, IIC_iALUsr,
|
||||
[(set GPR:$Rd, (subc so_reg_reg:$shift, GPR:$Rn))]>;
|
||||
}
|
||||
|
||||
let Uses = [CPSR] in {
|
||||
@ -2391,28 +2522,50 @@ def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
}
|
||||
def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
|
||||
def RSCrsi : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
|
||||
DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>,
|
||||
[(set GPR:$Rd, (sube_dead_carry so_reg_imm:$shift, GPR:$Rn))]>,
|
||||
Requires<[IsARM]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
def RSCrsr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
|
||||
DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (sube_dead_carry so_reg_reg:$shift, GPR:$Rn))]>,
|
||||
Requires<[IsARM]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOTE: CPSR def omitted because it will be handled by the custom inserter.
|
||||
let usesCustomInserter = 1, Uses = [CPSR] in {
|
||||
def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
|
||||
4, IIC_iALUi,
|
||||
[(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>;
|
||||
def RSCSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
|
||||
def RSCSrsi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
|
||||
4, IIC_iALUsr,
|
||||
[(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>;
|
||||
[(set GPR:$Rd, (sube_dead_carry so_reg_imm:$shift, GPR:$Rn))]>;
|
||||
def RSCSrsr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
|
||||
4, IIC_iALUsr,
|
||||
[(set GPR:$Rd, (sube_dead_carry so_reg_reg:$shift, GPR:$Rn))]>;
|
||||
}
|
||||
|
||||
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
|
||||
@ -2684,15 +2837,31 @@ def MVNr : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr,
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{3-0} = Rm;
|
||||
}
|
||||
def MVNs : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg:$shift), DPSoRegFrm,
|
||||
def MVNsi : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_imm:$shift), DPSoRegFrm,
|
||||
IIC_iMVNsr, "mvn", "\t$Rd, $shift",
|
||||
[(set GPR:$Rd, (not so_reg:$shift))]>, UnaryDP {
|
||||
[(set GPR:$Rd, (not so_reg_imm:$shift))]>, UnaryDP {
|
||||
bits<4> Rd;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = 0b0000;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{11-5} = shift{11-5};
|
||||
let Inst{4} = 0;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
def MVNsr : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_reg:$shift), DPSoRegFrm,
|
||||
IIC_iMVNsr, "mvn", "\t$Rd, $shift",
|
||||
[(set GPR:$Rd, (not so_reg_reg:$shift))]>, UnaryDP {
|
||||
bits<4> Rd;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{19-16} = 0b0000;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{11-8} = shift{11-8};
|
||||
let Inst{7} = 0;
|
||||
let Inst{6-5} = shift{6-5};
|
||||
let Inst{4} = 1;
|
||||
let Inst{3-0} = shift{3-0};
|
||||
}
|
||||
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
|
||||
def MVNi : AsI1<0b1111, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm,
|
||||
@ -3156,8 +3325,10 @@ def : ARMPat<(ARMcmpZ GPR:$src, so_imm:$imm),
|
||||
(CMPri GPR:$src, so_imm:$imm)>;
|
||||
def : ARMPat<(ARMcmpZ GPR:$src, GPR:$rhs),
|
||||
(CMPrr GPR:$src, GPR:$rhs)>;
|
||||
def : ARMPat<(ARMcmpZ GPR:$src, so_reg:$rhs),
|
||||
(CMPrs GPR:$src, so_reg:$rhs)>;
|
||||
def : ARMPat<(ARMcmpZ GPR:$src, so_reg_imm:$rhs),
|
||||
(CMPrsi GPR:$src, so_reg_imm:$rhs)>;
|
||||
def : ARMPat<(ARMcmpZ GPR:$src, so_reg_reg:$rhs),
|
||||
(CMPrsr GPR:$src, so_reg_reg:$rhs)>;
|
||||
|
||||
// FIXME: We have to be careful when using the CMN instruction and comparison
|
||||
// with 0. One would expect these two pieces of code should give identical
|
||||
@ -3243,11 +3414,17 @@ def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p),
|
||||
4, IIC_iCMOVr,
|
||||
[/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>,
|
||||
RegConstraint<"$false = $Rd">;
|
||||
def MOVCCs : ARMPseudoInst<(outs GPR:$Rd),
|
||||
(ins GPR:$false, so_reg:$shift, pred:$p),
|
||||
def MOVCCsi : ARMPseudoInst<(outs GPR:$Rd),
|
||||
(ins GPR:$false, so_reg_imm:$shift, pred:$p),
|
||||
4, IIC_iCMOVsr,
|
||||
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>,
|
||||
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_imm:$shift, imm:$cc, CCR:$ccr))*/]>,
|
||||
RegConstraint<"$false = $Rd">;
|
||||
def MOVCCsr : ARMPseudoInst<(outs GPR:$Rd),
|
||||
(ins GPR:$false, so_reg_reg:$shift, pred:$p),
|
||||
4, IIC_iCMOVsr,
|
||||
[/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_reg:$shift, imm:$cc, CCR:$ccr))*/]>,
|
||||
RegConstraint<"$false = $Rd">;
|
||||
|
||||
|
||||
let isMoveImm = 1 in
|
||||
def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd),
|
||||
|
@ -172,6 +172,7 @@ class ARMOperand : public MCParsedAsmOperand {
|
||||
DPRRegisterList,
|
||||
SPRRegisterList,
|
||||
ShiftedRegister,
|
||||
ShiftedImmediate,
|
||||
Shifter,
|
||||
Token
|
||||
} Kind;
|
||||
@ -241,6 +242,11 @@ class ARMOperand : public MCParsedAsmOperand {
|
||||
unsigned ShiftReg;
|
||||
unsigned ShiftImm;
|
||||
} ShiftedReg;
|
||||
struct {
|
||||
ARM_AM::ShiftOpc ShiftTy;
|
||||
unsigned SrcReg;
|
||||
unsigned ShiftImm;
|
||||
} ShiftedImm;
|
||||
};
|
||||
|
||||
ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
|
||||
@ -290,6 +296,9 @@ public:
|
||||
case ShiftedRegister:
|
||||
ShiftedReg = o.ShiftedReg;
|
||||
break;
|
||||
case ShiftedImmediate:
|
||||
ShiftedImm = o.ShiftedImm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,6 +477,7 @@ public:
|
||||
bool isMemory() const { return Kind == Memory; }
|
||||
bool isShifter() const { return Kind == Shifter; }
|
||||
bool isShiftedReg() const { return Kind == ShiftedRegister; }
|
||||
bool isShiftedImm() const { return Kind == ShiftedImmediate; }
|
||||
bool isMemMode2() const {
|
||||
if (getMemAddrMode() != ARMII::AddrMode2)
|
||||
return false;
|
||||
@ -601,15 +611,25 @@ public:
|
||||
void addShiftedRegOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 3 && "Invalid number of operands!");
|
||||
assert(isShiftedReg() && "addShiftedRegOperands() on non ShiftedReg!");
|
||||
assert((ShiftedReg.ShiftReg == 0 ||
|
||||
ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) == 0) &&
|
||||
"Invalid shifted register operand!");
|
||||
Inst.addOperand(MCOperand::CreateReg(ShiftedReg.SrcReg));
|
||||
Inst.addOperand(MCOperand::CreateReg(ShiftedReg.ShiftReg));
|
||||
Inst.addOperand(MCOperand::CreateImm(
|
||||
ARM_AM::getSORegOpc(ShiftedReg.ShiftTy, ShiftedReg.ShiftImm)));
|
||||
}
|
||||
|
||||
void addShiftedImmOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 3 && "Invalid number of operands!");
|
||||
assert(isShiftedImm() && "addShiftedImmOperands() on non ShiftedImm!");
|
||||
Inst.addOperand(MCOperand::CreateReg(ShiftedImm.SrcReg));
|
||||
if (ShiftedImm.ShiftTy == ARM_AM::rrx)
|
||||
Inst.addOperand(MCOperand::CreateReg(ShiftedImm.SrcReg));
|
||||
else
|
||||
Inst.addOperand(MCOperand::CreateReg(0));
|
||||
Inst.addOperand(MCOperand::CreateImm(
|
||||
ARM_AM::getSORegOpc(ShiftedImm.ShiftTy, ShiftedImm.ShiftImm)));
|
||||
}
|
||||
|
||||
|
||||
void addShifterOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateImm(
|
||||
@ -885,6 +905,19 @@ public:
|
||||
return Op;
|
||||
}
|
||||
|
||||
static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
|
||||
unsigned SrcReg,
|
||||
unsigned ShiftImm,
|
||||
SMLoc S, SMLoc E) {
|
||||
ARMOperand *Op = new ARMOperand(ShiftedImmediate);
|
||||
Op->ShiftedImm.ShiftTy = ShTy;
|
||||
Op->ShiftedImm.SrcReg = SrcReg;
|
||||
Op->ShiftedImm.ShiftImm = ShiftImm;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
}
|
||||
|
||||
static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
|
||||
SMLoc S, SMLoc E) {
|
||||
ARMOperand *Op = new ARMOperand(Shifter);
|
||||
@ -1052,13 +1085,20 @@ void ARMOperand::print(raw_ostream &OS) const {
|
||||
OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">";
|
||||
break;
|
||||
case ShiftedRegister:
|
||||
OS << "<so_reg"
|
||||
OS << "<so_reg_reg "
|
||||
<< ShiftedReg.SrcReg
|
||||
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedReg.ShiftImm))
|
||||
<< ", " << ShiftedReg.ShiftReg << ", "
|
||||
<< ARM_AM::getSORegOffset(ShiftedReg.ShiftImm)
|
||||
<< ">";
|
||||
break;
|
||||
case ShiftedImmediate:
|
||||
OS << "<so_reg_imm "
|
||||
<< ShiftedImm.SrcReg
|
||||
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedImm.ShiftImm))
|
||||
<< ", " << ARM_AM::getSORegOffset(ShiftedImm.ShiftImm)
|
||||
<< ">";
|
||||
break;
|
||||
case RegisterList:
|
||||
case DPRRegisterList:
|
||||
case SPRRegisterList: {
|
||||
@ -1201,9 +1241,13 @@ int ARMAsmParser::TryParseShiftRegister(
|
||||
}
|
||||
}
|
||||
|
||||
Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
|
||||
if (ShiftReg && ShiftTy != ARM_AM::rrx)
|
||||
Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
|
||||
ShiftReg, Imm,
|
||||
S, Parser.getTok().getLoc()));
|
||||
else
|
||||
Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
|
||||
S, Parser.getTok().getLoc()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -623,7 +623,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
|
||||
MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||
MISC("so_reg_imm", "kOperandTypeARMSoReg"); // R, R, I
|
||||
MISC("so_reg_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||
MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||
MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I
|
||||
MISC("so_imm", "kOperandTypeARMSoImm"); // I
|
||||
|
Loading…
x
Reference in New Issue
Block a user