| Index: src/IceAssemblerARM32.cpp
|
| diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
|
| index ba328c807b494716de33ac15eaecea328dd01f34..a9ef88e7f0115bc2e054f1e6f5c9cb703c732bec 100644
|
| --- a/src/IceAssemblerARM32.cpp
|
| +++ b/src/IceAssemblerARM32.cpp
|
| @@ -158,7 +158,7 @@ IValueT encodeElmtType(Type ElmtTy) {
|
| return 3;
|
| default:
|
| llvm::report_fatal_error("SIMD op: Don't understand element type " +
|
| - std::string(typeString(ElmtTy)));
|
| + typeIceString(ElmtTy));
|
| }
|
| }
|
|
|
| @@ -213,7 +213,17 @@ IValueT getEncodedQRegNum(const Variable *Var) {
|
| return RegARM32::getEncodedQReg(Var->getRegNum());
|
| }
|
|
|
| -IValueT mapQRegToDReg(IValueT EncodedQReg) { return EncodedQReg << 1; }
|
| +IValueT mapQRegToDReg(IValueT EncodedQReg) {
|
| + IValueT DReg = EncodedQReg << 1;
|
| + assert(DReg < RegARM32::getNumDRegs());
|
| + return DReg;
|
| +}
|
| +
|
| +IValueT mapQRegToSReg(IValueT EncodedQReg) {
|
| + IValueT SReg = EncodedQReg << 2;
|
| + assert(SReg < RegARM32::getNumSRegs());
|
| + return SReg;
|
| +}
|
|
|
| IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; }
|
|
|
| @@ -1010,6 +1020,60 @@ void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
|
| emitInst(Encoding);
|
| }
|
|
|
| +void AssemblerARM32::emitInsertExtractInt(CondARM32::Cond Cond,
|
| + const Operand *OpQn, uint32_t Index,
|
| + const Operand *OpRt, bool IsExtract,
|
| + const char *InstName) {
|
| + const IValueT Rt = encodeGPRegister(OpRt, "Rt", InstName);
|
| + IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", InstName));
|
| + assert(Rt != RegARM32::Encoded_Reg_pc);
|
| + assert(Rt != RegARM32::Encoded_Reg_sp);
|
| + assert(CondARM32::isDefined(Cond));
|
| + const uint32_t BitSize = typeWidthInBytes(OpRt->getType()) * CHAR_BIT;
|
| + IValueT Opcode1 = 0;
|
| + IValueT Opcode2 = 0;
|
| + switch (BitSize) {
|
| + default:
|
| + llvm::report_fatal_error(std::string(InstName) +
|
| + ": Unable to process type " +
|
| + typeIceString(OpRt->getType()));
|
| + case 8:
|
| + assert(Index < 16);
|
| + Dn = Dn | mask(Index, 3, 1);
|
| + Opcode1 = B1 | mask(Index, 2, 1);
|
| + Opcode2 = mask(Index, 0, 2);
|
| + break;
|
| + case 16:
|
| + assert(Index < 8);
|
| + Dn = Dn | mask(Index, 2, 1);
|
| + Opcode1 = mask(Index, 1, 1);
|
| + Opcode2 = (mask(Index, 0, 1) << 1) | B0;
|
| + break;
|
| + case 32:
|
| + assert(Index < 4);
|
| + Dn = Dn | mask(Index, 1, 1);
|
| + Opcode1 = mask(Index, 0, 1);
|
| + break;
|
| + }
|
| + const IValueT Encoding = B27 | B26 | B25 | B11 | B9 | B8 | B4 |
|
| + (encodeCondition(Cond) << kConditionShift) |
|
| + (Opcode1 << 21) |
|
| + (getXXXXInRegYXXXX(Dn) << kRnShift) | (Rt << 12) |
|
| + (encodeBool(IsExtract) << 20) |
|
| + (getYInRegYXXXX(Dn) << 7) | (Opcode2 << 5);
|
| + emitInst(Encoding);
|
| +}
|
| +
|
| +void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) {
|
| + // VMOV (register) - ARM section A8.8.340, encoding A2:
|
| + // vmov<c>.f32 <Sd>, <Sm>
|
| + //
|
| + // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
|
| + constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6;
|
| + constexpr IValueT S0 = 0;
|
| + emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm);
|
| +}
|
| +
|
| void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
|
| IValueT Rn, IValueT Rm, IValueT Rs,
|
| bool SetFlags) {
|
| @@ -2654,6 +2718,33 @@ void AssemblerARM32::vmovdrr(const Operand *OpDm, const Operand *OpRt,
|
| emitInst(Encoding);
|
| }
|
|
|
| +void AssemblerARM32::vmovqir(const Operand *OpQn, uint32_t Index,
|
| + const Operand *OpRt, CondARM32::Cond Cond) {
|
| + // VMOV (ARM core register to scalar) - ARM section A8.8.341, encoding A1:
|
| + // vmov<c>.<size> <Dn[x]>, <Rt>
|
| + constexpr const char *Vmovdr = "vmovdr";
|
| + constexpr bool IsExtract = true;
|
| + emitInsertExtractInt(Cond, OpQn, Index, OpRt, !IsExtract, Vmovdr);
|
| +}
|
| +
|
| +void AssemblerARM32::vmovqis(const Operand *OpQd, uint32_t Index,
|
| + const Operand *OpSm, CondARM32::Cond Cond) {
|
| + constexpr const char *Vmovqis = "vmovqis";
|
| + assert(Index < 4);
|
| + IValueT Sd = mapQRegToSReg(encodeQRegister(OpQd, "Qd", Vmovqis)) + Index;
|
| + IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovqis);
|
| + emitMoveSS(Cond, Sd, Sm);
|
| +}
|
| +
|
| +void AssemblerARM32::vmovrqi(const Operand *OpRt, const Operand *OpQn,
|
| + uint32_t Index, CondARM32::Cond Cond) {
|
| + // VMOV (scalar to ARM core register) - ARM section A8.8.342, encoding A1:
|
| + // vmov<c>.<dt> <Rt>, <Dn[x]>
|
| + constexpr const char *Vmovrd = "vmovrd";
|
| + constexpr bool IsExtract = true;
|
| + emitInsertExtractInt(Cond, OpQn, Index, OpRt, IsExtract, Vmovrd);
|
| +}
|
| +
|
| void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2,
|
| const Operand *OpDm, CondARM32::Cond Cond) {
|
| // VMOV (between two ARM core registers and a doubleword extension register).
|
| @@ -2716,16 +2807,20 @@ void AssemblerARM32::vmovs(const Operand *OpSd,
|
|
|
| void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm,
|
| CondARM32::Cond Cond) {
|
| - // VMOV (register) - ARM section A8.8.340, encoding A2:
|
| - // vmov<c>.f32 <Sd>, <Sm>
|
| - //
|
| - // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
|
| constexpr const char *Vmovss = "Vmovss";
|
| IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss);
|
| IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss);
|
| - constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6;
|
| - constexpr IValueT S0 = 0;
|
| - emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm);
|
| + emitMoveSS(Cond, Sd, Sm);
|
| +}
|
| +
|
| +void AssemblerARM32::vmovsqi(const Operand *OpSd, const Operand *OpQm,
|
| + uint32_t Index, CondARM32::Cond Cond) {
|
| + constexpr const char *Vmovsqi = "vmovsqi";
|
| + const IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovsqi);
|
| + assert(Index < 4);
|
| + const IValueT Sm =
|
| + mapQRegToSReg(encodeQRegister(OpQm, "Qm", Vmovsqi)) + Index;
|
| + emitMoveSS(Cond, Sd, Sm);
|
| }
|
|
|
| void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
|
|
|