// Copyright 2015, ARM Limited
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//   * Neither the name of ARM Limited nor the names of its contributors may be
//     used to endorse or promote products derived from this software without
//     specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "jsutil.h"

#include "jit/arm64/vixl/Assembler-vixl.h"
#include "jit/Label.h"

namespace vixl {


// Assembler
void Assembler::FinalizeCode() {
#ifdef DEBUG
  finalized_ = true;
#endif
}

// Unbound Label Representation.
//
// We can have multiple branches using the same label before it is bound.
// Assembler::bind() must then be able to enumerate all the branches and patch
// them to target the final label location.
//
// When a Label is unbound with uses, its offset is pointing to the tip of a
// linked list of uses. The uses can be branches or adr/adrp instructions. In
// the case of branches, the next member in the linked list is simply encoded
// as the branch target. For adr/adrp, the relative pc offset is encoded in the
// immediate field as a signed instruction offset.
//
// In both cases, the end of the list is encoded as a 0 pc offset, i.e. the
// tail is pointing to itself.

static const ptrdiff_t kEndOfLabelUseList = 0;

BufferOffset
MozBaseAssembler::NextLink(BufferOffset cur)
{
    Instruction* link = getInstructionAt(cur);
    // Raw encoded offset.
    ptrdiff_t offset = link->ImmPCRawOffset();
    // End of the list is encoded as 0.
    if (offset == kEndOfLabelUseList)
        return BufferOffset();
    // The encoded offset is the number of instructions to move.
    return BufferOffset(cur.getOffset() + offset * kInstructionSize);
}

static ptrdiff_t
EncodeOffset(BufferOffset cur, BufferOffset next)
{
    MOZ_ASSERT(next.assigned() && cur.assigned());
    ptrdiff_t offset = next.getOffset() - cur.getOffset();
    MOZ_ASSERT(offset % kInstructionSize == 0);
    return offset / kInstructionSize;
}

void
MozBaseAssembler::SetNextLink(BufferOffset cur, BufferOffset next)
{
    Instruction* link = getInstructionAt(cur);
    link->SetImmPCRawOffset(EncodeOffset(cur, next));
}

// A common implementation for the LinkAndGet<Type>OffsetTo helpers.
//
// If the label is bound, returns the offset as a multiple of 1 << elementShift.
// Otherwise, links the instruction to the label and returns the raw offset to
// encode. (This will be an instruction count.)
//
// The offset is calculated by aligning the PC and label addresses down to a
// multiple of 1 << elementShift, then calculating the (scaled) offset between
// them. This matches the semantics of adrp, for example. (Assuming that the
// assembler buffer is page-aligned, which it probably isn't.)
//
// For an unbound label, the returned offset will be encodable in the provided
// branch range. If the label is already bound, the caller is expected to make
// sure that it is in range, and emit the necessary branch instrutions if it
// isn't.
//
ptrdiff_t
MozBaseAssembler::LinkAndGetOffsetTo(BufferOffset branch, ImmBranchRangeType branchRange,
                                     unsigned elementShift, Label* label)
{
  if (armbuffer_.oom())
    return kEndOfLabelUseList;

  if (label->bound()) {
    // The label is bound: all uses are already linked.
    ptrdiff_t branch_offset = ptrdiff_t(branch.getOffset() >> elementShift);
    ptrdiff_t label_offset = ptrdiff_t(label->offset() >> elementShift);
    return label_offset - branch_offset;
  }

  // Keep track of short-range branches targeting unbound labels. We may need
  // to insert veneers in PatchShortRangeBranchToVeneer() below.
  if (branchRange < NumShortBranchRangeTypes) {
      // This is the last possible branch target.
      BufferOffset deadline(branch.getOffset() +
                            Instruction::ImmBranchMaxForwardOffset(branchRange));
      armbuffer_.registerBranchDeadline(branchRange, deadline);
  }

  // The label is unbound and previously unused: Store the offset in the label
  // itself for patching by bind().
  if (!label->used()) {
    label->use(branch.getOffset());
    return kEndOfLabelUseList;
  }

  // The label is unbound and has multiple users. Create a linked list between
  // the branches, and update the linked list head in the label struct. This is
  // not always trivial since the branches in the linked list have limited
  // ranges.

  // What is the earliest buffer offset that would be reachable by the branch
  // we're about to add?
  ptrdiff_t earliestReachable =
    branch.getOffset() + Instruction::ImmBranchMinBackwardOffset(branchRange);

  // If the existing instruction at the head of the list is within reach of the
  // new branch, we can simply insert the new branch at the front of the list.
  if (label->offset() >= earliestReachable) {
      ptrdiff_t offset = EncodeOffset(branch, BufferOffset(label));
      label->use(branch.getOffset());
      MOZ_ASSERT(offset != kEndOfLabelUseList);
      return offset;
  }

  // The label already has a linked list of uses, but we can't reach the head
  // of the list with the allowed branch range. Insert this branch at a
  // different position in the list.
  //
  // Find an existing branch, exbr, such that:
  //
  // 1.  The new branch can be reached by exbr, and either
  // 2a. The new branch can reach exbr's target, or
  // 2b. The exbr branch is at the end of the list.
  //
  // Then the new branch can be inserted after exbr in the linked list.
  //
  // We know that it is always possible to find an exbr branch satisfying these
  // conditions because of the PatchShortRangeBranchToVeneer() mechanism. All
  // branches are guaranteed to either be able to reach the end of the
  // assembler buffer, or they will be pointing to an unconditional branch that
  // can.
  //
  // In particular, the end of the list is always a viable candidate, so we'll
  // just get that.
  BufferOffset next(label);
  BufferOffset exbr;
  do {
      exbr = next;
      next = NextLink(next);
  } while (next.assigned());
  SetNextLink(exbr, branch);

  // This branch becomes the new end of the list.
  return kEndOfLabelUseList;
}

ptrdiff_t MozBaseAssembler::LinkAndGetByteOffsetTo(BufferOffset branch, Label* label) {
  return LinkAndGetOffsetTo(branch, UncondBranchRangeType, 0, label);
}

ptrdiff_t MozBaseAssembler::LinkAndGetInstructionOffsetTo(BufferOffset branch,
                                                          ImmBranchRangeType branchRange,
                                                          Label* label) {
  return LinkAndGetOffsetTo(branch, branchRange, kInstructionSizeLog2, label);
}

ptrdiff_t MozBaseAssembler::LinkAndGetPageOffsetTo(BufferOffset branch, Label* label) {
  return LinkAndGetOffsetTo(branch, UncondBranchRangeType, kPageSizeLog2, label);
}

BufferOffset Assembler::b(int imm26) {
  return EmitBranch(B | ImmUncondBranch(imm26));
}


void Assembler::b(Instruction* at, int imm26) {
  return EmitBranch(at, B | ImmUncondBranch(imm26));
}


BufferOffset Assembler::b(int imm19, Condition cond) {
  return EmitBranch(B_cond | ImmCondBranch(imm19) | cond);
}


void Assembler::b(Instruction* at, int imm19, Condition cond) {
  EmitBranch(at, B_cond | ImmCondBranch(imm19) | cond);
}


BufferOffset Assembler::b(Label* label) {
  // Encode the relative offset from the inserted branch to the label.
  return b(LinkAndGetInstructionOffsetTo(nextInstrOffset(), UncondBranchRangeType, label));
}


BufferOffset Assembler::b(Label* label, Condition cond) {
  // Encode the relative offset from the inserted branch to the label.
  return b(LinkAndGetInstructionOffsetTo(nextInstrOffset(), CondBranchRangeType, label), cond);
}


void Assembler::blr(Instruction* at, const Register& xn) {
  VIXL_ASSERT(xn.Is64Bits());
  // No need for EmitBranch(): no immediate offset needs fixing.
  Emit(at, BLR | Rn(xn));
}


void Assembler::bl(int imm26) {
  EmitBranch(BL | ImmUncondBranch(imm26));
}


void Assembler::bl(Instruction* at, int imm26) {
  EmitBranch(at, BL | ImmUncondBranch(imm26));
}


void Assembler::bl(Label* label) {
  // Encode the relative offset from the inserted branch to the label.
  return bl(LinkAndGetInstructionOffsetTo(nextInstrOffset(), UncondBranchRangeType, label));
}


void Assembler::cbz(const Register& rt, int imm19) {
  EmitBranch(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
}


void Assembler::cbz(Instruction* at, const Register& rt, int imm19) {
  EmitBranch(at, SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
}


void Assembler::cbz(const Register& rt, Label* label) {
  // Encode the relative offset from the inserted branch to the label.
  return cbz(rt, LinkAndGetInstructionOffsetTo(nextInstrOffset(), CondBranchRangeType, label));
}


void Assembler::cbnz(const Register& rt, int imm19) {
  EmitBranch(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
}


void Assembler::cbnz(Instruction* at, const Register& rt, int imm19) {
  EmitBranch(at, SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
}


void Assembler::cbnz(const Register& rt, Label* label) {
  // Encode the relative offset from the inserted branch to the label.
  return cbnz(rt, LinkAndGetInstructionOffsetTo(nextInstrOffset(), CondBranchRangeType, label));
}


void Assembler::tbz(const Register& rt, unsigned bit_pos, int imm14) {
  VIXL_ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize)));
  EmitBranch(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
}


void Assembler::tbz(Instruction* at, const Register& rt, unsigned bit_pos, int imm14) {
  VIXL_ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize)));
  EmitBranch(at, TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
}


void Assembler::tbz(const Register& rt, unsigned bit_pos, Label* label) {
  // Encode the relative offset from the inserted branch to the label.
  return tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(nextInstrOffset(), TestBranchRangeType, label));
}


void Assembler::tbnz(const Register& rt, unsigned bit_pos, int imm14) {
  VIXL_ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize)));
  EmitBranch(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
}


void Assembler::tbnz(Instruction* at, const Register& rt, unsigned bit_pos, int imm14) {
  VIXL_ASSERT(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSize)));
  EmitBranch(at, TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
}


void Assembler::tbnz(const Register& rt, unsigned bit_pos, Label* label) {
  // Encode the relative offset from the inserted branch to the label.
  return tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(nextInstrOffset(), TestBranchRangeType, label));
}


void Assembler::adr(const Register& rd, int imm21) {
  VIXL_ASSERT(rd.Is64Bits());
  EmitBranch(ADR | ImmPCRelAddress(imm21) | Rd(rd));
}


void Assembler::adr(Instruction* at, const Register& rd, int imm21) {
  VIXL_ASSERT(rd.Is64Bits());
  EmitBranch(at, ADR | ImmPCRelAddress(imm21) | Rd(rd));
}


void Assembler::adr(const Register& rd, Label* label) {
  // Encode the relative offset from the inserted adr to the label.
  return adr(rd, LinkAndGetByteOffsetTo(nextInstrOffset(), label));
}


void Assembler::adrp(const Register& rd, int imm21) {
  VIXL_ASSERT(rd.Is64Bits());
  EmitBranch(ADRP | ImmPCRelAddress(imm21) | Rd(rd));
}


void Assembler::adrp(Instruction* at, const Register& rd, int imm21) {
  VIXL_ASSERT(rd.Is64Bits());
  EmitBranch(at, ADRP | ImmPCRelAddress(imm21) | Rd(rd));
}


void Assembler::adrp(const Register& rd, Label* label) {
  VIXL_ASSERT(AllowPageOffsetDependentCode());
  // Encode the relative offset from the inserted adr to the label.
  return adrp(rd, LinkAndGetPageOffsetTo(nextInstrOffset(), label));
}


BufferOffset Assembler::ands(const Register& rd, const Register& rn, const Operand& operand) {
  return Logical(rd, rn, operand, ANDS);
}


BufferOffset Assembler::tst(const Register& rn, const Operand& operand) {
  return ands(AppropriateZeroRegFor(rn), rn, operand);
}


void Assembler::ldr(Instruction* at, const CPURegister& rt, int imm19) {
  LoadLiteralOp op = LoadLiteralOpFor(rt);
  Emit(at, op | ImmLLiteral(imm19) | Rt(rt));
}


BufferOffset Assembler::hint(SystemHint code) {
  return Emit(HINT | ImmHint(code) | Rt(xzr));
}


void Assembler::hint(Instruction* at, SystemHint code) {
  Emit(at, HINT | ImmHint(code) | Rt(xzr));
}


void Assembler::svc(Instruction* at, int code) {
  VIXL_ASSERT(is_uint16(code));
  Emit(at, SVC | ImmException(code));
}


void Assembler::nop(Instruction* at) {
  hint(at, NOP);
}


BufferOffset Assembler::Logical(const Register& rd, const Register& rn,
                                const Operand operand, LogicalOp op)
{
  VIXL_ASSERT(rd.size() == rn.size());
  if (operand.IsImmediate()) {
    int64_t immediate = operand.immediate();
    unsigned reg_size = rd.size();

    VIXL_ASSERT(immediate != 0);
    VIXL_ASSERT(immediate != -1);
    VIXL_ASSERT(rd.Is64Bits() || is_uint32(immediate));

    // If the operation is NOT, invert the operation and immediate.
    if ((op & NOT) == NOT) {
      op = static_cast<LogicalOp>(op & ~NOT);
      immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask);
    }

    unsigned n, imm_s, imm_r;
    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
      // Immediate can be encoded in the instruction.
      return LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
    } else {
      // This case is handled in the macro assembler.
      VIXL_UNREACHABLE();
    }
  } else {
    VIXL_ASSERT(operand.IsShiftedRegister());
    VIXL_ASSERT(operand.reg().size() == rd.size());
    Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed);
    return DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op);
  }

  return BufferOffset();
}


BufferOffset Assembler::LogicalImmediate(const Register& rd, const Register& rn,
                                         unsigned n, unsigned imm_s, unsigned imm_r, LogicalOp op)
{
    unsigned reg_size = rd.size();
    Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd);
    return Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) |
                ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg | Rn(rn));
}


BufferOffset Assembler::DataProcShiftedRegister(const Register& rd, const Register& rn,
                                                const Operand& operand, FlagsUpdate S, Instr op)
{
  VIXL_ASSERT(operand.IsShiftedRegister());
  VIXL_ASSERT(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount())));
  return Emit(SF(rd) | op | Flags(S) |
              ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) |
              Rm(operand.reg()) | Rn(rn) | Rd(rd));
}


void MozBaseAssembler::InsertIndexIntoTag(uint8_t* load, uint32_t index) {
  // Store the js::jit::PoolEntry index into the instruction.
  // finishPool() will walk over all literal load instructions
  // and use PatchConstantPoolLoad() to patch to the final relative offset.
  *((uint32_t*)load) |= Assembler::ImmLLiteral(index);
}


bool MozBaseAssembler::PatchConstantPoolLoad(void* loadAddr, void* constPoolAddr) {
  Instruction* load = reinterpret_cast<Instruction*>(loadAddr);

  // The load currently contains the js::jit::PoolEntry's index,
  // as written by InsertIndexIntoTag().
  uint32_t index = load->ImmLLiteral();

  // Each entry in the literal pool is uint32_t-sized,
  // but literals may use multiple entries.
  uint32_t* constPool = reinterpret_cast<uint32_t*>(constPoolAddr);
  Instruction* source = reinterpret_cast<Instruction*>(&constPool[index]);

  load->SetImmLLiteral(source);
  return false; // Nothing uses the return value.
}

void
MozBaseAssembler::PatchShortRangeBranchToVeneer(ARMBuffer* buffer, unsigned rangeIdx,
                                                BufferOffset deadline, BufferOffset veneer)
{
  // Reconstruct the position of the branch from (rangeIdx, deadline).
  vixl::ImmBranchRangeType branchRange = static_cast<vixl::ImmBranchRangeType>(rangeIdx);
  BufferOffset branch(deadline.getOffset() - Instruction::ImmBranchMaxForwardOffset(branchRange));
  Instruction *branchInst = buffer->getInst(branch);
  Instruction *veneerInst = buffer->getInst(veneer);

  // Verify that the branch range matches what's encoded.
  MOZ_ASSERT(Instruction::ImmBranchTypeToRange(branchInst->BranchType()) == branchRange);

  // We want to insert veneer after branch in the linked list of instructions
  // that use the same unbound label.
  // The veneer should be an unconditional branch.
  ptrdiff_t nextElemOffset = branchInst->ImmPCRawOffset();

  // If offset is 0, this is the end of the linked list.
  if (nextElemOffset != kEndOfLabelUseList) {
      // Make the offset relative to veneer so it targets the same instruction
      // as branchInst.
      nextElemOffset *= kInstructionSize;
      nextElemOffset += branch.getOffset() - veneer.getOffset();
      nextElemOffset /= kInstructionSize;
  }
  Assembler::b(veneerInst, nextElemOffset);

  // Now point branchInst at veneer. See also SetNextLink() above.
  branchInst->SetImmPCRawOffset(EncodeOffset(branch, veneer));
}

struct PoolHeader {
  uint32_t data;

  struct Header {
    // The size should take into account the pool header.
    // The size is in units of Instruction (4bytes), not byte.
    union {
      struct {
        uint32_t size : 15;

	// "Natural" guards are part of the normal instruction stream,
	// while "non-natural" guards are inserted for the sole purpose
	// of skipping around a pool.
        bool isNatural : 1;
        uint32_t ONES : 16;
      };
      uint32_t data;
    };

    Header(int size_, bool isNatural_)
      : size(size_),
        isNatural(isNatural_),
        ONES(0xffff)
    { }

    Header(uint32_t data)
      : data(data)
    {
      JS_STATIC_ASSERT(sizeof(Header) == sizeof(uint32_t));
      VIXL_ASSERT(ONES == 0xffff);
    }

    uint32_t raw() const {
      JS_STATIC_ASSERT(sizeof(Header) == sizeof(uint32_t));
      return data;
    }
  };

  PoolHeader(int size_, bool isNatural_)
    : data(Header(size_, isNatural_).raw())
  { }

  uint32_t size() const {
    Header tmp(data);
    return tmp.size;
  }

  uint32_t isNatural() const {
    Header tmp(data);
    return tmp.isNatural;
  }
};


void MozBaseAssembler::WritePoolHeader(uint8_t* start, js::jit::Pool* p, bool isNatural) {
  JS_STATIC_ASSERT(sizeof(PoolHeader) == 4);

  // Get the total size of the pool.
  const uintptr_t totalPoolSize = sizeof(PoolHeader) + p->getPoolSize();
  const uintptr_t totalPoolInstructions = totalPoolSize / sizeof(Instruction);

  VIXL_ASSERT((totalPoolSize & 0x3) == 0);
  VIXL_ASSERT(totalPoolInstructions < (1 << 15));

  PoolHeader header(totalPoolInstructions, isNatural);
  *(PoolHeader*)start = header;
}


void MozBaseAssembler::WritePoolFooter(uint8_t* start, js::jit::Pool* p, bool isNatural) {
  return;
}


void MozBaseAssembler::WritePoolGuard(BufferOffset branch, Instruction* inst, BufferOffset dest) {
  int byteOffset = dest.getOffset() - branch.getOffset();
  VIXL_ASSERT(byteOffset % kInstructionSize == 0);

  int instOffset = byteOffset >> kInstructionSizeLog2;
  Assembler::b(inst, instOffset);
}


