bool isThumbTwo() const {
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
}
+ bool hasV6Ops() const {
+ return STI.getFeatureBits() & ARM::HasV6Ops;
+ }
void SwitchMode() {
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
setAvailableFeatures(FB);
public:
enum ARMMatchResultTy {
- Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY
+ Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
+ Match_RequiresV6,
+ Match_RequiresThumb2
};
ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
int64_t Value = CE->getValue();
return Value >= 0 && Value <= 0xffffff;
}
+ bool isImmThumbSR() const {
+ if (Kind != Immediate)
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ int64_t Value = CE->getValue();
+ return Value > 0 && Value < 33;
+ }
bool isPKHLSLImm() const {
if (Kind != Immediate)
return false;
addExpr(Inst, getImm());
}
+ void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The constant encodes as the immediate, except for 32, which encodes as
+ // zero.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Imm = CE->getValue();
+ Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
+ }
+
void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
// Next, determine if we have a carry setting bit. We explicitly ignore all
// the instructions we know end in 's'.
if (Mnemonic.endswith("s") &&
- !(Mnemonic == "asrs" || Mnemonic == "cps" || Mnemonic == "mls" ||
+ !(Mnemonic == "cps" || Mnemonic == "mls" ||
Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" ||
Mnemonic == "eor" || Mnemonic == "smlal" ||
+ // FIXME: We need a better way. This really confused Thumb2
+ // parsing for 'mov'.
(Mnemonic == "mov" && !isThumbOne())) {
CanAcceptCarrySet = true;
} else {
if (widthm1 >= 32 - lsb)
return Error(Operands[5]->getStartLoc(),
"bitfield width must be in range [1,32-lsb]");
+ return false;
}
}
Inst = TmpInst;
}
break;
+ case ARM::tADDi8:
+ // If the immediate is in the range 0-7, we really wanted tADDi3.
+ if (Inst.getOperand(3).getImm() < 8)
+ Inst.setOpcode(ARM::tADDi3);
+ break;
+ case ARM::tBcc:
+ // If the conditional is AL, we really want tB.
+ if (Inst.getOperand(1).getImm() == ARMCC::AL)
+ Inst.setOpcode(ARM::tB);
}
}
unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
// 16-bit thumb arithmetic instructions either require or preclude the 'S'
// suffix depending on whether they're in an IT block or not.
- MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
+ unsigned Opc = Inst.getOpcode();
+ MCInstrDesc &MCID = getInstDesc(Opc);
if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
assert(MCID.hasOptionalDef() &&
"optionally flag setting instruction missing optional def operand");
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
return Match_RequiresITBlock;
}
+ // Some high-register supporting Thumb1 encodings only allow both registers
+ // to be from r0-r7 when in Thumb2.
+ else if (Opc == ARM::tADDhirr && isThumbOne() &&
+ isARMLowRegister(Inst.getOperand(1).getReg()) &&
+ isARMLowRegister(Inst.getOperand(2).getReg()))
+ return Match_RequiresThumb2;
+ // Others only require ARMv6 or later.
+ else if (Opc == ARM::tMOVr && isThumbOne() &&
+ isARMLowRegister(Inst.getOperand(0).getReg()) &&
+ isARMLowRegister(Inst.getOperand(1).getReg()))
+ return Match_RequiresV6;
return Match_Success;
}
return Error(IDLoc, "unable to convert operands to instruction");
case Match_RequiresITBlock:
return Error(IDLoc, "instruction only valid inside IT block");
+ case Match_RequiresV6:
+ return Error(IDLoc, "instruction variant requires ARMv6 or later");
+ case Match_RequiresThumb2:
+ return Error(IDLoc, "instruction variant requires Thumb2");
}
llvm_unreachable("Implement any new match types added!");