| 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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 } | 137 } |
| 138 | 138 |
| 139 RegARM32::GPRRegister decodeGPRRegister(IValueT R) { | 139 RegARM32::GPRRegister decodeGPRRegister(IValueT R) { |
| 140 return static_cast<RegARM32::GPRRegister>(R); | 140 return static_cast<RegARM32::GPRRegister>(R); |
| 141 } | 141 } |
| 142 | 142 |
| 143 IValueT encodeCondition(CondARM32::Cond Cond) { | 143 IValueT encodeCondition(CondARM32::Cond Cond) { |
| 144 return static_cast<IValueT>(Cond); | 144 return static_cast<IValueT>(Cond); |
| 145 } | 145 } |
| 146 | 146 |
| 147 // Returns the SIMD encoding of the element type for the vector. | |
| 148 IValueT encodeElmtType(Type ElmtTy) { | |
| 149 switch (ElmtTy) { | |
| 150 case IceType_i8: | |
| 151 case IceType_f32: | |
| 152 return 0; | |
| 153 case IceType_i16: | |
| 154 return 1; | |
| 155 case IceType_i32: | |
| 156 return 2; | |
| 157 case IceType_i64: | |
| 158 return 3; | |
| 159 default: | |
| 160 llvm::report_fatal_error("SIMD op: Don't understand element type " + | |
| 161 typeIceString(ElmtTy)); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 IValueT encodeShift(OperandARM32::ShiftKind Shift) { | 147 IValueT encodeShift(OperandARM32::ShiftKind Shift) { |
| 166 // Follows encoding in ARM section A8.4.1 "Constant shifts". | 148 // Follows encoding in ARM section A8.4.1 "Constant shifts". |
| 167 switch (Shift) { | 149 switch (Shift) { |
| 168 case OperandARM32::kNoShift: | 150 case OperandARM32::kNoShift: |
| 169 case OperandARM32::LSL: | 151 case OperandARM32::LSL: |
| 170 return 0; // 0b00 | 152 return 0; // 0b00 |
| 171 case OperandARM32::LSR: | 153 case OperandARM32::LSR: |
| 172 return 1; // 0b01 | 154 return 1; // 0b01 |
| 173 case OperandARM32::ASR: | 155 case OperandARM32::ASR: |
| 174 return 2; // 0b10 | 156 return 2; // 0b10 |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC || | 594 const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC || |
| 613 kind() == llvm::ELF::R_ARM_MOVW_PREL_NC; | 595 kind() == llvm::ELF::R_ARM_MOVW_PREL_NC; |
| 614 Str << "\t" | 596 Str << "\t" |
| 615 "mov" << (IsMovw ? "w" : "t") << "\t" | 597 "mov" << (IsMovw ? "w" : "t") << "\t" |
| 616 << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF)) | 598 << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF)) |
| 617 << ", #:" << (IsMovw ? "lower" : "upper") << "16:" << symbol(Ctx, &Asm) | 599 << ", #:" << (IsMovw ? "lower" : "upper") << "16:" << symbol(Ctx, &Asm) |
| 618 << "\t@ .word " << llvm::format_hex_no_prefix(Inst, 8) << "\n"; | 600 << "\t@ .word " << llvm::format_hex_no_prefix(Inst, 8) << "\n"; |
| 619 return InstARM32::InstSize; | 601 return InstARM32::InstSize; |
| 620 } | 602 } |
| 621 | 603 |
| 604 IValueT AssemblerARM32::encodeElmtType(Type ElmtTy) { |
| 605 switch (ElmtTy) { |
| 606 case IceType_i8: |
| 607 return 0; |
| 608 case IceType_i16: |
| 609 return 1; |
| 610 case IceType_i32: |
| 611 case IceType_f32: |
| 612 return 2; |
| 613 case IceType_i64: |
| 614 return 3; |
| 615 default: |
| 616 llvm::report_fatal_error("SIMD op: Don't understand element type " + |
| 617 typeIceString(ElmtTy)); |
| 618 } |
| 619 } |
| 620 |
| 622 // This fixup points to an ARM32 instruction with the following format: | 621 // This fixup points to an ARM32 instruction with the following format: |
| 623 void MoveRelocatableFixup::emitOffset(Assembler *Asm) const { | 622 void MoveRelocatableFixup::emitOffset(Assembler *Asm) const { |
| 624 // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, | 623 // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, |
| 625 // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt. | 624 // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt. |
| 626 | 625 |
| 627 const IValueT Inst = Asm->load<IValueT>(position()); | 626 const IValueT Inst = Asm->load<IValueT>(position()); |
| 628 constexpr IValueT Imm16Mask = 0x000F0FFF; | 627 constexpr IValueT Imm16Mask = 0x000F0FFF; |
| 629 const IValueT Imm16 = offset() & 0xffff; | 628 const IValueT Imm16 = offset() & 0xffff; |
| 630 Asm->store(position(), | 629 Asm->store(position(), |
| 631 (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff)); | 630 (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff)); |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 IValueT Rot = encodeRotation(Rotation); | 1141 IValueT Rot = encodeRotation(Rotation); |
| 1143 if (!Utils::IsUint(2, Rot)) | 1142 if (!Utils::IsUint(2, Rot)) |
| 1144 llvm::report_fatal_error(std::string(InstName) + | 1143 llvm::report_fatal_error(std::string(InstName) + |
| 1145 ": Illegal rotation value"); | 1144 ": Illegal rotation value"); |
| 1146 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | | 1145 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | |
| 1147 (Rn << kRnShift) | (Rd << kRdShift) | | 1146 (Rn << kRnShift) | (Rd << kRdShift) | |
| 1148 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); | 1147 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); |
| 1149 emitInst(Encoding); | 1148 emitInst(Encoding); |
| 1150 } | 1149 } |
| 1151 | 1150 |
| 1151 void AssemblerARM32::emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn, |
| 1152 IValueT Dm, bool UseQRegs, bool IsFloatTy) { |
| 1153 const IValueT Encoding = |
| 1154 Opcode | B25 | (encodeCondition(CondARM32::kNone) << kConditionShift) | |
| 1155 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | |
| 1156 (getXXXXInRegYXXXX(Dd) << 12) | (IsFloatTy ? B10 : 0) | |
| 1157 (getYInRegYXXXX(Dn) << 7) | (encodeBool(UseQRegs) << 6) | |
| 1158 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); |
| 1159 emitInst(Encoding); |
| 1160 } |
| 1161 |
| 1152 void AssemblerARM32::emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, | 1162 void AssemblerARM32::emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, |
| 1153 IValueT Dn, IValueT Dm, bool UseQRegs) { | 1163 IValueT Dn, IValueT Dm, bool UseQRegs) { |
| 1154 IValueT Sz = encodeElmtType(ElmtTy); | 1164 constexpr IValueT ElmtShift = 20; |
| 1155 assert(Utils::IsUint(2, Sz)); | 1165 const IValueT ElmtSize = encodeElmtType(ElmtTy); |
| 1156 IValueT Encoding = | 1166 assert(Utils::IsUint(2, ElmtSize)); |
| 1157 Opcode | B25 | (encodeCondition(CondARM32::kNone) << kConditionShift) | | 1167 emitSIMDBase(Opcode | (ElmtSize << ElmtShift), Dd, Dn, Dm, UseQRegs, |
| 1158 (Sz << 20) | (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | | 1168 isFloatingType(ElmtTy)); |
| 1159 (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) | | 1169 } |
| 1160 (encodeBool(UseQRegs) << 6) | (getYInRegYXXXX(Dm) << 5) | | 1170 |
| 1161 getXXXXInRegYXXXX(Dm); | 1171 void AssemblerARM32::emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd, |
| 1162 emitInst(Encoding); | 1172 const Operand *OpQn, const Operand *OpQm, |
| 1173 bool IsFloatTy, const char *OpcodeName) { |
| 1174 const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); |
| 1175 const IValueT Qn = encodeQRegister(OpQn, "Qn", OpcodeName); |
| 1176 const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); |
| 1177 constexpr bool UseQRegs = true; |
| 1178 emitSIMDBase(Opcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), mapQRegToDReg(Qm), |
| 1179 UseQRegs, IsFloatTy); |
| 1163 } | 1180 } |
| 1164 | 1181 |
| 1165 void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy, | 1182 void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy, |
| 1166 const Operand *OpQd, const Operand *OpQn, | 1183 const Operand *OpQd, const Operand *OpQn, |
| 1167 const Operand *OpQm, const char *OpcodeName) { | 1184 const Operand *OpQm, const char *OpcodeName) { |
| 1168 IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); | 1185 constexpr IValueT ElmtShift = 20; |
| 1169 IValueT Qn = encodeQRegister(OpQn, "Qn", OpcodeName); | 1186 const IValueT ElmtSize = encodeElmtType(ElmtTy); |
| 1170 IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); | 1187 assert(Utils::IsUint(2, ElmtSize)); |
| 1171 constexpr bool UseQRegs = true; | 1188 emitSIMDqqqBase(Opcode | (ElmtSize << ElmtShift), OpQd, OpQn, OpQm, |
| 1172 emitSIMD(Opcode, ElmtTy, mapQRegToDReg(Qd), mapQRegToDReg(Qn), | 1189 isFloatingType(ElmtTy), OpcodeName); |
| 1173 mapQRegToDReg(Qm), UseQRegs); | |
| 1174 } | 1190 } |
| 1175 | 1191 |
| 1176 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, | 1192 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, |
| 1177 IValueT Dd, IValueT Dn, IValueT Dm) { | 1193 IValueT Dd, IValueT Dn, IValueT Dm) { |
| 1178 assert(Dd < RegARM32::getNumDRegs()); | 1194 assert(Dd < RegARM32::getNumDRegs()); |
| 1179 assert(Dn < RegARM32::getNumDRegs()); | 1195 assert(Dn < RegARM32::getNumDRegs()); |
| 1180 assert(Dm < RegARM32::getNumDRegs()); | 1196 assert(Dm < RegARM32::getNumDRegs()); |
| 1181 assert(CondARM32::isDefined(Cond)); | 1197 assert(CondARM32::isDefined(Cond)); |
| 1182 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8; | 1198 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8; |
| 1183 const IValueT Encoding = | 1199 const IValueT Encoding = |
| (...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2242 emitVFPsss(Cond, VabssOpcode, Sd, S0, Sm); | 2258 emitVFPsss(Cond, VabssOpcode, Sd, S0, Sm); |
| 2243 } | 2259 } |
| 2244 | 2260 |
| 2245 void AssemblerARM32::vabsd(const Operand *OpDd, const Operand *OpDm, | 2261 void AssemblerARM32::vabsd(const Operand *OpDd, const Operand *OpDm, |
| 2246 CondARM32::Cond Cond) { | 2262 CondARM32::Cond Cond) { |
| 2247 // VABS - ARM section A8.8.280, encoding A2: | 2263 // VABS - ARM section A8.8.280, encoding A2: |
| 2248 // vabs<c>.f64 <Dd>, <Dm> | 2264 // vabs<c>.f64 <Dd>, <Dm> |
| 2249 // | 2265 // |
| 2250 // cccc11101D110000dddd101111M0mmmm where cccc=Cond, Ddddd=Dd, and Mmmmm=Dm. | 2266 // cccc11101D110000dddd101111M0mmmm where cccc=Cond, Ddddd=Dd, and Mmmmm=Dm. |
| 2251 constexpr const char *Vabsd = "vabsd"; | 2267 constexpr const char *Vabsd = "vabsd"; |
| 2252 IValueT Dd = encodeDRegister(OpDd, "Dd", Vabsd); | 2268 const IValueT Dd = encodeDRegister(OpDd, "Dd", Vabsd); |
| 2253 IValueT Dm = encodeDRegister(OpDm, "Dm", Vabsd); | 2269 const IValueT Dm = encodeDRegister(OpDm, "Dm", Vabsd); |
| 2254 constexpr IValueT D0 = 0; | 2270 constexpr IValueT D0 = 0; |
| 2255 constexpr IValueT VabsdOpcode = B23 | B21 | B20 | B7 | B6; | 2271 constexpr IValueT VabsdOpcode = B23 | B21 | B20 | B7 | B6; |
| 2256 emitVFPddd(Cond, VabsdOpcode, Dd, D0, Dm); | 2272 emitVFPddd(Cond, VabsdOpcode, Dd, D0, Dm); |
| 2257 } | 2273 } |
| 2258 | 2274 |
| 2275 void AssemblerARM32::vabsq(const Operand *OpQd, const Operand *OpQm) { |
| 2276 // VABS - ARM section A8.8.280, encoding A1: |
| 2277 // vabs.<dt> <Qd>, <Qm> |
| 2278 // |
| 2279 // 111100111D11ss01ddd0f1101M0mmm0 where Dddd=OpQd, Mddd=OpQm, and |
| 2280 // <dt> in {s8, s16, s32, f32} and ss is the encoding of <dt>. |
| 2281 const Type ElmtTy = typeElementType(OpQd->getType()); |
| 2282 assert(ElmtTy != IceType_i64 && "vabsq doesn't allow i64!"); |
| 2283 constexpr const char *Vabsq = "vabsq"; |
| 2284 const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vabsq)); |
| 2285 const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vabsq)); |
| 2286 constexpr IValueT Dn = 0; |
| 2287 const IValueT VabsqOpcode = |
| 2288 B24 | B23 | B21 | B20 | B16 | B9 | B8 | (encodeElmtType(ElmtTy) << 18); |
| 2289 constexpr bool UseQRegs = true; |
| 2290 emitSIMDBase(VabsqOpcode, Dd, Dn, Dm, UseQRegs, isFloatingType(ElmtTy)); |
| 2291 } |
| 2292 |
| 2259 void AssemblerARM32::vadds(const Operand *OpSd, const Operand *OpSn, | 2293 void AssemblerARM32::vadds(const Operand *OpSd, const Operand *OpSn, |
| 2260 const Operand *OpSm, CondARM32::Cond Cond) { | 2294 const Operand *OpSm, CondARM32::Cond Cond) { |
| 2261 // VADD (floating-point) - ARM section A8.8.283, encoding A2: | 2295 // VADD (floating-point) - ARM section A8.8.283, encoding A2: |
| 2262 // vadd<c>.f32 <Sd>, <Sn>, <Sm> | 2296 // vadd<c>.f32 <Sd>, <Sn>, <Sm> |
| 2263 // | 2297 // |
| 2264 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, | 2298 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, |
| 2265 // and mmmmM=Rm. | 2299 // and mmmmM=Rm. |
| 2266 constexpr const char *Vadds = "vadds"; | 2300 constexpr const char *Vadds = "vadds"; |
| 2267 constexpr IValueT VaddsOpcode = B21 | B20; | 2301 constexpr IValueT VaddsOpcode = B21 | B20; |
| 2268 emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds); | 2302 emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds); |
| 2269 } | 2303 } |
| 2270 | 2304 |
| 2271 void AssemblerARM32::vaddqi(Type ElmtTy, const Operand *OpQd, | 2305 void AssemblerARM32::vaddqi(Type ElmtTy, const Operand *OpQd, |
| 2272 const Operand *OpQm, const Operand *OpQn) { | 2306 const Operand *OpQm, const Operand *OpQn) { |
| 2273 // VADD (integer) - ARM section A8.8.282, encoding A1: | 2307 // VADD (integer) - ARM section A8.8.282, encoding A1: |
| 2274 // vadd.<dt> <Qd>, <Qn>, <Qm> | 2308 // vadd.<dt> <Qd>, <Qn>, <Qm> |
| 2275 // | 2309 // |
| 2276 // 111100100Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, | 2310 // 111100100Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, |
| 2277 // and dt in [i8, i16, i32, i64] where ss is the index. | 2311 // and dt in [i8, i16, i32, i64] where ss is the index. |
| 2312 assert(isScalarIntegerType(ElmtTy) && |
| 2313 "vaddqi expects vector with integer element type"); |
| 2278 constexpr const char *Vaddqi = "vaddqi"; | 2314 constexpr const char *Vaddqi = "vaddqi"; |
| 2279 constexpr IValueT VaddqiOpcode = B11; | 2315 constexpr IValueT VaddqiOpcode = B11; |
| 2280 emitSIMDqqq(VaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vaddqi); | 2316 emitSIMDqqq(VaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vaddqi); |
| 2281 } | 2317 } |
| 2282 | 2318 |
| 2283 void AssemblerARM32::vaddqf(const Operand *OpQd, const Operand *OpQn, | 2319 void AssemblerARM32::vaddqf(const Operand *OpQd, const Operand *OpQn, |
| 2284 const Operand *OpQm) { | 2320 const Operand *OpQm) { |
| 2285 // VADD (floating-point) - ARM section A8.8.283, Encoding A1: | 2321 // VADD (floating-point) - ARM section A8.8.283, Encoding A1: |
| 2286 // vadd.f32 <Qd>, <Qn>, <Qm> | 2322 // vadd.f32 <Qd>, <Qn>, <Qm> |
| 2287 // | 2323 // |
| 2288 // 111100100D00nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. | 2324 // 111100100D00nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. |
| 2325 assert(OpQd->getType() == IceType_v4f32 && "vaddqf expects type <4 x float>"); |
| 2289 constexpr const char *Vaddqf = "vaddqf"; | 2326 constexpr const char *Vaddqf = "vaddqf"; |
| 2290 constexpr IValueT VaddqfOpcode = B11 | B10 | B8; | 2327 constexpr IValueT VaddqfOpcode = B11 | B8; |
| 2291 emitSIMDqqq(VaddqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vaddqf); | 2328 constexpr bool IsFloatTy = true; |
| 2329 emitSIMDqqqBase(VaddqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vaddqf); |
| 2292 } | 2330 } |
| 2293 | 2331 |
| 2294 void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, | 2332 void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, |
| 2295 const Operand *OpDm, CondARM32::Cond Cond) { | 2333 const Operand *OpDm, CondARM32::Cond Cond) { |
| 2296 // VADD (floating-point) - ARM section A8.8.283, encoding A2: | 2334 // VADD (floating-point) - ARM section A8.8.283, encoding A2: |
| 2297 // vadd<c>.f64 <Dd>, <Dn>, <Dm> | 2335 // vadd<c>.f64 <Dd>, <Dn>, <Dm> |
| 2298 // | 2336 // |
| 2299 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, | 2337 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, |
| 2300 // and Mmmmm=Rm. | 2338 // and Mmmmm=Rm. |
| 2301 constexpr const char *Vaddd = "vaddd"; | 2339 constexpr const char *Vaddd = "vaddd"; |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2553 B25 | B24 | B8 | B4 | | 2591 B25 | B24 | B8 | B4 | |
| 2554 (encodeCondition(CondARM32::Cond::kNone) << kConditionShift) | | 2592 (encodeCondition(CondARM32::Cond::kNone) << kConditionShift) | |
| 2555 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | | 2593 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | |
| 2556 (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) | | 2594 (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) | |
| 2557 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); | 2595 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); |
| 2558 emitInst(Encoding); | 2596 emitInst(Encoding); |
| 2559 } | 2597 } |
| 2560 | 2598 |
| 2561 void AssemblerARM32::veorq(const Operand *OpQd, const Operand *OpQn, | 2599 void AssemblerARM32::veorq(const Operand *OpQd, const Operand *OpQn, |
| 2562 const Operand *OpQm) { | 2600 const Operand *OpQm) { |
| 2601 // VEOR - ARM section A8.8.316, encoding A1: |
| 2602 // veor <Qd>, <Qn>, <Qm> |
| 2603 // |
| 2604 // 111100110D00nnn0ddd00001N1M1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. |
| 2563 constexpr const char *Veorq = "veorq"; | 2605 constexpr const char *Veorq = "veorq"; |
| 2564 constexpr IValueT VeorqOpcode = B24 | B8 | B4; | 2606 constexpr IValueT VeorqOpcode = B24 | B8 | B4; |
| 2565 emitSIMDqqq(VeorqOpcode, IceType_i8, OpQd, OpQn, OpQm, Veorq); | 2607 emitSIMDqqq(VeorqOpcode, IceType_i8, OpQd, OpQn, OpQm, Veorq); |
| 2566 } | 2608 } |
| 2567 | 2609 |
| 2568 void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress, | 2610 void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress, |
| 2569 CondARM32::Cond Cond, const TargetInfo &TInfo) { | 2611 CondARM32::Cond Cond, const TargetInfo &TInfo) { |
| 2570 // VLDR - ARM section A8.8.333, encoding A1. | 2612 // VLDR - ARM section A8.8.333, encoding A1. |
| 2571 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] | 2613 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] |
| 2572 // | 2614 // |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2930 emitVFPddd(Cond, VmuldOpcode, OpDd, OpDn, OpDm, Vmuld); | 2972 emitVFPddd(Cond, VmuldOpcode, OpDd, OpDn, OpDm, Vmuld); |
| 2931 } | 2973 } |
| 2932 | 2974 |
| 2933 void AssemblerARM32::vmulqi(Type ElmtTy, const Operand *OpQd, | 2975 void AssemblerARM32::vmulqi(Type ElmtTy, const Operand *OpQd, |
| 2934 const Operand *OpQn, const Operand *OpQm) { | 2976 const Operand *OpQn, const Operand *OpQm) { |
| 2935 // VMUL, VMULL (integer and polynomial) - ARM section A8.8.350, encoding A1: | 2977 // VMUL, VMULL (integer and polynomial) - ARM section A8.8.350, encoding A1: |
| 2936 // vmul<c>.<dt> <Qd>, <Qn>, <Qm> | 2978 // vmul<c>.<dt> <Qd>, <Qn>, <Qm> |
| 2937 // | 2979 // |
| 2938 // 111100100Dssnnn0ddd01001NqM1mmm0 where Dddd=Qd, Nnnn=Qn, Mmmm=Qm, and | 2980 // 111100100Dssnnn0ddd01001NqM1mmm0 where Dddd=Qd, Nnnn=Qn, Mmmm=Qm, and |
| 2939 // dt in [i8, i16, i32] where ss is the index. | 2981 // dt in [i8, i16, i32] where ss is the index. |
| 2982 assert(isScalarIntegerType(ElmtTy) && |
| 2983 "vmulqi expects vector with integer element type"); |
| 2940 assert(ElmtTy != IceType_i64 && "vmulqi on i64 vector not allowed"); | 2984 assert(ElmtTy != IceType_i64 && "vmulqi on i64 vector not allowed"); |
| 2941 constexpr const char *Vmulqi = "vmulqi"; | 2985 constexpr const char *Vmulqi = "vmulqi"; |
| 2942 constexpr IValueT VmulqiOpcode = B11 | B8 | B4; | 2986 constexpr IValueT VmulqiOpcode = B11 | B8 | B4; |
| 2943 emitSIMDqqq(VmulqiOpcode, ElmtTy, OpQd, OpQn, OpQm, Vmulqi); | 2987 emitSIMDqqq(VmulqiOpcode, ElmtTy, OpQd, OpQn, OpQm, Vmulqi); |
| 2944 } | 2988 } |
| 2945 | 2989 |
| 2946 void AssemblerARM32::vmulqf(const Operand *OpQd, const Operand *OpQn, | 2990 void AssemblerARM32::vmulqf(const Operand *OpQd, const Operand *OpQn, |
| 2947 const Operand *OpQm) { | 2991 const Operand *OpQm) { |
| 2948 // VMUL (floating-point) - ARM section A8.8.351, encoding A1: | 2992 // VMUL (floating-point) - ARM section A8.8.351, encoding A1: |
| 2949 // vmul.f32 <Qd>, <Qn>, <Qm> | 2993 // vmul.f32 <Qd>, <Qn>, <Qm> |
| 2950 // | 2994 // |
| 2951 // 111100110D00nnn0ddd01101MqM1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. | 2995 // 111100110D00nnn0ddd01101MqM1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. |
| 2996 assert(OpQd->getType() == IceType_v4f32 && "vmulqf expects type <4 x float>"); |
| 2952 constexpr const char *Vmulqf = "vmulqf"; | 2997 constexpr const char *Vmulqf = "vmulqf"; |
| 2953 constexpr IValueT VmulqfOpcode = B24 | B11 | B10 | B8 | B4; | 2998 constexpr IValueT VmulqfOpcode = B24 | B11 | B8 | B4; |
| 2954 emitSIMDqqq(VmulqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vmulqf); | 2999 constexpr bool IsFloatTy = true; |
| 3000 emitSIMDqqqBase(VmulqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vmulqf); |
| 2955 } | 3001 } |
| 2956 | 3002 |
| 2957 void AssemblerARM32::vorrq(const Operand *OpQd, const Operand *OpQm, | 3003 void AssemblerARM32::vorrq(const Operand *OpQd, const Operand *OpQm, |
| 2958 const Operand *OpQn) { | 3004 const Operand *OpQn) { |
| 2959 // VORR (register) - ARM section A8.8.360, encoding A1: | 3005 // VORR (register) - ARM section A8.8.360, encoding A1: |
| 2960 // vorr <Qd>, <Qn>, <Qm> | 3006 // vorr <Qd>, <Qn>, <Qm> |
| 2961 // | 3007 // |
| 2962 // 111100100D10nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. | 3008 // 111100100D10nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. |
| 2963 constexpr const char *Vorrq = "vorrq"; | 3009 constexpr const char *Vorrq = "vorrq"; |
| 2964 constexpr IValueT VorrqOpcode = B21 | B8 | B4; | 3010 constexpr IValueT VorrqOpcode = B21 | B8 | B4; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3055 emitVFPddd(Cond, VsubdOpcode, OpDd, OpDn, OpDm, Vsubd); | 3101 emitVFPddd(Cond, VsubdOpcode, OpDd, OpDn, OpDm, Vsubd); |
| 3056 } | 3102 } |
| 3057 | 3103 |
| 3058 void AssemblerARM32::vsubqi(Type ElmtTy, const Operand *OpQd, | 3104 void AssemblerARM32::vsubqi(Type ElmtTy, const Operand *OpQd, |
| 3059 const Operand *OpQm, const Operand *OpQn) { | 3105 const Operand *OpQm, const Operand *OpQn) { |
| 3060 // VSUB (integer) - ARM section A8.8.414, encoding A1: | 3106 // VSUB (integer) - ARM section A8.8.414, encoding A1: |
| 3061 // vsub.<dt> <Qd>, <Qn>, <Qm> | 3107 // vsub.<dt> <Qd>, <Qn>, <Qm> |
| 3062 // | 3108 // |
| 3063 // 111100110Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, | 3109 // 111100110Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, |
| 3064 // and dt in [i8, i16, i32, i64] where ss is the index. | 3110 // and dt in [i8, i16, i32, i64] where ss is the index. |
| 3111 assert(isScalarIntegerType(ElmtTy) && |
| 3112 "vsubqi expects vector with integer element type"); |
| 3065 constexpr const char *Vsubqi = "vsubqi"; | 3113 constexpr const char *Vsubqi = "vsubqi"; |
| 3066 constexpr IValueT VsubqiOpcode = B24 | B11; | 3114 constexpr IValueT VsubqiOpcode = B24 | B11; |
| 3067 emitSIMDqqq(VsubqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vsubqi); | 3115 emitSIMDqqq(VsubqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vsubqi); |
| 3068 } | 3116 } |
| 3069 | 3117 |
| 3070 void AssemblerARM32::vsubqf(const Operand *OpQd, const Operand *OpQn, | 3118 void AssemblerARM32::vsubqf(const Operand *OpQd, const Operand *OpQn, |
| 3071 const Operand *OpQm) { | 3119 const Operand *OpQm) { |
| 3072 // VSUB (floating-point) - ARM section A8.8.415, Encoding A1: | 3120 // VSUB (floating-point) - ARM section A8.8.415, Encoding A1: |
| 3073 // vsub.f32 <Qd>, <Qn>, <Qm> | 3121 // vsub.f32 <Qd>, <Qn>, <Qm> |
| 3074 // | 3122 // |
| 3075 // 111100100D10nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. | 3123 // 111100100D10nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. |
| 3124 assert(OpQd->getType() == IceType_v4f32 && "vsubqf expects type <4 x float>"); |
| 3076 constexpr const char *Vsubqf = "vsubqf"; | 3125 constexpr const char *Vsubqf = "vsubqf"; |
| 3077 constexpr IValueT VsubqfOpcode = B21 | B11 | B10 | B8; | 3126 constexpr IValueT VsubqfOpcode = B21 | B11 | B8; |
| 3078 emitSIMDqqq(VsubqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vsubqf); | 3127 emitSIMDqqq(VsubqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vsubqf); |
| 3079 } | 3128 } |
| 3080 | 3129 |
| 3081 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, | 3130 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, |
| 3082 const Variable *OpBaseReg, | 3131 const Variable *OpBaseReg, |
| 3083 SizeT NumConsecRegs) { | 3132 SizeT NumConsecRegs) { |
| 3084 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); | 3133 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); |
| 3085 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. | 3134 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. |
| 3086 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. | 3135 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. |
| 3087 assert(0 < NumConsecRegs); | 3136 assert(0 < NumConsecRegs); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3147 constexpr const char *Vsqrts = "vsqrts"; | 3196 constexpr const char *Vsqrts = "vsqrts"; |
| 3148 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); | 3197 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); |
| 3149 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); | 3198 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); |
| 3150 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; | 3199 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; |
| 3151 constexpr IValueT S0 = 0; | 3200 constexpr IValueT S0 = 0; |
| 3152 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); | 3201 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); |
| 3153 } | 3202 } |
| 3154 | 3203 |
| 3155 } // end of namespace ARM32 | 3204 } // end of namespace ARM32 |
| 3156 } // end of namespace Ice | 3205 } // end of namespace Ice |
| OLD | NEW |