| 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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 const Instr kLdrStrOffsetMask = 0x00000fff; | 264 const Instr kLdrStrOffsetMask = 0x00000fff; |
| 265 | 265 |
| 266 | 266 |
| 267 // Spare buffer. | 267 // Spare buffer. |
| 268 static const int kMinimalBufferSize = 4*KB; | 268 static const int kMinimalBufferSize = 4*KB; |
| 269 static byte* spare_buffer_ = NULL; | 269 static byte* spare_buffer_ = NULL; |
| 270 | 270 |
| 271 | 271 |
| 272 Assembler::Assembler(void* buffer, int buffer_size) | 272 Assembler::Assembler(void* buffer, int buffer_size) |
| 273 : positions_recorder_(this), | 273 : positions_recorder_(this), |
| 274 allow_peephole_optimization_(false) { | 274 allow_peephole_optimization_(false), |
| 275 emit_debug_code_(FLAG_debug_code) { |
| 275 allow_peephole_optimization_ = FLAG_peephole_optimization; | 276 allow_peephole_optimization_ = FLAG_peephole_optimization; |
| 276 if (buffer == NULL) { | 277 if (buffer == NULL) { |
| 277 // Do our own buffer management. | 278 // Do our own buffer management. |
| 278 if (buffer_size <= kMinimalBufferSize) { | 279 if (buffer_size <= kMinimalBufferSize) { |
| 279 buffer_size = kMinimalBufferSize; | 280 buffer_size = kMinimalBufferSize; |
| 280 | 281 |
| 281 if (spare_buffer_ != NULL) { | 282 if (spare_buffer_ != NULL) { |
| 282 buffer = spare_buffer_; | 283 buffer = spare_buffer_; |
| 283 spare_buffer_ = NULL; | 284 spare_buffer_ = NULL; |
| 284 } | 285 } |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 } | 761 } |
| 761 #endif // def DEBUG | 762 #endif // def DEBUG |
| 762 return Serializer::enabled(); | 763 return Serializer::enabled(); |
| 763 } else if (rmode_ == RelocInfo::NONE) { | 764 } else if (rmode_ == RelocInfo::NONE) { |
| 764 return false; | 765 return false; |
| 765 } | 766 } |
| 766 return true; | 767 return true; |
| 767 } | 768 } |
| 768 | 769 |
| 769 | 770 |
| 770 bool Operand::is_single_instruction() const { | 771 bool Operand::is_single_instruction(Instr instr) const { |
| 771 if (rm_.is_valid()) return true; | 772 if (rm_.is_valid()) return true; |
| 772 if (must_use_constant_pool()) return false; | |
| 773 uint32_t dummy1, dummy2; | 773 uint32_t dummy1, dummy2; |
| 774 return fits_shifter(imm32_, &dummy1, &dummy2, NULL); | 774 if (must_use_constant_pool() || |
| 775 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { |
| 776 // The immediate operand cannot be encoded as a shifter operand, or use of |
| 777 // constant pool is required. For a mov instruction not setting the |
| 778 // condition code additional instruction conventions can be used. |
| 779 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set |
| 780 if (must_use_constant_pool() || !CpuFeatures::IsSupported(ARMv7)) { |
| 781 // mov instruction will be an ldr from constant pool (one instruction). |
| 782 return true; |
| 783 } else { |
| 784 // mov instruction will be a mov or movw followed by movt (two |
| 785 // instructions). |
| 786 return false; |
| 787 } |
| 788 } else { |
| 789 // If this is not a mov or mvn instruction there will always an additional |
| 790 // instructions - either mov or ldr. The mov might actually be two |
| 791 // instructions mov or movw followed by movt so including the actual |
| 792 // instruction two or three instructions will be generated. |
| 793 return false; |
| 794 } |
| 795 } else { |
| 796 // No use of constant pool and the immediate operand can be encoded as a |
| 797 // shifter operand. |
| 798 return true; |
| 799 } |
| 775 } | 800 } |
| 776 | 801 |
| 777 | 802 |
| 778 void Assembler::addrmod1(Instr instr, | 803 void Assembler::addrmod1(Instr instr, |
| 779 Register rn, | 804 Register rn, |
| 780 Register rd, | 805 Register rd, |
| 781 const Operand& x) { | 806 const Operand& x) { |
| 782 CheckBuffer(); | 807 CheckBuffer(); |
| 783 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); | 808 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); |
| 784 if (!x.rm_.is_valid()) { | 809 if (!x.rm_.is_valid()) { |
| (...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1841 // Ddst = MEM(Rbase + offset). | 1866 // Ddst = MEM(Rbase + offset). |
| 1842 // Instruction details available in ARM DDI 0406A, A8-628. | 1867 // Instruction details available in ARM DDI 0406A, A8-628. |
| 1843 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | | 1868 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | |
| 1844 // Vdst(15-12) | 1011(11-8) | offset | 1869 // Vdst(15-12) | 1011(11-8) | offset |
| 1845 ASSERT(CpuFeatures::IsEnabled(VFP3)); | 1870 ASSERT(CpuFeatures::IsEnabled(VFP3)); |
| 1846 int u = 1; | 1871 int u = 1; |
| 1847 if (offset < 0) { | 1872 if (offset < 0) { |
| 1848 offset = -offset; | 1873 offset = -offset; |
| 1849 u = 0; | 1874 u = 0; |
| 1850 } | 1875 } |
| 1851 ASSERT(offset % 4 == 0); | 1876 |
| 1852 ASSERT((offset / 4) < 256); | |
| 1853 ASSERT(offset >= 0); | 1877 ASSERT(offset >= 0); |
| 1854 emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | | 1878 if ((offset % 4) == 0 && (offset / 4) < 256) { |
| 1855 0xB*B8 | ((offset / 4) & 255)); | 1879 emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | |
| 1880 0xB*B8 | ((offset / 4) & 255)); |
| 1881 } else { |
| 1882 // Larger offsets must be handled by computing the correct address |
| 1883 // in the ip register. |
| 1884 ASSERT(!base.is(ip)); |
| 1885 if (u == 1) { |
| 1886 add(ip, base, Operand(offset)); |
| 1887 } else { |
| 1888 sub(ip, base, Operand(offset)); |
| 1889 } |
| 1890 emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8); |
| 1891 } |
| 1892 } |
| 1893 |
| 1894 |
| 1895 void Assembler::vldr(const DwVfpRegister dst, |
| 1896 const MemOperand& operand, |
| 1897 const Condition cond) { |
| 1898 ASSERT(!operand.rm().is_valid()); |
| 1899 ASSERT(operand.am_ == Offset); |
| 1900 vldr(dst, operand.rn(), operand.offset(), cond); |
| 1856 } | 1901 } |
| 1857 | 1902 |
| 1858 | 1903 |
| 1859 void Assembler::vldr(const SwVfpRegister dst, | 1904 void Assembler::vldr(const SwVfpRegister dst, |
| 1860 const Register base, | 1905 const Register base, |
| 1861 int offset, | 1906 int offset, |
| 1862 const Condition cond) { | 1907 const Condition cond) { |
| 1863 // Sdst = MEM(Rbase + offset). | 1908 // Sdst = MEM(Rbase + offset). |
| 1864 // Instruction details available in ARM DDI 0406A, A8-628. | 1909 // Instruction details available in ARM DDI 0406A, A8-628. |
| 1865 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | | 1910 // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | |
| 1866 // Vdst(15-12) | 1010(11-8) | offset | 1911 // Vdst(15-12) | 1010(11-8) | offset |
| 1867 ASSERT(CpuFeatures::IsEnabled(VFP3)); | 1912 ASSERT(CpuFeatures::IsEnabled(VFP3)); |
| 1868 int u = 1; | 1913 int u = 1; |
| 1869 if (offset < 0) { | 1914 if (offset < 0) { |
| 1870 offset = -offset; | 1915 offset = -offset; |
| 1871 u = 0; | 1916 u = 0; |
| 1872 } | 1917 } |
| 1873 ASSERT(offset % 4 == 0); | |
| 1874 ASSERT((offset / 4) < 256); | |
| 1875 ASSERT(offset >= 0); | |
| 1876 int sd, d; | 1918 int sd, d; |
| 1877 dst.split_code(&sd, &d); | 1919 dst.split_code(&sd, &d); |
| 1920 ASSERT(offset >= 0); |
| 1921 |
| 1922 if ((offset % 4) == 0 && (offset / 4) < 256) { |
| 1878 emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 | | 1923 emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 | |
| 1879 0xA*B8 | ((offset / 4) & 255)); | 1924 0xA*B8 | ((offset / 4) & 255)); |
| 1925 } else { |
| 1926 // Larger offsets must be handled by computing the correct address |
| 1927 // in the ip register. |
| 1928 ASSERT(!base.is(ip)); |
| 1929 if (u == 1) { |
| 1930 add(ip, base, Operand(offset)); |
| 1931 } else { |
| 1932 sub(ip, base, Operand(offset)); |
| 1933 } |
| 1934 emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); |
| 1935 } |
| 1936 } |
| 1937 |
| 1938 |
| 1939 void Assembler::vldr(const SwVfpRegister dst, |
| 1940 const MemOperand& operand, |
| 1941 const Condition cond) { |
| 1942 ASSERT(!operand.rm().is_valid()); |
| 1943 ASSERT(operand.am_ == Offset); |
| 1944 vldr(dst, operand.rn(), operand.offset(), cond); |
| 1880 } | 1945 } |
| 1881 | 1946 |
| 1882 | 1947 |
| 1883 void Assembler::vstr(const DwVfpRegister src, | 1948 void Assembler::vstr(const DwVfpRegister src, |
| 1884 const Register base, | 1949 const Register base, |
| 1885 int offset, | 1950 int offset, |
| 1886 const Condition cond) { | 1951 const Condition cond) { |
| 1887 // MEM(Rbase + offset) = Dsrc. | 1952 // MEM(Rbase + offset) = Dsrc. |
| 1888 // Instruction details available in ARM DDI 0406A, A8-786. | 1953 // Instruction details available in ARM DDI 0406A, A8-786. |
| 1889 // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) | | 1954 // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) | |
| 1890 // Vsrc(15-12) | 1011(11-8) | (offset/4) | 1955 // Vsrc(15-12) | 1011(11-8) | (offset/4) |
| 1891 ASSERT(CpuFeatures::IsEnabled(VFP3)); | 1956 ASSERT(CpuFeatures::IsEnabled(VFP3)); |
| 1892 int u = 1; | 1957 int u = 1; |
| 1893 if (offset < 0) { | 1958 if (offset < 0) { |
| 1894 offset = -offset; | 1959 offset = -offset; |
| 1895 u = 0; | 1960 u = 0; |
| 1896 } | 1961 } |
| 1897 ASSERT(offset % 4 == 0); | |
| 1898 ASSERT((offset / 4) < 256); | |
| 1899 ASSERT(offset >= 0); | 1962 ASSERT(offset >= 0); |
| 1900 emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | | 1963 if ((offset % 4) == 0 && (offset / 4) < 256) { |
| 1901 0xB*B8 | ((offset / 4) & 255)); | 1964 emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | |
| 1965 0xB*B8 | ((offset / 4) & 255)); |
| 1966 } else { |
| 1967 // Larger offsets must be handled by computing the correct address |
| 1968 // in the ip register. |
| 1969 ASSERT(!base.is(ip)); |
| 1970 if (u == 1) { |
| 1971 add(ip, base, Operand(offset)); |
| 1972 } else { |
| 1973 sub(ip, base, Operand(offset)); |
| 1974 } |
| 1975 emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8); |
| 1976 } |
| 1977 } |
| 1978 |
| 1979 |
| 1980 void Assembler::vstr(const DwVfpRegister src, |
| 1981 const MemOperand& operand, |
| 1982 const Condition cond) { |
| 1983 ASSERT(!operand.rm().is_valid()); |
| 1984 ASSERT(operand.am_ == Offset); |
| 1985 vstr(src, operand.rn(), operand.offset(), cond); |
| 1902 } | 1986 } |
| 1903 | 1987 |
| 1904 | 1988 |
| 1905 void Assembler::vstr(const SwVfpRegister src, | 1989 void Assembler::vstr(const SwVfpRegister src, |
| 1906 const Register base, | 1990 const Register base, |
| 1907 int offset, | 1991 int offset, |
| 1908 const Condition cond) { | 1992 const Condition cond) { |
| 1909 // MEM(Rbase + offset) = SSrc. | 1993 // MEM(Rbase + offset) = SSrc. |
| 1910 // Instruction details available in ARM DDI 0406A, A8-786. | 1994 // Instruction details available in ARM DDI 0406A, A8-786. |
| 1911 // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) | | 1995 // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) | |
| 1912 // Vdst(15-12) | 1010(11-8) | (offset/4) | 1996 // Vdst(15-12) | 1010(11-8) | (offset/4) |
| 1913 ASSERT(CpuFeatures::IsEnabled(VFP3)); | 1997 ASSERT(CpuFeatures::IsEnabled(VFP3)); |
| 1914 int u = 1; | 1998 int u = 1; |
| 1915 if (offset < 0) { | 1999 if (offset < 0) { |
| 1916 offset = -offset; | 2000 offset = -offset; |
| 1917 u = 0; | 2001 u = 0; |
| 1918 } | 2002 } |
| 1919 ASSERT(offset % 4 == 0); | |
| 1920 ASSERT((offset / 4) < 256); | |
| 1921 ASSERT(offset >= 0); | |
| 1922 int sd, d; | 2003 int sd, d; |
| 1923 src.split_code(&sd, &d); | 2004 src.split_code(&sd, &d); |
| 1924 emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | | 2005 ASSERT(offset >= 0); |
| 1925 0xA*B8 | ((offset / 4) & 255)); | 2006 if ((offset % 4) == 0 && (offset / 4) < 256) { |
| 2007 emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 | |
| 2008 0xA*B8 | ((offset / 4) & 255)); |
| 2009 } else { |
| 2010 // Larger offsets must be handled by computing the correct address |
| 2011 // in the ip register. |
| 2012 ASSERT(!base.is(ip)); |
| 2013 if (u == 1) { |
| 2014 add(ip, base, Operand(offset)); |
| 2015 } else { |
| 2016 sub(ip, base, Operand(offset)); |
| 2017 } |
| 2018 emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8); |
| 2019 } |
| 2020 } |
| 2021 |
| 2022 |
| 2023 void Assembler::vstr(const SwVfpRegister src, |
| 2024 const MemOperand& operand, |
| 2025 const Condition cond) { |
| 2026 ASSERT(!operand.rm().is_valid()); |
| 2027 ASSERT(operand.am_ == Offset); |
| 2028 vldr(src, operand.rn(), operand.offset(), cond); |
| 1926 } | 2029 } |
| 1927 | 2030 |
| 1928 | 2031 |
| 1929 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) { | 2032 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) { |
| 1930 uint64_t i; | 2033 uint64_t i; |
| 1931 memcpy(&i, &d, 8); | 2034 memcpy(&i, &d, 8); |
| 1932 | 2035 |
| 1933 *lo = i & 0xffffffff; | 2036 *lo = i & 0xffffffff; |
| 1934 *hi = i >> 32; | 2037 *hi = i >> 32; |
| 1935 } | 2038 } |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2275 | 2378 |
| 2276 void Assembler::vcvt_f32_f64(const SwVfpRegister dst, | 2379 void Assembler::vcvt_f32_f64(const SwVfpRegister dst, |
| 2277 const DwVfpRegister src, | 2380 const DwVfpRegister src, |
| 2278 VFPConversionMode mode, | 2381 VFPConversionMode mode, |
| 2279 const Condition cond) { | 2382 const Condition cond) { |
| 2280 ASSERT(CpuFeatures::IsEnabled(VFP3)); | 2383 ASSERT(CpuFeatures::IsEnabled(VFP3)); |
| 2281 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); | 2384 emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond)); |
| 2282 } | 2385 } |
| 2283 | 2386 |
| 2284 | 2387 |
| 2388 void Assembler::vneg(const DwVfpRegister dst, |
| 2389 const DwVfpRegister src, |
| 2390 const Condition cond) { |
| 2391 emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 | |
| 2392 0x5*B9 | B8 | B6 | src.code()); |
| 2393 } |
| 2394 |
| 2395 |
| 2285 void Assembler::vabs(const DwVfpRegister dst, | 2396 void Assembler::vabs(const DwVfpRegister dst, |
| 2286 const DwVfpRegister src, | 2397 const DwVfpRegister src, |
| 2287 const Condition cond) { | 2398 const Condition cond) { |
| 2288 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | | 2399 emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | |
| 2289 0x5*B9 | B8 | 0x3*B6 | src.code()); | 2400 0x5*B9 | B8 | 0x3*B6 | src.code()); |
| 2290 } | 2401 } |
| 2291 | 2402 |
| 2292 | 2403 |
| 2293 void Assembler::vadd(const DwVfpRegister dst, | 2404 void Assembler::vadd(const DwVfpRegister dst, |
| 2294 const DwVfpRegister src1, | 2405 const DwVfpRegister src1, |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2548 BlockConstPoolBefore(pc_offset() + kInstrSize); | 2659 BlockConstPoolBefore(pc_offset() + kInstrSize); |
| 2549 } | 2660 } |
| 2550 if (rinfo.rmode() != RelocInfo::NONE) { | 2661 if (rinfo.rmode() != RelocInfo::NONE) { |
| 2551 // Don't record external references unless the heap will be serialized. | 2662 // Don't record external references unless the heap will be serialized. |
| 2552 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { | 2663 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { |
| 2553 #ifdef DEBUG | 2664 #ifdef DEBUG |
| 2554 if (!Serializer::enabled()) { | 2665 if (!Serializer::enabled()) { |
| 2555 Serializer::TooLateToEnableNow(); | 2666 Serializer::TooLateToEnableNow(); |
| 2556 } | 2667 } |
| 2557 #endif | 2668 #endif |
| 2558 if (!Serializer::enabled() && !FLAG_debug_code) { | 2669 if (!Serializer::enabled() && !emit_debug_code()) { |
| 2559 return; | 2670 return; |
| 2560 } | 2671 } |
| 2561 } | 2672 } |
| 2562 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here | 2673 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here |
| 2563 reloc_info_writer.Write(&rinfo); | 2674 reloc_info_writer.Write(&rinfo); |
| 2564 } | 2675 } |
| 2565 } | 2676 } |
| 2566 | 2677 |
| 2567 | 2678 |
| 2568 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { | 2679 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2669 | 2780 |
| 2670 // Since a constant pool was just emitted, move the check offset forward by | 2781 // Since a constant pool was just emitted, move the check offset forward by |
| 2671 // the standard interval. | 2782 // the standard interval. |
| 2672 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2783 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 2673 } | 2784 } |
| 2674 | 2785 |
| 2675 | 2786 |
| 2676 } } // namespace v8::internal | 2787 } } // namespace v8::internal |
| 2677 | 2788 |
| 2678 #endif // V8_TARGET_ARCH_ARM | 2789 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |