Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index bba8e16fbbea420e1d23e959408b046076e1969b..ebc95a45db58285aad3ff9e13015092fe268cf5d 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -215,6 +215,28 @@ IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } |
IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } |
+// Figures out Op/Cmode values for given Value. Returns true if able to encode. |
+bool encodeAdvSIMDExpandImm(IValueT Value, Type ElmtTy, IValueT &Op, |
+ IValueT &Cmode, IValueT &Imm8) { |
+ // TODO(kschimpf): Handle other shifted 8-bit values. |
+ constexpr IValueT Imm8Mask = 0xFF; |
+ if ((Value & IValueT(~Imm8Mask)) != 0) |
+ return false; |
+ Imm8 = Value; |
+ switch (ElmtTy) { |
+ case IceType_i16: |
+ Op = 0; |
+ Cmode = 8; // 100:0 |
+ return true; |
+ case IceType_i32: |
+ Op = 0; |
+ Cmode = 0; // 000:0 |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
// Defines layouts of an operand representing a (register) memory address, |
// possibly modified by an immediate value. |
enum EncodedImmAddress { |
@@ -2710,6 +2732,36 @@ void AssemblerARM32::vld1qr(size_t ElmtSize, const Operand *OpQd, |
emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vld1qr); |
} |
+bool AssemblerARM32::vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm) { |
+ // VMOV (immediate) - ARM section A8.8.320, encoding A1: |
+ // VMOV.<dt> <Qd>, #<Imm> |
+ // 1111001x1D000yyyddddcccc01p1zzzz where Qd=Ddddd, Imm=xyyyzzzz, cmode=cccc, |
+ // and Op=p. |
+ constexpr const char *Vmovc = "vmovc"; |
+ const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmovc)); |
+ IValueT Value = Imm->getValue(); |
+ const Type VecTy = OpQd->getType(); |
+ if (!isVectorType(VecTy)) |
+ return false; |
+ |
+ IValueT Op; |
+ IValueT Cmode; |
+ IValueT Imm8; |
+ if (!encodeAdvSIMDExpandImm(Value, typeElementType(VecTy), Op, Cmode, Imm8)) |
+ return false; |
+ if (Op == 0 && mask(Cmode, 0, 1) == 1) |
+ return false; |
+ if (Op == 1 && Cmode != 13) |
+ return false; |
+ const IValueT Encoding = |
+ (0xF << kConditionShift) | B25 | B23 | B6 | B4 | |
+ (mask(Imm8, 7, 1) << 24) | (getYInRegYXXXX(Dd) << 22) | |
+ (mask(Imm8, 4, 3) << 16) | (getXXXXInRegYXXXX(Dd) << 12) | (Cmode << 8) | |
+ (Op << 5) | mask(Imm8, 0, 4); |
+ emitInst(Encoding); |
+ return true; |
+} |
+ |
void AssemblerARM32::vmovd(const Operand *OpDd, |
const OperandARM32FlexFpImm *OpFpImm, |
CondARM32::Cond Cond) { |