| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include "serialize.h" | 42 #include "serialize.h" |
| 43 | 43 |
| 44 namespace v8 { | 44 namespace v8 { |
| 45 namespace internal { | 45 namespace internal { |
| 46 | 46 |
| 47 #ifdef DEBUG | 47 #ifdef DEBUG |
| 48 bool CpuFeatures::initialized_ = false; | 48 bool CpuFeatures::initialized_ = false; |
| 49 #endif | 49 #endif |
| 50 unsigned CpuFeatures::supported_ = 0; | 50 unsigned CpuFeatures::supported_ = 0; |
| 51 unsigned CpuFeatures::found_by_runtime_probing_only_ = 0; | 51 unsigned CpuFeatures::found_by_runtime_probing_only_ = 0; |
| 52 unsigned CpuFeatures::cache_line_size_ = 64; |
| 52 | 53 |
| 53 | 54 |
| 54 ExternalReference ExternalReference::cpu_features() { | 55 ExternalReference ExternalReference::cpu_features() { |
| 55 ASSERT(CpuFeatures::initialized_); | 56 ASSERT(CpuFeatures::initialized_); |
| 56 return ExternalReference(&CpuFeatures::supported_); | 57 return ExternalReference(&CpuFeatures::supported_); |
| 57 } | 58 } |
| 58 | 59 |
| 59 | 60 |
| 60 // Get the CPU features enabled by the build. For cross compilation the | 61 // Get the CPU features enabled by the build. For cross compilation the |
| 61 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS | 62 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 } | 119 } |
| 119 | 120 |
| 120 #ifndef __arm__ | 121 #ifndef __arm__ |
| 121 // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is | 122 // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is |
| 122 // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6. | 123 // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6. |
| 123 if (FLAG_enable_vfp3) { | 124 if (FLAG_enable_vfp3) { |
| 124 supported_ |= | 125 supported_ |= |
| 125 static_cast<uint64_t>(1) << VFP3 | | 126 static_cast<uint64_t>(1) << VFP3 | |
| 126 static_cast<uint64_t>(1) << ARMv7; | 127 static_cast<uint64_t>(1) << ARMv7; |
| 127 } | 128 } |
| 129 if (FLAG_enable_neon) { |
| 130 supported_ |= 1u << NEON; |
| 131 } |
| 128 // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled | 132 // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled |
| 129 if (FLAG_enable_armv7) { | 133 if (FLAG_enable_armv7) { |
| 130 supported_ |= static_cast<uint64_t>(1) << ARMv7; | 134 supported_ |= static_cast<uint64_t>(1) << ARMv7; |
| 131 } | 135 } |
| 132 | 136 |
| 133 if (FLAG_enable_sudiv) { | 137 if (FLAG_enable_sudiv) { |
| 134 supported_ |= static_cast<uint64_t>(1) << SUDIV; | 138 supported_ |= static_cast<uint64_t>(1) << SUDIV; |
| 135 } | 139 } |
| 136 | 140 |
| 137 if (FLAG_enable_movw_movt) { | 141 if (FLAG_enable_movw_movt) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 150 // Probe for additional features not already known to be available. | 154 // Probe for additional features not already known to be available. |
| 151 if (!IsSupported(VFP3) && FLAG_enable_vfp3 && OS::ArmCpuHasFeature(VFP3)) { | 155 if (!IsSupported(VFP3) && FLAG_enable_vfp3 && OS::ArmCpuHasFeature(VFP3)) { |
| 152 // This implementation also sets the VFP flags if runtime | 156 // This implementation also sets the VFP flags if runtime |
| 153 // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI | 157 // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI |
| 154 // 0406B, page A1-6. | 158 // 0406B, page A1-6. |
| 155 found_by_runtime_probing_only_ |= | 159 found_by_runtime_probing_only_ |= |
| 156 static_cast<uint64_t>(1) << VFP3 | | 160 static_cast<uint64_t>(1) << VFP3 | |
| 157 static_cast<uint64_t>(1) << ARMv7; | 161 static_cast<uint64_t>(1) << ARMv7; |
| 158 } | 162 } |
| 159 | 163 |
| 164 if (!IsSupported(NEON) && FLAG_enable_neon && OS::ArmCpuHasFeature(NEON)) { |
| 165 found_by_runtime_probing_only_ |= 1u << NEON; |
| 166 } |
| 167 |
| 160 if (!IsSupported(ARMv7) && FLAG_enable_armv7 && OS::ArmCpuHasFeature(ARMv7)) { | 168 if (!IsSupported(ARMv7) && FLAG_enable_armv7 && OS::ArmCpuHasFeature(ARMv7)) { |
| 161 found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << ARMv7; | 169 found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << ARMv7; |
| 162 } | 170 } |
| 163 | 171 |
| 164 if (!IsSupported(SUDIV) && FLAG_enable_sudiv && OS::ArmCpuHasFeature(SUDIV)) { | 172 if (!IsSupported(SUDIV) && FLAG_enable_sudiv && OS::ArmCpuHasFeature(SUDIV)) { |
| 165 found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << SUDIV; | 173 found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << SUDIV; |
| 166 } | 174 } |
| 167 | 175 |
| 168 if (!IsSupported(UNALIGNED_ACCESSES) && FLAG_enable_unaligned_accesses | 176 if (!IsSupported(UNALIGNED_ACCESSES) && FLAG_enable_unaligned_accesses |
| 169 && OS::ArmCpuHasFeature(ARMv7)) { | 177 && OS::ArmCpuHasFeature(ARMv7)) { |
| 170 found_by_runtime_probing_only_ |= | 178 found_by_runtime_probing_only_ |= |
| 171 static_cast<uint64_t>(1) << UNALIGNED_ACCESSES; | 179 static_cast<uint64_t>(1) << UNALIGNED_ACCESSES; |
| 172 } | 180 } |
| 173 | 181 |
| 174 if (OS::GetCpuImplementer() == QUALCOMM_IMPLEMENTER && | 182 CpuImplementer implementer = OS::GetCpuImplementer(); |
| 183 if (implementer == QUALCOMM_IMPLEMENTER && |
| 175 FLAG_enable_movw_movt && OS::ArmCpuHasFeature(ARMv7)) { | 184 FLAG_enable_movw_movt && OS::ArmCpuHasFeature(ARMv7)) { |
| 176 found_by_runtime_probing_only_ |= | 185 found_by_runtime_probing_only_ |= |
| 177 static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS; | 186 static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS; |
| 178 } | 187 } |
| 179 | 188 |
| 189 CpuPart part = OS::GetCpuPart(implementer); |
| 190 if ((part == CORTEX_A9) || (part == CORTEX_A5)) { |
| 191 cache_line_size_ = 32; |
| 192 } |
| 193 |
| 180 if (!IsSupported(VFP32DREGS) && FLAG_enable_32dregs | 194 if (!IsSupported(VFP32DREGS) && FLAG_enable_32dregs |
| 181 && OS::ArmCpuHasFeature(VFP32DREGS)) { | 195 && OS::ArmCpuHasFeature(VFP32DREGS)) { |
| 182 found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP32DREGS; | 196 found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP32DREGS; |
| 183 } | 197 } |
| 184 | 198 |
| 185 supported_ |= found_by_runtime_probing_only_; | 199 supported_ |= found_by_runtime_probing_only_; |
| 186 #endif | 200 #endif |
| 187 | 201 |
| 188 // Assert that VFP3 implies ARMv7. | 202 // Assert that VFP3 implies ARMv7. |
| 189 ASSERT(!IsSupported(VFP3) || IsSupported(ARMv7)); | 203 ASSERT(!IsSupported(VFP3) || IsSupported(ARMv7)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 254 |
| 241 #endif // __arm__ | 255 #endif // __arm__ |
| 242 | 256 |
| 243 printf("target%s %s%s%s %s\n", | 257 printf("target%s %s%s%s %s\n", |
| 244 arm_test, arm_arch, arm_fpu, arm_thumb, arm_float_abi); | 258 arm_test, arm_arch, arm_fpu, arm_thumb, arm_float_abi); |
| 245 } | 259 } |
| 246 | 260 |
| 247 | 261 |
| 248 void CpuFeatures::PrintFeatures() { | 262 void CpuFeatures::PrintFeatures() { |
| 249 printf( | 263 printf( |
| 250 "ARMv7=%d VFP3=%d VFP32DREGS=%d SUDIV=%d UNALIGNED_ACCESSES=%d " | 264 "ARMv7=%d VFP3=%d VFP32DREGS=%d NEON=%d SUDIV=%d UNALIGNED_ACCESSES=%d " |
| 251 "MOVW_MOVT_IMMEDIATE_LOADS=%d", | 265 "MOVW_MOVT_IMMEDIATE_LOADS=%d", |
| 252 CpuFeatures::IsSupported(ARMv7), | 266 CpuFeatures::IsSupported(ARMv7), |
| 253 CpuFeatures::IsSupported(VFP3), | 267 CpuFeatures::IsSupported(VFP3), |
| 254 CpuFeatures::IsSupported(VFP32DREGS), | 268 CpuFeatures::IsSupported(VFP32DREGS), |
| 269 CpuFeatures::IsSupported(NEON), |
| 255 CpuFeatures::IsSupported(SUDIV), | 270 CpuFeatures::IsSupported(SUDIV), |
| 256 CpuFeatures::IsSupported(UNALIGNED_ACCESSES), | 271 CpuFeatures::IsSupported(UNALIGNED_ACCESSES), |
| 257 CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS)); | 272 CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS)); |
| 258 #ifdef __arm__ | 273 #ifdef __arm__ |
| 259 bool eabi_hardfloat = OS::ArmUsingHardFloat(); | 274 bool eabi_hardfloat = OS::ArmUsingHardFloat(); |
| 260 #elif USE_EABI_HARDFLOAT | 275 #elif USE_EABI_HARDFLOAT |
| 261 bool eabi_hardfloat = true; | 276 bool eabi_hardfloat = true; |
| 262 #else | 277 #else |
| 263 bool eabi_hardfloat = false; | 278 bool eabi_hardfloat = false; |
| 264 #endif | 279 #endif |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 ShiftOp shift_op, int shift_imm, AddrMode am) { | 386 ShiftOp shift_op, int shift_imm, AddrMode am) { |
| 372 ASSERT(is_uint5(shift_imm)); | 387 ASSERT(is_uint5(shift_imm)); |
| 373 rn_ = rn; | 388 rn_ = rn; |
| 374 rm_ = rm; | 389 rm_ = rm; |
| 375 shift_op_ = shift_op; | 390 shift_op_ = shift_op; |
| 376 shift_imm_ = shift_imm & 31; | 391 shift_imm_ = shift_imm & 31; |
| 377 am_ = am; | 392 am_ = am; |
| 378 } | 393 } |
| 379 | 394 |
| 380 | 395 |
| 396 NeonMemOperand::NeonMemOperand(Register rn, AddrMode am, int align) { |
| 397 ASSERT((am == Offset) || (am == PostIndex)); |
| 398 rn_ = rn; |
| 399 rm_ = (am == Offset) ? pc : sp; |
| 400 SetAlignment(align); |
| 401 } |
| 402 |
| 403 |
| 404 NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) { |
| 405 rn_ = rn; |
| 406 rm_ = rm; |
| 407 SetAlignment(align); |
| 408 } |
| 409 |
| 410 |
| 411 void NeonMemOperand::SetAlignment(int align) { |
| 412 switch (align) { |
| 413 case 0: |
| 414 align_ = 0; |
| 415 break; |
| 416 case 64: |
| 417 align_ = 1; |
| 418 break; |
| 419 case 128: |
| 420 align_ = 2; |
| 421 break; |
| 422 case 256: |
| 423 align_ = 3; |
| 424 break; |
| 425 default: |
| 426 UNREACHABLE(); |
| 427 align_ = 0; |
| 428 break; |
| 429 } |
| 430 } |
| 431 |
| 432 |
| 433 NeonListOperand::NeonListOperand(DoubleRegister base, int registers_count) { |
| 434 base_ = base; |
| 435 switch (registers_count) { |
| 436 case 1: |
| 437 type_ = nlt_1; |
| 438 break; |
| 439 case 2: |
| 440 type_ = nlt_2; |
| 441 break; |
| 442 case 3: |
| 443 type_ = nlt_3; |
| 444 break; |
| 445 case 4: |
| 446 type_ = nlt_4; |
| 447 break; |
| 448 default: |
| 449 UNREACHABLE(); |
| 450 type_ = nlt_1; |
| 451 break; |
| 452 } |
| 453 } |
| 454 |
| 455 |
| 381 // ----------------------------------------------------------------------------- | 456 // ----------------------------------------------------------------------------- |
| 382 // Specific instructions, constants, and masks. | 457 // Specific instructions, constants, and masks. |
| 383 | 458 |
| 384 // add(sp, sp, 4) instruction (aka Pop()) | 459 // add(sp, sp, 4) instruction (aka Pop()) |
| 385 const Instr kPopInstruction = | 460 const Instr kPopInstruction = |
| 386 al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 | | 461 al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 | |
| 387 kRegister_sp_Code * B12; | 462 kRegister_sp_Code * B12; |
| 388 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) | 463 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) |
| 389 // register r is not encoded. | 464 // register r is not encoded. |
| 390 const Instr kPushRegPattern = | 465 const Instr kPushRegPattern = |
| (...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1614 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
| 1540 ASSERT(!dst.is(pc) && !src.is(pc)); | 1615 ASSERT(!dst.is(pc) && !src.is(pc)); |
| 1541 ASSERT((lsb >= 0) && (lsb <= 31)); | 1616 ASSERT((lsb >= 0) && (lsb <= 31)); |
| 1542 ASSERT((width >= 1) && (width <= (32 - lsb))); | 1617 ASSERT((width >= 1) && (width <= (32 - lsb))); |
| 1543 int msb = lsb + width - 1; | 1618 int msb = lsb + width - 1; |
| 1544 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | | 1619 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | |
| 1545 src.code()); | 1620 src.code()); |
| 1546 } | 1621 } |
| 1547 | 1622 |
| 1548 | 1623 |
| 1624 void Assembler::pkhbt(Register dst, |
| 1625 Register src1, |
| 1626 const Operand& src2, |
| 1627 Condition cond ) { |
| 1628 // Instruction details available in ARM DDI 0406C.b, A8.8.125. |
| 1629 // cond(31-28) | 01101000(27-20) | Rn(19-16) | |
| 1630 // Rd(15-12) | imm5(11-7) | 0(6) | 01(5-4) | Rm(3-0) |
| 1631 ASSERT(!dst.is(pc)); |
| 1632 ASSERT(!src1.is(pc)); |
| 1633 ASSERT(!src2.rm().is(pc)); |
| 1634 ASSERT(!src2.rm().is(no_reg)); |
| 1635 ASSERT(src2.rs().is(no_reg)); |
| 1636 ASSERT((src2.shift_imm_ >= 0) && (src2.shift_imm_ <= 31)); |
| 1637 ASSERT(src2.shift_op() == LSL); |
| 1638 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 | |
| 1639 src2.shift_imm_*B7 | B4 | src2.rm().code()); |
| 1640 } |
| 1641 |
| 1642 |
| 1643 void Assembler::pkhtb(Register dst, |
| 1644 Register src1, |
| 1645 const Operand& src2, |
| 1646 Condition cond) { |
| 1647 // Instruction details available in ARM DDI 0406C.b, A8.8.125. |
| 1648 // cond(31-28) | 01101000(27-20) | Rn(19-16) | |
| 1649 // Rd(15-12) | imm5(11-7) | 1(6) | 01(5-4) | Rm(3-0) |
| 1650 ASSERT(!dst.is(pc)); |
| 1651 ASSERT(!src1.is(pc)); |
| 1652 ASSERT(!src2.rm().is(pc)); |
| 1653 ASSERT(!src2.rm().is(no_reg)); |
| 1654 ASSERT(src2.rs().is(no_reg)); |
| 1655 ASSERT((src2.shift_imm_ >= 1) && (src2.shift_imm_ <= 32)); |
| 1656 ASSERT(src2.shift_op() == ASR); |
| 1657 int asr = (src2.shift_imm_ == 32) ? 0 : src2.shift_imm_; |
| 1658 emit(cond | 0x68*B20 | src1.code()*B16 | dst.code()*B12 | |
| 1659 asr*B7 | B6 | B4 | src2.rm().code()); |
| 1660 } |
| 1661 |
| 1662 |
| 1663 void Assembler::uxtb(Register dst, |
| 1664 const Operand& src, |
| 1665 Condition cond) { |
| 1666 // Instruction details available in ARM DDI 0406C.b, A8.8.274. |
| 1667 // cond(31-28) | 01101110(27-20) | 1111(19-16) | |
| 1668 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) |
| 1669 ASSERT(!dst.is(pc)); |
| 1670 ASSERT(!src.rm().is(pc)); |
| 1671 ASSERT(!src.rm().is(no_reg)); |
| 1672 ASSERT(src.rs().is(no_reg)); |
| 1673 ASSERT((src.shift_imm_ == 0) || |
| 1674 (src.shift_imm_ == 8) || |
| 1675 (src.shift_imm_ == 16) || |
| 1676 (src.shift_imm_ == 24)); |
| 1677 ASSERT(src.shift_op() == ROR); |
| 1678 emit(cond | 0x6E*B20 | 0xF*B16 | dst.code()*B12 | |
| 1679 ((src.shift_imm_ >> 1)&0xC)*B8 | 7*B4 | src.rm().code()); |
| 1680 } |
| 1681 |
| 1682 |
| 1683 void Assembler::uxtab(Register dst, |
| 1684 Register src1, |
| 1685 const Operand& src2, |
| 1686 Condition cond) { |
| 1687 // Instruction details available in ARM DDI 0406C.b, A8.8.271. |
| 1688 // cond(31-28) | 01101110(27-20) | Rn(19-16) | |
| 1689 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) |
| 1690 ASSERT(!dst.is(pc)); |
| 1691 ASSERT(!src1.is(pc)); |
| 1692 ASSERT(!src2.rm().is(pc)); |
| 1693 ASSERT(!src2.rm().is(no_reg)); |
| 1694 ASSERT(src2.rs().is(no_reg)); |
| 1695 ASSERT((src2.shift_imm_ == 0) || |
| 1696 (src2.shift_imm_ == 8) || |
| 1697 (src2.shift_imm_ == 16) || |
| 1698 (src2.shift_imm_ == 24)); |
| 1699 ASSERT(src2.shift_op() == ROR); |
| 1700 emit(cond | 0x6E*B20 | src1.code()*B16 | dst.code()*B12 | |
| 1701 ((src2.shift_imm_ >> 1) &0xC)*B8 | 7*B4 | src2.rm().code()); |
| 1702 } |
| 1703 |
| 1704 |
| 1705 void Assembler::uxtb16(Register dst, |
| 1706 const Operand& src, |
| 1707 Condition cond) { |
| 1708 // Instruction details available in ARM DDI 0406C.b, A8.8.275. |
| 1709 // cond(31-28) | 01101100(27-20) | 1111(19-16) | |
| 1710 // Rd(15-12) | rotate(11-10) | 00(9-8)| 0111(7-4) | Rm(3-0) |
| 1711 ASSERT(!dst.is(pc)); |
| 1712 ASSERT(!src.rm().is(pc)); |
| 1713 ASSERT(!src.rm().is(no_reg)); |
| 1714 ASSERT(src.rs().is(no_reg)); |
| 1715 ASSERT((src.shift_imm_ == 0) || |
| 1716 (src.shift_imm_ == 8) || |
| 1717 (src.shift_imm_ == 16) || |
| 1718 (src.shift_imm_ == 24)); |
| 1719 ASSERT(src.shift_op() == ROR); |
| 1720 emit(cond | 0x6C*B20 | 0xF*B16 | dst.code()*B12 | |
| 1721 ((src.shift_imm_ >> 1)&0xC)*B8 | 7*B4 | src.rm().code()); |
| 1722 } |
| 1723 |
| 1724 |
| 1549 // Status register access instructions. | 1725 // Status register access instructions. |
| 1550 void Assembler::mrs(Register dst, SRegister s, Condition cond) { | 1726 void Assembler::mrs(Register dst, SRegister s, Condition cond) { |
| 1551 ASSERT(!dst.is(pc)); | 1727 ASSERT(!dst.is(pc)); |
| 1552 emit(cond | B24 | s | 15*B16 | dst.code()*B12); | 1728 emit(cond | B24 | s | 15*B16 | dst.code()*B12); |
| 1553 } | 1729 } |
| 1554 | 1730 |
| 1555 | 1731 |
| 1556 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, | 1732 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, |
| 1557 Condition cond) { | 1733 Condition cond) { |
| 1558 ASSERT(fields >= B16 && fields < B20); // at least one field set | 1734 ASSERT(fields >= B16 && fields < B20); // at least one field set |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1637 const MemOperand& dst, Condition cond) { | 1813 const MemOperand& dst, Condition cond) { |
| 1638 ASSERT(dst.rm().is(no_reg)); | 1814 ASSERT(dst.rm().is(no_reg)); |
| 1639 ASSERT(!src1.is(lr)); // r14. | 1815 ASSERT(!src1.is(lr)); // r14. |
| 1640 ASSERT_EQ(0, src1.code() % 2); | 1816 ASSERT_EQ(0, src1.code() % 2); |
| 1641 ASSERT_EQ(src1.code() + 1, src2.code()); | 1817 ASSERT_EQ(src1.code() + 1, src2.code()); |
| 1642 ASSERT(IsEnabled(ARMv7)); | 1818 ASSERT(IsEnabled(ARMv7)); |
| 1643 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); | 1819 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); |
| 1644 } | 1820 } |
| 1645 | 1821 |
| 1646 | 1822 |
| 1823 // Preload instructions. |
| 1824 void Assembler::pld(const MemOperand& address) { |
| 1825 // Instruction details available in ARM DDI 0406C.b, A8.8.128. |
| 1826 // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) | |
| 1827 // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) | |
| 1828 ASSERT(address.rm().is(no_reg)); |
| 1829 ASSERT(address.am() == Offset); |
| 1830 int U = B23; |
| 1831 int offset = address.offset(); |
| 1832 if (offset < 0) { |
| 1833 offset = -offset; |
| 1834 U = 0; |
| 1835 } |
| 1836 ASSERT(offset < 4096); |
| 1837 emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 | |
| 1838 0xf*B12 | offset); |
| 1839 } |
| 1840 |
| 1841 |
| 1647 // Load/Store multiple instructions. | 1842 // Load/Store multiple instructions. |
| 1648 void Assembler::ldm(BlockAddrMode am, | 1843 void Assembler::ldm(BlockAddrMode am, |
| 1649 Register base, | 1844 Register base, |
| 1650 RegList dst, | 1845 RegList dst, |
| 1651 Condition cond) { | 1846 Condition cond) { |
| 1652 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. | 1847 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. |
| 1653 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); | 1848 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); |
| 1654 | 1849 |
| 1655 addrmod4(cond | B27 | am | L, base, dst); | 1850 addrmod4(cond | B27 | am | L, base, dst); |
| 1656 | 1851 |
| (...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2700 // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) | 2895 // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) |
| 2701 int vd, d; | 2896 int vd, d; |
| 2702 dst.split_code(&vd, &d); | 2897 dst.split_code(&vd, &d); |
| 2703 int vm, m; | 2898 int vm, m; |
| 2704 src.split_code(&vm, &m); | 2899 src.split_code(&vm, &m); |
| 2705 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | | 2900 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | |
| 2706 m*B5 | vm); | 2901 m*B5 | vm); |
| 2707 } | 2902 } |
| 2708 | 2903 |
| 2709 | 2904 |
| 2905 // Support for NEON. |
| 2906 |
| 2907 void Assembler::vld1(NeonSize size, |
| 2908 const NeonListOperand& dst, |
| 2909 const NeonMemOperand& src) { |
| 2910 // Instruction details available in ARM DDI 0406C.b, A8.8.320. |
| 2911 // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) | |
| 2912 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0) |
| 2913 ASSERT(CpuFeatures::IsSupported(NEON)); |
| 2914 int vd, d; |
| 2915 dst.base().split_code(&vd, &d); |
| 2916 emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 | |
| 2917 dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code()); |
| 2918 } |
| 2919 |
| 2920 |
| 2921 void Assembler::vst1(NeonSize size, |
| 2922 const NeonListOperand& src, |
| 2923 const NeonMemOperand& dst) { |
| 2924 // Instruction details available in ARM DDI 0406C.b, A8.8.404. |
| 2925 // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) | |
| 2926 // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0) |
| 2927 ASSERT(CpuFeatures::IsSupported(NEON)); |
| 2928 int vd, d; |
| 2929 src.base().split_code(&vd, &d); |
| 2930 emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 | |
| 2931 size*B6 | dst.align()*B4 | dst.rm().code()); |
| 2932 } |
| 2933 |
| 2934 |
| 2935 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) { |
| 2936 // Instruction details available in ARM DDI 0406C.b, A8.8.346. |
| 2937 // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) | |
| 2938 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) |
| 2939 ASSERT(CpuFeatures::IsSupported(NEON)); |
| 2940 int vd, d; |
| 2941 dst.split_code(&vd, &d); |
| 2942 int vm, m; |
| 2943 src.split_code(&vm, &m); |
| 2944 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 | |
| 2945 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm); |
| 2946 } |
| 2947 |
| 2948 |
| 2710 // Pseudo instructions. | 2949 // Pseudo instructions. |
| 2711 void Assembler::nop(int type) { | 2950 void Assembler::nop(int type) { |
| 2712 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes | 2951 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes |
| 2713 // some of the CPU's pipeline and has to issue. Older ARM chips simply used | 2952 // some of the CPU's pipeline and has to issue. Older ARM chips simply used |
| 2714 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. | 2953 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. |
| 2715 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode | 2954 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode |
| 2716 // a type. | 2955 // a type. |
| 2717 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. | 2956 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. |
| 2718 emit(al | 13*B21 | type*B12 | type); | 2957 emit(al | 13*B21 | type*B12 | type); |
| 2719 } | 2958 } |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3110 | 3349 |
| 3111 // Since a constant pool was just emitted, move the check offset forward by | 3350 // Since a constant pool was just emitted, move the check offset forward by |
| 3112 // the standard interval. | 3351 // the standard interval. |
| 3113 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 3352 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
| 3114 } | 3353 } |
| 3115 | 3354 |
| 3116 | 3355 |
| 3117 } } // namespace v8::internal | 3356 } } // namespace v8::internal |
| 3118 | 3357 |
| 3119 #endif // V8_TARGET_ARCH_ARM | 3358 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |