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 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1247 Str << getPredicate() << WidthString; | 1247 Str << getPredicate() << WidthString; |
| 1248 } else { | 1248 } else { |
| 1249 Str << WidthString << getPredicate(); | 1249 Str << WidthString << getPredicate(); |
| 1250 } | 1250 } |
| 1251 Str << "\t"; | 1251 Str << "\t"; |
| 1252 Dest->emit(Func); | 1252 Dest->emit(Func); |
| 1253 Str << ", "; | 1253 Str << ", "; |
| 1254 Src0->emit(Func); | 1254 Src0->emit(Func); |
| 1255 } | 1255 } |
| 1256 | 1256 |
| 1257 void InstARM32Mov::emitIASScalarVFPMove(const Cfg *Func) const { | |
| 1258 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1259 Operand *Src0 = getSrc(0); | |
| 1260 Variable *Dest = getDest(); | |
| 1261 switch (Dest->getType()) { | |
| 1262 default: | |
| 1263 assert(false && "Do not know how to emit scalar FP move for type."); | |
| 1264 break; | |
| 1265 case IceType_f32: | |
| 1266 if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { | |
| 1267 Asm->vmovss(Dest, Var, getPredicate()); | |
| 1268 return; | |
| 1269 } else if (const auto *FpImm = | |
| 1270 llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { | |
| 1271 Asm->vmovs(Dest, FpImm, getPredicate()); | |
| 1272 return; | |
| 1273 } | |
| 1274 assert(!Asm->needsTextFixup()); | |
| 1275 return; | |
| 1276 case IceType_f64: | |
| 1277 if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { | |
| 1278 Asm->vmovdd(Dest, Var, getPredicate()); | |
| 1279 return; | |
| 1280 } else if (const auto *FpImm = | |
| 1281 llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { | |
| 1282 Asm->vmovd(Dest, FpImm, getPredicate()); | |
| 1283 return; | |
| 1284 } | |
| 1285 assert(!Asm->needsTextFixup()); | |
| 1286 return; | |
| 1287 } | |
| 1288 // TODO(kschimpf) Handle register to register move. | |
| 1289 Asm->setNeedsTextFixup(); | |
| 1290 return; | |
| 1291 } | |
| 1292 | |
| 1293 void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const { | |
| 1294 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1295 Operand *Src0 = getSrc(0); | |
| 1296 if (!llvm::isa<Variable>(Src0)) | |
| 1297 // TODO(kschimpf) Handle moving constants into registers. | |
| 1298 return Asm->setNeedsTextFixup(); | |
| 1299 | |
| 1300 // Move register to register. | |
| 1301 Variable *Dest = getDest(); | |
| 1302 // TODO(kschimpf) Consider merging methods emitIAS.. methods into | |
| 1303 // a single case statement. | |
| 1304 switch (Dest->getType()) { | |
| 1305 default: | |
| 1306 // TODO(kschimpf): Fill this out more. | |
| 1307 return Asm->setNeedsTextFixup(); | |
| 1308 case IceType_i1: | |
| 1309 case IceType_i8: | |
| 1310 case IceType_i16: | |
| 1311 case IceType_i32: | |
| 1312 assert(Src0->getType() == IceType_f32 && "Expected int to float move"); | |
| 1313 Asm->vmovrs(Dest, Src0, getPredicate()); | |
| 1314 return; | |
| 1315 case IceType_i64: | |
| 1316 assert(false && "i64 to float moves not handled here!"); | |
| 1317 return; | |
| 1318 case IceType_f32: | |
| 1319 switch (Src0->getType()) { | |
| 1320 default: | |
| 1321 assert(false && "Expected float to int move"); | |
| 1322 return; | |
| 1323 case IceType_i1: | |
| 1324 case IceType_i8: | |
| 1325 case IceType_i16: | |
| 1326 case IceType_i32: | |
| 1327 return Asm->vmovsr(Dest, Src0, getPredicate()); | |
| 1328 } | |
| 1329 } | |
| 1330 } | |
| 1331 | |
| 1332 void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { | |
| 1333 Variable *Dest = getDest(); | |
| 1334 Operand *Src0 = getSrc(0); | |
| 1335 | |
| 1336 if (!Dest->hasReg()) { | |
| 1337 llvm::report_fatal_error("mov can't store."); | |
| 1338 } | |
| 1339 | |
| 1340 if (isMemoryAccess(Src0)) { | |
| 1341 llvm::report_fatal_error("mov can't load."); | |
| 1342 } | |
| 1343 | |
| 1344 if (isMoveBetweenCoreAndVFPRegisters(Dest, Src0)) | |
| 1345 return emitIASCoreVFPMove(Func); | |
| 1346 | |
| 1347 const Type DestTy = Dest->getType(); | |
| 1348 if (isScalarFloatingType(DestTy)) | |
| 1349 return emitIASScalarVFPMove(Func); | |
| 1350 | |
| 1351 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | |
| 1352 if (isVectorType(DestTy)) | |
| 1353 return Asm->setNeedsTextFixup(); | |
| 1354 | |
| 1355 return Asm->mov(Dest, Src0, getPredicate()); | |
| 1356 } | |
| 1357 | |
| 1358 void InstARM32Mov::emit(const Cfg *Func) const { | 1257 void InstARM32Mov::emit(const Cfg *Func) const { |
| 1359 if (!BuildDefs::dump()) | 1258 if (!BuildDefs::dump()) |
| 1360 return; | 1259 return; |
| 1361 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); | 1260 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); |
| 1362 if (isMultiDest()) { | 1261 if (isMultiDest()) { |
| 1363 emitMultiDestSingleSource(Func); | 1262 emitMultiDestSingleSource(Func); |
| 1364 return; | 1263 return; |
| 1365 } | 1264 } |
| 1366 | 1265 |
| 1367 if (isMultiSource()) { | 1266 if (isMultiSource()) { |
| 1368 emitSingleDestMultiSource(Func); | 1267 emitSingleDestMultiSource(Func); |
| 1369 return; | 1268 return; |
| 1370 } | 1269 } |
| 1371 | 1270 |
| 1372 emitSingleDestSingleSource(Func); | 1271 emitSingleDestSingleSource(Func); |
| 1373 } | 1272 } |
| 1374 | 1273 |
| 1375 void InstARM32Mov::emitIAS(const Cfg *Func) const { | 1274 void InstARM32Mov::emitIAS(const Cfg *Func) const { |
| 1376 // TODO(kschimpf) Flatten this to a switch statement of dest type. That is, | |
| 1377 // combine code of emitIASSingleDestSingleSource, emitIASCoreVFPMove, | |
| 1378 // emitIASScalarVFPMove, emitDoubleToI64Move, and emitI64ToDoubleMove. | |
| 1379 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); | 1275 auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); |
| 1276 Variable *Dest = getDest(); | |
| 1277 Operand *Src0 = getSrc(0); | |
| 1278 if (!Dest->hasReg()) { | |
| 1279 llvm::report_fatal_error("mov can't store."); | |
| 1280 } | |
| 1281 if (isMemoryAccess(Src0)) { | |
| 1282 llvm::report_fatal_error("mov can't load."); | |
| 1283 } | |
| 1284 | |
| 1380 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); | 1285 assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); |
| 1381 if (isMultiDest()) | 1286 if (isMultiDest()) { |
| 1382 Asm->vmovrrd(getDest(), getDestHi(), getSrc(0), getPredicate()); | 1287 Asm->vmovrrd(Dest, getDestHi(), Src0, getPredicate()); |
| 1383 else if (isMultiSource()) | 1288 return; |
| 1384 Asm->vmovdrr(getDest(), getSrc(0), getSrc(1), getPredicate()); | 1289 } |
| 1385 else | 1290 if (isMultiSource()) { |
| 1386 emitIASSingleDestSingleSource(Func); | 1291 Asm->vmovdrr(Dest, Src0, getSrc(1), getPredicate()); |
| 1387 if (Asm->needsTextFixup()) | 1292 return; |
| 1293 } | |
| 1294 | |
| 1295 const Type DestTy = Dest->getType(); | |
| 1296 const Type SrcTy = Src0->getType(); | |
| 1297 switch (DestTy) { | |
| 1298 case IceType_void: | |
|
Jim Stichnoth
2016/02/05 00:56:23
Consider just using "default:", for symmetry with
Karl
2016/02/05 15:27:08
Done.
| |
| 1299 case IceType_NUM: | |
| 1300 break; // Error | |
| 1301 case IceType_i1: | |
| 1302 case IceType_i8: | |
| 1303 case IceType_i16: | |
| 1304 case IceType_i32: | |
| 1305 switch (SrcTy) { | |
| 1306 default: | |
| 1307 break; // Error | |
| 1308 case IceType_i1: | |
| 1309 case IceType_i8: | |
| 1310 case IceType_i16: | |
| 1311 case IceType_i32: | |
| 1312 case IceType_i64: | |
| 1313 Asm->mov(Dest, Src0, getPredicate()); | |
| 1314 return; | |
| 1315 case IceType_f32: | |
| 1316 Asm->vmovrs(Dest, Src0, getPredicate()); | |
| 1317 return; | |
| 1318 } | |
| 1319 break; // Error | |
| 1320 case IceType_i64: | |
| 1321 if (isScalarIntegerType(SrcTy)) { | |
| 1322 Asm->mov(Dest, Src0, getPredicate()); | |
| 1323 return; | |
| 1324 } | |
| 1325 if (SrcTy == IceType_f64) { | |
| 1326 if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { | |
| 1327 Asm->vmovdd(Dest, Var, getPredicate()); | |
| 1328 return; | |
| 1329 } else if (const auto *FpImm = | |
|
Jim Stichnoth
2016/02/05 00:56:23
Don't use "else if" after a clause that ends with
Karl
2016/02/05 15:27:08
Done.
| |
| 1330 llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { | |
| 1331 Asm->vmovd(Dest, FpImm, getPredicate()); | |
| 1332 return; | |
| 1333 } | |
| 1334 } | |
| 1335 break; // Error | |
| 1336 case IceType_f32: | |
| 1337 switch (SrcTy) { | |
| 1338 default: | |
| 1339 break; // Error | |
| 1340 case IceType_i1: | |
| 1341 case IceType_i8: | |
| 1342 case IceType_i16: | |
| 1343 case IceType_i32: | |
| 1344 return Asm->vmovsr(Dest, Src0, getPredicate()); | |
| 1345 case IceType_f32: | |
| 1346 if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { | |
| 1347 Asm->vmovss(Dest, Var, getPredicate()); | |
| 1348 return; | |
| 1349 } else if (const auto *FpImm = | |
| 1350 llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { | |
| 1351 Asm->vmovs(Dest, FpImm, getPredicate()); | |
| 1352 return; | |
| 1353 } | |
| 1354 break; // Error | |
| 1355 } | |
| 1356 break; // Error | |
| 1357 case IceType_f64: | |
| 1358 if (SrcTy == IceType_f64) { | |
| 1359 if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { | |
| 1360 Asm->vmovdd(Dest, Var, getPredicate()); | |
| 1361 return; | |
| 1362 } else if (const auto *FpImm = | |
| 1363 llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { | |
| 1364 Asm->vmovd(Dest, FpImm, getPredicate()); | |
| 1365 return; | |
| 1366 } | |
| 1367 } | |
| 1368 break; // Error | |
| 1369 case IceType_v4i1: | |
| 1370 case IceType_v8i1: | |
| 1371 case IceType_v16i1: | |
| 1372 case IceType_v16i8: | |
| 1373 case IceType_v8i16: | |
| 1374 case IceType_v4i32: | |
| 1375 case IceType_v4f32: | |
| 1376 // TODO(kschimpf): Add vector moves. | |
| 1388 emitUsingTextFixup(Func); | 1377 emitUsingTextFixup(Func); |
| 1378 return; | |
| 1379 } | |
| 1380 llvm::report_fatal_error("Mov: don't know how to move " + | |
| 1381 typeIceString(SrcTy) + " to " + | |
| 1382 typeIceString(DestTy)); | |
| 1389 } | 1383 } |
| 1390 | 1384 |
| 1391 void InstARM32Mov::dump(const Cfg *Func) const { | 1385 void InstARM32Mov::dump(const Cfg *Func) const { |
| 1392 if (!BuildDefs::dump()) | 1386 if (!BuildDefs::dump()) |
| 1393 return; | 1387 return; |
| 1394 assert(getSrcSize() == 1 || getSrcSize() == 2); | 1388 assert(getSrcSize() == 1 || getSrcSize() == 2); |
| 1395 Ostream &Str = Func->getContext()->getStrDump(); | 1389 Ostream &Str = Func->getContext()->getStrDump(); |
| 1396 Variable *Dest = getDest(); | 1390 Variable *Dest = getDest(); |
| 1397 Variable *DestHi = getDestHi(); | 1391 Variable *DestHi = getDestHi(); |
| 1398 Dest->dump(Func); | 1392 Dest->dump(Func); |
| (...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2547 | 2541 |
| 2548 template class InstARM32FourAddrGPR<InstARM32::Mla>; | 2542 template class InstARM32FourAddrGPR<InstARM32::Mla>; |
| 2549 template class InstARM32FourAddrGPR<InstARM32::Mls>; | 2543 template class InstARM32FourAddrGPR<InstARM32::Mls>; |
| 2550 | 2544 |
| 2551 template class InstARM32CmpLike<InstARM32::Cmn>; | 2545 template class InstARM32CmpLike<InstARM32::Cmn>; |
| 2552 template class InstARM32CmpLike<InstARM32::Cmp>; | 2546 template class InstARM32CmpLike<InstARM32::Cmp>; |
| 2553 template class InstARM32CmpLike<InstARM32::Tst>; | 2547 template class InstARM32CmpLike<InstARM32::Tst>; |
| 2554 | 2548 |
| 2555 } // end of namespace ARM32 | 2549 } // end of namespace ARM32 |
| 2556 } // end of namespace Ice | 2550 } // end of namespace Ice |
| OLD | NEW |