blob: 5f636981d798f7e04d9bacfb7dd6e44d26580766 [file] [log] [blame]
// 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
((offset & 0x3) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
int32_t target;
if ((offset >= 0) && (offset <= 4095)) {
target = offset;
} else {
target = -offset;
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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
int32_t target;
ImmediateA32 positive_immediate_a32(offset);
if (positive_immediate_a32.IsValid()) {
target = positive_immediate_a32.GetEncodingValue();
} else {
ImmediateA32 negative_immediate_a32(-offset);
VIXL_ASSERT(negative_immediate_a32.IsValid());
// Emit the A2 encoding.
target = negative_immediate_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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
((offset & 0x1) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
((offset & 0x1) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
((offset & 0x1) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
((offset & 0x1) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
((offset & 0x3) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
((offset & 0x1) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
((offset & 0x3) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
((offset & 0x3) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const
VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset =
location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
((offset & 0x1) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
((offset & 0x1) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - pc;
VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
((offset & 0x1) == 0));
const int32_t target = offset >> 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.GetList() & ~0x80ff) == 0)) {
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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
((offset & 0x3) == 0));
const int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
((offset & 0x3) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -255) && (offset <= 255));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -255) && (offset <= 255));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -255) && (offset <= 255));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -255) && (offset <= 255));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const
VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset =
location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 pc,
const Location* location) const
VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset =
location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
uint32_t U = (offset >= 0);
int32_t target = abs(offset) | (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 (IsUsingT32()) {
// POP{<c>}{<q>} <registers> ; T1
if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
GetRegisterListEncoding(registers, 0, 8));
AdvanceIT();
return;
}
// POP{<c>}{<q>} <registers> ; T2
if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
EmitT32_32(0xe8bd0000U |
(GetRegisterListEncoding(registers, 15, 1) << 15) |
(GetRegisterListEncoding(registers, 14, 1) << 14) |
GetRegisterListEncoding(registers, 0, 13));
AdvanceIT();
return;
}
} else {
// POP{<c>}{<q>} <registers> ; A1
if (cond.IsNotNever()) {
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 (IsUsingT32()) {
// POP{<c>}{<q>} <single_register_list> ; 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
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 (IsUsingT32()) {
// PUSH{<c>}{<q>} <registers> ; T1
if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
GetRegisterListEncoding(registers, 0, 8));
AdvanceIT();
return;
}
// PUSH{<c>}{<q>} <registers> ; T1
if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
EmitT32_32(0xe92d0000U |
(GetRegisterListEncoding(registers, 14, 1) << 14) |
GetRegisterListEncoding(registers, 0, 13));
AdvanceIT();
return;
}
} else {
// PUSH{<c>}{<q>} <registers> ; A1
if (cond.IsNotNever()) {
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
if (!size.IsNarrow() && (!rt.IsPC() || AllowUnpredictable())) {
EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
AdvanceIT();
return;
}
} else {
// PUSH{<c>}{<q>} <single_register_list> ; A1
if (cond.IsNotNever() && (!rt.IsPC() || 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.GetList() & ~0x40ff) == 0)) {
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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
((offset & 0x3) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
((offset & 0x3) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kT32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
((offset & 0x3) == 0));
int32_t target = offset >> 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 pc,
const Location* location) const VIXL_OVERRIDE {
pc += kA32PcDelta;
Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
((offset & 0x3) == 0));
int32_t target = offset >> 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