// Copyright 2017, VIXL authors
// 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.

extern "C" {
#include <stdint.h>
}

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>

#include "utils-vixl.h"
#include "aarch32/assembler-aarch32.h"
#include "aarch32/constants-aarch32.h"
#include "aarch32/instructions-aarch32.h"
#include "aarch32/operands-aarch32.h"

namespace vixl {
namespace aarch32 {

void Assembler::EmitT32_16(uint16_t instr) {
  VIXL_ASSERT(buffer_.Is16bitAligned());
  buffer_.Emit16(instr);
}


void Assembler::EmitT32_32(uint32_t instr) {
  VIXL_ASSERT(buffer_.Is16bitAligned());
  buffer_.Emit16(static_cast<uint16_t>(instr >> 16));
  buffer_.Emit16(static_cast<uint16_t>(instr & 0xffff));
}


void Assembler::EmitA32(uint32_t instr) {
  VIXL_ASSERT(buffer_.Is32bitAligned());
  buffer_.Emit32(instr);
}


#ifdef VIXL_DEBUG
void Assembler::PerformCheckIT(Condition condition) {
  if (it_mask_ == 0) {
    VIXL_ASSERT(IsUsingA32() || condition.Is(al));
  } else {
    VIXL_ASSERT(condition.Is(first_condition_));
    // For A32, AdavanceIT() is not called by the assembler. We must call it
    // in order to check that IT instructions are used consistently with
    // the following conditional instructions.
    if (IsUsingA32()) AdvanceIT();
  }
}
#endif


void Assembler::BindHelper(Label* label) {
  VIXL_ASSERT(!label->IsBound());
  label->SetLocation(this, GetCursorOffset());
  label->MarkBound();
}

uint32_t Assembler::Link(uint32_t instr,
                         Location* location,
                         const Location::EmitOperator& op,
                         const ReferenceInfo* info) {
  location->SetReferenced();
  if (location->IsBound()) {
    return op.Encode(instr, GetCursorOffset(), location);
  }
  location->AddForwardRef(GetCursorOffset(), op, info);
  return instr;
}


// Start of generated code.
class Dt_L_imm6_1 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_L_imm6_1(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      type_ = 0x0;
      SetEncodingValue(0x1);
      break;
    case U8:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S16:
      type_ = 0x0;
      SetEncodingValue(0x2);
      break;
    case U16:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    case S32:
      type_ = 0x0;
      SetEncodingValue(0x4);
      break;
    case U32:
      type_ = 0x1;
      SetEncodingValue(0x4);
      break;
    case S64:
      type_ = 0x0;
      SetEncodingValue(0x8);
      break;
    case U64:
      type_ = 0x1;
      SetEncodingValue(0x8);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_L_imm6_2 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_L_imm6_2(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S16:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    case S32:
      type_ = 0x1;
      SetEncodingValue(0x4);
      break;
    case S64:
      type_ = 0x1;
      SetEncodingValue(0x8);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_L_imm6_3 : public EncodingValue {
 public:
  explicit Dt_L_imm6_3(DataType dt);
};

Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
  switch (dt.GetValue()) {
    case I8:
      SetEncodingValue(0x1);
      break;
    case I16:
      SetEncodingValue(0x2);
      break;
    case I32:
      SetEncodingValue(0x4);
      break;
    case I64:
      SetEncodingValue(0x8);
      break;
    default:
      break;
  }
}

class Dt_L_imm6_4 : public EncodingValue {
 public:
  explicit Dt_L_imm6_4(DataType dt);
};

Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x1);
      break;
    case Untyped16:
      SetEncodingValue(0x2);
      break;
    case Untyped32:
      SetEncodingValue(0x4);
      break;
    case Untyped64:
      SetEncodingValue(0x8);
      break;
    default:
      break;
  }
}

class Dt_imm6_1 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_imm6_1(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_imm6_1::Dt_imm6_1(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      type_ = 0x0;
      SetEncodingValue(0x1);
      break;
    case U16:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S32:
      type_ = 0x0;
      SetEncodingValue(0x2);
      break;
    case U32:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    case S64:
      type_ = 0x0;
      SetEncodingValue(0x4);
      break;
    case U64:
      type_ = 0x1;
      SetEncodingValue(0x4);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_imm6_2 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_imm6_2(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_imm6_2::Dt_imm6_2(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S32:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    case S64:
      type_ = 0x1;
      SetEncodingValue(0x4);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_imm6_3 : public EncodingValue {
 public:
  explicit Dt_imm6_3(DataType dt);
};

Dt_imm6_3::Dt_imm6_3(DataType dt) {
  switch (dt.GetValue()) {
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    case I64:
      SetEncodingValue(0x4);
      break;
    default:
      break;
  }
}

class Dt_imm6_4 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_imm6_4(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_imm6_4::Dt_imm6_4(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      type_ = 0x0;
      SetEncodingValue(0x1);
      break;
    case U8:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S16:
      type_ = 0x0;
      SetEncodingValue(0x2);
      break;
    case U16:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    case S32:
      type_ = 0x0;
      SetEncodingValue(0x4);
      break;
    case U32:
      type_ = 0x1;
      SetEncodingValue(0x4);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_op_U_size_1 : public EncodingValue {
 public:
  explicit Dt_op_U_size_1(DataType dt);
};

Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x0);
      break;
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    case U8:
      SetEncodingValue(0x4);
      break;
    case U16:
      SetEncodingValue(0x5);
      break;
    case U32:
      SetEncodingValue(0x6);
      break;
    case P8:
      SetEncodingValue(0x8);
      break;
    case P64:
      SetEncodingValue(0xa);
      break;
    default:
      break;
  }
}

class Dt_op_size_1 : public EncodingValue {
 public:
  explicit Dt_op_size_1(DataType dt);
};

Dt_op_size_1::Dt_op_size_1(DataType dt) {
  switch (dt.GetValue()) {
    case I8:
      SetEncodingValue(0x0);
      break;
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    case P8:
      SetEncodingValue(0x4);
      break;
    default:
      break;
  }
}

class Dt_op_size_2 : public EncodingValue {
 public:
  explicit Dt_op_size_2(DataType dt);
};

Dt_op_size_2::Dt_op_size_2(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x0);
      break;
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    case U8:
      SetEncodingValue(0x4);
      break;
    case U16:
      SetEncodingValue(0x5);
      break;
    case U32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_op_size_3 : public EncodingValue {
 public:
  explicit Dt_op_size_3(DataType dt);
};

Dt_op_size_3::Dt_op_size_3(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      SetEncodingValue(0x0);
      break;
    case S32:
      SetEncodingValue(0x1);
      break;
    case S64:
      SetEncodingValue(0x2);
      break;
    case U16:
      SetEncodingValue(0x4);
      break;
    case U32:
      SetEncodingValue(0x5);
      break;
    case U64:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_U_imm3H_1 : public EncodingValue {
 public:
  explicit Dt_U_imm3H_1(DataType dt);
};

Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x1);
      break;
    case S16:
      SetEncodingValue(0x2);
      break;
    case S32:
      SetEncodingValue(0x4);
      break;
    case U8:
      SetEncodingValue(0x9);
      break;
    case U16:
      SetEncodingValue(0xa);
      break;
    case U32:
      SetEncodingValue(0xc);
      break;
    default:
      break;
  }
}

class Dt_U_opc1_opc2_1 : public EncodingValue {
 public:
  explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
};

Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
  switch (dt.GetValue()) {
    case S8:
      if ((lane.GetLane() & 7) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x8 | lane.GetLane());
      break;
    case S16:
      if ((lane.GetLane() & 3) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x1 | (lane.GetLane() << 1));
      break;
    case U8:
      if ((lane.GetLane() & 7) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x18 | lane.GetLane());
      break;
    case U16:
      if ((lane.GetLane() & 3) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x11 | (lane.GetLane() << 1));
      break;
    case Untyped32:
      if ((lane.GetLane() & 1) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x0 | (lane.GetLane() << 2));
      break;
    case kDataTypeValueNone:
      if ((lane.GetLane() & 1) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x0 | (lane.GetLane() << 2));
      break;
    default:
      break;
  }
}

class Dt_opc1_opc2_1 : public EncodingValue {
 public:
  explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
};

Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
  switch (dt.GetValue()) {
    case Untyped8:
      if ((lane.GetLane() & 7) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x8 | lane.GetLane());
      break;
    case Untyped16:
      if ((lane.GetLane() & 3) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x1 | (lane.GetLane() << 1));
      break;
    case Untyped32:
      if ((lane.GetLane() & 1) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x0 | (lane.GetLane() << 2));
      break;
    case kDataTypeValueNone:
      if ((lane.GetLane() & 1) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x0 | (lane.GetLane() << 2));
      break;
    default:
      break;
  }
}

class Dt_imm4_1 : public EncodingValue {
 public:
  explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
};

Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
  switch (dt.GetValue()) {
    case Untyped8:
      if ((lane.GetLane() & 7) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x1 | (lane.GetLane() << 1));
      break;
    case Untyped16:
      if ((lane.GetLane() & 3) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x2 | (lane.GetLane() << 2));
      break;
    case Untyped32:
      if ((lane.GetLane() & 1) != lane.GetLane()) {
        return;
      }
      SetEncodingValue(0x4 | (lane.GetLane() << 3));
      break;
    default:
      break;
  }
}

class Dt_B_E_1 : public EncodingValue {
 public:
  explicit Dt_B_E_1(DataType dt);
};

Dt_B_E_1::Dt_B_E_1(DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x2);
      break;
    case Untyped16:
      SetEncodingValue(0x1);
      break;
    case Untyped32:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Dt_op_1 : public EncodingValue {
 public:
  Dt_op_1(DataType dt1, DataType dt2);
};

Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
  if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
    SetEncodingValue(0x0);
    return;
  }
  if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
    SetEncodingValue(0x1);
    return;
  }
  if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
    SetEncodingValue(0x2);
    return;
  }
  if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
    SetEncodingValue(0x3);
    return;
  }
}

class Dt_op_2 : public EncodingValue {
 public:
  explicit Dt_op_2(DataType dt);
};

Dt_op_2::Dt_op_2(DataType dt) {
  switch (dt.GetValue()) {
    case U32:
      SetEncodingValue(0x0);
      break;
    case S32:
      SetEncodingValue(0x1);
      break;
    default:
      break;
  }
}

class Dt_op_3 : public EncodingValue {
 public:
  explicit Dt_op_3(DataType dt);
};

Dt_op_3::Dt_op_3(DataType dt) {
  switch (dt.GetValue()) {
    case S32:
      SetEncodingValue(0x0);
      break;
    case U32:
      SetEncodingValue(0x1);
      break;
    default:
      break;
  }
}

class Dt_U_sx_1 : public EncodingValue {
 public:
  explicit Dt_U_sx_1(DataType dt);
};

Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      SetEncodingValue(0x0);
      break;
    case S32:
      SetEncodingValue(0x1);
      break;
    case U16:
      SetEncodingValue(0x2);
      break;
    case U32:
      SetEncodingValue(0x3);
      break;
    default:
      break;
  }
}

class Dt_op_U_1 : public EncodingValue {
 public:
  Dt_op_U_1(DataType dt1, DataType dt2);
};

Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
  if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
    SetEncodingValue(0x0);
    return;
  }
  if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
    SetEncodingValue(0x1);
    return;
  }
  if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
    SetEncodingValue(0x2);
    return;
  }
  if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
    SetEncodingValue(0x3);
    return;
  }
}

class Dt_sz_1 : public EncodingValue {
 public:
  explicit Dt_sz_1(DataType dt);
};

