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 |