1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <math.h>
29 
30 #include <iostream>
31 
32 #include "src/base/utils/random-number-generator.h"
33 #include "src/codegen/assembler-inl.h"
34 #include "src/codegen/macro-assembler.h"
35 #include "src/diagnostics/disassembler.h"
36 #include "src/execution/simulator.h"
37 #include "src/heap/factory.h"
38 #include "src/init/v8.h"
39 #include "src/utils/utils.h"
40 #include "test/cctest/cctest.h"
41 #include "test/cctest/compiler/value-helper.h"
42 #include "test/cctest/test-helper-riscv64.h"
43 
44 namespace v8 {
45 namespace internal {
46 
47 // Define these function prototypes to match JSEntryFunction in execution.cc
48 using F1 = void*(int x, int p1, int p2, int p3, int p4);
49 using F2 = void*(int x, int y, int p2, int p3, int p4);
50 using F3 = void*(void* p, int p1, int p2, int p3, int p4);
51 using F4 = void*(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4);
52 using F5 = void*(void* p0, void* p1, int p2, int p3, int p4);
53 
54 #define MIN_VAL_IMM12 -(1 << 11)
55 #define LARGE_INT_EXCEED_32_BIT 0x01C9'1075'0321'FB01LL
56 #define LARGE_INT_UNDER_32_BIT 0x1234'5678
57 #define LARGE_UINT_EXCEED_32_BIT 0xFDCB'1234'A034'5691ULL
58 
59 #define __ assm.
60 
61 #define UTEST_R2_FORM_WITH_RES(instr_name, type, rs1_val, rs2_val,     \
62                                expected_res)                           \
63   TEST(RISCV_UTEST_##instr_name) {                                     \
64     CcTest::InitializeVM();                                            \
65     auto fn = [](MacroAssembler& assm) { __ instr_name(a0, a0, a1); }; \
66     auto res = GenAndRunTest<type, type>(rs1_val, rs2_val, fn);        \
67     CHECK_EQ(expected_res, res);                                       \
68   }
69 
70 #define UTEST_R1_FORM_WITH_RES(instr_name, in_type, out_type, rs1_val, \
71                                expected_res)                           \
72   TEST(RISCV_UTEST_##instr_name) {                                     \
73     CcTest::InitializeVM();                                            \
74     auto fn = [](MacroAssembler& assm) { __ instr_name(a0, a0); };     \
75     auto res = GenAndRunTest<out_type, in_type>(rs1_val, fn);          \
76     CHECK_EQ(expected_res, res);                                       \
77   }
78 
79 #define UTEST_R1_FORM_WITH_RES_C(instr_name, in_type, out_type, rs1_val, \
80                                  expected_res)                           \
81   TEST(RISCV_UTEST_##instr_name) {                                       \
82     i::FLAG_riscv_c_extension = true;                                    \
83     CcTest::InitializeVM();                                              \
84     auto fn = [](MacroAssembler& assm) { __ instr_name(a0, a0); };       \
85     auto res = GenAndRunTest<out_type, in_type>(rs1_val, fn);            \
86     CHECK_EQ(expected_res, res);                                         \
87   }
88 
89 #define UTEST_I_FORM_WITH_RES(instr_name, type, rs1_val, imm12, expected_res) \
90   TEST(RISCV_UTEST_##instr_name) {                                            \
91     CcTest::InitializeVM();                                                   \
92     CHECK_EQ(is_intn(imm12, 12), true);                                       \
93     auto fn = [](MacroAssembler& assm) { __ instr_name(a0, a0, imm12); };     \
94     auto res = GenAndRunTest<type, type>(rs1_val, fn);                        \
95     CHECK_EQ(expected_res, res);                                              \
96   }
97 
98 #define UTEST_AMO_WITH_RES(instr_name, aq, rl, inout_type, rs1_val, rs2_val,   \
99                            expected_res)                                       \
100   TEST(RISCV_UTEST_##instr_name) {                                             \
101     CcTest::InitializeVM();                                                    \
102     auto fn = [](MacroAssembler& assm) { __ instr_name(aq, rl, a1, a0, a2); }; \
103     auto res =                                                                 \
104         GenAndRunTestForAMO<inout_type, inout_type>(rs1_val, rs2_val, fn);     \
105     CHECK_EQ(expected_res, res);                                               \
106   }
107 
108 #define UTEST_LOAD_STORE(ldname, stname, value_type, value) \
109   TEST(RISCV_UTEST_##stname##ldname) {                      \
110     CcTest::InitializeVM();                                 \
111     auto fn = [](MacroAssembler& assm) {                    \
112       __ stname(a1, a0, 0);                                 \
113       __ ldname(a0, a0, 0);                                 \
114     };                                                      \
115     GenAndRunTestForLoadStore<value_type>(value, fn);       \
116   }
117 
118 // Since f.Call() is implemented as vararg calls and RISCV calling convention
119 // passes all vararg arguments and returns (including floats) in GPRs, we have
120 // to move from GPR to FPR and back in all floating point tests
121 #define UTEST_LOAD_STORE_F(ldname, stname, value_type, store_value) \
122   TEST(RISCV_UTEST_##stname##ldname) {                              \
123     DCHECK(std::is_floating_point<value_type>::value);              \
124                                                                     \
125     CcTest::InitializeVM();                                         \
126     auto fn = [](MacroAssembler& assm) {                            \
127       __ stname(fa0, a0, 0);                                        \
128       __ ldname(fa0, a0, 0);                                        \
129     };                                                              \
130     GenAndRunTestForLoadStore<value_type>(store_value, fn);         \
131   }
132 
133 #define UTEST_LR_SC(ldname, stname, aq, rl, value_type, value) \
134   TEST(RISCV_UTEST_##stname##ldname) {                         \
135     CcTest::InitializeVM();                                    \
136     auto fn = [](MacroAssembler& assm) {                       \
137       __ ldname(aq, rl, a1, a0);                               \
138       __ stname(aq, rl, a0, a0, a1);                           \
139     };                                                         \
140     GenAndRunTestForLRSC<value_type>(value, fn);               \
141   }
142 
143 #define UTEST_R1_FORM_WITH_RES_F(instr_name, type, rs1_fval, expected_fres) \
144   TEST(RISCV_UTEST_##instr_name) {                                          \
145     DCHECK(std::is_floating_point<type>::value);                            \
146     CcTest::InitializeVM();                                                 \
147     auto fn = [](MacroAssembler& assm) { __ instr_name(fa0, fa0); };        \
148     auto res = GenAndRunTest<type, type>(rs1_fval, fn);                     \
149     CHECK_EQ(expected_fres, res);                                           \
150   }
151 
152 #define UTEST_R2_FORM_WITH_RES_F(instr_name, type, rs1_fval, rs2_fval,    \
153                                  expected_fres)                           \
154   TEST(RISCV_UTEST_##instr_name) {                                        \
155     DCHECK(std::is_floating_point<type>::value);                          \
156     CcTest::InitializeVM();                                               \
157     auto fn = [](MacroAssembler& assm) { __ instr_name(fa0, fa0, fa1); }; \
158     auto res = GenAndRunTest<type, type>(rs1_fval, rs2_fval, fn);         \
159     CHECK_EQ(expected_fres, res);                                         \
160   }
161 
162 #define UTEST_R3_FORM_WITH_RES_F(instr_name, type, rs1_fval, rs2_fval,         \
163                                  rs3_fval, expected_fres)                      \
164   TEST(RISCV_UTEST_##instr_name) {                                             \
165     DCHECK(std::is_floating_point<type>::value);                               \
166     CcTest::InitializeVM();                                                    \
167     auto fn = [](MacroAssembler& assm) { __ instr_name(fa0, fa0, fa1, fa2); }; \
168     auto res = GenAndRunTest<type, type>(rs1_fval, rs2_fval, rs3_fval, fn);    \
169     CHECK_EQ(expected_fres, res);                                              \
170   }
171 
172 #define UTEST_COMPARE_WITH_RES_F(instr_name, input_type, rs1_fval, rs2_fval, \
173                                  expected_res)                               \
174   TEST(RISCV_UTEST_##instr_name) {                                           \
175     CcTest::InitializeVM();                                                  \
176     auto fn = [](MacroAssembler& assm) { __ instr_name(a0, fa0, fa1); };     \
177     auto res = GenAndRunTest<int32_t, input_type>(rs1_fval, rs2_fval, fn);   \
178     CHECK_EQ(expected_res, res);                                             \
179   }
180 
181 #define UTEST_CONV_F_FROM_I(instr_name, input_type, output_type, rs1_val, \
182                             expected_fres)                                \
183   TEST(RISCV_UTEST_##instr_name) {                                        \
184     DCHECK(std::is_integral<input_type>::value&&                          \
185                std::is_floating_point<output_type>::value);               \
186                                                                           \
187     CcTest::InitializeVM();                                               \
188     auto fn = [](MacroAssembler& assm) { __ instr_name(fa0, a0); };       \
189     auto res = GenAndRunTest<output_type, input_type>(rs1_val, fn);       \
190     CHECK_EQ(expected_fres, res);                                         \
191   }
192 
193 #define UTEST_CONV_I_FROM_F(instr_name, input_type, output_type,     \
194                             rounding_mode, rs1_fval, expected_res)   \
195   TEST(RISCV_UTEST_##instr_name) {                                   \
196     DCHECK(std::is_floating_point<input_type>::value&&               \
197                std::is_integral<output_type>::value);                \
198                                                                      \
199     CcTest::InitializeVM();                                          \
200     auto fn = [](MacroAssembler& assm) {                             \
201       __ instr_name(a0, fa0, rounding_mode);                         \
202     };                                                               \
203     auto res = GenAndRunTest<output_type, input_type>(rs1_fval, fn); \
204     CHECK_EQ(expected_res, res);                                     \
205   }                                                                  \
206                                                                      \
207   TEST(RISCV_UTEST_dyn_##instr_name) {                               \
208     DCHECK(std::is_floating_point<input_type>::value&&               \
209                std::is_integral<output_type>::value);                \
210                                                                      \
211     CcTest::InitializeVM();                                          \
212     auto fn = [](MacroAssembler& assm) {                             \
213       __ csrwi(csr_frm, rounding_mode);                              \
214       __ instr_name(a0, fa0, DYN);                                   \
215     };                                                               \
216     auto res = GenAndRunTest<output_type, input_type>(rs1_fval, fn); \
217     CHECK_EQ(expected_res, res);                                     \
218   }
219 
220 #define UTEST_CONV_F_FROM_F(instr_name, input_type, output_type, rs1_val, \
221                             expected_fres)                                \
222   TEST(RISCV_UTEST_##instr_name) {                                        \
223     CcTest::InitializeVM();                                               \
224     auto fn = [](MacroAssembler& assm) { __ instr_name(fa0, fa0); };      \
225     auto res = GenAndRunTest<output_type, input_type>(rs1_val, fn);       \
226     CHECK_EQ(expected_fres, res);                                         \
227   }
228 
229 #define UTEST_CSRI(csr_reg, csr_write_val, csr_set_clear_val)               \
230   TEST(RISCV_UTEST_CSRI_##csr_reg) {                                        \
231     CHECK_EQ(is_uint5(csr_write_val) && is_uint5(csr_set_clear_val), true); \
232                                                                             \
233     CcTest::InitializeVM();                                                 \
234     int64_t expected_res = 111;                                             \
235     Label exit, error;                                                      \
236     auto fn = [&exit, &error, expected_res](MacroAssembler& assm) {         \
237       /* test csr-write and csr-read */                                     \
238       __ csrwi(csr_reg, csr_write_val);                                     \
239       __ csrr(a0, csr_reg);                                                 \
240       __ RV_li(a1, csr_write_val);                                          \
241       __ bne(a0, a1, &error);                                               \
242       /* test csr_set */                                                    \
243       __ csrsi(csr_reg, csr_set_clear_val);                                 \
244       __ csrr(a0, csr_reg);                                                 \
245       __ RV_li(a1, (csr_write_val) | (csr_set_clear_val));                  \
246       __ bne(a0, a1, &error);                                               \
247       /* test csr_clear */                                                  \
248       __ csrci(csr_reg, csr_set_clear_val);                                 \
249       __ csrr(a0, csr_reg);                                                 \
250       __ RV_li(a1, (csr_write_val) & (~(csr_set_clear_val)));               \
251       __ bne(a0, a1, &error);                                               \
252       /* everyhing runs correctly, return 111 */                            \
253       __ RV_li(a0, expected_res);                                           \
254       __ j(&exit);                                                          \
255                                                                             \
256       __ bind(&error);                                                      \
257       /* got an error, return 666 */                                        \
258       __ RV_li(a0, 666);                                                    \
259                                                                             \
260       __ bind(&exit);                                                       \
261     };                                                                      \
262     auto res = GenAndRunTest(fn);                                           \
263     CHECK_EQ(expected_res, res);                                            \
264   }
265 
266 #define UTEST_CSR(csr_reg, csr_write_val, csr_set_clear_val)        \
267   TEST(RISCV_UTEST_CSR_##csr_reg) {                                 \
268     Label exit, error;                                              \
269     int64_t expected_res = 111;                                     \
270     auto fn = [&exit, &error, expected_res](MacroAssembler& assm) { \
271       /* test csr-write and csr-read */                             \
272       __ RV_li(t0, csr_write_val);                                  \
273       __ csrw(csr_reg, t0);                                         \
274       __ csrr(a0, csr_reg);                                         \
275       __ RV_li(a1, csr_write_val);                                  \
276       __ bne(a0, a1, &error);                                       \
277       /* test csr_set */                                            \
278       __ RV_li(t0, csr_set_clear_val);                              \
279       __ csrs(csr_reg, t0);                                         \
280       __ csrr(a0, csr_reg);                                         \
281       __ RV_li(a1, (csr_write_val) | (csr_set_clear_val));          \
282       __ bne(a0, a1, &error);                                       \
283       /* test csr_clear */                                          \
284       __ RV_li(t0, csr_set_clear_val);                              \
285       __ csrc(csr_reg, t0);                                         \
286       __ csrr(a0, csr_reg);                                         \
287       __ RV_li(a1, (csr_write_val) & (~(csr_set_clear_val)));       \
288       __ bne(a0, a1, &error);                                       \
289       /* everyhing runs correctly, return 111 */                    \
290       __ RV_li(a0, expected_res);                                   \
291       __ j(&exit);                                                  \
292                                                                     \
293       __ bind(&error);                                              \
294       /* got an error, return 666 */                                \
295       __ RV_li(a0, 666);                                            \
296                                                                     \
297       __ bind(&exit);                                               \
298     };                                                              \
299                                                                     \
300     auto res = GenAndRunTest(fn);                                   \
301     CHECK_EQ(expected_res, res);                                    \
302   }
303 
304 #define UTEST_R2_FORM_WITH_OP(instr_name, type, rs1_val, rs2_val, tested_op) \
305   UTEST_R2_FORM_WITH_RES(instr_name, type, rs1_val, rs2_val,                 \
306                          ((rs1_val)tested_op(rs2_val)))
307 
308 #define UTEST_I_FORM_WITH_OP(instr_name, type, rs1_val, imm12, tested_op) \
309   UTEST_I_FORM_WITH_RES(instr_name, type, rs1_val, imm12,                 \
310                         ((rs1_val)tested_op(imm12)))
311 
312 #define UTEST_R2_FORM_WITH_OP_F(instr_name, type, rs1_fval, rs2_fval, \
313                                 tested_op)                            \
314   UTEST_R2_FORM_WITH_RES_F(instr_name, type, rs1_fval, rs2_fval,      \
315                            ((rs1_fval)tested_op(rs2_fval)))
316 
317 #define UTEST_COMPARE_WITH_OP_F(instr_name, input_type, rs1_fval, rs2_fval, \
318                                 tested_op)                                  \
319   UTEST_COMPARE_WITH_RES_F(instr_name, input_type, rs1_fval, rs2_fval,      \
320                            ((rs1_fval)tested_op(rs2_fval)))
321 
322 // -- test load-store --
323 UTEST_LOAD_STORE(ld, sd, int64_t, 0xFBB10A9C12345678)
324 // due to sign-extension of lw
325 // instruction, value-to-stored must have
326 // its 32th least significant bit be 0
327 UTEST_LOAD_STORE(lw, sw, int32_t, 0x456AF894)
328 // set the 32th least significant bit of
329 // value-to-store to 1 to test
330 // zero-extension by lwu
331 UTEST_LOAD_STORE(lwu, sw, uint32_t, 0x856AF894)
332 // due to sign-extension of lh
333 // instruction, value-to-stored must have
334 // its 16th least significant bit be 0
335 UTEST_LOAD_STORE(lh, sh, int32_t, 0x7894)
336 // set the 16th least significant bit of
337 // value-to-store to 1 to test
338 // zero-extension by lhu
339 UTEST_LOAD_STORE(lhu, sh, uint32_t, 0xF894)
340 // due to sign-extension of lb
341 // instruction, value-to-stored must have
342 // its 8th least significant bit be 0
343 UTEST_LOAD_STORE(lb, sb, int32_t, 0x54)
344 // set the 8th least significant bit of
345 // value-to-store to 1 to test
346 // zero-extension by lbu
347 UTEST_LOAD_STORE(lbu, sb, uint32_t, 0x94)
348 
349 // -- arithmetic w/ immediate --
350 UTEST_I_FORM_WITH_OP(addi, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, +)
351 UTEST_I_FORM_WITH_OP(slti, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, <)
352 UTEST_I_FORM_WITH_OP(sltiu, uint64_t, LARGE_UINT_EXCEED_32_BIT, 0x4FB, <)
353 UTEST_I_FORM_WITH_OP(xori, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, ^)
354 UTEST_I_FORM_WITH_OP(ori, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, |)
355 UTEST_I_FORM_WITH_OP(andi, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, &)
356 UTEST_I_FORM_WITH_OP(slli, int64_t, 0x1234'5678ULL, 33, <<)
357 UTEST_I_FORM_WITH_OP(srli, int64_t, 0x8234'5678'0000'0000ULL, 33, >>)
358 UTEST_I_FORM_WITH_OP(srai, int64_t, -0x1234'5678'0000'0000LL, 33, >>)
359 
360 // -- arithmetic --
361 UTEST_R2_FORM_WITH_OP(add, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, +)
362 UTEST_R2_FORM_WITH_OP(sub, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, -)
363 UTEST_R2_FORM_WITH_OP(slt, int64_t, MIN_VAL_IMM12, LARGE_INT_EXCEED_32_BIT, <)
364 UTEST_R2_FORM_WITH_OP(sltu, uint64_t, 0x4FB, LARGE_UINT_EXCEED_32_BIT, <)
365 UTEST_R2_FORM_WITH_OP(xor_, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, ^)
366 UTEST_R2_FORM_WITH_OP(or_, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, |)
367 UTEST_R2_FORM_WITH_OP(and_, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, &)
368 UTEST_R2_FORM_WITH_OP(sll, int64_t, 0x12345678ULL, 33, <<)
369 UTEST_R2_FORM_WITH_OP(srl, int64_t, 0x8234567800000000ULL, 33, >>)
370 UTEST_R2_FORM_WITH_OP(sra, int64_t, -0x1234'5678'0000'0000LL, 33, >>)
371 
372 // -- Memory fences --
373 // void fence(uint8_t pred, uint8_t succ);
374 // void fence_tso();
375 
376 // -- Environment call / break --
377 // void ecall();
378 // void ebreak();
379 // void unimp();
380 
381 // -- CSR --
UTEST_CSRI(csr_frm,DYN,RUP)382 UTEST_CSRI(csr_frm, DYN, RUP)
383 UTEST_CSRI(csr_fflags, kInexact | kInvalidOperation, kInvalidOperation)
384 UTEST_CSRI(csr_fcsr, kDivideByZero | kOverflow, kUnderflow)
385 UTEST_CSR(csr_frm, DYN, RUP)
386 UTEST_CSR(csr_fflags, kInexact | kInvalidOperation, kInvalidOperation)
387 UTEST_CSR(csr_fcsr, kDivideByZero | kOverflow | (RDN << kFcsrFrmShift),
388           kUnderflow | (RNE << kFcsrFrmShift))
389 
390 // -- RV64I --
391 UTEST_I_FORM_WITH_OP(addiw, int32_t, LARGE_INT_UNDER_32_BIT, MIN_VAL_IMM12, +)
392 UTEST_I_FORM_WITH_OP(slliw, int32_t, 0x12345678U, 12, <<)
393 UTEST_I_FORM_WITH_OP(srliw, int32_t, 0x82345678U, 12, >>)
394 UTEST_I_FORM_WITH_OP(sraiw, int32_t, -123, 12, >>)
395 
396 UTEST_R2_FORM_WITH_OP(addw, int32_t, LARGE_INT_UNDER_32_BIT, MIN_VAL_IMM12, +)
397 UTEST_R2_FORM_WITH_OP(subw, int32_t, LARGE_INT_UNDER_32_BIT, MIN_VAL_IMM12, -)
398 UTEST_R2_FORM_WITH_OP(sllw, int32_t, 0x12345678U, 12, <<)
399 UTEST_R2_FORM_WITH_OP(srlw, int32_t, 0x82345678U, 12, >>)
400 UTEST_R2_FORM_WITH_OP(sraw, int32_t, -123, 12, >>)
401 
402 // -- RV32M Standard Extension --
403 UTEST_R2_FORM_WITH_OP(mul, int64_t, 0x0F945001L, MIN_VAL_IMM12, *)
404 UTEST_R2_FORM_WITH_RES(mulh, int64_t, 0x1234567800000000LL,
405                        -0x1234'5617'0000'0000LL, 0x12345678LL * -0x1234'5617LL)
406 UTEST_R2_FORM_WITH_RES(mulhu, int64_t, 0x1234'5678'0000'0000ULL,
407                        0xF896'7021'0000'0000ULL,
408                        0x1234'5678ULL * 0xF896'7021ULL)
409 UTEST_R2_FORM_WITH_RES(mulhsu, int64_t, -0x1234'56780000'0000LL,
410                        0xF234'5678'0000'0000ULL,
411                        static_cast<int64_t>(-0x1234'5678LL * 0xF234'5678ULL))
412 UTEST_R2_FORM_WITH_OP(div, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, /)
413 UTEST_R2_FORM_WITH_OP(divu, uint64_t, LARGE_UINT_EXCEED_32_BIT, 100, /)
414 UTEST_R2_FORM_WITH_OP(rem, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, %)
415 UTEST_R2_FORM_WITH_OP(remu, uint64_t, LARGE_UINT_EXCEED_32_BIT, 100, %)
416 
417 // -- RV64M Standard Extension (in addition to RV32M) --
418 UTEST_R2_FORM_WITH_OP(mulw, int32_t, -20, 56, *)
419 UTEST_R2_FORM_WITH_OP(divw, int32_t, 200, -10, /)
420 UTEST_R2_FORM_WITH_OP(divuw, uint32_t, 1000, 100, /)
421 UTEST_R2_FORM_WITH_OP(remw, int32_t, 1234, -91, %)
422 UTEST_R2_FORM_WITH_OP(remuw, uint32_t, 1234, 43, %)
423 
424 // -- RV32A Standard Extension --
425 UTEST_LR_SC(lr_w, sc_w, false, false, int32_t, 0xFBB1A75C)
426 UTEST_AMO_WITH_RES(amoswap_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
427                    (uint32_t)0xA75C0A9C)
428 UTEST_AMO_WITH_RES(amoadd_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
429                    (uint32_t)0xFBB1A75C + (uint32_t)0xA75C0A9C)
430 UTEST_AMO_WITH_RES(amoxor_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
431                    (uint32_t)0xFBB1A75C ^ (uint32_t)0xA75C0A9C)
432 UTEST_AMO_WITH_RES(amoand_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
433                    (uint32_t)0xFBB1A75C & (uint32_t)0xA75C0A9C)
434 UTEST_AMO_WITH_RES(amoor_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
435                    (uint32_t)0xFBB1A75C | (uint32_t)0xA75C0A9C)
436 UTEST_AMO_WITH_RES(amomin_w, false, false, int32_t, 0xFBB1A75C, 0xA75C0A9C,
437                    std::min((int32_t)0xFBB1A75C, (int32_t)0xA75C0A9C))
438 UTEST_AMO_WITH_RES(amomax_w, false, false, int32_t, 0xFBB1A75C, 0xA75C0A9C,
439                    std::max((int32_t)0xFBB1A75C, (int32_t)0xA75C0A9C))
440 UTEST_AMO_WITH_RES(amominu_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
441                    std::min((uint32_t)0xFBB1A75C, (uint32_t)0xA75C0A9C))
442 UTEST_AMO_WITH_RES(amomaxu_w, false, false, uint32_t, 0xFBB1A75C, 0xA75C0A9C,
443                    std::max((uint32_t)0xFBB1A75C, (uint32_t)0xA75C0A9C))
444 
445 // -- RV64A Standard Extension (in addition to RV32A) --
446 UTEST_LR_SC(lr_d, sc_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6)
447 UTEST_AMO_WITH_RES(amoswap_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
448                    0x284ff922346ad35c, (int64_t)0x284ff922346ad35c)
449 UTEST_AMO_WITH_RES(amoadd_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
450                    0x284ff922346ad35c,
451                    (int64_t)0xFBB10A9Cbfb76aa6 + (int64_t)0x284ff922346ad35c)
452 UTEST_AMO_WITH_RES(amoxor_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
453                    0x284ff922346ad35c,
454                    (int64_t)0xFBB10A9Cbfb76aa6 ^ (int64_t)0x284ff922346ad35c)
455 UTEST_AMO_WITH_RES(amoand_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
456                    0x284ff922346ad35c,
457                    (int64_t)0xFBB10A9Cbfb76aa6 & (int64_t)0x284ff922346ad35c)
458 UTEST_AMO_WITH_RES(amoor_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
459                    0x284ff922346ad35c,
460                    (int64_t)0xFBB10A9Cbfb76aa6 | (int64_t)0x284ff922346ad35c)
461 UTEST_AMO_WITH_RES(amomin_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
462                    0x284ff922346ad35c,
463                    std::min((int64_t)0xFBB10A9Cbfb76aa6,
464                             (int64_t)0x284ff922346ad35c))
465 UTEST_AMO_WITH_RES(amomax_d, false, false, int64_t, 0xFBB10A9Cbfb76aa6,
466                    0x284ff922346ad35c,
467                    std::max((int64_t)0xFBB10A9Cbfb76aa6,
468                             (int64_t)0x284ff922346ad35c))
469 UTEST_AMO_WITH_RES(amominu_d, false, false, uint64_t, 0xFBB10A9Cbfb76aa6,
470                    0x284ff922346ad35c,
471                    std::min((uint64_t)0xFBB10A9Cbfb76aa6,
472                             (uint64_t)0x284ff922346ad35c))
473 UTEST_AMO_WITH_RES(amomaxu_d, false, false, uint64_t, 0xFBB10A9Cbfb76aa6,
474                    0x284ff922346ad35c,
475                    std::max((uint64_t)0xFBB10A9Cbfb76aa6,
476                             (uint64_t)0x284ff922346ad35c))
477 
478 // -- RV32F Standard Extension --
479 UTEST_LOAD_STORE_F(flw, fsw, float, -2345.678f)
480 UTEST_R2_FORM_WITH_OP_F(fadd_s, float, -1012.01f, 3456.13f, +)
481 UTEST_R2_FORM_WITH_OP_F(fsub_s, float, -1012.01f, 3456.13f, -)
482 UTEST_R2_FORM_WITH_OP_F(fmul_s, float, -10.01f, 56.13f, *)
483 UTEST_R2_FORM_WITH_OP_F(fdiv_s, float, -10.01f, 34.13f, /)
484 UTEST_R1_FORM_WITH_RES_F(fsqrt_s, float, 34.13f, sqrtf(34.13f))
485 UTEST_R2_FORM_WITH_RES_F(fmin_s, float, -1012.0f, 3456.13f, -1012.0f)
486 UTEST_R2_FORM_WITH_RES_F(fmax_s, float, -1012.0f, 3456.13f, 3456.13f)
487 UTEST_R3_FORM_WITH_RES_F(fmadd_s, float, 67.56f, -1012.01f, 3456.13f,
488                          std::fma(67.56f, -1012.01f, 3456.13f))
489 UTEST_R3_FORM_WITH_RES_F(fmsub_s, float, 67.56f, -1012.01f, 3456.13f,
490                          std::fma(67.56f, -1012.01f, -3456.13f))
491 UTEST_R3_FORM_WITH_RES_F(fnmsub_s, float, 67.56f, -1012.01f, 3456.13f,
492                          -std::fma(67.56f, -1012.01f, -3456.13f))
493 UTEST_R3_FORM_WITH_RES_F(fnmadd_s, float, 67.56f, -1012.01f, 3456.13f,
494                          -std::fma(67.56f, -1012.01f, 3456.13f))
495 UTEST_COMPARE_WITH_OP_F(feq_s, float, -3456.56, -3456.56, ==)
496 UTEST_COMPARE_WITH_OP_F(flt_s, float, -3456.56, -3456.56, <)
497 UTEST_COMPARE_WITH_OP_F(fle_s, float, -3456.56, -3456.56, <=)
498 UTEST_CONV_F_FROM_I(fcvt_s_w, int32_t, float, -100, (float)(-100))
499 UTEST_CONV_F_FROM_I(fcvt_s_wu, uint32_t, float,
500                     std::numeric_limits<uint32_t>::max(),
501                     (float)(std::numeric_limits<uint32_t>::max()))
502 UTEST_CONV_I_FROM_F(fcvt_w_s, float, int32_t, RMM, -100.5f, -101)
503 UTEST_CONV_I_FROM_F(fcvt_wu_s, float, uint32_t, RUP, 256.1f, 257)
504 UTEST_R2_FORM_WITH_RES_F(fsgnj_s, float, -100.0f, 200.0f, 100.0f)
505 UTEST_R2_FORM_WITH_RES_F(fsgnjn_s, float, 100.0f, 200.0f, -100.0f)
506 UTEST_R2_FORM_WITH_RES_F(fsgnjx_s, float, -100.0f, 200.0f, -100.0f)
507 
508 // -- RV64F Standard Extension (in addition to RV32F) --
509 UTEST_LOAD_STORE_F(fld, fsd, double, -3456.678)
510 UTEST_R2_FORM_WITH_OP_F(fadd_d, double, -1012.01, 3456.13, +)
511 UTEST_R2_FORM_WITH_OP_F(fsub_d, double, -1012.01, 3456.13, -)
512 UTEST_R2_FORM_WITH_OP_F(fmul_d, double, -10.01, 56.13, *)
513 UTEST_R2_FORM_WITH_OP_F(fdiv_d, double, -10.01, 34.13, /)
514 UTEST_R1_FORM_WITH_RES_F(fsqrt_d, double, 34.13, std::sqrt(34.13))
515 UTEST_R2_FORM_WITH_RES_F(fmin_d, double, -1012.0, 3456.13, -1012.0)
516 UTEST_R2_FORM_WITH_RES_F(fmax_d, double, -1012.0, 3456.13, 3456.13)
517 
518 UTEST_R3_FORM_WITH_RES_F(fmadd_d, double, 67.56, -1012.01, 3456.13,
519                          std::fma(67.56, -1012.01, 3456.13))
520 UTEST_R3_FORM_WITH_RES_F(fmsub_d, double, 67.56, -1012.01, 3456.13,
521                          std::fma(67.56, -1012.01, -3456.13))
522 UTEST_R3_FORM_WITH_RES_F(fnmsub_d, double, 67.56, -1012.01, 3456.13,
523                          -std::fma(67.56, -1012.01, -3456.13))
524 UTEST_R3_FORM_WITH_RES_F(fnmadd_d, double, 67.56, -1012.01, 3456.13,
525                          -std::fma(67.56, -1012.01, 3456.13))
526 
527 UTEST_COMPARE_WITH_OP_F(feq_d, double, -3456.56, -3456.56, ==)
528 UTEST_COMPARE_WITH_OP_F(flt_d, double, -3456.56, -3456.56, <)
529 UTEST_COMPARE_WITH_OP_F(fle_d, double, -3456.56, -3456.56, <=)
530 
531 UTEST_CONV_F_FROM_I(fcvt_d_w, int32_t, double, -100, -100.0)
532 UTEST_CONV_F_FROM_I(fcvt_d_wu, uint32_t, double,
533                     std::numeric_limits<uint32_t>::max(),
534                     (double)(std::numeric_limits<uint32_t>::max()))
535 UTEST_CONV_I_FROM_F(fcvt_w_d, double, int32_t, RTZ, -100.0, -100)
536 UTEST_CONV_I_FROM_F(fcvt_wu_d, double, uint32_t, RTZ,
537                     (double)(std::numeric_limits<uint32_t>::max()),
538                     std::numeric_limits<uint32_t>::max())
539 
540 // -- RV64F Standard Extension (in addition to RV32F) --
541 UTEST_CONV_I_FROM_F(fcvt_l_s, float, int64_t, RDN, -100.5f, -101)
542 UTEST_CONV_I_FROM_F(fcvt_lu_s, float, uint64_t, RTZ, 1000001.0f, 1000001)
543 UTEST_CONV_F_FROM_I(fcvt_s_l, int64_t, float, (-0x1234'5678'0000'0001LL),
544                     (float)(-0x1234'5678'0000'0001LL))
545 UTEST_CONV_F_FROM_I(fcvt_s_lu, uint64_t, float,
546                     std::numeric_limits<uint64_t>::max(),
547                     (float)(std::numeric_limits<uint64_t>::max()))
548 
549 // -- RV32D Standard Extension --
550 UTEST_CONV_F_FROM_F(fcvt_s_d, double, float, 100.0, 100.0f)
551 UTEST_CONV_F_FROM_F(fcvt_d_s, float, double, 100.0f, 100.0)
552 
553 UTEST_R2_FORM_WITH_RES_F(fsgnj_d, double, -100.0, 200.0, 100.0)
554 UTEST_R2_FORM_WITH_RES_F(fsgnjn_d, double, 100.0, 200.0, -100.0)
555 UTEST_R2_FORM_WITH_RES_F(fsgnjx_d, double, -100.0, 200.0, -100.0)
556 
557 // -- RV64D Standard Extension (in addition to RV32D) --
558 UTEST_CONV_I_FROM_F(fcvt_l_d, double, int64_t, RNE, -100.5, -100)
559 UTEST_CONV_I_FROM_F(fcvt_lu_d, double, uint64_t, RTZ, 2456.5, 2456)
560 UTEST_CONV_F_FROM_I(fcvt_d_l, int64_t, double, (-0x1234'5678'0000'0001LL),
561                     (double)(-0x1234'5678'0000'0001LL))
562 UTEST_CONV_F_FROM_I(fcvt_d_lu, uint64_t, double,
563                     std::numeric_limits<uint64_t>::max(),
564                     (double)(std::numeric_limits<uint64_t>::max()))
565 
566 // -- RV64C Standard Extension --
567 UTEST_R1_FORM_WITH_RES_C(c_mv, int64_t, int64_t, 0x0f5600ab123400,
568                          0x0f5600ab123400)
569 
570 // -- Assembler Pseudo Instructions --
571 UTEST_R1_FORM_WITH_RES(mv, int64_t, int64_t, 0x0f5600ab123400, 0x0f5600ab123400)
572 UTEST_R1_FORM_WITH_RES(not_, int64_t, int64_t, 0, ~0)
573 UTEST_R1_FORM_WITH_RES(neg, int64_t, int64_t, 0x0f5600ab123400LL,
574                        -(0x0f5600ab123400LL))
575 UTEST_R1_FORM_WITH_RES(negw, int32_t, int32_t, 0xab123400, -(0xab123400))
576 UTEST_R1_FORM_WITH_RES(sext_w, int32_t, int64_t, 0xFA01'1234,
577                        static_cast<int64_t>(0xFFFFFFFFFA011234LL))
578 UTEST_R1_FORM_WITH_RES(seqz, int64_t, int64_t, 20, 20 == 0)
579 UTEST_R1_FORM_WITH_RES(snez, int64_t, int64_t, 20, 20 != 0)
580 UTEST_R1_FORM_WITH_RES(sltz, int64_t, int64_t, -20, -20 < 0)
581 UTEST_R1_FORM_WITH_RES(sgtz, int64_t, int64_t, -20, -20 > 0)
582 
583 UTEST_R1_FORM_WITH_RES_F(fmv_s, float, -23.5f, -23.5f)
584 UTEST_R1_FORM_WITH_RES_F(fabs_s, float, -23.5f, 23.5f)
585 UTEST_R1_FORM_WITH_RES_F(fneg_s, float, 23.5f, -23.5f)
586 UTEST_R1_FORM_WITH_RES_F(fmv_d, double, -23.5, -23.5)
587 UTEST_R1_FORM_WITH_RES_F(fabs_d, double, -23.5, 23.5)
588 UTEST_R1_FORM_WITH_RES_F(fneg_d, double, 23.5, -23.5)
589 
590 // Test LI
591 TEST(RISCV0) {
592   CcTest::InitializeVM();
593 
594   FOR_INT64_INPUTS(i) {
595     auto fn = [i](MacroAssembler& assm) { __ RV_li(a0, i); };
596     auto res = GenAndRunTest(fn);
597     CHECK_EQ(i, res);
598   }
599 }
600 
TEST(RISCV1)601 TEST(RISCV1) {
602   CcTest::InitializeVM();
603 
604   Label L, C;
605   auto fn = [&L, &C](MacroAssembler& assm) {
606     __ mv(a1, a0);
607     __ RV_li(a0, 0l);
608     __ j(&C);
609 
610     __ bind(&L);
611     __ add(a0, a0, a1);
612     __ addi(a1, a1, -1);
613 
614     __ bind(&C);
615     __ xori(a2, a1, 0);
616     __ bnez(a2, &L);
617   };
618 
619   int64_t input = 50;
620   int64_t expected_res = 1275L;
621   auto res = GenAndRunTest<int64_t>(input, fn);
622   CHECK_EQ(expected_res, res);
623 }
624 
TEST(RISCV2)625 TEST(RISCV2) {
626   CcTest::InitializeVM();
627   Isolate* isolate = CcTest::i_isolate();
628   HandleScope scope(isolate);
629 
630   Label exit, error;
631   int64_t expected_res = 0x31415926L;
632 
633   // ----- Test all instructions.
634 
635   // Test lui, ori, and addiw, used in the
636   // li pseudo-instruction. This way we
637   // can then safely load registers with
638   // chosen values.
639   auto fn = [&exit, &error, expected_res](MacroAssembler& assm) {
640     __ ori(a4, zero_reg, 0);
641     __ lui(a4, 0x12345);
642     __ ori(a4, a4, 0);
643     __ ori(a4, a4, 0xF0F);
644     __ ori(a4, a4, 0x0F0);
645     __ addiw(a5, a4, 1);
646     __ addiw(a6, a5, -0x10);
647 
648     // Load values in temporary registers.
649     __ RV_li(a4, 0x00000004);
650     __ RV_li(a5, 0x00001234);
651     __ RV_li(a6, 0x12345678);
652     __ RV_li(a7, 0x7FFFFFFF);
653     __ RV_li(t0, 0xFFFFFFFC);
654     __ RV_li(t1, 0xFFFFEDCC);
655     __ RV_li(t2, 0xEDCBA988);
656     __ RV_li(t3, 0x80000000);
657 
658     __ srliw(t0, a6, 8);   // 0x00123456
659     __ slliw(t0, t0, 11);  // 0x91A2B000
660     __ sraiw(t0, t0, 3);   // 0xFFFFFFFF F2345600
661     __ sraw(t0, t0, a4);   // 0xFFFFFFFF FF234560
662     __ sllw(t0, t0, a4);   // 0xFFFFFFFF F2345600
663     __ srlw(t0, t0, a4);   // 0x0F234560
664     __ RV_li(t5, 0x0F234560);
665     __ bne(t0, t5, &error);
666 
667     __ addw(t0, a4, a5);  // 0x00001238
668     __ subw(t0, t0, a4);  // 0x00001234
669     __ RV_li(t5, 0x00001234);
670     __ bne(t0, t5, &error);
671     __ addw(a1, a7,
672             a4);  // 32bit addu result is sign-extended into 64bit reg.
673     __ RV_li(t5, 0xFFFFFFFF80000003);
674     __ bne(a1, t5, &error);
675     __ subw(a1, t3, a4);  // 0x7FFFFFFC
676     __ RV_li(t5, 0x7FFFFFFC);
677     __ bne(a1, t5, &error);
678 
679     __ and_(t0, a5, a6);  // 0x0000000000001230
680     __ or_(t0, t0, a5);   // 0x0000000000001234
681     __ xor_(t0, t0, a6);  // 0x000000001234444C
682     __ or_(t0, t0, a6);
683     __ not_(t0, t0);  // 0xFFFFFFFFEDCBA983
684     __ RV_li(t5, 0xFFFFFFFFEDCBA983);
685     __ bne(t0, t5, &error);
686 
687     // Shift both 32bit number to left, to
688     // preserve meaning of next comparison.
689     __ slli(a7, a7, 32);
690     __ slli(t3, t3, 32);
691 
692     __ slt(t0, t3, a7);
693     __ RV_li(t5, 1);
694     __ bne(t0, t5, &error);
695     __ sltu(t0, t3, a7);
696     __ bne(t0, zero_reg, &error);
697 
698     // Restore original values in registers.
699     __ srli(a7, a7, 32);
700     __ srli(t3, t3, 32);
701 
702     __ RV_li(t0, 0x7421);    // 0x00007421
703     __ addi(t0, t0, -0x1);   // 0x00007420
704     __ addi(t0, t0, -0x20);  // 0x00007400
705     __ RV_li(t5, 0x00007400);
706     __ bne(t0, t5, &error);
707     __ addiw(a1, a7, 0x1);  // 0x80000000 - result is sign-extended.
708     __ RV_li(t5, 0xFFFFFFFF80000000);
709     __ bne(a1, t5, &error);
710 
711     __ RV_li(t5, 0x00002000);
712     __ slt(t0, a5, t5);  // 0x1
713     __ RV_li(t6, 0xFFFFFFFFFFFF8000);
714     __ slt(t0, t0, t6);  // 0x0
715     __ bne(t0, zero_reg, &error);
716     __ sltu(t0, a5, t5);  // 0x1
717     __ RV_li(t6, 0x00008000);
718     __ sltu(t0, t0, t6);  // 0x1
719     __ RV_li(t5, 1);
720     __ bne(t0, t5, &error);
721 
722     __ andi(t0, a5, 0x0F0);  // 0x00000030
723     __ ori(t0, t0, 0x200);   // 0x00000230
724     __ xori(t0, t0, 0x3CC);  // 0x000001FC
725     __ RV_li(t5, 0x000001FC);
726     __ bne(t0, t5, &error);
727     __ lui(a1, -519628);  // Result is sign-extended into 64bit register.
728     __ RV_li(t5, 0xFFFFFFFF81234000);
729     __ bne(a1, t5, &error);
730 
731     // Everything was correctly executed.
732     // Load the expected result.
733     __ RV_li(a0, expected_res);
734     __ j(&exit);
735 
736     __ bind(&error);
737     // Got an error. Return a wrong result.
738     __ RV_li(a0, 666);
739 
740     __ bind(&exit);
741   };
742   auto res = GenAndRunTest(fn);
743   CHECK_EQ(expected_res, res);
744 }
745 
TEST(RISCV3)746 TEST(RISCV3) {
747   // Test floating point instructions.
748   CcTest::InitializeVM();
749   Isolate* isolate = CcTest::i_isolate();
750   HandleScope scope(isolate);
751 
752   struct T {
753     double a;
754     double b;
755     double c;
756     double d;
757     double e;
758     double f;
759     double g;
760     double h;
761     double i;
762     float fa;
763     float fb;
764     float fc;
765     float fd;
766     float fe;
767     float ff;
768     float fg;
769   } t;
770 
771   // Create a function that accepts &t and loads, manipulates, and stores
772   // the doubles t.a ... t.f.
773 
774   // Double precision floating point instructions.
775   auto fn = [](MacroAssembler& assm) {
776     __ fld(ft0, a0, offsetof(T, a));
777     __ fld(ft1, a0, offsetof(T, b));
778     __ fadd_d(ft2, ft0, ft1);
779     __ fsd(ft2, a0, offsetof(T, c));  // c = a + b.
780 
781     __ fmv_d(ft3, ft2);   // c
782     __ fneg_d(fa0, ft1);  // -b
783     __ fsub_d(ft3, ft3, fa0);
784     __ fsd(ft3, a0, offsetof(T, d));  // d = c - (-b).
785 
786     __ fsd(ft0, a0, offsetof(T, b));  // b = a.
787 
788     __ RV_li(a4, 120);
789     __ fcvt_d_w(ft5, a4);
790     __ fmul_d(ft3, ft3, ft5);
791     __ fsd(ft3, a0, offsetof(T, e));  // e = d * 120 = 1.8066e16.
792 
793     __ fdiv_d(ft4, ft3, ft0);
794     __ fsd(ft4, a0, offsetof(T, f));  // f = e / a = 120.44.
795 
796     __ fsqrt_d(ft5, ft4);
797     __ fsd(ft5, a0, offsetof(T, g));
798     // g = sqrt(f) = 10.97451593465515908537
799 
800     __ fld(ft0, a0, offsetof(T, h));
801     __ fld(ft1, a0, offsetof(T, i));
802     __ fmadd_d(ft5, ft1, ft0, ft1);
803     __ fsd(ft5, a0, offsetof(T, h));
804 
805     // // Single precision floating point instructions.
806     __ flw(ft0, a0, offsetof(T, fa));
807     __ flw(ft1, a0, offsetof(T, fb));
808     __ fadd_s(ft2, ft0, ft1);
809     __ fsw(ft2, a0, offsetof(T, fc));  // fc = fa + fb.
810 
811     __ fneg_s(ft3, ft1);  // -fb
812     __ fsub_s(ft3, ft2, ft3);
813     __ fsw(ft3, a0, offsetof(T, fd));  // fd = fc - (-fb).
814 
815     __ fsw(ft0, a0, offsetof(T, fb));  // fb = fa.
816 
817     __ RV_li(t0, 120);
818     __ fcvt_s_w(ft5, t0);  // ft5 = 120.0.
819     __ fmul_s(ft3, ft3, ft5);
820     __ fsw(ft3, a0, offsetof(T, fe));  // fe = fd * 120
821 
822     __ fdiv_s(ft4, ft3, ft0);
823     __ fsw(ft4, a0, offsetof(T, ff));  // ff = fe / fa
824 
825     __ fsqrt_s(ft5, ft4);
826     __ fsw(ft5, a0, offsetof(T, fg));
827   };
828   auto f = AssembleCode<F3>(fn);
829 
830   // Double test values.
831   t.a = 1.5e14;
832   t.b = 2.75e11;
833   t.c = 0.0;
834   t.d = 0.0;
835   t.e = 0.0;
836   t.f = 0.0;
837   t.h = 1.5;
838   t.i = 2.75;
839   // Single test values.
840   t.fa = 1.5e6;
841   t.fb = 2.75e4;
842   t.fc = 0.0;
843   t.fd = 0.0;
844   t.fe = 0.0;
845   t.ff = 0.0;
846   f.Call(&t, 0, 0, 0, 0);
847   // Expected double results.
848   CHECK_EQ(1.5e14, t.a);
849   CHECK_EQ(1.5e14, t.b);
850   CHECK_EQ(1.50275e14, t.c);
851   CHECK_EQ(1.50550e14, t.d);
852   CHECK_EQ(1.8066e16, t.e);
853   CHECK_EQ(120.44, t.f);
854   CHECK_EQ(10.97451593465515908537, t.g);
855   CHECK_EQ(6.875, t.h);
856   // Expected single results.
857   CHECK_EQ(1.5e6, t.fa);
858   CHECK_EQ(1.5e6, t.fb);
859   CHECK_EQ(1.5275e06, t.fc);
860   CHECK_EQ(1.5550e06, t.fd);
861   CHECK_EQ(1.866e08, t.fe);
862   CHECK_EQ(124.40000152587890625, t.ff);
863   CHECK_EQ(11.1534748077392578125, t.fg);
864 }
TEST(RISCV4)865 TEST(RISCV4) {
866   // Test moves between floating point and
867   // integer registers.
868   CcTest::InitializeVM();
869   Isolate* isolate = CcTest::i_isolate();
870   HandleScope scope(isolate);
871 
872   struct T {
873     double a;
874     double b;
875     double c;
876     float d;
877     int64_t e;
878   } t;
879 
880   auto fn = [](MacroAssembler& assm) {
881     __ fld(ft0, a0, offsetof(T, a));
882     __ fld(fa1, a0, offsetof(T, b));
883 
884     // Swap ft0 and fa1, by using 2 integer registers, a4-a5,
885     __ fmv_x_d(a4, ft0);
886     __ fmv_x_d(a5, fa1);
887 
888     __ fmv_d_x(fa1, a4);
889     __ fmv_d_x(ft0, a5);
890 
891     // Store the swapped ft0 and fa1 back to memory.
892     __ fsd(ft0, a0, offsetof(T, a));
893     __ fsd(fa1, a0, offsetof(T, c));
894 
895     // Test sign extension of move operations from coprocessor.
896     __ flw(ft0, a0, offsetof(T, d));
897     __ fmv_x_w(a4, ft0);
898 
899     __ sd(a4, a0, offsetof(T, e));
900   };
901   auto f = AssembleCode<F3>(fn);
902 
903   t.a = 1.5e22;
904   t.b = 2.75e11;
905   t.c = 17.17;
906   t.d = -2.75e11;
907   f.Call(&t, 0, 0, 0, 0);
908 
909   CHECK_EQ(2.75e11, t.a);
910   CHECK_EQ(2.75e11, t.b);
911   CHECK_EQ(1.5e22, t.c);
912   CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD2800E8EL), t.e);
913 }
914 
TEST(RISCV5)915 TEST(RISCV5) {
916   // Test conversions between doubles and
917   // integers.
918   CcTest::InitializeVM();
919   Isolate* isolate = CcTest::i_isolate();
920   HandleScope scope(isolate);
921 
922   struct T {
923     double a;
924     double b;
925     int i;
926     int j;
927   } t;
928 
929   auto fn = [](MacroAssembler& assm) {
930     // Load all structure elements to registers.
931     __ fld(ft0, a0, offsetof(T, a));
932     __ fld(ft1, a0, offsetof(T, b));
933     __ lw(a4, a0, offsetof(T, i));
934     __ lw(a5, a0, offsetof(T, j));
935 
936     // Convert double in ft0 to int in element i.
937     __ fcvt_l_d(a6, ft0);
938     __ sw(a6, a0, offsetof(T, i));
939 
940     // Convert double in ft1 to int in element j.
941     __ fcvt_l_d(a7, ft1);
942     __ sw(a7, a0, offsetof(T, j));
943 
944     // Convert int in original i (a4) to double in a.
945     __ fcvt_d_l(fa0, a4);
946     __ fsd(fa0, a0, offsetof(T, a));
947 
948     // Convert int in original j (a5) to double in b.
949     __ fcvt_d_l(fa1, a5);
950     __ fsd(fa1, a0, offsetof(T, b));
951   };
952   auto f = AssembleCode<F3>(fn);
953 
954   t.a = 1.5e4;
955   t.b = 2.75e8;
956   t.i = 12345678;
957   t.j = -100000;
958   f.Call(&t, 0, 0, 0, 0);
959 
960   CHECK_EQ(12345678.0, t.a);
961   CHECK_EQ(-100000.0, t.b);
962   CHECK_EQ(15000, t.i);
963   CHECK_EQ(275000000, t.j);
964 }
965 
TEST(RISCV6)966 TEST(RISCV6) {
967   // Test simple memory loads and stores.
968   CcTest::InitializeVM();
969   Isolate* isolate = CcTest::i_isolate();
970   HandleScope scope(isolate);
971 
972   struct T {
973     uint32_t ui;
974     int32_t si;
975     int32_t r1;
976     int32_t r2;
977     int32_t r3;
978     int32_t r4;
979     int32_t r5;
980     int32_t r6;
981   } t;
982 
983   auto fn = [](MacroAssembler& assm) {
984     // Basic word load/store.
985     __ lw(a4, a0, offsetof(T, ui));
986     __ sw(a4, a0, offsetof(T, r1));
987 
988     // lh with positive data.
989     __ lh(a5, a0, offsetof(T, ui));
990     __ sw(a5, a0, offsetof(T, r2));
991 
992     // lh with negative data.
993     __ lh(a6, a0, offsetof(T, si));
994     __ sw(a6, a0, offsetof(T, r3));
995 
996     // lhu with negative data.
997     __ lhu(a7, a0, offsetof(T, si));
998     __ sw(a7, a0, offsetof(T, r4));
999 
1000     // Lb with negative data.
1001     __ lb(t0, a0, offsetof(T, si));
1002     __ sw(t0, a0, offsetof(T, r5));
1003 
1004     // sh writes only 1/2 of word.
1005     __ RV_li(t1, 0x33333333);
1006     __ sw(t1, a0, offsetof(T, r6));
1007     __ lhu(t1, a0, offsetof(T, si));
1008     __ sh(t1, a0, offsetof(T, r6));
1009   };
1010   auto f = AssembleCode<F3>(fn);
1011 
1012   t.ui = 0x11223344;
1013   t.si = 0x99AABBCC;
1014   f.Call(&t, 0, 0, 0, 0);
1015 
1016   CHECK_EQ(static_cast<int32_t>(0x11223344), t.r1);
1017   if (kArchEndian == kLittle) {
1018     CHECK_EQ(static_cast<int32_t>(0x3344), t.r2);
1019     CHECK_EQ(static_cast<int32_t>(0xFFFFBBCC), t.r3);
1020     CHECK_EQ(static_cast<int32_t>(0x0000BBCC), t.r4);
1021     CHECK_EQ(static_cast<int32_t>(0xFFFFFFCC), t.r5);
1022     CHECK_EQ(static_cast<int32_t>(0x3333BBCC), t.r6);
1023   } else {
1024     CHECK_EQ(static_cast<int32_t>(0x1122), t.r2);
1025     CHECK_EQ(static_cast<int32_t>(0xFFFF99AA), t.r3);
1026     CHECK_EQ(static_cast<int32_t>(0x000099AA), t.r4);
1027     CHECK_EQ(static_cast<int32_t>(0xFFFFFF99), t.r5);
1028     CHECK_EQ(static_cast<int32_t>(0x99AA3333), t.r6);
1029   }
1030 }
1031 
1032 // pair.first is the F_TYPE input to test, pair.second is I_TYPE expected result
1033 template <typename T>
fclass_test_values()1034 static const std::vector<std::pair<T, uint64_t>> fclass_test_values() {
1035   static const std::pair<T, uint64_t> kValues[] = {
1036       std::make_pair(-std::numeric_limits<T>::infinity(), kNegativeInfinity),
1037       std::make_pair(-10240.56, kNegativeNormalNumber),
1038       std::make_pair(-(std::numeric_limits<T>::min() / 2),
1039                      kNegativeSubnormalNumber),
1040       std::make_pair(-0.0, kNegativeZero),
1041       std::make_pair(+0.0, kPositiveZero),
1042       std::make_pair((std::numeric_limits<T>::min() / 2),
1043                      kPositiveSubnormalNumber),
1044       std::make_pair(10240.56, kPositiveNormalNumber),
1045       std::make_pair(std::numeric_limits<T>::infinity(), kPositiveInfinity),
1046       std::make_pair(std::numeric_limits<T>::signaling_NaN(), kSignalingNaN),
1047       std::make_pair(std::numeric_limits<T>::quiet_NaN(), kQuietNaN)};
1048   return std::vector<std::pair<T, uint64_t>>(&kValues[0],
1049                                              &kValues[arraysize(kValues)]);
1050 }
1051 
TEST(FCLASS)1052 TEST(FCLASS) {
1053   CcTest::InitializeVM();
1054   {
1055     auto i_vec = fclass_test_values<float>();
1056     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1057       auto input = *i;
1058       auto fn = [](MacroAssembler& assm) { __ fclass_s(a0, fa0); };
1059       auto res = GenAndRunTest<uint32_t>(input.first, fn);
1060       CHECK_EQ(input.second, res);
1061     }
1062   }
1063 
1064   {
1065     auto i_vec = fclass_test_values<double>();
1066     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1067       auto input = *i;
1068       auto fn = [](MacroAssembler& assm) { __ fclass_d(a0, fa0); };
1069       auto res = GenAndRunTest<uint32_t>(input.first, fn);
1070       CHECK_EQ(input.second, res);
1071     }
1072   }
1073 }
1074 
TEST(RISCV7)1075 TEST(RISCV7) {
1076   // Test floating point compare and
1077   // branch instructions.
1078   CcTest::InitializeVM();
1079   Isolate* isolate = CcTest::i_isolate();
1080   HandleScope scope(isolate);
1081 
1082   struct T {
1083     double a;
1084     double b;
1085     double c;
1086     double d;
1087     double e;
1088     double f;
1089     int32_t result;
1090   } t;
1091 
1092   // Create a function that accepts &t,
1093   // and loads, manipulates, and stores
1094   // the doubles t.a ... t.f.
1095   Label neither_is_nan, less_than, outa_here;
1096   auto fn = [&neither_is_nan, &less_than, &outa_here](MacroAssembler& assm) {
1097     __ fld(ft0, a0, offsetof(T, a));
1098     __ fld(ft1, a0, offsetof(T, b));
1099 
1100     __ fclass_d(t5, ft0);
1101     __ fclass_d(t6, ft1);
1102     __ or_(t5, t5, t6);
1103     __ andi(t5, t5, kSignalingNaN | kQuietNaN);
1104     __ beq(t5, zero_reg, &neither_is_nan);
1105     __ sw(zero_reg, a0, offsetof(T, result));
1106     __ j(&outa_here);
1107 
1108     __ bind(&neither_is_nan);
1109 
1110     __ flt_d(t5, ft1, ft0);
1111     __ bne(t5, zero_reg, &less_than);
1112 
1113     __ sw(zero_reg, a0, offsetof(T, result));
1114     __ j(&outa_here);
1115 
1116     __ bind(&less_than);
1117     __ RV_li(a4, 1);
1118     __ sw(a4, a0, offsetof(T, result));  // Set true.
1119 
1120     // This test-case should have additional
1121     // tests.
1122 
1123     __ bind(&outa_here);
1124   };
1125 
1126   auto f = AssembleCode<F3>(fn);
1127 
1128   t.a = 1.5e14;
1129   t.b = 2.75e11;
1130   t.c = 2.0;
1131   t.d = -4.0;
1132   t.e = 0.0;
1133   t.f = 0.0;
1134   t.result = 0;
1135   f.Call(&t, 0, 0, 0, 0);
1136   CHECK_EQ(1.5e14, t.a);
1137   CHECK_EQ(2.75e11, t.b);
1138   CHECK_EQ(1, t.result);
1139 }
1140 
TEST(RISCV9)1141 TEST(RISCV9) {
1142   // Test BRANCH improvements.
1143   CcTest::InitializeVM();
1144   Isolate* isolate = CcTest::i_isolate();
1145   HandleScope scope(isolate);
1146 
1147   MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1148   Label exit, exit2, exit3;
1149 
1150   __ Branch(&exit, ge, a0, Operand(zero_reg));
1151   __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
1152   __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
1153 
1154   __ bind(&exit);
1155   __ bind(&exit2);
1156   __ bind(&exit3);
1157   __ jr(ra);
1158 
1159   CodeDesc desc;
1160   assm.GetCode(isolate, &desc);
1161   Handle<Code> code =
1162       Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1163   USE(code);
1164 }
1165 
TEST(NAN_BOX)1166 TEST(NAN_BOX) {
1167   // Test float NaN-boxing.
1168   CcTest::InitializeVM();
1169 
1170   // Test NaN boxing in FMV.X.D
1171   {
1172     auto fn = [](MacroAssembler& assm) { __ fmv_x_d(a0, fa0); };
1173     auto res = GenAndRunTest<uint64_t>(1234.56f, fn);
1174     CHECK_EQ(0xFFFFFFFF00000000 | bit_cast<uint32_t>(1234.56f), res);
1175   }
1176   // Test NaN boxing in FMV.X.W
1177   {
1178     auto fn = [](MacroAssembler& assm) { __ fmv_x_w(a0, fa0); };
1179     auto res = GenAndRunTest<uint64_t>(1234.56f, fn);
1180     CHECK_EQ((uint64_t)bit_cast<uint32_t>(1234.56f), res);
1181   }
1182 
1183   // Test FLW and FSW
1184   Isolate* isolate = CcTest::i_isolate();
1185   HandleScope scope(isolate);
1186 
1187   struct T {
1188     float a;
1189     uint64_t box;
1190     uint64_t res;
1191   } t;
1192 
1193   auto fn = [](MacroAssembler& assm) {
1194     // Load all structure elements to registers.
1195     __ flw(fa0, a0, offsetof(T, a));
1196     // Check boxing when flw
1197     __ fsd(fa0, a0, offsetof(T, box));
1198     // Check only transfer low 32bits when fsw
1199     __ fsw(fa0, a0, offsetof(T, res));
1200   };
1201   auto f = AssembleCode<F3>(fn);
1202 
1203   t.a = -123.45;
1204   t.box = 0;
1205   t.res = 0;
1206   f.Call(&t, 0, 0, 0, 0);
1207 
1208   CHECK_EQ(0xFFFFFFFF00000000 | bit_cast<int32_t>(t.a), t.box);
1209   CHECK_EQ((uint64_t)bit_cast<uint32_t>(t.a), t.res);
1210 }
1211 
TEST(RVC_CI)1212 TEST(RVC_CI) {
1213   // Test RV64C extension CI type instructions.
1214   i::FLAG_riscv_c_extension = true;
1215   CcTest::InitializeVM();
1216 
1217   // Test c.addi
1218   {
1219     auto fn = [](MacroAssembler& assm) { __ c_addi(a0, -15); };
1220     auto res = GenAndRunTest<int64_t>(LARGE_INT_EXCEED_32_BIT, fn);
1221     CHECK_EQ(LARGE_INT_EXCEED_32_BIT - 15, res);
1222   }
1223 
1224   // Test c.addiw
1225   {
1226     auto fn = [](MacroAssembler& assm) { __ c_addiw(a0, -20); };
1227     auto res = GenAndRunTest<int32_t>(LARGE_INT_UNDER_32_BIT, fn);
1228     CHECK_EQ(LARGE_INT_UNDER_32_BIT - 20, res);
1229   }
1230 
1231   // Test c.addi16sp
1232   {
1233     auto fn = [](MacroAssembler& assm) {
1234       __ mv(t1, sp);
1235       __ mv(sp, a0);
1236       __ c_addi16sp(-432);
1237       __ mv(a0, sp);
1238       __ mv(sp, t1);
1239     };
1240     auto res = GenAndRunTest<int64_t>(66666, fn);
1241     CHECK_EQ(66666 - 432, res);
1242   }
1243 
1244   // Test c.li
1245   {
1246     auto fn = [](MacroAssembler& assm) { __ c_li(a0, -15); };
1247     auto res = GenAndRunTest<int64_t>(1234543, fn);
1248     CHECK_EQ(-15, res);
1249   }
1250 
1251   // Test c.lui
1252   {
1253     auto fn = [](MacroAssembler& assm) { __ c_lui(a0, -20); };
1254     auto res = GenAndRunTest<int64_t>(0x1234567, fn);
1255     CHECK_EQ(0xfffffffffffec000, (uint64_t)res);
1256   }
1257 
1258   // Test c.slli
1259   {
1260     auto fn = [](MacroAssembler& assm) { __ c_slli(a0, 13); };
1261     auto res = GenAndRunTest<int64_t>(0x1234'5678ULL, fn);
1262     CHECK_EQ(0x1234'5678ULL << 13, res);
1263   }
1264 }
1265 
TEST(RVC_CIW)1266 TEST(RVC_CIW) {
1267   i::FLAG_riscv_c_extension = true;
1268   CcTest::InitializeVM();
1269 
1270   // Test c.addi4spn
1271   {
1272     auto fn = [](MacroAssembler& assm) {
1273       __ mv(t1, sp);
1274       __ mv(sp, a0);
1275       __ c_addi4spn(a0, 924);
1276       __ mv(sp, t1);
1277     };
1278     auto res = GenAndRunTest<int64_t>(66666, fn);
1279     CHECK_EQ(66666 + 924, res);
1280   }
1281 }
1282 
TEST(RVC_CR)1283 TEST(RVC_CR) {
1284   // Test RV64C extension CR type instructions.
1285   i::FLAG_riscv_c_extension = true;
1286   CcTest::InitializeVM();
1287 
1288   // Test c.add
1289   {
1290     auto fn = [](MacroAssembler& assm) {
1291       __ RV_li(a1, MIN_VAL_IMM12);
1292       __ c_add(a0, a1);
1293     };
1294     auto res = GenAndRunTest<int64_t>(LARGE_INT_EXCEED_32_BIT, fn);
1295     CHECK_EQ(LARGE_INT_EXCEED_32_BIT + MIN_VAL_IMM12, res);
1296   }
1297 }
1298 
TEST(RVC_CA)1299 TEST(RVC_CA) {
1300   // Test RV64C extension CA type instructions.
1301   i::FLAG_riscv_c_extension = true;
1302   CcTest::InitializeVM();
1303 
1304   // Test c.sub
1305   {
1306     auto fn = [](MacroAssembler& assm) {
1307       __ RV_li(a1, MIN_VAL_IMM12);
1308       __ c_sub(a0, a1);
1309     };
1310     auto res = GenAndRunTest<int64_t>(LARGE_INT_UNDER_32_BIT, fn);
1311     CHECK_EQ(LARGE_INT_UNDER_32_BIT - MIN_VAL_IMM12, res);
1312   }
1313 
1314   // Test c.xor
1315   {
1316     auto fn = [](MacroAssembler& assm) {
1317       __ RV_li(a1, MIN_VAL_IMM12);
1318       __ c_xor(a0, a1);
1319     };
1320     auto res = GenAndRunTest<int64_t>(LARGE_INT_UNDER_32_BIT, fn);
1321     CHECK_EQ(LARGE_INT_UNDER_32_BIT ^ MIN_VAL_IMM12, res);
1322   }
1323 
1324   // Test c.or
1325   {
1326     auto fn = [](MacroAssembler& assm) {
1327       __ RV_li(a1, MIN_VAL_IMM12);
1328       __ c_or(a0, a1);
1329     };
1330     auto res = GenAndRunTest<int64_t>(LARGE_INT_UNDER_32_BIT, fn);
1331     CHECK_EQ(LARGE_INT_UNDER_32_BIT | MIN_VAL_IMM12, res);
1332   }
1333 
1334   // Test c.and
1335   {
1336     auto fn = [](MacroAssembler& assm) {
1337       __ RV_li(a1, MIN_VAL_IMM12);
1338       __ c_and(a0, a1);
1339     };
1340     auto res = GenAndRunTest<int64_t>(LARGE_INT_UNDER_32_BIT, fn);
1341     CHECK_EQ(LARGE_INT_UNDER_32_BIT & MIN_VAL_IMM12, res);
1342   }
1343 
1344   // Test c.subw
1345   {
1346     auto fn = [](MacroAssembler& assm) {
1347       __ RV_li(a1, MIN_VAL_IMM12);
1348       __ c_subw(a0, a1);
1349     };
1350     auto res = GenAndRunTest<int64_t>(LARGE_INT_UNDER_32_BIT, fn);
1351     CHECK_EQ(LARGE_INT_UNDER_32_BIT - MIN_VAL_IMM12, res);
1352   }
1353 
1354   // Test c.addw
1355   {
1356     auto fn = [](MacroAssembler& assm) {
1357       __ RV_li(a1, MIN_VAL_IMM12);
1358       __ c_addw(a0, a1);
1359     };
1360     auto res = GenAndRunTest<int64_t>(LARGE_INT_UNDER_32_BIT, fn);
1361     CHECK_EQ(LARGE_INT_UNDER_32_BIT + MIN_VAL_IMM12, res);
1362   }
1363 }
1364 
TEST(RVC_LOAD_STORE_SP)1365 TEST(RVC_LOAD_STORE_SP) {
1366   // Test RV64C extension fldsp/fsdsp, lwsp/swsp, ldsp/sdsp.
1367   i::FLAG_riscv_c_extension = true;
1368   CcTest::InitializeVM();
1369 
1370   {
1371     auto fn = [](MacroAssembler& assm) {
1372       __ c_fsdsp(fa0, 80);
1373       __ c_fldsp(fa0, 80);
1374     };
1375     auto res = GenAndRunTest<double>(-3456.678, fn);
1376     CHECK_EQ(-3456.678, res);
1377   }
1378 
1379   {
1380     auto fn = [](MacroAssembler& assm) {
1381       __ c_swsp(a0, 40);
1382       __ c_lwsp(a0, 40);
1383     };
1384     auto res = GenAndRunTest<int32_t>(0x456AF894, fn);
1385     CHECK_EQ(0x456AF894, res);
1386   }
1387 
1388   {
1389     auto fn = [](MacroAssembler& assm) {
1390       __ c_sdsp(a0, 160);
1391       __ c_ldsp(a0, 160);
1392     };
1393     auto res = GenAndRunTest<uint64_t>(0xFBB10A9C12345678, fn);
1394     CHECK_EQ(0xFBB10A9C12345678, res);
1395   }
1396 }
1397 
TEST(RVC_LOAD_STORE_COMPRESSED)1398 TEST(RVC_LOAD_STORE_COMPRESSED) {
1399   // Test RV64C extension fld,  lw, ld.
1400   i::FLAG_riscv_c_extension = true;
1401 
1402   CcTest::InitializeVM();
1403   Isolate* isolate = CcTest::i_isolate();
1404   HandleScope scope(isolate);
1405 
1406   struct T {
1407     double a;
1408     double b;
1409     double c;
1410   } t;
1411 
1412   // c.fld
1413   {
1414     auto fn = [](MacroAssembler& assm) {
1415       __ c_fld(fa0, a0, offsetof(T, a));
1416       __ c_fld(fa1, a0, offsetof(T, b));
1417       __ fadd_d(fa2, fa1, fa0);
1418       __ c_fsd(fa2, a0, offsetof(T, c));  // c = a + b.
1419     };
1420     auto f = AssembleCode<F3>(fn);
1421 
1422     t.a = 1.5e14;
1423     t.b = 1.5e14;
1424     t.c = 3.0e14;
1425     f.Call(&t, 0, 0, 0, 0);
1426     // Expected double results.
1427     CHECK_EQ(1.5e14, t.a);
1428     CHECK_EQ(1.5e14, t.b);
1429     CHECK_EQ(3.0e14, t.c);
1430   }
1431 
1432   struct S {
1433     int32_t a;
1434     int32_t b;
1435     int32_t c;
1436   } s;
1437   // c.lw
1438   {
1439     auto fn = [](MacroAssembler& assm) {
1440       __ c_lw(a1, a0, offsetof(S, a));
1441       __ c_lw(a2, a0, offsetof(S, b));
1442       __ add(a3, a1, a2);
1443       __ c_sw(a3, a0, offsetof(S, c));  // c = a + b.
1444     };
1445     auto f = AssembleCode<F3>(fn);
1446 
1447     s.a = 1;
1448     s.b = 2;
1449     s.c = 3;
1450     f.Call(&s, 0, 0, 0, 0);
1451     CHECK_EQ(1, s.a);
1452     CHECK_EQ(2, s.b);
1453     CHECK_EQ(3, s.c);
1454   }
1455 
1456   struct U {
1457     int64_t a;
1458     int64_t b;
1459     int64_t c;
1460   } u;
1461   // c.ld
1462   {
1463     auto fn = [](MacroAssembler& assm) {
1464       __ c_ld(a1, a0, offsetof(U, a));
1465       __ c_ld(a2, a0, offsetof(U, b));
1466       __ add(a3, a1, a2);
1467       __ c_sd(a3, a0, offsetof(U, c));  // c = a + b.
1468     };
1469     auto f = AssembleCode<F3>(fn);
1470 
1471     u.a = 1;
1472     u.b = 2;
1473     u.c = 3;
1474     f.Call(&u, 0, 0, 0, 0);
1475     CHECK_EQ(1, u.a);
1476     CHECK_EQ(2, u.b);
1477     CHECK_EQ(3, u.c);
1478   }
1479 }
1480 
TEST(RVC_JUMP)1481 TEST(RVC_JUMP) {
1482   i::FLAG_riscv_c_extension = true;
1483   CcTest::InitializeVM();
1484 
1485   Label L, C;
1486   auto fn = [&L, &C](MacroAssembler& assm) {
1487     __ mv(a1, a0);
1488     __ RV_li(a0, 0l);
1489     __ c_j(&C);
1490 
1491     __ bind(&L);
1492     __ add(a0, a0, a1);
1493     __ addi(a1, a1, -1);
1494 
1495     __ bind(&C);
1496     __ xori(a2, a1, 0);
1497     __ bnez(a2, &L);
1498   };
1499 
1500   int64_t input = 50;
1501   int64_t expected_res = 1275L;
1502   auto res = GenAndRunTest<int64_t>(input, fn);
1503   CHECK_EQ(expected_res, res);
1504 }
1505 
TEST(RVC_CB)1506 TEST(RVC_CB) {
1507   // Test RV64C extension CI type instructions.
1508   FLAG_riscv_c_extension = true;
1509   CcTest::InitializeVM();
1510 
1511   // Test c.srai
1512   {
1513     auto fn = [](MacroAssembler& assm) { __ c_srai(a0, 13); };
1514     auto res = GenAndRunTest<int64_t>(0x1234'5678ULL, fn);
1515     CHECK_EQ(0x1234'5678ULL >> 13, res);
1516   }
1517 
1518   // Test c.srli
1519   {
1520     auto fn = [](MacroAssembler& assm) { __ c_srli(a0, 13); };
1521     auto res = GenAndRunTest<int64_t>(0x1234'5678ULL, fn);
1522     CHECK_EQ(0x1234'5678ULL >> 13, res);
1523   }
1524 
1525   // Test c.andi
1526   {
1527     auto fn = [](MacroAssembler& assm) { __ c_andi(a0, 13); };
1528     auto res = GenAndRunTest<int64_t>(LARGE_INT_EXCEED_32_BIT, fn);
1529     CHECK_EQ(LARGE_INT_EXCEED_32_BIT & 13, res);
1530   }
1531 }
1532 
TEST(RVC_CB_BRANCH)1533 TEST(RVC_CB_BRANCH) {
1534   FLAG_riscv_c_extension = true;
1535   // Test floating point compare and
1536   // branch instructions.
1537   CcTest::InitializeVM();
1538   Isolate* isolate = CcTest::i_isolate();
1539   HandleScope scope(isolate);
1540 
1541   struct T {
1542     double a;
1543     double b;
1544     double c;
1545     double d;
1546     double e;
1547     double f;
1548     int32_t result;
1549   } t;
1550 
1551   // Create a function that accepts &t,
1552   // and loads, manipulates, and stores
1553   // the doubles t.a ... t.f.
1554   Label neither_is_nan, less_than, outa_here;
1555   auto fn = [&neither_is_nan, &less_than, &outa_here](MacroAssembler& assm) {
1556     __ fld(ft0, a0, offsetof(T, a));
1557     __ fld(ft1, a0, offsetof(T, b));
1558 
1559     __ fclass_d(t5, ft0);
1560     __ fclass_d(t6, ft1);
1561     __ or_(a1, t5, t6);
1562     __ andi(a1, a1, kSignalingNaN | kQuietNaN);
1563     __ c_beqz(a1, &neither_is_nan);
1564     __ sw(zero_reg, a0, offsetof(T, result));
1565     __ j(&outa_here);
1566 
1567     __ bind(&neither_is_nan);
1568 
1569     __ flt_d(a1, ft1, ft0);
1570     __ c_bnez(a1, &less_than);
1571 
1572     __ sw(zero_reg, a0, offsetof(T, result));
1573     __ j(&outa_here);
1574 
1575     __ bind(&less_than);
1576     __ RV_li(a4, 1);
1577     __ sw(a4, a0, offsetof(T, result));  // Set true.
1578 
1579     // This test-case should have additional
1580     // tests.
1581 
1582     __ bind(&outa_here);
1583   };
1584 
1585   auto f = AssembleCode<F3>(fn);
1586 
1587   t.a = 1.5e14;
1588   t.b = 2.75e11;
1589   t.c = 2.0;
1590   t.d = -4.0;
1591   t.e = 0.0;
1592   t.f = 0.0;
1593   t.result = 0;
1594   f.Call(&t, 0, 0, 0, 0);
1595   CHECK_EQ(1.5e14, t.a);
1596   CHECK_EQ(2.75e11, t.b);
1597   CHECK_EQ(1, t.result);
1598 }
1599 
TEST(TARGET_ADDR)1600 TEST(TARGET_ADDR) {
1601   CcTest::InitializeVM();
1602   Isolate* isolate = CcTest::i_isolate();
1603   HandleScope scope(isolate);
1604 
1605   // This is the series of instructions to load 48 bit address 0x0123456789ab
1606   uint32_t buffer[6] = {0x091ab37,  0x2b330213, 0x00b21213,
1607                         0x62626213, 0x00621213, 0x02b26213};
1608   MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1609 
1610   uintptr_t addr = reinterpret_cast<uintptr_t>(&buffer[0]);
1611   Address res = __ target_address_at(static_cast<Address>(addr));
1612   CHECK_EQ(0x0123456789abL, res);
1613 }
1614 
TEST(SET_TARGET_ADDR)1615 TEST(SET_TARGET_ADDR) {
1616   CcTest::InitializeVM();
1617   Isolate* isolate = CcTest::i_isolate();
1618   HandleScope scope(isolate);
1619 
1620   // This is the series of instructions to load 48 bit address 0xba9876543210
1621   uint32_t buffer[6] = {0x091ab37,  0x2b330213, 0x00b21213,
1622                         0x62626213, 0x00621213, 0x02b26213};
1623 
1624   MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1625 
1626   uintptr_t addr = reinterpret_cast<uintptr_t>(&buffer[0]);
1627   __ set_target_value_at(static_cast<Address>(addr), 0xba9876543210L,
1628                          FLUSH_ICACHE_IF_NEEDED);
1629   Address res = __ target_address_at(static_cast<Address>(addr));
1630   CHECK_EQ(0xba9876543210L, res);
1631 }
1632 
1633 // pair.first is the F_TYPE input to test, pair.second is I_TYPE expected
1634 // result
1635 template <typename F_TYPE, typename I_TYPE>
out_of_range_test_values()1636 static const std::vector<std::pair<F_TYPE, I_TYPE>> out_of_range_test_values() {
1637   static const std::pair<F_TYPE, I_TYPE> kValues[] = {
1638       std::make_pair(std::numeric_limits<F_TYPE>::quiet_NaN(),
1639                      std::numeric_limits<I_TYPE>::max()),
1640       std::make_pair(std::numeric_limits<F_TYPE>::signaling_NaN(),
1641                      std::numeric_limits<I_TYPE>::max()),
1642       std::make_pair(std::numeric_limits<F_TYPE>::infinity(),
1643                      std::numeric_limits<I_TYPE>::max()),
1644       std::make_pair(-std::numeric_limits<F_TYPE>::infinity(),
1645                      std::numeric_limits<I_TYPE>::min()),
1646       std::make_pair(
1647           static_cast<F_TYPE>(std::numeric_limits<I_TYPE>::max()) + 1024,
1648           std::numeric_limits<I_TYPE>::max()),
1649       std::make_pair(
1650           static_cast<F_TYPE>(std::numeric_limits<I_TYPE>::min()) - 1024,
1651           std::numeric_limits<I_TYPE>::min()),
1652   };
1653   return std::vector<std::pair<F_TYPE, I_TYPE>>(&kValues[0],
1654                                                 &kValues[arraysize(kValues)]);
1655 }
1656 
1657 // Test conversion from wider to narrower types w/ out-of-range values or from
1658 // nan, inf, -inf
TEST(OUT_OF_RANGE_CVT)1659 TEST(OUT_OF_RANGE_CVT) {
1660   CcTest::InitializeVM();
1661 
1662   {  // test fvt_w_d
1663     auto i_vec = out_of_range_test_values<double, int32_t>();
1664     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1665       auto input = *i;
1666       auto fn = [](MacroAssembler& assm) { __ fcvt_w_d(a0, fa0); };
1667       auto res = GenAndRunTest<int32_t>(input.first, fn);
1668       CHECK_EQ(input.second, res);
1669     }
1670   }
1671 
1672   {  // test fvt_w_s
1673     auto i_vec = out_of_range_test_values<float, int32_t>();
1674     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1675       auto input = *i;
1676       auto fn = [](MacroAssembler& assm) { __ fcvt_w_s(a0, fa0); };
1677       auto res = GenAndRunTest<int32_t>(input.first, fn);
1678       CHECK_EQ(input.second, res);
1679     }
1680   }
1681 
1682   {  // test fvt_wu_d
1683     auto i_vec = out_of_range_test_values<double, uint32_t>();
1684     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1685       auto input = *i;
1686       auto fn = [](MacroAssembler& assm) { __ fcvt_wu_d(a0, fa0); };
1687       auto res = GenAndRunTest<uint32_t>(input.first, fn);
1688       CHECK_EQ(input.second, res);
1689     }
1690   }
1691 
1692   {  // test fvt_wu_s
1693     auto i_vec = out_of_range_test_values<float, uint32_t>();
1694     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1695       auto input = *i;
1696       auto fn = [](MacroAssembler& assm) { __ fcvt_wu_s(a0, fa0); };
1697       auto res = GenAndRunTest<uint32_t>(input.first, fn);
1698       CHECK_EQ(input.second, res);
1699     }
1700   }
1701 
1702   {  // test fvt_l_d
1703     auto i_vec = out_of_range_test_values<double, int64_t>();
1704     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1705       auto input = *i;
1706       auto fn = [](MacroAssembler& assm) { __ fcvt_l_d(a0, fa0); };
1707       auto res = GenAndRunTest<int64_t>(input.first, fn);
1708       CHECK_EQ(input.second, res);
1709     }
1710   }
1711 
1712   {  // test fvt_l_s
1713     auto i_vec = out_of_range_test_values<float, int64_t>();
1714     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1715       auto input = *i;
1716       auto fn = [](MacroAssembler& assm) { __ fcvt_l_s(a0, fa0); };
1717       auto res = GenAndRunTest<int64_t>(input.first, fn);
1718       CHECK_EQ(input.second, res);
1719     }
1720   }
1721 
1722   {  // test fvt_lu_d
1723     auto i_vec = out_of_range_test_values<double, uint64_t>();
1724     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1725       auto input = *i;
1726       auto fn = [](MacroAssembler& assm) { __ fcvt_lu_d(a0, fa0); };
1727       auto res = GenAndRunTest<uint64_t>(input.first, fn);
1728       CHECK_EQ(input.second, res);
1729     }
1730   }
1731 
1732   {  // test fvt_lu_s
1733     auto i_vec = out_of_range_test_values<float, uint64_t>();
1734     for (auto i = i_vec.begin(); i != i_vec.end(); ++i) {
1735       auto input = *i;
1736       auto fn = [](MacroAssembler& assm) { __ fcvt_lu_s(a0, fa0); };
1737       auto res = GenAndRunTest<uint64_t>(input.first, fn);
1738       CHECK_EQ(input.second, res);
1739     }
1740   }
1741 }
1742 
1743 #define FCMP_TEST_HELPER(F, fn, op)                                         \
1744   {                                                                         \
1745     auto res1 = GenAndRunTest<int32_t>(std::numeric_limits<F>::quiet_NaN(), \
1746                                        static_cast<F>(1.0), fn);            \
1747     CHECK_EQ(false, res1);                                                  \
1748     auto res2 =                                                             \
1749         GenAndRunTest<int32_t>(std::numeric_limits<F>::quiet_NaN(),         \
1750                                std::numeric_limits<F>::quiet_NaN(), fn);    \
1751     CHECK_EQ(false, res2);                                                  \
1752     auto res3 =                                                             \
1753         GenAndRunTest<int32_t>(std::numeric_limits<F>::signaling_NaN(),     \
1754                                std::numeric_limits<F>::quiet_NaN(), fn);    \
1755     CHECK_EQ(false, res3);                                                  \
1756     auto res4 =                                                             \
1757         GenAndRunTest<int32_t>(std::numeric_limits<F>::quiet_NaN(),         \
1758                                std::numeric_limits<F>::infinity(), fn);     \
1759     CHECK_EQ(false, res4);                                                  \
1760     auto res5 =                                                             \
1761         GenAndRunTest<int32_t>(std::numeric_limits<F>::infinity(),          \
1762                                std::numeric_limits<F>::infinity(), fn);     \
1763     CHECK_EQ((std::numeric_limits<F>::infinity()                            \
1764                   op std::numeric_limits<F>::infinity()),                   \
1765              res5);                                                         \
1766     auto res6 =                                                             \
1767         GenAndRunTest<int32_t>(-std::numeric_limits<F>::infinity(),         \
1768                                std::numeric_limits<F>::infinity(), fn);     \
1769     CHECK_EQ((-std::numeric_limits<F>::infinity()                           \
1770                   op std::numeric_limits<F>::infinity()),                   \
1771              res6);                                                         \
1772   }
1773 
TEST(F_NAN)1774 TEST(F_NAN) {
1775   // test floating-point compare w/ NaN, +/-Inf
1776   CcTest::InitializeVM();
1777 
1778   // floating compare
1779   auto fn1 = [](MacroAssembler& assm) { __ feq_s(a0, fa0, fa1); };
1780   FCMP_TEST_HELPER(float, fn1, ==);
1781   auto fn2 = [](MacroAssembler& assm) { __ flt_s(a0, fa0, fa1); };
1782   FCMP_TEST_HELPER(float, fn2, <);
1783   auto fn3 = [](MacroAssembler& assm) { __ fle_s(a0, fa0, fa1); };
1784   FCMP_TEST_HELPER(float, fn3, <=);
1785 
1786   // double compare
1787   auto fn4 = [](MacroAssembler& assm) { __ feq_d(a0, fa0, fa1); };
1788   FCMP_TEST_HELPER(double, fn4, ==);
1789   auto fn5 = [](MacroAssembler& assm) { __ flt_d(a0, fa0, fa1); };
1790   FCMP_TEST_HELPER(double, fn5, <);
1791   auto fn6 = [](MacroAssembler& assm) { __ fle_d(a0, fa0, fa1); };
1792   FCMP_TEST_HELPER(double, fn6, <=);
1793 }
1794 
TEST(jump_tables1)1795 TEST(jump_tables1) {
1796   // Test jump tables with forward jumps.
1797   CcTest::InitializeVM();
1798   Isolate* isolate = CcTest::i_isolate();
1799   HandleScope scope(isolate);
1800 
1801   const int kNumCases = 128;
1802   int values[kNumCases];
1803   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1804   Label labels[kNumCases], done;
1805 
1806   auto fn = [&labels, &done, values](MacroAssembler& assm) {
1807     __ addi(sp, sp, -8);
1808     __ Sd(ra, MemOperand(sp));
1809     __ Align(8);
1810     {
1811       __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
1812 
1813       __ auipc(ra, 0);
1814       __ slli(t3, a0, 3);
1815       __ add(t3, t3, ra);
1816       __ Ld(t3, MemOperand(t3, 6 * kInstrSize));
1817       __ jr(t3);
1818       __ nop();  // For 16-byte alignment
1819       for (int i = 0; i < kNumCases; ++i) {
1820         __ dd(&labels[i]);
1821       }
1822     }
1823 
1824     for (int i = 0; i < kNumCases; ++i) {
1825       __ bind(&labels[i]);
1826       __ RV_li(a0, values[i]);
1827       __ j(&done);
1828     }
1829 
1830     __ bind(&done);
1831     __ Ld(ra, MemOperand(sp));
1832     __ addi(sp, sp, 8);
1833 
1834     CHECK_EQ(0, assm.UnboundLabelsCount());
1835   };
1836   auto f = AssembleCode<F1>(fn);
1837 
1838   for (int i = 0; i < kNumCases; ++i) {
1839     int64_t res = reinterpret_cast<int64_t>(f.Call(i, 0, 0, 0, 0));
1840     CHECK_EQ(values[i], static_cast<int>(res));
1841   }
1842 }
1843 
TEST(jump_tables2)1844 TEST(jump_tables2) {
1845   // Test jump tables with backward jumps.
1846   CcTest::InitializeVM();
1847   Isolate* isolate = CcTest::i_isolate();
1848   HandleScope scope(isolate);
1849 
1850   const int kNumCases = 128;
1851   int values[kNumCases];
1852   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1853   Label labels[kNumCases], done, dispatch;
1854 
1855   auto fn = [&labels, &done, &dispatch, values](MacroAssembler& assm) {
1856     __ addi(sp, sp, -8);
1857     __ Sd(ra, MemOperand(sp));
1858     __ j(&dispatch);
1859 
1860     for (int i = 0; i < kNumCases; ++i) {
1861       __ bind(&labels[i]);
1862       __ RV_li(a0, values[i]);
1863       __ j(&done);
1864     }
1865 
1866     __ Align(8);
1867     __ bind(&dispatch);
1868 
1869     {
1870       __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
1871 
1872       __ auipc(ra, 0);
1873       __ slli(t3, a0, 3);
1874       __ add(t3, t3, ra);
1875       __ Ld(t3, MemOperand(t3, 6 * kInstrSize));
1876       __ jr(t3);
1877       __ nop();  // For 16-byte alignment
1878       for (int i = 0; i < kNumCases; ++i) {
1879         __ dd(&labels[i]);
1880       }
1881     }
1882     __ bind(&done);
1883     __ Ld(ra, MemOperand(sp));
1884     __ addi(sp, sp, 8);
1885   };
1886   auto f = AssembleCode<F1>(fn);
1887 
1888   for (int i = 0; i < kNumCases; ++i) {
1889     int64_t res = reinterpret_cast<int64_t>(f.Call(i, 0, 0, 0, 0));
1890     CHECK_EQ(values[i], res);
1891   }
1892 }
1893 
TEST(jump_tables3)1894 TEST(jump_tables3) {
1895   // Test jump tables with backward jumps and embedded heap objects.
1896   CcTest::InitializeVM();
1897   Isolate* isolate = CcTest::i_isolate();
1898   HandleScope scope(isolate);
1899 
1900   const int kNumCases = 128;
1901   Handle<Object> values[kNumCases];
1902   for (int i = 0; i < kNumCases; ++i) {
1903     double value = isolate->random_number_generator()->NextDouble();
1904     values[i] = isolate->factory()->NewHeapNumber<AllocationType::kOld>(value);
1905   }
1906   Label labels[kNumCases], done, dispatch;
1907   Object obj;
1908   int64_t imm64;
1909 
1910   auto fn = [&labels, &done, &dispatch, values, &obj,
1911              &imm64](MacroAssembler& assm) {
1912     __ addi(sp, sp, -8);
1913     __ Sd(ra, MemOperand(sp));
1914 
1915     __ j(&dispatch);
1916 
1917     for (int i = 0; i < kNumCases; ++i) {
1918       __ bind(&labels[i]);
1919       obj = *values[i];
1920       imm64 = obj.ptr();
1921       __ nop();  // For 8 byte alignment
1922       __ RV_li(a0, imm64);
1923       __ nop();  // For 8 byte alignment
1924       __ j(&done);
1925     }
1926 
1927     __ bind(&dispatch);
1928     {
1929       __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
1930       __ Align(8);
1931       __ auipc(ra, 0);
1932       __ slli(t3, a0, 3);
1933       __ add(t3, t3, ra);
1934       __ Ld(t3, MemOperand(t3, 6 * kInstrSize));
1935       __ jr(t3);
1936       __ nop();  // For 16-byte alignment
1937       for (int i = 0; i < kNumCases; ++i) {
1938         __ dd(&labels[i]);
1939       }
1940     }
1941 
1942     __ bind(&done);
1943     __ Ld(ra, MemOperand(sp));
1944     __ addi(sp, sp, 8);
1945   };
1946   auto f = AssembleCode<F1>(fn);
1947 
1948   for (int i = 0; i < kNumCases; ++i) {
1949     Handle<Object> result(
1950         Object(reinterpret_cast<Address>(f.Call(i, 0, 0, 0, 0))), isolate);
1951 #ifdef OBJECT_PRINT
1952     ::printf("f(%d) = ", i);
1953     result->Print(std::cout);
1954     ::printf("\n");
1955 #endif
1956     CHECK(values[i].is_identical_to(result));
1957   }
1958 }
1959 
TEST(li_estimate)1960 TEST(li_estimate) {
1961   std::vector<int64_t> immediates = {
1962       -256,      -255,          0,         255,        8192,      0x7FFFFFFF,
1963       INT32_MIN, INT32_MAX / 2, INT32_MAX, UINT32_MAX, INT64_MAX, INT64_MAX / 2,
1964       INT64_MIN};
1965   // Test jump tables with backward jumps and embedded heap objects.
1966   CcTest::InitializeVM();
1967   Isolate* isolate = CcTest::i_isolate();
1968   HandleScope scope(isolate);
1969   MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1970   for (auto p : immediates) {
1971     Label a;
1972     assm.bind(&a);
1973     assm.RV_li(t0, p);
1974     int expected_count = assm.li_estimate(p, true);
1975     int count = assm.InstructionsGeneratedSince(&a);
1976     CHECK_EQ(count, expected_count);
1977   }
1978 }
1979 
1980 #define UTEST_LOAD_STORE_RVV(ldname, stname, SEW, arg...)            \
1981   TEST(RISCV_UTEST_##stname##ldname##SEW) {                          \
1982     CcTest::InitializeVM();                                          \
1983     Isolate* isolate = CcTest::i_isolate();                          \
1984     HandleScope scope(isolate);                                      \
1985     int8_t src[16] = {arg};                                          \
1986     int8_t dst[16];                                                  \
1987     auto fn = [](MacroAssembler& assm) {                             \
1988       __ VU.set(t0, SEW, Vlmul::m1);                                 \
1989       __ vl(v2, a0, 0, VSew::E8);                                    \
1990       __ vs(v2, a1, 0, VSew::E8);                                    \
1991     };                                                               \
1992     GenAndRunTest<int32_t, int64_t>((int64_t)src, (int64_t)dst, fn); \
1993     CHECK(!memcmp(src, dst, sizeof(src)));                           \
1994   }
1995 
1996 #ifdef CAN_USE_RVV_INSTRUCTIONS
1997 UTEST_LOAD_STORE_RVV(vl, vs, E8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1998                      15, 16)
1999 // UTEST_LOAD_STORE_RVV(vl, vs, E8, 127, 127, 127, 127, 127, 127, 127)
2000 
TEST(RVV_VSETIVLI)2001 TEST(RVV_VSETIVLI) {
2002   CcTest::InitializeVM();
2003   Isolate* isolate = CcTest::i_isolate();
2004   HandleScope scope(isolate);
2005   auto fn = [](MacroAssembler& assm) {
2006     __ VU.set(t0, VSew::E8, Vlmul::m1);
2007     __ vsetivli(t0, 16, VSew::E128, Vlmul::m1);
2008   };
2009   GenAndRunTest(fn);
2010 }
2011 #endif
2012 
2013 #undef __
2014 
2015 }  // namespace internal
2016 }  // namespace v8
2017