Dt_sz_1::Dt_sz_1(DataType dt) {
  switch (dt.GetValue()) {
    case F32:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Dt_F_size_1 : public EncodingValue {
 public:
  explicit Dt_F_size_1(DataType dt);
};

Dt_F_size_1::Dt_F_size_1(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x0);
      break;
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    case F32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_F_size_2 : public EncodingValue {
 public:
  explicit Dt_F_size_2(DataType dt);
};

Dt_F_size_2::Dt_F_size_2(DataType dt) {
  switch (dt.GetValue()) {
    case I8:
      SetEncodingValue(0x0);
      break;
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    case F32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_F_size_3 : public EncodingValue {
 public:
  explicit Dt_F_size_3(DataType dt);
};

Dt_F_size_3::Dt_F_size_3(DataType dt) {
  switch (dt.GetValue()) {
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    case F32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_F_size_4 : public EncodingValue {
 public:
  explicit Dt_F_size_4(DataType dt);
};

Dt_F_size_4::Dt_F_size_4(DataType dt) {
  switch (dt.GetValue()) {
    case U32:
      SetEncodingValue(0x2);
      break;
    case F32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_U_size_1 : public EncodingValue {
 public:
  explicit Dt_U_size_1(DataType dt);
};

Dt_U_size_1::Dt_U_size_1(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x0);
      break;
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    case U8:
      SetEncodingValue(0x4);
      break;
    case U16:
      SetEncodingValue(0x5);
      break;
    case U32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_U_size_2 : public EncodingValue {
 public:
  explicit Dt_U_size_2(DataType dt);
};

Dt_U_size_2::Dt_U_size_2(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    case U16:
      SetEncodingValue(0x5);
      break;
    case U32:
      SetEncodingValue(0x6);
      break;
    default:
      break;
  }
}

class Dt_U_size_3 : public EncodingValue {
 public:
  explicit Dt_U_size_3(DataType dt);
};

Dt_U_size_3::Dt_U_size_3(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x0);
      break;
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    case S64:
      SetEncodingValue(0x3);
      break;
    case U8:
      SetEncodingValue(0x4);
      break;
    case U16:
      SetEncodingValue(0x5);
      break;
    case U32:
      SetEncodingValue(0x6);
      break;
    case U64:
      SetEncodingValue(0x7);
      break;
    default:
      break;
  }
}

class Dt_size_1 : public EncodingValue {
 public:
  explicit Dt_size_1(DataType dt);
};

Dt_size_1::Dt_size_1(DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Dt_size_2 : public EncodingValue {
 public:
  explicit Dt_size_2(DataType dt);
};

Dt_size_2::Dt_size_2(DataType dt) {
  switch (dt.GetValue()) {
    case I8:
      SetEncodingValue(0x0);
      break;
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    case I64:
      SetEncodingValue(0x3);
      break;
    default:
      break;
  }
}

class Dt_size_3 : public EncodingValue {
 public:
  explicit Dt_size_3(DataType dt);
};

Dt_size_3::Dt_size_3(DataType dt) {
  switch (dt.GetValue()) {
    case I16:
      SetEncodingValue(0x0);
      break;
    case I32:
      SetEncodingValue(0x1);
      break;
    case I64:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_4 : public EncodingValue {
 public:
  explicit Dt_size_4(DataType dt);
};

Dt_size_4::Dt_size_4(DataType dt) {
  switch (dt.GetValue()) {
    case I8:
      SetEncodingValue(0x0);
      break;
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_5 : public EncodingValue {
 public:
  explicit Dt_size_5(DataType dt);
};

Dt_size_5::Dt_size_5(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      SetEncodingValue(0x0);
      break;
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_6 : public EncodingValue {
 public:
  explicit Dt_size_6(DataType dt);
};

Dt_size_6::Dt_size_6(DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x0);
      break;
    case Untyped16:
      SetEncodingValue(0x1);
      break;
    case Untyped32:
      SetEncodingValue(0x2);
      break;
    case Untyped64:
      SetEncodingValue(0x3);
      break;
    default:
      break;
  }
}

class Dt_size_7 : public EncodingValue {
 public:
  explicit Dt_size_7(DataType dt);
};

Dt_size_7::Dt_size_7(DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x0);
      break;
    case Untyped16:
      SetEncodingValue(0x1);
      break;
    case Untyped32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_8 : public EncodingValue {
 public:
  Dt_size_8(DataType dt, Alignment align);
};

Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x0);
      break;
    case Untyped16:
      SetEncodingValue(0x1);
      break;
    case Untyped32:
      if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
        SetEncodingValue(0x2);
      } else if (align.Is(k128BitAlign)) {
        SetEncodingValue(0x3);
      }
      break;
    default:
      break;
  }
}

class Dt_size_9 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_size_9(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_size_9::Dt_size_9(DataType dt) {
  switch (dt.GetValue()) {
    case I16:
      type_ = 0x0;
      SetEncodingValue(0x1);
      break;
    case I32:
      type_ = 0x0;
      SetEncodingValue(0x2);
      break;
    case F32:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_size_10 : public EncodingValue {
 public:
  explicit Dt_size_10(DataType dt);
};

Dt_size_10::Dt_size_10(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
    case U8:
    case I8:
      SetEncodingValue(0x0);
      break;
    case S16:
    case U16:
    case I16:
      SetEncodingValue(0x1);
      break;
    case S32:
    case U32:
    case I32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_11 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_size_11(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_size_11::Dt_size_11(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      type_ = 0x0;
      SetEncodingValue(0x1);
      break;
    case U16:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S32:
      type_ = 0x0;
      SetEncodingValue(0x2);
      break;
    case U32:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_size_12 : public EncodingValue {
  uint32_t type_;

 public:
  explicit Dt_size_12(DataType dt);
  uint32_t GetTypeEncodingValue() const { return type_; }
};

Dt_size_12::Dt_size_12(DataType dt) {
  switch (dt.GetValue()) {
    case S8:
      type_ = 0x0;
      SetEncodingValue(0x0);
      break;
    case U8:
      type_ = 0x1;
      SetEncodingValue(0x0);
      break;
    case S16:
      type_ = 0x0;
      SetEncodingValue(0x1);
      break;
    case U16:
      type_ = 0x1;
      SetEncodingValue(0x1);
      break;
    case S32:
      type_ = 0x0;
      SetEncodingValue(0x2);
      break;
    case U32:
      type_ = 0x1;
      SetEncodingValue(0x2);
      break;
    default:
      VIXL_UNREACHABLE();
      type_ = 0x0;
      break;
  }
}

class Dt_size_13 : public EncodingValue {
 public:
  explicit Dt_size_13(DataType dt);
};

Dt_size_13::Dt_size_13(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      SetEncodingValue(0x1);
      break;
    case S32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_14 : public EncodingValue {
 public:
  explicit Dt_size_14(DataType dt);
};

Dt_size_14::Dt_size_14(DataType dt) {
  switch (dt.GetValue()) {
    case S16:
      SetEncodingValue(0x0);
      break;
    case S32:
      SetEncodingValue(0x1);
      break;
    case S64:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_15 : public EncodingValue {
 public:
  explicit Dt_size_15(DataType dt);
};

Dt_size_15::Dt_size_15(DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8:
      SetEncodingValue(0x0);
      break;
    case Untyped16:
      SetEncodingValue(0x1);
      break;
    default:
      break;
  }
}

class Dt_size_16 : public EncodingValue {
 public:
  explicit Dt_size_16(DataType dt);
};

Dt_size_16::Dt_size_16(DataType dt) {
  switch (dt.GetValue()) {
    case F32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Dt_size_17 : public EncodingValue {
 public:
  explicit Dt_size_17(DataType dt);
};

Dt_size_17::Dt_size_17(DataType dt) {
  switch (dt.GetValue()) {
    case I8:
      SetEncodingValue(0x0);
      break;
    case I16:
      SetEncodingValue(0x1);
      break;
    case I32:
      SetEncodingValue(0x2);
      break;
    default:
      break;
  }
}

class Index_1 : public EncodingValue {
 public:
  Index_1(const NeonRegisterList& nreglist, DataType dt);
};

Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8: {
      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
        return;
      }
      uint32_t value = nreglist.GetTransferLane() << 1;
      if (!nreglist.IsSingleSpaced()) return;
      SetEncodingValue(value);
      break;
    }
    case Untyped16: {
      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
        return;
      }
      uint32_t value = nreglist.GetTransferLane() << 2;
      if (nreglist.IsDoubleSpaced()) value |= 2;
      SetEncodingValue(value);
      break;
    }
    case Untyped32: {
      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
        return;
      }
      uint32_t value = nreglist.GetTransferLane() << 3;
      if (nreglist.IsDoubleSpaced()) value |= 4;
      SetEncodingValue(value);
      break;
    }
    default:
      break;
  }
}

class Align_index_align_1 : public EncodingValue {
 public:
  Align_index_align_1(Alignment align,
                      const NeonRegisterList& nreglist,
                      DataType dt);
};

Align_index_align_1::Align_index_align_1(Alignment align,
                                         const NeonRegisterList& nreglist,
                                         DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8: {
      uint32_t value;
      if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 1;
      SetEncodingValue(value);
      break;
    }
    case Untyped16: {
      uint32_t value;
      if (align.GetType() == k16BitAlign) {
        value = 1;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 2;
      SetEncodingValue(value);
      break;
    }
    case Untyped32: {
      uint32_t value;
      if (align.GetType() == k32BitAlign) {
        value = 3;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 3;
      SetEncodingValue(value);
      break;
    }
    default:
      break;
  }
}

class Align_index_align_2 : public EncodingValue {
 public:
  Align_index_align_2(Alignment align,
                      const NeonRegisterList& nreglist,
                      DataType dt);
};

Align_index_align_2::Align_index_align_2(Alignment align,
                                         const NeonRegisterList& nreglist,
                                         DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8: {
      uint32_t value;
      if (align.GetType() == k16BitAlign) {
        value = 1;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 1;
      if (!nreglist.IsSingleSpaced()) return;
      SetEncodingValue(value);
      break;
    }
    case Untyped16: {
      uint32_t value;
      if (align.GetType() == k32BitAlign) {
        value = 1;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 2;
      if (nreglist.IsDoubleSpaced()) value |= 2;
      SetEncodingValue(value);
      break;
    }
    case Untyped32: {
      uint32_t value;
      if (align.GetType() == k64BitAlign) {
        value = 1;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 3;
      if (nreglist.IsDoubleSpaced()) value |= 4;
      SetEncodingValue(value);
      break;
    }
    default:
      break;
  }
}

class Align_index_align_3 : public EncodingValue {
 public:
  Align_index_align_3(Alignment align,
                      const NeonRegisterList& nreglist,
                      DataType dt);
};

Align_index_align_3::Align_index_align_3(Alignment align,
                                         const NeonRegisterList& nreglist,
                                         DataType dt) {
  switch (dt.GetValue()) {
    case Untyped8: {
      uint32_t value;
      if (align.GetType() == k32BitAlign) {
        value = 1;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 1;
      if (!nreglist.IsSingleSpaced()) return;
      SetEncodingValue(value);
      break;
    }
    case Untyped16: {
      uint32_t value;
      if (align.GetType() == k64BitAlign) {
        value = 1;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 2;
      if (nreglist.IsDoubleSpaced()) value |= 2;
      SetEncodingValue(value);
      break;
    }
    case Untyped32: {
      uint32_t value;
      if (align.GetType() == k64BitAlign) {
        value = 1;
      } else if (align.GetType() == k128BitAlign) {
        value = 2;
      } else if (align.GetType() == kNoAlignment) {
        value = 0;
      } else {
        return;
      }
      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
        return;
      }
      value |= nreglist.GetTransferLane() << 3;
      if (nreglist.IsDoubleSpaced()) value |= 4;
      SetEncodingValue(value);
      break;
    }
    default:
      break;
  }
}

class Align_a_1 : public EncodingValue {
 public:
  Align_a_1(Alignment align, DataType dt);
};

Align_a_1::Align_a_1(Alignment align, DataType dt) {
  switch (align.GetType()) {
    case k16BitAlign:
      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
      break;
    case k32BitAlign:
      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_a_2 : public EncodingValue {
 public:
  Align_a_2(Alignment align, DataType dt);
};

Align_a_2::Align_a_2(Alignment align, DataType dt) {
  switch (align.GetType()) {
    case k16BitAlign:
      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
      break;
    case k32BitAlign:
      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
      break;
    case k64BitAlign:
      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_a_3 : public EncodingValue {
 public:
  Align_a_3(Alignment align, DataType dt);
};

Align_a_3::Align_a_3(Alignment align, DataType dt) {
  switch (align.GetType()) {
    case k32BitAlign:
      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
      break;
    case k64BitAlign:
      if (dt.Is(Untyped16))
        SetEncodingValue(0x1);
      else if (dt.Is(Untyped32))
        SetEncodingValue(0x1);
      break;
    case k128BitAlign:
      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_align_1 : public EncodingValue {
 public:
  Align_align_1(Alignment align, const NeonRegisterList& nreglist);
};

Align_align_1::Align_align_1(Alignment align,
                             const NeonRegisterList& nreglist) {
  switch (align.GetType()) {
    case k64BitAlign:
      SetEncodingValue(0x1);
      break;
    case k128BitAlign:
      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
        SetEncodingValue(0x2);
      break;
    case k256BitAlign:
      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
        SetEncodingValue(0x3);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_align_2 : public EncodingValue {
 public:
  Align_align_2(Alignment align, const NeonRegisterList& nreglist);
};

Align_align_2::Align_align_2(Alignment align,
                             const NeonRegisterList& nreglist) {
  switch (align.GetType()) {
    case k64BitAlign:
      SetEncodingValue(0x1);
      break;
    case k128BitAlign:
      SetEncodingValue(0x2);
      break;
    case k256BitAlign:
      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_align_3 : public EncodingValue {
 public:
  explicit Align_align_3(Alignment align);
};

Align_align_3::Align_align_3(Alignment align) {
  switch (align.GetType()) {
    case k64BitAlign:
      SetEncodingValue(0x1);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_align_4 : public EncodingValue {
 public:
  explicit Align_align_4(Alignment align);
};

Align_align_4::Align_align_4(Alignment align) {
  switch (align.GetType()) {
    case k64BitAlign:
      SetEncodingValue(0x1);
      break;
    case k128BitAlign:
      SetEncodingValue(0x2);
      break;
    case k256BitAlign:
      SetEncodingValue(0x3);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}

class Align_align_5 : public EncodingValue {
 public:
  Align_align_5(Alignment align, const NeonRegisterList& nreglist);
};

Align_align_5::Align_align_5(Alignment align,
                             const NeonRegisterList& nreglist) {
  switch (align.GetType()) {
    case k64BitAlign:
      SetEncodingValue(0x1);
      break;
    case k128BitAlign:
      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
        SetEncodingValue(0x2);
      break;
    case k256BitAlign:
      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
      break;
    case kNoAlignment:
      SetEncodingValue(0x0);
      break;
    default:
      break;
  }
}


// CBNZ{<q>} <Rn>, <label> ; T1
// CBZ{<q>} <Rn>, <label> ; T1
static const struct ReferenceInfo kT16CbzInfo =
    {k16BitT32InstructionSizeInBytes,
     0,    // Min offset.
     126,  // Max offset.
     2,    // Alignment.
     ReferenceInfo::kDontAlignPc};


// B<c>{<q>} <label> ; T1
static const struct ReferenceInfo kT16ConditionalBranchInfo =
    {k16BitT32InstructionSizeInBytes,
     -256,  // Min offset.
     254,   // Max offset.
     2,     // Alignment.
     ReferenceInfo::kDontAlignPc};


// ADR{<c>}{<q>} <Rd>, <label> ; T1
// LDR{<c>}{<q>} <Rt>, <label> ; T1
static const struct ReferenceInfo kT16DataInfo =
    {k16BitT32InstructionSizeInBytes,
     0,     // Min offset.
     1020,  // Max offset.
     4,     // Alignment.
     ReferenceInfo::kAlignPc};


// B{<c>}{<q>} <label> ; T2
static const struct ReferenceInfo kT16BranchInfo =
    {k16BitT32InstructionSizeInBytes,
     -2048,  // Min offset.
     2046,   // Max offset.
     2,      // Alignment.
     ReferenceInfo::kDontAlignPc};


// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
static const struct ReferenceInfo kT32DataInfo =
    {k32BitT32InstructionSizeInBytes,
     -1020,  // Min offset.
     1020,   // Max offset.
     4,      // Alignment.
     ReferenceInfo::kAlignPc};


// ADR{<c>}{<q>} <Rd>, <label> ; T3
// LDR{<c>}{<q>} <Rt>, <label> ; T2
// LDRB{<c>}{<q>} <Rt>, <label> ; T1
// LDRH{<c>}{<q>} <Rt>, <label> ; T1
// LDRSB{<c>}{<q>} <Rt>, <label> ; T1
// LDRSH{<c>}{<q>} <Rt>, <label> ; T1
// PLD{<c>}{<q>} <label> ; T1
// PLI{<c>}{<q>} <label> ; T3
static const struct ReferenceInfo kT32FarDataInfo =
    {k32BitT32InstructionSizeInBytes,
     -4095,  // Min offset.
     4095,   // Max offset.
     1,      // Alignment.
     ReferenceInfo::kAlignPc};


// B<c>{<q>} <label> ; T3
static const struct ReferenceInfo kT32ConditionalBranchInfo =
    {k32BitT32InstructionSizeInBytes,
     -1048576,  // Min offset.
     1048574,   // Max offset.
     2,         // Alignment.
     ReferenceInfo::kDontAlignPc};


// B{<c>}{<q>} <label> ; T4
// BL{<c>}{<q>} <label> ; T1
static const struct ReferenceInfo kT32BranchInfo =
    {k32BitT32InstructionSizeInBytes,
     -16777216,  // Min offset.
     16777214,   // Max offset.
     2,          // Alignment.
     ReferenceInfo::kDontAlignPc};


// BLX{<c>}{<q>} <label> ; T2
static const struct ReferenceInfo kT32BlxInfo =
    {k32BitT32InstructionSizeInBytes,
     -16777216,  // Min offset.
     16777212,   // Max offset.
     4,          // Alignment.
     ReferenceInfo::kAlignPc};


// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
// LDRH{<c>}{<q>} <Rt>, <label> ; A1
// LDRSB{<c>}{<q>} <Rt>, <label> ; A1
// LDRSH{<c>}{<q>} <Rt>, <label> ; A1
static const struct ReferenceInfo kA32VeryNearDataInfo =
    {kA32InstructionSizeInBytes,
     -255,  // Min offset.
     255,   // Max offset.
     1,     // Alignment.
     ReferenceInfo::kAlignPc};


// ADR{<c>}{<q>} <Rd>, <label> ; A1
static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes,
                                                 -256,  // Min offset.
                                                 256,   // Max offset.
                                                 1,     // Alignment.
                                                 ReferenceInfo::kAlignPc};


// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes,
                                                  -1020,  // Min offset.
                                                  1020,   // Max offset.
                                                  4,      // Alignment.
                                                  ReferenceInfo::kAlignPc};


// LDR{<c>}{<q>} <Rt>, <label> ; A1
// LDRB{<c>}{<q>} <Rt>, <label> ; A1
// PLD{<c>}{<q>} <label> ; A1
// PLI{<c>}{<q>} <label> ; A1
static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes,
                                                     -4095,  // Min offset.
                                                     4095,   // Max offset.
                                                     1,      // Alignment.
                                                     ReferenceInfo::kAlignPc};


// B{<c>}{<q>} <label> ; A1
// BL{<c>}{<q>} <label> ; A1
static const struct ReferenceInfo kA32BranchInfo =
    {kA32InstructionSizeInBytes,
     -33554432,  // Min offset.
     33554428,   // Max offset.
     4,          // Alignment.
     ReferenceInfo::kDontAlignPc};


// BLX{<c>}{<q>} <label> ; A2
static const struct ReferenceInfo kA32BlxInfo = {kA32InstructionSizeInBytes,
                                                 -33554432,  // Min offset.
                                                 33554430,   // Max offset.
                                                 2,          // Alignment.
                                                 ReferenceInfo::kAlignPc};


void Assembler::adc(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
}

void Assembler::adcs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
}

void Assembler::add(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
      if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
          ((imm % 4) == 0)) {
        uint32_t imm_ = imm >> 2;
        EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
        AdvanceIT();
        return;
      }
      // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
          (imm <= 7)) {
        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
        AdvanceIT();
        return;
      }
      // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
          (imm <= 255)) {
        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
      if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
          ((imm % 4) == 0)) {
        uint32_t imm_ = imm >> 2;
        EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
          ((imm % 4) == 0)) {
        uint32_t imm_ = imm >> 2;
        EmitT32_16(0xb000 | imm_);
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever() &&
          ((rn.GetCode() & 0xd) != 0xd)) {
        EmitA32(0x02800000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
                     (rm.GetCode() << 6));
          AdvanceIT();
          return;
        }
        // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
        if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
            (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
              (!rd.IsPC() || !rm.IsPC())) ||
             AllowUnpredictable())) {
          EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
        // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
        if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
            ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
             AllowUnpredictable())) {
          EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
                     ((rd.GetCode() & 0x8) << 4));
          AdvanceIT();
          return;
        }
        // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
        if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
          EmitT32_16(0x4485 | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00800000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00800010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
}

void Assembler::add(Condition cond, Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rm = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // ADD<c>{<q>} <Rdn>, <Rm> ; T2
      if (InITBlock() && !rm.Is(sp) &&
          (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
            (!rd.IsPC() || !rm.IsPC())) ||
           AllowUnpredictable())) {
        EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
                   (rm.GetCode() << 3));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kAdd, &Assembler::add, cond, rd, operand);
}

void Assembler::adds(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
          (imm <= 7)) {
        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
        AdvanceIT();
        return;
      }
      // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
          (imm <= 255)) {
        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
          !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
          !rd.Is(pc)) {
        EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
        EmitA32(0x02900000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
                     (rm.GetCode() << 6));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
          !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
          !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00900000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00900010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
}

void Assembler::adds(Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // ADDS{<q>} <Rdn>, #<imm8> ; T2
      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kAdds, &Assembler::adds, rd, operand);
}

void Assembler::addw(Condition cond,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
      if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
      if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
}

void Assembler::adr(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    int32_t neg_offset = -offset;
    // ADR{<c>}{<q>} <Rd>, <label> ; T1
    if (!size.IsWide() && rd.IsLow() &&
        ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         (!location->IsBound() && size.IsNarrow()))) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= 0) && (off <= 1020) && ((off & 0x3) == 0));
          const int32_t target = off >> 2;
          return instr | (target & 0xff);
        }
      } immop;
      EmitT32_16(
          Link(0xa000 | (rd.GetCode() << 8), location, immop, &kT16DataInfo));
      AdvanceIT();
      return;
    }
    // ADR{<c>}{<q>} <Rd>, <label> ; T2
    if (!size.IsNarrow() && location->IsBound() && (neg_offset > 0) &&
        (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
                 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
      AdvanceIT();
      return;
    }
    // ADR{<c>}{<q>} <Rd>, <label> ; T3
    if (!size.IsNarrow() &&
        (!location->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
        (!rd.IsPC() || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          int32_t target;
          if ((off >= 0) && (off <= 4095)) {
            target = off;
          } else {
            target = -off;
            VIXL_ASSERT((target >= 0) && (target <= 4095));
            // Emit the T2 encoding.
            instr |= 0x00a00000;
          }
          return instr | (target & 0xff) | ((target & 0x700) << 4) |
                 ((target & 0x800) << 15);
        }
      } immop;
      EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8),
                      location,
                      immop,
                      &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    ImmediateA32 positive_immediate_a32(offset);
    ImmediateA32 negative_immediate_a32(-offset);
    // ADR{<c>}{<q>} <Rd>, <label> ; A1
    if ((!location->IsBound() || positive_immediate_a32.IsValid()) &&
        cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          int32_t target;
          ImmediateA32 pos_imm_a32(off);
          if (pos_imm_a32.IsValid()) {
            target = pos_imm_a32.GetEncodingValue();
          } else {
            ImmediateA32 neg_imm_a32(-off);
            VIXL_ASSERT(neg_imm_a32.IsValid());
            // Emit the A2 encoding.
            target = neg_imm_a32.GetEncodingValue();
            instr = (instr & ~0x00f00000) | 0x00400000;
          }
          return instr | (target & 0xfff);
        }
      } immop;
      EmitA32(
          Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
               location,
               immop,
               &kA32AdrInfo));
      return;
    }
    // ADR{<c>}{<q>} <Rd>, <label> ; A2
    if (location->IsBound() && negative_immediate_a32.IsValid() &&
        cond.IsNotNever()) {
      EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              negative_immediate_a32.GetEncodingValue());
      return;
    }
  }
  Delegate(kAdr, &Assembler::adr, cond, size, rd, location);
}

bool Assembler::adr_info(Condition cond,
                         EncodingSize size,
                         Register rd,
                         Location* location,
                         const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // ADR{<c>}{<q>} <Rd>, <label> ; T1
    if (!size.IsWide() && rd.IsLow() && size.IsNarrow()) {
      *info = &kT16DataInfo;
      return true;
    }
    // Skipped T2, as it is a negative offset variant.
    // The minimum offset is included in the corresponding
    // positive variant.
    // ADR{<c>}{<q>} <Rd>, <label> ; T3
    if (!size.IsNarrow()) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // ADR{<c>}{<q>} <Rd>, <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32AdrInfo;
      return true;
    }
    // Skipped A2, as it is a negative offset variant.
    // The minimum offset is included in the corresponding
    // positive variant.
  }
  return false;
}

void Assembler::and_(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02000000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00000000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00000010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
}

void Assembler::ands(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
          (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02100000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00100000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00100010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
}

void Assembler::asr(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rm,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
          (imm >= 1) && (imm <= 32)) {
        uint32_t amount_ = imm % 32;
        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
                   (amount_ << 6));
        AdvanceIT();
        return;
      }
      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = imm % 32;
        EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
        uint32_t amount_ = imm % 32;
        EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
}

void Assembler::asrs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rm,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
          (imm >= 1) && (imm <= 32)) {
        uint32_t amount_ = imm % 32;
        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
                   (amount_ << 6));
        AdvanceIT();
        return;
      }
      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = imm % 32;
        EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
        uint32_t amount_ = imm % 32;
        EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
}

