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:
parent
ee8da2795f
commit
437b3b6fd2
@ -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,
|
||||
|
@ -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_ +=
|
||||
|
@ -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 &&
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user