Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Side by Side Diff: src/IceAssemblerARM32.cpp

Issue 1652173002: Implements the vector add instructions in the integrated ARM assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix nits. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698