void Assembler::b(Condition cond, EncodingSize size, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                (GetCursorOffset() + GetArchitectureStatePCOffset())
          : 0;
  if (IsUsingT32()) {
    // B<c>{<q>} <label> ; T1
    if (OutsideITBlock() && !size.IsWide() &&
        ((location->IsBound() && (offset >= -256) && (offset <= 254) &&
          ((offset & 0x1) == 0)) ||
         (!location->IsBound() && size.IsNarrow())) &&
        !cond.Is(al) && cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -256) && (off <= 254) && ((off & 0x1) == 0));
          const int32_t target = off >> 1;
          return instr | (target & 0xff);
        }
      } immop;
      EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8),
                      location,
                      immop,
                      &kT16ConditionalBranchInfo));
      AdvanceIT();
      return;
    }
    // B{<c>}{<q>} <label> ; T2
    if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
        ((location->IsBound() && (offset >= -2048) && (offset <= 2046) &&
          ((offset & 0x1) == 0)) ||
         (!location->IsBound() && size.IsNarrow()))) {
      CheckIT(cond);
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -2048) && (off <= 2046) && ((off & 0x1) == 0));
          const int32_t target = off >> 1;
          return instr | (target & 0x7ff);
        }
      } immop;
      EmitT32_16(Link(0xe000, location, immop, &kT16BranchInfo));
      AdvanceIT();
      return;
    }
    // B<c>{<q>} <label> ; T3
    if (OutsideITBlock() && !size.IsNarrow() &&
        ((location->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
          ((offset & 0x1) == 0)) ||
         !location->IsBound()) &&
        !cond.Is(al) && cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -1048576) && (off <= 1048574) &&
                      ((off & 0x1) == 0));
          const int32_t target = off >> 1;
          return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
                 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
                 ((target & 0x80000) << 7);
        }
      } immop;
      EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22),
                      location,
                      immop,
                      &kT32ConditionalBranchInfo));
      AdvanceIT();
      return;
    }
    // B{<c>}{<q>} <label> ; T4
    if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
        ((location->IsBound() && (offset >= -16777216) &&
          (offset <= 16777214) && ((offset & 0x1) == 0)) ||
         !location->IsBound())) {
      CheckIT(cond);
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -16777216) && (off <= 16777214) &&
                      ((off & 0x1) == 0));
          int32_t target = off >> 1;
          uint32_t S = target & (1 << 23);
          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
                 ((target & 0x800000) << 3);
        }
      } immop;
      EmitT32_32(Link(0xf0009000U, location, immop, &kT32BranchInfo));
      AdvanceIT();
      return;
    }
  } else {
    // B{<c>}{<q>} <label> ; A1
    if (((location->IsBound() && (offset >= -33554432) &&
          (offset <= 33554428) && ((offset & 0x3) == 0)) ||
         !location->IsBound()) &&
        cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -33554432) && (off <= 33554428) &&
                      ((off & 0x3) == 0));
          const int32_t target = off >> 2;
          return instr | (target & 0xffffff);
        }
      } immop;
      EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28),
                   location,
                   immop,
                   &kA32BranchInfo));
      return;
    }
  }
  Delegate(kB, &Assembler::b, cond, size, location);
}

bool Assembler::b_info(Condition cond,
                       EncodingSize size,
                       Location* location,
                       const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // B<c>{<q>} <label> ; T1
    if (OutsideITBlock() && !size.IsWide() && size.IsNarrow() && !cond.Is(al) &&
        cond.IsNotNever()) {
      *info = &kT16ConditionalBranchInfo;
      return true;
    }
    // B{<c>}{<q>} <label> ; T2
    if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() && size.IsNarrow()) {
      *info = &kT16BranchInfo;
      return true;
    }
    // B<c>{<q>} <label> ; T3
    if (OutsideITBlock() && !size.IsNarrow() && !cond.Is(al) &&
        cond.IsNotNever()) {
      *info = &kT32ConditionalBranchInfo;
      return true;
    }
    // B{<c>}{<q>} <label> ; T4
    if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow()) {
      *info = &kT32BranchInfo;
      return true;
    }
  } else {
    // B{<c>}{<q>} <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32BranchInfo;
      return true;
    }
  }
  return false;
}

void Assembler::bfc(Condition cond, Register rd, uint32_t lsb, uint32_t width) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
    if ((lsb <= 31) && (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
                        AllowUnpredictable())) {
      uint32_t msb = lsb + width - 1;
      EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
                 ((lsb & 0x1c) << 10) | msb);
      AdvanceIT();
      return;
    }
  } else {
    // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
    if ((lsb <= 31) && cond.IsNotNever() &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t msb = lsb + width - 1;
      EmitA32(0x07c0001fU | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (lsb << 7) | (msb << 16));
      return;
    }
  }
  Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, width);
}

void Assembler::bfi(
    Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
    if ((lsb <= 31) && !rn.Is(pc) &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t msb = lsb + width - 1;
      EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
      AdvanceIT();
      return;
    }
  } else {
    // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
    if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t msb = lsb + width - 1;
      EmitA32(0x07c00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rn.GetCode() | (lsb << 7) | (msb << 16));
      return;
    }
  }
  Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, width);
}

void Assembler::bic(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
}

void Assembler::bics(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
}

void Assembler::bkpt(Condition cond, uint32_t imm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // BKPT{<q>} {#}<imm> ; T1
    if ((imm <= 255)) {
      EmitT32_16(0xbe00 | imm);
      AdvanceIT();
      return;
    }
  } else {
    // BKPT{<q>} {#}<imm> ; A1
    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
      EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
              ((imm & 0xfff0) << 4));
      return;
    }
  }
  Delegate(kBkpt, &Assembler::bkpt, cond, imm);
}

void Assembler::bl(Condition cond, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                (GetCursorOffset() + GetArchitectureStatePCOffset())
          : 0;
  if (IsUsingT32()) {
    // BL{<c>}{<q>} <label> ; T1
    if (((location->IsBound() && (offset >= -16777216) &&
          (offset <= 16777214) && ((offset & 0x1) == 0)) ||
         !location->IsBound()) &&
        (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -16777216) && (off <= 16777214) &&
                      ((off & 0x1) == 0));
          int32_t target = off >> 1;
          uint32_t S = target & (1 << 23);
          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
                 ((target & 0x800000) << 3);
        }
      } immop;
      EmitT32_32(Link(0xf000d000U, location, immop, &kT32BranchInfo));
      AdvanceIT();
      return;
    }
  } else {
    // BL{<c>}{<q>} <label> ; A1
    if (((location->IsBound() && (offset >= -33554432) &&
          (offset <= 33554428) && ((offset & 0x3) == 0)) ||
         !location->IsBound()) &&
        cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= -33554432) && (off <= 33554428) &&
                      ((off & 0x3) == 0));
          const int32_t target = off >> 2;
          return instr | (target & 0xffffff);
        }
      } immop;
      EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28),
                   location,
                   immop,
                   &kA32BranchInfo));
      return;
    }
  }
  Delegate(kBl, &Assembler::bl, cond, location);
}

bool Assembler::bl_info(Condition cond,
                        Location* location,
                        const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // BL{<c>}{<q>} <label> ; T1
    if (true) {
      *info = &kT32BranchInfo;
      return true;
    }
  } else {
    // BL{<c>}{<q>} <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32BranchInfo;
      return true;
    }
  }
  return false;
}

void Assembler::blx(Condition cond, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // BLX{<c>}{<q>} <label> ; T2
    if (((location->IsBound() && (offset >= -16777216) &&
          (offset <= 16777212) && ((offset & 0x3) == 0)) ||
         !location->IsBound()) &&
        (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -16777216) && (off <= 16777212) &&
                      ((off & 0x3) == 0));
          int32_t target = off >> 2;
          uint32_t S = target & (1 << 22);
          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
          return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
                 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
                 ((target & 0x400000) << 4);
        }
      } immop;
      EmitT32_32(Link(0xf000c000U, location, immop, &kT32BlxInfo));
      AdvanceIT();
      return;
    }
  } else {
    // BLX{<c>}{<q>} <label> ; A2
    if (((location->IsBound() && (offset >= -33554432) &&
          (offset <= 33554430) && ((offset & 0x1) == 0)) ||
         !location->IsBound())) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        static class EmitOp : public Location::EmitOperator {
         public:
          EmitOp() : Location::EmitOperator(A32) {}
          virtual uint32_t Encode(uint32_t instr,
                                  Location::Offset program_counter,
                                  const Location* loc) const VIXL_OVERRIDE {
            program_counter += kA32PcDelta;
            Location::Offset off =
                loc->GetLocation() - AlignDown(program_counter, 4);
            VIXL_ASSERT((off >= -33554432) && (off <= 33554430) &&
                        ((off & 0x1) == 0));
            const int32_t target = off >> 1;
            return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
          }
        } immop;
        EmitA32(Link(0xfa000000U, location, immop, &kA32BlxInfo));
        return;
      }
    }
  }
  Delegate(kBlx, &Assembler::blx, cond, location);
}

bool Assembler::blx_info(Condition cond,
                         Location* location,
                         const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  USE(cond);
  if (IsUsingT32()) {
    // BLX{<c>}{<q>} <label> ; T2
    if (true) {
      *info = &kT32BlxInfo;
      return true;
    }
  } else {
    // BLX{<c>}{<q>} <label> ; A2
    if (true) {
      *info = &kA32BlxInfo;
      return true;
    }
  }
  return false;
}

void Assembler::blx(Condition cond, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // BLX{<c>}{<q>} <Rm> ; T1
    if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
         AllowUnpredictable())) {
      EmitT32_16(0x4780 | (rm.GetCode() << 3));
      AdvanceIT();
      return;
    }
  } else {
    // BLX{<c>}{<q>} <Rm> ; A1
    if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
      EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
      return;
    }
  }
  Delegate(kBlx, &Assembler::blx, cond, rm);
}

void Assembler::bx(Condition cond, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // BX{<c>}{<q>} <Rm> ; T1
    if ((OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
      EmitT32_16(0x4700 | (rm.GetCode() << 3));
      AdvanceIT();
      return;
    }
  } else {
    // BX{<c>}{<q>} <Rm> ; A1
    if (cond.IsNotNever()) {
      EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
      return;
    }
  }
  Delegate(kBx, &Assembler::bx, cond, rm);
}

void Assembler::bxj(Condition cond, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // BXJ{<c>}{<q>} <Rm> ; T1
    if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
         AllowUnpredictable())) {
      EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // BXJ{<c>}{<q>} <Rm> ; A1
    if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
      EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
      return;
    }
  }
  Delegate(kBxj, &Assembler::bxj, cond, rm);
}

void Assembler::cbnz(Register rn, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                (GetCursorOffset() + GetArchitectureStatePCOffset())
          : 0;
  if (IsUsingT32()) {
    // CBNZ{<q>} <Rn>, <label> ; T1
    if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
                        (offset <= 126) && ((offset & 0x1) == 0)) ||
                       !location->IsBound())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= 0) && (off <= 126) && ((off & 0x1) == 0));
          const int32_t target = off >> 1;
          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
        }
      } immop;
      EmitT32_16(Link(0xb900 | rn.GetCode(), location, immop, &kT16CbzInfo));
      AdvanceIT();
      return;
    }
  }
  Delegate(kCbnz, &Assembler::cbnz, rn, location);
}

bool Assembler::cbnz_info(Register rn,
                          Location* location,
                          const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // CBNZ{<q>} <Rn>, <label> ; T1
    if (rn.IsLow()) {
      *info = &kT16CbzInfo;
      return true;
    }
  }
  return false;
}

void Assembler::cbz(Register rn, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                (GetCursorOffset() + GetArchitectureStatePCOffset())
          : 0;
  if (IsUsingT32()) {
    // CBZ{<q>} <Rn>, <label> ; T1
    if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
                        (offset <= 126) && ((offset & 0x1) == 0)) ||
                       !location->IsBound())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off = loc->GetLocation() - program_counter;
          VIXL_ASSERT((off >= 0) && (off <= 126) && ((off & 0x1) == 0));
          const int32_t target = off >> 1;
          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
        }
      } immop;
      EmitT32_16(Link(0xb100 | rn.GetCode(), location, immop, &kT16CbzInfo));
      AdvanceIT();
      return;
    }
  }
  Delegate(kCbz, &Assembler::cbz, rn, location);
}

bool Assembler::cbz_info(Register rn,
                         Location* location,
                         const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // CBZ{<q>} <Rn>, <label> ; T1
    if (rn.IsLow()) {
      *info = &kT16CbzInfo;
      return true;
    }
  }
  return false;
}

void Assembler::clrex(Condition cond) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CLREX{<c>}{<q>} ; T1
    EmitT32_32(0xf3bf8f2fU);
    AdvanceIT();
    return;
  } else {
    // CLREX{<c>}{<q>} ; A1
    if (cond.Is(al)) {
      EmitA32(0xf57ff01fU);
      return;
    }
  }
  Delegate(kClrex, &Assembler::clrex, cond);
}

void Assembler::clz(Condition cond, Register rd, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rm.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kClz, &Assembler::clz, cond, rd, rm);
}

void Assembler::cmn(Condition cond,
                    EncodingSize size,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // CMN{<c>}{<q>} <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // CMN{<c>}{<q>} <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03700000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
          EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01700000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01700010U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
}

void Assembler::cmp(Condition cond,
                    EncodingSize size,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
      if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
        EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // CMP{<c>}{<q>} <Rn>, #<const> ; T2
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // CMP{<c>}{<q>} <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03500000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
          EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
        // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
        if (!size.IsWide() &&
            ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
          EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
                     ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01500000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01500010U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
}

void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
    if ((cond.Is(al) || AllowUnpredictable()) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
}

void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
    if ((cond.Is(al) || AllowUnpredictable()) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
}

void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
    if ((cond.Is(al) || AllowUnpredictable()) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
}

void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
    if ((cond.Is(al) || AllowUnpredictable()) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
}

void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
    if ((cond.Is(al) || AllowUnpredictable()) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
}

void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
    if ((cond.Is(al) || AllowUnpredictable()) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
}

void Assembler::dmb(Condition cond, MemoryBarrier option) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // DMB{<c>}{<q>} {<option>} ; T1
    EmitT32_32(0xf3bf8f50U | option.GetType());
    AdvanceIT();
    return;
  } else {
    // DMB{<c>}{<q>} {<option>} ; A1
    if (cond.Is(al)) {
      EmitA32(0xf57ff050U | option.GetType());
      return;
    }
  }
  Delegate(kDmb, &Assembler::dmb, cond, option);
}

void Assembler::dsb(Condition cond, MemoryBarrier option) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // DSB{<c>}{<q>} {<option>} ; T1
    EmitT32_32(0xf3bf8f40U | option.GetType());
    AdvanceIT();
    return;
  } else {
    // DSB{<c>}{<q>} {<option>} ; A1
    if (cond.Is(al)) {
      EmitA32(0xf57ff040U | option.GetType());
      return;
    }
  }
  Delegate(kDsb, &Assembler::dsb, cond, option);
}

void Assembler::eor(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02200000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00200000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00200010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
}

void Assembler::eors(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
          (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02300000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00300000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00300010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
}

void Assembler::fldmdbx(Condition cond,
                        Register rn,
                        WriteBack write_back,
                        DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
    if (write_back.DoesWriteBack() &&
        (((dreglist.GetLength() <= 16) &&
          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
        (((dreglist.GetLength() <= 16) &&
          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              dreg.Encode(22, 12) | (len & 0xff));
      return;
    }
  }
  Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
}

void Assembler::fldmiax(Condition cond,
                        Register rn,
                        WriteBack write_back,
                        DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
    if ((((dreglist.GetLength() <= 16) &&
          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
                               (dreglist.GetLastDRegister().GetCode() < 16) &&
                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
                              AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
}

void Assembler::fstmdbx(Condition cond,
                        Register rn,
                        WriteBack write_back,
                        DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
    if (write_back.DoesWriteBack() &&
        (((dreglist.GetLength() <= 16) &&
          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
        (((dreglist.GetLength() <= 16) &&
          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              dreg.Encode(22, 12) | (len & 0xff));
      return;
    }
  }
  Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
}

void Assembler::fstmiax(Condition cond,
                        Register rn,
                        WriteBack write_back,
                        DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
    if ((((dreglist.GetLength() <= 16) &&
          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
                               (dreglist.GetLastDRegister().GetCode() < 16) &&
                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
                              AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
}

void Assembler::hlt(Condition cond, uint32_t imm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // HLT{<q>} {#}<imm> ; T1
    if ((imm <= 63)) {
      EmitT32_16(0xba80 | imm);
      AdvanceIT();
      return;
    }
  } else {
    // HLT{<q>} {#}<imm> ; A1
    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
      EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
              ((imm & 0xfff0) << 4));
      return;
    }
  }
  Delegate(kHlt, &Assembler::hlt, cond, imm);
}

void Assembler::hvc(Condition cond, uint32_t imm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // HVC{<q>} {#}<imm16> ; T1
    if ((imm <= 65535) && (OutsideITBlock() || AllowUnpredictable())) {
      EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
      AdvanceIT();
      return;
    }
  } else {
    // HVC{<q>} {#}<imm16> ; A1
    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
      EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
              ((imm & 0xfff0) << 4));
      return;
    }
  }
  Delegate(kHvc, &Assembler::hvc, cond, imm);
}

void Assembler::isb(Condition cond, MemoryBarrier option) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // ISB{<c>}{<q>} {<option>} ; T1
    EmitT32_32(0xf3bf8f60U | option.GetType());
    AdvanceIT();
    return;
  } else {
    // ISB{<c>}{<q>} {<option>} ; A1
    if (cond.Is(al)) {
      EmitA32(0xf57ff060U | option.GetType());
      return;
    }
  }
  Delegate(kIsb, &Assembler::isb, cond, option);
}

void Assembler::it(Condition cond, uint16_t mask) {
  VIXL_ASSERT(AllowAssembler());
  CheckNotIT();
  if (mask != 0) {
    if ((cond.GetCondition() & 0x1) != 0) {
      if ((mask & 0x1) != 0) {
        mask ^= 0xE;
      } else if ((mask & 0x2) != 0) {
        mask ^= 0xC;
      } else if ((mask & 0x4) != 0) {
        mask ^= 0x8;
      }
    }
    if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
    SetIT(cond, mask);
    return;
  }
  DelegateIt(cond, mask);
}

void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLda, &Assembler::lda, cond, rt, operand);
}

void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
}

void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
}

void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
}

void Assembler::ldaexd(Condition cond,
                       Register rt,
                       Register rt2,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
}

void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
}

void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
}

void Assembler::ldm(Condition cond,
                    EncodingSize size,
                    Register rn,
                    WriteBack write_back,
                    RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
    if (!size.IsWide() && rn.IsLow() &&
        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
         write_back.DoesWriteBack()) &&
        ((registers.GetList() & ~0xff) == 0)) {
      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
                 GetRegisterListEncoding(registers, 0, 8));
      AdvanceIT();
      return;
    }
    // LDM{<c>}{<q>} SP!, <registers> ; T1
    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
        registers.IsR0toR7orPC()) {
      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
                 GetRegisterListEncoding(registers, 0, 8));
      AdvanceIT();
      return;
    }
    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
}

void Assembler::ldmda(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
}

