Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// | 1 //===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 assert(Inst->getSrcSize() == 2); | 178 assert(Inst->getSrcSize() == 2); |
| 179 Str << "\t" << Opcode << getVecWidthString(Inst->getDest()->getType()) | 179 Str << "\t" << Opcode << getVecWidthString(Inst->getDest()->getType()) |
| 180 << "\t"; | 180 << "\t"; |
| 181 Inst->getDest()->emit(Func); | 181 Inst->getDest()->emit(Func); |
| 182 Str << ", "; | 182 Str << ", "; |
| 183 Inst->getSrc(0)->emit(Func); | 183 Inst->getSrc(0)->emit(Func); |
| 184 Str << ", "; | 184 Str << ", "; |
| 185 Inst->getSrc(1)->emit(Func); | 185 Inst->getSrc(1)->emit(Func); |
| 186 } | 186 } |
| 187 | 187 |
| 188 void InstARM32::emitFourAddrFP(const char *Opcode, const InstARM32 *Inst, | |
| 189 const Cfg *Func) { | |
| 190 if (!BuildDefs::dump()) | |
| 191 return; | |
| 192 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 193 assert(Inst->getSrcSize() == 3); | |
| 194 assert(Inst->getSrc(0) == Inst->getDest()); | |
| 195 Str << "\t" << Opcode << getVecWidthString(Inst->getDest()->getType()) | |
| 196 << "\t"; | |
| 197 Inst->getDest()->emit(Func); | |
| 198 Str << ", "; | |
| 199 Inst->getSrc(1)->emit(Func); | |
| 200 Str << ", "; | |
| 201 Inst->getSrc(2)->emit(Func); | |
| 202 } | |
| 203 | |
| 188 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Inst, | 204 void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 189 const Cfg *Func) { | 205 const Cfg *Func) { |
| 190 if (!BuildDefs::dump()) | 206 if (!BuildDefs::dump()) |
| 191 return; | 207 return; |
| 192 Ostream &Str = Func->getContext()->getStrEmit(); | 208 Ostream &Str = Func->getContext()->getStrEmit(); |
| 193 assert(Inst->getSrcSize() == 3); | 209 assert(Inst->getSrcSize() == 3); |
| 194 Str << "\t" << Opcode << Inst->getPredicate() << "\t"; | 210 Str << "\t" << Opcode << Inst->getPredicate() << "\t"; |
| 195 Inst->getDest()->emit(Func); | 211 Inst->getDest()->emit(Func); |
| 196 Str << ", "; | 212 Str << ", "; |
| 197 Inst->getSrc(0)->emit(Func); | 213 Inst->getSrc(0)->emit(Func); |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 } | 573 } |
| 558 | 574 |
| 559 InstARM32Label::InstARM32Label(Cfg *Func, TargetARM32 *Target) | 575 InstARM32Label::InstARM32Label(Cfg *Func, TargetARM32 *Target) |
| 560 : InstARM32(Func, InstARM32::Label, 0, nullptr), | 576 : InstARM32(Func, InstARM32::Label, 0, nullptr), |
| 561 Number(Target->makeNextLabelNumber()) {} | 577 Number(Target->makeNextLabelNumber()) {} |
| 562 | 578 |
| 563 IceString InstARM32Label::getName(const Cfg *Func) const { | 579 IceString InstARM32Label::getName(const Cfg *Func) const { |
| 564 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); | 580 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); |
| 565 } | 581 } |
| 566 | 582 |
| 583 namespace { | |
| 584 // | |
|
Jim Stichnoth
2015/12/08 19:20:16
Fill in the comment, or delete this line.
John
2015/12/09 13:11:08
Done.
| |
| 585 void ValidatePushOrPopRegisterListOrDie(const VarList &RegList) { | |
|
Jim Stichnoth
2015/12/08 19:20:16
lowerCase function name
John
2015/12/09 13:11:08
Done.
| |
| 586 Type PreviousTy = IceType_void; | |
| 587 for (Variable *Reg : RegList) { | |
| 588 if (PreviousTy != IceType_void && Reg->getType() != PreviousTy) { | |
| 589 llvm::report_fatal_error("Type mismatch when popping/pushing " | |
| 590 "registers."); | |
| 591 } | |
| 592 | |
| 593 if (!Reg->hasReg()) { | |
| 594 llvm::report_fatal_error("Push/pop operand does not have a register " | |
| 595 "assigned to it."); | |
| 596 } | |
| 597 | |
| 598 PreviousTy = Reg->getType(); | |
| 599 } | |
| 600 } | |
| 601 } // end of anonymous namespace | |
| 602 | |
| 567 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests) | 603 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests) |
| 568 : InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) { | 604 : InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) { |
| 569 // Track modifications to Dests separately via FakeDefs. Also, a pop | 605 // Track modifications to Dests separately via FakeDefs. Also, a pop |
| 570 // instruction affects the stack pointer and so it should not be allowed to | 606 // instruction affects the stack pointer and so it should not be allowed to |
| 571 // be automatically dead-code eliminated. This is automatic since we leave | 607 // be automatically dead-code eliminated. This is automatic since we leave |
| 572 // the Dest as nullptr. | 608 // the Dest as nullptr. |
| 609 ValidatePushOrPopRegisterListOrDie(Dests); | |
| 573 } | 610 } |
| 574 | 611 |
| 575 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs) | 612 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs) |
| 576 : InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) { | 613 : InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) { |
| 577 for (Variable *Source : Srcs) | 614 ValidatePushOrPopRegisterListOrDie(Srcs); |
| 615 for (Variable *Source : Srcs) { | |
| 578 addSource(Source); | 616 addSource(Source); |
| 617 } | |
| 579 } | 618 } |
| 580 | 619 |
| 581 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) | 620 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) |
| 582 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { | 621 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { |
| 583 addSource(LR); | 622 addSource(LR); |
| 584 if (Source) | 623 if (Source) |
| 585 addSource(Source); | 624 addSource(Source); |
| 586 } | 625 } |
| 587 | 626 |
| 588 InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, | 627 InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 714 template <> const char *InstARM32Orr::Opcode = "orr"; | 753 template <> const char *InstARM32Orr::Opcode = "orr"; |
| 715 template <> const char *InstARM32Rsb::Opcode = "rsb"; | 754 template <> const char *InstARM32Rsb::Opcode = "rsb"; |
| 716 template <> const char *InstARM32Rsc::Opcode = "rsc"; | 755 template <> const char *InstARM32Rsc::Opcode = "rsc"; |
| 717 template <> const char *InstARM32Sbc::Opcode = "sbc"; | 756 template <> const char *InstARM32Sbc::Opcode = "sbc"; |
| 718 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; | 757 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; |
| 719 template <> const char *InstARM32Sub::Opcode = "sub"; | 758 template <> const char *InstARM32Sub::Opcode = "sub"; |
| 720 template <> const char *InstARM32Udiv::Opcode = "udiv"; | 759 template <> const char *InstARM32Udiv::Opcode = "udiv"; |
| 721 // FP | 760 // FP |
| 722 template <> const char *InstARM32Vadd::Opcode = "vadd"; | 761 template <> const char *InstARM32Vadd::Opcode = "vadd"; |
| 723 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; | 762 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; |
| 763 template <> const char *InstARM32Veor::Opcode = "veor"; | |
| 764 template <> const char *InstARM32Vmla::Opcode = "vmla"; | |
| 765 template <> const char *InstARM32Vmls::Opcode = "vmls"; | |
| 724 template <> const char *InstARM32Vmul::Opcode = "vmul"; | 766 template <> const char *InstARM32Vmul::Opcode = "vmul"; |
| 725 template <> const char *InstARM32Veor::Opcode = "veor"; | |
| 726 template <> const char *InstARM32Vsub::Opcode = "vsub"; | 767 template <> const char *InstARM32Vsub::Opcode = "vsub"; |
| 727 // Four-addr ops | 768 // Four-addr ops |
| 728 template <> const char *InstARM32Mla::Opcode = "mla"; | 769 template <> const char *InstARM32Mla::Opcode = "mla"; |
| 729 template <> const char *InstARM32Mls::Opcode = "mls"; | 770 template <> const char *InstARM32Mls::Opcode = "mls"; |
| 730 // Cmp-like ops | 771 // Cmp-like ops |
| 731 template <> const char *InstARM32Cmn::Opcode = "cmn"; | 772 template <> const char *InstARM32Cmn::Opcode = "cmn"; |
| 732 template <> const char *InstARM32Cmp::Opcode = "cmp"; | 773 template <> const char *InstARM32Cmp::Opcode = "cmp"; |
| 733 template <> const char *InstARM32Tst::Opcode = "tst"; | 774 template <> const char *InstARM32Tst::Opcode = "tst"; |
| 734 | 775 |
| 735 void InstARM32::dump(const Cfg *Func) const { | 776 void InstARM32::dump(const Cfg *Func) const { |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1186 } | 1227 } |
| 1187 | 1228 |
| 1188 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const { | 1229 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const { |
| 1189 assert(getSrcSize() == 1); | 1230 assert(getSrcSize() == 1); |
| 1190 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 1231 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 1191 Asm->uxt(getDest(), getSrc(0), getPredicate()); | 1232 Asm->uxt(getDest(), getSrc(0), getPredicate()); |
| 1192 if (Asm->needsTextFixup()) | 1233 if (Asm->needsTextFixup()) |
| 1193 emitUsingTextFixup(Func); | 1234 emitUsingTextFixup(Func); |
| 1194 } | 1235 } |
| 1195 | 1236 |
| 1237 namespace { | |
| 1238 | |
| 1239 bool isAssignedConsecutiveRegisters(Variable *Before, Variable *After) { | |
| 1240 assert(Before->hasReg()); | |
| 1241 assert(After->hasReg()); | |
| 1242 return Before->getRegNum() + 1 == After->getRegNum(); | |
| 1243 } | |
| 1244 | |
| 1245 } // end of anonymous namespace | |
| 1246 | |
| 1196 void InstARM32Pop::emit(const Cfg *Func) const { | 1247 void InstARM32Pop::emit(const Cfg *Func) const { |
| 1197 // TODO(jpp): Improve FP register save/restore. | 1248 // TODO(jpp): Improve FP register save/restore. |
| 1198 if (!BuildDefs::dump()) | 1249 if (!BuildDefs::dump()) |
| 1199 return; | 1250 return; |
| 1200 SizeT IntegerCount = 0; | 1251 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1201 for (const Operand *Op : Dests) { | 1252 const SizeT DestSize = Dests.size(); |
| 1202 if (isScalarIntegerType(Op->getType())) { | 1253 assert(DestSize > 0); |
| 1203 ++IntegerCount; | 1254 if (DestSize == 0) { |
| 1204 } | 1255 return; |
| 1205 } | 1256 } |
| 1206 Ostream &Str = Func->getContext()->getStrEmit(); | 1257 |
| 1207 bool NeedNewline = false; | 1258 Variable *Reg = Dests[0]; |
| 1208 if (IntegerCount != 0) { | 1259 if (isScalarIntegerType(Reg->getType())) { |
| 1260 // GPR push. | |
| 1209 Str << "\t" | 1261 Str << "\t" |
| 1210 << "pop" | 1262 "pop" |
| 1211 << "\t{"; | 1263 "\t{"; |
| 1212 bool PrintComma = false; | 1264 Reg->emit(Func); |
| 1213 for (const Operand *Op : Dests) { | 1265 for (SizeT i = 1; i < DestSize; ++i) { |
| 1214 if (isScalarIntegerType(Op->getType())) { | 1266 Str << ", "; |
| 1215 if (PrintComma) | 1267 Reg = Dests[i]; |
| 1216 Str << ", "; | 1268 Reg->emit(Func); |
| 1217 Op->emit(Func); | |
| 1218 PrintComma = true; | |
| 1219 } | |
| 1220 } | 1269 } |
| 1221 Str << "}"; | 1270 Str << "}"; |
| 1222 NeedNewline = true; | 1271 return; |
| 1223 } | 1272 } |
| 1224 | 1273 |
| 1225 for (const Operand *Op : Dests) { | 1274 // VFP "s" reg push. |
| 1226 if (isScalarIntegerType(Op->getType())) | 1275 SizeT End = DestSize - 1; |
| 1227 continue; | 1276 SizeT Start = DestSize - 1; |
| 1228 if (NeedNewline) { | 1277 Reg = Dests[DestSize - 1]; |
| 1229 Str << "\n"; | 1278 Str << "\t" |
| 1279 "vpop" | |
| 1280 "\t{"; | |
| 1281 for (SizeT i = 2; i <= DestSize; ++i) { | |
| 1282 Variable *PreviousReg = Dests[DestSize - i]; | |
| 1283 if (!isAssignedConsecutiveRegisters(PreviousReg, Reg)) { | |
| 1284 Dests[Start]->emit(Func); | |
| 1285 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1286 Str << ", "; | |
| 1287 Dests[j]->emit(Func); | |
| 1288 } | |
| 1230 startNextInst(Func); | 1289 startNextInst(Func); |
| 1231 NeedNewline = false; | 1290 Str << "}\n\t" |
| 1291 "vpop" | |
| 1292 "\t{"; | |
| 1293 End = DestSize - i; | |
| 1232 } | 1294 } |
| 1233 Str << "\t" | 1295 Reg = PreviousReg; |
| 1234 << "vpop" | 1296 Start = DestSize - i; |
| 1235 << "\t{"; | |
| 1236 Op->emit(Func); | |
| 1237 Str << "}"; | |
| 1238 NeedNewline = true; | |
| 1239 } | 1297 } |
| 1240 assert(NeedNewline); // caller will add the newline | 1298 Dests[Start]->emit(Func); |
| 1299 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1300 Str << ", "; | |
| 1301 Dests[j]->emit(Func); | |
| 1302 } | |
| 1303 Str << "}"; | |
| 1241 } | 1304 } |
| 1242 | 1305 |
| 1243 void InstARM32Pop::emitIAS(const Cfg *Func) const { | 1306 void InstARM32Pop::emitIAS(const Cfg *Func) const { |
| 1244 SizeT IntegerCount = 0; | 1307 SizeT IntegerCount = 0; |
| 1245 ARM32::IValueT GPRegisters = 0; | 1308 ARM32::IValueT GPRegisters = 0; |
| 1246 const Variable *LastDest = nullptr; | 1309 const Variable *LastDest = nullptr; |
| 1247 for (const Variable *Var : Dests) { | 1310 for (const Variable *Var : Dests) { |
| 1248 if (!isScalarIntegerType(Var->getType())) | 1311 if (!isScalarIntegerType(Var->getType())) |
| 1249 // TODO(kschimpf) Implement vpush. | 1312 // TODO(kschimpf) Implement vpush. |
| 1250 return emitUsingTextFixup(Func); | 1313 return emitUsingTextFixup(Func); |
| 1251 assert((Var && Var->hasReg()) && "pop only applies to registers"); | 1314 assert((Var && Var->hasReg()) && "pop only applies to registers"); |
| 1252 int32_t Reg = Var->getRegNum(); | 1315 int32_t Reg = Var->getRegNum(); |
| 1253 assert(Reg != RegARM32::Encoded_Not_GPR); | 1316 assert(Reg != RegARM32::Encoded_Not_GPR); |
| 1254 LastDest = Var; | 1317 LastDest = Var; |
| 1255 GPRegisters |= (1 << Reg); | 1318 GPRegisters |= (1 << Reg); |
| 1256 ++IntegerCount; | 1319 ++IntegerCount; |
| 1257 } | 1320 } |
| 1258 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 1321 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 1259 switch (IntegerCount) { | 1322 switch (IntegerCount) { |
| 1260 case 0: | 1323 case 0: |
| 1261 return; | 1324 return; |
| 1262 case 1: | 1325 case 1: |
| 1263 // Note: Can only apply pop register if single register is not sp. | 1326 // Note: Can only apply pop register if single register is not sp. |
| 1264 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && | 1327 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && |
| 1265 "Effects of pop register SP is undefined!"); | 1328 "Effects of pop register SP is undefined!"); |
| 1266 // TODO(kschimpf) ARM sandbox does not allow the single register form of | 1329 // TODO(kschimpf): ARM sandbox does not allow the single register form of |
| 1267 // pop, and the popList form expects multiple registers. Convert this | 1330 // pop, and the popList form expects multiple registers. Convert this |
| 1268 // assert to a conditional check once it has been shown that popList | 1331 // assert to a conditional check once it has been shown that popList |
| 1269 // works. | 1332 // works. |
| 1270 assert(!Func->getContext()->getFlags().getUseSandboxing() && | 1333 assert(!Func->getContext()->getFlags().getUseSandboxing() && |
| 1271 "pop register not in ARM sandbox!"); | 1334 "pop register not in ARM sandbox!"); |
| 1272 Asm->pop(LastDest, CondARM32::AL); | 1335 Asm->pop(LastDest, CondARM32::AL); |
| 1273 break; | 1336 break; |
| 1274 default: | 1337 default: |
| 1275 Asm->popList(GPRegisters, CondARM32::AL); | 1338 Asm->popList(GPRegisters, CondARM32::AL); |
| 1276 break; | 1339 break; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1289 if (I > 0) | 1352 if (I > 0) |
| 1290 Str << ", "; | 1353 Str << ", "; |
| 1291 Dests[I]->dump(Func); | 1354 Dests[I]->dump(Func); |
| 1292 } | 1355 } |
| 1293 } | 1356 } |
| 1294 | 1357 |
| 1295 void InstARM32Push::emit(const Cfg *Func) const { | 1358 void InstARM32Push::emit(const Cfg *Func) const { |
| 1296 // TODO(jpp): Improve FP register save/restore. | 1359 // TODO(jpp): Improve FP register save/restore. |
| 1297 if (!BuildDefs::dump()) | 1360 if (!BuildDefs::dump()) |
| 1298 return; | 1361 return; |
| 1299 SizeT IntegerCount = 0; | 1362 |
| 1300 for (SizeT i = 0; i < getSrcSize(); ++i) { | 1363 // Push can't be emitted if there are no registers to save. This should never |
| 1301 if (isScalarIntegerType(getSrc(i)->getType())) { | 1364 // happen, but if it does, we don't need to bring Subzero down -- we just skip |
| 1302 ++IntegerCount; | 1365 // emitting the push instruction (and maybe emit a nop?) The assert() is here |
| 1303 } | 1366 // so that we can detect this error during development. |
| 1367 const SizeT SrcSize = getSrcSize(); | |
| 1368 if (SrcSize == 0) { | |
| 1369 assert(false && "Empty push list"); | |
| 1370 return; | |
| 1304 } | 1371 } |
| 1372 | |
| 1305 Ostream &Str = Func->getContext()->getStrEmit(); | 1373 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1306 bool NeedNewline = false; | 1374 |
| 1307 for (SizeT i = getSrcSize(); i > 0; --i) { | 1375 Variable *Reg = llvm::cast<Variable>(getSrc(0)); |
| 1308 Operand *Op = getSrc(i - 1); | 1376 if (isScalarIntegerType(Reg->getType())) { |
| 1309 if (isScalarIntegerType(Op->getType())) | 1377 // GPR push. |
| 1310 continue; | |
| 1311 if (NeedNewline) { | |
| 1312 Str << "\n"; | |
| 1313 startNextInst(Func); | |
| 1314 NeedNewline = false; | |
| 1315 } | |
| 1316 Str << "\t" | 1378 Str << "\t" |
| 1317 << "vpush" | 1379 "push" |
| 1318 << "\t{"; | 1380 "\t{"; |
| 1319 Op->emit(Func); | 1381 Reg->emit(Func); |
| 1320 Str << "}"; | 1382 for (SizeT i = 1; i < SrcSize; ++i) { |
| 1321 NeedNewline = true; | 1383 Str << ", "; |
| 1322 } | 1384 getSrc(i)->emit(Func); |
| 1323 if (IntegerCount != 0) { | |
| 1324 if (NeedNewline) { | |
| 1325 Str << "\n"; | |
| 1326 startNextInst(Func); | |
| 1327 NeedNewline = false; | |
| 1328 } | |
| 1329 Str << "\t" | |
| 1330 << "push" | |
| 1331 << "\t{"; | |
| 1332 bool PrintComma = false; | |
| 1333 for (SizeT i = 0; i < getSrcSize(); ++i) { | |
| 1334 Operand *Op = getSrc(i); | |
| 1335 if (isScalarIntegerType(Op->getType())) { | |
| 1336 if (PrintComma) | |
| 1337 Str << ", "; | |
| 1338 Op->emit(Func); | |
| 1339 PrintComma = true; | |
| 1340 } | |
| 1341 } | 1385 } |
| 1342 Str << "}"; | 1386 Str << "}"; |
| 1343 NeedNewline = true; | 1387 return; |
| 1344 } | 1388 } |
| 1345 assert(NeedNewline); // caller will add the newline | 1389 |
| 1390 // VFP "s" reg push. | |
| 1391 Str << "\t" | |
| 1392 "vpush" | |
| 1393 "\t{"; | |
| 1394 Reg->emit(Func); | |
| 1395 for (SizeT i = 1; i < SrcSize; ++i) { | |
| 1396 Variable *NextReg = llvm::cast<Variable>(getSrc(i)); | |
| 1397 if (isAssignedConsecutiveRegisters(Reg, NextReg)) { | |
| 1398 Str << ", "; | |
| 1399 } else { | |
| 1400 startNextInst(Func); | |
| 1401 Str << "}\n\t" | |
| 1402 "vpush" | |
| 1403 "\t{"; | |
| 1404 } | |
| 1405 Reg = NextReg; | |
| 1406 Reg->emit(Func); | |
| 1407 } | |
| 1408 Str << "}"; | |
| 1346 } | 1409 } |
| 1347 | 1410 |
| 1348 void InstARM32Push::emitIAS(const Cfg *Func) const { | 1411 void InstARM32Push::emitIAS(const Cfg *Func) const { |
| 1349 SizeT IntegerCount = 0; | 1412 SizeT IntegerCount = 0; |
| 1350 ARM32::IValueT GPRegisters = 0; | 1413 ARM32::IValueT GPRegisters = 0; |
| 1351 const Variable *LastSrc = nullptr; | 1414 const Variable *LastSrc = nullptr; |
| 1352 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { | 1415 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { |
| 1353 if (!isScalarIntegerType(getSrc(Index)->getType())) | 1416 if (!isScalarIntegerType(getSrc(Index)->getType())) |
| 1354 // TODO(kschimpf) Implement vpush. | 1417 // TODO(kschimpf) Implement vpush. |
| 1355 return emitUsingTextFixup(Func); | 1418 return emitUsingTextFixup(Func); |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1892 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; | 1955 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; |
| 1893 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; | 1956 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; |
| 1894 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>; | 1957 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>; |
| 1895 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; | 1958 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; |
| 1896 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; | 1959 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; |
| 1897 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; | 1960 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; |
| 1898 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; | 1961 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; |
| 1899 | 1962 |
| 1900 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; | 1963 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; |
| 1901 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; | 1964 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; |
| 1965 template class InstARM32ThreeAddrFP<InstARM32::Veor>; | |
| 1902 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; | 1966 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; |
| 1903 template class InstARM32ThreeAddrFP<InstARM32::Veor>; | 1967 template class InstARM32ThreeAddrFP<InstARM32::Vmla>; |
| 1968 template class InstARM32ThreeAddrFP<InstARM32::Vmls>; | |
| 1904 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; | 1969 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; |
| 1905 | 1970 |
| 1906 template class InstARM32LoadBase<InstARM32::Ldr>; | 1971 template class InstARM32LoadBase<InstARM32::Ldr>; |
| 1907 template class InstARM32LoadBase<InstARM32::Ldrex>; | 1972 template class InstARM32LoadBase<InstARM32::Ldrex>; |
| 1908 | 1973 |
| 1909 template class InstARM32TwoAddrGPR<InstARM32::Movt>; | 1974 template class InstARM32TwoAddrGPR<InstARM32::Movt>; |
| 1910 | 1975 |
| 1911 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; | 1976 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; |
| 1912 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; | 1977 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; |
| 1913 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; | 1978 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; |
| 1914 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; | 1979 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; |
| 1915 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; | 1980 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; |
| 1916 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; | 1981 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; |
| 1917 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; | 1982 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; |
| 1918 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; | 1983 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; |
| 1919 | 1984 |
| 1920 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 1985 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 1921 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 1986 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 1922 | 1987 |
| 1923 template class InstARM32CmpLike<InstARM32::Cmn>; | 1988 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 1924 template class InstARM32CmpLike<InstARM32::Cmp>; | 1989 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 1925 template class InstARM32CmpLike<InstARM32::Tst>; | 1990 template class InstARM32CmpLike<InstARM32::Tst>; |
| 1926 | 1991 |
| 1927 } // end of namespace Ice | 1992 } // end of namespace Ice |
| OLD | NEW |