Title: [288372] trunk/Source/_javascript_Core
Revision
288372
Author
commit-qu...@webkit.org
Date
2022-01-21 13:13:52 -0800 (Fri, 21 Jan 2022)

Log Message

[RISCV64] Add MacroAssemblerRISCV64 operations for bitfield, zero-counting, byte-swapping operations
https://bugs.webkit.org/show_bug.cgi?id=235439

Patch by Zan Dobersek <zdober...@igalia.com> on 2022-01-21
Reviewed by Yusuke Suzuki.

Add MacroAssemblerRISCV64 implementations that cover unsigned bitfield,
leading-zero, trailing-zero and byte-swapping operations. All these
operations are not supported in base RISC-V specifications. There are
extensions currently being ratified that will introduce more useful
instructions, but until then more verbose implementations will have
to be used.

For the unsigned bitfield operations, the desired result is achieved
through shifting and masking. Scratch registers are only needed in
case of the mask immediate being too large, but that will be properly
handled by the higher-level JITs. For other operations covered in this
patch  we have to use scratch registers and custom loops to implement
the necessary behavior.

* assembler/MacroAssemblerRISCV64.h:
(JSC::MacroAssemblerRISCV64::extractUnsignedBitfield32):
(JSC::MacroAssemblerRISCV64::extractUnsignedBitfield64):
(JSC::MacroAssemblerRISCV64::insertUnsignedBitfieldInZero32):
(JSC::MacroAssemblerRISCV64::insertUnsignedBitfieldInZero64):
(JSC::MacroAssemblerRISCV64::countLeadingZeros32):
(JSC::MacroAssemblerRISCV64::countLeadingZeros64):
(JSC::MacroAssemblerRISCV64::countTrailingZeros32):
(JSC::MacroAssemblerRISCV64::countTrailingZeros64):
(JSC::MacroAssemblerRISCV64::byteSwap16):
(JSC::MacroAssemblerRISCV64::byteSwap32):
(JSC::MacroAssemblerRISCV64::byteSwap64):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (288371 => 288372)