void Assembler::ldmdb(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
    if (((registers.GetList() & ~0xdfff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
}

void Assembler::ldmea(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
    if (((registers.GetList() & ~0xdfff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
}

void Assembler::ldmed(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
}

void Assembler::ldmfa(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
}

void Assembler::ldmfd(Condition cond,
                      EncodingSize size,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
    if (!size.IsWide() && rn.IsLow() &&
        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
         write_back.DoesWriteBack()) &&
        ((registers.GetList() & ~0xff) == 0)) {
      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
                 GetRegisterListEncoding(registers, 0, 8));
      AdvanceIT();
      return;
    }
    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
}

void Assembler::ldmib(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
}

void Assembler::ldr(Condition cond,
                    EncodingSize size,
                    Register rt,
                    const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
          (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
        int32_t offset_ = offset >> 2;
        EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
                   ((offset_ & 0x1f) << 6));
        AdvanceIT();
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
          ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
        int32_t offset_ = offset >> 2;
        EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
        AdvanceIT();
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
           AllowUnpredictable())) {
        EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
           AllowUnpredictable())) {
        EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
          rn.Is(pc) && operand.IsOffset() &&
          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05100000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x04100000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05300000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
          operand.IsOffset() && cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | offset_ | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rm.IsPC() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
           AllowUnpredictable())) {
        EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07100000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
      if (operand.IsShiftValid() && operand.IsPostIndex() &&
          cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x06100000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07300000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
    }
  }
  Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
}

void Assembler::ldr(Condition cond,
                    EncodingSize size,
                    Register rt,
                    Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // LDR{<c>}{<q>} <Rt>, <label> ; T1
    if (!size.IsWide() && rt.IsLow() &&
        ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         (!location->IsBound() && size.IsNarrow()))) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= 0) && (off <= 1020) && ((off & 0x3) == 0));
          const int32_t target = off >> 2;
          return instr | (target & 0xff);
        }
      } immop;
      EmitT32_16(
          Link(0x4800 | (rt.GetCode() << 8), location, immop, &kT16DataInfo));
      AdvanceIT();
      return;
    }
    // LDR{<c>}{<q>} <Rt>, <label> ; T2
    if (!size.IsNarrow() &&
        ((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
         AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12),
                      location,
                      immop,
                      &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // LDR{<c>}{<q>} <Rt>, <label> ; A1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitA32(
          Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
               location,
               immop,
               &kA32FarDataInfo));
      return;
    }
  }
  Delegate(kLdr, &Assembler::ldr, cond, size, rt, location);
}

bool Assembler::ldr_info(Condition cond,
                         EncodingSize size,
                         Register rt,
                         Location* location,
                         const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // LDR{<c>}{<q>} <Rt>, <label> ; T1
    if (!size.IsWide() && rt.IsLow() && size.IsNarrow()) {
      *info = &kT16DataInfo;
      return true;
    }
    // LDR{<c>}{<q>} <Rt>, <label> ; T2
    if (!size.IsNarrow()) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // LDR{<c>}{<q>} <Rt>, <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32FarDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::ldrb(Condition cond,
                     EncodingSize size,
                     Register rt,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
          (offset <= 31) && operand.IsOffset()) {
        EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
                   ((offset & 0x1f) << 6));
        AdvanceIT();
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05500000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x04500000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05700000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
          operand.IsOffset() && cond.IsNotNever() &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | offset_ | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07500000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
      if (operand.IsShiftValid() && operand.IsPostIndex() &&
          cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x06500000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07700000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
    }
  }
  Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
}

void Assembler::ldrb(Condition cond, Register rt, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // LDRB{<c>}{<q>} <Rt>, <label> ; T1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        !rt.Is(pc)) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12),
                      location,
                      immop,
                      &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // LDRB{<c>}{<q>} <Rt>, <label> ; A1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitA32(
          Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
               location,
               immop,
               &kA32FarDataInfo));
      return;
    }
  }
  Delegate(kLdrb, &Assembler::ldrb, cond, rt, location);
}

bool Assembler::ldrb_info(Condition cond,
                          Register rt,
                          Location* location,
                          const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // LDRB{<c>}{<q>} <Rt>, <label> ; T1
    if (!rt.Is(pc)) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // LDRB{<c>}{<q>} <Rt>, <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32FarDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::ldrd(Condition cond,
                     Register rt,
                     Register rt2,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
          operand.IsOffset() &&
          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingA32()) {
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsPostIndex() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsPreIndex() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
    }
  }
  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
}

void Assembler::ldrd(Condition cond,
                     Register rt,
                     Register rt2,
                     Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
    if (((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         !location->IsBound()) &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
          int32_t target = off >> 2;
          uint32_t U = (target >= 0);
          target = abs(target) | (U << 8);
          return instr | (target & 0xff) | ((target & 0x100) << 15);
        }
      } immop;
      EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
                      location,
                      immop,
                      &kT32DataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
    if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
        ((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
         !location->IsBound()) &&
        cond.IsNotNever() &&
        ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -255) && (off <= 255));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 8);
          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
                 ((target & 0x100) << 15);
        }
      } immop;
      EmitA32(
          Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
               location,
               immop,
               &kA32VeryNearDataInfo));
      return;
    }
  }
  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, location);
}

bool Assembler::ldrd_info(Condition cond,
                          Register rt,
                          Register rt2,
                          Location* location,
                          const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
    if (true) {
      *info = &kT32DataInfo;
      return true;
    }
  } else {
    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
    if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
        cond.IsNotNever()) {
      *info = &kA32VeryNearDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        int32_t offset_ = offset >> 2;
        EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset_ & 0xff));
        AdvanceIT();
        return;
      }
    } else {
      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
      if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
}

void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
}

void Assembler::ldrexd(Condition cond,
                       Register rt,
                       Register rt2,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
}

void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
}

void Assembler::ldrh(Condition cond,
                     EncodingSize size,
                     Register rt,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
          (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
        int32_t offset_ = offset >> 1;
        EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
                   ((offset_ & 0x1f) << 6));
        AdvanceIT();
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
          operand.IsOffset() && cond.IsNotNever() &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    } else {
      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
      if (operand.IsPostIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
      if (operand.IsPreIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
}

void Assembler::ldrh(Condition cond, Register rt, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // LDRH{<c>}{<q>} <Rt>, <label> ; T1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        !rt.Is(pc)) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12),
                      location,
                      immop,
                      &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // LDRH{<c>}{<q>} <Rt>, <label> ; A1
    if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
         !location->IsBound()) &&
        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -255) && (off <= 255));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 8);
          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
                 ((target & 0x100) << 15);
        }
      } immop;
      EmitA32(
          Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
               location,
               immop,
               &kA32VeryNearDataInfo));
      return;
    }
  }
  Delegate(kLdrh, &Assembler::ldrh, cond, rt, location);
}

bool Assembler::ldrh_info(Condition cond,
                          Register rt,
                          Location* location,
                          const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // LDRH{<c>}{<q>} <Rt>, <label> ; T1
    if (!rt.Is(pc)) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // LDRH{<c>}{<q>} <Rt>, <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32VeryNearDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::ldrsb(Condition cond,
                      EncodingSize size,
                      Register rt,
                      const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
          operand.IsOffset() && cond.IsNotNever() &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    } else {
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
      if (operand.IsPostIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
      if (operand.IsPreIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
}

void Assembler::ldrsb(Condition cond, Register rt, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        !rt.Is(pc)) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12),
                      location,
                      immop,
                      &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
    if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
         !location->IsBound()) &&
        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -255) && (off <= 255));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 8);
          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
                 ((target & 0x100) << 15);
        }
      } immop;
      EmitA32(
          Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
               location,
               immop,
               &kA32VeryNearDataInfo));
      return;
    }
  }
  Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, location);
}

bool Assembler::ldrsb_info(Condition cond,
                           Register rt,
                           Location* location,
                           const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
    if (!rt.Is(pc)) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32VeryNearDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::ldrsh(Condition cond,
                      EncodingSize size,
                      Register rt,
                      const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
        EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
          operand.IsOffset() && cond.IsNotNever() &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    } else {
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
      if (operand.IsPostIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
      if (operand.IsPreIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
}

void Assembler::ldrsh(Condition cond, Register rt, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound()) &&
        !rt.Is(pc)) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12),
                      location,
                      immop,
                      &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
    if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
         !location->IsBound()) &&
        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -255) && (off <= 255));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 8);
          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
                 ((target & 0x100) << 15);
        }
      } immop;
      EmitA32(
          Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
               location,
               immop,
               &kA32VeryNearDataInfo));
      return;
    }
  }
  Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, location);
}

bool Assembler::ldrsh_info(Condition cond,
                           Register rt,
                           Location* location,
                           const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  if (IsUsingT32()) {
    // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
    if (!rt.Is(pc)) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
    if (cond.IsNotNever()) {
      *info = &kA32VeryNearDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::lsl(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rm,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
          (imm >= 1) && (imm <= 31)) {
        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
        AdvanceIT();
        return;
      }
      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
}

void Assembler::lsls(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rm,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
          (imm >= 1) && (imm <= 31)) {
        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
        AdvanceIT();
        return;
      }
      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
}

void Assembler::lsr(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rm,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
          (imm >= 1) && (imm <= 32)) {
        uint32_t amount_ = imm % 32;
        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
                   (amount_ << 6));
        AdvanceIT();
        return;
      }
      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = imm % 32;
        EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
        uint32_t amount_ = imm % 32;
        EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
}

void Assembler::lsrs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rm,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
          (imm >= 1) && (imm <= 32)) {
        uint32_t amount_ = imm % 32;
        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
                   (amount_ << 6));
        AdvanceIT();
        return;
      }
      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = imm % 32;
        EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
        uint32_t amount_ = imm % 32;
        EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
}

void Assembler::mla(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
}

void Assembler::mlas(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
}

void Assembler::mls(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
}

void Assembler::mov(Condition cond,
                    EncodingSize size,
                    Register rd,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
        if (!size.IsWide() &&
            ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
             AllowUnpredictable())) {
          EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
      if (InITBlock() && !size.IsWide() && rd.IsLow() &&
          shift.IsValidAmount(amount) && rm.IsLow() &&
          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
          ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
        AdvanceIT();
        return;
      }
      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingT32()) {
      // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsASR() && rs.IsLow()) {
        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsLSL() && rs.IsLow()) {
        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsLSR() && rs.IsLow()) {
        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsROR() && rs.IsLow()) {
        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   (shift.GetType() << 21) | rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // MOV<c>{<q>} <Rd>, #<imm8> ; T1
      if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // MOV{<c>}{<q>} <Rd>, #<const> ; T2
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
      if (!size.IsNarrow() && (imm <= 65535) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
                   ((imm & 0xf000) << 4));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // MOV{<c>}{<q>} <Rd>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
      // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
      if ((imm <= 65535) && cond.IsNotNever() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
        return;
      }
    }
  }
  Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
}

void Assembler::movs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
          shift.IsValidAmount(amount) && rm.IsLow() &&
          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
        uint32_t amount_ = amount % 32;
        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
        AdvanceIT();
        return;
      }
      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingT32()) {
      // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsASR() && rs.IsLow()) {
        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsLSL() && rs.IsLow()) {
        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsLSR() && rs.IsLow()) {
        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          shift.IsROR() && rs.IsLow()) {
        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   (shift.GetType() << 21) | rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // MOVS{<q>} <Rd>, #<imm8> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
}

void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
      if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
                   ((imm & 0xf000) << 4));
        AdvanceIT();
        return;
      }
    } else {
      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
      if ((imm <= 65535) && cond.IsNotNever() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitA32(0x03400000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
        return;
      }
    }
  }
  Delegate(kMovt, &Assembler::movt, cond, rd, operand);
}

void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
      if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
                   ((imm & 0xf000) << 4));
        AdvanceIT();
        return;
      }
    } else {
      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
      if ((imm <= 65535) && cond.IsNotNever() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
        return;
      }
    }
  }
  Delegate(kMovw, &Assembler::movw, cond, rd, operand);
}

void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
    if ((!rd.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
      AdvanceIT();
      return;
    }
  } else {
    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
    if (cond.IsNotNever() && (!rd.IsPC() || AllowUnpredictable())) {
      EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (spec_reg.GetReg() << 22));
      return;
    }
  }
  Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
}

void Assembler::msr(Condition cond,
                    MaskedSpecialRegister spec_reg,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingA32()) {
      ImmediateA32 immediate_a32(imm);
      // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
                ((spec_reg.GetReg() & 0xf) << 16) |
                ((spec_reg.GetReg() & 0x10) << 18) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
      if ((!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
                   ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
      if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
        EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
                ((spec_reg.GetReg() & 0xf) << 16) |
                ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
        return;
      }
    }
  }
  Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
}

void Assembler::mul(
    Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
    if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
        rm.IsLow()) {
      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
      AdvanceIT();
      return;
    }
    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
    if (!size.IsNarrow() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
}

void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
    if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
      AdvanceIT();
      return;
    }
  } else {
    // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
}

void Assembler::mvn(Condition cond,
                    EncodingSize size,
                    Register rd,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // MVN{<c>}{<q>} <Rd>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // MVN{<c>}{<q>} <Rd>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // MVN<c>{<q>} <Rd>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
}

void Assembler::mvns(Condition cond,
                     EncodingSize size,
                     Register rd,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // MVNS{<q>} <Rd>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
}

void Assembler::nop(Condition cond, EncodingSize size) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // NOP{<c>}{<q>} ; T1
    if (!size.IsWide()) {
      EmitT32_16(0xbf00);
      AdvanceIT();
      return;
    }
    // NOP{<c>}.W ; T2
    if (!size.IsNarrow()) {
      EmitT32_32(0xf3af8000U);
      AdvanceIT();
      return;
    }
  } else {
    // NOP{<c>}{<q>} ; A1
    if (cond.IsNotNever()) {
      EmitA32(0x0320f000U | (cond.GetCondition() << 28));
      return;
    }
  }
  Delegate(kNop, &Assembler::nop, cond, size);
}

void Assembler::orn(Condition cond,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (immediate_t32.IsValid() && !rn.Is(pc) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
      if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
}

void Assembler::orns(Condition cond,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (immediate_t32.IsValid() && !rn.Is(pc) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
      if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
}

void Assembler::orr(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03800000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01800000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01800010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
}

void Assembler::orrs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03900000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01900000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01900010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
}

void Assembler::pkhbt(Condition cond,
                      Register rd,
                      Register rn,
                      const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
      if (shift.IsLSL() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | ((amount & 0x3) << 6) |
                   ((amount & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
      if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x06800010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount << 7));
        return;
      }
    }
  }
  Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
}

void Assembler::pkhtb(Condition cond,
                      Register rd,
                      Register rn,
                      const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | ((amount_ & 0x3) << 6) |
                   ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
          cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x06800050U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 7));
        return;
      }
    }
  }
  Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
}

void Assembler::pld(Condition cond, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // PLD{<c>}{<q>} <label> ; T1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf81ff000U, location, immop, &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // PLD{<c>}{<q>} <label> ; A1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound())) {
      if (cond.Is(al)) {
        static class EmitOp : public Location::EmitOperator {
         public:
          EmitOp() : Location::EmitOperator(A32) {}
          virtual uint32_t Encode(uint32_t instr,
                                  Location::Offset program_counter,
                                  const Location* loc) const VIXL_OVERRIDE {
            program_counter += kA32PcDelta;
            Location::Offset off =
                loc->GetLocation() - AlignDown(program_counter, 4);
            VIXL_ASSERT((off >= -4095) && (off <= 4095));
            uint32_t U = (off >= 0);
            int32_t target = abs(off) | (U << 12);
            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
          }
        } immop;
        EmitA32(Link(0xf55ff000U, location, immop, &kA32FarDataInfo));
        return;
      }
    }
  }
  Delegate(kPld, &Assembler::pld, cond, location);
}

bool Assembler::pld_info(Condition cond,
                         Location* location,
                         const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  USE(cond);
  if (IsUsingT32()) {
    // PLD{<c>}{<q>} <label> ; T1
    if (true) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // PLD{<c>}{<q>} <label> ; A1
    if (true) {
      *info = &kA32FarDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::pld(Condition cond, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
          operand.IsOffset()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
          operand.IsOffset()) {
        if (cond.Is(al)) {
          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
          uint32_t offset_ = abs(offset);
          EmitA32(0xf55ff000U | offset_ | (sign << 23));
          return;
        }
      }
    }
  }
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
        AdvanceIT();
        return;
      }
    } else {
      // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        if (cond.Is(al)) {
          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
          uint32_t offset_ = abs(offset);
          EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
          return;
        }
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
                   (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
          uint32_t amount_ = amount % 32;
          EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
          return;
        }
      }
      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
      if (shift.IsRRX() && operand.IsOffset() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
          EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
                  (sign_ << 23));
          return;
        }
      }
    }
  }
  Delegate(kPld, &Assembler::pld, cond, operand);
}

void Assembler::pldw(Condition cond, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
        AdvanceIT();
        return;
      }
    } else {
      // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        if (cond.Is(al)) {
          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
          uint32_t offset_ = abs(offset);
          EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
          return;
        }
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
                   (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
          uint32_t amount_ = amount % 32;
          EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
          return;
        }
      }
      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
      if (shift.IsRRX() && operand.IsOffset() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
          EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
                  (sign_ << 23));
          return;
        }
      }
    }
  }
  Delegate(kPldw, &Assembler::pldw, cond, operand);
}

void Assembler::pli(Condition cond, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
        AdvanceIT();
        return;
      }
    } else {
      // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        if (cond.Is(al)) {
          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
          uint32_t offset_ = abs(offset);
          EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
          return;
        }
      }
    }
  }
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
          operand.IsOffset()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
          operand.IsOffset()) {
        if (cond.Is(al)) {
          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
          uint32_t offset_ = abs(offset);
          EmitA32(0xf45ff000U | offset_ | (sign << 23));
          return;
        }
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf) &&
          (!rm.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
                   (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
      if (shift.IsRRX() && operand.IsOffset() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
          EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
                  (sign_ << 23));
          return;
        }
      }
      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
          uint32_t amount_ = amount % 32;
          EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
          return;
        }
      }
    }
  }
  Delegate(kPli, &Assembler::pli, cond, operand);
}

void Assembler::pli(Condition cond, Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // PLI{<c>}{<q>} <label> ; T3
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -4095) && (off <= 4095));
          uint32_t U = (off >= 0);
          int32_t target = abs(off) | (U << 12);
          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
        }
      } immop;
      EmitT32_32(Link(0xf91ff000U, location, immop, &kT32FarDataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // PLI{<c>}{<q>} <label> ; A1
    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
         !location->IsBound())) {
      if (cond.Is(al)) {
        static class EmitOp : public Location::EmitOperator {
         public:
          EmitOp() : Location::EmitOperator(A32) {}
          virtual uint32_t Encode(uint32_t instr,
                                  Location::Offset program_counter,
                                  const Location* loc) const VIXL_OVERRIDE {
            program_counter += kA32PcDelta;
            Location::Offset off =
                loc->GetLocation() - AlignDown(program_counter, 4);
            VIXL_ASSERT((off >= -4095) && (off <= 4095));
            uint32_t U = (off >= 0);
            int32_t target = abs(off) | (U << 12);
            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
          }
        } immop;
        EmitA32(Link(0xf45ff000U, location, immop, &kA32FarDataInfo));
        return;
      }
    }
  }
  Delegate(kPli, &Assembler::pli, cond, location);
}

