OLD | NEW |
1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
6 // | 6 // |
7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 case IceType_f32: | 151 case IceType_f32: |
152 return 0; | 152 return 0; |
153 case IceType_i16: | 153 case IceType_i16: |
154 return 1; | 154 return 1; |
155 case IceType_i32: | 155 case IceType_i32: |
156 return 2; | 156 return 2; |
157 case IceType_i64: | 157 case IceType_i64: |
158 return 3; | 158 return 3; |
159 default: | 159 default: |
160 llvm::report_fatal_error("SIMD op: Don't understand element type " + | 160 llvm::report_fatal_error("SIMD op: Don't understand element type " + |
161 std::string(typeString(ElmtTy))); | 161 typeIceString(ElmtTy)); |
162 } | 162 } |
163 } | 163 } |
164 | 164 |
165 IValueT encodeShift(OperandARM32::ShiftKind Shift) { | 165 IValueT encodeShift(OperandARM32::ShiftKind Shift) { |
166 // Follows encoding in ARM section A8.4.1 "Constant shifts". | 166 // Follows encoding in ARM section A8.4.1 "Constant shifts". |
167 switch (Shift) { | 167 switch (Shift) { |
168 case OperandARM32::kNoShift: | 168 case OperandARM32::kNoShift: |
169 case OperandARM32::LSL: | 169 case OperandARM32::LSL: |
170 return 0; // 0b00 | 170 return 0; // 0b00 |
171 case OperandARM32::LSR: | 171 case OperandARM32::LSR: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 } | 206 } |
207 | 207 |
208 IValueT getEncodedDRegNum(const Variable *Var) { | 208 IValueT getEncodedDRegNum(const Variable *Var) { |
209 return RegARM32::getEncodedDReg(Var->getRegNum()); | 209 return RegARM32::getEncodedDReg(Var->getRegNum()); |
210 } | 210 } |
211 | 211 |
212 IValueT getEncodedQRegNum(const Variable *Var) { | 212 IValueT getEncodedQRegNum(const Variable *Var) { |
213 return RegARM32::getEncodedQReg(Var->getRegNum()); | 213 return RegARM32::getEncodedQReg(Var->getRegNum()); |
214 } | 214 } |
215 | 215 |
216 IValueT mapQRegToDReg(IValueT EncodedQReg) { return EncodedQReg << 1; } | 216 IValueT mapQRegToDReg(IValueT EncodedQReg) { |
| 217 IValueT DReg = EncodedQReg << 1; |
| 218 assert(DReg < RegARM32::getNumDRegs()); |
| 219 return DReg; |
| 220 } |
| 221 |
| 222 IValueT mapQRegToSReg(IValueT EncodedQReg) { |
| 223 IValueT SReg = EncodedQReg << 2; |
| 224 assert(SReg < RegARM32::getNumSRegs()); |
| 225 return SReg; |
| 226 } |
217 | 227 |
218 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } | 228 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } |
219 | 229 |
220 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } | 230 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } |
221 | 231 |
222 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } | 232 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } |
223 | 233 |
224 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } | 234 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } |
225 | 235 |
226 // Defines layouts of an operand representing a (register) memory address, | 236 // Defines layouts of an operand representing a (register) memory address, |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 assert(Rn < RegARM32::getNumGPRegs()); | 1013 assert(Rn < RegARM32::getNumGPRegs()); |
1004 assert(Rm < RegARM32::getNumGPRegs()); | 1014 assert(Rm < RegARM32::getNumGPRegs()); |
1005 assert(CondARM32::isDefined(Cond)); | 1015 assert(CondARM32::isDefined(Cond)); |
1006 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 1016 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
1007 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | | 1017 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | |
1008 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | | 1018 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | |
1009 (Rm << kDivRmShift); | 1019 (Rm << kDivRmShift); |
1010 emitInst(Encoding); | 1020 emitInst(Encoding); |
1011 } | 1021 } |
1012 | 1022 |
| 1023 void AssemblerARM32::emitInsertExtractInt(CondARM32::Cond Cond, |
| 1024 const Operand *OpQn, uint32_t Index, |
| 1025 const Operand *OpRt, bool IsExtract, |
| 1026 const char *InstName) { |
| 1027 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InstName); |
| 1028 IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", InstName)); |
| 1029 assert(Rt != RegARM32::Encoded_Reg_pc); |
| 1030 assert(Rt != RegARM32::Encoded_Reg_sp); |
| 1031 assert(CondARM32::isDefined(Cond)); |
| 1032 const uint32_t BitSize = typeWidthInBytes(OpRt->getType()) * CHAR_BIT; |
| 1033 IValueT Opcode1 = 0; |
| 1034 IValueT Opcode2 = 0; |
| 1035 switch (BitSize) { |
| 1036 default: |
| 1037 llvm::report_fatal_error(std::string(InstName) + |
| 1038 ": Unable to process type " + |
| 1039 typeIceString(OpRt->getType())); |
| 1040 case 8: |
| 1041 assert(Index < 16); |
| 1042 Dn = Dn | mask(Index, 3, 1); |
| 1043 Opcode1 = B1 | mask(Index, 2, 1); |
| 1044 Opcode2 = mask(Index, 0, 2); |
| 1045 break; |
| 1046 case 16: |
| 1047 assert(Index < 8); |
| 1048 Dn = Dn | mask(Index, 2, 1); |
| 1049 Opcode1 = mask(Index, 1, 1); |
| 1050 Opcode2 = (mask(Index, 0, 1) << 1) | B0; |
| 1051 break; |
| 1052 case 32: |
| 1053 assert(Index < 4); |
| 1054 Dn = Dn | mask(Index, 1, 1); |
| 1055 Opcode1 = mask(Index, 0, 1); |
| 1056 break; |
| 1057 } |
| 1058 const IValueT Encoding = B27 | B26 | B25 | B11 | B9 | B8 | B4 | |
| 1059 (encodeCondition(Cond) << kConditionShift) | |
| 1060 (Opcode1 << 21) | |
| 1061 (getXXXXInRegYXXXX(Dn) << kRnShift) | (Rt << 12) | |
| 1062 (encodeBool(IsExtract) << 20) | |
| 1063 (getYInRegYXXXX(Dn) << 7) | (Opcode2 << 5); |
| 1064 emitInst(Encoding); |
| 1065 } |
| 1066 |
| 1067 void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) { |
| 1068 // VMOV (register) - ARM section A8.8.340, encoding A2: |
| 1069 // vmov<c>.f32 <Sd>, <Sm> |
| 1070 // |
| 1071 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. |
| 1072 constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6; |
| 1073 constexpr IValueT S0 = 0; |
| 1074 emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm); |
| 1075 } |
| 1076 |
1013 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 1077 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
1014 IValueT Rn, IValueT Rm, IValueT Rs, | 1078 IValueT Rn, IValueT Rm, IValueT Rs, |
1015 bool SetFlags) { | 1079 bool SetFlags) { |
1016 assert(Rd < RegARM32::getNumGPRegs()); | 1080 assert(Rd < RegARM32::getNumGPRegs()); |
1017 assert(Rn < RegARM32::getNumGPRegs()); | 1081 assert(Rn < RegARM32::getNumGPRegs()); |
1018 assert(Rm < RegARM32::getNumGPRegs()); | 1082 assert(Rm < RegARM32::getNumGPRegs()); |
1019 assert(Rs < RegARM32::getNumGPRegs()); | 1083 assert(Rs < RegARM32::getNumGPRegs()); |
1020 assert(CondARM32::isDefined(Cond)); | 1084 assert(CondARM32::isDefined(Cond)); |
1021 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 1085 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
1022 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | | 1086 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | |
(...skipping 1624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2647 assert(Rt2 != RegARM32::Encoded_Reg_pc); | 2711 assert(Rt2 != RegARM32::Encoded_Reg_pc); |
2648 assert(Rt != Rt2); | 2712 assert(Rt != Rt2); |
2649 assert(CondARM32::isDefined(Cond)); | 2713 assert(CondARM32::isDefined(Cond)); |
2650 IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 | | 2714 IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 | |
2651 (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) | | 2715 (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) | |
2652 (Rt << 12) | (getYInRegYXXXX(Dm) << 5) | | 2716 (Rt << 12) | (getYInRegYXXXX(Dm) << 5) | |
2653 getXXXXInRegYXXXX(Dm); | 2717 getXXXXInRegYXXXX(Dm); |
2654 emitInst(Encoding); | 2718 emitInst(Encoding); |
2655 } | 2719 } |
2656 | 2720 |
| 2721 void AssemblerARM32::vmovqir(const Operand *OpQn, uint32_t Index, |
| 2722 const Operand *OpRt, CondARM32::Cond Cond) { |
| 2723 // VMOV (ARM core register to scalar) - ARM section A8.8.341, encoding A1: |
| 2724 // vmov<c>.<size> <Dn[x]>, <Rt> |
| 2725 constexpr const char *Vmovdr = "vmovdr"; |
| 2726 constexpr bool IsExtract = true; |
| 2727 emitInsertExtractInt(Cond, OpQn, Index, OpRt, !IsExtract, Vmovdr); |
| 2728 } |
| 2729 |
| 2730 void AssemblerARM32::vmovqis(const Operand *OpQd, uint32_t Index, |
| 2731 const Operand *OpSm, CondARM32::Cond Cond) { |
| 2732 constexpr const char *Vmovqis = "vmovqis"; |
| 2733 assert(Index < 4); |
| 2734 IValueT Sd = mapQRegToSReg(encodeQRegister(OpQd, "Qd", Vmovqis)) + Index; |
| 2735 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovqis); |
| 2736 emitMoveSS(Cond, Sd, Sm); |
| 2737 } |
| 2738 |
| 2739 void AssemblerARM32::vmovrqi(const Operand *OpRt, const Operand *OpQn, |
| 2740 uint32_t Index, CondARM32::Cond Cond) { |
| 2741 // VMOV (scalar to ARM core register) - ARM section A8.8.342, encoding A1: |
| 2742 // vmov<c>.<dt> <Rt>, <Dn[x]> |
| 2743 constexpr const char *Vmovrd = "vmovrd"; |
| 2744 constexpr bool IsExtract = true; |
| 2745 emitInsertExtractInt(Cond, OpQn, Index, OpRt, IsExtract, Vmovrd); |
| 2746 } |
| 2747 |
2657 void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2, | 2748 void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2, |
2658 const Operand *OpDm, CondARM32::Cond Cond) { | 2749 const Operand *OpDm, CondARM32::Cond Cond) { |
2659 // VMOV (between two ARM core registers and a doubleword extension register). | 2750 // VMOV (between two ARM core registers and a doubleword extension register). |
2660 // ARM section A8.8.345, encoding A1: | 2751 // ARM section A8.8.345, encoding A1: |
2661 // vmov<c> <Rt>, <Rt2>, <Dm> | 2752 // vmov<c> <Rt>, <Rt2>, <Dm> |
2662 // | 2753 // |
2663 // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and | 2754 // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and |
2664 // Mmmmm=Dm. | 2755 // Mmmmm=Dm. |
2665 constexpr const char *Vmovrrd = "vmovrrd"; | 2756 constexpr const char *Vmovrrd = "vmovrrd"; |
2666 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd); | 2757 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2709 IValueT Imm8 = OpFpImm->getModifiedImm(); | 2800 IValueT Imm8 = OpFpImm->getModifiedImm(); |
2710 assert(Imm8 < (1 << 8)); | 2801 assert(Imm8 < (1 << 8)); |
2711 constexpr IValueT VmovsOpcode = B23 | B21 | B20; | 2802 constexpr IValueT VmovsOpcode = B23 | B21 | B20; |
2712 IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf); | 2803 IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf); |
2713 constexpr IValueT S0 = 0; | 2804 constexpr IValueT S0 = 0; |
2714 emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0); | 2805 emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0); |
2715 } | 2806 } |
2716 | 2807 |
2717 void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm, | 2808 void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm, |
2718 CondARM32::Cond Cond) { | 2809 CondARM32::Cond Cond) { |
2719 // VMOV (register) - ARM section A8.8.340, encoding A2: | |
2720 // vmov<c>.f32 <Sd>, <Sm> | |
2721 // | |
2722 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. | |
2723 constexpr const char *Vmovss = "Vmovss"; | 2810 constexpr const char *Vmovss = "Vmovss"; |
2724 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss); | 2811 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss); |
2725 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss); | 2812 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss); |
2726 constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6; | 2813 emitMoveSS(Cond, Sd, Sm); |
2727 constexpr IValueT S0 = 0; | 2814 } |
2728 emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm); | 2815 |
| 2816 void AssemblerARM32::vmovsqi(const Operand *OpSd, const Operand *OpQm, |
| 2817 uint32_t Index, CondARM32::Cond Cond) { |
| 2818 constexpr const char *Vmovsqi = "vmovsqi"; |
| 2819 const IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovsqi); |
| 2820 assert(Index < 4); |
| 2821 const IValueT Sm = |
| 2822 mapQRegToSReg(encodeQRegister(OpQm, "Qm", Vmovsqi)) + Index; |
| 2823 emitMoveSS(Cond, Sd, Sm); |
2729 } | 2824 } |
2730 | 2825 |
2731 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, | 2826 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, |
2732 CondARM32::Cond Cond) { | 2827 CondARM32::Cond Cond) { |
2733 // VMOV (between ARM core register and single-precision register) | 2828 // VMOV (between ARM core register and single-precision register) |
2734 // ARM section A8.8.343, encoding A1. | 2829 // ARM section A8.8.343, encoding A1. |
2735 // | 2830 // |
2736 // vmov<c> <Sn>, <Rt> | 2831 // vmov<c> <Sn>, <Rt> |
2737 // | 2832 // |
2738 // cccc11100000nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt. | 2833 // cccc11100000nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt. |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3050 constexpr const char *Vsqrts = "vsqrts"; | 3145 constexpr const char *Vsqrts = "vsqrts"; |
3051 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); | 3146 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); |
3052 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); | 3147 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); |
3053 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; | 3148 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; |
3054 constexpr IValueT S0 = 0; | 3149 constexpr IValueT S0 = 0; |
3055 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); | 3150 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); |
3056 } | 3151 } |
3057 | 3152 |
3058 } // end of namespace ARM32 | 3153 } // end of namespace ARM32 |
3059 } // end of namespace Ice | 3154 } // end of namespace Ice |
OLD | NEW |