| 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 |