| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index fc33b660011afc7731c5136a4d9a7720bd96353f..2b6f416e8506f6d312c108901ebdd10d4fe8402b 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -510,11 +510,14 @@ const Instr kLdrStrInstrTypeMask = 0xffff0000;
|
| const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
|
| const Instr kLdrStrOffsetMask = 0x00000fff;
|
|
|
| +const Instr kThumbLdrPCMask = BH15 | 7 * BH12 | 15 * BH8 | 7 * BH4 | 15 * BH0;
|
| +const Instr kThumbLdrPCPattern = BH15 | 7 * BH12 | BH11 | BH6 | BH4 | 15 * BH0;
|
|
|
| Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
|
| : AssemblerBase(isolate, buffer, buffer_size),
|
| recorded_ast_id_(TypeFeedbackId::None()),
|
| - positions_recorder_(this) {
|
| + positions_recorder_(this),
|
| + thumb_mode_(false) {
|
| reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
|
| num_pending_reloc_info_ = 0;
|
| num_pending_64_bit_reloc_info_ = 0;
|
| @@ -775,6 +778,10 @@ int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
|
|
|
|
|
| int Assembler::target_at(int pos) {
|
| + if (is_thumb_mode()) {
|
| + return target_at_thumb(pos);
|
| + }
|
| +
|
| Instr instr = instr_at(pos);
|
| if (is_uint24(instr)) {
|
| // Emitted link to a label, not part of a branch.
|
| @@ -792,6 +799,11 @@ int Assembler::target_at(int pos) {
|
|
|
|
|
| void Assembler::target_at_put(int pos, int target_pos) {
|
| + if (is_thumb_mode()) {
|
| + target_at_put_thumb(pos, target_pos);
|
| + return;
|
| + }
|
| +
|
| Instr instr = instr_at(pos);
|
| if (is_uint24(instr)) {
|
| ASSERT(target_pos == pos || target_pos >= 0);
|
| @@ -1313,12 +1325,20 @@ int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
|
| // Block the emission of the constant pool, since the branch instruction must
|
| // be emitted at the pc offset recorded by the label.
|
| BlockConstPoolFor(1);
|
| + if (is_thumb_mode()) {
|
| + return target_pos - (pc_offset() + kThumbPcLoadDelta);
|
| + }
|
| return target_pos - (pc_offset() + kPcLoadDelta);
|
| }
|
|
|
|
|
| // Branch instructions.
|
| void Assembler::b(int branch_offset, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT((branch_offset & 1) == 0);
|
| + b_thumb(branch_offset, cond);
|
| + return;
|
| + }
|
| ASSERT((branch_offset & 3) == 0);
|
| int imm24 = branch_offset >> 2;
|
| ASSERT(is_int24(imm24));
|
| @@ -1333,6 +1353,13 @@ void Assembler::b(int branch_offset, Condition cond) {
|
|
|
| void Assembler::bl(int branch_offset, Condition cond) {
|
| positions_recorder()->WriteRecordedPositions();
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ASSERT((branch_offset & 1) == 0);
|
| + int imm = branch_offset >> 1;
|
| + emit32(thumb32_mode4(BL_32_IMM) | thumb32_sign_extend_imm24(imm));
|
| + return;
|
| + }
|
| ASSERT((branch_offset & 3) == 0);
|
| int imm24 = branch_offset >> 2;
|
| ASSERT(is_int24(imm24));
|
| @@ -1342,6 +1369,12 @@ void Assembler::bl(int branch_offset, Condition cond) {
|
|
|
| void Assembler::blx(int branch_offset) { // v5 and above
|
| positions_recorder()->WriteRecordedPositions();
|
| + if (is_thumb_mode()) {
|
| + ASSERT((branch_offset & 3) == 0);
|
| + int imm = branch_offset >> 1;
|
| + emit32(thumb32_mode4(BLX_32_IMM) | thumb32_sign_extend_imm24(imm));
|
| + return;
|
| + }
|
| ASSERT((branch_offset & 1) == 0);
|
| int h = ((branch_offset & 2) >> 1)*B24;
|
| int imm24 = branch_offset >> 2;
|
| @@ -1353,6 +1386,11 @@ void Assembler::blx(int branch_offset) { // v5 and above
|
| void Assembler::blx(Register target, Condition cond) { // v5 and above
|
| positions_recorder()->WriteRecordedPositions();
|
| ASSERT(!target.is(pc));
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit16(thumb16_mode3(BLX_REG) | thumb16_anyreg_encoding(target));
|
| + return;
|
| + }
|
| emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
|
| }
|
|
|
| @@ -1360,6 +1398,11 @@ void Assembler::blx(Register target, Condition cond) { // v5 and above
|
| void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t
|
| positions_recorder()->WriteRecordedPositions();
|
| ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit16(thumb16_mode3(BX_REG) | thumb16_anyreg_encoding(target));
|
| + return;
|
| + }
|
| emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
|
| }
|
|
|
| @@ -1368,42 +1411,70 @@ void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t
|
|
|
| void Assembler::and_(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + and_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | AND | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::eor(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + eor_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | EOR | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::sub(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + sub_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | SUB | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::rsb(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + rsb_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | RSB | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::add(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + add_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | ADD | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::adc(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + adc_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | ADC | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::sbc(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + sbc_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | SBC | s, src1, dst, src2);
|
| }
|
|
|
| @@ -1415,16 +1486,28 @@ void Assembler::rsc(Register dst, Register src1, const Operand& src2,
|
|
|
|
|
| void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + tst_thumb(src1, src2, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | TST | S, src1, r0, src2);
|
| }
|
|
|
|
|
| void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + teq_thumb(src1, src2, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | TEQ | S, src1, r0, src2);
|
| }
|
|
|
|
|
| void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + cmp_thumb(src1, src2, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | CMP | S, src1, r0, src2);
|
| }
|
|
|
| @@ -1437,12 +1520,20 @@ void Assembler::cmp_raw_immediate(
|
|
|
|
|
| void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + cmn_thumb(src1, src2, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | CMN | S, src1, r0, src2);
|
| }
|
|
|
|
|
| void Assembler::orr(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + orr_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | ORR | s, src1, dst, src2);
|
| }
|
|
|
| @@ -1455,6 +1546,10 @@ void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
|
| // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
|
| // or MarkCode(int/NopMarkerTypes) pseudo instructions.
|
| ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
|
| + if (is_thumb_mode()) {
|
| + mov_thumb(dst, src, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | MOV | s, r0, dst, src);
|
| }
|
|
|
| @@ -1508,17 +1603,29 @@ void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
|
|
|
|
|
| void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + movt_thumb(reg, immediate, cond);
|
| + return;
|
| + }
|
| emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
|
| }
|
|
|
|
|
| void Assembler::bic(Register dst, Register src1, const Operand& src2,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + bic_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | BIC | s, src1, dst, src2);
|
| }
|
|
|
|
|
| void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + mvn_thumb(dst, src, s, cond);
|
| + return;
|
| + }
|
| addrmod1(cond | MVN | s, r0, dst, src);
|
| }
|
|
|
| @@ -1526,6 +1633,10 @@ void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
|
| // Multiply instructions.
|
| void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
|
| SBit s, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + mla_thumb(dst, src1, src2, srcA, s, cond);
|
| + return;
|
| + }
|
| ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
|
| emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
|
| src2.code()*B8 | B7 | B4 | src1.code());
|
| @@ -1534,6 +1645,10 @@ void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
|
|
|
| void Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + mls_thumb(dst, src1, src2, srcA, cond);
|
| + return;
|
| + }
|
| ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
|
| emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 |
|
| src2.code()*B8 | B7 | B4 | src1.code());
|
| @@ -1542,6 +1657,10 @@ void Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
|
|
|
| void Assembler::sdiv(Register dst, Register src1, Register src2,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + sdiv_thumb(dst, src1, src2, cond);
|
| + return;
|
| + }
|
| ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
|
| ASSERT(IsEnabled(SUDIV));
|
| emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 |
|
| @@ -1552,6 +1671,10 @@ void Assembler::sdiv(Register dst, Register src1, Register src2,
|
| void Assembler::mul(Register dst, Register src1, Register src2,
|
| SBit s, Condition cond) {
|
| ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
|
| + if (is_thumb_mode()) {
|
| + mul_thumb(dst, src1, src2, s, cond);
|
| + return;
|
| + }
|
| // dst goes in bits 16-19 for this instruction!
|
| emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
|
| }
|
| @@ -1563,6 +1686,10 @@ void Assembler::smlal(Register dstL,
|
| Register src2,
|
| SBit s,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + smlal_thumb(dstL, dstH, src1, src2, s, cond);
|
| + return;
|
| + }
|
| ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
|
| ASSERT(!dstL.is(dstH));
|
| emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
|
| @@ -1576,6 +1703,10 @@ void Assembler::smull(Register dstL,
|
| Register src2,
|
| SBit s,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + smull_thumb(dstL, dstH, src1, src2, s, cond);
|
| + return;
|
| + }
|
| ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
|
| ASSERT(!dstL.is(dstH));
|
| emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
|
| @@ -1589,6 +1720,10 @@ void Assembler::umlal(Register dstL,
|
| Register src2,
|
| SBit s,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + umlal_thumb(dstL, dstH, src1, src2, s, cond);
|
| + return;
|
| + }
|
| ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
|
| ASSERT(!dstL.is(dstH));
|
| emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
|
| @@ -1602,6 +1737,10 @@ void Assembler::umull(Register dstL,
|
| Register src2,
|
| SBit s,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + umull_thumb(dstL, dstH, src1, src2, s, cond);
|
| + return;
|
| + }
|
| ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
|
| ASSERT(!dstL.is(dstH));
|
| emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
|
| @@ -1613,6 +1752,14 @@ void Assembler::umull(Register dstL,
|
| void Assembler::clz(Register dst, Register src, Condition cond) {
|
| // v5 and above.
|
| ASSERT(!dst.is(pc) && !src.is(pc));
|
| +
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit32(BH15 | BH14 | BH13 | BH12 | BH11 | BH9 | BH7 | src.code()*BH0 |
|
| + B15 | B14 | B13 | B12 | dst.code()*B8 | B7 | src.code());
|
| + return;
|
| + }
|
| +
|
| emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
|
| 15*B8 | CLZ | src.code());
|
| }
|
| @@ -1637,6 +1784,13 @@ void Assembler::usat(Register dst,
|
| sh = 1;
|
| }
|
|
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit32(thumb32_mode3(USAT_32_IMM) | sh*BH5 |
|
| + thumb32_bit_field(src.rm_, dst, src.shift_imm_, satpos));
|
| + return;
|
| + }
|
| +
|
| emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
|
| src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
|
| }
|
| @@ -1658,6 +1812,14 @@ void Assembler::ubfx(Register dst,
|
| ASSERT(!dst.is(pc) && !src.is(pc));
|
| ASSERT((lsb >= 0) && (lsb <= 31));
|
| ASSERT((width >= 1) && (width <= (32 - lsb)));
|
| +
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit32(thumb32_mode3(UBFX_32_IMM) |
|
| + thumb32_bit_field(src, dst, lsb, width - 1));
|
| + return;
|
| + }
|
| +
|
| emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
|
| lsb*B7 | B6 | B4 | src.code());
|
| }
|
| @@ -1678,6 +1840,14 @@ void Assembler::sbfx(Register dst,
|
| ASSERT(!dst.is(pc) && !src.is(pc));
|
| ASSERT((lsb >= 0) && (lsb <= 31));
|
| ASSERT((width >= 1) && (width <= (32 - lsb)));
|
| +
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit32(thumb32_mode3(SBFX_32_IMM) |
|
| + thumb32_bit_field(src, dst, lsb, width - 1));
|
| + return;
|
| + }
|
| +
|
| emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
|
| lsb*B7 | B6 | B4 | src.code());
|
| }
|
| @@ -1694,6 +1864,13 @@ void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
|
| ASSERT((lsb >= 0) && (lsb <= 31));
|
| ASSERT((width >= 1) && (width <= (32 - lsb)));
|
| int msb = lsb + width - 1;
|
| +
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit32(thumb32_mode3(BFC_32_IMM) | thumb32_bit_field(pc, dst, lsb, msb));
|
| + return;
|
| + }
|
| +
|
| emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
|
| }
|
|
|
| @@ -1713,6 +1890,13 @@ void Assembler::bfi(Register dst,
|
| ASSERT((lsb >= 0) && (lsb <= 31));
|
| ASSERT((width >= 1) && (width <= (32 - lsb)));
|
| int msb = lsb + width - 1;
|
| +
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + emit32(thumb32_mode3(BFI_32_IMM) | thumb32_bit_field(src, dst, lsb, msb));
|
| + return;
|
| + }
|
| +
|
| emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
|
| src.code());
|
| }
|
| @@ -1856,41 +2040,82 @@ void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
|
| if (dst.is(pc)) {
|
| positions_recorder()->WriteRecordedPositions();
|
| }
|
| +
|
| + if (is_thumb_mode()) {
|
| + ldr_thumb(dst, src);
|
| + return;
|
| + }
|
| +
|
| addrmod2(cond | B26 | L, dst, src);
|
| }
|
|
|
|
|
| void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + str_thumb(src, dst);
|
| + return;
|
| + }
|
| addrmod2(cond | B26, src, dst);
|
| }
|
|
|
|
|
| void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ldrb_thumb(dst, src);
|
| + return;
|
| + }
|
| addrmod2(cond | B26 | B | L, dst, src);
|
| }
|
|
|
|
|
| void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + strb_thumb(src, dst);
|
| + return;
|
| + }
|
| addrmod2(cond | B26 | B, src, dst);
|
| }
|
|
|
|
|
| void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ldrh_thumb(dst, src);
|
| + return;
|
| + }
|
| addrmod3(cond | L | B7 | H | B4, dst, src);
|
| }
|
|
|
|
|
| void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + strh_thumb(src, dst);
|
| + return;
|
| + }
|
| addrmod3(cond | B7 | H | B4, src, dst);
|
| }
|
|
|
|
|
| void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ldrsb_thumb(dst, src);
|
| + return;
|
| + }
|
| addrmod3(cond | L | B7 | S6 | B4, dst, src);
|
| }
|
|
|
|
|
| void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ldrsh_thumb(dst, src);
|
| + return;
|
| + }
|
| addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
|
| }
|
|
|
| @@ -1901,6 +2126,12 @@ void Assembler::ldrd(Register dst1, Register dst2,
|
| ASSERT(src.rm().is(no_reg));
|
| ASSERT(!dst1.is(lr)); // r14.
|
| ASSERT_EQ(0, dst1.code() % 2);
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ASSERT(!src.rm_.is_valid()); // Immediate.
|
| + ldrd_imm_t1(dst1, dst2, src);
|
| + return;
|
| + }
|
| ASSERT_EQ(dst1.code() + 1, dst2.code());
|
| addrmod3(cond | B7 | B6 | B4, dst1, src);
|
| }
|
| @@ -1911,8 +2142,14 @@ void Assembler::strd(Register src1, Register src2,
|
| ASSERT(dst.rm().is(no_reg));
|
| ASSERT(!src1.is(lr)); // r14.
|
| ASSERT_EQ(0, src1.code() % 2);
|
| - ASSERT_EQ(src1.code() + 1, src2.code());
|
| ASSERT(IsEnabled(ARMv7));
|
| + if (is_thumb_mode()) {
|
| + ASSERT(cond == al);
|
| + ASSERT(!dst.rm_.is_valid()); // Immediate.
|
| + strd_imm_t1(src1, src2, dst);
|
| + return;
|
| + }
|
| + ASSERT_EQ(src1.code() + 1, src2.code());
|
| addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
|
| }
|
|
|
| @@ -1943,7 +2180,10 @@ void Assembler::ldm(BlockAddrMode am,
|
| Condition cond) {
|
| // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable.
|
| ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
|
| -
|
| + if (is_thumb_mode()) {
|
| + ldm_thumb(am, base, dst, cond);
|
| + return;
|
| + }
|
| addrmod4(cond | B27 | am | L, base, dst);
|
|
|
| // Emit the constant pool after a function return implemented by ldm ..{..pc}.
|
| @@ -1962,6 +2202,10 @@ void Assembler::stm(BlockAddrMode am,
|
| Register base,
|
| RegList src,
|
| Condition cond) {
|
| + if (is_thumb_mode()) {
|
| + stm_thumb(am, base, src, cond);
|
| + return;
|
| + }
|
| addrmod4(cond | B27 | am, base, src);
|
| }
|
|
|
| @@ -1997,6 +2241,11 @@ void Assembler::stop(const char* msg, Condition cond, int32_t code) {
|
|
|
|
|
| void Assembler::bkpt(uint32_t imm16) { // v5 and above
|
| + if (is_thumb_mode()) {
|
| + ASSERT(is_uint8(imm16));
|
| + emit16(B15 | B13 | B12 | B11 | B10 | B9 | (imm16 & 0xFF));
|
| + return;
|
| + }
|
| ASSERT(is_uint16(imm16));
|
| emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
|
| }
|
| @@ -2539,6 +2788,12 @@ void Assembler::vmov(const DwVfpRegister dst,
|
| ASSERT(index.index == 0 || index.index == 1);
|
| int vd, d;
|
| dst.split_code(&vd, &d);
|
| + if (is_thumb_mode() && cond != al) {
|
| + it_thumb(cond, 1);
|
| + emit(al | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
|
| + d*B7 | B4);
|
| + return;
|
| + }
|
| emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
|
| d*B7 | B4);
|
| }
|
| @@ -2816,7 +3071,12 @@ void Assembler::vneg(const DwVfpRegister dst,
|
| dst.split_code(&vd, &d);
|
| int vm, m;
|
| src.split_code(&vm, &m);
|
| -
|
| + if (is_thumb_mode() && cond != al) {
|
| + it_thumb(cond, 1);
|
| + emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 |
|
| + m*B5 | vm);
|
| + return;
|
| + }
|
| emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 |
|
| m*B5 | vm);
|
| }
|
| @@ -3068,6 +3328,11 @@ void Assembler::nop(int type) {
|
| // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
|
| // a type.
|
| ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop.
|
| + if (is_thumb_mode()) {
|
| + uint16_t d = type >> 3;
|
| + emit16(4*B12 | 6*B8 | d*B7 | type*B3 | (type & 7));
|
| + return;
|
| + }
|
| emit(al | 13*B21 | type*B12 | type);
|
| }
|
|
|
| @@ -3088,6 +3353,16 @@ bool Assembler::IsMovW(Instr instr) {
|
| }
|
|
|
|
|
| +bool Assembler::IsMovTThumb(Instr instr) {
|
| + return ((instr & ~MOVW_THUMB_IMM_MASK) == (MOVW_THUMB_MASK | BH7));
|
| +}
|
| +
|
| +
|
| +bool Assembler::IsMovWThumb(Instr instr) {
|
| + return ((instr & ~MOVW_THUMB_IMM_MASK) == MOVW_THUMB_MASK);
|
| +}
|
| +
|
| +
|
| bool Assembler::IsNop(Instr instr, int type) {
|
| ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop.
|
| // Check for mov rx, rx where x = type.
|
| @@ -3379,8 +3654,13 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
|
|
|
| // Put down constant pool marker "Undefined instruction".
|
| // The data size helps disassembly know what to print.
|
| - emit(kConstantPoolMarker |
|
| - EncodeConstantPoolLength(size_after_marker / kPointerSize));
|
| + if (is_thumb_mode()) {
|
| + emit32(kConstantPoolMarker |
|
| + EncodeConstantPoolLength(size_after_marker / kPointerSize));
|
| + } else {
|
| + emit(kConstantPoolMarker |
|
| + EncodeConstantPoolLength(size_after_marker / kPointerSize));
|
| + }
|
|
|
| if (require_64_bit_align) {
|
| emit(kConstantPoolMarker);
|
| @@ -3428,6 +3708,23 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
|
| continue;
|
| }
|
|
|
| + if (is_thumb_mode()) {
|
| + Instr instr = thumb32_instr_at(rinfo.pc());
|
| + int thumb_ldr_delta = 2;
|
| + if ((reinterpret_cast<int>(rinfo.pc()) & 3) == 0) {
|
| + thumb_ldr_delta = 4;
|
| + }
|
| + int delta = pc_ - rinfo.pc() - thumb_ldr_delta;
|
| + ASSERT(is_uint12(delta));
|
| + instr &= ~kOff12Mask;
|
| + instr |= delta;
|
| + thumb32_instr_at_put(rinfo.pc(), instr);
|
| + set_arm_mode();
|
| + emit(rinfo.data());
|
| + set_thumb_mode();
|
| + continue;
|
| + }
|
| +
|
| Instr instr = instr_at(rinfo.pc());
|
|
|
| // 64-bit loads shouldn't get here.
|
|
|