| 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( |
| 161 std::string("SIMD op: Don't understand element type ") + |
| 162 typeString(ElmtTy)); |
| 163 } |
| 164 } |
| 165 |
| 147 IValueT encodeShift(OperandARM32::ShiftKind Shift) { | 166 IValueT encodeShift(OperandARM32::ShiftKind Shift) { |
| 148 // Follows encoding in ARM section A8.4.1 "Constant shifts". | 167 // Follows encoding in ARM section A8.4.1 "Constant shifts". |
| 149 switch (Shift) { | 168 switch (Shift) { |
| 150 case OperandARM32::kNoShift: | 169 case OperandARM32::kNoShift: |
| 151 case OperandARM32::LSL: | 170 case OperandARM32::LSL: |
| 152 return 0; // 0b00 | 171 return 0; // 0b00 |
| 153 case OperandARM32::LSR: | 172 case OperandARM32::LSR: |
| 154 return 1; // 0b01 | 173 return 1; // 0b01 |
| 155 case OperandARM32::ASR: | 174 case OperandARM32::ASR: |
| 156 return 2; // 0b10 | 175 return 2; // 0b10 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 184 | 203 |
| 185 IValueT getEncodedSRegNum(const Variable *Var) { | 204 IValueT getEncodedSRegNum(const Variable *Var) { |
| 186 assert(Var->hasReg()); | 205 assert(Var->hasReg()); |
| 187 return RegARM32::getEncodedSReg(Var->getRegNum()); | 206 return RegARM32::getEncodedSReg(Var->getRegNum()); |
| 188 } | 207 } |
| 189 | 208 |
| 190 IValueT getEncodedDRegNum(const Variable *Var) { | 209 IValueT getEncodedDRegNum(const Variable *Var) { |
| 191 return RegARM32::getEncodedDReg(Var->getRegNum()); | 210 return RegARM32::getEncodedDReg(Var->getRegNum()); |
| 192 } | 211 } |
| 193 | 212 |
| 213 IValueT getEncodedQRegNum(const Variable *Var) { |
| 214 return RegARM32::getEncodedQReg(Var->getRegNum()); |
| 215 } |
| 216 |
| 217 IValueT mapQRegToDReg(IValueT EncodedQReg) { return EncodedQReg << 1; } |
| 218 |
| 194 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } | 219 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } |
| 195 | 220 |
| 196 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } | 221 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } |
| 197 | 222 |
| 198 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } | 223 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } |
| 199 | 224 |
| 200 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } | 225 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } |
| 201 | 226 |
| 202 // Defines layouts of an operand representing a (register) memory address, | 227 // Defines layouts of an operand representing a (register) memory address, |
| 203 // possibly modified by an immediate value. | 228 // possibly modified by an immediate value. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 | 323 |
| 299 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and | 324 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and |
| 300 // tt=Shift. | 325 // tt=Shift. |
| 301 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, | 326 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, |
| 302 IValueT Rs) { | 327 IValueT Rs) { |
| 303 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | | 328 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | |
| 304 (Rm << kRmShift); | 329 (Rm << kRmShift); |
| 305 } | 330 } |
| 306 | 331 |
| 307 // Defines the set of registers expected in an operand. | 332 // Defines the set of registers expected in an operand. |
| 308 enum RegSetWanted { WantGPRegs, WantSRegs, WantDRegs }; | 333 enum RegSetWanted { WantGPRegs, WantSRegs, WantDRegs, WantQRegs }; |
| 309 | 334 |
| 310 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value, | 335 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value, |
| 311 RegSetWanted WantedRegSet) { | 336 RegSetWanted WantedRegSet) { |
| 312 Value = 0; // Make sure initialized. | 337 Value = 0; // Make sure initialized. |
| 313 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | 338 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { |
| 314 if (Var->hasReg()) { | 339 if (Var->hasReg()) { |
| 315 switch (WantedRegSet) { | 340 switch (WantedRegSet) { |
| 316 case WantGPRegs: | 341 case WantGPRegs: |
| 317 Value = getEncodedGPRegNum(Var); | 342 Value = getEncodedGPRegNum(Var); |
| 318 break; | 343 break; |
| 319 case WantSRegs: | 344 case WantSRegs: |
| 320 Value = getEncodedSRegNum(Var); | 345 Value = getEncodedSRegNum(Var); |
| 321 break; | 346 break; |
| 322 case WantDRegs: | 347 case WantDRegs: |
| 323 Value = getEncodedDRegNum(Var); | 348 Value = getEncodedDRegNum(Var); |
| 324 break; | 349 break; |
| 350 case WantQRegs: |
| 351 Value = getEncodedQRegNum(Var); |
| 352 break; |
| 325 } | 353 } |
| 326 return EncodedAsRegister; | 354 return EncodedAsRegister; |
| 327 } | 355 } |
| 328 return CantEncode; | 356 return CantEncode; |
| 329 } | 357 } |
| 330 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { | 358 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { |
| 331 const IValueT Immed8 = FlexImm->getImm(); | 359 const IValueT Immed8 = FlexImm->getImm(); |
| 332 const IValueT Rotate = FlexImm->getRotateAmt(); | 360 const IValueT Rotate = FlexImm->getRotateAmt(); |
| 333 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) | 361 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) |
| 334 return CantEncode; | 362 return CantEncode; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 IValueT encodeSRegister(const Operand *OpReg, const char *RegName, | 524 IValueT encodeSRegister(const Operand *OpReg, const char *RegName, |
| 497 const char *InstName) { | 525 const char *InstName) { |
| 498 return encodeRegister(OpReg, WantSRegs, RegName, InstName); | 526 return encodeRegister(OpReg, WantSRegs, RegName, InstName); |
| 499 } | 527 } |
| 500 | 528 |
| 501 IValueT encodeDRegister(const Operand *OpReg, const char *RegName, | 529 IValueT encodeDRegister(const Operand *OpReg, const char *RegName, |
| 502 const char *InstName) { | 530 const char *InstName) { |
| 503 return encodeRegister(OpReg, WantDRegs, RegName, InstName); | 531 return encodeRegister(OpReg, WantDRegs, RegName, InstName); |
| 504 } | 532 } |
| 505 | 533 |
| 534 IValueT encodeQRegister(const Operand *OpReg, const char *RegName, |
| 535 const char *InstName) { |
| 536 return encodeRegister(OpReg, WantQRegs, RegName, InstName); |
| 537 } |
| 538 |
| 506 void verifyPOrNotW(IValueT Address, const char *InstName) { | 539 void verifyPOrNotW(IValueT Address, const char *InstName) { |
| 507 if (BuildDefs::minimal()) | 540 if (BuildDefs::minimal()) |
| 508 return; | 541 return; |
| 509 if (!isBitSet(P, Address) && isBitSet(W, Address)) | 542 if (!isBitSet(P, Address) && isBitSet(W, Address)) |
| 510 llvm::report_fatal_error(std::string(InstName) + | 543 llvm::report_fatal_error(std::string(InstName) + |
| 511 ": P=0 when W=1 not allowed"); | 544 ": P=0 when W=1 not allowed"); |
| 512 } | 545 } |
| 513 | 546 |
| 514 void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2, | 547 void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2, |
| 515 const char *Reg2Name, const char *InstName) { | 548 const char *Reg2Name, const char *InstName) { |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 IValueT Rot = encodeRotation(Rotation); | 1056 IValueT Rot = encodeRotation(Rotation); |
| 1024 if (!Utils::IsUint(2, Rot)) | 1057 if (!Utils::IsUint(2, Rot)) |
| 1025 llvm::report_fatal_error(std::string(InstName) + | 1058 llvm::report_fatal_error(std::string(InstName) + |
| 1026 ": Illegal rotation value"); | 1059 ": Illegal rotation value"); |
| 1027 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | | 1060 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | |
| 1028 (Rn << kRnShift) | (Rd << kRdShift) | | 1061 (Rn << kRnShift) | (Rd << kRdShift) | |
| 1029 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); | 1062 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); |
| 1030 emitInst(Encoding); | 1063 emitInst(Encoding); |
| 1031 } | 1064 } |
| 1032 | 1065 |
| 1066 void AssemblerARM32::emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, |
| 1067 IValueT Dn, IValueT Dm, bool UseQRegs) { |
| 1068 IValueT Sz = encodeElmtType(ElmtTy); |
| 1069 assert(Utils::IsUint(2, Sz)); |
| 1070 IValueT Encoding = |
| 1071 Opcode | B25 | (encodeCondition(CondARM32::kNone) << kConditionShift) | |
| 1072 (Sz << 20) | (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | |
| 1073 (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) | |
| 1074 (encodeBool(UseQRegs) << 6) | (getYInRegYXXXX(Dm) << 5) | |
| 1075 getXXXXInRegYXXXX(Dm); |
| 1076 emitInst(Encoding); |
| 1077 } |
| 1078 |
| 1079 void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy, |
| 1080 const Operand *OpQd, const Operand *OpQn, |
| 1081 const Operand *OpQm, const char *OpcodeName) { |
| 1082 IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); |
| 1083 IValueT Qn = encodeQRegister(OpQn, "Qn", OpcodeName); |
| 1084 IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); |
| 1085 constexpr bool UseQRegs = true; |
| 1086 emitSIMD(Opcode, ElmtTy, mapQRegToDReg(Qd), mapQRegToDReg(Qn), |
| 1087 mapQRegToDReg(Qm), UseQRegs); |
| 1088 } |
| 1089 |
| 1033 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, | 1090 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, |
| 1034 IValueT Dd, IValueT Dn, IValueT Dm) { | 1091 IValueT Dd, IValueT Dn, IValueT Dm) { |
| 1035 assert(Dd < RegARM32::getNumDRegs()); | 1092 assert(Dd < RegARM32::getNumDRegs()); |
| 1036 assert(Dn < RegARM32::getNumDRegs()); | 1093 assert(Dn < RegARM32::getNumDRegs()); |
| 1037 assert(Dm < RegARM32::getNumDRegs()); | 1094 assert(Dm < RegARM32::getNumDRegs()); |
| 1038 assert(CondARM32::isDefined(Cond)); | 1095 assert(CondARM32::isDefined(Cond)); |
| 1039 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8; | 1096 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8; |
| 1040 const IValueT Encoding = | 1097 const IValueT Encoding = |
| 1041 Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | | 1098 Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | |
| 1042 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | | 1099 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | |
| (...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2090 // VADD (floating-point) - ARM section A8.8.283, encoding A2: | 2147 // VADD (floating-point) - ARM section A8.8.283, encoding A2: |
| 2091 // vadd<c>.f32 <Sd>, <Sn>, <Sm> | 2148 // vadd<c>.f32 <Sd>, <Sn>, <Sm> |
| 2092 // | 2149 // |
| 2093 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, | 2150 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, |
| 2094 // and mmmmM=Rm. | 2151 // and mmmmM=Rm. |
| 2095 constexpr const char *Vadds = "vadds"; | 2152 constexpr const char *Vadds = "vadds"; |
| 2096 constexpr IValueT VaddsOpcode = B21 | B20; | 2153 constexpr IValueT VaddsOpcode = B21 | B20; |
| 2097 emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds); | 2154 emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds); |
| 2098 } | 2155 } |
| 2099 | 2156 |
| 2157 void AssemblerARM32::vaddqi(Type ElmtTy, const Operand *OpQd, |
| 2158 const Operand *OpQm, const Operand *OpQn) { |
| 2159 // VADD (integer) - ARM section A8.8.282, encoding A1: |
| 2160 // vadd.<dt> <Qd>, <Qn>, <Qm> |
| 2161 // |
| 2162 // 111100100Dssnnn0ddd01000NqM0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, |
| 2163 // and dt in [i8, i16, i32, i64] where ss is the index. |
| 2164 constexpr const char *Vaddqi = "vaddqi"; |
| 2165 constexpr IValueT VaddqiOpcode = B11; |
| 2166 emitSIMDqqq(VaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vaddqi); |
| 2167 } |
| 2168 |
| 2169 void AssemblerARM32::vaddqf(const Operand *OpQd, const Operand *OpQn, |
| 2170 const Operand *OpQm) { |
| 2171 // VADD (floating-point) - ARM section A8.8.283, Encoding A1: |
| 2172 // vadd.f32 <Qd>, <Qn>, <Qm> |
| 2173 // |
| 2174 // 111100100D00nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. |
| 2175 constexpr const char *Vaddqf = "vaddqf"; |
| 2176 constexpr IValueT VaddqfOpcode = B11 | B10 | B8; |
| 2177 emitSIMDqqq(VaddqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vaddqf); |
| 2178 } |
| 2179 |
| 2100 void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, | 2180 void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, |
| 2101 const Operand *OpDm, CondARM32::Cond Cond) { | 2181 const Operand *OpDm, CondARM32::Cond Cond) { |
| 2102 // VADD (floating-point) - ARM section A8.8.283, encoding A2: | 2182 // VADD (floating-point) - ARM section A8.8.283, encoding A2: |
| 2103 // vadd<c>.f64 <Dd>, <Dn>, <Dm> | 2183 // vadd<c>.f64 <Dd>, <Dn>, <Dm> |
| 2104 // | 2184 // |
| 2105 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, | 2185 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, |
| 2106 // and Mmmmm=Rm. | 2186 // and Mmmmm=Rm. |
| 2107 constexpr const char *Vaddd = "vaddd"; | 2187 constexpr const char *Vaddd = "vaddd"; |
| 2108 constexpr IValueT VadddOpcode = B21 | B20; | 2188 constexpr IValueT VadddOpcode = B21 | B20; |
| 2109 emitVFPddd(Cond, VadddOpcode, OpDd, OpDn, OpDm, Vaddd); | 2189 emitVFPddd(Cond, VadddOpcode, OpDd, OpDn, OpDm, Vaddd); |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2767 constexpr const char *Vsqrts = "vsqrts"; | 2847 constexpr const char *Vsqrts = "vsqrts"; |
| 2768 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); | 2848 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); |
| 2769 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); | 2849 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); |
| 2770 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; | 2850 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; |
| 2771 constexpr IValueT S0 = 0; | 2851 constexpr IValueT S0 = 0; |
| 2772 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); | 2852 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); |
| 2773 } | 2853 } |
| 2774 | 2854 |
| 2775 } // end of namespace ARM32 | 2855 } // end of namespace ARM32 |
| 2776 } // end of namespace Ice | 2856 } // end of namespace Ice |
| OLD | NEW |