Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // | 1 // |
| 2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
| 3 // | 3 // |
| 4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
| 5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
| 6 // | 6 // |
| 7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
| 8 /// | 8 /// |
| 9 /// \file | 9 /// \file |
| 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 UnimplementedError(getFlags()); | 388 UnimplementedError(getFlags()); |
| 389 } | 389 } |
| 390 | 390 |
| 391 void TargetMIPS32::lowerArguments() { | 391 void TargetMIPS32::lowerArguments() { |
| 392 VarList &Args = Func->getArgs(); | 392 VarList &Args = Func->getArgs(); |
| 393 // We are only handling integer registers for now. The Mips o32 ABI is | 393 // We are only handling integer registers for now. The Mips o32 ABI is |
| 394 // somewhat complex but will be implemented in its totality through follow | 394 // somewhat complex but will be implemented in its totality through follow |
| 395 // on patches. | 395 // on patches. |
| 396 // | 396 // |
| 397 unsigned NumGPRRegsUsed = 0; | 397 unsigned NumGPRRegsUsed = 0; |
| 398 | |
| 398 // For each register argument, replace Arg in the argument list with the | 399 // For each register argument, replace Arg in the argument list with the |
| 399 // home register. Then generate an instruction in the prolog to copy the | 400 // home register. Then generate an instruction in the prolog to copy the |
| 400 // home register to the assigned location of Arg. | 401 // home register to the assigned location of Arg. |
| 401 Context.init(Func->getEntryNode()); | 402 Context.init(Func->getEntryNode()); |
| 402 Context.setInsertPoint(Context.getCur()); | 403 Context.setInsertPoint(Context.getCur()); |
| 403 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 404 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
| 404 Variable *Arg = Args[I]; | 405 Variable *Arg = Args[I]; |
| 405 Type Ty = Arg->getType(); | 406 Type Ty = Arg->getType(); |
| 406 // TODO(rkotler): handle float/vector types. | 407 // TODO(rkotler): handle float/vector types. |
| 407 if (isVectorType(Ty)) { | 408 if (isVectorType(Ty)) { |
| 408 UnimplementedError(getFlags()); | 409 UnimplementedError(getFlags()); |
| 409 continue; | 410 continue; |
| 410 } | 411 } |
| 412 | |
| 411 if (isFloatingType(Ty)) { | 413 if (isFloatingType(Ty)) { |
| 414 assert(Ty = IceType_f32); | |
|
Jim Stichnoth
2016/05/19 23:12:25
Is this really necessary, given the UnimplementedE
obucinac
2016/05/27 11:13:18
Done.
| |
| 412 UnimplementedError(getFlags()); | 415 UnimplementedError(getFlags()); |
| 413 continue; | 416 continue; |
| 414 } | 417 } |
| 418 | |
| 415 if (Ty == IceType_i64) { | 419 if (Ty == IceType_i64) { |
| 416 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | 420 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) |
| 417 continue; | 421 continue; |
| 418 auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); | 422 auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); |
| 419 auto RegHi = RegNumT::fixme(RegLo + 1); | 423 auto RegHi = RegNumT::fixme(RegLo + 1); |
| 420 ++NumGPRRegsUsed; | 424 ++NumGPRRegsUsed; |
| 421 // Always start i64 registers at an even register, so this may end | 425 // Always start i64 registers at an even register, so this may end |
| 422 // up padding away a register. | 426 // up padding away a register. |
| 423 if (RegLo % 2 != 0) { | 427 if (RegLo % 2 != 0) { |
| 424 RegLo = RegNumT::fixme(RegLo + 1); | 428 RegLo = RegNumT::fixme(RegLo + 1); |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1269 | 1273 |
| 1270 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { | 1274 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { |
| 1271 Func->setError("Phi found in regular instruction list"); | 1275 Func->setError("Phi found in regular instruction list"); |
| 1272 } | 1276 } |
| 1273 | 1277 |
| 1274 void TargetMIPS32::lowerRet(const InstRet *Instr) { | 1278 void TargetMIPS32::lowerRet(const InstRet *Instr) { |
| 1275 Variable *Reg = nullptr; | 1279 Variable *Reg = nullptr; |
| 1276 if (Instr->hasRetValue()) { | 1280 if (Instr->hasRetValue()) { |
| 1277 Operand *Src0 = Instr->getRetValue(); | 1281 Operand *Src0 = Instr->getRetValue(); |
| 1278 switch (Src0->getType()) { | 1282 switch (Src0->getType()) { |
| 1283 case IceType_f32: { | |
| 1284 Operand *Src0F = legalize(Src0, Legal_Reg); | |
| 1285 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); | |
|
Jim Stichnoth
2016/05/19 23:12:25
Should this be Reg_F0 instead?
obucinac
2016/05/27 11:13:18
We need to rework this to o32 convention. Leaving
| |
| 1286 _mov(Reg, Src0F); | |
| 1287 break; | |
| 1288 } | |
| 1279 case IceType_i1: | 1289 case IceType_i1: |
| 1280 case IceType_i8: | 1290 case IceType_i8: |
| 1281 case IceType_i16: | 1291 case IceType_i16: |
| 1282 case IceType_i32: { | 1292 case IceType_i32: { |
| 1283 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); | 1293 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); |
| 1284 Operand *Src0F = legalize(Src0, Legal_Reg); | 1294 Operand *Src0F = legalize(Src0, Legal_Reg); |
| 1285 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); | 1295 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); |
| 1286 _mov(Reg, Src0F); | 1296 _mov(Reg, Src0F); |
| 1287 break; | 1297 break; |
| 1288 } | 1298 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1396 if (getFlags().getDisableTranslation()) | 1406 if (getFlags().getDisableTranslation()) |
| 1397 return; | 1407 return; |
| 1398 UnimplementedError(getFlags()); | 1408 UnimplementedError(getFlags()); |
| 1399 } | 1409 } |
| 1400 | 1410 |
| 1401 // Helper for legalize() to emit the right code to lower an operand to a | 1411 // Helper for legalize() to emit the right code to lower an operand to a |
| 1402 // register of the appropriate type. | 1412 // register of the appropriate type. |
| 1403 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 1413 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
| 1404 Type Ty = Src->getType(); | 1414 Type Ty = Src->getType(); |
| 1405 Variable *Reg = makeReg(Ty, RegNum); | 1415 Variable *Reg = makeReg(Ty, RegNum); |
| 1406 if (isVectorType(Ty) || isFloatingType(Ty)) { | 1416 if (isVectorType(Ty)) { |
| 1417 UnimplementedError(getFlags()); | |
| 1418 } else if (isFloatingType(Ty)) { | |
| 1407 UnimplementedError(getFlags()); | 1419 UnimplementedError(getFlags()); |
| 1408 } else { | 1420 } else { |
| 1409 // Mov's Src operand can really only be the flexible second operand type | 1421 // Mov's Src operand can really only be the flexible second operand type |
| 1410 // or a register. Users should guarantee that. | 1422 // or a register. Users should guarantee that. |
| 1411 _mov(Reg, Src); | 1423 _mov(Reg, Src); |
| 1412 } | 1424 } |
| 1413 return Reg; | 1425 return Reg; |
| 1414 } | 1426 } |
| 1415 | 1427 |
| 1416 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, | 1428 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
| 1417 RegNumT RegNum) { | 1429 RegNumT RegNum) { |
| 1418 Type Ty = From->getType(); | 1430 Type Ty = From->getType(); |
| 1419 // Assert that a physical register is allowed. To date, all calls | 1431 // Assert that a physical register is allowed. To date, all calls |
| 1420 // to legalize() allow a physical register. Legal_Flex converts | 1432 // to legalize() allow a physical register. Legal_Flex converts |
| 1421 // registers to the right type OperandMIPS32FlexReg as needed. | 1433 // registers to the right type OperandMIPS32FlexReg as needed. |
| 1422 assert(Allowed & Legal_Reg); | 1434 assert(Allowed & Legal_Reg); |
| 1423 // Go through the various types of operands: | 1435 // Go through the various types of operands: |
| 1424 // OperandMIPS32Mem, Constant, and Variable. | 1436 // OperandMIPS32Mem, Constant, and Variable. |
| 1425 // Given the above assertion, if type of operand is not legal | 1437 // Given the above assertion, if type of operand is not legal |
| 1426 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy | 1438 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy |
| 1427 // to a register. | 1439 // to a register. |
| 1428 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 1440 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
| 1429 (void)C; | 1441 (void)C; |
| 1430 // TODO(reed kotler): complete this case for proper implementation | 1442 // TODO(reed kotler): complete this case for proper implementation |
| 1431 Variable *Reg = makeReg(Ty, RegNum); | 1443 Variable *Reg = makeReg(Ty, RegNum); |
| 1432 Context.insert<InstFakeDef>(Reg); | 1444 Context.insert<InstFakeDef>(Reg); |
| 1433 return Reg; | 1445 return Reg; |
| 1446 } else if (auto *C32 = llvm::dyn_cast<ConstantFloat>(From)) { | |
| 1447 const float Value = C32->getValue(); | |
| 1448 // Check if the immediate will fit in a Flexible second operand, | |
| 1449 // if a Flexible second operand is allowed. We need to know the exact | |
| 1450 // value, so that rules out relocatable constants. | |
| 1451 // Also try the inverse and use MVN if possible. | |
| 1452 // Do a movw/movt to a register. | |
| 1453 Variable *Reg; | |
| 1454 if (RegNum.hasValue()) | |
| 1455 Reg = getPhysicalRegister(RegNum); | |
|
Jim Stichnoth
2016/05/19 23:12:25
I'm very nervous about this use of getPhysicalRegi
obucinac
2016/05/27 11:13:18
We need to rework this to o32 convention. Leaving
| |
| 1456 else | |
| 1457 Reg = makeReg(Ty, RegNum); | |
| 1458 | |
| 1459 const uint32_t UIntValue = llvm::FloatToBits(Value); | |
| 1460 | |
| 1461 if (isInt<16>(int32_t(UIntValue))) { | |
| 1462 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); | |
| 1463 Context.insert<InstFakeDef>(Zero); | |
| 1464 _addiu(Reg, Zero, UIntValue); | |
| 1465 } else { | |
| 1466 uint32_t UpperBits = (UIntValue >> 16) & 0xFFFF; | |
| 1467 (void)UpperBits; | |
|
Jim Stichnoth
2016/05/19 23:12:25
Remove this
obucinac
2016/05/27 11:13:18
Done.
| |
| 1468 uint32_t LowerBits = UIntValue & 0xFFFF; | |
| 1469 Variable *TReg = makeReg(Ty, RegNum); | |
| 1470 _lui(TReg, UpperBits); | |
| 1471 _ori(Reg, TReg, LowerBits); | |
| 1472 } | |
| 1473 return Reg; | |
| 1434 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 1474 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 1435 const uint32_t Value = C32->getValue(); | 1475 const uint32_t Value = C32->getValue(); |
| 1436 // Check if the immediate will fit in a Flexible second operand, | 1476 // Check if the immediate will fit in a Flexible second operand, |
| 1437 // if a Flexible second operand is allowed. We need to know the exact | 1477 // if a Flexible second operand is allowed. We need to know the exact |
| 1438 // value, so that rules out relocatable constants. | 1478 // value, so that rules out relocatable constants. |
| 1439 // Also try the inverse and use MVN if possible. | 1479 // Also try the inverse and use MVN if possible. |
| 1440 // Do a movw/movt to a register. | 1480 // Do a movw/movt to a register. |
| 1441 Variable *Reg; | 1481 Variable *Reg; |
| 1442 if (RegNum.hasValue()) | 1482 if (RegNum.hasValue()) |
| 1443 Reg = getPhysicalRegister(RegNum); | 1483 Reg = getPhysicalRegister(RegNum); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1486 Str << "\t.set\t" | 1526 Str << "\t.set\t" |
| 1487 << "nomips16\n"; | 1527 << "nomips16\n"; |
| 1488 } | 1528 } |
| 1489 | 1529 |
| 1490 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1530 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 1491 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1531 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 1492 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1532 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 1493 | 1533 |
| 1494 } // end of namespace MIPS32 | 1534 } // end of namespace MIPS32 |
| 1495 } // end of namespace Ice | 1535 } // end of namespace Ice |
| OLD | NEW |