From 6dce00ced45b5bd1b7f34fe6f2d70c50fc090664 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Tue, 13 Jul 2010 04:44:34 +0000 Subject: [PATCH] Move NEON "modified immediate" encode/decode into ARMAddressingModes.h to avoid replicated code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108227 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAddressingModes.h | 62 ++++++++++++++++++++ lib/Target/ARM/ARMISelLowering.cpp | 35 +++++------ lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 32 +--------- lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp | 32 +--------- 4 files changed, 84 insertions(+), 77 deletions(-) diff --git a/lib/Target/ARM/ARMAddressingModes.h b/lib/Target/ARM/ARMAddressingModes.h index d136afa544b..d316b13e048 100644 --- a/lib/Target/ARM/ARMAddressingModes.h +++ b/lib/Target/ARM/ARMAddressingModes.h @@ -523,6 +523,68 @@ namespace ARM_AM { // Valid alignments are: 0, 8, 16, and 32 bytes, depending on the specific // instruction. + //===--------------------------------------------------------------------===// + // NEON Modified Immediates + //===--------------------------------------------------------------------===// + // + // Several NEON instructions (e.g., VMOV) take a "modified immediate" + // vector operand, where a small immediate encoded in the instruction + // specifies a full NEON vector value. These modified immediates are + // represented here as encoded integers. The low 8 bits hold the immediate + // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold + // the "Cmode" field of the instruction. The interfaces below treat the + // Op and Cmode values as a single 5-bit value. + + static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) { + return (OpCmode << 8) | Val; + } + static inline unsigned getNEONModImmOpCmode(unsigned ModImm) { + return (ModImm >> 8) & 0x1f; + } + static inline unsigned getNEONModImmVal(unsigned ModImm) { + return ModImm & 0xff; + } + + /// decodeNEONModImm - Decode a NEON modified immediate value into the + /// element value and the element size in bits. (If the element size is + /// smaller than the vector, it is splatted into all the elements.) + static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) { + unsigned OpCmode = getNEONModImmOpCmode(ModImm); + unsigned Imm8 = getNEONModImmVal(ModImm); + uint64_t Val = 0; + + if (OpCmode == 0xe) { + // 8-bit vector elements + Val = Imm8; + EltBits = 8; + } else if ((OpCmode & 0xc) == 0x8) { + // 16-bit vector elements + unsigned ByteNum = (OpCmode & 0x6) >> 1; + Val = Imm8 << (8 * ByteNum); + EltBits = 16; + } else if ((OpCmode & 0x8) == 0) { + // 32-bit vector elements, zero with one byte set + unsigned ByteNum = (OpCmode & 0x6) >> 1; + Val = Imm8 << (8 * ByteNum); + EltBits = 32; + } else if ((OpCmode & 0xe) == 0xc) { + // 32-bit vector elements, one byte with low bits set + unsigned ByteNum = 1 + (OpCmode & 0x1); + Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); + EltBits = 32; + } else if (OpCmode == 0x1e) { + // 64-bit vector elements + for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { + if ((ModImm >> ByteNum) & 1) + Val |= (uint64_t)0xff << (8 * ByteNum); + } + EltBits = 64; + } else { + assert(false && "Unsupported NEON immediate"); + } + return Val; + } + } // end namespace ARM_AM } // end namespace llvm diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 2d4426eb067..98d8b858542 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -2851,13 +2851,11 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) { /// isNEONModifiedImm - Check if the specified splat value corresponds to a /// valid vector constant for a NEON instruction with a "modified immediate" /// operand (e.g., VMOV). If so, return either the constant being -/// splatted or the encoded value, depending on the DoEncode parameter. The -/// format of the encoded value is: bit12=Op, bits11-8=Cmode, -/// bits7-0=Immediate. +/// splatted or the encoded value, depending on the DoEncode parameter. static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, bool isVMOV, bool DoEncode) { - unsigned Op, Cmode, Imm; + unsigned OpCmode, Imm; EVT VT; // SplatBitSize is set to the smallest size that splats the vector, so a @@ -2868,12 +2866,11 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, if (SplatBits == 0) SplatBitSize = 32; - Op = 0; switch (SplatBitSize) { case 8: // Any 1-byte value is OK. Op=0, Cmode=1110. assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big"); - Cmode = 0xe; + OpCmode = 0xe; Imm = SplatBits; VT = MVT::i8; break; @@ -2883,13 +2880,13 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, VT = MVT::i16; if ((SplatBits & ~0xff) == 0) { // Value = 0x00nn: Op=x, Cmode=100x. - Cmode = 0x8; + OpCmode = 0x8; Imm = SplatBits; break; } if ((SplatBits & ~0xff00) == 0) { // Value = 0xnn00: Op=x, Cmode=101x. - Cmode = 0xa; + OpCmode = 0xa; Imm = SplatBits >> 8; break; } @@ -2903,25 +2900,25 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, VT = MVT::i32; if ((SplatBits & ~0xff) == 0) { // Value = 0x000000nn: Op=x, Cmode=000x. - Cmode = 0; + OpCmode = 0; Imm = SplatBits; break; } if ((SplatBits & ~0xff00) == 0) { // Value = 0x0000nn00: Op=x, Cmode=001x. - Cmode = 0x2; + OpCmode = 0x2; Imm = SplatBits >> 8; break; } if ((SplatBits & ~0xff0000) == 0) { // Value = 0x00nn0000: Op=x, Cmode=010x. - Cmode = 0x4; + OpCmode = 0x4; Imm = SplatBits >> 16; break; } if ((SplatBits & ~0xff000000) == 0) { // Value = 0xnn000000: Op=x, Cmode=011x. - Cmode = 0x6; + OpCmode = 0x6; Imm = SplatBits >> 24; break; } @@ -2929,7 +2926,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, if ((SplatBits & ~0xffff) == 0 && ((SplatBits | SplatUndef) & 0xff) == 0xff) { // Value = 0x0000nnff: Op=x, Cmode=1100. - Cmode = 0xc; + OpCmode = 0xc; Imm = SplatBits >> 8; SplatBits |= 0xff; break; @@ -2938,7 +2935,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, if ((SplatBits & ~0xffffff) == 0 && ((SplatBits | SplatUndef) & 0xffff) == 0xffff) { // Value = 0x00nnffff: Op=x, Cmode=1101. - Cmode = 0xd; + OpCmode = 0xd; Imm = SplatBits >> 16; SplatBits |= 0xffff; break; @@ -2970,8 +2967,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, ImmMask <<= 1; } // Op=1, Cmode=1110. - Op = 1; - Cmode = 0xe; + OpCmode = 0x1e; SplatBits = Val; VT = MVT::i64; break; @@ -2982,12 +2978,13 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, return SDValue(); } - if (DoEncode) - return DAG.getTargetConstant((Op << 12) | (Cmode << 8) | Imm, MVT::i32); + if (DoEncode) { + unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm); + return DAG.getTargetConstant(EncodedVal, MVT::i32); + } return DAG.getTargetConstant(SplatBits, VT); } - /// getNEONModImm - If this is a valid vector constant for a NEON instruction /// with a "modified immediate" operand (e.g., VMOV) of the specified element /// size, return the encoded value for that immediate. The ByteSize field diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index b4809b5e4d2..6a40cf3602e 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -1030,35 +1030,9 @@ void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum, void ARMAsmPrinter::printNEONModImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { - unsigned Imm = MI->getOperand(OpNum).getImm(); - unsigned OpCmode = (Imm >> 8) & 0x1f; - unsigned Imm8 = Imm & 0xff; - uint64_t Val = 0; - - if (OpCmode == 0xe) { - // 8-bit vector elements - Val = Imm8; - } else if ((OpCmode & 0xc) == 0x8) { - // 16-bit vector elements - unsigned ByteNum = (OpCmode & 0x6) >> 1; - Val = Imm8 << (8 * ByteNum); - } else if ((OpCmode & 0x8) == 0) { - // 32-bit vector elements, zero with one byte set - unsigned ByteNum = (OpCmode & 0x6) >> 1; - Val = Imm8 << (8 * ByteNum); - } else if ((OpCmode & 0xe) == 0xc) { - // 32-bit vector elements, one byte with low bits set - unsigned ByteNum = 1 + (OpCmode & 0x1); - Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); - } else if (OpCmode == 0x1e) { - // 64-bit vector elements - for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { - if ((Imm >> ByteNum) & 1) - Val |= (uint64_t)0xff << (8 * ByteNum); - } - } else { - assert(false && "Unsupported NEON immediate"); - } + unsigned EncodedImm = MI->getOperand(OpNum).getImm(); + unsigned EltBits; + uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); O << "#0x" << utohexstr(Val); } diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp index b4abb658112..170819ad4f0 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -781,34 +781,8 @@ void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum, void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { - unsigned Imm = MI->getOperand(OpNum).getImm(); - unsigned OpCmode = (Imm >> 8) & 0x1f; - unsigned Imm8 = Imm & 0xff; - uint64_t Val = 0; - - if (OpCmode == 0xe) { - // 8-bit vector elements - Val = Imm8; - } else if ((OpCmode & 0xc) == 0x8) { - // 16-bit vector elements - unsigned ByteNum = (OpCmode & 0x6) >> 1; - Val = Imm8 << (8 * ByteNum); - } else if ((OpCmode & 0x8) == 0) { - // 32-bit vector elements, zero with one byte set - unsigned ByteNum = (OpCmode & 0x6) >> 1; - Val = Imm8 << (8 * ByteNum); - } else if ((OpCmode & 0xe) == 0xc) { - // 32-bit vector elements, one byte with low bits set - unsigned ByteNum = 1 + (OpCmode & 0x1); - Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); - } else if (OpCmode == 0x1e) { - // 64-bit vector elements - for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { - if ((Imm >> ByteNum) & 1) - Val |= (uint64_t)0xff << (8 * ByteNum); - } - } else { - assert(false && "Unsupported NEON immediate"); - } + unsigned EncodedImm = MI->getOperand(OpNum).getImm(); + unsigned EltBits; + uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits); O << "#0x" << utohexstr(Val); } -- 2.34.1