bool Assembler::pli_info(Condition cond,
                         Location* location,
                         const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  USE(cond);
  if (IsUsingT32()) {
    // PLI{<c>}{<q>} <label> ; T3
    if (true) {
      *info = &kT32FarDataInfo;
      return true;
    }
  } else {
    // PLI{<c>}{<q>} <label> ; A1
    if (true) {
      *info = &kA32FarDataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (!registers.IsEmpty() || AllowUnpredictable()) {
    if (IsUsingT32()) {
      // A branch out of an IT block should be the last instruction in the
      // block.
      if (!registers.Includes(pc) || OutsideITBlockAndAlOrLast(cond) ||
          AllowUnpredictable()) {
        // POP{<c>}{<q>} <registers> ; T1
        if (!size.IsWide() && registers.IsR0toR7orPC()) {
          EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
                     GetRegisterListEncoding(registers, 0, 8));
          AdvanceIT();
          return;
        }
        // POP{<c>}{<q>} <registers> ; T2
        // Alias of: LDM{<c>}{<q>} SP!, <registers> ; T2
        if (!size.IsNarrow() &&
            ((!registers.Includes(sp) && (registers.GetCount() > 1) &&
              !(registers.Includes(pc) && registers.Includes(lr))) ||
             AllowUnpredictable())) {
          EmitT32_32(0xe8bd0000U | GetRegisterListEncoding(registers, 0, 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // POP{<c>}{<q>} <registers> ; A1
      // Alias of: LDM{<c>}{<q>} SP!, <registers> ; A1
      if (cond.IsNotNever() &&
          (!registers.Includes(sp) || AllowUnpredictable())) {
        EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
                GetRegisterListEncoding(registers, 0, 16));
        return;
      }
    }
  }
  Delegate(kPop, &Assembler::pop, cond, size, registers);
}

void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (!rt.IsSP() || AllowUnpredictable()) {
    if (IsUsingT32()) {
      // POP{<c>}{<q>} <single_register_list> ; T4
      // Alias of: LDR{<c>}{<q>} <Rt>, [SP], #4 ; T4
      if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond) ||
                               AllowUnpredictable())) {
        EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
        AdvanceIT();
        return;
      }
    } else {
      // POP{<c>}{<q>} <single_register_list> ; A1
      // Alias of: LDR{<c>}{<q>} <Rt>, [SP], #4 ; T1
      if (cond.IsNotNever()) {
        EmitA32(0x049d0004U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12));
        return;
      }
    }
  }
  Delegate(kPop, &Assembler::pop, cond, size, rt);
}

void Assembler::push(Condition cond,
                     EncodingSize size,
                     RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (!registers.IsEmpty() || AllowUnpredictable()) {
    if (IsUsingT32()) {
      // PUSH{<c>}{<q>} <registers> ; T1
      if (!size.IsWide() && registers.IsR0toR7orLR()) {
        EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
                   GetRegisterListEncoding(registers, 0, 8));
        AdvanceIT();
        return;
      }
      // PUSH{<c>}{<q>} <registers> ; T1
      // Alias of: STMDB SP!, <registers> ; T1
      if (!size.IsNarrow() && !registers.Includes(pc) &&
          ((!registers.Includes(sp) && (registers.GetCount() > 1)) ||
           AllowUnpredictable())) {
        EmitT32_32(0xe92d0000U | GetRegisterListEncoding(registers, 0, 15));
        AdvanceIT();
        return;
      }
    } else {
      // PUSH{<c>}{<q>} <registers> ; A1
      // Alias of: STMDB SP!, <registers> ; A1
      if (cond.IsNotNever() &&
          // For A32, sp can appear in the list, but stores an UNKNOWN value if
          // it is not the lowest-valued register.
          (!registers.Includes(sp) ||
           registers.GetFirstAvailableRegister().IsSP() ||
           AllowUnpredictable())) {
        EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
                GetRegisterListEncoding(registers, 0, 16));
        return;
      }
    }
  }
  Delegate(kPush, &Assembler::push, cond, size, registers);
}

void Assembler::push(Condition cond, EncodingSize size, Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // PUSH{<c>}{<q>} <single_register_list> ; T4
    // Alias of: STR{<c>}{<q>} <Rt>, [SP, #4]! ; T4
    if (!size.IsNarrow() &&
        ((!rt.IsPC() && !rt.IsSP()) || AllowUnpredictable())) {
      EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // PUSH{<c>}{<q>} <single_register_list> ; A1
    // Alias of: STR{<c>}{<q>} <Rt>, [SP, #4]! ; A1
    if (cond.IsNotNever() && (!rt.IsSP() || AllowUnpredictable())) {
      EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
      return;
    }
  }
  Delegate(kPush, &Assembler::push, cond, size, rt);
}

void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rn.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode() | (rn.GetCode() << 16));
      return;
    }
  }
  Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
}

void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
}

void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
}

void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
}

void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rn.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode() | (rn.GetCode() << 16));
      return;
    }
  }
  Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
}

void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rn.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode() | (rn.GetCode() << 16));
      return;
    }
  }
  Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
}

void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
}

void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rn.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode() | (rn.GetCode() << 16));
      return;
    }
  }
  Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
}

void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
}

void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
}

void Assembler::rbit(Condition cond, Register rd, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rm.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
}

void Assembler::rev(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // REV{<c>}{<q>} <Rd>, <Rm> ; T1
    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
      EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
      AdvanceIT();
      return;
    }
    // REV{<c>}{<q>} <Rd>, <Rm> ; T2
    if (!size.IsNarrow() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rm.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // REV{<c>}{<q>} <Rd>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
}

void Assembler::rev16(Condition cond,
                      EncodingSize size,
                      Register rd,
                      Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
      EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
      AdvanceIT();
      return;
    }
    // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
    if (!size.IsNarrow() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rm.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
}

void Assembler::revsh(Condition cond,
                      EncodingSize size,
                      Register rd,
                      Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
      EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
      AdvanceIT();
      return;
    }
    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
    if (!size.IsNarrow() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
                 (rm.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
}

void Assembler::ror(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rm,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
        EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
}

void Assembler::rors(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rm,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
        EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rs = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
          rs.IsLow()) {
        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
      if (!size.IsNarrow() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
                   rs.GetCode());
        AdvanceIT();
        return;
      }
    } else {
      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
}

void Assembler::rrx(Condition cond, Register rd, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
    if (cond.IsNotNever()) {
      EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
}

void Assembler::rrxs(Condition cond, Register rd, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
    if (cond.IsNotNever()) {
      EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rm.GetCode());
      return;
    }
  }
  Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
}

void Assembler::rsb(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
          (imm == 0)) {
        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02600000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00600000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00600010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
}

void Assembler::rsbs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
          (imm == 0)) {
        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
        AdvanceIT();
        return;
      }
      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02700000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00700000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00700010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
}

void Assembler::rsc(Condition cond,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingA32()) {
      ImmediateA32 immediate_a32(imm);
      // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingA32()) {
      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
}

void Assembler::rscs(Condition cond,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingA32()) {
      ImmediateA32 immediate_a32(imm);
      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingA32()) {
      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
}

void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
}

void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
}

void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
}

void Assembler::sbc(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
}

void Assembler::sbcs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
}

void Assembler::sbfx(
    Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
    if ((lsb <= 31) &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t widthm1 = width - 1;
      EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
      AdvanceIT();
      return;
    }
  } else {
    // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
    if ((lsb <= 31) && cond.IsNotNever() &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t widthm1 = width - 1;
      EmitA32(0x07a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rn.GetCode() | (lsb << 7) | (widthm1 << 16));
      return;
    }
  }
  Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, width);
}

void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
}

void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
}

void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
}

void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
}

void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
}

void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
}

void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
}

void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
}

void Assembler::smlabb(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
}

void Assembler::smlabt(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
}

void Assembler::smlad(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
}

void Assembler::smladx(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
}

void Assembler::smlal(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlalbb(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x01400080U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlalbt(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlald(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x07400010U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlaldx(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x07400030U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlals(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlaltb(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlaltt(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlatb(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
}

void Assembler::smlatt(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
}

void Assembler::smlawb(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
}

void Assembler::smlawt(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
}

void Assembler::smlsd(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
}

void Assembler::smlsdx(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
}

void Assembler::smlsld(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x07400050U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smlsldx(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x07400070U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smmla(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
}

void Assembler::smmlar(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
}

void Assembler::smmls(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
}

void Assembler::smmlsr(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
}

void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
}

void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
}

void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
}

void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
}

void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
}

void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
}

void Assembler::smull(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smulls(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
}

void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
}

void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
}

void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
}

void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
}

void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
}

void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
}

void Assembler::ssat(Condition cond,
                     Register rd,
                     uint32_t imm,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
          (amount <= 31) &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        uint32_t imm_ = imm - 1;
        EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
                   ((amount & 0x1c) << 10));
        AdvanceIT();
        return;
      }
      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        uint32_t imm_ = imm - 1;
        EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
                   ((amount & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
          (amount <= 32) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        uint32_t imm_ = imm - 1;
        uint32_t amount_ = amount % 32;
        EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
                (amount_ << 7));
        return;
      }
      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
          cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        uint32_t imm_ = imm - 1;
        EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
                (amount << 7));
        return;
      }
    }
  }
  Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
}

void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
    if ((imm >= 1) && (imm <= 16) &&
        ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
      uint32_t imm_ = imm - 1;
      EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
                 (rn.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
    if ((imm >= 1) && (imm <= 16) && cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
      uint32_t imm_ = imm - 1;
      EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (imm_ << 16) | rn.GetCode());
      return;
    }
  }
  Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
}

void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
}

void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
}

void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
}

void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
                (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStl, &Assembler::stl, cond, rt, operand);
}

void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
                (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
}

void Assembler::stlex(Condition cond,
                      Register rd,
                      Register rt,
                      const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
}

void Assembler::stlexb(Condition cond,
                       Register rd,
                       Register rt,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
}

void Assembler::stlexd(Condition cond,
                       Register rd,
                       Register rt,
                       Register rt2,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
           AllowUnpredictable())) {
        EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
            !rn.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
}

void Assembler::stlexh(Condition cond,
                       Register rd,
                       Register rt,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
}

void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
                (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
}

void Assembler::stm(Condition cond,
                    EncodingSize size,
                    Register rn,
                    WriteBack write_back,
                    RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // STM{<c>}{<q>} <Rn>!, <registers> ; T1
    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
        ((registers.GetList() & ~0xff) == 0)) {
      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
                 GetRegisterListEncoding(registers, 0, 8));
      AdvanceIT();
      return;
    }
    // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
}

void Assembler::stmda(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
}

void Assembler::stmdb(Condition cond,
                      EncodingSize size,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // STMDB{<c>}{<q>} SP!, <registers> ; T1
    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
        registers.IsR0toR7orLR()) {
      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
                 GetRegisterListEncoding(registers, 0, 8));
      AdvanceIT();
      return;
    }
    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
}

void Assembler::stmea(Condition cond,
                      EncodingSize size,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
        ((registers.GetList() & ~0xff) == 0)) {
      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
                 GetRegisterListEncoding(registers, 0, 8));
      AdvanceIT();
      return;
    }
    // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
}

void Assembler::stmed(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
}

void Assembler::stmfa(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
}

void Assembler::stmfd(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
    if (((registers.GetList() & ~0x5fff) == 0) &&
        (!rn.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) |
                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
                 GetRegisterListEncoding(registers, 0, 13));
      AdvanceIT();
      return;
    }
  } else {
    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
}

void Assembler::stmib(Condition cond,
                      Register rn,
                      WriteBack write_back,
                      RegisterList registers) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) |
              GetRegisterListEncoding(registers, 0, 16));
      return;
    }
  }
  Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
}

void Assembler::str(Condition cond,
                    EncodingSize size,
                    Register rt,
                    const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
          (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
        int32_t offset_ = offset >> 2;
        EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
                   ((offset_ & 0x1f) << 6));
        AdvanceIT();
        return;
      }
      // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
          ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
        int32_t offset_ = offset >> 2;
        EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
        AdvanceIT();
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
    } else {
      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05000000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
          cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x04000000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
          cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05200000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07000000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
      if (operand.IsShiftValid() && operand.IsPostIndex() &&
          cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x06000000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
          (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07200000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
    }
  }
  Delegate(kStr, &Assembler::str, cond, size, rt, operand);
}

void Assembler::strb(Condition cond,
                     EncodingSize size,
                     Register rt,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
          (offset <= 31) && operand.IsOffset()) {
        EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
                   ((offset & 0x1f) << 6));
        AdvanceIT();
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
    } else {
      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05400000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x04400000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x05600000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
                (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    } else {
      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07400000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
      if (operand.IsShiftValid() && operand.IsPostIndex() &&
          cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x06400000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        uint32_t shift_ = TypeEncodingValue(shift);
        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
        EmitA32(0x07600000U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
        return;
      }
    }
  }
  Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
}

void Assembler::strd(Condition cond,
                     Register rt,
                     Register rt2,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
                   (rn.GetCode() << 16) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
          cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
                                AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
          cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
                                AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
          cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
                                AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingA32()) {
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsPostIndex() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsPreIndex() && cond.IsNotNever() &&
          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
           AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
    }
  }
  Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
}

void Assembler::strex(Condition cond,
                      Register rd,
                      Register rt,
                      const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
          operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        int32_t offset_ = offset >> 2;
        EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
                   (rn.GetCode() << 16) | (offset_ & 0xff));
        AdvanceIT();
        return;
      }
    } else {
      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
      if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
}

void Assembler::strexb(Condition cond,
                       Register rd,
                       Register rt,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
}

void Assembler::strexd(Condition cond,
                       Register rd,
                       Register rt,
                       Register rt2,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
           AllowUnpredictable())) {
        EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
          operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
            !rn.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
}

void Assembler::strexh(Condition cond,
                       Register rd,
                       Register rt,
                       const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    if (IsUsingT32()) {
      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
      if (operand.IsOffset() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
                   (rn.GetCode() << 16));
        AdvanceIT();
        return;
      }
    } else {
      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
        return;
      }
    }
  }
  Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
}

void Assembler::strh(Condition cond,
                     EncodingSize size,
                     Register rt,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
          (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
        int32_t offset_ = offset >> 1;
        EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
                   ((offset_ & 0x1f) << 6));
        AdvanceIT();
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (offset & 0xfff));
        AdvanceIT();
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   (-offset & 0xff));
        AdvanceIT();
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
          (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 9));
        AdvanceIT();
        return;
      }
    } else {
      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset);
        EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
                ((offset_ & 0xf0) << 4) | (sign << 23));
        return;
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    if (IsUsingT32()) {
      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
          sign.IsPlus() && operand.IsOffset()) {
        EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
                   (rm.GetCode() << 6));
        AdvanceIT();
        return;
      }
    } else {
      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
      if (operand.IsOffset() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
      if (operand.IsPostIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
      if (operand.IsPreIndex() && cond.IsNotNever() &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
        EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (sign_ << 23));
        return;
      }
    }
  }
  if (operand.IsShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount << 4));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
}

void Assembler::sub(Condition cond,
                    EncodingSize size,
                    Register rd,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
          (imm <= 7)) {
        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
        AdvanceIT();
        return;
      }
      // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
          (imm <= 255)) {
        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
          ((imm % 4) == 0)) {
        uint32_t imm_ = imm >> 2;
        EmitT32_16(0xb080 | imm_);
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever() &&
          ((rn.GetCode() & 0xd) != 0xd)) {
        EmitA32(0x02400000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
                     (rm.GetCode() << 6));
          AdvanceIT();
          return;
        }
        // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
        if (rn.Is(sp) && ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
          EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00400000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00400010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
}

void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kSub, &Assembler::sub, cond, rd, operand);
}

void Assembler::subs(Condition cond,
                     EncodingSize size,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
          (imm <= 7)) {
        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
        AdvanceIT();
        return;
      }
      // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
          (imm <= 255)) {
        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
          !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
      if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255) &&
          (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
        EmitT32_32(0xf3de8f00U | imm);
        AdvanceIT();
        return;
      }
      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
          !rd.Is(pc)) {
        EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
        EmitA32(0x02500000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
                immediate_a32.GetEncodingValue());
        return;
      }
      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
            rm.IsLow()) {
          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
                     (rm.GetCode() << 6));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
          !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
          !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x00500000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
           AllowUnpredictable())) {
        EmitA32(0x00500010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (shift.GetType() << 5) | (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
}

void Assembler::subs(Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // SUBS{<q>} <Rdn>, #<imm8> ; T2
      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kSubs, &Assembler::subs, rd, operand);
}

void Assembler::subw(Condition cond,
                     Register rd,
                     Register rn,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
          (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
      // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
      if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
        AdvanceIT();
        return;
      }
    }
  }
  Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
}

void Assembler::svc(Condition cond, uint32_t imm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // SVC{<c>}{<q>} {#}<imm> ; T1
    if ((imm <= 255)) {
      EmitT32_16(0xdf00 | imm);
      AdvanceIT();
      return;
    }
  } else {
    // SVC{<c>}{<q>} {#}<imm> ; A1
    if ((imm <= 16777215) && cond.IsNotNever()) {
      EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
      return;
    }
  }
  Delegate(kSvc, &Assembler::svc, cond, imm);
}

void Assembler::sxtab(Condition cond,
                      Register rd,
                      Register rn,
                      const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
}

void Assembler::sxtab16(Condition cond,
                        Register rd,
                        Register rn,
                        const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06800070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
}

void Assembler::sxtah(Condition cond,
                      Register rd,
                      Register rn,
                      const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
}

void Assembler::sxtb(Condition cond,
                     EncodingSize size,
                     Register rd,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
          EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
          (amount <= 24) && ((amount % 8) == 0) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
                   (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
}

void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
                   (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
}

void Assembler::sxth(Condition cond,
                     EncodingSize size,
                     Register rd,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
          EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
          (amount <= 24) && ((amount % 8) == 0) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
                   (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
}

void Assembler::tbb(Condition cond, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
    if (OutsideITBlockAndAlOrLast(cond) &&
        (!rm.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  }
  Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
}

void Assembler::tbh(Condition cond, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
    if (OutsideITBlockAndAlOrLast(cond) &&
        (!rm.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  }
  Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
}

void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
      if (immediate_t32.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03300000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
      if (shift.IsValidAmount(amount) &&
          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01300000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01300010U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kTeq, &Assembler::teq, cond, rn, operand);
}

void Assembler::tst(Condition cond,
                    EncodingSize size,
                    Register rn,
                    const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    uint32_t imm = operand.GetImmediate();
    if (IsUsingT32()) {
      ImmediateT32 immediate_t32(imm);
      // TST{<c>}{<q>} <Rn>, #<const> ; T1
      if (!size.IsNarrow() && immediate_t32.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
                   (immediate_t32.GetEncodingValue() & 0xff) |
                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
        AdvanceIT();
        return;
      }
    } else {
      ImmediateA32 immediate_a32(imm);
      // TST{<c>}{<q>} <Rn>, #<const> ; A1
      if (immediate_a32.IsValid() && cond.IsNotNever()) {
        EmitA32(0x03100000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
        return;
      }
    }
  }
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // TST{<c>}{<q>} <Rn>, <Rm> ; T1
        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
          EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
                   (operand.GetTypeEncodingValue() << 4) |
                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x01100000U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() |
                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
        return;
      }
    }
  }
  if (operand.IsRegisterShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    Register rs = operand.GetShiftRegister();
    if (IsUsingA32()) {
      // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
      if (cond.IsNotNever() &&
          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x01100010U | (cond.GetCondition() << 28) |
                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
                (rs.GetCode() << 8));
        return;
      }
    }
  }
  Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
}