--- trunk/Source/_javascript_Core/ChangeLog	2022-01-21 21:07:04 UTC (rev 288371)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-01-21 21:13:52 UTC (rev 288372)
@@ -1,3 +1,37 @@
+2022-01-21  Zan Dobersek  <zdober...@igalia.com>
+
+        [RISCV64] Add MacroAssemblerRISCV64 operations for bitfield, zero-counting, byte-swapping operations
+        https://bugs.webkit.org/show_bug.cgi?id=235439
+
+        Reviewed by Yusuke Suzuki.
+
+        Add MacroAssemblerRISCV64 implementations that cover unsigned bitfield,
+        leading-zero, trailing-zero and byte-swapping operations. All these
+        operations are not supported in base RISC-V specifications. There are
+        extensions currently being ratified that will introduce more useful
+        instructions, but until then more verbose implementations will have
+        to be used.
+
+        For the unsigned bitfield operations, the desired result is achieved
+        through shifting and masking. Scratch registers are only needed in
+        case of the mask immediate being too large, but that will be properly
+        handled by the higher-level JITs. For other operations covered in this
+        patch  we have to use scratch registers and custom loops to implement
+        the necessary behavior.
+
+        * assembler/MacroAssemblerRISCV64.h:
+        (JSC::MacroAssemblerRISCV64::extractUnsignedBitfield32):
+        (JSC::MacroAssemblerRISCV64::extractUnsignedBitfield64):
+        (JSC::MacroAssemblerRISCV64::insertUnsignedBitfieldInZero32):
+        (JSC::MacroAssemblerRISCV64::insertUnsignedBitfieldInZero64):
+        (JSC::MacroAssemblerRISCV64::countLeadingZeros32):
+        (JSC::MacroAssemblerRISCV64::countLeadingZeros64):
+        (JSC::MacroAssemblerRISCV64::countTrailingZeros32):
+        (JSC::MacroAssemblerRISCV64::countTrailingZeros64):
+        (JSC::MacroAssemblerRISCV64::byteSwap16):
+        (JSC::MacroAssemblerRISCV64::byteSwap32):
+        (JSC::MacroAssemblerRISCV64::byteSwap64):
+
 2022-01-21  Alex Christensen  <achristen...@webkit.org>
 
         Fix build when using Visual Studio 2022

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerRISCV64.h (288371 => 288372)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerRISCV64.h	2022-01-21 21:07:04 UTC (rev 288371)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerRISCV64.h	2022-01-21 21:13:52 UTC (rev 288372)
@@ -471,20 +471,164 @@
         m_assembler.mulInsn(dest, lhs, rhs);
     }
 
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(extractUnsignedBitfield32);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(extractUnsignedBitfield64);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(insertUnsignedBitfieldInZero32);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(insertUnsignedBitfieldInZero64);
+    void extractUnsignedBitfield32(RegisterID src, TrustedImm32 lsb, TrustedImm32 width, RegisterID dest)
+    {
+        m_assembler.srliInsn(dest, src, std::clamp<int32_t>(lsb.m_value, 0, 31));
+        if (!Imm::isValid<Imm::IType>(width.m_value)) {
+            auto temp = temps<Data>();
+            loadImmediate(width, temp.data());
+            m_assembler.andInsn(dest, dest, temp.data());
+        } else
+            m_assembler.andiInsn(dest, dest, Imm::I(width.m_value));
+    }
 
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(countLeadingZeros32);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(countLeadingZeros64);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(countTrailingZeros32);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(countTrailingZeros64);
+    void extractUnsignedBitfield64(RegisterID src, TrustedImm32 lsb, TrustedImm32 width, RegisterID dest)
+    {
+        m_assembler.srliInsn(dest, src, std::clamp<int32_t>(lsb.m_value, 0, 63));
+        if (!Imm::isValid<Imm::IType>(width.m_value)) {
+            auto temp = temps<Data>();
+            loadImmediate(width, temp.data());
+            m_assembler.andInsn(dest, dest, temp.data());
+        } else
+            m_assembler.andiInsn(dest, dest, Imm::I(width.m_value));
+    }
 
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(byteSwap16);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(byteSwap32);
-    MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(byteSwap64);
+    void insertUnsignedBitfieldInZero32(RegisterID src, TrustedImm32 lsb, TrustedImm32 width, RegisterID dest)
+    {
+        if (!Imm::isValid<Imm::IType>(width.m_value)) {
+            auto temp = temps<Data>();
+            loadImmediate(width, temp.data());
+            m_assembler.andInsn(dest, src, temp.data());
+        } else
+            m_assembler.andiInsn(dest, src, Imm::I(width.m_value));
+        m_assembler.slliInsn(dest, dest, std::clamp<int32_t>(lsb.m_value, 0, 63));
+    }
 
