OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 } | 1263 } |
1264 #endif | 1264 #endif |
1265 __ ConvertDoubleToInt64(i.InputDoubleRegister(0), | 1265 __ ConvertDoubleToInt64(i.InputDoubleRegister(0), |
1266 #if !V8_TARGET_ARCH_PPC64 | 1266 #if !V8_TARGET_ARCH_PPC64 |
1267 kScratchReg, | 1267 kScratchReg, |
1268 #endif | 1268 #endif |
1269 i.OutputRegister(0), kScratchDoubleReg); | 1269 i.OutputRegister(0), kScratchDoubleReg); |
1270 #if V8_TARGET_ARCH_PPC64 | 1270 #if V8_TARGET_ARCH_PPC64 |
1271 if (check_conversion) { | 1271 if (check_conversion) { |
1272 // Set 2nd output to zero if conversion fails. | 1272 // Set 2nd output to zero if conversion fails. |
1273 CRBit crbit = static_cast<CRBit>(VXCVI % CRWIDTH); | 1273 CRegister cr = cr7; |
1274 __ mcrfs(cr7, VXCVI); // extract FPSCR field containing VXCVI into cr7 | 1274 int crbit = v8::internal::Assembler::encode_crbit( |
1275 __ li(i.OutputRegister(1), Operand(1)); | 1275 cr, static_cast<CRBit>(VXCVI % CRWIDTH)); |
1276 __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), | 1276 __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7 |
1277 v8::internal::Assembler::encode_crbit(cr7, crbit)); | 1277 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1278 __ li(i.OutputRegister(1), Operand(1)); |
| 1279 __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit); |
| 1280 } else { |
| 1281 __ li(i.OutputRegister(1), Operand::Zero()); |
| 1282 __ bc(v8::internal::Assembler::kInstrSize * 2, BT, crbit); |
| 1283 __ li(i.OutputRegister(1), Operand(1)); |
| 1284 } |
1278 } | 1285 } |
1279 #endif | 1286 #endif |
1280 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1287 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1281 break; | 1288 break; |
1282 } | 1289 } |
1283 #if V8_TARGET_ARCH_PPC64 | 1290 #if V8_TARGET_ARCH_PPC64 |
1284 case kPPC_DoubleToUint64: { | 1291 case kPPC_DoubleToUint64: { |
1285 bool check_conversion = (i.OutputCount() > 1); | 1292 bool check_conversion = (i.OutputCount() > 1); |
1286 if (check_conversion) { | 1293 if (check_conversion) { |
1287 __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit | 1294 __ mtfsb0(VXCVI); // clear FPSCR:VXCVI bit |
1288 } | 1295 } |
1289 __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0), | 1296 __ ConvertDoubleToUnsignedInt64(i.InputDoubleRegister(0), |
1290 i.OutputRegister(0), kScratchDoubleReg); | 1297 i.OutputRegister(0), kScratchDoubleReg); |
1291 if (check_conversion) { | 1298 if (check_conversion) { |
1292 // Set 2nd output to zero if conversion fails. | 1299 // Set 2nd output to zero if conversion fails. |
1293 CRBit crbit = static_cast<CRBit>(VXCVI % CRWIDTH); | 1300 CRegister cr = cr7; |
1294 __ mcrfs(cr7, VXCVI); // extract FPSCR field containing VXCVI into cr7 | 1301 int crbit = v8::internal::Assembler::encode_crbit( |
1295 __ li(i.OutputRegister(1), Operand(1)); | 1302 cr, static_cast<CRBit>(VXCVI % CRWIDTH)); |
1296 __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), | 1303 __ mcrfs(cr, VXCVI); // extract FPSCR field containing VXCVI into cr7 |
1297 v8::internal::Assembler::encode_crbit(cr7, crbit)); | 1304 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1305 __ li(i.OutputRegister(1), Operand(1)); |
| 1306 __ isel(i.OutputRegister(1), r0, i.OutputRegister(1), crbit); |
| 1307 } else { |
| 1308 __ li(i.OutputRegister(1), Operand::Zero()); |
| 1309 __ bc(v8::internal::Assembler::kInstrSize * 2, BT, crbit); |
| 1310 __ li(i.OutputRegister(1), Operand(1)); |
| 1311 } |
1298 } | 1312 } |
1299 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 1313 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
1300 break; | 1314 break; |
1301 } | 1315 } |
1302 #endif | 1316 #endif |
1303 case kPPC_DoubleToFloat32: | 1317 case kPPC_DoubleToFloat32: |
1304 ASSEMBLE_FLOAT_UNOP_RC(frsp); | 1318 ASSEMBLE_FLOAT_UNOP_RC(frsp); |
1305 break; | 1319 break; |
1306 case kPPC_Float32ToDouble: | 1320 case kPPC_Float32ToDouble: |
1307 // Nothing to do. | 1321 // Nothing to do. |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); | 1496 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); |
1483 } | 1497 } |
1484 | 1498 |
1485 | 1499 |
1486 // Assembles boolean materializations after an instruction. | 1500 // Assembles boolean materializations after an instruction. |
1487 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1501 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1488 FlagsCondition condition) { | 1502 FlagsCondition condition) { |
1489 PPCOperandConverter i(this, instr); | 1503 PPCOperandConverter i(this, instr); |
1490 Label done; | 1504 Label done; |
1491 ArchOpcode op = instr->arch_opcode(); | 1505 ArchOpcode op = instr->arch_opcode(); |
1492 bool check_unordered = (op == kPPC_CmpDouble); | |
1493 CRegister cr = cr0; | 1506 CRegister cr = cr0; |
| 1507 int reg_value = -1; |
1494 | 1508 |
1495 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 1509 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
1496 // last output of the instruction. | 1510 // last output of the instruction. |
1497 DCHECK_NE(0u, instr->OutputCount()); | 1511 DCHECK_NE(0u, instr->OutputCount()); |
1498 Register reg = i.OutputRegister(instr->OutputCount() - 1); | 1512 Register reg = i.OutputRegister(instr->OutputCount() - 1); |
1499 | 1513 |
1500 Condition cond = FlagsConditionToCondition(condition, op); | 1514 Condition cond = FlagsConditionToCondition(condition, op); |
1501 switch (cond) { | 1515 if (op == kPPC_CmpDouble) { |
1502 case eq: | 1516 // check for unordered if necessary |
1503 case lt: | 1517 if (cond == le) { |
| 1518 reg_value = 0; |
1504 __ li(reg, Operand::Zero()); | 1519 __ li(reg, Operand::Zero()); |
1505 __ li(kScratchReg, Operand(1)); | 1520 __ bunordered(&done, cr); |
1506 __ isel(cond, reg, kScratchReg, reg, cr); | 1521 } else if (cond == gt) { |
1507 break; | 1522 reg_value = 1; |
1508 case ne: | |
1509 case ge: | |
1510 __ li(reg, Operand(1)); | 1523 __ li(reg, Operand(1)); |
1511 __ isel(NegateCondition(cond), reg, r0, reg, cr); | 1524 __ bunordered(&done, cr); |
1512 break; | 1525 } |
1513 case gt: | 1526 // Unnecessary for eq/lt & ne/ge since only FU bit will be set. |
1514 if (check_unordered) { | 1527 } |
1515 __ li(reg, Operand(1)); | 1528 |
| 1529 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1530 switch (cond) { |
| 1531 case eq: |
| 1532 case lt: |
| 1533 case gt: |
| 1534 if (reg_value != 1) __ li(reg, Operand(1)); |
1516 __ li(kScratchReg, Operand::Zero()); | 1535 __ li(kScratchReg, Operand::Zero()); |
1517 __ bunordered(&done, cr); | |
1518 __ isel(cond, reg, reg, kScratchReg, cr); | 1536 __ isel(cond, reg, reg, kScratchReg, cr); |
1519 } else { | 1537 break; |
1520 __ li(reg, Operand::Zero()); | 1538 case ne: |
1521 __ li(kScratchReg, Operand(1)); | 1539 case ge: |
1522 __ isel(cond, reg, kScratchReg, reg, cr); | 1540 case le: |
1523 } | 1541 if (reg_value != 1) __ li(reg, Operand(1)); |
1524 break; | 1542 // r0 implies logical zero in this form |
1525 case le: | |
1526 if (check_unordered) { | |
1527 __ li(reg, Operand::Zero()); | |
1528 __ li(kScratchReg, Operand(1)); | |
1529 __ bunordered(&done, cr); | |
1530 __ isel(NegateCondition(cond), reg, r0, kScratchReg, cr); | |
1531 } else { | |
1532 __ li(reg, Operand(1)); | |
1533 __ isel(NegateCondition(cond), reg, r0, reg, cr); | 1543 __ isel(NegateCondition(cond), reg, r0, reg, cr); |
1534 } | 1544 break; |
1535 break; | |
1536 default: | 1545 default: |
1537 UNREACHABLE(); | 1546 UNREACHABLE(); |
1538 break; | 1547 break; |
| 1548 } |
| 1549 } else { |
| 1550 if (reg_value != 0) __ li(reg, Operand::Zero()); |
| 1551 __ b(NegateCondition(cond), &done, cr); |
| 1552 __ li(reg, Operand(1)); |
1539 } | 1553 } |
1540 __ bind(&done); | 1554 __ bind(&done); |
1541 } | 1555 } |
1542 | 1556 |
1543 | 1557 |
1544 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { | 1558 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
1545 PPCOperandConverter i(this, instr); | 1559 PPCOperandConverter i(this, instr); |
1546 Register input = i.InputRegister(0); | 1560 Register input = i.InputRegister(0); |
1547 for (size_t index = 2; index < instr->InputCount(); index += 2) { | 1561 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
1548 __ Cmpi(input, Operand(i.InputInt32(index + 0)), r0); | 1562 __ Cmpi(input, Operand(i.InputInt32(index + 0)), r0); |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 padding_size -= v8::internal::Assembler::kInstrSize; | 1906 padding_size -= v8::internal::Assembler::kInstrSize; |
1893 } | 1907 } |
1894 } | 1908 } |
1895 } | 1909 } |
1896 | 1910 |
1897 #undef __ | 1911 #undef __ |
1898 | 1912 |
1899 } // namespace compiler | 1913 } // namespace compiler |
1900 } // namespace internal | 1914 } // namespace internal |
1901 } // namespace v8 | 1915 } // namespace v8 |
OLD | NEW |