Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index 3cbd4675e4a11f485597b6c5a7001ec4cb76ee64..d21bd1b11cc498cc57542e187227dd806cb72b9f 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -224,13 +224,17 @@ bool encodeAdvSIMDExpandImm(IValueT Value, Type ElmtTy, IValueT &Op, |
return false; |
Imm8 = Value; |
switch (ElmtTy) { |
+ case IceType_i8: |
+ Op = 0; |
+ Cmode = 14; // 0b1110 |
+ return true; |
case IceType_i16: |
Op = 0; |
- Cmode = 8; // 100:0 |
+ Cmode = 8; // 0b1000 |
return true; |
case IceType_i32: |
Op = 0; |
- Cmode = 0; // 000:0 |
+ Cmode = 0; // 0b0000 |
return true; |
default: |
return false; |
@@ -1215,6 +1219,33 @@ void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy, |
isFloatingType(ElmtTy), OpcodeName); |
} |
+void AssemblerARM32::emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd, |
+ const Operand *OpQm, const IValueT Imm6, |
+ const char *OpcodeName) { |
+ const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); |
+ const IValueT Qn = 0; |
+ const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); |
+ constexpr bool UseQRegs = true; |
+ constexpr bool IsFloatTy = false; |
+ constexpr IValueT ElmtShift = 16; |
+ emitSIMDBase(Opcode | (Imm6 << ElmtShift), mapQRegToDReg(Qd), |
+ mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs, IsFloatTy); |
+} |
+ |
+void AssemblerARM32::emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd, |
+ const Operand *OpQm, |
+ const char *OpcodeName) { |
+ const IValueT SIMDOpcode = |
+ B24 | B23 | B21 | B20 | B19 | B17 | B16 | B10 | B9 | Opcode; |
+ constexpr bool UseQRegs = true; |
+ constexpr bool IsFloatTy = false; |
+ const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); |
+ constexpr IValueT Qn = 0; |
+ const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); |
+ emitSIMDBase(SIMDOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), |
+ mapQRegToDReg(Qm), UseQRegs, IsFloatTy); |
+} |
+ |
void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, |
IValueT Dd, IValueT Dn, IValueT Dm) { |
assert(Dd < RegARM32::getNumDRegs()); |
@@ -2557,6 +2588,50 @@ void AssemblerARM32::vcvtus(const Operand *OpSd, const Operand *OpSm, |
emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm); |
} |
+void AssemblerARM32::vcvtqsi(const Operand *OpQd, const Operand *OpQm) { |
+ // VCVT (between floating-point and integer, Advanced SIMD) |
+ // - ARM Section A8.8.305, encoding A1: |
+ // vcvt<c>.f32.s32 <Qd>, <Qm> |
+ // |
+ // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 10=op. |
+ constexpr const char *Vcvtqsi = "vcvt.s32.f32"; |
+ constexpr IValueT VcvtqsiOpcode = B8; |
+ emitSIMDCvtqq(VcvtqsiOpcode, OpQd, OpQm, Vcvtqsi); |
+} |
+ |
+void AssemblerARM32::vcvtqsu(const Operand *OpQd, const Operand *OpQm) { |
+ // VCVT (between floating-point and integer, Advanced SIMD) |
+ // - ARM Section A8.8.305, encoding A1: |
+ // vcvt<c>.f32.u32 <Qd>, <Qm> |
+ // |
+ // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 11=op. |
+ constexpr const char *Vcvtqsu = "vcvt.u32.f32"; |
+ constexpr IValueT VcvtqsuOpcode = B8 | B7; |
+ emitSIMDCvtqq(VcvtqsuOpcode, OpQd, OpQm, Vcvtqsu); |
+} |
+ |
+void AssemblerARM32::vcvtqis(const Operand *OpQd, const Operand *OpQm) { |
+ // VCVT (between floating-point and integer, Advanced SIMD) |
+ // - ARM Section A8.8.305, encoding A1: |
+ // vcvt<c>.f32.s32 <Qd>, <Qm> |
+ // |
+ // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op. |
+ constexpr const char *Vcvtqis = "vcvt.f32.s32"; |
+ constexpr IValueT VcvtqisOpcode = 0; |
+ emitSIMDCvtqq(VcvtqisOpcode, OpQd, OpQm, Vcvtqis); |
+} |
+ |
+void AssemblerARM32::vcvtqus(const Operand *OpQd, const Operand *OpQm) { |
+ // VCVT (between floating-point and integer, Advanced SIMD) |
+ // - ARM Section A8.8.305, encoding A1: |
+ // vcvt<c>.f32.u32 <Qd>, <Qm> |
+ // |
+ // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op. |
+ constexpr const char *Vcvtqus = "vcvt.f32.u32"; |
+ constexpr IValueT VcvtqusOpcode = B7; |
+ emitSIMDCvtqq(VcvtqusOpcode, OpQd, OpQm, Vcvtqus); |
+} |
+ |
void AssemblerARM32::emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, |
IValueT Sm) { |
assert(Dd < RegARM32::getNumDRegs()); |
@@ -3267,6 +3342,70 @@ void AssemblerARM32::vshlqi(Type ElmtTy, const Operand *OpQd, |
emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl); |
} |
+namespace { |
+enum SIMDShiftType { ST_Vshl, ST_Vshr }; |
+IValueT encodeSIMDShiftImm6(SIMDShiftType Shift, Type ElmtTy, |
+ const ConstantInteger32 *Imm6) { |
+ const IValueT Imm = Imm6->getValue(); |
+ assert(Imm > 0); |
+ const SizeT MaxShift = getScalarIntBitWidth(ElmtTy); |
+ assert(Imm < MaxShift); |
+ assert(ElmtTy == IceType_i8 || ElmtTy == IceType_i16 || |
+ ElmtTy == IceType_i32); |
+ const IValueT VshlImm = Imm - MaxShift; |
+ const IValueT VshrImm = 2 * MaxShift - Imm; |
+ return ((Shift == ST_Vshl) ? VshlImm : VshrImm) & (2 * MaxShift - 1); |
+} |
+} // end of anonymous namespace |
+ |
+void AssemblerARM32::vshlqc(Type ElmtTy, const Operand *OpQd, |
+ const Operand *OpQm, |
+ const ConstantInteger32 *Imm6) { |
+ // VSHL - ARM section A8.8.395, encoding A1: |
+ // vshl Qd, Qm, #Imm |
+ // |
+ // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6, |
+ // 0=U, 1=Q, 0=L. |
+ assert(isScalarIntegerType(ElmtTy) && |
+ "vshl expects vector with integer element type"); |
+ constexpr const char *Vshl = "vshl"; |
+ constexpr IValueT VshlOpcode = B23 | B10 | B8 | B4; |
+ emitSIMDShiftqqc(VshlOpcode, OpQd, OpQm, |
+ encodeSIMDShiftImm6(ST_Vshl, ElmtTy, Imm6), Vshl); |
+} |
+ |
+void AssemblerARM32::vshrqic(Type ElmtTy, const Operand *OpQd, |
+ const Operand *OpQm, |
+ const ConstantInteger32 *Imm6) { |
+ // VSHR - ARM section A8.8.398, encoding A1: |
+ // vshr Qd, Qm, #Imm |
+ // |
+ // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6, |
+ // 0=U, 1=Q, 0=L. |
+ assert(isScalarIntegerType(ElmtTy) && |
+ "vshr expects vector with integer element type"); |
+ constexpr const char *Vshr = "vshr"; |
+ constexpr IValueT VshrOpcode = B23 | B4; |
+ emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm, |
+ encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr); |
+} |
+ |
+void AssemblerARM32::vshrquc(Type ElmtTy, const Operand *OpQd, |
+ const Operand *OpQm, |
+ const ConstantInteger32 *Imm6) { |
+ // VSHR - ARM section A8.8.398, encoding A1: |
+ // vshr Qd, Qm, #Imm |
+ // |
+ // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6, |
+ // 0=U, 1=Q, 0=L. |
+ assert(isScalarIntegerType(ElmtTy) && |
+ "vshr expects vector with integer element type"); |
+ constexpr const char *Vshr = "vshr"; |
+ constexpr IValueT VshrOpcode = B23 | B4; |
+ emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm, |
+ encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr); |
+} |
+ |
void AssemblerARM32::vshlqu(Type ElmtTy, const Operand *OpQd, |
const Operand *OpQm, const Operand *OpQn) { |
// VSHL - ARM section A8.8.396, encoding A1: |