ptrdiff_t MozBaseAssembler::GetBranchOffset(const Instruction* ins) {
  // Branch instructions use an instruction offset.
  if (ins->BranchType() != UnknownBranchType)
    return ins->ImmPCRawOffset() * kInstructionSize;

  // ADR and ADRP encode relative offsets and therefore require patching as if they were branches.
  // ADR uses a byte offset.
  if (ins->IsADR())
    return ins->ImmPCRawOffset();

  // ADRP uses a page offset.
  if (ins->IsADRP())
    return ins->ImmPCRawOffset() * kPageSize;

  MOZ_CRASH("Unsupported branch type");
}


void MozBaseAssembler::RetargetNearBranch(Instruction* i, int offset, Condition cond, bool final) {
  if (i->IsCondBranchImm()) {
    VIXL_ASSERT(i->IsCondB());
    Assembler::b(i, offset, cond);
    return;
  }
  MOZ_CRASH("Unsupported branch type");
}


void MozBaseAssembler::RetargetNearBranch(Instruction* i, int byteOffset, bool final) {
  const int instOffset = byteOffset >> kInstructionSizeLog2;

  // The only valid conditional instruction is B.
  if (i->IsCondBranchImm()) {
    VIXL_ASSERT(byteOffset % kInstructionSize == 0);
    VIXL_ASSERT(i->IsCondB());
    Condition cond = static_cast<Condition>(i->ConditionBranch());
    Assembler::b(i, instOffset, cond);
    return;
  }

  // Valid unconditional branches are B and BL.
  if (i->IsUncondBranchImm()) {
    VIXL_ASSERT(byteOffset % kInstructionSize == 0);
    if (i->IsUncondB()) {
      Assembler::b(i, instOffset);
    } else {
      VIXL_ASSERT(i->IsBL());
      Assembler::bl(i, instOffset);
    }

    VIXL_ASSERT(i->ImmUncondBranch() == instOffset);
    return;
  }

  // Valid compare branches are CBZ and CBNZ.
  if (i->IsCompareBranch()) {
    VIXL_ASSERT(byteOffset % kInstructionSize == 0);
    Register rt = i->SixtyFourBits() ? Register::XRegFromCode(i->Rt())
                                     : Register::WRegFromCode(i->Rt());

    if (i->IsCBZ()) {
      Assembler::cbz(i, rt, instOffset);
    } else {
      VIXL_ASSERT(i->IsCBNZ());
      Assembler::cbnz(i, rt, instOffset);
    }

    VIXL_ASSERT(i->ImmCmpBranch() == instOffset);
    return;
  }

  // Valid test branches are TBZ and TBNZ.
  if (i->IsTestBranch()) {
    VIXL_ASSERT(byteOffset % kInstructionSize == 0);
    // Opposite of ImmTestBranchBit(): MSB in bit 5, 0:5 at bit 40.
    unsigned bit_pos = (i->ImmTestBranchBit5() << 5) | (i->ImmTestBranchBit40());
    VIXL_ASSERT(is_uint6(bit_pos));

    // Register size doesn't matter for the encoding.
    Register rt = Register::XRegFromCode(i->Rt());

    if (i->IsTBZ()) {
      Assembler::tbz(i, rt, bit_pos, instOffset);
    } else {
      VIXL_ASSERT(i->IsTBNZ());
      Assembler::tbnz(i, rt, bit_pos, instOffset);
    }

    VIXL_ASSERT(i->ImmTestBranch() == instOffset);
    return;
  }

  if (i->IsADR()) {
    Register rd = Register::XRegFromCode(i->Rd());
    Assembler::adr(i, rd, byteOffset);
    return;
  }

  if (i->IsADRP()) {
    const int pageOffset = byteOffset >> kPageSizeLog2;
    Register rd = Register::XRegFromCode(i->Rd());
    Assembler::adrp(i, rd, pageOffset);
    return;
  }

  MOZ_CRASH("Unsupported branch type");
}


void MozBaseAssembler::RetargetFarBranch(Instruction* i, uint8_t** slot, uint8_t* dest, Condition cond) {
  MOZ_CRASH("RetargetFarBranch()");
}


}  // namespace vixl

