| 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/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
| 10 #include "src/compiler/gap-resolver.h" | 10 #include "src/compiler/gap-resolver.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 UNREACHABLE(); | 142 UNREACHABLE(); |
| 143 return MemOperand(r0); | 143 return MemOperand(r0); |
| 144 } | 144 } |
| 145 | 145 |
| 146 MemOperand InputOffset(size_t first_index = 0) { | 146 MemOperand InputOffset(size_t first_index = 0) { |
| 147 return InputOffset(&first_index); | 147 return InputOffset(&first_index); |
| 148 } | 148 } |
| 149 | 149 |
| 150 MemOperand ToMemOperand(InstructionOperand* op) const { | 150 MemOperand ToMemOperand(InstructionOperand* op) const { |
| 151 DCHECK_NOT_NULL(op); | 151 DCHECK_NOT_NULL(op); |
| 152 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 152 DCHECK(op->IsStackSlot() || op->IsFPStackSlot()); |
| 153 return SlotToMemOperand(AllocatedOperand::cast(op)->index()); | 153 return SlotToMemOperand(AllocatedOperand::cast(op)->index()); |
| 154 } | 154 } |
| 155 | 155 |
| 156 MemOperand SlotToMemOperand(int slot) const { | 156 MemOperand SlotToMemOperand(int slot) const { |
| 157 FrameOffset offset = frame_access_state()->GetFrameOffset(slot); | 157 FrameOffset offset = frame_access_state()->GetFrameOffset(slot); |
| 158 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); | 158 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
| 159 } | 159 } |
| 160 }; | 160 }; |
| 161 | 161 |
| 162 | 162 |
| (...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 case kArmAsrPair: | 873 case kArmAsrPair: |
| 874 if (instr->InputAt(2)->IsImmediate()) { | 874 if (instr->InputAt(2)->IsImmediate()) { |
| 875 __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), | 875 __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), |
| 876 i.InputRegister(1), i.InputInt32(2)); | 876 i.InputRegister(1), i.InputInt32(2)); |
| 877 } else { | 877 } else { |
| 878 __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), | 878 __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), |
| 879 i.InputRegister(1), kScratchReg, i.InputRegister(2)); | 879 i.InputRegister(1), kScratchReg, i.InputRegister(2)); |
| 880 } | 880 } |
| 881 break; | 881 break; |
| 882 case kArmVcmpF32: | 882 case kArmVcmpF32: |
| 883 if (instr->InputAt(1)->IsDoubleRegister()) { | 883 if (instr->InputAt(1)->IsFPRegister()) { |
| 884 __ VFPCompareAndSetFlags(i.InputFloat32Register(0), | 884 __ VFPCompareAndSetFlags(i.InputFloat32Register(0), |
| 885 i.InputFloat32Register(1)); | 885 i.InputFloat32Register(1)); |
| 886 } else { | 886 } else { |
| 887 DCHECK(instr->InputAt(1)->IsImmediate()); | 887 DCHECK(instr->InputAt(1)->IsImmediate()); |
| 888 // 0.0 is the only immediate supported by vcmp instructions. | 888 // 0.0 is the only immediate supported by vcmp instructions. |
| 889 DCHECK(i.InputFloat32(1) == 0.0f); | 889 DCHECK(i.InputFloat32(1) == 0.0f); |
| 890 __ VFPCompareAndSetFlags(i.InputFloat32Register(0), i.InputFloat32(1)); | 890 __ VFPCompareAndSetFlags(i.InputFloat32Register(0), i.InputFloat32(1)); |
| 891 } | 891 } |
| 892 DCHECK_EQ(SetCC, i.OutputSBit()); | 892 DCHECK_EQ(SetCC, i.OutputSBit()); |
| 893 break; | 893 break; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 924 case kArmVsqrtF32: | 924 case kArmVsqrtF32: |
| 925 __ vsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0)); | 925 __ vsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
| 926 break; | 926 break; |
| 927 case kArmVabsF32: | 927 case kArmVabsF32: |
| 928 __ vabs(i.OutputFloat32Register(), i.InputFloat32Register(0)); | 928 __ vabs(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
| 929 break; | 929 break; |
| 930 case kArmVnegF32: | 930 case kArmVnegF32: |
| 931 __ vneg(i.OutputFloat32Register(), i.InputFloat32Register(0)); | 931 __ vneg(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
| 932 break; | 932 break; |
| 933 case kArmVcmpF64: | 933 case kArmVcmpF64: |
| 934 if (instr->InputAt(1)->IsDoubleRegister()) { | 934 if (instr->InputAt(1)->IsFPRegister()) { |
| 935 __ VFPCompareAndSetFlags(i.InputFloat64Register(0), | 935 __ VFPCompareAndSetFlags(i.InputFloat64Register(0), |
| 936 i.InputFloat64Register(1)); | 936 i.InputFloat64Register(1)); |
| 937 } else { | 937 } else { |
| 938 DCHECK(instr->InputAt(1)->IsImmediate()); | 938 DCHECK(instr->InputAt(1)->IsImmediate()); |
| 939 // 0.0 is the only immediate supported by vcmp instructions. | 939 // 0.0 is the only immediate supported by vcmp instructions. |
| 940 DCHECK(i.InputDouble(1) == 0.0); | 940 DCHECK(i.InputDouble(1) == 0.0); |
| 941 __ VFPCompareAndSetFlags(i.InputFloat64Register(0), i.InputDouble(1)); | 941 __ VFPCompareAndSetFlags(i.InputFloat64Register(0), i.InputDouble(1)); |
| 942 } | 942 } |
| 943 DCHECK_EQ(SetCC, i.OutputSBit()); | 943 DCHECK_EQ(SetCC, i.OutputSBit()); |
| 944 break; | 944 break; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 CpuFeatureScope scope(masm(), ARMv8); | 1204 CpuFeatureScope scope(masm(), ARMv8); |
| 1205 // (a < b) ? a : b | 1205 // (a < b) ? a : b |
| 1206 DwVfpRegister a = i.InputFloat64Register(0); | 1206 DwVfpRegister a = i.InputFloat64Register(0); |
| 1207 DwVfpRegister b = i.InputFloat64Register(1); | 1207 DwVfpRegister b = i.InputFloat64Register(1); |
| 1208 DwVfpRegister result = i.OutputFloat64Register(0); | 1208 DwVfpRegister result = i.OutputFloat64Register(0); |
| 1209 __ VFPCompareAndSetFlags(b, a); | 1209 __ VFPCompareAndSetFlags(b, a); |
| 1210 __ vsel(gt, result, a, b); | 1210 __ vsel(gt, result, a, b); |
| 1211 break; | 1211 break; |
| 1212 } | 1212 } |
| 1213 case kArmPush: | 1213 case kArmPush: |
| 1214 if (instr->InputAt(0)->IsDoubleRegister()) { | 1214 if (instr->InputAt(0)->IsFPRegister()) { |
| 1215 __ vpush(i.InputDoubleRegister(0)); | 1215 __ vpush(i.InputDoubleRegister(0)); |
| 1216 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); | 1216 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); |
| 1217 } else { | 1217 } else { |
| 1218 __ push(i.InputRegister(0)); | 1218 __ push(i.InputRegister(0)); |
| 1219 frame_access_state()->IncreaseSPDelta(1); | 1219 frame_access_state()->IncreaseSPDelta(1); |
| 1220 } | 1220 } |
| 1221 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 1221 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 1222 break; | 1222 break; |
| 1223 case kArmPoke: { | 1223 case kArmPoke: { |
| 1224 int const slot = MiscField::decode(instr->opcode()); | 1224 int const slot = MiscField::decode(instr->opcode()); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1553 __ Move(dst, src_object); | 1553 __ Move(dst, src_object); |
| 1554 } | 1554 } |
| 1555 break; | 1555 break; |
| 1556 } | 1556 } |
| 1557 case Constant::kRpoNumber: | 1557 case Constant::kRpoNumber: |
| 1558 UNREACHABLE(); // TODO(dcarney): loading RPO constants on arm. | 1558 UNREACHABLE(); // TODO(dcarney): loading RPO constants on arm. |
| 1559 break; | 1559 break; |
| 1560 } | 1560 } |
| 1561 if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination)); | 1561 if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination)); |
| 1562 } else if (src.type() == Constant::kFloat32) { | 1562 } else if (src.type() == Constant::kFloat32) { |
| 1563 if (destination->IsDoubleStackSlot()) { | 1563 if (destination->IsFPStackSlot()) { |
| 1564 MemOperand dst = g.ToMemOperand(destination); | 1564 MemOperand dst = g.ToMemOperand(destination); |
| 1565 __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32()))); | 1565 __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
| 1566 __ str(ip, dst); | 1566 __ str(ip, dst); |
| 1567 } else { | 1567 } else { |
| 1568 SwVfpRegister dst = g.ToFloat32Register(destination); | 1568 SwVfpRegister dst = g.ToFloat32Register(destination); |
| 1569 __ vmov(dst, src.ToFloat32()); | 1569 __ vmov(dst, src.ToFloat32()); |
| 1570 } | 1570 } |
| 1571 } else { | 1571 } else { |
| 1572 DCHECK_EQ(Constant::kFloat64, src.type()); | 1572 DCHECK_EQ(Constant::kFloat64, src.type()); |
| 1573 DwVfpRegister dst = destination->IsDoubleRegister() | 1573 DwVfpRegister dst = destination->IsFPRegister() |
| 1574 ? g.ToFloat64Register(destination) | 1574 ? g.ToFloat64Register(destination) |
| 1575 : kScratchDoubleReg; | 1575 : kScratchDoubleReg; |
| 1576 __ vmov(dst, src.ToFloat64(), kScratchReg); | 1576 __ vmov(dst, src.ToFloat64(), kScratchReg); |
| 1577 if (destination->IsDoubleStackSlot()) { | 1577 if (destination->IsFPStackSlot()) { |
| 1578 __ vstr(dst, g.ToMemOperand(destination)); | 1578 __ vstr(dst, g.ToMemOperand(destination)); |
| 1579 } | 1579 } |
| 1580 } | 1580 } |
| 1581 } else if (source->IsDoubleRegister()) { | 1581 } else if (source->IsFPRegister()) { |
| 1582 DwVfpRegister src = g.ToDoubleRegister(source); | 1582 DwVfpRegister src = g.ToDoubleRegister(source); |
| 1583 if (destination->IsDoubleRegister()) { | 1583 if (destination->IsFPRegister()) { |
| 1584 DwVfpRegister dst = g.ToDoubleRegister(destination); | 1584 DwVfpRegister dst = g.ToDoubleRegister(destination); |
| 1585 __ Move(dst, src); | 1585 __ Move(dst, src); |
| 1586 } else { | 1586 } else { |
| 1587 DCHECK(destination->IsDoubleStackSlot()); | 1587 DCHECK(destination->IsFPStackSlot()); |
| 1588 __ vstr(src, g.ToMemOperand(destination)); | 1588 __ vstr(src, g.ToMemOperand(destination)); |
| 1589 } | 1589 } |
| 1590 } else if (source->IsDoubleStackSlot()) { | 1590 } else if (source->IsFPStackSlot()) { |
| 1591 DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot()); | 1591 DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot()); |
| 1592 MemOperand src = g.ToMemOperand(source); | 1592 MemOperand src = g.ToMemOperand(source); |
| 1593 if (destination->IsDoubleRegister()) { | 1593 if (destination->IsFPRegister()) { |
| 1594 __ vldr(g.ToDoubleRegister(destination), src); | 1594 __ vldr(g.ToDoubleRegister(destination), src); |
| 1595 } else { | 1595 } else { |
| 1596 DwVfpRegister temp = kScratchDoubleReg; | 1596 DwVfpRegister temp = kScratchDoubleReg; |
| 1597 __ vldr(temp, src); | 1597 __ vldr(temp, src); |
| 1598 __ vstr(temp, g.ToMemOperand(destination)); | 1598 __ vstr(temp, g.ToMemOperand(destination)); |
| 1599 } | 1599 } |
| 1600 } else { | 1600 } else { |
| 1601 UNREACHABLE(); | 1601 UNREACHABLE(); |
| 1602 } | 1602 } |
| 1603 } | 1603 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1627 } else if (source->IsStackSlot()) { | 1627 } else if (source->IsStackSlot()) { |
| 1628 DCHECK(destination->IsStackSlot()); | 1628 DCHECK(destination->IsStackSlot()); |
| 1629 Register temp_0 = kScratchReg; | 1629 Register temp_0 = kScratchReg; |
| 1630 SwVfpRegister temp_1 = kScratchDoubleReg.low(); | 1630 SwVfpRegister temp_1 = kScratchDoubleReg.low(); |
| 1631 MemOperand src = g.ToMemOperand(source); | 1631 MemOperand src = g.ToMemOperand(source); |
| 1632 MemOperand dst = g.ToMemOperand(destination); | 1632 MemOperand dst = g.ToMemOperand(destination); |
| 1633 __ ldr(temp_0, src); | 1633 __ ldr(temp_0, src); |
| 1634 __ vldr(temp_1, dst); | 1634 __ vldr(temp_1, dst); |
| 1635 __ str(temp_0, dst); | 1635 __ str(temp_0, dst); |
| 1636 __ vstr(temp_1, src); | 1636 __ vstr(temp_1, src); |
| 1637 } else if (source->IsDoubleRegister()) { | 1637 } else if (source->IsFPRegister()) { |
| 1638 DwVfpRegister temp = kScratchDoubleReg; | 1638 DwVfpRegister temp = kScratchDoubleReg; |
| 1639 DwVfpRegister src = g.ToDoubleRegister(source); | 1639 DwVfpRegister src = g.ToDoubleRegister(source); |
| 1640 if (destination->IsDoubleRegister()) { | 1640 if (destination->IsFPRegister()) { |
| 1641 DwVfpRegister dst = g.ToDoubleRegister(destination); | 1641 DwVfpRegister dst = g.ToDoubleRegister(destination); |
| 1642 __ Move(temp, src); | 1642 __ Move(temp, src); |
| 1643 __ Move(src, dst); | 1643 __ Move(src, dst); |
| 1644 __ Move(dst, temp); | 1644 __ Move(dst, temp); |
| 1645 } else { | 1645 } else { |
| 1646 DCHECK(destination->IsDoubleStackSlot()); | 1646 DCHECK(destination->IsFPStackSlot()); |
| 1647 MemOperand dst = g.ToMemOperand(destination); | 1647 MemOperand dst = g.ToMemOperand(destination); |
| 1648 __ Move(temp, src); | 1648 __ Move(temp, src); |
| 1649 __ vldr(src, dst); | 1649 __ vldr(src, dst); |
| 1650 __ vstr(temp, dst); | 1650 __ vstr(temp, dst); |
| 1651 } | 1651 } |
| 1652 } else if (source->IsDoubleStackSlot()) { | 1652 } else if (source->IsFPStackSlot()) { |
| 1653 DCHECK(destination->IsDoubleStackSlot()); | 1653 DCHECK(destination->IsFPStackSlot()); |
| 1654 Register temp_0 = kScratchReg; | 1654 Register temp_0 = kScratchReg; |
| 1655 DwVfpRegister temp_1 = kScratchDoubleReg; | 1655 DwVfpRegister temp_1 = kScratchDoubleReg; |
| 1656 MemOperand src0 = g.ToMemOperand(source); | 1656 MemOperand src0 = g.ToMemOperand(source); |
| 1657 MemOperand src1(src0.rn(), src0.offset() + kPointerSize); | 1657 MemOperand src1(src0.rn(), src0.offset() + kPointerSize); |
| 1658 MemOperand dst0 = g.ToMemOperand(destination); | 1658 MemOperand dst0 = g.ToMemOperand(destination); |
| 1659 MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize); | 1659 MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize); |
| 1660 __ vldr(temp_1, dst0); // Save destination in temp_1. | 1660 __ vldr(temp_1, dst0); // Save destination in temp_1. |
| 1661 __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. | 1661 __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. |
| 1662 __ str(temp_0, dst0); | 1662 __ str(temp_0, dst0); |
| 1663 __ ldr(temp_0, src1); | 1663 __ ldr(temp_0, src1); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1695 padding_size -= v8::internal::Assembler::kInstrSize; | 1695 padding_size -= v8::internal::Assembler::kInstrSize; |
| 1696 } | 1696 } |
| 1697 } | 1697 } |
| 1698 } | 1698 } |
| 1699 | 1699 |
| 1700 #undef __ | 1700 #undef __ |
| 1701 | 1701 |
| 1702 } // namespace compiler | 1702 } // namespace compiler |
| 1703 } // namespace internal | 1703 } // namespace internal |
| 1704 } // namespace v8 | 1704 } // namespace v8 |
| OLD | NEW |