Chromium Code Reviews| 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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 al | B26 | 4 | NegPreIndex | sp.code() * B16; | 256 al | B26 | 4 | NegPreIndex | sp.code() * B16; |
| 257 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) | 257 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) |
| 258 // register r is not encoded. | 258 // register r is not encoded. |
| 259 static const Instr kPopRegPattern = | 259 static const Instr kPopRegPattern = |
| 260 al | B26 | L | 4 | PostIndex | sp.code() * B16; | 260 al | B26 | L | 4 | PostIndex | sp.code() * B16; |
| 261 // mov lr, pc | 261 // mov lr, pc |
| 262 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; | 262 const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; |
| 263 // ldr rd, [pc, #offset] | 263 // ldr rd, [pc, #offset] |
| 264 const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16; | 264 const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16; |
| 265 const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16; | 265 const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16; |
| 266 const Instr kLdrMask = 15 * B24 | 7 * B20 | 15 * B16; | |
| 267 const Instr kLdrPattern = 5 * B24 | B20 | 15 * B16; | |
| 268 const Instr kMovwMovtMask = 15 * B24 | 15 * B20; | |
| 269 const Instr kMovwPattern = 3 * B24; | |
| 270 const Instr kMovtPattern = 3 * B24 | 4 * B20; | |
| 266 // blxcc rm | 271 // blxcc rm |
| 267 const Instr kBlxRegMask = | 272 const Instr kBlxRegMask = |
| 268 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; | 273 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; |
| 269 const Instr kBlxRegPattern = | 274 const Instr kBlxRegPattern = |
| 270 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4; | 275 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4; |
| 271 | 276 |
| 272 // Spare buffer. | 277 // Spare buffer. |
| 273 static const int kMinimalBufferSize = 4*KB; | 278 static const int kMinimalBufferSize = 4*KB; |
| 274 static byte* spare_buffer_ = NULL; | 279 static byte* spare_buffer_ = NULL; |
| 275 | 280 |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 557 } else if (rmode == RelocInfo::NONE) { | 562 } else if (rmode == RelocInfo::NONE) { |
| 558 return false; | 563 return false; |
| 559 } | 564 } |
| 560 return true; | 565 return true; |
| 561 } | 566 } |
| 562 | 567 |
| 563 | 568 |
| 564 void Assembler::addrmod1(Instr instr, | 569 void Assembler::addrmod1(Instr instr, |
| 565 Register rn, | 570 Register rn, |
| 566 Register rd, | 571 Register rd, |
| 567 const Operand& x) { | 572 const Operand& x, |
| 573 bool use_movw_movt) { | |
| 568 CheckBuffer(); | 574 CheckBuffer(); |
| 569 ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); | 575 ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); |
| 570 if (!x.rm_.is_valid()) { | 576 if (!x.rm_.is_valid()) { |
| 571 // Immediate. | 577 // Immediate. |
| 572 uint32_t rotate_imm; | 578 uint32_t rotate_imm; |
| 573 uint32_t immed_8; | 579 uint32_t immed_8; |
| 574 if (MustUseIp(x.rmode_) || | 580 if (MustUseIp(x.rmode_) || |
| 575 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { | 581 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { |
| 576 // The immediate operand cannot be encoded as a shifter operand, so load | 582 Condition cond = static_cast<Condition>(instr & CondMask); |
| 577 // it first to register ip and change the original instruction to use ip. | 583 if (!Serializer::enabled() && CpuFeatures::IsSupported(ARMv7) && |
| 578 // However, if the original instruction is a 'mov rd, x' (not setting the | 584 use_movw_movt && (x.rmode_ != RelocInfo::EMBEDDED_OBJECT) && |
| 579 // condition code), then replace it with a 'ldr rd, [pc]'. | 585 ((instr & ~CondMask) == 13*B21) && |
| 580 RecordRelocInfo(x.rmode_, x.imm32_); | 586 (x.imm32_ >= 0) && !rd.is(pc)) { |
| 581 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed | 587 RecordRelocInfo(x.rmode_, x.imm32_, false); |
| 582 Condition cond = static_cast<Condition>(instr & CondMask); | 588 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed |
| 583 if ((instr & ~CondMask) == 13*B21) { // mov, S not set | 589 movw(rd, x, cond); |
| 584 ldr(rd, MemOperand(pc, 0), cond); | 590 movt(rd, x, cond); |
|
Erik Corry
2010/05/03 10:06:28
In the case of the relocinfo being "None" we don't
| |
| 585 } else { | 591 } else { |
| 586 ldr(ip, MemOperand(pc, 0), cond); | 592 // The immediate operand cannot be encoded as a shifter operand, so |
| 587 addrmod1(instr, rn, rd, Operand(ip)); | 593 // load it first to register ip and change the original instruction |
| 588 } | 594 // to use ip. |
| 595 // However, if the original instruction is a 'mov rd, x' (not setting | |
| 596 // the condition code), then replace it with a 'ldr rd, [pc]' | |
| 597 RecordRelocInfo(x.rmode_, x.imm32_); | |
| 598 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed | |
| 599 if ((instr & ~CondMask) == 13*B21) { // mov, S not set | |
| 600 ldr(rd, MemOperand(pc, 0), cond); | |
| 601 } else { | |
| 602 ldr(ip, MemOperand(pc, 0), cond); | |
|
Erik Corry
2010/05/03 10:06:28
This code, that handles instructions other than mo
| |
| 603 addrmod1(instr, rn, rd, Operand(ip)); | |
| 604 } | |
| 605 } | |
| 589 return; | 606 return; |
| 590 } | 607 } |
| 591 instr |= I | rotate_imm*B8 | immed_8; | 608 instr |= I | rotate_imm*B8 | immed_8; |
| 592 } else if (!x.rs_.is_valid()) { | 609 } else if (!x.rs_.is_valid()) { |
| 593 // Immediate shift. | 610 // Immediate shift. |
| 594 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); | 611 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); |
| 595 } else { | 612 } else { |
| 596 // Register shift. | 613 // Register shift. |
| 597 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); | 614 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); |
| 598 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); | 615 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 addrmod1(cond | 11*B21 | S, src1, r0, src2); | 908 addrmod1(cond | 11*B21 | S, src1, r0, src2); |
| 892 } | 909 } |
| 893 | 910 |
| 894 | 911 |
| 895 void Assembler::orr(Register dst, Register src1, const Operand& src2, | 912 void Assembler::orr(Register dst, Register src1, const Operand& src2, |
| 896 SBit s, Condition cond) { | 913 SBit s, Condition cond) { |
| 897 addrmod1(cond | 12*B21 | s, src1, dst, src2); | 914 addrmod1(cond | 12*B21 | s, src1, dst, src2); |
| 898 } | 915 } |
| 899 | 916 |
| 900 | 917 |
| 901 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { | 918 void Assembler::mov(Register dst, const Operand& src, SBit s, |
| 919 Condition cond, bool use_movw_movt) { | |
| 902 if (dst.is(pc)) { | 920 if (dst.is(pc)) { |
| 903 WriteRecordedPositions(); | 921 WriteRecordedPositions(); |
| 904 } | 922 } |
| 905 addrmod1(cond | 13*B21 | s, r0, dst, src); | 923 addrmod1(cond | 13*B21 | s, r0, dst, src, use_movw_movt); |
| 924 } | |
| 925 | |
| 926 | |
| 927 void Assembler::movt(Register dst, const Operand& src, Condition cond) { | |
| 928 ASSERT(!src.rm_.is_valid()); | |
| 929 emit(cond | (0x34)*B20 | ((src.imm32_ >> 28) & 15) * B16 | |
| 930 | dst.code()*B12 | ((src.imm32_ >> 16) & 0xfff)); | |
| 931 } | |
| 932 | |
| 933 | |
| 934 void Assembler::movw(Register dst, const Operand& src, Condition cond) { | |
| 935 ASSERT(!src.rm_.is_valid()); | |
| 936 emit(cond | (0x30)*B20 | ((src.imm32_ >> 12) & 15) * B16 | |
| 937 | dst.code()*B12 | ((src.imm32_ & 0xfff))); | |
| 906 } | 938 } |
| 907 | 939 |
| 908 | 940 |
| 909 void Assembler::bic(Register dst, Register src1, const Operand& src2, | 941 void Assembler::bic(Register dst, Register src1, const Operand& src2, |
| 910 SBit s, Condition cond) { | 942 SBit s, Condition cond) { |
| 911 addrmod1(cond | 14*B21 | s, src1, dst, src2); | 943 addrmod1(cond | 14*B21 | s, src1, dst, src2); |
| 912 } | 944 } |
| 913 | 945 |
| 914 | 946 |
| 915 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { | 947 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { |
| (...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1825 RelocInfo& rinfo = prinfo_[i]; | 1857 RelocInfo& rinfo = prinfo_[i]; |
| 1826 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && | 1858 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
| 1827 rinfo.rmode() != RelocInfo::POSITION); | 1859 rinfo.rmode() != RelocInfo::POSITION); |
| 1828 if (rinfo.rmode() != RelocInfo::JS_RETURN) { | 1860 if (rinfo.rmode() != RelocInfo::JS_RETURN) { |
| 1829 rinfo.set_pc(rinfo.pc() + pc_delta); | 1861 rinfo.set_pc(rinfo.pc() + pc_delta); |
| 1830 } | 1862 } |
| 1831 } | 1863 } |
| 1832 } | 1864 } |
| 1833 | 1865 |
| 1834 | 1866 |
| 1835 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 1867 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, |
| 1868 intptr_t data, | |
| 1869 bool with_const_pool) { | |
| 1836 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants | 1870 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants |
| 1837 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { | 1871 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { |
| 1838 // Adjust code for new modes. | 1872 // Adjust code for new modes. |
| 1839 ASSERT(RelocInfo::IsJSReturn(rmode) | 1873 ASSERT(RelocInfo::IsJSReturn(rmode) |
| 1840 || RelocInfo::IsComment(rmode) | 1874 || RelocInfo::IsComment(rmode) |
| 1841 || RelocInfo::IsPosition(rmode)); | 1875 || RelocInfo::IsPosition(rmode)); |
| 1842 // These modes do not need an entry in the constant pool. | 1876 // These modes do not need an entry in the constant pool. |
| 1843 } else { | 1877 } else { |
| 1844 ASSERT(num_prinfo_ < kMaxNumPRInfo); | 1878 ASSERT(num_prinfo_ < kMaxNumPRInfo); |
| 1845 prinfo_[num_prinfo_++] = rinfo; | 1879 prinfo_[num_prinfo_++] = rinfo; |
| 1846 // Make sure the constant pool is not emitted in place of the next | 1880 if (with_const_pool) { |
| 1847 // instruction for which we just recorded relocation info. | 1881 // Make sure the constant pool is not emitted in place of the next |
| 1848 BlockConstPoolBefore(pc_offset() + kInstrSize); | 1882 // instruction for which we just recorded relocation info |
| 1883 BlockConstPoolBefore(pc_offset() + kInstrSize); | |
| 1884 } | |
| 1849 } | 1885 } |
| 1850 if (rinfo.rmode() != RelocInfo::NONE) { | 1886 if (rinfo.rmode() != RelocInfo::NONE) { |
| 1851 // Don't record external references unless the heap will be serialized. | 1887 // Don't record external references unless the heap will be serialized. |
| 1852 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { | 1888 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { |
| 1853 #ifdef DEBUG | 1889 #ifdef DEBUG |
| 1854 if (!Serializer::enabled()) { | 1890 if (!Serializer::enabled()) { |
| 1855 Serializer::TooLateToEnableNow(); | 1891 Serializer::TooLateToEnableNow(); |
| 1856 } | 1892 } |
| 1857 #endif | 1893 #endif |
| 1858 if (!Serializer::enabled() && !FLAG_debug_code) { | 1894 if (!Serializer::enabled() && !FLAG_debug_code) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1908 | 1944 |
| 1909 int jump_instr = require_jump ? kInstrSize : 0; | 1945 int jump_instr = require_jump ? kInstrSize : 0; |
| 1910 | 1946 |
| 1911 // Check that the code buffer is large enough before emitting the constant | 1947 // Check that the code buffer is large enough before emitting the constant |
| 1912 // pool and relocation information (include the jump over the pool and the | 1948 // pool and relocation information (include the jump over the pool and the |
| 1913 // constant pool marker). | 1949 // constant pool marker). |
| 1914 int max_needed_space = | 1950 int max_needed_space = |
| 1915 jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); | 1951 jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); |
| 1916 while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); | 1952 while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); |
| 1917 | 1953 |
| 1954 int block_for_prinfo = num_prinfo_*kInstrSize; | |
|
Erik Corry
2010/05/03 10:06:28
There should be spaces around '*'.
| |
| 1955 | |
| 1956 // Movw/movt instructions do not have const pool entries. | |
| 1957 for (int i = 0; i < num_prinfo_; i++) { | |
| 1958 RelocInfo& rinfo = prinfo_[i]; | |
| 1959 Instr instr = instr_at(rinfo.pc()); | |
| 1960 | |
| 1961 if (((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) != | |
|
Erik Corry
2010/05/03 10:06:28
It must be possible to rewrite this with a named m
| |
| 1962 (2*B25 | P | U | pc.code()*B16))) | |
| 1963 block_for_prinfo -= kInstrSize; | |
| 1964 } | |
| 1965 | |
| 1918 // Block recursive calls to CheckConstPool. | 1966 // Block recursive calls to CheckConstPool. |
| 1919 BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + | 1967 BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + |
| 1920 num_prinfo_*kInstrSize); | 1968 block_for_prinfo); |
| 1921 // Don't bother to check for the emit calls below. | 1969 // Don't bother to check for the emit calls below. |
| 1922 next_buffer_check_ = no_const_pool_before_; | 1970 next_buffer_check_ = no_const_pool_before_; |
| 1923 | 1971 |
| 1924 // Emit jump over constant pool if necessary. | 1972 // Emit jump over constant pool if necessary. |
| 1925 Label after_pool; | 1973 Label after_pool; |
| 1926 if (require_jump) b(&after_pool); | 1974 if (require_jump) b(&after_pool); |
| 1927 | 1975 |
| 1928 RecordComment("[ Constant Pool"); | 1976 RecordComment("[ Constant Pool"); |
| 1929 | 1977 |
| 1930 // Put down constant pool marker "Undefined instruction" as specified by | 1978 // Put down constant pool marker "Undefined instruction" as specified by |
| 1931 // A3.1 Instruction set encoding. | 1979 // A3.1 Instruction set encoding. |
| 1932 emit(0x03000000 | num_prinfo_); | 1980 emit(0x03000000 | num_prinfo_); |
| 1933 | 1981 |
| 1934 // Emit constant pool entries. | 1982 // Emit constant pool entries. |
| 1935 for (int i = 0; i < num_prinfo_; i++) { | 1983 for (int i = 0; i < num_prinfo_; i++) { |
| 1936 RelocInfo& rinfo = prinfo_[i]; | 1984 RelocInfo& rinfo = prinfo_[i]; |
| 1937 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && | 1985 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
| 1938 rinfo.rmode() != RelocInfo::POSITION && | 1986 rinfo.rmode() != RelocInfo::POSITION && |
| 1939 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); | 1987 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); |
| 1940 Instr instr = instr_at(rinfo.pc()); | 1988 Instr instr = instr_at(rinfo.pc()); |
| 1941 | 1989 |
| 1990 // Do not generate const pool entries for movw/movt instructions. | |
| 1991 if (((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) != | |
|
Erik Corry
2010/05/03 10:06:28
And this.
| |
| 1992 (2*B25 | P | U | pc.code()*B16))) | |
| 1993 continue; | |
|
Erik Corry
2010/05/03 10:06:28
Use braces on multi-line ifs.
| |
| 1994 | |
| 1942 // Instruction to patch must be a ldr/str [pc, #offset]. | 1995 // Instruction to patch must be a ldr/str [pc, #offset]. |
| 1943 // P and U set, B and W clear, Rn == pc, offset12 still 0. | 1996 // P and U set, B and W clear, Rn == pc, offset12 still 0. |
| 1944 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == | 1997 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == |
| 1945 (2*B25 | P | U | pc.code()*B16)); | 1998 (2*B25 | P | U | pc.code()*B16)); |
| 1946 int delta = pc_ - rinfo.pc() - 8; | 1999 int delta = pc_ - rinfo.pc() - 8; |
| 1947 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 | 2000 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 |
| 1948 if (delta < 0) { | 2001 if (delta < 0) { |
| 1949 instr &= ~U; | 2002 instr &= ~U; |
| 1950 delta = -delta; | 2003 delta = -delta; |
| 1951 } | 2004 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1962 bind(&after_pool); | 2015 bind(&after_pool); |
| 1963 } | 2016 } |
| 1964 | 2017 |
| 1965 // Since a constant pool was just emitted, move the check offset forward by | 2018 // Since a constant pool was just emitted, move the check offset forward by |
| 1966 // the standard interval. | 2019 // the standard interval. |
| 1967 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2020 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 1968 } | 2021 } |
| 1969 | 2022 |
| 1970 | 2023 |
| 1971 } } // namespace v8::internal | 2024 } } // namespace v8::internal |
| OLD | NEW |