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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 IceString InstARM32Label::getName(const Cfg *Func) const { | 572 IceString InstARM32Label::getName(const Cfg *Func) const { |
| 557 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); | 573 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); |
| 558 } | 574 } |
| 559 | 575 |
| 560 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests) | 576 InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests) |
| 561 : InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) { | 577 : InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) { |
| 562 // Track modifications to Dests separately via FakeDefs. Also, a pop | 578 // Track modifications to Dests separately via FakeDefs. Also, a pop |
| 563 // instruction affects the stack pointer and so it should not be allowed to | 579 // instruction affects the stack pointer and so it should not be allowed to |
| 564 // be automatically dead-code eliminated. This is automatic since we leave | 580 // be automatically dead-code eliminated. This is automatic since we leave |
| 565 // the Dest as nullptr. | 581 // the Dest as nullptr. |
| 582 Type PreviousTy = IceType_void; | |
|
Jim Stichnoth
2015/12/07 20:58:14
What do you think about adding this?
if (BuildD
John
2015/12/08 13:54:24
This seems like a serious error that should be ver
Jim Stichnoth
2015/12/08 19:20:16
The only argument for removing it would be a very
| |
| 583 for (Variable *Dest : Dests) { | |
| 584 if (PreviousTy != IceType_void && Dest->getType() != PreviousTy) { | |
| 585 llvm::report_fatal_error("Type mismatch when popping registers."); | |
| 586 } | |
| 587 PreviousTy = Dest->getType(); | |
| 588 } | |
| 566 } | 589 } |
| 567 | 590 |
| 568 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs) | 591 InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs) |
| 569 : InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) { | 592 : InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) { |
| 570 for (Variable *Source : Srcs) | 593 Type PreviousTy = IceType_void; |
| 594 for (Variable *Source : Srcs) { | |
| 595 if (PreviousTy != IceType_void && Source->getType() != PreviousTy) { | |
| 596 llvm::report_fatal_error("Type mismatch when pushing registers."); | |
| 597 } | |
| 571 addSource(Source); | 598 addSource(Source); |
| 599 PreviousTy = Source->getType(); | |
| 600 } | |
| 572 } | 601 } |
| 573 | 602 |
| 574 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) | 603 InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source) |
| 575 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { | 604 : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) { |
| 576 addSource(LR); | 605 addSource(LR); |
| 577 if (Source) | 606 if (Source) |
| 578 addSource(Source); | 607 addSource(Source); |
| 579 } | 608 } |
| 580 | 609 |
| 581 InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, | 610 InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 template <> const char *InstARM32Orr::Opcode = "orr"; | 736 template <> const char *InstARM32Orr::Opcode = "orr"; |
| 708 template <> const char *InstARM32Rsb::Opcode = "rsb"; | 737 template <> const char *InstARM32Rsb::Opcode = "rsb"; |
| 709 template <> const char *InstARM32Rsc::Opcode = "rsc"; | 738 template <> const char *InstARM32Rsc::Opcode = "rsc"; |
| 710 template <> const char *InstARM32Sbc::Opcode = "sbc"; | 739 template <> const char *InstARM32Sbc::Opcode = "sbc"; |
| 711 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; | 740 template <> const char *InstARM32Sdiv::Opcode = "sdiv"; |
| 712 template <> const char *InstARM32Sub::Opcode = "sub"; | 741 template <> const char *InstARM32Sub::Opcode = "sub"; |
| 713 template <> const char *InstARM32Udiv::Opcode = "udiv"; | 742 template <> const char *InstARM32Udiv::Opcode = "udiv"; |
| 714 // FP | 743 // FP |
| 715 template <> const char *InstARM32Vadd::Opcode = "vadd"; | 744 template <> const char *InstARM32Vadd::Opcode = "vadd"; |
| 716 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; | 745 template <> const char *InstARM32Vdiv::Opcode = "vdiv"; |
| 746 template <> const char *InstARM32Veor::Opcode = "veor"; | |
| 747 template <> const char *InstARM32Vmla::Opcode = "vmla"; | |
| 748 template <> const char *InstARM32Vmls::Opcode = "vmls"; | |
| 717 template <> const char *InstARM32Vmul::Opcode = "vmul"; | 749 template <> const char *InstARM32Vmul::Opcode = "vmul"; |
| 718 template <> const char *InstARM32Veor::Opcode = "veor"; | |
| 719 template <> const char *InstARM32Vsub::Opcode = "vsub"; | 750 template <> const char *InstARM32Vsub::Opcode = "vsub"; |
| 720 // Four-addr ops | 751 // Four-addr ops |
| 721 template <> const char *InstARM32Mla::Opcode = "mla"; | 752 template <> const char *InstARM32Mla::Opcode = "mla"; |
| 722 template <> const char *InstARM32Mls::Opcode = "mls"; | 753 template <> const char *InstARM32Mls::Opcode = "mls"; |
| 723 // Cmp-like ops | 754 // Cmp-like ops |
| 724 template <> const char *InstARM32Cmn::Opcode = "cmn"; | 755 template <> const char *InstARM32Cmn::Opcode = "cmn"; |
| 725 template <> const char *InstARM32Cmp::Opcode = "cmp"; | 756 template <> const char *InstARM32Cmp::Opcode = "cmp"; |
| 726 template <> const char *InstARM32Tst::Opcode = "tst"; | 757 template <> const char *InstARM32Tst::Opcode = "tst"; |
| 727 | 758 |
| 728 void InstARM32::dump(const Cfg *Func) const { | 759 void InstARM32::dump(const Cfg *Func) const { |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1179 } | 1210 } |
| 1180 | 1211 |
| 1181 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const { | 1212 template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const { |
| 1182 assert(getSrcSize() == 1); | 1213 assert(getSrcSize() == 1); |
| 1183 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 1214 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 1184 Asm->uxt(getDest(), getSrc(0), getPredicate()); | 1215 Asm->uxt(getDest(), getSrc(0), getPredicate()); |
| 1185 if (Asm->needsTextFixup()) | 1216 if (Asm->needsTextFixup()) |
| 1186 emitUsingTextFixup(Func); | 1217 emitUsingTextFixup(Func); |
| 1187 } | 1218 } |
| 1188 | 1219 |
| 1220 namespace { | |
| 1221 | |
| 1222 bool AssignedConsecutiveRegisters(Operand *Before, Operand *After) { | |
|
Jim Stichnoth
2015/12/07 20:58:14
Maybe isAssignedConsecutiveRegisters() ?
(in any
John
2015/12/08 13:54:24
Done.
PS: don't be sorry for the code style. :)
| |
| 1223 return llvm::cast<Variable>(Before)->getRegNum() + 1 == | |
|
Jim Stichnoth
2015/12/07 20:58:14
I think you should make Before and After both Vari
John
2015/12/08 13:54:24
I am asserting here because I moved the actual tes
| |
| 1224 llvm::cast<Variable>(After)->getRegNum(); | |
| 1225 } | |
| 1226 | |
| 1227 } // end of anonymous namespace | |
| 1228 | |
| 1189 void InstARM32Pop::emit(const Cfg *Func) const { | 1229 void InstARM32Pop::emit(const Cfg *Func) const { |
| 1190 // TODO(jpp): Improve FP register save/restore. | 1230 // TODO(jpp): Improve FP register save/restore. |
| 1191 if (!BuildDefs::dump()) | 1231 if (!BuildDefs::dump()) |
| 1192 return; | 1232 return; |
| 1193 SizeT IntegerCount = 0; | 1233 Ostream &Str = Func->getContext()->getStrEmit(); |
|
Jim Stichnoth
2015/12/07 20:58:14
Maybe move this after the DestSize assert / early
John
2015/12/08 13:54:24
Done.
| |
| 1194 for (const Operand *Op : Dests) { | 1234 const SizeT DestSize = Dests.size(); |
| 1195 if (isScalarIntegerType(Op->getType())) { | 1235 assert(DestSize > 0); |
|
Jim Stichnoth
2015/12/07 20:58:14
Maybe move the assert into the "if" branch, right
John
2015/12/08 13:54:24
Done.
Jim Stichnoth
2015/12/08 19:20:16
Actually, looks like not (yet) done...
John
2015/12/09 13:11:08
Done.
| |
| 1196 ++IntegerCount; | 1236 if (DestSize == 0) { |
| 1197 } | 1237 return; |
| 1198 } | 1238 } |
| 1199 Ostream &Str = Func->getContext()->getStrEmit(); | 1239 |
| 1200 bool NeedNewline = false; | 1240 Operand *Op = Dests[0]; |
|
Jim Stichnoth
2015/12/07 20:58:14
Can this be declared as Variable* ? Maybe "Variab
John
2015/12/08 13:54:24
Done.
| |
| 1201 if (IntegerCount != 0) { | 1241 if (isScalarIntegerType(Op->getType())) { |
| 1242 // GPR push. | |
| 1202 Str << "\t" | 1243 Str << "\t" |
| 1203 << "pop" | 1244 "pop" |
| 1204 << "\t{"; | 1245 "\t{"; |
| 1205 bool PrintComma = false; | 1246 Op->emit(Func); |
| 1206 for (const Operand *Op : Dests) { | 1247 for (SizeT i = 1; i < DestSize; ++i) { |
| 1207 if (isScalarIntegerType(Op->getType())) { | 1248 Str << ", "; |
| 1208 if (PrintComma) | 1249 Op = Dests[i]; |
| 1209 Str << ", "; | 1250 Op->emit(Func); |
| 1210 Op->emit(Func); | |
| 1211 PrintComma = true; | |
| 1212 } | |
| 1213 } | 1251 } |
| 1214 Str << "}"; | 1252 Str << "}"; |
| 1215 NeedNewline = true; | 1253 return; |
|
Karl
2015/12/07 19:11:07
I assume you return here because you modified the
John
2015/12/08 13:54:24
That's correct.
| |
| 1216 } | 1254 } |
| 1217 | 1255 |
| 1218 for (const Operand *Op : Dests) { | 1256 // VFP "s" reg push. |
| 1219 if (isScalarIntegerType(Op->getType())) | 1257 SizeT End = DestSize - 1; |
| 1220 continue; | 1258 SizeT Start = DestSize - 1; |
| 1221 if (NeedNewline) { | 1259 Op = Dests[DestSize - 1]; |
| 1222 Str << "\n"; | 1260 Str << "\t" |
| 1261 "vpop" | |
| 1262 "\t{"; | |
| 1263 for (SizeT i = 2; i <= DestSize; ++i) { | |
| 1264 Operand *PreviousOp = Dests[DestSize - i]; | |
| 1265 if (!AssignedConsecutiveRegisters(PreviousOp, Op)) { | |
| 1266 Dests[Start]->emit(Func); | |
| 1267 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1268 Str << ", "; | |
| 1269 Dests[j]->emit(Func); | |
| 1270 } | |
| 1223 startNextInst(Func); | 1271 startNextInst(Func); |
| 1224 NeedNewline = false; | 1272 Str << "}\n\t" |
| 1273 "vpop" | |
| 1274 "\t{"; | |
| 1275 End = DestSize - i; | |
| 1225 } | 1276 } |
| 1226 Str << "\t" | 1277 Op = PreviousOp; |
| 1227 << "vpop" | 1278 Start = DestSize - i; |
| 1228 << "\t{"; | |
| 1229 Op->emit(Func); | |
| 1230 Str << "}"; | |
| 1231 NeedNewline = true; | |
| 1232 } | 1279 } |
| 1233 assert(NeedNewline); // caller will add the newline | 1280 Dests[Start]->emit(Func); |
| 1281 for (SizeT j = Start + 1; j <= End; ++j) { | |
| 1282 Str << ", "; | |
| 1283 Dests[j]->emit(Func); | |
| 1284 } | |
| 1285 Str << "}"; | |
| 1234 } | 1286 } |
| 1235 | 1287 |
| 1236 void InstARM32Pop::emitIAS(const Cfg *Func) const { | 1288 void InstARM32Pop::emitIAS(const Cfg *Func) const { |
| 1237 SizeT IntegerCount = 0; | 1289 SizeT IntegerCount = 0; |
| 1238 ARM32::IValueT GPRegisters = 0; | 1290 ARM32::IValueT GPRegisters = 0; |
| 1239 const Variable *LastDest = nullptr; | 1291 const Variable *LastDest = nullptr; |
| 1240 for (const Variable *Var : Dests) { | 1292 for (const Variable *Var : Dests) { |
| 1241 if (!isScalarIntegerType(Var->getType())) | 1293 if (!isScalarIntegerType(Var->getType())) |
| 1242 // TODO(kschimpf) Implement vpush. | 1294 // TODO(kschimpf) Implement vpush. |
| 1243 return emitUsingTextFixup(Func); | 1295 return emitUsingTextFixup(Func); |
| 1244 assert((Var && Var->hasReg()) && "pop only applies to registers"); | 1296 assert((Var && Var->hasReg()) && "pop only applies to registers"); |
| 1245 int32_t Reg = Var->getRegNum(); | 1297 int32_t Reg = Var->getRegNum(); |
| 1246 assert(Reg != RegARM32::Encoded_Not_GPR); | 1298 assert(Reg != RegARM32::Encoded_Not_GPR); |
| 1247 LastDest = Var; | 1299 LastDest = Var; |
| 1248 GPRegisters |= (1 << Reg); | 1300 GPRegisters |= (1 << Reg); |
| 1249 ++IntegerCount; | 1301 ++IntegerCount; |
| 1250 } | 1302 } |
| 1251 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 1303 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 1252 switch (IntegerCount) { | 1304 switch (IntegerCount) { |
| 1253 case 0: | 1305 case 0: |
| 1254 return; | 1306 return; |
| 1255 case 1: | 1307 case 1: |
| 1256 // Note: Can only apply pop register if single register is not sp. | 1308 // Note: Can only apply pop register if single register is not sp. |
| 1257 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && | 1309 assert((RegARM32::Encoded_Reg_sp != LastDest->getRegNum()) && |
| 1258 "Effects of pop register SP is undefined!"); | 1310 "Effects of pop register SP is undefined!"); |
| 1259 // TODO(kschimpf) ARM sandbox does not allow the single register form of | 1311 // TODO(kschimpf): ARM sandbox does not allow the single register form of |
| 1260 // pop, and the popList form expects multiple registers. Convert this | 1312 // pop, and the popList form expects multiple registers. Convert this |
| 1261 // assert to a conditional check once it has been shown that popList | 1313 // assert to a conditional check once it has been shown that popList |
| 1262 // works. | 1314 // works. |
| 1263 assert(!Func->getContext()->getFlags().getUseSandboxing() && | 1315 assert(!Func->getContext()->getFlags().getUseSandboxing() && |
| 1264 "pop register not in ARM sandbox!"); | 1316 "pop register not in ARM sandbox!"); |
| 1265 Asm->pop(LastDest, CondARM32::AL); | 1317 Asm->pop(LastDest, CondARM32::AL); |
| 1266 break; | 1318 break; |
| 1267 default: | 1319 default: |
| 1268 Asm->popList(GPRegisters, CondARM32::AL); | 1320 Asm->popList(GPRegisters, CondARM32::AL); |
| 1269 break; | 1321 break; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1282 if (I > 0) | 1334 if (I > 0) |
| 1283 Str << ", "; | 1335 Str << ", "; |
| 1284 Dests[I]->dump(Func); | 1336 Dests[I]->dump(Func); |
| 1285 } | 1337 } |
| 1286 } | 1338 } |
| 1287 | 1339 |
| 1288 void InstARM32Push::emit(const Cfg *Func) const { | 1340 void InstARM32Push::emit(const Cfg *Func) const { |
| 1289 // TODO(jpp): Improve FP register save/restore. | 1341 // TODO(jpp): Improve FP register save/restore. |
| 1290 if (!BuildDefs::dump()) | 1342 if (!BuildDefs::dump()) |
| 1291 return; | 1343 return; |
| 1292 SizeT IntegerCount = 0; | 1344 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1293 for (SizeT i = 0; i < getSrcSize(); ++i) { | 1345 const SizeT SrcSize = getSrcSize(); |
| 1294 if (isScalarIntegerType(getSrc(i)->getType())) { | 1346 assert(SrcSize > 0); |
| 1295 ++IntegerCount; | 1347 if (SrcSize == 0) { |
| 1296 } | 1348 return; |
| 1297 } | 1349 } |
| 1298 Ostream &Str = Func->getContext()->getStrEmit(); | 1350 |
| 1299 bool NeedNewline = false; | 1351 Operand *Op = getSrc(0); |
| 1300 for (SizeT i = getSrcSize(); i > 0; --i) { | 1352 if (isScalarIntegerType(Op->getType())) { |
| 1301 Operand *Op = getSrc(i - 1); | 1353 // GPR push. |
| 1302 if (isScalarIntegerType(Op->getType())) | |
| 1303 continue; | |
| 1304 if (NeedNewline) { | |
| 1305 Str << "\n"; | |
| 1306 startNextInst(Func); | |
| 1307 NeedNewline = false; | |
| 1308 } | |
| 1309 Str << "\t" | 1354 Str << "\t" |
| 1310 << "vpush" | 1355 "push" |
| 1311 << "\t{"; | 1356 "\t{"; |
| 1312 Op->emit(Func); | 1357 Op->emit(Func); |
| 1313 Str << "}"; | 1358 for (SizeT i = 1; i < SrcSize; ++i) { |
| 1314 NeedNewline = true; | 1359 Str << ", "; |
| 1315 } | 1360 Op = getSrc(i); |
| 1316 if (IntegerCount != 0) { | 1361 Op->emit(Func); |
| 1317 if (NeedNewline) { | |
| 1318 Str << "\n"; | |
| 1319 startNextInst(Func); | |
| 1320 NeedNewline = false; | |
| 1321 } | |
| 1322 Str << "\t" | |
| 1323 << "push" | |
| 1324 << "\t{"; | |
| 1325 bool PrintComma = false; | |
| 1326 for (SizeT i = 0; i < getSrcSize(); ++i) { | |
| 1327 Operand *Op = getSrc(i); | |
| 1328 if (isScalarIntegerType(Op->getType())) { | |
| 1329 if (PrintComma) | |
| 1330 Str << ", "; | |
| 1331 Op->emit(Func); | |
| 1332 PrintComma = true; | |
| 1333 } | |
| 1334 } | 1362 } |
| 1335 Str << "}"; | 1363 Str << "}"; |
| 1336 NeedNewline = true; | 1364 return; |
| 1337 } | 1365 } |
| 1338 assert(NeedNewline); // caller will add the newline | 1366 |
| 1367 // VFP "s" reg push. | |
| 1368 Str << "\t" | |
| 1369 "vpush" | |
| 1370 "\t{"; | |
| 1371 Op->emit(Func); | |
| 1372 for (SizeT i = 1; i < SrcSize; ++i) { | |
| 1373 Operand *NextOp = getSrc(i); | |
| 1374 if (AssignedConsecutiveRegisters(Op, NextOp)) { | |
| 1375 Str << ", "; | |
| 1376 } else { | |
| 1377 startNextInst(Func); | |
| 1378 Str << "}\n\t" | |
| 1379 "vpush" | |
| 1380 "\t{"; | |
| 1381 } | |
| 1382 Op = NextOp; | |
| 1383 Op->emit(Func); | |
| 1384 } | |
| 1385 Str << "}"; | |
| 1339 } | 1386 } |
| 1340 | 1387 |
| 1341 void InstARM32Push::emitIAS(const Cfg *Func) const { | 1388 void InstARM32Push::emitIAS(const Cfg *Func) const { |
| 1342 SizeT IntegerCount = 0; | 1389 SizeT IntegerCount = 0; |
| 1343 ARM32::IValueT GPRegisters = 0; | 1390 ARM32::IValueT GPRegisters = 0; |
| 1344 const Variable *LastSrc = nullptr; | 1391 const Variable *LastSrc = nullptr; |
| 1345 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { | 1392 for (SizeT Index = 0; Index < getSrcSize(); ++Index) { |
| 1346 if (!isScalarIntegerType(getSrc(Index)->getType())) | 1393 if (!isScalarIntegerType(getSrc(Index)->getType())) |
| 1347 // TODO(kschimpf) Implement vpush. | 1394 // TODO(kschimpf) Implement vpush. |
| 1348 return emitUsingTextFixup(Func); | 1395 return emitUsingTextFixup(Func); |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1885 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; | 1932 template class InstARM32ThreeAddrGPR<InstARM32::Orr>; |
| 1886 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; | 1933 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>; |
| 1887 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>; | 1934 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>; |
| 1888 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; | 1935 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>; |
| 1889 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; | 1936 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>; |
| 1890 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; | 1937 template class InstARM32ThreeAddrGPR<InstARM32::Sub>; |
| 1891 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; | 1938 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>; |
| 1892 | 1939 |
| 1893 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; | 1940 template class InstARM32ThreeAddrFP<InstARM32::Vadd>; |
| 1894 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; | 1941 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>; |
| 1942 template class InstARM32ThreeAddrFP<InstARM32::Veor>; | |
| 1895 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; | 1943 template class InstARM32ThreeAddrFP<InstARM32::Vmul>; |
| 1896 template class InstARM32ThreeAddrFP<InstARM32::Veor>; | 1944 template class InstARM32ThreeAddrFP<InstARM32::Vmla>; |
| 1945 template class InstARM32ThreeAddrFP<InstARM32::Vmls>; | |
| 1897 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; | 1946 template class InstARM32ThreeAddrFP<InstARM32::Vsub>; |
| 1898 | 1947 |
| 1899 template class InstARM32LoadBase<InstARM32::Ldr>; | 1948 template class InstARM32LoadBase<InstARM32::Ldr>; |
| 1900 template class InstARM32LoadBase<InstARM32::Ldrex>; | 1949 template class InstARM32LoadBase<InstARM32::Ldrex>; |
| 1901 | 1950 |
| 1902 template class InstARM32TwoAddrGPR<InstARM32::Movt>; | 1951 template class InstARM32TwoAddrGPR<InstARM32::Movt>; |
| 1903 | 1952 |
| 1904 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; | 1953 template class InstARM32UnaryopGPR<InstARM32::Movw, false>; |
| 1905 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; | 1954 template class InstARM32UnaryopGPR<InstARM32::Clz, false>; |
| 1906 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; | 1955 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>; |
| 1907 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; | 1956 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>; |
| 1908 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; | 1957 template class InstARM32UnaryopGPR<InstARM32::Rev, false>; |
| 1909 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; | 1958 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>; |
| 1910 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; | 1959 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>; |
| 1911 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; | 1960 template class InstARM32UnaryopFP<InstARM32::Vsqrt>; |
| 1912 | 1961 |
| 1913 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 1962 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 1914 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 1963 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 1915 | 1964 |
| 1916 template class InstARM32CmpLike<InstARM32::Cmn>; | 1965 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 1917 template class InstARM32CmpLike<InstARM32::Cmp>; | 1966 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 1918 template class InstARM32CmpLike<InstARM32::Tst>; | 1967 template class InstARM32CmpLike<InstARM32::Tst>; |
| 1919 | 1968 |
| 1920 } // end of namespace Ice | 1969 } // end of namespace Ice |
| OLD | NEW |