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