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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
|
From: Daniel Golle <daniel@makrotopia.org>
Subject: [PATCH] JavaScriptCore: add RISCV64 MacroAssembler primitives required by BBQJIT
Enabling BBQJIT on RISCV64 exposes a set of MacroAssembler primitives that
WasmBBQJIT.cpp / WasmBBQJIT64.cpp / WasmBBQJIT32_64.cpp call but that
MacroAssemblerRISCV64.h does not yet provide. Add them in four groups:
* Scalar BBQJIT primitives, fully implemented for RISCV64:
- floatMin / floatMax / doubleMin / doubleMax via fmin.s/fmax.s and
fmin.d/fmax.d (the F/D extensions in rv64gc).
- addLeftShift64 via slli + add.
- multiplyAddZeroExtend32 via mulw + 32-bit mask + add.
- rotateLeft32 / rotateLeft64 (immediate and variable shift) via
shift + shift + or; rv64gc has no rotate, the Zbb rol* family
is not in the baseline.
- div32 / uDiv32 / div64 / uDiv64 via the RISC-V M extension
(divw / divuw / div / divu); 32-bit results are masked back to
32 bits.
- multiplySub32 / multiplySub64 via mul + sub.
- convertUInt32ToFloat via fcvt.s.wu.
* 8/16-bit and Address->BaseIndex transfer overloads. transfer{8,16}
were not defined for any addressing mode, and transfer{32,64,Vector}
only had Address->Address and BaseIndex->BaseIndex variants. BBQJIT
calls all of these for wasm struct copy / memory init code. Each is
the same pattern as the existing transfer32: load to a scratch
register, store from it.
* SIMD vector noop stubs (~44 methods). The RISC-V V vector extension
is not part of the OpenWrt rv64gc baseline, and there is no SIMD
codegen for RISCV64 in MacroAssemblerRISCV64.h. Options::useWasmSIMD
is forced off on RISCV64, so the BBQJIT SIMD codepaths are
unreachable; matching the existing pattern in this file, these are
templated empty noops via MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD.
vectorExtractLane / vectorReplaceLane cannot use the existing
forwarding-reference noop macro: their first argument is a SIMDInfo
bit-field (SIMDLane / SIMDSignMode) and bit-fields cannot bind to
Args&&. They are defined as separate by-value templated overloads.
The SIMDLane / SIMDSignMode type names are not visible in this
header without pulling in <JavaScriptCore/SIMDInfo.h>, which we
avoid for pure stubs, so the by-value template avoids naming the
types altogether.
* Wasm atomic hard-fault stubs (36 methods: loadLinkAcq{8,16,32,64},
storeCondRel{8,16,32,64}, branchAtomicStrongCAS{8,16,32,64},
atomicStrongCAS{8,16,32,64}, atomicXchg{,Add,Clear,Or,Xor}{8,16,32,64}).
The RISC-V A extension is present in rv64gc, but the corresponding
AMO / LR / SC instruction emitters have not been added to
RISCV64Assembler.h. Wasm threads / shared memory is gated off at
runtime via useSharedArrayBuffer = false (the default), which keeps
wasm atomic opcodes off the JIT codepath, so these stubs are
unreachable. A new
MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD macro variant
is added so an accidentally-reached atomic codepath traps loudly
rather than silently miscompiling.
This is the minimum surface needed to make BBQJIT on RISCV64 link and
run non-SIMD, non-atomic wasm modules. The two stub groups (atomic and
SIMD) are intentionally flagged in their comments so they are easy to
find when implementing the real codegen in follow-up work.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h
@@ -36,6 +36,16 @@
template<typename... Args> void methodName(Args&&...) { }
#define MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD_WITH_RETURN(methodName, returnType) \
template<typename... Args> returnType methodName(Args&&...) { return { }; }
+// Atomic / FP-minmax / SIMD methods needed by BBQJIT for which no native
+// RISC-V code generation exists yet. These are deliberately runtime-fatal
+// rather than silent noops: wasm shared memory and SIMD are gated off on
+// RISCV64 (useSharedArrayBuffer / useWasmSIMD), so the BBQJIT codegen for
+// atomic and SIMD wasm opcodes must never run. If something does reach
+// these, we want to know with a loud crash, not a silent miscompilation.
+#define MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(methodName) \
+ template<typename... Args> void methodName(Args&&...) { RELEASE_ASSERT_NOT_REACHED(); }
+#define MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD_WITH_RETURN(methodName, returnType) \
+ template<typename... Args> returnType methodName(Args&&...) { RELEASE_ASSERT_NOT_REACHED(); return { }; }
namespace JSC {
@@ -837,6 +847,123 @@ public:
MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(rotateRight32);
MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(rotateRight64);
+ // Scalar BBQJIT primitives: fused shift/add and rotate-left, used by the
+ // wasm bytecode-to-machine-code path. RISC-V's baseline rv64gc has no
+ // rotate instruction (Zbb's rolw/rol would do it in one), so synthesize
+ // via shift + shift + or.
+ void addLeftShift64(RegisterID n, RegisterID m, TrustedImm32 amount, RegisterID d)
+ {
+ auto temp = temps<Data>();
+ m_assembler.slliInsn(temp.data(), m, uint32_t(amount.m_value & 63));
+ m_assembler.addInsn(d, n, temp.data());
+ }
+
+ void multiplyAddZeroExtend32(RegisterID mulLeft, RegisterID mulRight, RegisterID summand, RegisterID dest)
+ {
+ auto temp = temps<Data>();
+ m_assembler.mulwInsn(temp.data(), mulLeft, mulRight);
+ m_assembler.maskRegister<32>(temp.data());
+ m_assembler.addInsn(dest, summand, temp.data());
+ }
+
+ void rotateLeft32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+ {
+ int32_t shift = imm.m_value & 31;
+ if (!shift) {
+ if (src != dest)
+ move(src, dest);
+ m_assembler.maskRegister<32>(dest);
+ return;
+ }
+ auto temp = temps<Data, Memory>();
+ m_assembler.slliwInsn(temp.data(), src, uint32_t(shift));
+ m_assembler.srliwInsn(temp.memory(), src, uint32_t(32 - shift));
+ m_assembler.orInsn(dest, temp.data(), temp.memory());
+ m_assembler.maskRegister<32>(dest);
+ }
+
+ void rotateLeft32(RegisterID src, RegisterID shift, RegisterID dest)
+ {
+ auto temp = temps<Data, Memory>();
+ m_assembler.addiInsn(temp.data(), RISCV64Registers::zero, Imm::I<32>());
+ m_assembler.subInsn(temp.data(), temp.data(), shift);
+ m_assembler.sllwInsn(temp.memory(), src, shift);
+ m_assembler.srlwInsn(temp.data(), src, temp.data());
+ m_assembler.orInsn(dest, temp.memory(), temp.data());
+ m_assembler.maskRegister<32>(dest);
+ }
+
+ void rotateLeft64(RegisterID src, TrustedImm32 imm, RegisterID dest)
+ {
+ int32_t shift = imm.m_value & 63;
+ if (!shift) {
+ if (src != dest)
+ move(src, dest);
+ return;
+ }
+ auto temp = temps<Data, Memory>();
+ m_assembler.slliInsn(temp.data(), src, uint32_t(shift));
+ m_assembler.srliInsn(temp.memory(), src, uint32_t(64 - shift));
+ m_assembler.orInsn(dest, temp.data(), temp.memory());
+ }
+
+ void rotateLeft64(RegisterID src, RegisterID shift, RegisterID dest)
+ {
+ auto temp = temps<Data, Memory>();
+ m_assembler.addiInsn(temp.data(), RISCV64Registers::zero, Imm::I<64>());
+ m_assembler.subInsn(temp.data(), temp.data(), shift);
+ m_assembler.sllInsn(temp.memory(), src, shift);
+ m_assembler.srlInsn(temp.data(), src, temp.data());
+ m_assembler.orInsn(dest, temp.memory(), temp.data());
+ }
+
+ // Integer divide / modulo via the RISC-V M extension (in rv64gc).
+ // The 32-bit forms produce a sign-extended result; mask to 32 bits.
+ void div32(RegisterID dividend, RegisterID divisor, RegisterID dest)
+ {
+ m_assembler.divwInsn(dest, dividend, divisor);
+ m_assembler.maskRegister<32>(dest);
+ }
+
+ void uDiv32(RegisterID dividend, RegisterID divisor, RegisterID dest)
+ {
+ m_assembler.divuwInsn(dest, dividend, divisor);
+ m_assembler.maskRegister<32>(dest);
+ }
+
+ void div64(RegisterID dividend, RegisterID divisor, RegisterID dest)
+ {
+ m_assembler.divInsn(dest, dividend, divisor);
+ }
+
+ void uDiv64(RegisterID dividend, RegisterID divisor, RegisterID dest)
+ {
+ m_assembler.divuInsn(dest, dividend, divisor);
+ }
+
+ // dest = minuend - (mulLeft * mulRight). Used by wasm i32/i64 rem
+ // (rem == lhs - (lhs/rhs) * rhs). RISC-V has no fused mul-sub.
+ void multiplySub32(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
+ {
+ auto temp = temps<Data>();
+ m_assembler.mulwInsn(temp.data(), mulLeft, mulRight);
+ m_assembler.subwInsn(dest, minuend, temp.data());
+ m_assembler.maskRegister<32>(dest);
+ }
+
+ void multiplySub64(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
+ {
+ auto temp = temps<Data>();
+ m_assembler.mulInsn(temp.data(), mulLeft, mulRight);
+ m_assembler.subInsn(dest, minuend, temp.data());
+ }
+
+ // uint32 -> single-precision float, fcvt.s.wu (one instruction).
+ void convertUInt32ToFloat(RegisterID src, FPRegisterID dest)
+ {
+ m_assembler.fcvtInsn<RISCV64Assembler::FCVTType::S, RISCV64Assembler::FCVTType::WU>(dest, src);
+ }
+
void load8(Address address, RegisterID dest)
{
auto resolution = resolveAddress(address, lazyTemp<Memory>());
@@ -1425,6 +1552,73 @@ public:
transfer64(src, dest);
}
+ // 8- and 16-bit mem-to-mem transfers, and Address->BaseIndex
+ // variants of the existing widths, needed by BBQJIT (wasm
+ // struct copy / memory init etc.). Implemented in the same shape
+ // as the existing transfer32 / transfer64: load to a scratch
+ // register, store from it.
+ void transfer8(Address src, Address dest)
+ {
+ auto temp = temps<Data>();
+ load8(src, temp.data());
+ store8(temp.data(), dest);
+ }
+
+ void transfer8(BaseIndex src, BaseIndex dest)
+ {
+ auto temp = temps<Data>();
+ load8(src, temp.data());
+ store8(temp.data(), dest);
+ }
+
+ void transfer8(Address src, BaseIndex dest)
+ {
+ auto temp = temps<Data>();
+ load8(src, temp.data());
+ store8(temp.data(), dest);
+ }
+
+ void transfer16(Address src, Address dest)
+ {
+ auto temp = temps<Data>();
+ load16(src, temp.data());
+ store16(temp.data(), dest);
+ }
+
+ void transfer16(BaseIndex src, BaseIndex dest)
+ {
+ auto temp = temps<Data>();
+ load16(src, temp.data());
+ store16(temp.data(), dest);
+ }
+
+ void transfer16(Address src, BaseIndex dest)
+ {
+ auto temp = temps<Data>();
+ load16(src, temp.data());
+ store16(temp.data(), dest);
+ }
+
+ void transfer32(Address src, BaseIndex dest)
+ {
+ auto temp = temps<Data>();
+ load32(src, temp.data());
+ store32(temp.data(), dest);
+ }
+
+ void transfer64(Address src, BaseIndex dest)
+ {
+ auto temp = temps<Data>();
+ load64(src, temp.data());
+ store64(temp.data(), dest);
+ }
+
+ void transferVector(Address src, BaseIndex dest)
+ {
+ loadVector(src, fpTempRegister);
+ storeVector(fpTempRegister, dest);
+ }
+
void storePair32(RegisterID src1, RegisterID src2, RegisterID dest)
{
storePair32(src1, src2, dest, TrustedImm32(0));
@@ -2150,6 +2344,116 @@ public:
MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorMulSat);
MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorDotProduct);
MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSwizzle);
+ // Additional vector noop stubs needed by BBQJIT (kept unreachable via
+ // useWasmSIMD = false on RISCV64; see Options.cpp).
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(compareFloatingPointVectorUnordered);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(moveZeroToVector);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorAbsInt64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorConvertLowSignedInt32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorConvertLowUnsignedInt32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorConvertUnsigned);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorExtaddPairwiseUnsignedInt16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorExtractPair);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorHorizontalAdd);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad8Splat);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSshl);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSshr8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUshl);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUshr8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSwizzle2);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorTruncSatSignedFloat64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorTruncSatUnsignedFloat32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorTruncSatUnsignedFloat64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUnsignedMax);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUnsignedMin);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUnzipEven);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorZipUpper);
+
+ // Wasm atomics: the RISC-V A extension is available (the OpenWrt -march
+ // baseline is rv64gc, i.e. includes A), but the AMO/LR/SC instruction
+ // emitters in RISCV64Assembler.h have not been added yet. Stub the
+ // BBQJIT atomic API with hard-fault unimplemented methods: at runtime
+ // wasm shared memory is gated off via useSharedArrayBuffer = false, so
+ // wasm atomic opcodes are unreachable, and these stubs only ever exist
+ // for compile-time completeness. Filling these in (and adding the
+ // matching RISCV64Assembler.h emitters) is a follow-up that unlocks the
+ // wasm threads proposal on RISCV64.
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(loadLinkAcq8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(loadLinkAcq16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(loadLinkAcq32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(loadLinkAcq64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(storeCondRel8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(storeCondRel16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(storeCondRel32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(storeCondRel64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD_WITH_RETURN(branchAtomicStrongCAS8, Jump);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD_WITH_RETURN(branchAtomicStrongCAS16, Jump);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD_WITH_RETURN(branchAtomicStrongCAS32, Jump);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD_WITH_RETURN(branchAtomicStrongCAS64, Jump);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchg8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchg16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchg32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchg64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgAdd8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgAdd16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgAdd32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgAdd64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgClear8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgClear16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgClear32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgClear64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgOr8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgOr16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgOr32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgOr64);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgXor8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgXor16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgXor32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicXchgXor64);
+ // atomicStrongCAS{N}: the non-branching CAS overloads used by BBQJIT
+ // when the caller only needs success/failure in resultGPR (rather
+ // than a JIT-emitted branch). Same runtime-unreachable rationale as
+ // branchAtomicStrongCAS{N} above.
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicStrongCAS8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicStrongCAS16);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicStrongCAS32);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_UNIMPLEMENTED_METHOD(atomicStrongCAS64);
+ // Additional SIMD vector noop stubs uncovered by enabling BBQJIT.
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSplat);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUshl8);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSshr);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUshr);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorMulLow);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorMulHigh);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorFusedMulAdd);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorFusedNegMulAdd);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad16Splat);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad32Splat);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad64Splat);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad8Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad16Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad32Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorLoad64Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorStore8Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorStore16Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorStore32Lane);
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorStore64Lane);
+ // vectorExtractLane / vectorReplaceLane: by-value templated stubs.
+ // The MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD form uses
+ // Args&& forwarding references; binding a SIMDInfo::lane /
+ // SIMDInfo::signMode bit-field to a non-const reference is
+ // ill-formed, so use by-value template parameters instead.
+ // (The SIMD type names are not visible in this header without
+ // pulling in <JavaScriptCore/SIMDInfo.h>, which we avoid for
+ // pure stubs.) Same unreachability rationale as the other SIMD
+ // stubs: useWasmSIMD = false on RISCV64.
+ template<typename T1, typename T2, typename T3, typename T4>
+ void vectorExtractLane(T1, T2, T3, T4) { }
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ void vectorExtractLane(T1, T2, T3, T4, T5) { }
+ template<typename T1, typename T2, typename T3, typename T4>
+ void vectorReplaceLane(T1, T2, T3, T4) { }
+ MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(move128ToVector);
template<PtrTag resultTag, PtrTag locationTag>
static CodePtr<resultTag> readCallTarget(CodeLocationCall<locationTag> call)
@@ -3520,6 +3824,26 @@ public:
m_assembler.fsgnjxInsn<64>(dest, src, src);
}
+ void floatMin(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+ {
+ m_assembler.fminInsn<32>(dest, op1, op2);
+ }
+
+ void floatMax(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+ {
+ m_assembler.fmaxInsn<32>(dest, op1, op2);
+ }
+
+ void doubleMin(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+ {
+ m_assembler.fminInsn<64>(dest, op1, op2);
+ }
+
+ void doubleMax(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+ {
+ m_assembler.fmaxInsn<64>(dest, op1, op2);
+ }
+
void ceilFloat(FPRegisterID src, FPRegisterID dest)
{
roundFP<32, RISCV64Assembler::FPRoundingMode::RUP>(src, dest);
|