diff --git a/src/codegen/arm/assembler-arm.cc b/src/codegen/arm/assembler-arm.cc index 1e7fa26858..d8502e1962 100644 --- a/src/codegen/arm/assembler-arm.cc +++ b/src/codegen/arm/assembler-arm.cc @@ -4338,9 +4338,8 @@ static Instr EncodeNeonShiftRegisterOp(NeonShiftOp op, NeonDataType dt, static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonSize size, bool is_unsigned, NeonRegType reg_type, int dst_code, int src_code, int shift) { - int imm6 = 0; int size_in_bits = kBitsPerByte << static_cast(size); - int op_encoding = 0; + int op_encoding = 0, imm6 = 0, L = 0; switch (op) { case VSHL: { DCHECK(shift >= 0 && size_in_bits > shift); @@ -4357,30 +4356,29 @@ static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonSize size, bool is_unsigned, case VSLI: { DCHECK(shift >= 0 && size_in_bits > shift); imm6 = size_in_bits + shift; - int L = imm6 >> 6; - imm6 &= 0x3F; - op_encoding = B24 | 0x5 * B8 | L * B7; + op_encoding = B24 | 0x5 * B8; break; } case VSRI: { DCHECK(shift > 0 && size_in_bits >= shift); imm6 = 2 * size_in_bits - shift; - int L = imm6 >> 6; - imm6 &= 0x3F; - op_encoding = B24 | 0x4 * B8 | L * B7; + op_encoding = B24 | 0x4 * B8; break; } default: UNREACHABLE(); } + L = imm6 >> 6; + imm6 &= 0x3F; + int vd, d; NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding); int vm, m; NeonSplitCode(reg_type, src_code, &vm, &m, &op_encoding); - return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | m * B5 | B4 | vm | - op_encoding; + return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | L * B7 | m * B5 | B4 | + vm | op_encoding; } void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, diff --git a/src/diagnostics/arm/disasm-arm.cc b/src/diagnostics/arm/disasm-arm.cc index 962af46364..457f158305 100644 --- a/src/diagnostics/arm/disasm-arm.cc +++ b/src/diagnostics/arm/disasm-arm.cc @@ -2033,19 +2033,23 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d", Vd, Vn, Vm, imm4); - } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) { + } else if (instr->Bits(11, 8) == 5 && instr->Bit(4) == 1) { // vshl.i Qd, Qm, shift - int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); - int shift = instr->Bits(21, 16) - size; + int imm7 = instr->Bits(21, 16); + if (instr->Bit(7) != 0) imm7 += 64; + int size = base::bits::RoundDownToPowerOfTwo32(imm7); + int shift = imm7 - size; int Vd = instr->VFPDRegValue(kSimd128Precision); int Vm = instr->VFPMRegValue(kSimd128Precision); out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vshl.i%d q%d, q%d, #%d", size, Vd, Vm, shift); - } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { + } else if (instr->Bits(11, 8) == 0 && instr->Bit(4) == 1) { // vshr.s Qd, Qm, shift - int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); - int shift = 2 * size - instr->Bits(21, 16); + int imm7 = instr->Bits(21, 16); + if (instr->Bit(7) != 0) imm7 += 64; + int size = base::bits::RoundDownToPowerOfTwo32(imm7); + int shift = 2 * size - imm7; int Vd = instr->VFPDRegValue(kSimd128Precision); int Vm = instr->VFPMRegValue(kSimd128Precision); out_buffer_pos_ += @@ -2358,11 +2362,13 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { Unknown(instr); } } - } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1 && + } else if (instr->Bits(11, 8) == 0 && instr->Bit(4) == 1 && instr->Bit(6) == 1) { // vshr.u Qd, Qm, shift - int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); - int shift = 2 * size - instr->Bits(21, 16); + int imm7 = instr->Bits(21, 16); + if (instr->Bit(7) != 0) imm7 += 64; + int size = base::bits::RoundDownToPowerOfTwo32(imm7); + int shift = 2 * size - imm7; int Vd = instr->VFPDRegValue(kSimd128Precision); int Vm = instr->VFPMRegValue(kSimd128Precision); out_buffer_pos_ += diff --git a/src/execution/arm/simulator-arm.cc b/src/execution/arm/simulator-arm.cc index ae5996bb57..eea99366b4 100644 --- a/src/execution/arm/simulator-arm.cc +++ b/src/execution/arm/simulator-arm.cc @@ -4636,13 +4636,16 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { dst[i] = src2[i - boundary]; } set_neon_register(Vd, dst); - } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) { + } else if (instr->Bits(11, 8) == 5 && instr->Bit(4) == 1) { // vshl.i Qd, Qm, shift - int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); - int shift = instr->Bits(21, 16) - size; + int imm7 = instr->Bits(21, 16); + if (instr->Bit(7) != 0) imm7 += 64; + int size = base::bits::RoundDownToPowerOfTwo32(imm7); + int shift = imm7 - size; int Vd = instr->VFPDRegValue(kSimd128Precision); int Vm = instr->VFPMRegValue(kSimd128Precision); - NeonSize ns = static_cast(size / 16); + NeonSize ns = + static_cast(base::bits::WhichPowerOfTwo(size >> 3)); switch (ns) { case Neon8: ShiftLeft(this, Vd, Vm, shift); @@ -4653,17 +4656,20 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { case Neon32: ShiftLeft(this, Vd, Vm, shift); break; - default: - UNREACHABLE(); + case Neon64: + ShiftLeft(this, Vd, Vm, shift); break; } - } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { + } else if (instr->Bits(11, 8) == 0 && instr->Bit(4) == 1) { // vshr.s Qd, Qm, shift - int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); - int shift = 2 * size - instr->Bits(21, 16); + int imm7 = instr->Bits(21, 16); + if (instr->Bit(7) != 0) imm7 += 64; + int size = base::bits::RoundDownToPowerOfTwo32(imm7); + int shift = 2 * size - imm7; int Vd = instr->VFPDRegValue(kSimd128Precision); int Vm = instr->VFPMRegValue(kSimd128Precision); - NeonSize ns = static_cast(size / 16); + NeonSize ns = + static_cast(base::bits::WhichPowerOfTwo(size >> 3)); switch (ns) { case Neon8: ArithmeticShiftRight(this, Vd, Vm, shift); @@ -4674,8 +4680,8 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { case Neon32: ArithmeticShiftRight(this, Vd, Vm, shift); break; - default: - UNREACHABLE(); + case Neon64: + ArithmeticShiftRight(this, Vd, Vm, shift); break; } } else { @@ -5437,13 +5443,16 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { } else { UNIMPLEMENTED(); } - } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) { + } else if (instr->Bits(11, 8) == 0 && instr->Bit(4) == 1) { // vshr.u Qd, Qm, shift - int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16)); - int shift = 2 * size - instr->Bits(21, 16); + int imm7 = instr->Bits(21, 16); + if (instr->Bit(7) != 0) imm7 += 64; + int size = base::bits::RoundDownToPowerOfTwo32(imm7); + int shift = 2 * size - imm7; int Vd = instr->VFPDRegValue(kSimd128Precision); int Vm = instr->VFPMRegValue(kSimd128Precision); - NeonSize ns = static_cast(size / 16); + NeonSize ns = + static_cast(base::bits::WhichPowerOfTwo(size >> 3)); switch (ns) { case Neon8: ShiftRight(this, Vd, Vm, shift); @@ -5454,8 +5463,8 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) { case Neon32: ShiftRight(this, Vd, Vm, shift); break; - default: - UNREACHABLE(); + case Neon64: + ShiftRight(this, Vd, Vm, shift); break; } } else if (instr->Bits(11, 8) == 0x5 && instr->Bit(6) == 0 && diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc index a75637efdf..327384cd70 100644 --- a/test/cctest/test-disasm-arm.cc +++ b/test/cctest/test-disasm-arm.cc @@ -1177,6 +1177,8 @@ TEST(Neon) { "f2dae550 vshl.i16 q15, q0, #10"); COMPARE(vshl(NeonS32, q15, q0, 17), "f2f1e550 vshl.i32 q15, q0, #17"); + COMPARE(vshl(NeonS64, q15, q0, 40), + "f2e8e5d0 vshl.i64 q15, q0, #40"); COMPARE(vshl(NeonS8, q15, q0, q1), "f242e440 vshl.s8 q15, q0, q1"); COMPARE(vshl(NeonU16, q15, q2, q3), @@ -1189,6 +1191,10 @@ TEST(Neon) { "f3d6e050 vshr.u16 q15, q0, #10"); COMPARE(vshr(NeonS32, q15, q0, 17), "f2efe050 vshr.s32 q15, q0, #17"); + COMPARE(vshr(NeonS64, q15, q0, 40), + "f2d8e0d0 vshr.s64 q15, q0, #40"); + COMPARE(vshr(NeonU64, q15, q0, 40), + "f3d8e0d0 vshr.u64 q15, q0, #40"); COMPARE(vsli(Neon64, d2, d0, 32), "f3a02590 vsli.64 d2, d0, #32"); COMPARE(vsli(Neon32, d7, d8, 17),