// 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