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