Chromium Code Reviews| Index: src/arm/assembler-arm.cc |
| =================================================================== |
| --- src/arm/assembler-arm.cc (revision 4311) |
| +++ src/arm/assembler-arm.cc (working copy) |
| @@ -263,6 +263,11 @@ |
| // ldr rd, [pc, #offset] |
| const Instr kLdrPCMask = CondMask | 15 * B24 | 7 * B20 | 15 * B16; |
| const Instr kLdrPCPattern = al | 5 * B24 | L | pc.code() * B16; |
| +const Instr kLdrMask = 15 * B24 | 7 * B20 | 15 * B16; |
| +const Instr kLdrPattern = 5 * B24 | B20 | 15 * B16; |
| +const Instr kMovwMovtMask = 15 * B24 | 15 * B20; |
| +const Instr kMovwPattern = 3 * B24; |
| +const Instr kMovtPattern = 3 * B24 | 4 * B20; |
| // blxcc rm |
| const Instr kBlxRegMask = |
| 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; |
| @@ -564,7 +569,8 @@ |
| void Assembler::addrmod1(Instr instr, |
| Register rn, |
| Register rd, |
| - const Operand& x) { |
| + const Operand& x, |
| + bool use_movw_movt) { |
| CheckBuffer(); |
| ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); |
| if (!x.rm_.is_valid()) { |
| @@ -573,19 +579,30 @@ |
| uint32_t immed_8; |
| if (MustUseIp(x.rmode_) || |
| !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { |
| - // The immediate operand cannot be encoded as a shifter operand, so load |
| - // it first to register ip and change the original instruction to use ip. |
| - // However, if the original instruction is a 'mov rd, x' (not setting the |
| - // condition code), then replace it with a 'ldr rd, [pc]'. |
| - RecordRelocInfo(x.rmode_, x.imm32_); |
| - CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed |
| - Condition cond = static_cast<Condition>(instr & CondMask); |
| - if ((instr & ~CondMask) == 13*B21) { // mov, S not set |
| - ldr(rd, MemOperand(pc, 0), cond); |
| - } else { |
| - ldr(ip, MemOperand(pc, 0), cond); |
| - addrmod1(instr, rn, rd, Operand(ip)); |
| - } |
| + Condition cond = static_cast<Condition>(instr & CondMask); |
| + if (!Serializer::enabled() && CpuFeatures::IsSupported(ARMv7) && |
| + use_movw_movt && (x.rmode_ != RelocInfo::EMBEDDED_OBJECT) && |
| + ((instr & ~CondMask) == 13*B21) && |
| + (x.imm32_ >= 0) && !rd.is(pc)) { |
| + RecordRelocInfo(x.rmode_, x.imm32_, false); |
| + CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed |
| + movw(rd, x, cond); |
| + movt(rd, x, cond); |
|
Erik Corry
2010/05/03 10:06:28
In the case of the relocinfo being "None" we don't
|
| + } else { |
| + // The immediate operand cannot be encoded as a shifter operand, so |
| + // load it first to register ip and change the original instruction |
| + // to use ip. |
| + // However, if the original instruction is a 'mov rd, x' (not setting |
| + // the condition code), then replace it with a 'ldr rd, [pc]' |
| + RecordRelocInfo(x.rmode_, x.imm32_); |
| + CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed |
| + if ((instr & ~CondMask) == 13*B21) { // mov, S not set |
| + ldr(rd, MemOperand(pc, 0), cond); |
| + } else { |
| + ldr(ip, MemOperand(pc, 0), cond); |
|
Erik Corry
2010/05/03 10:06:28
This code, that handles instructions other than mo
|
| + addrmod1(instr, rn, rd, Operand(ip)); |
| + } |
| + } |
| return; |
| } |
| instr |= I | rotate_imm*B8 | immed_8; |
| @@ -898,14 +915,29 @@ |
| } |
| -void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { |
| +void Assembler::mov(Register dst, const Operand& src, SBit s, |
| + Condition cond, bool use_movw_movt) { |
| if (dst.is(pc)) { |
| WriteRecordedPositions(); |
| } |
| - addrmod1(cond | 13*B21 | s, r0, dst, src); |
| + addrmod1(cond | 13*B21 | s, r0, dst, src, use_movw_movt); |
| } |
| +void Assembler::movt(Register dst, const Operand& src, Condition cond) { |
| + ASSERT(!src.rm_.is_valid()); |
| + emit(cond | (0x34)*B20 | ((src.imm32_ >> 28) & 15) * B16 |
| + | dst.code()*B12 | ((src.imm32_ >> 16) & 0xfff)); |
| +} |
| + |
| + |
| +void Assembler::movw(Register dst, const Operand& src, Condition cond) { |
| + ASSERT(!src.rm_.is_valid()); |
| + emit(cond | (0x30)*B20 | ((src.imm32_ >> 12) & 15) * B16 |
| + | dst.code()*B12 | ((src.imm32_ & 0xfff))); |
| +} |
| + |
| + |
| void Assembler::bic(Register dst, Register src1, const Operand& src2, |
| SBit s, Condition cond) { |
| addrmod1(cond | 14*B21 | s, src1, dst, src2); |
| @@ -1832,7 +1864,9 @@ |
| } |
| -void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
| +void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, |
| + intptr_t data, |
| + bool with_const_pool) { |
| RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants |
| if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { |
| // Adjust code for new modes. |
| @@ -1843,9 +1877,11 @@ |
| } else { |
| ASSERT(num_prinfo_ < kMaxNumPRInfo); |
| prinfo_[num_prinfo_++] = rinfo; |
| - // Make sure the constant pool is not emitted in place of the next |
| - // instruction for which we just recorded relocation info. |
| - BlockConstPoolBefore(pc_offset() + kInstrSize); |
| + if (with_const_pool) { |
| + // Make sure the constant pool is not emitted in place of the next |
| + // instruction for which we just recorded relocation info |
| + BlockConstPoolBefore(pc_offset() + kInstrSize); |
| + } |
| } |
| if (rinfo.rmode() != RelocInfo::NONE) { |
| // Don't record external references unless the heap will be serialized. |
| @@ -1915,9 +1951,21 @@ |
| jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); |
| while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); |
| + int block_for_prinfo = num_prinfo_*kInstrSize; |
|
Erik Corry
2010/05/03 10:06:28
There should be spaces around '*'.
|
| + |
| + // Movw/movt instructions do not have const pool entries. |
| + for (int i = 0; i < num_prinfo_; i++) { |
| + RelocInfo& rinfo = prinfo_[i]; |
| + Instr instr = instr_at(rinfo.pc()); |
| + |
| + 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
|
| + (2*B25 | P | U | pc.code()*B16))) |
| + block_for_prinfo -= kInstrSize; |
| + } |
| + |
| // Block recursive calls to CheckConstPool. |
| BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + |
| - num_prinfo_*kInstrSize); |
| + block_for_prinfo); |
| // Don't bother to check for the emit calls below. |
| next_buffer_check_ = no_const_pool_before_; |
| @@ -1939,6 +1987,11 @@ |
| rinfo.rmode() != RelocInfo::STATEMENT_POSITION); |
| Instr instr = instr_at(rinfo.pc()); |
| + // Do not generate const pool entries for movw/movt instructions. |
| + if (((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) != |
|
Erik Corry
2010/05/03 10:06:28
And this.
|
| + (2*B25 | P | U | pc.code()*B16))) |
| + continue; |
|
Erik Corry
2010/05/03 10:06:28
Use braces on multi-line ifs.
|
| + |
| // Instruction to patch must be a ldr/str [pc, #offset]. |
| // P and U set, B and W clear, Rn == pc, offset12 still 0. |
| ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == |