Support Neon64 size for shifts

Add 64-bit data size support to SHL and SHR, add simulator logic to
support new data size, and fix disasm.

For the disasm fix, casting size / 16 to NeonSize no longer works when
given a size of 64, it is 4, but should be 3.

Change-Id: I5bd1ce254cd3ff4b86159837087f22b2ed06703e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1994180
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65825}
This commit is contained in:
Ng Zhi An 2020-01-10 09:46:51 -08:00 committed by Commit Bot
parent ee8da2795f
commit 437b3b6fd2
4 changed files with 56 additions and 37 deletions

View File

@ -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<int>(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,

View File

@ -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<size> 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<size> 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<size> 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_ +=

View File

@ -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<size> 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<NeonSize>(size / 16);
NeonSize ns =
static_cast<NeonSize>(base::bits::WhichPowerOfTwo(size >> 3));
switch (ns) {
case Neon8:
ShiftLeft<uint8_t, kSimd128Size>(this, Vd, Vm, shift);
@ -4653,17 +4656,20 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
case Neon32:
ShiftLeft<uint32_t, kSimd128Size>(this, Vd, Vm, shift);
break;
default:
UNREACHABLE();
case Neon64:
ShiftLeft<uint64_t, kSimd128Size>(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<size> 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<NeonSize>(size / 16);
NeonSize ns =
static_cast<NeonSize>(base::bits::WhichPowerOfTwo(size >> 3));
switch (ns) {
case Neon8:
ArithmeticShiftRight<int8_t, kSimd128Size>(this, Vd, Vm, shift);
@ -4674,8 +4680,8 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
case Neon32:
ArithmeticShiftRight<int32_t, kSimd128Size>(this, Vd, Vm, shift);
break;
default:
UNREACHABLE();
case Neon64:
ArithmeticShiftRight<int64_t, kSimd128Size>(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<size> 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<NeonSize>(size / 16);
NeonSize ns =
static_cast<NeonSize>(base::bits::WhichPowerOfTwo(size >> 3));
switch (ns) {
case Neon8:
ShiftRight<uint8_t, kSimd128Size>(this, Vd, Vm, shift);
@ -5454,8 +5463,8 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
case Neon32:
ShiftRight<uint32_t, kSimd128Size>(this, Vd, Vm, shift);
break;
default:
UNREACHABLE();
case Neon64:
ShiftRight<uint64_t, kSimd128Size>(this, Vd, Vm, shift);
break;
}
} else if (instr->Bits(11, 8) == 0x5 && instr->Bit(6) == 0 &&

View File

@ -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),