void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
}

void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
}

void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
}

void Assembler::ubfx(
    Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
    if ((lsb <= 31) &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t widthm1 = width - 1;
      EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
      AdvanceIT();
      return;
    }
  } else {
    // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
    if ((lsb <= 31) && cond.IsNotNever() &&
        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
         AllowUnpredictable())) {
      uint32_t widthm1 = width - 1;
      EmitA32(0x07e00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              rn.GetCode() | (lsb << 7) | (widthm1 << 16));
      return;
    }
  }
  Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, width);
}

void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UDF{<c>}{<q>} {#}<imm> ; T1
    if (!size.IsWide() && (imm <= 255)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_16(0xde00 | imm);
        AdvanceIT();
        return;
      }
    }
    // UDF{<c>}{<q>} {#}<imm> ; T2
    if (!size.IsNarrow() && (imm <= 65535)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
        AdvanceIT();
        return;
      }
    }
  } else {
    // UDF{<c>}{<q>} {#}<imm> ; A1
    if ((imm <= 65535)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
        return;
      }
    }
  }
  Delegate(kUdf, &Assembler::udf, cond, size, imm);
}

void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
}

void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
}

void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
}

void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
}

void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
}

void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
}

void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
}

void Assembler::umaal(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00400090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
}

void Assembler::umlal(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
}

void Assembler::umlals(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
}

void Assembler::umull(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
                 (rn.GetCode() << 16) | rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00800090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
}

void Assembler::umulls(
    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingA32()) {
    // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
         AllowUnpredictable())) {
      EmitA32(0x00900090U | (cond.GetCondition() << 28) |
              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
              (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
}

void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
}

void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
}

void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
}

void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
}

void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
}

void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
}

void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8));
      return;
    }
  }
  Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
}

void Assembler::usada8(
    Condition cond, Register rd, Register rn, Register rm, Register ra) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
    if (!ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode() | (ra.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
    if (cond.IsNotNever() && !ra.Is(pc) &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
      return;
    }
  }
  Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
}

void Assembler::usat(Condition cond,
                     Register rd,
                     uint32_t imm,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rn = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31) &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
                   ((amount & 0x1c) << 10));
        AdvanceIT();
        return;
      }
      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
      if ((imm <= 31) && shift.IsLSL() && (amount <= 31) &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
                   ((amount & 0x1c) << 10));
        AdvanceIT();
        return;
      }
    } else {
      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
          cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount % 32;
        EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
                (amount_ << 7));
        return;
      }
      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
      if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
        EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
                (amount << 7));
        return;
      }
    }
  }
  Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
}

void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
    if ((imm <= 15) && ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
                 (rn.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
    if ((imm <= 15) && cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (imm << 16) | rn.GetCode());
      return;
    }
  }
  Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
}

void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
}

void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
}

void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                 rm.GetCode());
      AdvanceIT();
      return;
    }
  } else {
    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
    if (cond.IsNotNever() &&
        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
              (rn.GetCode() << 16) | rm.GetCode());
      return;
    }
  }
  Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
}

void Assembler::uxtab(Condition cond,
                      Register rd,
                      Register rn,
                      const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
}

void Assembler::uxtab16(Condition cond,
                        Register rd,
                        Register rn,
                        const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
}

void Assembler::uxtah(Condition cond,
                      Register rd,
                      Register rn,
                      const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
                   rm.GetCode() | (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
                (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
}

void Assembler::uxtb(Condition cond,
                     EncodingSize size,
                     Register rd,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
          EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
          (amount <= 24) && ((amount % 8) == 0) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
                   (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
}

void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
                   (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
}

void Assembler::uxth(Condition cond,
                     EncodingSize size,
                     Register rd,
                     const Operand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateShiftedRegister()) {
    Register rm = operand.GetBaseRegister();
    if (operand.IsPlainRegister()) {
      if (IsUsingT32()) {
        // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
          EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
          AdvanceIT();
          return;
        }
      }
    }
    Shift shift = operand.GetShift();
    uint32_t amount = operand.GetShiftAmount();
    if (IsUsingT32()) {
      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
          (amount <= 24) && ((amount % 8) == 0) &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
                   (amount_ << 4));
        AdvanceIT();
        return;
      }
    } else {
      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
          ((amount % 8) == 0) && cond.IsNotNever() &&
          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
        uint32_t amount_ = amount / 8;
        EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
        return;
      }
    }
  }
  Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
}

void Assembler::vaba(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
}

void Assembler::vaba(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
}

void Assembler::vabal(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
}

void Assembler::vabd(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
}

void Assembler::vabd(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
}

void Assembler::vabdl(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
}

void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
}

void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
}

void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
}

void Assembler::vacge(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
}

void Assembler::vacge(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
}

void Assembler::vacgt(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
}

void Assembler::vacgt(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
}

void Assembler::vacle(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
}

void Assembler::vacle(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
}

void Assembler::vaclt(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
}

void Assembler::vaclt(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
}

void Assembler::vadd(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
}

void Assembler::vadd(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
}

void Assembler::vadd(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
}

void Assembler::vaddhn(
    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
}

void Assembler::vaddl(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
}

void Assembler::vaddw(
    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
}

void Assembler::vand(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rn,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
}

void Assembler::vand(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rn,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    QRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
}

void Assembler::vbic(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rn,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
}

void Assembler::vbic(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rn,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    QRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
}

void Assembler::vbif(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
}

void Assembler::vbif(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
}

void Assembler::vbit(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
}

void Assembler::vbit(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
}

void Assembler::vbsl(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
}

void Assembler::vbsl(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
}

void Assembler::vceq(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_2 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10100U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10100U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
}

void Assembler::vceq(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_2 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10140U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10140U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
}

void Assembler::vceq(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_4 encoded_dt(dt);
  Dt_sz_1 encoded_dt_2(dt);
  if (IsUsingT32()) {
    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
    if (encoded_dt_2.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
    if (encoded_dt_2.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
}

void Assembler::vceq(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_4 encoded_dt(dt);
  Dt_sz_1 encoded_dt_2(dt);
  if (IsUsingT32()) {
    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
    if (encoded_dt_2.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
    if (encoded_dt_2.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
}

void Assembler::vcge(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10080U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10080U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
}

void Assembler::vcge(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb100c0U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b100c0U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
}

void Assembler::vcge(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
}

void Assembler::vcge(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
}

void Assembler::vcgt(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10000U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10000U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
}

void Assembler::vcgt(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10040U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10040U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
}

void Assembler::vcgt(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
}

void Assembler::vcgt(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
}

void Assembler::vcle(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10180U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10180U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
}

void Assembler::vcle(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb101c0U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b101c0U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
}

void Assembler::vcle(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                   rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        return;
      }
    }
    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                rm.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
}

void Assembler::vcle(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                   rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        return;
      }
    }
    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                rm.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
}

void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_5 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
}

void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_5 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
}

void Assembler::vclt(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10200U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10200U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
}

void Assembler::vclt(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_F_size_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb10240U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b10240U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
}

void Assembler::vclt(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                   rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        return;
      }
    }
    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                rm.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
}

void Assembler::vclt(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                   rm.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
        return;
      }
    }
    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
                rm.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
}

void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
}

void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
}

void Assembler::vcmp(Condition cond,
                     DataType dt,
                     SRegister rd,
                     const SOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    SRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
      if (dt.Is(F32)) {
        EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
      if (dt.Is(F32) && cond.IsNotNever()) {
        EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    if (IsUsingT32()) {
      // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
      if (dt.Is(F32) && (operand.IsFloatZero())) {
        EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
        AdvanceIT();
        return;
      }
    } else {
      // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
      if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
        EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
        return;
      }
    }
  }
  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
}

void Assembler::vcmp(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
      if (dt.Is(F64)) {
        EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
      if (dt.Is(F64) && cond.IsNotNever()) {
        EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    if (IsUsingT32()) {
      // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
      if (dt.Is(F64) && (operand.IsFloatZero())) {
        EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
        AdvanceIT();
        return;
      }
    } else {
      // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
      if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
        EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
        return;
      }
    }
  }
  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
}

void Assembler::vcmpe(Condition cond,
                      DataType dt,
                      SRegister rd,
                      const SOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    SRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
      if (dt.Is(F32)) {
        EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
      if (dt.Is(F32) && cond.IsNotNever()) {
        EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    if (IsUsingT32()) {
      // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
      if (dt.Is(F32) && (operand.IsFloatZero())) {
        EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
        AdvanceIT();
        return;
      }
    } else {
      // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
      if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
        EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
        return;
      }
    }
  }
  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
}

void Assembler::vcmpe(Condition cond,
                      DataType dt,
                      DRegister rd,
                      const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
      if (dt.Is(F64)) {
        EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
      if (dt.Is(F64) && cond.IsNotNever()) {
        EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    if (IsUsingT32()) {
      // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
      if (dt.Is(F64) && (operand.IsFloatZero())) {
        EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
        AdvanceIT();
        return;
      }
    } else {
      // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
      if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
        EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
        return;
      }
    }
  }
  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
}

void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
    if (dt.Is(Untyped8)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
    if (dt.Is(Untyped8)) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
}

void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
    if (dt.Is(Untyped8)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
    if (dt.Is(Untyped8)) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_2 encoded_dt(dt2);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
    if (dt1.Is(F64) && dt2.Is(F32)) {
      EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
    if (dt1.Is(F64) && encoded_dt.IsValid()) {
      EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
    if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
    if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
      EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(F32) && dt2.Is(F64)) {
      EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(U32) && dt2.Is(F64)) {
      EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(S32) && dt2.Is(F64)) {
      EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvt(Condition cond,
                     DataType dt1,
                     DataType dt2,
                     DRegister rd,
                     DRegister rm,
                     int32_t fbits) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_U_1 encoded_dt(dt1, dt2);
  Dt_U_sx_1 encoded_dt_2(dt2);
  Dt_U_sx_1 encoded_dt_3(dt1);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t fbits_ = 64 - fbits;
        EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
        AdvanceIT();
        return;
      }
    }
    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
      unsigned offset = 32;
      if (dt2.Is(S16) || dt2.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
                 ((fbits_ & 0x1e) >> 1));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
      unsigned offset = 32;
      if (dt1.Is(S16) || dt1.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
                 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
                 ((fbits_ & 0x1e) >> 1));
      AdvanceIT();
      return;
    }
  } else {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
      if (cond.Is(al)) {
        uint32_t fbits_ = 64 - fbits;
        EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
        return;
      }
    }
    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
        cond.IsNotNever()) {
      unsigned offset = 32;
      if (dt2.Is(S16) || dt2.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
              ((fbits_ & 0x1e) >> 1));
      return;
    }
    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
        cond.IsNotNever()) {
      unsigned offset = 32;
      if (dt1.Is(S16) || dt1.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
              ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
              ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
              ((fbits_ & 0x1e) >> 1));
      return;
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
}

void Assembler::vcvt(Condition cond,
                     DataType dt1,
                     DataType dt2,
                     QRegister rd,
                     QRegister rm,
                     int32_t fbits) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_U_1 encoded_dt(dt1, dt2);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t fbits_ = 64 - fbits;
        EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
      if (cond.Is(al)) {
        uint32_t fbits_ = 64 - fbits;
        EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
        return;
      }
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
}

void Assembler::vcvt(Condition cond,
                     DataType dt1,
                     DataType dt2,
                     SRegister rd,
                     SRegister rm,
                     int32_t fbits) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_sx_1 encoded_dt(dt2);
  Dt_U_sx_1 encoded_dt_2(dt1);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
      unsigned offset = 32;
      if (dt2.Is(S16) || dt2.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
                 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
                 ((fbits_ & 0x1e) >> 1));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
      unsigned offset = 32;
      if (dt1.Is(S16) || dt1.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
                 ((fbits_ & 0x1e) >> 1));
      AdvanceIT();
      return;
    }
  } else {
    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
        cond.IsNotNever()) {
      unsigned offset = 32;
      if (dt2.Is(S16) || dt2.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
              ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
              ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
              ((fbits_ & 0x1e) >> 1));
      return;
    }
    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
        cond.IsNotNever()) {
      unsigned offset = 32;
      if (dt1.Is(S16) || dt1.Is(U16)) {
        offset = 16;
      }
      uint32_t fbits_ = offset - fbits;
      EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
              ((fbits_ & 0x1e) >> 1));
      return;
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_1 encoded_dt(dt1, dt2);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_1 encoded_dt(dt1, dt2);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
    if (dt1.Is(F16) && dt2.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
    if (dt1.Is(F16) && dt2.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
    if (dt1.Is(F32) && dt2.Is(F16)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
    if (dt1.Is(F32) && dt2.Is(F16)) {
      if (cond.Is(al)) {
        EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvt(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_2 encoded_dt(dt2);
  if (IsUsingT32()) {
    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
    if (dt1.Is(U32) && dt2.Is(F32)) {
      EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
    if (dt1.Is(S32) && dt2.Is(F32)) {
      EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
    if (dt1.Is(F32) && encoded_dt.IsValid()) {
      EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
    if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
      EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
}

void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
}

void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
}

void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
}

void Assembler::vcvtb(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
    if (dt1.Is(F32) && dt2.Is(F16)) {
      EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
    if (dt1.Is(F16) && dt2.Is(F32)) {
      EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
      EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtb(
    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
    if (dt1.Is(F64) && dt2.Is(F16)) {
      EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
      EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtb(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(F16) && dt2.Is(F64)) {
      EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
}

void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
}

void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
}

void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
}

void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
}

void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
}

void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
}

void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
}

void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
}

void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_3 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
}

void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F32)) {
      EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
}

void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_op_2 encoded_dt(dt1);
  if (IsUsingT32()) {
    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
    if (encoded_dt.IsValid() && dt2.Is(F64)) {
      EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
}

void Assembler::vcvtr(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
    if (dt1.Is(U32) && dt2.Is(F32)) {
      EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
    if (dt1.Is(S32) && dt2.Is(F32)) {
      EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtr(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(U32) && dt2.Is(F64)) {
      EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(S32) && dt2.Is(F64)) {
      EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtt(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
    if (dt1.Is(F32) && dt2.Is(F16)) {
      EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
    if (dt1.Is(F16) && dt2.Is(F32)) {
      EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
      EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtt(
    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
    if (dt1.Is(F64) && dt2.Is(F16)) {
      EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
      EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
}

void Assembler::vcvtt(
    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
    if (dt1.Is(F16) && dt2.Is(F64)) {
      EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
}

void Assembler::vdiv(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
}

void Assembler::vdiv(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
}

void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_B_E_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
                   rd.Encode(7, 16) | (rt.GetCode() << 12));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
    if (encoded_dt.IsValid() && cond.IsNotNever() &&
        (!rt.IsPC() || AllowUnpredictable())) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
                rd.Encode(7, 16) | (rt.GetCode() << 12));
        return;
      }
    }
  }
  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
}

void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_B_E_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
                   rd.Encode(7, 16) | (rt.GetCode() << 12));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
    if (encoded_dt.IsValid() && cond.IsNotNever() &&
        (!rt.IsPC() || AllowUnpredictable())) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
                rd.Encode(7, 16) | (rt.GetCode() << 12));
        return;
      }
    }
  }
  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
}

void Assembler::vdup(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_imm4_1 encoded_dt(dt, rm);
  if (IsUsingT32()) {
    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
}

void Assembler::vdup(Condition cond,
                     DataType dt,
                     QRegister rd,
                     DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_imm4_1 encoded_dt(dt, rm);
  if (IsUsingT32()) {
    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
}

void Assembler::veor(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
}

void Assembler::veor(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
}

void Assembler::vext(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rn,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      if (IsUsingT32()) {
        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
        if (dt.Is(Untyped8) && (imm <= 7)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                       rm.Encode(5, 0) | (imm << 8));
            AdvanceIT();
            return;
          }
        }
        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm4 = imm / dt.GetSize();
            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                       rm.Encode(5, 0) | (imm4 << 8));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
        if (dt.Is(Untyped8) && (imm <= 7)) {
          if (cond.Is(al)) {
            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                    rm.Encode(5, 0) | (imm << 8));
            return;
          }
        }
        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
          if (cond.Is(al)) {
            uint32_t imm4 = imm / dt.GetSize();
            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                    rm.Encode(5, 0) | (imm4 << 8));
            return;
          }
        }
      }
    }
  }
  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
}

void Assembler::vext(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rn,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      if (IsUsingT32()) {
        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
        if (dt.Is(Untyped8) && (imm <= 15)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                       rm.Encode(5, 0) | (imm << 8));
            AdvanceIT();
            return;
          }
        }
        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm4 = imm / dt.GetSize();
            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                       rm.Encode(5, 0) | (imm4 << 8));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
        if (dt.Is(Untyped8) && (imm <= 15)) {
          if (cond.Is(al)) {
            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                    rm.Encode(5, 0) | (imm << 8));
            return;
          }
        }
        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
          if (cond.Is(al)) {
            uint32_t imm4 = imm / dt.GetSize();
            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                    rm.Encode(5, 0) | (imm4 << 8));
            return;
          }
        }
      }
    }
  }
  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
}

void Assembler::vfma(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
}

void Assembler::vfma(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
}

void Assembler::vfma(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
}

void Assembler::vfms(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
}

void Assembler::vfms(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
}

void Assembler::vfms(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
}

void Assembler::vfnma(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
}

void Assembler::vfnma(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
}

void Assembler::vfnms(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
}

void Assembler::vfnms(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
}

void Assembler::vhadd(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
}

void Assembler::vhadd(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
}

void Assembler::vhsub(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
}

void Assembler::vhsub(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
}

