From fb8989e64024547e4ad5ab6fe4d94fe146a7899f Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 27 Jul 2011 21:09:25 +0000 Subject: [PATCH] ARM parsing and encoding of SBFX and UBFX. Encode the width operand as it encodes in the instruction, which simplifies the disassembler and the encoder, by using the imm1_32 operand def. Add a diagnostic for the context-sensitive constraint that the width must be in the range [1,32-lsb]. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136264 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMCodeEmitter.cpp | 2 -- lib/Target/ARM/ARMISelDAGToDAG.cpp | 6 ++++-- lib/Target/ARM/ARMInstrInfo.td | 12 ++---------- lib/Target/ARM/ARMInstrThumb2.td | 4 ++-- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 9 +++++++++ .../ARM/Disassembler/ARMDisassemblerCore.cpp | 2 +- .../ARM/Disassembler/ThumbDisassemblerCore.h | 2 +- .../ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 5 ----- test/MC/ARM/basic-arm-instructions.s | 18 ++++++++++++++++++ test/MC/ARM/diagnostics.s | 11 +++++++++++ 10 files changed, 48 insertions(+), 23 deletions(-) diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 6c10a431d9b..e0720b3da8f 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -215,8 +215,6 @@ namespace { const { return 0; } unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } - unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op) - const { return 0; } unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op) diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 928e2efa72f..74d877a27fc 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -2024,7 +2024,8 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, Srl_imm)) { assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); - unsigned Width = CountTrailingOnes_32(And_imm); + // Note: The width operand is encoded as width-1. + unsigned Width = CountTrailingOnes_32(And_imm) - 1; unsigned LSB = Srl_imm; SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); SDValue Ops[] = { N->getOperand(0).getOperand(0), @@ -2044,7 +2045,8 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Srl_imm = 0; if (isInt32Immediate(N->getOperand(1), Srl_imm)) { assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); - unsigned Width = 32 - Srl_imm; + // Note: The width operand is encoded as width-1. + unsigned Width = 32 - Srl_imm - 1; int LSB = Srl_imm - Shl_imm; if (LSB < 0) return NULL; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 4c6bace6399..7e9687a7cf1 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -513,14 +513,6 @@ def imm0_31 : Operand, ImmLeaf, ImmLeaf= 0 && Imm < 32; -}]> { - let EncoderMethod = "getImmMinusOneOpValue"; - let DecoderMethod = "DecodeImmMinusOneOperand"; -} - // imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference // a relocatable expression. // @@ -2423,7 +2415,7 @@ def UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">; def SBFX : I<(outs GPR:$Rd), - (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), + (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>, Requires<[IsARM, HasV6T2]> { @@ -2440,7 +2432,7 @@ def SBFX : I<(outs GPR:$Rd), } def UBFX : I<(outs GPR:$Rd), - (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), + (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>, Requires<[IsARM, HasV6T2]> { diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 7e516b2ce7c..b4ca828b26b 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2024,7 +2024,7 @@ def t2BFC : T2BitFI<(outs rGPR:$Rd), (ins rGPR:$src, bf_inv_mask_imm:$imm), } def t2SBFX: T2TwoRegBitFI< - (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm0_31_m1:$msb), + (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb), IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $msb", []> { let Inst{31-27} = 0b11110; let Inst{25} = 1; @@ -2033,7 +2033,7 @@ def t2SBFX: T2TwoRegBitFI< } def t2UBFX: T2TwoRegBitFI< - (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm0_31_m1:$msb), + (outs rGPR:$Rd), (ins rGPR:$Rn, imm0_31:$lsb, imm1_32:$msb), IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $msb", []> { let Inst{31-27} = 0b11110; let Inst{25} = 1; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index a2df19f8f49..352e9020098 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -2605,6 +2605,15 @@ validateInstruction(MCInst &Inst, "source operands must be sequential"); return false; } + case ARM::SBFX: + case ARM::UBFX: { + // width must be in range [1, 32-lsb] + unsigned lsb = Inst.getOperand(2).getImm(); + unsigned widthm1 = Inst.getOperand(3).getImm(); + if (widthm1 >= 32 - lsb) + return Error(Operands[5]->getStartLoc(), + "bitfield width must be in range [1,32-lsb]"); + } } return false; diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index f16870054e1..1f3920bd8cf 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -1026,7 +1026,7 @@ static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, decodeRm(insn)))); MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7))); - MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16) + 1)); + MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16))); OpIdx += 3; return true; } diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index e534e21375a..66a62ef5a56 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -1698,7 +1698,7 @@ static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX) && "Unexpected opcode"); MI.addOperand(MCOperand::CreateImm(getLsb(insn))); - MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn) + 1)); + MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn))); ++OpIdx; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 9482a6db1ae..4c5e9945139 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -259,11 +259,6 @@ public: unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const; - unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op, - SmallVectorImpl &Fixups) const { - return MI.getOperand(Op).getImm() - 1; - } - unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const { return 64 - MI.getOperand(Op).getImm(); diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s index 02ccb9deb05..c08bb83c096 100644 --- a/test/MC/ARM/basic-arm-instructions.s +++ b/test/MC/ARM/basic-arm-instructions.s @@ -1308,6 +1308,16 @@ _func: @ CHECK: sbc r6, r6, r7, ror r9 @ encoding: [0x77,0x69,0xc6,0xe0] +@------------------------------------------------------------------------------ +@ SBFX +@------------------------------------------------------------------------------ + sbfx r4, r5, #16, #1 + sbfxgt r4, r5, #16, #16 + +@ CHECK: sbfx r4, r5, #16, #1 @ encoding: [0x55,0x48,0xa0,0xe7] +@ CHECK: sbfxgt r4, r5, #16, #16 @ encoding: [0x55,0x48,0xaf,0xc7] + + @------------------------------------------------------------------------------ @ SEL @------------------------------------------------------------------------------ @@ -2001,3 +2011,11 @@ _func: @ CHECK: uasxeq r9, r12, r0 @ encoding: [0x30,0x9f,0x5c,0x06] +@------------------------------------------------------------------------------ +@ UBFX +@------------------------------------------------------------------------------ + ubfx r4, r5, #16, #1 + ubfxgt r4, r5, #16, #16 + +@ CHECK: ubfx r4, r5, #16, #1 @ encoding: [0x55,0x48,0xe0,0xe7] +@ CHECK: ubfxgt r4, r5, #16, #16 @ encoding: [0x55,0x48,0xef,0xc7] diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s index e086128f420..cc244164a48 100644 --- a/test/MC/ARM/diagnostics.s +++ b/test/MC/ARM/diagnostics.s @@ -272,3 +272,14 @@ @ CHECK-ERRORS: error: rotate operator 'ror' expected @ CHECK-ERRORS: sxtb16ge r2, r3, lsr #24 @ CHECK-ERRORS: ^ + + @ Out of range width for SBFX/UBFX + sbfx r4, r5, #31, #2 + ubfxgt r4, r5, #16, #17 + +@ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb] +@ CHECK-ERRORS: sbfx r4, r5, #31, #2 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb] +@ CHECK-ERRORS: ubfxgt r4, r5, #16, #17 +@ CHECK-ERRORS: ^