| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index 1a2f5d6e5dd0ecd274b2dd63888121a1175308a0..e586e5421e9d9e2f2a49c6736bd8d4ea0fab9e68 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -435,6 +435,10 @@ const Instr kMovLeaveCCPattern = 0x1a0 * B16;
|
| const Instr kMovwPattern = 0x30 * B20;
|
| const Instr kMovtPattern = 0x34 * B20;
|
| const Instr kMovwLeaveCCFlip = 0x5 * B21;
|
| +const Instr kMovImmedMask = 0x7f * B21;
|
| +const Instr kMovImmedPattern = 0x1d * B21;
|
| +const Instr kOrrImmedMask = 0x7f * B21;
|
| +const Instr kOrrImmedPattern = 0x1c * B21;
|
| const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
|
| const Instr kCmpCmnPattern = 0x15 * B20;
|
| const Instr kCmpCmnFlip = B21;
|
| @@ -1052,9 +1056,6 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const {
|
| static bool use_mov_immediate_load(const Operand& x,
|
| const Assembler* assembler) {
|
| if (assembler != NULL && !assembler->is_constant_pool_available()) {
|
| - // If there is no constant pool available, we must use an mov immediate.
|
| - // TODO(rmcilroy): enable ARMv6 support.
|
| - DCHECK(CpuFeatures::IsSupported(ARMv7));
|
| return true;
|
| } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
|
| (assembler == NULL || !assembler->predictable_code_size())) {
|
| @@ -1081,11 +1082,14 @@ int Operand::instructions_required(const Assembler* assembler,
|
| // for the constant pool or immediate load
|
| int instructions;
|
| if (use_mov_immediate_load(*this, assembler)) {
|
| - instructions = 2; // A movw, movt immediate load.
|
| + // A movw / movt or mov / orr immediate load.
|
| + instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
|
| } else if (assembler != NULL && assembler->use_extended_constant_pool()) {
|
| - instructions = 3; // An extended constant pool load.
|
| + // An extended constant pool load.
|
| + instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
|
| } else {
|
| - instructions = 1; // A small constant pool load.
|
| + // A small constant pool load.
|
| + instructions = 1;
|
| }
|
|
|
| if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set
|
| @@ -1107,21 +1111,27 @@ void Assembler::move_32_bit_immediate(Register rd,
|
| const Operand& x,
|
| Condition cond) {
|
| RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL);
|
| + uint32_t imm32 = static_cast<uint32_t>(x.imm32_);
|
| if (x.must_output_reloc_info(this)) {
|
| RecordRelocInfo(rinfo);
|
| }
|
|
|
| if (use_mov_immediate_load(x, this)) {
|
| Register target = rd.code() == pc.code() ? ip : rd;
|
| - // TODO(rmcilroy): add ARMv6 support for immediate loads.
|
| - DCHECK(CpuFeatures::IsSupported(ARMv7));
|
| - if (!FLAG_enable_ool_constant_pool &&
|
| - x.must_output_reloc_info(this)) {
|
| - // Make sure the movw/movt doesn't get separated.
|
| - BlockConstPoolFor(2);
|
| + if (CpuFeatures::IsSupported(ARMv7)) {
|
| + if (!FLAG_enable_ool_constant_pool && x.must_output_reloc_info(this)) {
|
| + // Make sure the movw/movt doesn't get separated.
|
| + BlockConstPoolFor(2);
|
| + }
|
| + movw(target, imm32 & 0xffff, cond);
|
| + movt(target, imm32 >> 16, cond);
|
| + } else {
|
| + DCHECK(FLAG_enable_ool_constant_pool);
|
| + mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
|
| + orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
|
| + orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
|
| + orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond);
|
| }
|
| - movw(target, static_cast<uint32_t>(x.imm32_ & 0xffff), cond);
|
| - movt(target, static_cast<uint32_t>(x.imm32_) >> 16, cond);
|
| if (target.code() != rd.code()) {
|
| mov(rd, target, LeaveCC, cond);
|
| }
|
| @@ -1132,8 +1142,15 @@ void Assembler::move_32_bit_immediate(Register rd,
|
| DCHECK(FLAG_enable_ool_constant_pool);
|
| Register target = rd.code() == pc.code() ? ip : rd;
|
| // Emit instructions to load constant pool offset.
|
| - movw(target, 0, cond);
|
| - movt(target, 0, cond);
|
| + if (CpuFeatures::IsSupported(ARMv7)) {
|
| + movw(target, 0, cond);
|
| + movt(target, 0, cond);
|
| + } else {
|
| + mov(target, Operand(0), LeaveCC, cond);
|
| + orr(target, target, Operand(0), LeaveCC, cond);
|
| + orr(target, target, Operand(0), LeaveCC, cond);
|
| + orr(target, target, Operand(0), LeaveCC, cond);
|
| + }
|
| // Load from constant pool at offset.
|
| ldr(rd, MemOperand(pp, target), cond);
|
| } else {
|
| @@ -3147,6 +3164,22 @@ Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
|
| }
|
|
|
|
|
| +int Assembler::DecodeShiftImm(Instr instr) {
|
| + int rotate = Instruction::RotateValue(instr) * 2;
|
| + int immed8 = Instruction::Immed8Value(instr);
|
| + return (immed8 >> rotate) | (immed8 << (32 - rotate));
|
| +}
|
| +
|
| +
|
| +Instr Assembler::PatchShiftImm(Instr instr, int immed) {
|
| + uint32_t rotate_imm = 0;
|
| + uint32_t immed_8 = 0;
|
| + bool immed_fits = fits_shifter(immed, &rotate_imm, &immed_8, NULL);
|
| + DCHECK(immed_fits);
|
| + return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8;
|
| +}
|
| +
|
| +
|
| bool Assembler::IsNop(Instr instr, int type) {
|
| DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop.
|
| // Check for mov rx, rx where x = type.
|
| @@ -3154,6 +3187,16 @@ bool Assembler::IsNop(Instr instr, int type) {
|
| }
|
|
|
|
|
| +bool Assembler::IsMovImmed(Instr instr) {
|
| + return (instr & kMovImmedMask) == kMovImmedPattern;
|
| +}
|
| +
|
| +
|
| +bool Assembler::IsOrrImmed(Instr instr) {
|
| + return (instr & kOrrImmedMask) == kOrrImmedPattern;
|
| +}
|
| +
|
| +
|
| // static
|
| bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
|
| uint32_t dummy1;
|
| @@ -3735,17 +3778,46 @@ void ConstantPoolBuilder::Populate(Assembler* assm,
|
| // Patch vldr/ldr instruction with correct offset.
|
| Instr instr = assm->instr_at(rinfo.pc());
|
| if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) {
|
| - // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
|
| - Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
|
| - DCHECK((Assembler::IsMovW(instr) &&
|
| - Instruction::ImmedMovwMovtValue(instr) == 0));
|
| - DCHECK((Assembler::IsMovT(next_instr) &&
|
| - Instruction::ImmedMovwMovtValue(next_instr) == 0));
|
| - assm->instr_at_put(rinfo.pc(),
|
| - Assembler::PatchMovwImmediate(instr, offset & 0xffff));
|
| - assm->instr_at_put(
|
| - rinfo.pc() + Assembler::kInstrSize,
|
| - Assembler::PatchMovwImmediate(next_instr, offset >> 16));
|
| + if (CpuFeatures::IsSupported(ARMv7)) {
|
| + // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
|
| + Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
|
| + DCHECK((Assembler::IsMovW(instr) &&
|
| + Instruction::ImmedMovwMovtValue(instr) == 0));
|
| + DCHECK((Assembler::IsMovT(next_instr) &&
|
| + Instruction::ImmedMovwMovtValue(next_instr) == 0));
|
| + assm->instr_at_put(
|
| + rinfo.pc(), Assembler::PatchMovwImmediate(instr, offset & 0xffff));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + Assembler::kInstrSize,
|
| + Assembler::PatchMovwImmediate(next_instr, offset >> 16));
|
| + } else {
|
| + // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
|
| + Instr instr_2 = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
|
| + Instr instr_3 = assm->instr_at(rinfo.pc() + 2 * Assembler::kInstrSize);
|
| + Instr instr_4 = assm->instr_at(rinfo.pc() + 3 * Assembler::kInstrSize);
|
| + DCHECK((Assembler::IsMovImmed(instr) &&
|
| + Instruction::Immed8Value(instr) == 0));
|
| + DCHECK((Assembler::IsOrrImmed(instr_2) &&
|
| + Instruction::Immed8Value(instr_2) == 0) &&
|
| + Assembler::GetRn(instr_2).is(Assembler::GetRd(instr_2)));
|
| + DCHECK((Assembler::IsOrrImmed(instr_3) &&
|
| + Instruction::Immed8Value(instr_3) == 0) &&
|
| + Assembler::GetRn(instr_3).is(Assembler::GetRd(instr_3)));
|
| + DCHECK((Assembler::IsOrrImmed(instr_4) &&
|
| + Instruction::Immed8Value(instr_4) == 0) &&
|
| + Assembler::GetRn(instr_4).is(Assembler::GetRd(instr_4)));
|
| + assm->instr_at_put(
|
| + rinfo.pc(), Assembler::PatchShiftImm(instr, (offset & kImm8Mask)));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + Assembler::kInstrSize,
|
| + Assembler::PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + 2 * Assembler::kInstrSize,
|
| + Assembler::PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + 3 * Assembler::kInstrSize,
|
| + Assembler::PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
|
| + }
|
| } else if (type == ConstantPoolArray::INT64) {
|
| // Instruction to patch must be 'vldr rd, [pp, #0]'.
|
| DCHECK((Assembler::IsVldrDPpImmediateOffset(instr) &&
|
|
|