summaryrefslogtreecommitdiffstats
path: root/libs/wpewebkit/patches/125-JavaScriptCore-RISCV64-MacroAssembler-add-missing-methods.patch
blob: e5ed26f7caf554ab367762846889e51f0e755bc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
From e0fa9d1a90afad8bd6fae08039864b1bd3e7eafa Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 23 Sep 2026 14:33:27 +0100
Subject: [PATCH] JavaScriptCore: add missing RISCV64 MacroAssembler methods

The RISCV64 MacroAssembler is missing five primitives that JSC's
optimising tiers (DFG, FTL, the inline-cache compiler) now call. Each
is straightforward, the RISC-V base ISA has the instructions required,
and the implementations mirror the patterns already used in this file:

 * add8(TrustedImm32, Address) - lbu / addi / sb (with the same
   immediate-out-of-range fallback used by add32(TrustedImm32, Address)
   right below it); needed by InlineCacheCompiler to bump an 8-bit
   countdown counter.

 * or32(RegisterID, Address) - lw / or / sw, the missing direct-Address
   counterpart of or32(RegisterID, AbsoluteAddress); used by FTL OSR
   exit.

 * convertUInt32ToDouble(RegisterID, FPRegisterID) and the TrustedImm32
   overload - fcvt.d.wu via the FCVTType::WU template; called from DFG
   and the inline-cache compiler.

 * add64/sub64(FPRegisterID, FPRegisterID, FPRegisterID) - 64-bit
   integer arithmetic performed on values that live in FP registers,
   used by the JSValue double boxing / NaN purification paths (see
   DFGSpeculativeJIT::boxDoubleAsDouble and purifyNaN). RISC-V has no
   integer ALU on FPRs so the values are moved through GPR scratch
   registers via fmv.x.d / add or sub / fmv.d.x.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 .../assembler/MacroAssemblerRISCV64.h         | 62 +++++++++++++++++++
 1 file changed, 62 insertions(+)

--- a/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h
@@ -199,6 +199,25 @@ public:
         m_assembler.maskRegister<32>(dest);
     }
 
+    void add8(TrustedImm32 imm, Address address)
+    {
+        auto temp = temps<Data, Memory>();
+        auto resolution = resolveAddress(address, temp.memory());
+        if (Imm::isValid<Imm::IType>(imm.m_value)) {
+            m_assembler.lbuInsn(temp.data(), resolution.base, Imm::I(resolution.offset));
+            m_assembler.addiInsn(temp.data(), temp.data(), Imm::I(imm.m_value));
+            m_assembler.sbInsn(resolution.base, temp.data(), Imm::S(resolution.offset));
+            return;
+        }
+
+        m_assembler.lbuInsn(temp.memory(), resolution.base, Imm::I(resolution.offset));
+        loadImmediate(imm, temp.data());
+        m_assembler.addInsn(temp.data(), temp.memory(), temp.data());
+
+        resolution = resolveAddress(address, temp.memory());
+        m_assembler.sbInsn(resolution.base, temp.data(), Imm::S(resolution.offset));
+    }
+
     void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
         auto temp = temps<Data, Memory>();
@@ -1701,6 +1720,15 @@ public:
         m_assembler.swInsn(temp.memory(), temp.data(), Imm::S<0>());
     }
 
+    void or32(RegisterID src, Address address)
+    {
+        auto temp = temps<Data, Memory>();
+        auto resolution = resolveAddress(address, temp.memory());
+        m_assembler.lwInsn(temp.data(), resolution.base, Imm::I(resolution.offset));
+        m_assembler.orInsn(temp.data(), src, temp.data());
+        m_assembler.swInsn(resolution.base, temp.data(), Imm::S(resolution.offset));
+    }
+
     void or32(TrustedImm32 imm, AbsoluteAddress address)
     {
         auto temp = temps<Data, Memory>();
@@ -2007,6 +2035,28 @@ public:
         m_assembler.fmvInsn<RISCV64Assembler::FMVType::W, RISCV64Assembler::FMVType::X>(dest, src);
     }
 
+    // 64-bit integer arithmetic on values held in FP registers. Used by the
+    // JSValue double boxing / NaN purification paths, where the bit pattern of
+    // a double is offset by JSValue::DoubleEncodeOffset without leaving the FP
+    // register file. RISC-V has no integer ALU on FPRs, so move through GPRs.
+    void add64(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        auto temp = temps<Data, Memory>();
+        m_assembler.fmvInsn<RISCV64Assembler::FMVType::X, RISCV64Assembler::FMVType::D>(temp.data(), op1);
+        m_assembler.fmvInsn<RISCV64Assembler::FMVType::X, RISCV64Assembler::FMVType::D>(temp.memory(), op2);
+        m_assembler.addInsn(temp.data(), temp.data(), temp.memory());
+        m_assembler.fmvInsn<RISCV64Assembler::FMVType::D, RISCV64Assembler::FMVType::X>(dest, temp.data());
+    }
+
+    void sub64(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        auto temp = temps<Data, Memory>();
+        m_assembler.fmvInsn<RISCV64Assembler::FMVType::X, RISCV64Assembler::FMVType::D>(temp.data(), op1);
+        m_assembler.fmvInsn<RISCV64Assembler::FMVType::X, RISCV64Assembler::FMVType::D>(temp.memory(), op2);
+        m_assembler.subInsn(temp.data(), temp.data(), temp.memory());
+        m_assembler.fmvInsn<RISCV64Assembler::FMVType::D, RISCV64Assembler::FMVType::X>(dest, temp.data());
+    }
+
     void moveDouble(FPRegisterID src, FPRegisterID dest)
     {
         if (src != dest)
@@ -3609,6 +3659,18 @@ public:
         convertInt32ToDouble(temp.data(), dest);
     }
 
+    void convertUInt32ToDouble(RegisterID src, FPRegisterID dest)
+    {
+        m_assembler.fcvtInsn<RISCV64Assembler::FCVTType::D, RISCV64Assembler::FCVTType::WU>(dest, src);
+    }
+
+    void convertUInt32ToDouble(TrustedImm32 imm, FPRegisterID dest)
+    {
+        auto temp = temps<Data>();
+        loadImmediate(imm, temp.data());
+        convertUInt32ToDouble(temp.data(), dest);
+    }
+
     void convertInt64ToFloat(RegisterID src, FPRegisterID dest)
     {
         m_assembler.fcvtInsn<RISCV64Assembler::FCVTType::S, RISCV64Assembler::FCVTType::L>(dest, src);