void Assembler::vld1(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_6 encoded_dt(dt);
    Dt_size_7 encoded_dt_2(dt);
    Align_align_1 encoded_align_1(align, nreglist);
    Align_a_1 encoded_align_2(align, dt);
    Align_index_align_1 encoded_align_3(align, nreglist, dt);
    if (IsUsingT32()) {
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.GetLength() - 1;
          EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.GetLength() - 1;
          EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsOffset() &&
          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.GetLength() - 1;
          EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.GetLength() - 1;
          EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsOffset() &&
          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_6 encoded_dt(dt);
    Dt_size_7 encoded_dt_2(dt);
    Align_align_1 encoded_align_1(align, nreglist);
    Align_a_1 encoded_align_2(align, dt);
    Align_index_align_1 encoded_align_3(align, nreglist, dt);
    if (IsUsingT32()) {
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.GetLength() - 1;
          EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.GetLength() - 1;
          EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
}

void Assembler::vld2(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_7 encoded_dt(dt);
    Align_align_2 encoded_align_1(align, nreglist);
    Align_a_2 encoded_align_2(align, dt);
    Align_index_align_2 encoded_align_3(align, nreglist, dt);
    if (IsUsingT32()) {
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsOffset() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsPostIndex() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsOffset() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsPostIndex() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Align_align_2 encoded_align_1(align, nreglist);
    Align_a_2 encoded_align_2(align, dt);
    Align_index_align_2 encoded_align_3(align, nreglist, dt);
    if (IsUsingT32()) {
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
}

void Assembler::vld3(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_7 encoded_dt(dt);
    Align_align_3 encoded_align_1(align);
    if (IsUsingT32()) {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Align_align_3 encoded_align_1(align);
    if (IsUsingT32()) {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
}

void Assembler::vld3(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Dt_size_7 encoded_dt(dt);
    Index_1 encoded_align_1(nreglist, dt);
    if (IsUsingT32()) {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Index_1 encoded_align_1(nreglist, dt);
    if (IsUsingT32()) {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          sign.IsPlus() && operand.IsPostIndex() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          sign.IsPlus() && operand.IsPostIndex() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          sign.IsPlus() && operand.IsPostIndex() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          sign.IsPlus() && operand.IsPostIndex() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
}

void Assembler::vld4(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_7 encoded_dt(dt);
    Dt_size_8 encoded_dt_2(dt, align);
    Align_align_4 encoded_align_1(align);
    Align_a_3 encoded_align_2(align, dt);
    Align_index_align_3 encoded_align_3(align, nreglist, dt);
    if (IsUsingT32()) {
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_3.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Dt_size_8 encoded_dt_2(dt, align);
    Align_align_4 encoded_align_1(align);
    Align_a_3 encoded_align_2(align, dt);
    Align_index_align_3 encoded_align_3(align, nreglist, dt);
    if (IsUsingT32()) {
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 5) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_3.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 5) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_3.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
}

void Assembler::vldm(Condition cond,
                     DataType dt,
                     Register rn,
                     WriteBack write_back,
                     DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
                              AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
}

void Assembler::vldm(Condition cond,
                     DataType dt,
                     Register rn,
                     WriteBack write_back,
                     SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
    if ((!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
    if (cond.IsNotNever() &&
        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
}

void Assembler::vldmdb(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
    if (write_back.DoesWriteBack() &&
        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              dreg.Encode(22, 12) | (len & 0xff));
      return;
    }
  }
  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
}

void Assembler::vldmdb(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
    if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
        (!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              sreg.Encode(22, 12) | (len & 0xff));
      return;
    }
  }
  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
}

void Assembler::vldmia(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
                              AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
}

void Assembler::vldmia(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
    if ((!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
    if (cond.IsNotNever() &&
        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
}

void Assembler::vldr(Condition cond,
                     DataType dt,
                     DRegister rd,
                     Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
    if (dt.IsNoneOr(Untyped64) &&
        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         !location->IsBound())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
          int32_t target = off >> 2;
          uint32_t U = (target >= 0);
          target = abs(target) | (U << 8);
          return instr | (target & 0xff) | ((target & 0x100) << 15);
        }
      } immop;
      EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12),
                      location,
                      immop,
                      &kT32DataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
    if (dt.IsNoneOr(Untyped64) &&
        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         !location->IsBound()) &&
        cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
          int32_t target = off >> 2;
          uint32_t U = (target >= 0);
          target = abs(target) | (U << 8);
          return instr | (target & 0xff) | ((target & 0x100) << 15);
        }
      } immop;
      EmitA32(
          Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
               location,
               immop,
               &kA32DataInfo));
      return;
    }
  }
  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
}

bool Assembler::vldr_info(Condition cond,
                          DataType dt,
                          DRegister rd,
                          Location* location,
                          const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  USE(rd);
  if (IsUsingT32()) {
    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
    if (dt.IsNoneOr(Untyped64)) {
      *info = &kT32DataInfo;
      return true;
    }
  } else {
    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
    if (dt.IsNoneOr(Untyped64) && cond.IsNotNever()) {
      *info = &kA32DataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::vldr(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
          cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                offset_ | (sign << 23));
        return;
      }
      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                (rn.GetCode() << 16) | offset_ | (sign << 23));
        return;
      }
    }
  }
  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
}

void Assembler::vldr(Condition cond,
                     DataType dt,
                     SRegister rd,
                     Location* location) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Location::Offset offset =
      location->IsBound()
          ? location->GetLocation() -
                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
          : 0;
  if (IsUsingT32()) {
    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
    if (dt.IsNoneOr(Untyped32) &&
        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         !location->IsBound())) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(T32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kT32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
          int32_t target = off >> 2;
          uint32_t U = (target >= 0);
          target = abs(target) | (U << 8);
          return instr | (target & 0xff) | ((target & 0x100) << 15);
        }
      } immop;
      EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12),
                      location,
                      immop,
                      &kT32DataInfo));
      AdvanceIT();
      return;
    }
  } else {
    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
    if (dt.IsNoneOr(Untyped32) &&
        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
          ((offset & 0x3) == 0)) ||
         !location->IsBound()) &&
        cond.IsNotNever()) {
      static class EmitOp : public Location::EmitOperator {
       public:
        EmitOp() : Location::EmitOperator(A32) {}
        virtual uint32_t Encode(uint32_t instr,
                                Location::Offset program_counter,
                                const Location* loc) const VIXL_OVERRIDE {
          program_counter += kA32PcDelta;
          Location::Offset off =
              loc->GetLocation() - AlignDown(program_counter, 4);
          VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
          int32_t target = off >> 2;
          uint32_t U = (target >= 0);
          target = abs(target) | (U << 8);
          return instr | (target & 0xff) | ((target & 0x100) << 15);
        }
      } immop;
      EmitA32(
          Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
               location,
               immop,
               &kA32DataInfo));
      return;
    }
  }
  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
}

bool Assembler::vldr_info(Condition cond,
                          DataType dt,
                          SRegister rd,
                          Location* location,
                          const struct ReferenceInfo** info) {
  VIXL_ASSERT(!location->IsBound());
  USE(location);
  USE(rd);
  if (IsUsingT32()) {
    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
    if (dt.IsNoneOr(Untyped32)) {
      *info = &kT32DataInfo;
      return true;
    }
  } else {
    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
    if (dt.IsNoneOr(Untyped32) && cond.IsNotNever()) {
      *info = &kA32DataInfo;
      return true;
    }
  }
  return false;
}

void Assembler::vldr(Condition cond,
                     DataType dt,
                     SRegister rd,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
          cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                offset_ | (sign << 23));
        return;
      }
      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
          ((rn.GetCode() & 0xf) != 0xf)) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                (rn.GetCode() << 16) | offset_ | (sign << 23));
        return;
      }
    }
  }
  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
}

void Assembler::vmax(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
}

void Assembler::vmax(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
}

void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
    if (OutsideITBlock() && dt.Is(F64)) {
      EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
    if (dt.Is(F64)) {
      EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
}

void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
}

void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
    if (dt.Is(F32)) {
      EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
}

void Assembler::vmin(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
}

void Assembler::vmin(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
}

void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
    if (OutsideITBlock() && dt.Is(F64)) {
      EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
    if (dt.Is(F64)) {
      EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
}

void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
}

void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
    if (dt.Is(F32)) {
      EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
}

void Assembler::vmla(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_9 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
}

void Assembler::vmla(
    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_9 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al)) {
        EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
}

void Assembler::vmla(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_10 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
}

void Assembler::vmla(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_10 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
}

void Assembler::vmla(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
}

void Assembler::vmlal(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_11 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
}

void Assembler::vmlal(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_12 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
}

void Assembler::vmls(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_9 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
}

void Assembler::vmls(
    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_9 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al)) {
        EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
}

void Assembler::vmls(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_10 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
}

void Assembler::vmls(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_10 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
}

void Assembler::vmls(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
}

void Assembler::vmlsl(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_11 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1)))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
}

void Assembler::vmlsl(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_12 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                   rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
                rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
}

void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
    if ((!rt.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
              rn.Encode(7, 16));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
}

void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
    if ((!rt.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
              (rt.GetCode() << 12));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
}

void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
    if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
    if (cond.IsNotNever() &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
              (rt2.GetCode() << 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
}

void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
    if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
                 (rt2.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
    if (cond.IsNotNever() &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
}

void Assembler::vmov(
    Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
        cond.IsNotNever() &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
              (rt2.GetCode() << 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
}

void Assembler::vmov(
    Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
                 (rt2.GetCode() << 16));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
        cond.IsNotNever() &&
        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
      EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
}

void Assembler::vmov(Condition cond,
                     DataType dt,
                     DRegisterLane rd,
                     Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_opc1_opc2_1 encoded_dt(dt, rd);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
                 rd.Encode(7, 16) | (rt.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
    if (encoded_dt.IsValid() && cond.IsNotNever() &&
        (!rt.IsPC() || AllowUnpredictable())) {
      EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
              ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
              (rt.GetCode() << 12));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
}

void Assembler::vmov(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(
              0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsImmediate()) {
    ImmediateVFP vfp(operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
      if (dt.Is(F64) && vfp.IsValid()) {
        EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
                   (vfp.GetEncodingValue() & 0xf) |
                   ((vfp.GetEncodingValue() & 0xf0) << 12));
        AdvanceIT();
        return;
      }
    } else {
      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
      if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
        EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                (vfp.GetEncodingValue() & 0xf) |
                ((vfp.GetEncodingValue() & 0xf0) << 12));
        return;
      }
    }
  }
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
      if (dt.Is(F64)) {
        EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
      if (!dt.Is(F64)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                     rm.Encode(5, 0));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
      if (dt.Is(F64) && cond.IsNotNever()) {
        EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                rm.Encode(5, 0));
        return;
      }
      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
      if (!dt.Is(F64)) {
        if (cond.Is(al)) {
          EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                  rm.Encode(5, 0));
          return;
        }
      }
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
}

void Assembler::vmov(Condition cond,
                     DataType dt,
                     QRegister rd,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(
              0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    QRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
      if (!dt.Is(F64)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                     rm.Encode(5, 0));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
      if (!dt.Is(F64)) {
        if (cond.Is(al)) {
          EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                  rm.Encode(5, 0));
          return;
        }
      }
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
}

void Assembler::vmov(Condition cond,
                     DataType dt,
                     SRegister rd,
                     const SOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVFP vfp(operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
      if (dt.Is(F32) && vfp.IsValid()) {
        EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
                   (vfp.GetEncodingValue() & 0xf) |
                   ((vfp.GetEncodingValue() & 0xf0) << 12));
        AdvanceIT();
        return;
      }
    } else {
      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
      if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
        EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                (vfp.GetEncodingValue() & 0xf) |
                ((vfp.GetEncodingValue() & 0xf0) << 12));
        return;
      }
    }
  }
  if (operand.IsRegister()) {
    SRegister rm = operand.GetRegister();
    if (IsUsingT32()) {
      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
      if (dt.Is(F32)) {
        EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
      if (dt.Is(F32) && cond.IsNotNever()) {
        EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
}

void Assembler::vmov(Condition cond,
                     DataType dt,
                     Register rt,
                     DRegisterLane rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
  if (IsUsingT32()) {
    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
                 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
                 (rt.GetCode() << 12) | rn.Encode(7, 16));
      AdvanceIT();
      return;
    }
  } else {
    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
    if (encoded_dt.IsValid() && cond.IsNotNever() &&
        (!rt.IsPC() || AllowUnpredictable())) {
      EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
              ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
              ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
              (rt.GetCode() << 12) | rn.Encode(7, 16));
      return;
    }
  }
  Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
}

void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_imm3H_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                   ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
}

void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
}

void Assembler::vmrs(Condition cond,
                     RegisterOrAPSR_nzcv rt,
                     SpecialFPRegister spec_reg) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
    EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
    AdvanceIT();
    return;
  } else {
    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
    if (cond.IsNotNever()) {
      EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
              (spec_reg.GetReg() << 16));
      return;
    }
  }
  Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
}

void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
    if ((!rt.IsPC() || AllowUnpredictable())) {
      EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) |
                 (rt.GetCode() << 12));
      AdvanceIT();
      return;
    }
  } else {
    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
      EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
              (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
      return;
    }
  }
  Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
}

void Assembler::vmul(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rn,
                     DRegister dm,
                     unsigned index) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
    if (encoded_dt.IsValid() &&
        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t shift = 4;
        if (dt.Is(I16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                   ((mvm & 0x10) << 1));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
    if (encoded_dt.IsValid() &&
        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
      if (cond.Is(al)) {
        uint32_t shift = 4;
        if (dt.Is(I16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                ((mvm & 0x10) << 1));
        return;
      }
    }
  }
  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
}

void Assembler::vmul(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rn,
                     DRegister dm,
                     unsigned index) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
    if (encoded_dt.IsValid() &&
        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t shift = 4;
        if (dt.Is(I16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                   ((mvm & 0x10) << 1));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
    if (encoded_dt.IsValid() &&
        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
      if (cond.Is(al)) {
        uint32_t shift = 4;
        if (dt.Is(I16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                ((mvm & 0x10) << 1));
        return;
      }
    }
  }
  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
}

void Assembler::vmul(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
}

void Assembler::vmul(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
}

void Assembler::vmul(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
}

void Assembler::vmull(Condition cond,
                      DataType dt,
                      QRegister rd,
                      DRegister rn,
                      DRegister dm,
                      unsigned index) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
    if (encoded_dt.IsValid() &&
        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
          (dm.GetCode() <= 15)))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t shift = 4;
        if (dt.Is(S16) || dt.Is(U16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                   ((mvm & 0x10) << 1));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
    if (encoded_dt.IsValid() &&
        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
          (dm.GetCode() <= 15)))) {
      if (cond.Is(al)) {
        uint32_t shift = 4;
        if (dt.Is(S16) || dt.Is(U16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                ((mvm & 0x10) << 1));
        return;
      }
    }
  }
  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
}

void Assembler::vmull(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
}

void Assembler::vmvn(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
}

void Assembler::vmvn(Condition cond,
                     DataType dt,
                     QRegister rd,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    QRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
}

void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
}

void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
}

void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
}

void Assembler::vnmla(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
}

void Assembler::vnmla(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
}

void Assembler::vnmls(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
}

void Assembler::vnmls(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
}

void Assembler::vnmul(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
}

void Assembler::vnmul(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
}

void Assembler::vorn(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rn,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
}

void Assembler::vorn(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rn,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  if (operand.IsRegister()) {
    QRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
}

void Assembler::vorr(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rn,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    DRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
}

void Assembler::vorr(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rn,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    QRegister rm = operand.GetRegister();
    USE(dt);
    if (IsUsingT32()) {
      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    } else {
      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
      if (cond.Is(al)) {
        EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  if (operand.IsImmediate()) {
    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
    if (IsUsingT32()) {
      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
                     rd.Encode(22, 12) |
                     (encoded_dt.GetEncodedImmediate() & 0xf) |
                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
      if (encoded_dt.IsValid() && rd.Is(rn)) {
        if (cond.Is(al)) {
          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
          return;
        }
      }
    }
  }
  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
}

void Assembler::vpadal(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
}

void Assembler::vpadal(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
}

void Assembler::vpadd(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
}

void Assembler::vpaddl(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
}

void Assembler::vpaddl(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
}

void Assembler::vpmax(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
}

void Assembler::vpmin(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
}

void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
    if (cond.IsNotNever() &&
        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
}

void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
    const SRegister& sreg = sreglist.GetFirstSRegister();
    unsigned len = sreglist.GetLength();
    EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
    AdvanceIT();
    return;
  } else {
    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
    if (cond.IsNotNever()) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
}

void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
    if (cond.IsNotNever() &&
        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
}

void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
    const SRegister& sreg = sreglist.GetFirstSRegister();
    unsigned len = sreglist.GetLength();
    EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
    AdvanceIT();
    return;
  } else {
    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
    if (cond.IsNotNever()) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
}

void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_5 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
}

void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_5 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
}

void Assembler::vqadd(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
}

void Assembler::vqadd(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
}

void Assembler::vqdmlal(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
}

void Assembler::vqdmlal(Condition cond,
                        DataType dt,
                        QRegister rd,
                        DRegister rn,
                        DRegister dm,
                        unsigned index) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
    if (encoded_dt.IsValid() &&
        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t shift = 4;
        if (dt.Is(S16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                   ((mvm & 0x10) << 1));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
    if (encoded_dt.IsValid() &&
        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        uint32_t shift = 4;
        if (dt.Is(S16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                ((mvm & 0x10) << 1));
        return;
      }
    }
  }
  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
}

void Assembler::vqdmlsl(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
}

void Assembler::vqdmlsl(Condition cond,
                        DataType dt,
                        QRegister rd,
                        DRegister rn,
                        DRegister dm,
                        unsigned index) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
    if (encoded_dt.IsValid() &&
        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        uint32_t shift = 4;
        if (dt.Is(S16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                   ((mvm & 0x10) << 1));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
    if (encoded_dt.IsValid() &&
        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        uint32_t shift = 4;
        if (dt.Is(S16)) {
          shift = 3;
        }
        uint32_t mvm = dm.GetCode() | index << shift;
        EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
                ((mvm & 0x10) << 1));
        return;
      }
    }
  }
  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
}

void Assembler::vqdmulh(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqdmulh(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqdmulh(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqdmulh(
    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqdmull(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
}

void Assembler::vqdmull(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
}

void Assembler::vqmovn(Condition cond,
                       DataType dt,
                       DRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_op_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
}

void Assembler::vqmovun(Condition cond,
                        DataType dt,
                        DRegister rd,
                        QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_14 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
}

void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_5 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
}

void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_5 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
}

void Assembler::vqrdmulh(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqrdmulh(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqrdmulh(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqrdmulh(
    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_13 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
    if (encoded_dt.IsValid() &&
        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
          (rm.GetLane() <= 1))) &&
        (dt.Is(S16) || dt.Is(S32))) {
      if (cond.Is(al)) {
        EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
        return;
      }
    }
  }
  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
}

void Assembler::vqrshl(
    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
}

void Assembler::vqrshl(
    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
}

void Assembler::vqrshrn(Condition cond,
                        DataType dt,
                        DRegister rd,
                        QRegister rm,
                        const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_op_size_3 encoded_dt(dt);
      Dt_imm6_1 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20280U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitT32_32(0xef800950U |
                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20280U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
}

void Assembler::vqrshrun(Condition cond,
                         DataType dt,
                         DRegister rd,
                         QRegister rm,
                         const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_imm6_2 encoded_dt(dt);
      Dt_size_14 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
}

void Assembler::vqshl(Condition cond,
                      DataType dt,
                      DRegister rd,
                      DRegister rm,
                      const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    DRegister rn = operand.GetRegister();
    Dt_U_size_3 encoded_dt(dt);
    if (IsUsingT32()) {
      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef000410U |
                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          return;
        }
      }
    }
  }
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
}

void Assembler::vqshl(Condition cond,
                      DataType dt,
                      QRegister rd,
                      QRegister rm,
                      const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsRegister()) {
    QRegister rn = operand.GetRegister();
    Dt_U_size_3 encoded_dt(dt);
    if (IsUsingT32()) {
      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef000450U |
                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          return;
        }
      }
    }
  }
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
}

