Skip to content

Commit 7dd74a9

Browse files
modulovaluedart-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[vm] arm64: add ushl in its 4S form
Needed to intrinsify Int32x4 operator >>>. Issue: #64170 Issue: #64345 Issue: #64511 TEST=vm/cc/Assembler_Vushlw Change-Id: I613b7a776f873ff52e22e1a75395e24c507769b3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/560561 Reviewed-by: Slava Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Auto-Submit: Modestas Valauskas <valauskasmodestas@gmail.com> Commit-Queue: Slava Egorov <vegorov@google.com>
1 parent 5e219b5 commit 7dd74a9

5 files changed

Lines changed: 63 additions & 0 deletions

File tree

‎runtime/vm/compiler/assembler/assembler_arm64.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,9 @@ class Assembler : public AssemblerBase {
15121512
void vsshlx(VRegister vd, VRegister vn, VRegister vm) {
15131513
EmitSIMDThreeSameOp(VSSHLX, vd, vn, vm);
15141514
}
1515+
void vushlw(VRegister vd, VRegister vn, VRegister vm) {
1516+
EmitSIMDThreeSameOp(VUSHLW, vd, vn, vm);
1517+
}
15151518
void vnot(VRegister vd, VRegister vn) { EmitSIMDTwoRegOp(VNOT, vd, vn); }
15161519
void vabss(VRegister vd, VRegister vn) { EmitSIMDTwoRegOp(VABSS, vd, vn); }
15171520
void vabsd(VRegister vd, VRegister vn) { EmitSIMDTwoRegOp(VABSD, vd, vn); }

‎runtime/vm/compiler/assembler/assembler_arm64_test.cc‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7174,6 +7174,52 @@ ASSEMBLER_TEST_RUN(VsshlxLargeNegativeCount, test) {
71747174
"ret\n");
71757175
}
71767176

7177+
ASSEMBLER_TEST_GENERATE(Vushlw, assembler) {
7178+
__ fldrq(V0, Address(R0, 0));
7179+
__ fldrq(V1, Address(R0, 16));
7180+
__ vushlw(V2, V0, V1);
7181+
__ fstrq(V2, Address(R0, 32));
7182+
__ ret();
7183+
}
7184+
7185+
ASSEMBLER_TEST_RUN(Vushlw, test) {
7186+
typedef void (*VushlwCode)(intptr_t) DART_UNUSED;
7187+
struct {
7188+
uint32_t values[4];
7189+
int32_t shifts[4];
7190+
uint32_t result[4];
7191+
} buffer;
7192+
auto check = [&](const uint32_t (&values)[4], const int32_t (&shifts)[4],
7193+
const uint32_t (&expected)[4]) {
7194+
for (intptr_t i = 0; i < 4; i++) {
7195+
buffer.values[i] = values[i];
7196+
buffer.shifts[i] = shifts[i];
7197+
buffer.result[i] = 0xAAAAAAAA;
7198+
}
7199+
EXECUTE_TEST_CODE_INTPTR_INTPTR(VushlwCode, test->entry(),
7200+
reinterpret_cast<intptr_t>(&buffer));
7201+
for (intptr_t i = 0; i < 4; i++) {
7202+
EXPECT_EQ(expected[i], buffer.result[i]);
7203+
}
7204+
};
7205+
const uint32_t values[4] = {0xFFFFFFF8, 8, 0x80000000, 0x7FFFFFFF};
7206+
// A positive count shifts left.
7207+
check(values, {2, 2, 2, 2}, {0xFFFFFFE0, 32, 0, 0xFFFFFFFC});
7208+
// A negative count shifts right, filling with zeros.
7209+
check(values, {-1, -1, -1, -1}, {0x7FFFFFFC, 4, 0x40000000, 0x3FFFFFFF});
7210+
// A shift of 32 or more in either direction shifts every bit out.
7211+
check(values, {32, 32, 32, 32}, {0, 0, 0, 0});
7212+
check(values, {-32, -32, -32, -32}, {0, 0, 0, 0});
7213+
// Each lane uses its own count.
7214+
check(values, {2, -1, 32, -32}, {0xFFFFFFE0, 4, 0, 0});
7215+
EXPECT_DISASSEMBLY(
7216+
"fldrq v0, [r0]\n"
7217+
"fldrq v1, [r0, #16]\n"
7218+
"vushlw v2, v0, v1\n"
7219+
"fstrq v2, [r0, #32]\n"
7220+
"ret\n");
7221+
}
7222+
71777223
ASSEMBLER_TEST_GENERATE(Vsubw, assembler) {
71787224
__ LoadImmediate(R4, 31);
71797225
__ LoadImmediate(R5, 10);

‎runtime/vm/compiler/assembler/disassembler_arm64.cc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,8 @@ void ARM64Decoder::DecodeSIMDThreeSame(Instr* instr) {
14711471
Format(instr, "vceq'vsz 'vd, 'vn, 'vm");
14721472
} else if ((U == 0) && (opcode == 0x8)) {
14731473
Format(instr, "vsshl'vsz 'vd, 'vn, 'vm");
1474+
} else if ((U == 1) && (opcode == 0x8)) {
1475+
Format(instr, "vushl'vsz 'vd, 'vn, 'vm");
14741476
} else if ((U == 0) && (opcode == 0x10)) {
14751477
Format(instr, "vadd'vsz 'vd, 'vn, 'vm");
14761478
} else if ((U == 1) && (opcode == 0x10)) {

‎runtime/vm/constants_arm64.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ enum SIMDThreeSameOp {
10621062
VRSQRTSS = SIMDThreeSameFixed | B30 | B23 | B15 | B14 | B13 | B12 | B11,
10631063
VSSHLW = SIMDThreeSameFixed | B30 | B23 | B14,
10641064
VSSHLX = SIMDThreeSameFixed | B30 | B23 | B22 | B14,
1065+
VUSHLW = SIMDThreeSameFixed | B30 | B29 | B23 | B14,
10651066
};
10661067

10671068
// C.3.6.17

‎runtime/vm/simulator_arm64.cc‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3351,6 +3351,17 @@ void Simulator::DecodeSIMDThreeSame(Instr* instr) {
33513351
// a copy of the sign bit in every position.
33523352
res = vn_val >> (-shift >= 32 ? 31 : -shift);
33533353
}
3354+
} else if ((U == 1) && (opcode == 0x8)) {
3355+
// Format(instr, "vushl'vsz 'vd, 'vn, 'vm");
3356+
const int8_t shift = static_cast<int8_t>(vm_val & 0xff);
3357+
const uint32_t vn_bits = static_cast<uint32_t>(vn_val);
3358+
// A shift of the element width or more, in either direction, shifts
3359+
// every bit out.
3360+
if (shift >= 0) {
3361+
res = shift >= 32 ? 0 : static_cast<int32_t>(vn_bits << shift);
3362+
} else {
3363+
res = -shift >= 32 ? 0 : static_cast<int32_t>(vn_bits >> -shift);
3364+
}
33543365
} else if ((U == 0) && (opcode == 0x10)) {
33553366
// Format(instr, "vadd'vsz 'vd, 'vn, 'vm");
33563367
res = vn_val + vm_val;

0 commit comments

Comments
 (0)