Chromium Code Reviews| Index: src/arm64/macro-assembler-arm64.cc |
| diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc |
| index 46626308091f6402aa8e07c25fc11808e2f43255..cc8b737e4c5b6d423cec8922a06769f908a62b00 100644 |
| --- a/src/arm64/macro-assembler-arm64.cc |
| +++ b/src/arm64/macro-assembler-arm64.cc |
| @@ -124,15 +124,15 @@ void MacroAssembler::LogicalMacro(const Register& rd, |
| } else { |
| // Immediate can't be encoded: synthesize using move immediate. |
| Register temp = temps.AcquireSameSizeAs(rn); |
| - Mov(temp, immediate); |
| + Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate); |
| if (rd.Is(csp)) { |
| // If rd is the stack pointer we cannot use it as the destination |
| // register so we use the temp register as an intermediate again. |
| - Logical(temp, rn, temp, op); |
| + Logical(temp, rn, imm_operand, op); |
| Mov(csp, temp); |
| AssertStackConsistency(); |
| } else { |
| - Logical(rd, rn, temp, op); |
| + Logical(rd, rn, imm_operand, op); |
| } |
| } |
| @@ -178,20 +178,11 @@ void MacroAssembler::Mov(const Register& rd, uint64_t imm) { |
| // applying move-keep operations to move-zero and move-inverted initial |
| // values. |
| - unsigned reg_size = rd.SizeInBits(); |
| - unsigned n, imm_s, imm_r; |
| - if (IsImmMovz(imm, reg_size) && !rd.IsSP()) { |
| - // Immediate can be represented in a move zero instruction. Movz can't |
| - // write to the stack pointer. |
| - movz(rd, imm); |
| - } else if (IsImmMovn(imm, reg_size) && !rd.IsSP()) { |
| - // Immediate can be represented in a move inverted instruction. Movn can't |
| - // write to the stack pointer. |
| - movn(rd, rd.Is64Bits() ? ~imm : (~imm & kWRegMask)); |
| - } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) { |
| - // Immediate can be represented in a logical orr instruction. |
| - LogicalImmediate(rd, AppropriateZeroRegFor(rd), n, imm_s, imm_r, ORR); |
| - } else { |
| + // Try to move the immediate in one instruction, and if that fails, switch to |
| + // using multiple instructions. |
| + if (!TryOneInstrMoveImmediate(rd, imm)) { |
| + unsigned reg_size = rd.SizeInBits(); |
| + |
| // Generic immediate case. Imm will be represented by |
| // [imm3, imm2, imm1, imm0], where each imm is 16 bits. |
| // A move-zero or move-inverted is generated for the first non-zero or |
| @@ -419,6 +410,62 @@ void MacroAssembler::Csel(const Register& rd, |
| } |
| +bool MacroAssembler::TryOneInstrMoveImmediate(const Register& dst, |
| + int64_t imm) { |
| + unsigned n, imm_s, imm_r; |
| + int reg_size = dst.SizeInBits(); |
| + if (IsImmMovz(imm, reg_size) && !dst.IsSP()) { |
| + // Immediate can be represented in a move zero instruction. Movz can't write |
| + // to the stack pointer. |
| + movz(dst, imm); |
| + return true; |
| + } else if (IsImmMovn(imm, reg_size) && !dst.IsSP()) { |
| + // Immediate can be represented in a move not instruction. Movn can't write |
| + // to the stack pointer. |
| + movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask)); |
| + return true; |
| + } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) { |
| + // Immediate can be represented in a logical orr instruction. |
| + LogicalImmediate(dst, AppropriateZeroRegFor(dst), n, imm_s, imm_r, ORR); |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| + |
| +Operand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst, |
| + int64_t imm) { |
| + int reg_size = dst.SizeInBits(); |
| + |
| + // Encode the immediate in a single move instruction, if possible. |
| + if (TryOneInstrMoveImmediate(dst, imm)) { |
| + // The move was successful; nothing to do here. |
| + } else { |
| + // Pre-shift the immediate to the least-significant bits of the register. |
| + int shift_low = CountTrailingZeros(imm, reg_size); |
| + int64_t imm_low = imm >> shift_low; |
| + |
| + // Pre-shift the immediate to the most-significant bits of the register, |
| + // inserting set bits in the least-significant bits. |
|
ulan
2014/07/07 07:42:20
Could you please add a comment explaining why we f
m.m.capewell
2014/07/07 13:28:03
Done.
|
| + int shift_high = CountLeadingZeros(imm, reg_size); |
| + int64_t imm_high = (imm << shift_high) | ((1 << shift_high) - 1); |
| + |
| + if (TryOneInstrMoveImmediate(dst, imm_low)) { |
| + // The new immediate has been moved into the destination's low bits: |
| + // return a new leftward-shifting operand. |
| + return Operand(dst, LSL, shift_low); |
| + } else if (TryOneInstrMoveImmediate(dst, imm_high)) { |
| + // The new immediate has been moved into the destination's high bits: |
| + // return a new rightward-shifting operand. |
| + return Operand(dst, LSR, shift_high); |
| + } else { |
| + Mov(dst, imm); |
| + } |
| + } |
| + return Operand(dst); |
| +} |
| + |
| + |
| void MacroAssembler::AddSubMacro(const Register& rd, |
| const Register& rn, |
| const Operand& operand, |
| @@ -441,8 +488,14 @@ void MacroAssembler::AddSubMacro(const Register& rd, |
| (operand.IsShiftedRegister() && (operand.shift() == ROR))) { |
| UseScratchRegisterScope temps(this); |
| Register temp = temps.AcquireSameSizeAs(rn); |
| - Mov(temp, operand); |
| - AddSub(rd, rn, temp, S, op); |
| + if (operand.IsImmediate()) { |
| + Operand imm_operand = |
| + MoveImmediateForShiftedOp(temp, operand.ImmediateValue()); |
| + AddSub(rd, rn, imm_operand, S, op); |
| + } else { |
| + Mov(temp, operand); |
| + AddSub(rd, rn, temp, S, op); |
| + } |
| } else { |
| AddSub(rd, rn, operand, S, op); |
| } |