} , ; T1 // CBZ{} , ; T1 static const struct ReferenceInfo kT16CbzInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 126, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{} ; T1 static const struct ReferenceInfo kT16ConditionalBranchInfo = {k16BitT32InstructionSizeInBytes, -256, // Min offset. 254, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // ADR{}{} , ; T1 // LDR{}{} , ; T1 static const struct ReferenceInfo kT16DataInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; T2 static const struct ReferenceInfo kT16BranchInfo = {k16BitT32InstructionSizeInBytes, -2048, // Min offset. 2046, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // LDRD{}{} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 static const struct ReferenceInfo kT16CbzInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 126, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{} ; T1 static const struct ReferenceInfo kT16ConditionalBranchInfo = {k16BitT32InstructionSizeInBytes, -256, // Min offset. 254, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // ADR{}{} , ; T1 // LDR{}{} , ; T1 static const struct ReferenceInfo kT16DataInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; T2 static const struct ReferenceInfo kT16BranchInfo = {k16BitT32InstructionSizeInBytes, -2048, // Min offset. 2046, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // LDRD{}{} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T1 static const struct ReferenceInfo kT16ConditionalBranchInfo = {k16BitT32InstructionSizeInBytes, -256, // Min offset. 254, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // ADR{}{} , ; T1 // LDR{}{} , ; T1 static const struct ReferenceInfo kT16DataInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; T2 static const struct ReferenceInfo kT16BranchInfo = {k16BitT32InstructionSizeInBytes, -2048, // Min offset. 2046, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // LDRD{}{} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 // LDR{}{} , ; T1 static const struct ReferenceInfo kT16DataInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; T2 static const struct ReferenceInfo kT16BranchInfo = {k16BitT32InstructionSizeInBytes, -2048, // Min offset. 2046, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // LDRD{}{} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 static const struct ReferenceInfo kT16DataInfo = {k16BitT32InstructionSizeInBytes, 0, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; T2 static const struct ReferenceInfo kT16BranchInfo = {k16BitT32InstructionSizeInBytes, -2048, // Min offset. 2046, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // LDRD{}{} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T2 static const struct ReferenceInfo kT16BranchInfo = {k16BitT32InstructionSizeInBytes, -2048, // Min offset. 2046, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // LDRD{}{} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , , ; T1 // VLDR{}{}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
}{.64} , ; T1 // VLDR{}{}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
}{.32} , ; T2 static const struct ReferenceInfo kT32DataInfo = {k32BitT32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T3 // LDR{}{} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T2 // LDRB{}{} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 // LDRH{}{} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 // LDRSB{}{} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 // LDRSH{}{} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; T1 // PLD{}{} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T1 // PLI{}{} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T3 static const struct ReferenceInfo kT32FarDataInfo = {k32BitT32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T3 static const struct ReferenceInfo kT32ConditionalBranchInfo = {k32BitT32InstructionSizeInBytes, -1048576, // Min offset. 1048574, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // B{}{} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T4 // BL{}{} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T1 static const struct ReferenceInfo kT32BranchInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777214, // Max offset. 2, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; T2 static const struct ReferenceInfo kT32BlxInfo = {k32BitT32InstructionSizeInBytes, -16777216, // Min offset. 16777212, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDRD{}{} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , , ; A1 // LDRH{}{} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; A1 // LDRSB{}{} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; A1 // LDRSH{}{} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; A1 static const struct ReferenceInfo kA32VeryNearDataInfo = {kA32InstructionSizeInBytes, -255, // Min offset. 255, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // ADR{}{} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; A1 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes, -256, // Min offset. 256, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // VLDR{}{}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
}{.64} , ; A1 // VLDR{}{}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
}{.32} , ; A2 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes, -1020, // Min offset. 1020, // Max offset. 4, // Alignment. ReferenceInfo::kAlignPc}; // LDR{}{} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; A1 // LDRB{}{} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , ; A1 // PLD{}{} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; A1 // PLI{}{} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; A1 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes, -4095, // Min offset. 4095, // Max offset. 1, // Alignment. ReferenceInfo::kAlignPc}; // B{}{} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; A1 // BL{}{} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; A1 static const struct ReferenceInfo kA32BranchInfo = {kA32InstructionSizeInBytes, -33554432, // Min offset. 33554428, // Max offset. 4, // Alignment. ReferenceInfo::kDontAlignPc}; // BLX{}{} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , , ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; 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{}{} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; 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{} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , ; 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{}{} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , {, # } ; 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{}{} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , {, # } ; 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{}{} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , , ; 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{}{} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , PC, # ; 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{} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , , # ; T1 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() && (imm <= 7)) { EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6)); AdvanceIT(); return; } // ADD{} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; T2 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() && (imm <= 255)) { EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm); AdvanceIT(); return; } // ADD{}{} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , SP, # ; 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{}{} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {SP}, SP, # ; 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{}{} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , PC, # ; 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{}{} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; 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{}{} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, , # ; 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{}{} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, SP, # ; 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{}{} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} {}, SP, # ; 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{}{} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{
} , PC, # ; A1 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) { EmitA32(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | immediate_a32.GetEncodingValue()); return; } // ADD{