mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-01 18:12:49 +00:00
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
This commit is contained in:
parent
37a746bc85
commit
6dce00ced4
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user