+    void insertUnsignedBitfieldInZero64(RegisterID src, TrustedImm32 lsb, TrustedImm32 width, RegisterID dest)
+    {
+        if (!Imm::isValid<Imm::IType>(width.m_value)) {
+            auto temp = temps<Data>();
+            loadImmediate(width, temp.data());
+            m_assembler.andInsn(dest, src, temp.data());
+        } else
+            m_assembler.andiInsn(dest, src, Imm::I(width.m_value));
+        m_assembler.slliInsn(dest, dest, std::clamp<int32_t>(lsb.m_value, 0, 63));
+    }
+
+    void countLeadingZeros32(RegisterID src, RegisterID dest)
+    {
+        auto temp = temps<Data>();
+        m_assembler.zeroExtend<32>(temp.data(), src);
+        m_assembler.addiInsn(dest, RISCV64Registers::zero, Imm::I<32>());
+
+        JumpList zero(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+
+        Label loop = label();
+        m_assembler.srliInsn<1>(temp.data(), temp.data());
+        m_assembler.addiInsn(dest, dest, Imm::I<-1>());
+        zero.append(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+        jump().linkTo(loop, this);
+
+        zero.link(this);
+    }
+
+    void countLeadingZeros64(RegisterID src, RegisterID dest)
+    {
+        auto temp = temps<Data>();
+        m_assembler.addiInsn(temp.data(), src, Imm::I<0>());
+        m_assembler.addiInsn(dest, RISCV64Registers::zero, Imm::I<64>());
+
+        JumpList zero(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+
+        Label loop = label();
+        m_assembler.srliInsn<1>(temp.data(), temp.data());
+        m_assembler.addiInsn(dest, dest, Imm::I<-1>());
+        zero.append(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+        jump().linkTo(loop, this);
+
+        zero.link(this);
+    }
+
+    void countTrailingZeros32(RegisterID src, RegisterID dest)
+    {
+        auto temp = temps<Data>();
+        m_assembler.addiInsn(dest, RISCV64Registers::zero, Imm::I<32>());
+        m_assembler.zeroExtend<32>(temp.data(), src);
+
+        JumpList zero(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+
+        Label loop = label();
+        m_assembler.slliInsn<1>(temp.data(), temp.data());
+        m_assembler.addiInsn(dest, dest, Imm::I<-1>());
+        zero.append(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+        jump().linkTo(loop, this);
+
+        zero.link(this);
+    }
+
+    void countTrailingZeros64(RegisterID src, RegisterID dest)
+    {
+        auto temp = temps<Data>();
+        m_assembler.addiInsn(dest, RISCV64Registers::zero, Imm::I<64>());
+        m_assembler.addiInsn(temp.data(), src, Imm::I<0>());
+
+        JumpList zero(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+
+        Label loop = label();
+        m_assembler.slliInsn<1>(temp.data(), temp.data());
+        m_assembler.addiInsn(dest, dest, Imm::I<-1>());
+        zero.append(makeBranch(Equal, temp.data(), RISCV64Registers::zero));
+        jump().linkTo(loop, this);
+
+        zero.link(this);
+    }
+
+    void byteSwap16(RegisterID reg)
+    {
+        auto temp = temps<Data>();
+        m_assembler.andiInsn(temp.data(), reg, Imm::I<0xff>());
+        m_assembler.slliInsn<8>(temp.data(), temp.data());
+        m_assembler.slliInsn<48>(reg, reg);
+        m_assembler.srliInsn<56>(reg, reg);
+        m_assembler.orInsn(reg, reg, temp.data());
+    }
+
+    void byteSwap32(RegisterID reg)
+    {
+        auto temp = temps<Data, Memory>();
+        m_assembler.andiInsn(temp.data(), reg, Imm::I<0xff>());
+        m_assembler.slliInsn<8>(temp.data(), temp.data());
+        m_assembler.srliInsn<8>(reg, reg);
+
+        for (unsigned i = 0; i < 2; ++i) {
+            m_assembler.andiInsn(temp.memory(), reg, Imm::I<0xff>());
+            m_assembler.orInsn(temp.data(), temp.data(), temp.memory());
+            m_assembler.slliInsn<8>(temp.data(), temp.data());
+            m_assembler.srliInsn<8>(reg, reg);
+        }
+
+        m_assembler.andiInsn(temp.memory(), reg, Imm::I<0xff>());
+        m_assembler.orInsn(reg, temp.data(), temp.memory());
+    }
+
+    void byteSwap64(RegisterID reg)
+    {
+        auto temp = temps<Data, Memory>();
+        m_assembler.andiInsn(temp.data(), reg, Imm::I<0xff>());
+        m_assembler.slliInsn<8>(temp.data(), temp.data());
+        m_assembler.srliInsn<8>(reg, reg);
+
+        for (unsigned i = 0; i < 6; ++i) {
+            m_assembler.andiInsn(temp.memory(), reg, Imm::I<0xff>());
+            m_assembler.orInsn(temp.data(), temp.data(), temp.memory());
+            m_assembler.slliInsn<8>(temp.data(), temp.data());
+            m_assembler.srliInsn<8>(reg, reg);
+        }
+
+        m_assembler.andiInsn(temp.memory(), reg, Imm::I<0xff>());
+        m_assembler.orInsn(reg, temp.data(), temp.memory());
+    }
+
     void lshift32(RegisterID shiftAmount, RegisterID dest)
     {
         lshift32(dest, shiftAmount, dest);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to