165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison/*
265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * Copyright (C) 2014 The Android Open Source Project
365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison *
465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * Licensed under the Apache License, Version 2.0 (the "License");
565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * you may not use this file except in compliance with the License.
665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * You may obtain a copy of the License at
765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison *
865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison *      http://www.apache.org/licenses/LICENSE-2.0
965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison *
1065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * Unless required by applicable law or agreed to in writing, software
1165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * distributed under the License is distributed on an "AS IS" BASIS,
1265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * See the License for the specific language governing permissions and
1465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison * limitations under the License.
1565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison */
1665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
1765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_
1865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#define ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_
1965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
20cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko#include <deque>
217cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe#include <utility>
2265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include <vector>
2365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
24d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko#include "base/arena_containers.h"
2565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "base/logging.h"
2665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "constants_arm.h"
2765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "utils/arm/managed_register_arm.h"
2865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "utils/arm/assembler_arm.h"
296b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko#include "utils/array_ref.h"
3065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#include "offsets.h"
3165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
3265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allisonnamespace art {
3365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allisonnamespace arm {
3465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
3565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allisonclass Thumb2Assembler FINAL : public ArmAssembler {
3665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison public:
37d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  explicit Thumb2Assembler(ArenaAllocator* arena, bool can_relocate_branches = true)
38d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko      : ArmAssembler(arena),
39d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        can_relocate_branches_(can_relocate_branches),
408d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray        force_32bit_(false),
418d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray        it_cond_index_(kNoItCondition),
42cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        next_condition_(AL),
43d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        fixups_(arena->Adapter(kArenaAllocAssembler)),
44d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        fixup_dependents_(arena->Adapter(kArenaAllocAssembler)),
45d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        literals_(arena->Adapter(kArenaAllocAssembler)),
46d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        jump_tables_(arena->Adapter(kArenaAllocAssembler)),
47cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        last_position_adjustment_(0u),
48cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        last_old_position_(0u),
49cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        last_fixup_id_(0u) {
5010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    cfi().DelayEmittingAdvancePCs();
5165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
5265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
5365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  virtual ~Thumb2Assembler() {
5465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
5565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
5665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  bool IsThumb() const OVERRIDE {
5765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    return true;
5865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
5965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
6065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  bool IsForced32Bit() const {
6165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    return force_32bit_;
6265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
6365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
64d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray  bool CanRelocateBranches() const {
65d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray    return can_relocate_branches_;
668d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray  }
678d486731559ba0c5e12c27b4a507181333702b7eNicolas Geoffray
68cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void FinalizeCode() OVERRIDE;
6965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
7065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Data-processing instructions.
7173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void and_(Register rd, Register rn, const ShifterOperand& so,
7273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                    Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
7365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
7473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void eor(Register rd, Register rn, const ShifterOperand& so,
7573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
7665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
7773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void sub(Register rd, Register rn, const ShifterOperand& so,
7873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
7965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
8073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
8173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
8265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
8373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void add(Register rd, Register rn, const ShifterOperand& so,
8473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
8565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
8673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void adc(Register rd, Register rn, const ShifterOperand& so,
8773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
8865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
8973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
9073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
9165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
9273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
9373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
9465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
9565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
9665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
9765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
9865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
9965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
10065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
10165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
10265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
10373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void orr(Register rd, Register rn, const ShifterOperand& so,
10473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
10565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
106d2b4ca2d02c86b1ce1826fd2b35ce6c9c58c1ff1Vladimir Marko  virtual void orn(Register rd, Register rn, const ShifterOperand& so,
107d2b4ca2d02c86b1ce1826fd2b35ce6c9c58c1ff1Vladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
108d2b4ca2d02c86b1ce1826fd2b35ce6c9c58c1ff1Vladimir Marko
10973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void mov(Register rd, const ShifterOperand& so,
11073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
11165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
11273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void bic(Register rd, Register rn, const ShifterOperand& so,
11373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
11465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
11573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void mvn(Register rd, const ShifterOperand& so,
11673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
11765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
11865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Miscellaneous data-processing instructions.
11965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
12065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
12165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
1229ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling  void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE;
123c257da7b0fb6737f65aba426add8831e45404755Artem Serov  void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE;
124c257da7b0fb6737f65aba426add8831e45404755Artem Serov  void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE;
125c257da7b0fb6737f65aba426add8831e45404755Artem Serov  void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE;
12665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
12765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Multiply instructions.
12865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
12965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void mla(Register rd, Register rn, Register rm, Register ra,
13065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison           Condition cond = AL) OVERRIDE;
13165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void mls(Register rd, Register rn, Register rm, Register ra,
13265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison           Condition cond = AL) OVERRIDE;
133c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
134c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu             Condition cond = AL) OVERRIDE;
13565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
13665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison             Condition cond = AL) OVERRIDE;
13765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
13865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
13965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
14065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
141981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain  // Bit field extract instructions.
14251d3fc40637fc73d4156ad617cd451b844cbb75eRoland Levillain  void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
143981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain  void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
14451d3fc40637fc73d4156ad617cd451b844cbb75eRoland Levillain
14565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Load/store instructions.
14665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
14765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
14865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
14965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
15065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
15165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
15265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
15365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
15465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
15565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
15665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
15765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
1584af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // Load/store register dual instructions using registers `rd` and `rd` + 1.
15965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
16065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
16165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
1624af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // Load/store register dual instructions using registers `rd` and `rd2`.
1634af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // Note that contrary to the ARM A1 encoding, the Thumb-2 T1 encoding
1644af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // does not require `rd` to be even, nor `rd2' to be equal to `rd` + 1.
1654af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  void ldrd(Register rd, Register rd2, const Address& ad, Condition cond);
1664af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  void strd(Register rd, Register rd2, const Address& ad, Condition cond);
1674af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
1684af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
16965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldm(BlockAddressMode am, Register base,
17065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison           RegList regs, Condition cond = AL) OVERRIDE;
17165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void stm(BlockAddressMode am, Register base,
17265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison           RegList regs, Condition cond = AL) OVERRIDE;
17365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
17465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE;
17565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE;
17665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
17765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL);
17865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL);
17965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
18052c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle  void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
18152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle  void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
18265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
18365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Miscellaneous instructions.
18465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void clrex(Condition cond = AL) OVERRIDE;
18565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void nop(Condition cond = AL) OVERRIDE;
18665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
18765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void bkpt(uint16_t imm16) OVERRIDE;
18865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void svc(uint32_t imm24) OVERRIDE;
18965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
19065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // If-then
19165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void it(Condition firstcond, ItState i1 = kItOmitted,
19265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison        ItState i2 = kItOmitted, ItState i3 = kItOmitted) OVERRIDE;
19365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
19465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void cbz(Register rn, Label* target) OVERRIDE;
19565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void cbnz(Register rn, Label* target) OVERRIDE;
19665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
19765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
19865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE;
19965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE;
20065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
20165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE;
20265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
20365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE;
20465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
20565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
20665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
20765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Returns false if the immediate cannot be encoded.
20865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE;
20965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE;
21065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
21165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
21265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
21365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
21465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
21565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
21665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
21765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
21865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
21965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
22065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
22165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
22265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
22365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
22465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
22565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
22665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
22765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
22865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
22965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
23065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
23165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
23265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
23365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
23465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
23565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
23665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
23765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
23865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
23965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
24065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
24165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
24265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
24365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
24465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
24565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
24665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
24765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
24865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
24965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE;
25065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE;
25165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vmstat(Condition cond = AL) OVERRIDE;  // VMRS APSR_nzcv, FPSCR
25265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
25365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
25465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
25565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
25665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
25765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
25865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Branch instructions.
25965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void b(Label* label, Condition cond = AL);
26065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void bl(Label* label, Condition cond = AL);
26165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void blx(Label* label);
26265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void blx(Register rm, Condition cond = AL) OVERRIDE;
26365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void bx(Register rm, Condition cond = AL) OVERRIDE;
26465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
26573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
26673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
26773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
26873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
26973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
27073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
27173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
27273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
27373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Rrx(Register rd, Register rm,
27473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
27573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko
27673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Lsl(Register rd, Register rm, Register rn,
27773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
27873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Lsr(Register rd, Register rm, Register rn,
27973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
28073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Asr(Register rd, Register rm, Register rn,
28173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
28273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual void Ror(Register rd, Register rm, Register rn,
28373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
28465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
28565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Push(Register rd, Condition cond = AL) OVERRIDE;
28665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Pop(Register rd, Condition cond = AL) OVERRIDE;
28765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
28865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void PushList(RegList regs, Condition cond = AL) OVERRIDE;
28965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void PopList(RegList regs, Condition cond = AL) OVERRIDE;
29065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
29165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE;
29265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
29365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE;
29465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE;
29565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
29619a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Memory barriers.
29719a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  void dmb(DmbOptions flavor) OVERRIDE;
29819a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
299cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Get the final position of a label after local fixup based on the old position
300cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // recorded before FinalizeCode().
301cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  uint32_t GetAdjustedPosition(uint32_t old_position) OVERRIDE;
302cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
303cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  using ArmAssembler::NewLiteral;  // Make the helper template visible.
304cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
305cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Literal* NewLiteral(size_t size, const uint8_t* data) OVERRIDE;
306cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void LoadLiteral(Register rt, Literal* literal) OVERRIDE;
307cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void LoadLiteral(Register rt, Register rt2, Literal* literal) OVERRIDE;
308cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void LoadLiteral(SRegister sd, Literal* literal) OVERRIDE;
309cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void LoadLiteral(DRegister dd, Literal* literal) OVERRIDE;
310cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
31165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Add signed constant value to rd. May clobber IP.
31265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void AddConstant(Register rd, Register rn, int32_t value,
313449b10922daacc880374d7862dbb5977c7657f6dVladimir Marko                   Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
31465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
3157cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  void CmpConstant(Register rn, int32_t value, Condition cond = AL) OVERRIDE;
3167cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe
31765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Load and Store. May clobber IP.
31865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE;
31965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void MarkExceptionHandler(Label* label) OVERRIDE;
32065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void LoadFromOffset(LoadOperandType type,
32165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Register reg,
32265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Register base,
32365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      int32_t offset,
32465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Condition cond = AL) OVERRIDE;
32565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void StoreToOffset(StoreOperandType type,
32665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                     Register reg,
32765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                     Register base,
32865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                     int32_t offset,
32965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                     Condition cond = AL) OVERRIDE;
33065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void LoadSFromOffset(SRegister reg,
33165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Register base,
33265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       int32_t offset,
33365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Condition cond = AL) OVERRIDE;
33465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void StoreSToOffset(SRegister reg,
33565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Register base,
33665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      int32_t offset,
33765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Condition cond = AL) OVERRIDE;
33865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void LoadDFromOffset(DRegister reg,
33965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Register base,
34065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       int32_t offset,
34165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Condition cond = AL) OVERRIDE;
34265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void StoreDToOffset(DRegister reg,
34365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Register base,
34465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      int32_t offset,
34565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Condition cond = AL) OVERRIDE;
34665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
3473bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray  bool ShifterOperandCanHold(Register rd,
3483bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray                             Register rn,
3493bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray                             Opcode opcode,
3503bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray                             uint32_t immediate,
351f5c09c3ed5bca4c34d8476dd9ed2714106fafbcfVladimir Marko                             SetCc set_cc,
3523bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray                             ShifterOperand* shifter_op) OVERRIDE;
353f5c09c3ed5bca4c34d8476dd9ed2714106fafbcfVladimir Marko  using ArmAssembler::ShifterOperandCanHold;  // Don't hide the non-virtual override.
3545bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray
3555bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray  bool ShifterOperandCanAlwaysHold(uint32_t immediate) OVERRIDE;
3563bcc8ea079d867f26622defd0611d134a3b4ae49Nicolas Geoffray
35765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
35813735955f39b3b304c37d2b2840663c131262c18Ian Rogers  static bool IsInstructionForExceptionHandling(uintptr_t pc);
35965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
36065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Emit data (e.g. encoded instruction or immediate) to the.
36165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // instruction stream.
36265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Emit32(int32_t value);     // Emit a 32 bit instruction in thumb format.
36365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Emit16(int16_t value);     // Emit a 16 bit instruction in little endian format.
36465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Bind(Label* label) OVERRIDE;
36565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
36665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
36765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
36865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Force the assembler to generate 32 bit instructions.
36965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Force32Bit() {
37065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    force_32bit_ = true;
37165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
37265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
3737cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  // Emit an ADR (or a sequence of instructions) to load the jump table address into base_reg. This
3747cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  // will generate a fixup.
3757cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) OVERRIDE;
3767cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  // Emit an ADD PC, X to dispatch a jump-table jump. This will generate a fixup.
3777cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) OVERRIDE;
3787cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe
37965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison private:
380cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  typedef uint16_t FixupId;
381cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
382cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Fixup: branches and literal pool references.
383cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  //
384cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The thumb2 architecture allows branches to be either 16 or 32 bit instructions. This
385cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // depends on both the type of branch and the offset to which it is branching. The 16-bit
386cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // cbz and cbnz instructions may also need to be replaced with a separate 16-bit compare
387cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // instruction and a 16- or 32-bit branch instruction. Load from a literal pool can also be
388cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // 16-bit or 32-bit instruction and, if the method is large, we may need to use a sequence
389cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // of instructions to make up for the limited range of load literal instructions (up to
390cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // 4KiB for the 32-bit variant). When generating code for these insns we don't know the
391cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // size before hand, so we assume it is the smallest available size and determine the final
392cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // code offsets and sizes and emit code in FinalizeCode().
393cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  //
394cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // To handle this, we keep a record of every branch and literal pool load in the program.
395cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The actual instruction encoding for these is delayed until we know the final size of
396cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // every instruction. When we bind a label to a branch we don't know the final location yet
397cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // as some preceding instructions may need to be expanded, so we record a non-final offset.
398cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // In FinalizeCode(), we expand the sizes of branches and literal loads that are out of
399cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // range. With each expansion, we need to update dependent Fixups, i.e. insntructios with
400cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // target on the other side of the expanded insn, as their offsets change and this may
401cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // trigger further expansion.
402cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  //
403cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // All Fixups have a 'fixup id' which is a 16 bit unsigned number used to identify the
404cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Fixup. For each unresolved label we keep a singly-linked list of all Fixups pointing
405cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // to it, using the fixup ids as links. The first link is stored in the label's position
406cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // (the label is linked but not bound), the following links are stored in the code buffer,
407cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // in the placeholder where we will eventually emit the actual code.
408cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
409cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  class Fixup {
410cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko   public:
411cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Branch type.
412cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    enum Type : uint8_t {
413cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kConditional,               // B<cond>.
414cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kUnconditional,             // B.
415cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kUnconditionalLink,         // BL.
416cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kUnconditionalLinkX,        // BLX.
417cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kCompareAndBranchXZero,     // cbz/cbnz.
418cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLoadLiteralNarrow,         // Load narrrow integer literal.
419cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLoadLiteralWide,           // Load wide integer literal.
4207cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      kLoadLiteralAddr,           // Load address of literal (used for jump table).
421cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLoadFPLiteralSingle,       // Load FP literal single.
422cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLoadFPLiteralDouble,       // Load FP literal double.
423cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    };
424cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
425cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Calculated size of branch instruction based on type and offset.
426cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    enum Size : uint8_t {
427cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // Branch variants.
428cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kBranch16Bit,
429cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kBranch32Bit,
430cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // NOTE: We don't support branches which would require multiple instructions, i.e.
431cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // conditinoal branches beyond +-1MiB and unconditional branches beyond +-16MiB.
432cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
433cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // CBZ/CBNZ variants.
434cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kCbxz16Bit,   // CBZ/CBNZ rX, label; X < 8; 7-bit positive offset.
435cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kCbxz32Bit,   // CMP rX, #0 + Bcc label; X < 8; 16-bit Bcc; +-8-bit offset.
436cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kCbxz48Bit,   // CMP rX, #0 + Bcc label; X < 8; 32-bit Bcc; up to +-1MiB offset.
437cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
438cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // Load integer literal variants.
439cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // LDR rX, label; X < 8; 16-bit variant up to 1KiB offset; 2 bytes.
440cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLiteral1KiB,
441cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // LDR rX, label; 32-bit variant up to 4KiB offset; 4 bytes.
442cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLiteral4KiB,
443cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // MOV rX, imm16 + ADD rX, pc + LDR rX, [rX]; X < 8; up to 64KiB offset; 8 bytes.
444cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLiteral64KiB,
445cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // MOV rX, modimm + ADD rX, pc + LDR rX, [rX, #imm12]; up to 1MiB offset; 10 bytes.
446cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLiteral1MiB,
447cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // NOTE: We don't provide the 12-byte version of kLiteralFar below where the LDR is 16-bit.
448cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc + LDR rX, [rX]; any offset; 14 bytes.
449cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLiteralFar,
450cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
4517cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      // Load literal base addr.
4527cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      // ADR rX, label; X < 8; 8 bit immediate, shifted to 10 bit. 2 bytes.
4537cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      kLiteralAddr1KiB,
4547cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      // ADR rX, label; 4KiB offset. 4 bytes.
4557cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      kLiteralAddr4KiB,
4567cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      // MOV rX, imm16 + ADD rX, pc; 64KiB offset. 6 bytes.
4577cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      kLiteralAddr64KiB,
4587cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      // MOV rX, imm16 + MOVT rX, imm16 + ADD rX, pc; any offset; 10 bytes.
4597cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      kLiteralAddrFar,
4607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe
461cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // Load long or FP literal variants.
462cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // VLDR s/dX, label; 32-bit insn, up to 1KiB offset; 4 bytes.
463cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLongOrFPLiteral1KiB,
464cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // MOV ip, modimm + ADD ip, pc + VLDR s/dX, [IP, #imm8*4]; up to 256KiB offset; 10 bytes.
465cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLongOrFPLiteral256KiB,
466cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // MOV ip, imm16 + MOVT ip, imm16 + ADD ip, pc + VLDR s/dX, [IP]; any offset; 14 bytes.
467cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      kLongOrFPLiteralFar,
468cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    };
469cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
470cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Unresolved branch possibly with a condition.
471cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static Fixup Branch(uint32_t location, Type type, Size size = kBranch16Bit,
472cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                        Condition cond = AL) {
473cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(type == kConditional || type == kUnconditional ||
474cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko             type == kUnconditionalLink || type == kUnconditionalLinkX);
475cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(size == kBranch16Bit || size == kBranch32Bit);
476cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(size == kBranch32Bit || (type == kConditional || type == kUnconditional));
477cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return Fixup(kNoRegister, kNoRegister, kNoSRegister, kNoDRegister,
478cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                   cond, type, size, location);
479cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
480cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
481cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Unresolved compare-and-branch instruction with a register and condition (EQ or NE).
482cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static Fixup CompareAndBranch(uint32_t location, Register rn, Condition cond) {
483cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(cond == EQ || cond == NE);
484cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return Fixup(rn, kNoRegister, kNoSRegister, kNoDRegister,
485cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                   cond, kCompareAndBranchXZero, kCbxz16Bit, location);
486cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
487cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
488cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Load narrow literal.
4897cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe    static Fixup LoadNarrowLiteral(uint32_t location, Register rt, Size size) {
490cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(size == kLiteral1KiB || size == kLiteral4KiB || size == kLiteral64KiB ||
491cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko             size == kLiteral1MiB || size == kLiteralFar);
492cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB));
493cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister,
494cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                   AL, kLoadLiteralNarrow, size, location);
495cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
496cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
497cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Load wide literal.
498cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static Fixup LoadWideLiteral(uint32_t location, Register rt, Register rt2,
499cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                                 Size size = kLongOrFPLiteral1KiB) {
500cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB ||
501cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko             size == kLongOrFPLiteralFar);
502cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(!IsHighRegister(rt) || (size != kLiteral1KiB && size != kLiteral64KiB));
503cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return Fixup(rt, rt2, kNoSRegister, kNoDRegister,
504cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                   AL, kLoadLiteralWide, size, location);
505cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
506cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
507cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Load FP single literal.
508cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static Fixup LoadSingleLiteral(uint32_t location, SRegister sd,
509cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                                   Size size = kLongOrFPLiteral1KiB) {
510cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB ||
511cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko             size == kLongOrFPLiteralFar);
512cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return Fixup(kNoRegister, kNoRegister, sd, kNoDRegister,
513cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                   AL, kLoadFPLiteralSingle, size, location);
514cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
515cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
516cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Load FP double literal.
517cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static Fixup LoadDoubleLiteral(uint32_t location, DRegister dd,
518cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                                   Size size = kLongOrFPLiteral1KiB) {
519cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK(size == kLongOrFPLiteral1KiB || size == kLongOrFPLiteral256KiB ||
520cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko             size == kLongOrFPLiteralFar);
521cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return Fixup(kNoRegister, kNoRegister, kNoSRegister, dd,
522cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                   AL, kLoadFPLiteralDouble, size, location);
523cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
524cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
5257cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe    static Fixup LoadLiteralAddress(uint32_t location, Register rt, Size size) {
5267cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      DCHECK(size == kLiteralAddr1KiB || size == kLiteralAddr4KiB || size == kLiteralAddr64KiB ||
5277cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe             size == kLiteralAddrFar);
5287cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      DCHECK(!IsHighRegister(rt) || size != kLiteralAddr1KiB);
5297cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe      return Fixup(rt, kNoRegister, kNoSRegister, kNoDRegister,
5307cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe                   AL, kLoadLiteralAddr, size, location);
5317cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe    }
5327cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe
533cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Type GetType() const {
534cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return type_;
535cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
536cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
537663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko    bool IsLoadLiteral() const {
538663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      return GetType() >= kLoadLiteralNarrow;
539663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko    }
540663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko
541f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko    // Returns whether the Fixup can expand from the original size.
542f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko    bool CanExpand() const {
543f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko      switch (GetOriginalSize()) {
544f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko        case kBranch32Bit:
545f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko        case kCbxz48Bit:
546f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko        case kLiteralFar:
547f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko        case kLiteralAddrFar:
548f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko        case kLongOrFPLiteralFar:
549f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko          return false;
550f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko        default:
551f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko          return true;
552f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko      }
553f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko    }
554f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko
555cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Size GetOriginalSize() const {
556cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return original_size_;
557cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
558cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
559cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Size GetSize() const {
560cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return size_;
561cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
562cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
563cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t GetOriginalSizeInBytes() const;
564cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
565cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t GetSizeInBytes() const;
566cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
567cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t GetLocation() const {
568cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return location_;
569cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
570cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
571cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t GetAdjustment() const {
572cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      return adjustment_;
573cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
574cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
5756b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko    // Prepare the assembler->fixup_dependents_ and each Fixup's dependents_start_/count_.
5766b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko    static void PrepareDependents(Thumb2Assembler* assembler);
577cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
578d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko    ArrayRef<const FixupId> Dependents(const Thumb2Assembler& assembler) const {
579d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko      return ArrayRef<const FixupId>(assembler.fixup_dependents_).SubArray(dependents_start_,
580d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko                                                                           dependents_count_);
581cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
582cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
583cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Resolve a branch when the target is known.
584cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    void Resolve(uint32_t target) {
585cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK_EQ(target_, kUnresolved);
586cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK_NE(target, kUnresolved);
587cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      target_ = target;
588cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
589cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
590cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Check if the current size is OK for current location_, target_ and adjustment_.
591cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // If not, increase the size. Return the size increase, 0 if unchanged.
592cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // If the target if after this Fixup, also add the difference to adjustment_,
593cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // so that we don't need to consider forward Fixups as their own dependencies.
594cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t AdjustSizeIfNeeded(uint32_t current_code_size);
595cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
596cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Increase adjustments. This is called for dependents of a Fixup when its size changes.
597cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    void IncreaseAdjustment(uint32_t increase) {
598cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      adjustment_ += increase;
599cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
600cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
601cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Finalize the branch with an adjustment to the location. Both location and target are updated.
602cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    void Finalize(uint32_t location_adjustment) {
603cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      DCHECK_NE(target_, kUnresolved);
604cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      location_ += location_adjustment;
605cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      target_ += location_adjustment;
606cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
607cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
608cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Emit the branch instruction into the assembler buffer.  This does the
609cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // encoding into the thumb instruction.
610cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    void Emit(AssemblerBuffer* buffer, uint32_t code_size) const;
611cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
612cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko   private:
613cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Fixup(Register rn, Register rt2, SRegister sd, DRegister dd,
614cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          Condition cond, Type type, Size size, uint32_t location)
615cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        : rn_(rn),
616cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          rt2_(rt2),
617cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          sd_(sd),
618cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          dd_(dd),
619cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          cond_(cond),
620cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          type_(type),
621cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          original_size_(size), size_(size),
622cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          location_(location),
623cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          target_(kUnresolved),
624cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko          adjustment_(0u),
6256b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko          dependents_count_(0u),
6266b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko          dependents_start_(0u) {
627cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
628f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko
629cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static size_t SizeInBytes(Size size);
630cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
631cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // The size of padding added before the literal pool.
632cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static size_t LiteralPoolPaddingSize(uint32_t current_code_size);
633cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
634cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Returns the offset from the PC-using insn to the target.
635cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    int32_t GetOffset(uint32_t current_code_size) const;
636cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
637cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    size_t IncreaseSize(Size new_size);
638cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
639cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    int32_t LoadWideOrFpEncoding(Register rbase, int32_t offset) const;
640cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
641f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko    template <typename Function>
642f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko    static void ForExpandableDependencies(Thumb2Assembler* assembler, Function fn);
643f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko
644cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    static constexpr uint32_t kUnresolved = 0xffffffff;     // Value for target_ for unresolved.
645cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
646cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    const Register rn_;   // Rn for cbnz/cbz, Rt for literal loads.
647cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Register rt2_;        // For kLoadLiteralWide.
648cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    SRegister sd_;        // For kLoadFPLiteralSingle.
649cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    DRegister dd_;        // For kLoadFPLiteralDouble.
650cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    const Condition cond_;
651cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    const Type type_;
652cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Size original_size_;
653cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    Size size_;
654cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t location_;     // Offset into assembler buffer in bytes.
655cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t target_;       // Offset into assembler buffer in bytes.
656cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    uint32_t adjustment_;   // The number of extra bytes inserted between location_ and target_.
6576b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko    // Fixups that require adjustment when current size changes are stored in a single
6586b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko    // array in the assembler and we store only the start index and count here.
6596b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko    uint32_t dependents_count_;
6606b756b5b7ad59358366268c5213a0a0f98637a18Vladimir Marko    uint32_t dependents_start_;
661cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  };
662cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
66365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Emit a single 32 or 16 bit data processing instruction.
66465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitDataProcessing(Condition cond,
6656a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                          Opcode opcode,
66673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                          SetCc set_cc,
6676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                          Register rn,
6686a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                          Register rd,
6696a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                          const ShifterOperand& so);
67065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
671c257da7b0fb6737f65aba426add8831e45404755Artem Serov  // Emit a single 32 bit miscellaneous instruction.
672c257da7b0fb6737f65aba426add8831e45404755Artem Serov  void Emit32Miscellaneous(uint8_t op1,
673c257da7b0fb6737f65aba426add8831e45404755Artem Serov                           uint8_t op2,
674c257da7b0fb6737f65aba426add8831e45404755Artem Serov                           uint32_t rest_encoding);
675c257da7b0fb6737f65aba426add8831e45404755Artem Serov
676c257da7b0fb6737f65aba426add8831e45404755Artem Serov  // Emit reverse byte instructions: rev, rev16, revsh.
677c257da7b0fb6737f65aba426add8831e45404755Artem Serov  void EmitReverseBytes(Register rd, Register rm, uint32_t op);
678c257da7b0fb6737f65aba426add8831e45404755Artem Serov
679c257da7b0fb6737f65aba426add8831e45404755Artem Serov  // Emit a single 16 bit miscellaneous instruction.
680c257da7b0fb6737f65aba426add8831e45404755Artem Serov  void Emit16Miscellaneous(uint32_t rest_encoding);
681c257da7b0fb6737f65aba426add8831e45404755Artem Serov
68265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Must the instruction be 32 bits or can it possibly be encoded
68365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // in 16 bits?
68465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  bool Is32BitDataProcessing(Condition cond,
6856a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                             Opcode opcode,
68673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                             SetCc set_cc,
6876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                             Register rn,
6886a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                             Register rd,
6896a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                             const ShifterOperand& so);
69065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
69165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Emit a 32 bit data processing instruction.
69265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Emit32BitDataProcessing(Condition cond,
6936a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               Opcode opcode,
69473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                               SetCc set_cc,
6956a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               Register rn,
6966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               Register rd,
6976a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               const ShifterOperand& so);
69865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
69965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // Emit a 16 bit data processing instruction.
70065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Emit16BitDataProcessing(Condition cond,
7016a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               Opcode opcode,
70273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                               SetCc set_cc,
7036a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               Register rn,
7046a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               Register rd,
7056a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               const ShifterOperand& so);
70665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
70765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void Emit16BitAddSub(Condition cond,
70865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Opcode opcode,
70973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                       SetCc set_cc,
71065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Register rn,
71165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       Register rd,
71265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                       const ShifterOperand& so);
71365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
71465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  uint16_t EmitCompareAndBranch(Register rn, uint16_t prev, bool n);
71565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
71665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitLoadStore(Condition cond,
7176a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                     bool load,
7186a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                     bool byte,
7196a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                     bool half,
7206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                     bool is_signed,
7216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                     Register rd,
7226a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                     const Address& ad);
72365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
72465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitMemOpAddressMode3(Condition cond,
72565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                             int32_t mode,
72665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                             Register rd,
72765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                             const Address& ad);
72865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
72965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitMultiMemOp(Condition cond,
73065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      BlockAddressMode am,
73165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      bool load,
73265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      Register base,
73365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                      RegList regs);
73465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
73565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitMulOp(Condition cond,
73665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 int32_t opcode,
73765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 Register rd,
73865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 Register rn,
73965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 Register rm,
74065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 Register rs);
74165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
74265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitVFPsss(Condition cond,
74365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  int32_t opcode,
74465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  SRegister sd,
74565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  SRegister sn,
74665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  SRegister sm);
74765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
74865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitVFPddd(Condition cond,
74965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  int32_t opcode,
75065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  DRegister dd,
75165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  DRegister dn,
75265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                  DRegister dm);
75365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
75465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitVFPsd(Condition cond,
75565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 int32_t opcode,
75665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 SRegister sd,
75765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 DRegister dm);
75865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
75965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitVFPds(Condition cond,
76065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 int32_t opcode,
76165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 DRegister dd,
76265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison                 SRegister sm);
76365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
76465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond);
76565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
766cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void EmitBranch(Condition cond, Label* label, bool link, bool x);
76765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  static int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
76865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  static int DecodeBranchOffset(int32_t inst);
76973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount,
77073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                 Condition cond = AL, SetCc set_cc = kCcDontCare);
77173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  void EmitShift(Register rd, Register rn, Shift shift, Register rm,
77273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko                 Condition cond = AL, SetCc set_cc = kCcDontCare);
77365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
7746fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko  static int32_t GetAllowedLoadOffsetBits(LoadOperandType type);
7756fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko  static int32_t GetAllowedStoreOffsetBits(StoreOperandType type);
7766fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko  bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits,
7776fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                               int32_t offset,
7786fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                               /*out*/ int32_t* add_to_base,
7796fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                               /*out*/ int32_t* offset_for_load_store);
7806fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko  int32_t AdjustLoadStoreOffset(int32_t allowed_offset_bits,
7816fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                                Register temp,
7826fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                                Register base,
7836fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                                int32_t offset,
7846fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko                                Condition cond);
7856fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko
786d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray  // Whether the assembler can relocate branches. If false, unresolved branches will be
787d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray  // emitted on 32bits.
788d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray  bool can_relocate_branches_;
789d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray
790d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray  // Force the assembler to use 32 bit thumb2 instructions.
791d126ba19a2a3352fedbe43ed628ab60ccd401424Nicolas Geoffray  bool force_32bit_;
79265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
79365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  // IfThen conditions.  Used to check that conditional instructions match the preceding IT.
79465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  Condition it_conditions_[4];
79565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  uint8_t it_cond_index_;
79665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  Condition next_condition_;
79765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
79865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void SetItCondition(ItState s, Condition cond, uint8_t index);
79965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
80065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void CheckCondition(Condition cond) {
80165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    CHECK_EQ(cond, next_condition_);
80265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
80365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    // Move to the next condition if there is one.
80465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    if (it_cond_index_ < 3) {
80565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison      ++it_cond_index_;
80665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison      next_condition_ = it_conditions_[it_cond_index_];
80765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    } else {
80865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison      next_condition_ = AL;
80965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    }
81065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
81165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
81265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  void CheckConditionLastIt(Condition cond) {
81365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    if (it_cond_index_ < 3) {
81465fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison      // Check that the next condition is AL.  This means that the
81565fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison      // current condition is the last in the IT block.
81665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison      CHECK_EQ(it_conditions_[it_cond_index_ + 1], AL);
81765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    }
81865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison    CheckCondition(cond);
81965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
82065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
821cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  FixupId AddFixup(Fixup fixup) {
822cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    FixupId fixup_id = static_cast<FixupId>(fixups_.size());
823cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    fixups_.push_back(fixup);
824cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // For iterating using FixupId, we need the next id to be representable.
825cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    DCHECK_EQ(static_cast<size_t>(static_cast<FixupId>(fixups_.size())), fixups_.size());
826cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    return fixup_id;
82765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
82865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
829cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Fixup* GetFixup(FixupId fixup_id) {
830cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    DCHECK_LT(fixup_id, fixups_.size());
831cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    return &fixups_[fixup_id];
83265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
83365fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
834cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void BindLabel(Label* label, uint32_t bound_pc);
8357cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  uint32_t BindLiterals();
8367cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  void BindJumpTables(uint32_t code_size);
837cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void AdjustFixupIfNeeded(Fixup* fixup, uint32_t* current_code_size,
838cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko                           std::deque<FixupId>* fixups_to_recalculate);
839cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  uint32_t AdjustFixups();
840cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void EmitFixups(uint32_t adjusted_code_size);
841cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void EmitLiterals();
8427cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  void EmitJumpTables();
84310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void PatchCFI();
844cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
845cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int16_t BEncoding16(int32_t offset, Condition cond);
846cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t BEncoding32(int32_t offset, Condition cond);
847cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int16_t CbxzEncoding16(Register rn, int32_t offset, Condition cond);
848cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int16_t CmpRnImm8Encoding16(Register rn, int32_t value);
849cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int16_t AddRdnRmEncoding16(Register rdn, Register rm);
850cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t MovwEncoding32(Register rd, int32_t value);
851cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t MovtEncoding32(Register rd, int32_t value);
852cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t MovModImmEncoding32(Register rd, int32_t value);
853cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int16_t LdrLitEncoding16(Register rt, int32_t offset);
854cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t LdrLitEncoding32(Register rt, int32_t offset);
855cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t LdrdEncoding32(Register rt, Register rt2, Register rn, int32_t offset);
856cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t VldrsEncoding32(SRegister sd, Register rn, int32_t offset);
857cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t VldrdEncoding32(DRegister dd, Register rn, int32_t offset);
858cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int16_t LdrRtRnImm5Encoding16(Register rt, Register rn, int32_t offset);
859cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  static int32_t LdrRtRnImm12Encoding(Register rt, Register rn, int32_t offset);
8607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  static int16_t AdrEncoding16(Register rd, int32_t offset);
8617cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  static int32_t AdrEncoding32(Register rd, int32_t offset);
862cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
863d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaVector<Fixup> fixups_;
864d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaVector<FixupId> fixup_dependents_;
865cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
866cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Use std::deque<> for literal labels to allow insertions at the end
867cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // without invalidating pointers and references to existing elements.
868d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaDeque<Literal> literals_;
869cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
8707cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe  // Jump table list.
871d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaDeque<JumpTable> jump_tables_;
8727cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe
873cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Data for AdjustedPosition(), see the description there.
874cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  uint32_t last_position_adjustment_;
875cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  uint32_t last_old_position_;
876cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  FixupId last_fixup_id_;
87765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison};
87865fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
87965fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison}  // namespace arm
88065fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison}  // namespace art
88165fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
88265fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison#endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_
883