Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: src/arm/assembler-arm.cc

Issue 1128009: Replace the constant pool access ldr instructions with movw/movt, and remove ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698