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 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1004 assert(Rn < RegARM32::getNumGPRegs()); | 1014 assert(Rn < RegARM32::getNumGPRegs()); |
1005 assert(Rm < RegARM32::getNumGPRegs()); | 1015 assert(Rm < RegARM32::getNumGPRegs()); |
1006 assert(CondARM32::isDefined(Cond)); | 1016 assert(CondARM32::isDefined(Cond)); |
1007 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 1017 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
1008 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | | 1018 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | |
1009 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | | 1019 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | |
1010 (Rm << kDivRmShift); | 1020 (Rm << kDivRmShift); |
1011 emitInst(Encoding); | 1021 emitInst(Encoding); |
1012 } | 1022 } |
1013 | 1023 |
1024 void AssemblerARM32::emitInsertExtractInt(CondARM32::Cond Cond, | |
1025 const Operand *OpQn, uint32_t Index, | |
1026 const Operand *OpRt, bool IsExtract, | |
1027 const char *InstName) { | |
1028 IValueT Rt = encodeGPRegister(OpRt, "Rt", InstName); | |
John
2016/02/10 20:25:38
const
Karl
2016/02/10 21:31:02
Done.
| |
1029 IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", InstName)); | |
1030 assert(Rt != RegARM32::Encoded_Reg_pc); | |
1031 assert(Rt != RegARM32::Encoded_Reg_sp); | |
1032 assert(CondARM32::isDefined(Cond)); | |
1033 const uint32_t BitSize = typeWidthInBytes(OpRt->getType()) * CHAR_BIT; | |
1034 IValueT Opcode1 = 0; | |
1035 IValueT Opcode2 = 0; | |
1036 switch (BitSize) { | |
1037 default: | |
1038 llvm::report_fatal_error(std::string(InstName) + | |
1039 ": Unable to process type " + | |
1040 typeIceString(OpRt->getType())); | |
1041 case 8: | |
1042 assert(Index < 16); | |
1043 Dn = Dn + mask(Index, 3, 1); | |
John
2016/02/10 20:25:38
perhaps | instead of +?
Karl
2016/02/10 21:31:03
Actually, we want an add here. We increment Dn to
| |
1044 Opcode1 = B1 | mask(Index, 2, 1); | |
1045 Opcode2 = mask(Index, 0, 2); | |
1046 break; | |
1047 case 16: | |
1048 assert(Index < 8); | |
1049 Dn = Dn + mask(Index, 2, 1); | |
1050 Opcode1 = mask(Index, 1, 1); | |
1051 Opcode2 = (mask(Index, 0, 1) << 1) | B0; | |
1052 break; | |
1053 case 32: | |
1054 assert(Index < 4); | |
1055 Dn = Dn + mask(Index, 1, 1); | |
1056 Opcode1 = mask(Index, 0, 1); | |
1057 break; | |
1058 } | |
1059 const IValueT Encoding = B27 | B26 | B25 | B11 | B9 | B8 | B4 | | |
1060 (encodeCondition(Cond) << kConditionShift) | | |
1061 (Opcode1 << 21) | | |
1062 (getXXXXInRegYXXXX(Dn) << kRnShift) | (Rt << 12) | | |
1063 (encodeBool(IsExtract) << 20) | | |
1064 (getYInRegYXXXX(Dn) << 7) | (Opcode2 << 5); | |
1065 emitInst(Encoding); | |
1066 } | |
1067 | |
1068 void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) { | |
1069 // VMOV (register) - ARM section A8.8.340, encoding A2: | |
1070 // vmov<c>.f32 <Sd>, <Sm> | |
1071 // | |
1072 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. | |
1073 constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6; | |
1074 constexpr IValueT S0 = 0; | |
1075 emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm); | |
1076 } | |
1077 | |
1014 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, | 1078 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
1015 IValueT Rn, IValueT Rm, IValueT Rs, | 1079 IValueT Rn, IValueT Rm, IValueT Rs, |
1016 bool SetFlags) { | 1080 bool SetFlags) { |
1017 assert(Rd < RegARM32::getNumGPRegs()); | 1081 assert(Rd < RegARM32::getNumGPRegs()); |
1018 assert(Rn < RegARM32::getNumGPRegs()); | 1082 assert(Rn < RegARM32::getNumGPRegs()); |
1019 assert(Rm < RegARM32::getNumGPRegs()); | 1083 assert(Rm < RegARM32::getNumGPRegs()); |
1020 assert(Rs < RegARM32::getNumGPRegs()); | 1084 assert(Rs < RegARM32::getNumGPRegs()); |
1021 assert(CondARM32::isDefined(Cond)); | 1085 assert(CondARM32::isDefined(Cond)); |
1022 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | | 1086 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
1023 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | | 1087 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | |
(...skipping 1624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2648 assert(Rt2 != RegARM32::Encoded_Reg_pc); | 2712 assert(Rt2 != RegARM32::Encoded_Reg_pc); |
2649 assert(Rt != Rt2); | 2713 assert(Rt != Rt2); |
2650 assert(CondARM32::isDefined(Cond)); | 2714 assert(CondARM32::isDefined(Cond)); |
2651 IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 | | 2715 IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 | |
2652 (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) | | 2716 (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) | |
2653 (Rt << 12) | (getYInRegYXXXX(Dm) << 5) | | 2717 (Rt << 12) | (getYInRegYXXXX(Dm) << 5) | |
2654 getXXXXInRegYXXXX(Dm); | 2718 getXXXXInRegYXXXX(Dm); |
2655 emitInst(Encoding); | 2719 emitInst(Encoding); |
2656 } | 2720 } |
2657 | 2721 |
2722 void AssemblerARM32::vmovqir(const Operand *OpQn, uint32_t Index, | |
2723 const Operand *OpRt, CondARM32::Cond Cond) { | |
2724 // VMOV (ARM core register to scalar) - ARM section A8.8.341, encoding A1: | |
2725 // vmov<c>.<size> <Dn[x]>, <Rt> | |
2726 constexpr const char *Vmovdr = "vmovdr"; | |
2727 constexpr bool IsExtract = true; | |
2728 emitInsertExtractInt(Cond, OpQn, Index, OpRt, !IsExtract, Vmovdr); | |
2729 } | |
2730 | |
2731 void AssemblerARM32::vmovqis(const Operand *OpQd, uint32_t Index, | |
2732 const Operand *OpSm, CondARM32::Cond Cond) { | |
2733 constexpr const char *Vmovqis = "vmovqis"; | |
2734 assert(Index < 4); | |
2735 IValueT Sd = mapQRegToSReg(encodeQRegister(OpQd, "Qd", Vmovqis)) + Index; | |
2736 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovqis); | |
2737 emitMoveSS(Cond, Sd, Sm); | |
2738 } | |
2739 | |
2740 void AssemblerARM32::vmovrqi(const Operand *OpRt, const Operand *OpQn, | |
2741 uint32_t Index, CondARM32::Cond Cond) { | |
2742 // VMOV (scalar to ARM core register) - ARM section A8.8.342, encoding A1: | |
2743 // vmov<c>.<dt> <Rt>, <Dn[x]> | |
2744 constexpr const char *Vmovrd = "vmovrd"; | |
2745 constexpr bool IsExtract = true; | |
2746 emitInsertExtractInt(Cond, OpQn, Index, OpRt, IsExtract, Vmovrd); | |
2747 } | |
2748 | |
2658 void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2, | 2749 void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2, |
2659 const Operand *OpDm, CondARM32::Cond Cond) { | 2750 const Operand *OpDm, CondARM32::Cond Cond) { |
2660 // VMOV (between two ARM core registers and a doubleword extension register). | 2751 // VMOV (between two ARM core registers and a doubleword extension register). |
2661 // ARM section A8.8.345, encoding A1: | 2752 // ARM section A8.8.345, encoding A1: |
2662 // vmov<c> <Rt>, <Rt2>, <Dm> | 2753 // vmov<c> <Rt>, <Rt2>, <Dm> |
2663 // | 2754 // |
2664 // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and | 2755 // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and |
2665 // Mmmmm=Dm. | 2756 // Mmmmm=Dm. |
2666 constexpr const char *Vmovrrd = "vmovrrd"; | 2757 constexpr const char *Vmovrrd = "vmovrrd"; |
2667 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd); | 2758 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2710 IValueT Imm8 = OpFpImm->getModifiedImm(); | 2801 IValueT Imm8 = OpFpImm->getModifiedImm(); |
2711 assert(Imm8 < (1 << 8)); | 2802 assert(Imm8 < (1 << 8)); |
2712 constexpr IValueT VmovsOpcode = B23 | B21 | B20; | 2803 constexpr IValueT VmovsOpcode = B23 | B21 | B20; |
2713 IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf); | 2804 IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf); |
2714 constexpr IValueT S0 = 0; | 2805 constexpr IValueT S0 = 0; |
2715 emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0); | 2806 emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0); |
2716 } | 2807 } |
2717 | 2808 |
2718 void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm, | 2809 void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm, |
2719 CondARM32::Cond Cond) { | 2810 CondARM32::Cond Cond) { |
2720 // VMOV (register) - ARM section A8.8.340, encoding A2: | |
2721 // vmov<c>.f32 <Sd>, <Sm> | |
2722 // | |
2723 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. | |
2724 constexpr const char *Vmovss = "Vmovss"; | 2811 constexpr const char *Vmovss = "Vmovss"; |
2725 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss); | 2812 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss); |
2726 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss); | 2813 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss); |
2727 constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6; | 2814 emitMoveSS(Cond, Sd, Sm); |
2728 constexpr IValueT S0 = 0; | 2815 } |
2729 emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm); | 2816 |
2817 void AssemblerARM32::vmovsqi(const Operand *OpSd, const Operand *OpQm, | |
2818 uint32_t Index, CondARM32::Cond Cond) { | |
2819 constexpr const char *Vmovsqi = "vmovsqi"; | |
2820 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovsqi); | |
John
2016/02/10 20:25:38
const
Karl
2016/02/10 21:31:03
Done.
| |
2821 assert(Index < 4); | |
2822 IValueT Sm = mapQRegToSReg(encodeQRegister(OpQm, "Qm", Vmovsqi)) + Index; | |
John
2016/02/10 20:25:38
const
Karl
2016/02/10 21:31:02
Done.
| |
2823 emitMoveSS(Cond, Sd, Sm); | |
2730 } | 2824 } |
2731 | 2825 |
2732 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, | 2826 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, |
2733 CondARM32::Cond Cond) { | 2827 CondARM32::Cond Cond) { |
2734 // VMOV (between ARM core register and single-precision register) | 2828 // VMOV (between ARM core register and single-precision register) |
2735 // ARM section A8.8.343, encoding A1. | 2829 // ARM section A8.8.343, encoding A1. |
2736 // | 2830 // |
2737 // vmov<c> <Sn>, <Rt> | 2831 // vmov<c> <Sn>, <Rt> |
2738 // | 2832 // |
2739 // 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... | |
3051 constexpr const char *Vsqrts = "vsqrts"; | 3145 constexpr const char *Vsqrts = "vsqrts"; |
3052 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); | 3146 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); |
3053 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); | 3147 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); |
3054 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; | 3148 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; |
3055 constexpr IValueT S0 = 0; | 3149 constexpr IValueT S0 = 0; |
3056 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); | 3150 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); |
3057 } | 3151 } |
3058 | 3152 |
3059 } // end of namespace ARM32 | 3153 } // end of namespace ARM32 |
3060 } // end of namespace Ice | 3154 } // end of namespace Ice |
OLD | NEW |