mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-06 03:38:34 +00:00
Thumb parsing diagnostics for low-reg requirements on ADD and MOV.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137779 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
94c7ddb6f5
commit
194bd89829
@ -33,19 +33,6 @@ namespace ARMRI {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isARMLowRegister - Returns true if the register is low register r0-r7.
|
|
||||||
///
|
|
||||||
static inline bool isARMLowRegister(unsigned Reg) {
|
|
||||||
using namespace ARM;
|
|
||||||
switch (Reg) {
|
|
||||||
case R0: case R1: case R2: case R3:
|
|
||||||
case R4: case R5: case R6: case R7:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// isARMArea1Register - Returns true if the register is a low register (r0-r7)
|
/// isARMArea1Register - Returns true if the register is a low register (r0-r7)
|
||||||
/// or a stack/pc register that we should push/pop.
|
/// or a stack/pc register that we should push/pop.
|
||||||
static inline bool isARMArea1Register(unsigned Reg, bool isDarwin) {
|
static inline bool isARMArea1Register(unsigned Reg, bool isDarwin) {
|
||||||
|
@ -81,6 +81,9 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||||||
bool isThumbTwo() const {
|
bool isThumbTwo() const {
|
||||||
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
|
return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
|
||||||
}
|
}
|
||||||
|
bool hasV6Ops() const {
|
||||||
|
return STI.getFeatureBits() & ARM::HasV6Ops;
|
||||||
|
}
|
||||||
void SwitchMode() {
|
void SwitchMode() {
|
||||||
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
|
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
|
||||||
setAvailableFeatures(FB);
|
setAvailableFeatures(FB);
|
||||||
@ -152,7 +155,9 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum ARMMatchResultTy {
|
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)
|
ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
|
||||||
@ -2714,6 +2719,8 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
|
|||||||
Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
|
Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
|
||||||
Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" ||
|
Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" ||
|
||||||
Mnemonic == "eor" || Mnemonic == "smlal" ||
|
Mnemonic == "eor" || Mnemonic == "smlal" ||
|
||||||
|
// FIXME: We need a better way. This really confused Thumb2
|
||||||
|
// parsing for 'mov'.
|
||||||
(Mnemonic == "mov" && !isThumbOne())) {
|
(Mnemonic == "mov" && !isThumbOne())) {
|
||||||
CanAcceptCarrySet = true;
|
CanAcceptCarrySet = true;
|
||||||
} else {
|
} else {
|
||||||
@ -3022,7 +3029,8 @@ static MCInstrDesc &getInstDesc(unsigned Opcode) {
|
|||||||
unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
|
unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
|
||||||
// 16-bit thumb arithmetic instructions either require or preclude the 'S'
|
// 16-bit thumb arithmetic instructions either require or preclude the 'S'
|
||||||
// suffix depending on whether they're in an IT block or not.
|
// 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) {
|
if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
|
||||||
assert(MCID.hasOptionalDef() &&
|
assert(MCID.hasOptionalDef() &&
|
||||||
"optionally flag setting instruction missing optional def operand");
|
"optionally flag setting instruction missing optional def operand");
|
||||||
@ -3044,6 +3052,17 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
|
|||||||
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
|
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
|
||||||
return Match_RequiresITBlock;
|
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 Match_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3090,6 +3109,10 @@ MatchAndEmitInstruction(SMLoc IDLoc,
|
|||||||
return Error(IDLoc, "unable to convert operands to instruction");
|
return Error(IDLoc, "unable to convert operands to instruction");
|
||||||
case Match_RequiresITBlock:
|
case Match_RequiresITBlock:
|
||||||
return Error(IDLoc, "instruction only valid inside IT block");
|
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!");
|
llvm_unreachable("Implement any new match types added!");
|
||||||
|
@ -188,6 +188,19 @@ inline static unsigned getARMRegisterNumbering(unsigned Reg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isARMLowRegister - Returns true if the register is a low register (r0-r7).
|
||||||
|
///
|
||||||
|
static inline bool isARMLowRegister(unsigned Reg) {
|
||||||
|
using namespace ARM;
|
||||||
|
switch (Reg) {
|
||||||
|
case R0: case R1: case R2: case R3:
|
||||||
|
case R4: case R5: case R6: case R7:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ARMII - This namespace holds all of the target specific flags that
|
/// ARMII - This namespace holds all of the target specific flags that
|
||||||
/// instruction info tracks.
|
/// instruction info tracks.
|
||||||
///
|
///
|
||||||
|
@ -8,3 +8,13 @@
|
|||||||
@ CHECK-ERRORS: error: invalid instruction
|
@ CHECK-ERRORS: error: invalid instruction
|
||||||
@ CHECK-ERRORS: add r1, r2, r3
|
@ CHECK-ERRORS: add r1, r2, r3
|
||||||
@ CHECK-ERRORS: ^
|
@ CHECK-ERRORS: ^
|
||||||
|
|
||||||
|
@ Instructions which require v6+ for both registers to be low regs.
|
||||||
|
add r2, r3
|
||||||
|
mov r2, r3
|
||||||
|
@ CHECK-ERRORS: error: instruction variant requires Thumb2
|
||||||
|
@ CHECK-ERRORS: add r2, r3
|
||||||
|
@ CHECK-ERRORS: ^
|
||||||
|
@ CHECK-ERRORS: error: instruction variant requires ARMv6 or later
|
||||||
|
@ CHECK-ERRORS: mov r2, r3
|
||||||
|
@ CHECK-ERRORS: ^
|
||||||
|
Loading…
Reference in New Issue
Block a user