void Assembler::vqshlu(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm,
                       const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_2 encoded_dt(dt);
      if (IsUsingT32()) {
        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
}

void Assembler::vqshlu(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm,
                       const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_2 encoded_dt(dt);
      if (IsUsingT32()) {
        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
}

void Assembler::vqshrn(Condition cond,
                       DataType dt,
                       DRegister rd,
                       QRegister rm,
                       const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_op_size_3 encoded_dt(dt);
      Dt_imm6_1 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20280U |
                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitT32_32(0xef800910U |
                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
        if (encoded_dt.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20280U |
                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
}

void Assembler::vqshrun(Condition cond,
                        DataType dt,
                        DRegister rd,
                        QRegister rm,
                        const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_imm6_2 encoded_dt(dt);
      Dt_size_14 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
}

void Assembler::vqsub(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
}

void Assembler::vqsub(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
}

void Assembler::vraddhn(
    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al)) {
        EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
}

void Assembler::vrecpe(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
}

void Assembler::vrecpe(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
}

void Assembler::vrecps(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
}

void Assembler::vrecps(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
}

void Assembler::vrev16(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
}

void Assembler::vrev16(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
}

void Assembler::vrev32(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_15 encoded_dt(dt);
  if (IsUsingT32()) {
    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
}

void Assembler::vrev32(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_15 encoded_dt(dt);
  if (IsUsingT32()) {
    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
}

void Assembler::vrev64(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
}

void Assembler::vrev64(Condition cond,
                       DataType dt,
                       QRegister rd,
                       QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
}

void Assembler::vrhadd(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
}

void Assembler::vrhadd(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
}

void Assembler::vrinta(DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTA{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20500U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VRINTA{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTA{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20500U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
    // VRINTA{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
}

void Assembler::vrinta(DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTA{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20540U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTA{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20540U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
}

void Assembler::vrinta(DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VRINTA{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTA{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
}

void Assembler::vrintm(DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTM{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20680U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VRINTM{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTM{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20680U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
    // VRINTM{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
}

void Assembler::vrintm(DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTM{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb206c0U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTM{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b206c0U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
}

void Assembler::vrintm(DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VRINTM{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTM{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
}

void Assembler::vrintn(DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTN{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20400U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VRINTN{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTN{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20400U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
    // VRINTN{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
}

void Assembler::vrintn(DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTN{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20440U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTN{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20440U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
}

void Assembler::vrintn(DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VRINTN{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTN{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
}

void Assembler::vrintp(DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTP{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20780U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VRINTP{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTP{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20780U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
    // VRINTP{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
}

void Assembler::vrintp(DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTP{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb207c0U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTP{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b207c0U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
}

void Assembler::vrintp(DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VRINTP{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTP{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
}

void Assembler::vrintr(Condition cond,
                       DataType dt,
                       SRegister rd,
                       SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRINTR{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTR{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintr, &Assembler::vrintr, cond, dt, rd, rm);
}

void Assembler::vrintr(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRINTR{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTR{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintr, &Assembler::vrintr, cond, dt, rd, rm);
}

void Assembler::vrintx(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTX{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20480U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VRINTX{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTX{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20480U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
    // VRINTX{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintx, &Assembler::vrintx, cond, dt, rd, rm);
}

void Assembler::vrintx(DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTX{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb204c0U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTX{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b204c0U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintx, &Assembler::vrintx, dt, rd, rm);
}

void Assembler::vrintx(Condition cond,
                       DataType dt,
                       SRegister rd,
                       SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRINTX{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTX{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintx, &Assembler::vrintx, cond, dt, rd, rm);
}

void Assembler::vrintz(Condition cond,
                       DataType dt,
                       DRegister rd,
                       DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTZ{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb20580U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VRINTZ{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTZ{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b20580U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
    // VRINTZ{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintz, &Assembler::vrintz, cond, dt, rd, rm);
}

void Assembler::vrintz(DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  Dt_size_16 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRINTZ{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      EmitT32_32(0xffb205c0U | (encoded_dt.GetEncodingValue() << 18) |
                 rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTZ{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      EmitA32(0xf3b205c0U | (encoded_dt.GetEncodingValue() << 18) |
              rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintz, &Assembler::vrintz, dt, rd, rm);
}

void Assembler::vrintz(Condition cond,
                       DataType dt,
                       SRegister rd,
                       SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRINTZ{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VRINTZ{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVrintz, &Assembler::vrintz, cond, dt, rd, rm);
}

void Assembler::vrshl(
    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
}

void Assembler::vrshl(
    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
        return;
      }
    }
  }
  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
}

void Assembler::vrshr(Condition cond,
                      DataType dt,
                      DRegister rd,
                      DRegister rm,
                      const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                       rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                    rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
}

void Assembler::vrshr(Condition cond,
                      DataType dt,
                      QRegister rd,
                      QRegister rm,
                      const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                       rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                    rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
}

void Assembler::vrshrn(Condition cond,
                       DataType dt,
                       DRegister rd,
                       QRegister rm,
                       const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_imm6_3 encoded_dt(dt);
      Dt_size_3 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitT32_32(0xef800850U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitA32(0xf2800850U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
}

void Assembler::vrsqrte(Condition cond,
                        DataType dt,
                        DRegister rd,
                        DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
}

void Assembler::vrsqrte(Condition cond,
                        DataType dt,
                        QRegister rd,
                        QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_F_size_4 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
}

void Assembler::vrsqrts(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
}

void Assembler::vrsqrts(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
}

void Assembler::vrsra(Condition cond,
                      DataType dt,
                      DRegister rd,
                      DRegister rm,
                      const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
}

void Assembler::vrsra(Condition cond,
                      DataType dt,
                      QRegister rd,
                      QRegister rm,
                      const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
}

void Assembler::vrsubhn(
    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al)) {
        EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
}

void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
    if (OutsideITBlock() && dt.Is(F64)) {
      EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
}

void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
}

void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
    if (OutsideITBlock() && dt.Is(F64)) {
      EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
}

void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
}

void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
    if (OutsideITBlock() && dt.Is(F64)) {
      EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
}

void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
}

void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
    if (OutsideITBlock() && dt.Is(F64)) {
      EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
    if (dt.Is(F64)) {
      EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
}

void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(al);
  if (IsUsingT32()) {
    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
    if (OutsideITBlock() && dt.Is(F32)) {
      EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
    if (dt.Is(F32)) {
      EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
}

void Assembler::vshl(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_3 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xef800510U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf2800510U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  if (operand.IsRegister()) {
    DRegister rn = operand.GetRegister();
    Dt_U_size_3 encoded_dt(dt);
    if (IsUsingT32()) {
      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef000400U |
                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          return;
        }
      }
    }
  }
  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
}

void Assembler::vshl(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_3 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xef800550U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf2800550U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  if (operand.IsRegister()) {
    QRegister rn = operand.GetRegister();
    Dt_U_size_3 encoded_dt(dt);
    if (IsUsingT32()) {
      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          EmitT32_32(0xef000440U |
                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
      if (encoded_dt.IsValid()) {
        if (cond.Is(al)) {
          EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
          return;
        }
      }
    }
  }
  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
}

void Assembler::vshll(Condition cond,
                      DataType dt,
                      QRegister rd,
                      DRegister rm,
                      const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_imm6_4 encoded_dt(dt);
      Dt_size_17 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() + imm;
            EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() + imm;
            EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
}

void Assembler::vshr(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                       rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                    rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
}

void Assembler::vshr(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                       rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
                    rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
}

void Assembler::vshrn(Condition cond,
                      DataType dt,
                      DRegister rd,
                      QRegister rm,
                      const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_imm6_3 encoded_dt(dt);
      Dt_size_3 encoded_dt_2(dt);
      if (IsUsingT32()) {
        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitT32_32(0xef800810U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
                       rd.Encode(22, 12) | rm.Encode(5, 0));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() / 2 - imm;
            EmitA32(0xf2800810U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
        if (encoded_dt_2.IsValid() && (imm == 0)) {
          if (cond.Is(al)) {
            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
                    rd.Encode(22, 12) | rm.Encode(5, 0));
            return;
          }
        }
      }
    }
  }
  Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
}

void Assembler::vsli(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_4 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xff800510U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf3800510U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
}

void Assembler::vsli(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_4 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = imm;
            EmitT32_32(0xff800550U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
          if (cond.Is(al)) {
            uint32_t imm6 = imm;
            EmitA32(0xf3800550U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
}

void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
    if (dt.Is(F32)) {
      EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
}

void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
    if (dt.Is(F64)) {
      EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
}

void Assembler::vsra(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
}

void Assembler::vsra(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_1 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
}

void Assembler::vsri(Condition cond,
                     DataType dt,
                     DRegister rd,
                     DRegister rm,
                     const DOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_4 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xff800410U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf3800410U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
}

void Assembler::vsri(Condition cond,
                     DataType dt,
                     QRegister rd,
                     QRegister rm,
                     const QOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
      Dt_L_imm6_4 encoded_dt(dt);
      if (IsUsingT32()) {
        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al) || AllowStronglyDiscouraged()) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitT32_32(0xff800450U |
                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            AdvanceIT();
            return;
          }
        }
      } else {
        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
          if (cond.Is(al)) {
            uint32_t imm6 = dt.GetSize() - imm;
            EmitA32(0xf3800450U |
                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
            return;
          }
        }
      }
    }
  }
  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
}

void Assembler::vst1(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_6 encoded_dt(dt);
    Dt_size_7 encoded_dt_2(dt);
    Align_align_5 encoded_align_1(align, nreglist);
    Align_index_align_1 encoded_align_2(align, nreglist, dt);
    if (IsUsingT32()) {
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsOffset() &&
          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsOffset() &&
          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_6 encoded_dt(dt);
    Dt_size_7 encoded_dt_2(dt);
    Align_align_5 encoded_align_1(align, nreglist);
    Align_index_align_1 encoded_align_2(align, nreglist, dt);
    if (IsUsingT32()) {
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          switch (nreglist.GetLength()) {
            default:
              VIXL_UNREACHABLE_OR_FALLTHROUGH();
            case 1:
              len_encoding = 0x7;
              break;
            case 2:
              len_encoding = 0xa;
              break;
            case 3:
              len_encoding = 0x6;
              break;
            case 4:
              len_encoding = 0x2;
              break;
          }
          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
}

void Assembler::vst2(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_7 encoded_dt(dt);
    Align_align_2 encoded_align_1(align, nreglist);
    Align_index_align_2 encoded_align_2(align, nreglist, dt);
    if (IsUsingT32()) {
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Align_align_2 encoded_align_1(align, nreglist);
    Align_index_align_2 encoded_align_2(align, nreglist, dt);
    if (IsUsingT32()) {
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding;
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x8;
          }
          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
            len_encoding = 0x9;
          }
          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
            len_encoding = 0x3;
          }
          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
}

void Assembler::vst3(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_7 encoded_dt(dt);
    Align_align_3 encoded_align_1(align);
    if (IsUsingT32()) {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Align_align_3 encoded_align_1(align);
    if (IsUsingT32()) {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
}

void Assembler::vst3(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Dt_size_7 encoded_dt(dt);
    Index_1 encoded_align_1(nreglist, dt);
    if (IsUsingT32()) {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Sign sign = operand.GetSign();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Index_1 encoded_align_1(nreglist, dt);
    if (IsUsingT32()) {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          sign.IsPlus() && operand.IsPostIndex() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
          sign.IsPlus() && operand.IsPostIndex() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
}

void Assembler::vst4(Condition cond,
                     DataType dt,
                     const NeonRegisterList& nreglist,
                     const AlignedMemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediateZero()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Dt_size_7 encoded_dt(dt);
    Align_align_4 encoded_align_1(align);
    Align_index_align_3 encoded_align_2(align, nreglist, dt);
    if (IsUsingT32()) {
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16));
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_1.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16));
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsOffset() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          operand.IsPostIndex() && encoded_align_2.IsValid() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16));
          return;
        }
      }
    }
  }
  if (operand.IsPlainRegister()) {
    Register rn = operand.GetBaseRegister();
    Alignment align = operand.GetAlignment();
    Register rm = operand.GetOffsetRegister();
    Dt_size_7 encoded_dt(dt);
    Align_align_4 encoded_align_1(align);
    Align_index_align_3 encoded_align_2(align, nreglist, dt);
    if (IsUsingT32()) {
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
                     (encoded_align_1.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (len_encoding << 8) |
                     (rn.GetCode() << 16) | rm.GetCode());
          AdvanceIT();
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al) || AllowStronglyDiscouraged()) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
                     (encoded_align_2.GetEncodingValue() << 4) |
                     first.Encode(22, 12) | (rn.GetCode() << 16) |
                     rm.GetCode());
          AdvanceIT();
          return;
        }
      }
    } else {
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
                  (encoded_align_1.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (len_encoding << 8) |
                  (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
        if (cond.Is(al)) {
          const DRegister& first = nreglist.GetFirstDRegister();
          EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
                  (encoded_align_2.GetEncodingValue() << 4) |
                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
          return;
        }
      }
    }
  }
  Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
}

void Assembler::vstm(Condition cond,
                     DataType dt,
                     Register rn,
                     WriteBack write_back,
                     DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
                              AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
}

void Assembler::vstm(Condition cond,
                     DataType dt,
                     Register rn,
                     WriteBack write_back,
                     SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
    if ((!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
    if (cond.IsNotNever() &&
        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
}

void Assembler::vstmdb(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
    if (write_back.DoesWriteBack() &&
        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              dreg.Encode(22, 12) | (len & 0xff));
      return;
    }
  }
  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
}

void Assembler::vstmdb(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
    if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
        (!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              sreg.Encode(22, 12) | (len & 0xff));
      return;
    }
  }
  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
}

void Assembler::vstmia(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       DRegisterList dreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
         AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
                              AllowUnpredictable())) {
      const DRegister& dreg = dreglist.GetFirstDRegister();
      unsigned len = dreglist.GetLength() * 2;
      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
}

void Assembler::vstmia(Condition cond,
                       DataType dt,
                       Register rn,
                       WriteBack write_back,
                       SRegisterList sreglist) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
    if ((!rn.IsPC() || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
                 (len & 0xff));
      AdvanceIT();
      return;
    }
  } else {
    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
    if (cond.IsNotNever() &&
        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
      const SRegister& sreg = sreglist.GetFirstSRegister();
      unsigned len = sreglist.GetLength();
      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
              (len & 0xff));
      return;
    }
  }
  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
}

void Assembler::vstr(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                (rn.GetCode() << 16) | offset_ | (sign << 23));
        return;
      }
    }
  }
  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
}

void Assembler::vstr(Condition cond,
                     DataType dt,
                     SRegister rd,
                     const MemOperand& operand) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (operand.IsImmediate()) {
    Register rn = operand.GetBaseRegister();
    int32_t offset = operand.GetOffsetImmediate();
    if (IsUsingT32()) {
      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() &&
          (!rn.IsPC() || AllowUnpredictable())) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
                   offset_ | (sign << 23));
        AdvanceIT();
        return;
      }
    } else {
      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
        uint32_t offset_ = abs(offset) >> 2;
        EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
                (rn.GetCode() << 16) | offset_ | (sign << 23));
        return;
      }
    }
  }
  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
}

void Assembler::vsub(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
    if (dt.Is(F64)) {
      EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
    if (dt.Is(F64) && cond.IsNotNever()) {
      EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
}

void Assembler::vsub(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_2 encoded_dt(dt);
  if (IsUsingT32()) {
    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
    if (dt.Is(F32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                   rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
    if (dt.Is(F32)) {
      if (cond.Is(al)) {
        EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                rm.Encode(5, 0));
        return;
      }
    }
    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
}

void Assembler::vsub(
    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
    if (dt.Is(F32)) {
      EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
                 rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
    if (dt.Is(F32) && cond.IsNotNever()) {
      EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
              rn.Encode(7, 16) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
}

void Assembler::vsubhn(
    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_3 encoded_dt(dt);
  if (IsUsingT32()) {
    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
      if (cond.Is(al)) {
        EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
}

void Assembler::vsubl(
    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
}

void Assembler::vsubw(
    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_U_size_1 encoded_dt(dt);
  if (IsUsingT32()) {
    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
}

void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
}

void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  USE(dt);
  if (IsUsingT32()) {
    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
    if (cond.Is(al) || AllowStronglyDiscouraged()) {
      EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
      AdvanceIT();
      return;
    }
  } else {
    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
    if (cond.Is(al)) {
      EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
      return;
    }
  }
  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
}

void Assembler::vtbl(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const NeonRegisterList& nreglist,
                     DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        const DRegister& first = nreglist.GetFirstDRegister();
        uint32_t len_encoding = nreglist.GetLength() - 1;
        EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
                   (len_encoding << 8) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
      if (cond.Is(al)) {
        const DRegister& first = nreglist.GetFirstDRegister();
        uint32_t len_encoding = nreglist.GetLength() - 1;
        EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
                (len_encoding << 8) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
}

void Assembler::vtbx(Condition cond,
                     DataType dt,
                     DRegister rd,
                     const NeonRegisterList& nreglist,
                     DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        const DRegister& first = nreglist.GetFirstDRegister();
        uint32_t len_encoding = nreglist.GetLength() - 1;
        EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
                   (len_encoding << 8) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
      if (cond.Is(al)) {
        const DRegister& first = nreglist.GetFirstDRegister();
        uint32_t len_encoding = nreglist.GetLength() - 1;
        EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
                (len_encoding << 8) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
}

void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
}

void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
}

void Assembler::vtst(
    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
}

void Assembler::vtst(
    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
}

void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_15 encoded_dt(dt);
  if (IsUsingT32()) {
    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
    if (dt.Is(Untyped32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
    if (dt.Is(Untyped32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
}

void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
}

void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_15 encoded_dt(dt);
  if (IsUsingT32()) {
    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
    if (dt.Is(Untyped32)) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
    if (dt.Is(Untyped32)) {
      if (cond.Is(al)) {
        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
}

void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  Dt_size_7 encoded_dt(dt);
  if (IsUsingT32()) {
    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al) || AllowStronglyDiscouraged()) {
        EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
                   rd.Encode(22, 12) | rm.Encode(5, 0));
        AdvanceIT();
        return;
      }
    }
  } else {
    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
    if (encoded_dt.IsValid()) {
      if (cond.Is(al)) {
        EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
                rd.Encode(22, 12) | rm.Encode(5, 0));
        return;
      }
    }
  }
  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
}

void Assembler::yield(Condition cond, EncodingSize size) {
  VIXL_ASSERT(AllowAssembler());
  CheckIT(cond);
  if (IsUsingT32()) {
    // YIELD{<c>}{<q>} ; T1
    if (!size.IsWide()) {
      EmitT32_16(0xbf10);
      AdvanceIT();
      return;
    }
    // YIELD{<c>}.W ; T2
    if (!size.IsNarrow()) {
      EmitT32_32(0xf3af8001U);
      AdvanceIT();
      return;
    }
  } else {
    // YIELD{<c>}{<q>} ; A1
    if (cond.IsNotNever()) {
      EmitA32(0x0320f001U | (cond.GetCondition() << 28));
      return;
    }
  }
  Delegate(kYield, &Assembler::yield, cond, size);
}
// End of generated code.

}  // namespace aarch32
}  // namespace vixl
