From 83ab070fc1fbb02ca77b0a37e6ae0eacf58001e1 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 13 Jul 2011 22:01:08 +0000 Subject: [PATCH] Range checking for CDP[2] immediates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135092 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 24 +++++++++++++++++---- lib/Target/ARM/ARMInstrThumb.td | 4 ---- lib/Target/ARM/ARMInstrThumb2.td | 8 +++---- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 26 +++++++++++++++++++++++ test/MC/ARM/basic-arm-instructions.s | 14 ++++++++++++ test/MC/ARM/diagnostics.s | 13 ++++++++++++ utils/TableGen/EDEmitter.cpp | 2 ++ 7 files changed, 79 insertions(+), 12 deletions(-) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 02c9edf5074..050fd9808e2 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -459,6 +459,22 @@ def arm_i32imm : PatLeaf<(imm), [{ return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue()); }]>; +/// imm0_7 predicate - Immediate in the range [0,31]. +def Imm0_7AsmOperand: AsmOperandClass { let Name = "Imm0_7"; } +def imm0_7 : Operand, ImmLeaf= 0 && Imm < 8; +}]> { + let ParserMatchClass = Imm0_7AsmOperand; +} + +/// imm0_15 predicate - Immediate in the range [0,31]. +def Imm0_15AsmOperand: AsmOperandClass { let Name = "Imm0_15"; } +def imm0_15 : Operand, ImmLeaf= 0 && Imm < 16; +}]> { + let ParserMatchClass = Imm0_15AsmOperand; +} + /// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31]. def imm0_31 : Operand, ImmLeaf= 0 && Imm < 32; @@ -3465,8 +3481,8 @@ def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb", // Coprocessor Instructions. // -def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { @@ -3486,8 +3502,8 @@ def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{23-20} = opc1; } -def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 20a8d1207a3..db945b59c33 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -26,10 +26,6 @@ def imm_comp_XFORM : SDNodeXFormgetTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); }]>; -/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. -def imm0_7 : ImmLeaf= 0 && Imm < 8; -}]>; def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 0d6f130260b..68fc69d0d7f 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -3421,8 +3421,8 @@ def t2MRRC2 : t2MovRRCopro<0b1111, "mrrc2", 1>; // Other Coprocessor Instructions. // -def tCDP : T2Cop<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def tCDP : T2Cop<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), "cdp\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { @@ -3444,8 +3444,8 @@ def tCDP : T2Cop<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, let Inst{23-20} = opc1; } -def t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, i32imm:$opc1, - c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), +def t2CDP2 : T2Cop<0b1111, (outs), (ins p_imm:$cop, imm0_15:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, imm0_7:$opc2), "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", [(int_arm_cdp2 imm:$cop, imm:$opc1, imm:$CRd, imm:$CRn, imm:$CRm, imm:$opc2)]> { diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 0ce4b4c1282..499c95440c4 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -386,6 +386,22 @@ public: int64_t Value = CE->getValue(); return Value >= 0 && Value < 256; } + bool isImm0_7() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 8; + } + bool isImm0_15() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 16; + } bool isImm0_65535() const { if (Kind != Immediate) return false; @@ -585,6 +601,16 @@ public: addExpr(Inst, getImm()); } + void addImm0_7Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addImm0_15Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + void addImm0_65535Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); addExpr(Inst, getImm()); diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s index 6c1b39d24b4..14833775ba0 100644 --- a/test/MC/ARM/basic-arm-instructions.s +++ b/test/MC/ARM/basic-arm-instructions.s @@ -357,3 +357,17 @@ _func: @ CHECK: bxj r2 @ encoding: [0x22,0xff,0x2f,0xe1] @ CHECK: bxjne r2 @ encoding: [0x22,0xff,0x2f,0x11] + +@------------------------------------------------------------------------------ +@ FIXME: CBNZ/CBZ +@------------------------------------------------------------------------------ + + +@------------------------------------------------------------------------------ +@ CDP/CDP2 +@------------------------------------------------------------------------------ + cdp p7, #1, c1, c1, c1, #4 + cdp2 p7, #1, c1, c1, c1, #4 + +@ CHECK: cdp p7, #1, c1, c1, c1, #4 @ encoding: [0x81,0x17,0x11,0xee] +@ CHECK: cdp2 p7, #1, c1, c1, c1, #4 @ encoding: [0x81,0x17,0x11,0xfe] diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s index bf8f1259e9f..4069fea509d 100644 --- a/test/MC/ARM/diagnostics.s +++ b/test/MC/ARM/diagnostics.s @@ -45,4 +45,17 @@ @ Out of range 16-bit immediate on BKPT bkpt #65536 +@ CHECK-ERRORS: error: invalid operand for instruction + + @ Out of range 4 and 3 bit immediates on CDP[2] + + @ Out of range immediates for CDP/CDP2 + cdp p7, #2, c1, c1, c1, #8 + cdp p7, #1, c1, c1, c1, #8 + cdp2 p7, #2, c1, c1, c1, #8 + cdp2 p7, #1, c1, c1, c1, #8 + +@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: invalid operand for instruction @ CHECK-ERRORS: error: invalid operand for instruction diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index afe5007ecf5..2f9814aee48 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -588,6 +588,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm0_31"); IMM("imm0_31_m1"); IMM("nModImm"); + IMM("imm0_7"); + IMM("imm0_15"); IMM("imm0_255"); IMM("imm0_4095"); IMM("imm0_65535");