diff options
author | Martyn Capewell <martyn.capewell@arm.com> | 2020-07-01 11:01:51 +0100 |
---|---|---|
committer | Jacob Bramley <jacob.bramley@arm.com> | 2020-07-13 20:05:18 +0000 |
commit | 960606b686f59d468f97dfa93b5dba5b2b38cc8f (patch) | |
tree | 3948abaa2c6f91c5259c81ddb1262f662474034f /src | |
parent | 4635261c9edcf4b056f9e1b26052b5612dee61ba (diff) | |
download | vixl-960606b686f59d468f97dfa93b5dba5b2b38cc8f.tar.gz |
Emit pairs of add/sub for larger immediates
For immediates between 12 and 24 bits in size, a pair of add or sub instructions
can be used instead of mov, avoiding the need to allocate a temporary.
Change-Id: I114b4667dcc1bda094652e01d88069d012249dca
Diffstat (limited to 'src')
-rw-r--r-- | src/aarch64/macro-assembler-aarch64.cc | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/src/aarch64/macro-assembler-aarch64.cc b/src/aarch64/macro-assembler-aarch64.cc index 1e81a8d7..0d9f0ec0 100644 --- a/src/aarch64/macro-assembler-aarch64.cc +++ b/src/aarch64/macro-assembler-aarch64.cc @@ -1427,8 +1427,7 @@ void MacroAssembler::Add(const Register& rd, const Operand& operand, FlagsUpdate S) { VIXL_ASSERT(allow_macro_instructions_); - if (operand.IsImmediate() && (operand.GetImmediate() < 0) && - IsImmAddSub(-operand.GetImmediate())) { + if (operand.IsImmediate() && (operand.GetImmediate() < 0)) { AddSubMacro(rd, rn, -operand.GetImmediate(), S, SUB); } else { AddSubMacro(rd, rn, operand, S, ADD); @@ -1448,8 +1447,7 @@ void MacroAssembler::Sub(const Register& rd, const Operand& operand, FlagsUpdate S) { VIXL_ASSERT(allow_macro_instructions_); - if (operand.IsImmediate() && (operand.GetImmediate() < 0) && - IsImmAddSub(-operand.GetImmediate())) { + if (operand.IsImmediate() && (operand.GetImmediate() < 0)) { AddSubMacro(rd, rn, -operand.GetImmediate(), S, ADD); } else { AddSubMacro(rd, rn, operand, S, SUB); @@ -1774,22 +1772,30 @@ void MacroAssembler::AddSubMacro(const Register& rd, // `rd`) because we don't need it after it is evaluated. Register temp = temps.AcquireSameSizeAs(rn); if (operand.IsImmediate()) { - PreShiftImmMode mode = kAnyShift; - - // If the destination or source register is the stack pointer, we can - // only pre-shift the immediate right by values supported in the add/sub - // extend encoding. - if (rd.IsSP()) { - // If the destination is SP and flags will be set, we can't pre-shift - // the immediate at all. - mode = (S == SetFlags) ? kNoShift : kLimitShiftForSP; - } else if (rn.IsSP()) { - mode = kLimitShiftForSP; - } + int64_t imm = operand.GetImmediate(); + int64_t divisor = 1 << ImmAddSub_width; + if ((S == LeaveFlags) && IsUint12(imm / divisor)) { + // Unsigned immediates requiring up to 24 bits are emitted as two adds + // or subs. + AddSub(rd, rn, imm % divisor, S, op); + AddSub(rd, rd, (imm / divisor) << ImmAddSub_width, S, op); + } else { + PreShiftImmMode mode = kAnyShift; + + // If the destination or source register is the stack pointer, we can + // only pre-shift the immediate right by values supported in the add/sub + // extend encoding. + if (rd.IsSP()) { + // If the destination is SP and flags will be set, we can't pre-shift + // the immediate at all. + mode = (S == SetFlags) ? kNoShift : kLimitShiftForSP; + } else if (rn.IsSP()) { + mode = kLimitShiftForSP; + } - Operand imm_operand = - MoveImmediateForShiftedOp(temp, operand.GetImmediate(), mode); - AddSub(rd, rn, imm_operand, S, op); + Operand imm_operand = MoveImmediateForShiftedOp(temp, imm, mode); + AddSub(rd, rn, imm_operand, S, op); + } } else { Mov(temp, operand); AddSub(rd, rn, temp, S, op); |