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 <iostream>
29
30 #include "src/base/utils/random-number-generator.h"
31 #include "src/codegen/assembler-inl.h"
32 #include "src/codegen/macro-assembler.h"
33 #include "src/diagnostics/disassembler.h"
34 #include "src/execution/simulator.h"
35 #include "src/heap/factory.h"
36 #include "src/init/v8.h"
37 #include "test/cctest/cctest.h"
38
39 namespace v8 {
40 namespace internal {
41
42 // Define these function prototypes to match JSEntryFunction in execution.cc.
43 // TODO(LOONG64): Refine these signatures per test case.
44 using F1 = void*(int x, int p1, int p2, int p3, int p4);
45 using F2 = void*(int x, int y, int p2, int p3, int p4);
46 using F3 = void*(void* p, int p1, int p2, int p3, int p4);
47 using F4 = void*(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4);
48 using F5 = void*(void* p0, void* p1, int p2, int p3, int p4);
49
50 #define __ assm.
51 // v0->a2, v1->a3
TEST(LA0)52 TEST(LA0) {
53 CcTest::InitializeVM();
54 Isolate* isolate = CcTest::i_isolate();
55 HandleScope scope(isolate);
56
57 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
58
59 // Addition.
60 __ addi_d(a2, a0, 0xC);
61
62 __ or_(a0, a2, zero_reg);
63 __ jirl(zero_reg, ra, 0);
64
65 CodeDesc desc;
66 assm.GetCode(isolate, &desc);
67 Handle<Code> code =
68 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
69 auto f = GeneratedCode<F2>::FromCode(*code);
70 int64_t res = reinterpret_cast<int64_t>(f.Call(0xAB0, 0, 0, 0, 0));
71 CHECK_EQ(0xABCL, res);
72 }
73
TEST(LA1)74 TEST(LA1) {
75 CcTest::InitializeVM();
76 Isolate* isolate = CcTest::i_isolate();
77 HandleScope scope(isolate);
78
79 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
80 Label L, C;
81
82 __ ori(a1, a0, 0);
83 __ ori(a2, zero_reg, 0);
84 __ b(&C);
85
86 __ bind(&L);
87 __ add_d(a2, a2, a1);
88 __ addi_d(a1, a1, -1);
89
90 __ bind(&C);
91 __ ori(a3, a1, 0);
92
93 __ Branch(&L, ne, a3, Operand((int64_t)0));
94
95 __ or_(a0, a2, zero_reg);
96 __ or_(a1, a3, zero_reg);
97 __ jirl(zero_reg, ra, 0);
98
99 CodeDesc desc;
100 assm.GetCode(isolate, &desc);
101 Handle<Code> code =
102 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
103 auto f = GeneratedCode<F1>::FromCode(*code);
104 int64_t res = reinterpret_cast<int64_t>(f.Call(50, 0, 0, 0, 0));
105 CHECK_EQ(1275L, res);
106 }
107
TEST(LA2)108 TEST(LA2) {
109 CcTest::InitializeVM();
110 Isolate* isolate = CcTest::i_isolate();
111 HandleScope scope(isolate);
112
113 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
114
115 Label exit, error;
116
117 __ ori(a4, zero_reg, 0); // 00000000
118 __ lu12i_w(a4, 0x12345); // 12345000
119 __ ori(a4, a4, 0); // 12345000
120 __ ori(a2, a4, 0xF0F); // 12345F0F
121 __ Branch(&error, ne, a2, Operand(0x12345F0F));
122
123 __ ori(a4, zero_reg, 0);
124 __ lu32i_d(a4, 0x12345); // 1 2345 0000 0000
125 __ ori(a4, a4, 0xFFF); // 1 2345 0000 0FFF
126 __ addi_d(a2, a4, 1);
127 __ Branch(&error, ne, a2, Operand(0x1234500001000));
128
129 __ ori(a4, zero_reg, 0);
130 __ lu52i_d(a4, zero_reg, 0x123); // 1230 0000 0000 0000
131 __ ori(a4, a4, 0xFFF); // 123F 0000 0000 0FFF
132 __ addi_d(a2, a4, 1); // 1230 0000 0000 1000
133 __ Branch(&error, ne, a2, Operand(0x1230000000001000));
134
135 __ li(a2, 0x31415926);
136 __ b(&exit);
137
138 __ bind(&error);
139 __ li(a2, 0x666);
140
141 __ bind(&exit);
142 __ or_(a0, a2, zero_reg);
143 __ jirl(zero_reg, ra, 0);
144
145 CodeDesc desc;
146 assm.GetCode(isolate, &desc);
147 Handle<Code> code =
148 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
149 auto f = GeneratedCode<F2>::FromCode(*code);
150 int64_t res = reinterpret_cast<int64_t>(f.Call(0, 0, 0, 0, 0));
151
152 CHECK_EQ(0x31415926L, res);
153 }
154
TEST(LA3)155 TEST(LA3) {
156 // Test 32bit calculate instructions.
157 CcTest::InitializeVM();
158 Isolate* isolate = CcTest::i_isolate();
159 HandleScope scope(isolate);
160 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
161
162 Label exit, error;
163
164 __ li(a4, 0x00000004);
165 __ li(a5, 0x00001234);
166 __ li(a6, 0x12345678);
167 __ li(a7, 0x7FFFFFFF);
168 __ li(t0, static_cast<int32_t>(0xFFFFFFFC));
169 __ li(t1, static_cast<int32_t>(0xFFFFEDCC));
170 __ li(t2, static_cast<int32_t>(0xEDCBA988));
171 __ li(t3, static_cast<int32_t>(0x80000000));
172
173 __ ori(a2, zero_reg, 0); // 0x00000000
174 __ add_w(a2, a4, a5); // 0x00001238
175 __ sub_w(a2, a2, a4); // 0x00001234
176 __ Branch(&error, ne, a2, Operand(0x00001234));
177 __ ori(a3, zero_reg, 0); // 0x00000000
178 __ add_w(a3, a7, a4); // 32bit addu result is sign-extended into 64bit reg.
179 __ Branch(&error, ne, a3, Operand(0xFFFFFFFF80000003));
180
181 __ sub_w(a3, t3, a4); // 0x7FFFFFFC
182 __ Branch(&error, ne, a3, Operand(0x7FFFFFFC));
183
184 __ ori(a2, zero_reg, 0); // 0x00000000
185 __ ori(a3, zero_reg, 0); // 0x00000000
186 __ addi_w(a2, zero_reg, 0x421); // 0x00007421
187 __ addi_w(a2, a2, -0x1); // 0x00007420
188 __ addi_w(a2, a2, -0x20); // 0x00007400
189 __ Branch(&error, ne, a2, Operand(0x0000400));
190 __ addi_w(a3, a7, 0x1); // 0x80000000 - result is sign-extended.
191 __ Branch(&error, ne, a3, Operand(0xFFFFFFFF80000000));
192
193 __ ori(a2, zero_reg, 0); // 0x00000000
194 __ ori(a3, zero_reg, 0); // 0x00000000
195 __ alsl_w(a2, a6, a4, 3); // 0xFFFFFFFF91A2B3C4
196 __ alsl_w(a2, a2, a4, 2); // 0x468ACF14
197 __ Branch(&error, ne, a2, Operand(0x468acf14));
198 __ ori(a0, zero_reg, 31);
199 __ alsl_wu(a3, a6, a4, 3); // 0x91A2B3C4
200 __ alsl_wu(a3, a3, a7, 1); // 0xFFFFFFFFA3456787
201 __ Branch(&error, ne, a3, Operand(0xA3456787));
202
203 __ ori(a2, zero_reg, 0);
204 __ ori(a3, zero_reg, 0);
205 __ mul_w(a2, a5, a7);
206 __ div_w(a2, a2, a4);
207 __ Branch(&error, ne, a2, Operand(0xFFFFFFFFFFFFFB73));
208 __ mul_w(a3, a4, t1);
209 __ Branch(&error, ne, a3, Operand(0xFFFFFFFFFFFFB730));
210 __ div_w(a3, t3, a4);
211 __ Branch(&error, ne, a3, Operand(0xFFFFFFFFE0000000));
212
213 __ ori(a2, zero_reg, 0);
214 __ mulh_w(a2, a4, t1);
215 __ Branch(&error, ne, a2, Operand(0xFFFFFFFFFFFFFFFF));
216 __ mulh_w(a2, a4, a6);
217 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
218
219 __ ori(a2, zero_reg, 0);
220 __ mulh_wu(a2, a4, t1);
221 __ Branch(&error, ne, a2, Operand(0x3));
222 __ mulh_wu(a2, a4, a6);
223 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
224
225 __ ori(a2, zero_reg, 0);
226 __ mulw_d_w(a2, a4, t1);
227 __ Branch(&error, ne, a2, Operand(0xFFFFFFFFFFFFB730));
228 __ mulw_d_w(a2, a4, a6);
229 __ Branch(&error, ne, a2, Operand(0x48D159E0));
230
231 __ ori(a2, zero_reg, 0);
232 __ mulw_d_wu(a2, a4, t1);
233 __ Branch(&error, ne, a2, Operand(0x3FFFFB730)); //========0xFFFFB730
234 __ ori(a2, zero_reg, 81);
235 __ mulw_d_wu(a2, a4, a6);
236 __ Branch(&error, ne, a2, Operand(0x48D159E0));
237
238 __ ori(a2, zero_reg, 0);
239 __ div_wu(a2, a7, a5);
240 __ Branch(&error, ne, a2, Operand(0x70821));
241 __ div_wu(a2, t0, a5);
242 __ Branch(&error, ne, a2, Operand(0xE1042));
243 __ div_wu(a2, t0, t1);
244 __ Branch(&error, ne, a2, Operand(0x1));
245
246 __ ori(a2, zero_reg, 0);
247 __ mod_w(a2, a6, a5);
248 __ Branch(&error, ne, a2, Operand(0xDA8));
249 __ ori(a2, zero_reg, 0);
250 __ mod_w(a2, t2, a5);
251 __ Branch(&error, ne, a2, Operand(0xFFFFFFFFFFFFF258));
252 __ ori(a2, zero_reg, 0);
253 __ mod_w(a2, t2, t1);
254 __ Branch(&error, ne, a2, Operand(0xFFFFFFFFFFFFF258));
255
256 __ ori(a2, zero_reg, 0);
257 __ mod_wu(a2, a6, a5);
258 __ Branch(&error, ne, a2, Operand(0xDA8));
259 __ mod_wu(a2, t2, a5);
260 __ Branch(&error, ne, a2, Operand(0xF0));
261 __ mod_wu(a2, t2, t1);
262 __ Branch(&error, ne, a2, Operand(0xFFFFFFFFEDCBA988));
263
264 __ li(a2, 0x31415926);
265 __ b(&exit);
266
267 __ bind(&error);
268 __ li(a2, 0x666);
269
270 __ bind(&exit);
271 __ or_(a0, a2, zero_reg);
272 __ jirl(zero_reg, ra, 0);
273
274 CodeDesc desc;
275 assm.GetCode(isolate, &desc);
276 Handle<Code> code =
277 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
278 auto f = GeneratedCode<F2>::FromCode(*code);
279 int64_t res = reinterpret_cast<int64_t>(f.Call(0, 0, 0, 0, 0));
280
281 CHECK_EQ(0x31415926L, res);
282 }
283
TEST(LA4)284 TEST(LA4) {
285 // Test 64bit calculate instructions.
286 CcTest::InitializeVM();
287 Isolate* isolate = CcTest::i_isolate();
288 HandleScope scope(isolate);
289 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
290
291 Label exit, error;
292
293 __ li(a4, 0x17312);
294 __ li(a5, 0x1012131415161718);
295 __ li(a6, 0x51F4B764A26E7412);
296 __ li(a7, 0x7FFFFFFFFFFFFFFF);
297 __ li(t0, static_cast<int64_t>(0xFFFFFFFFFFFFF547));
298 __ li(t1, static_cast<int64_t>(0xDF6B8F35A10E205C));
299 __ li(t2, static_cast<int64_t>(0x81F25A87C4236841));
300 __ li(t3, static_cast<int64_t>(0x8000000000000000));
301
302 __ ori(a2, zero_reg, 0);
303 __ add_d(a2, a4, a5);
304 __ sub_d(a2, a2, a4);
305 __ Branch(&error, ne, a2, Operand(0x1012131415161718));
306 __ ori(a3, zero_reg, 0);
307 __ add_d(a3, a6, a7); //溢出
308 __ Branch(&error, ne, a3, Operand(0xd1f4b764a26e7411));
309 __ sub_d(a3, t3, a4); //溢出
310 __ Branch(&error, ne, a3, Operand(0x7ffffffffffe8cee));
311
312 __ ori(a2, zero_reg, 0);
313 __ addi_d(a2, a5, 0x412); //正值
314 __ Branch(&error, ne, a2, Operand(0x1012131415161b2a));
315 __ addi_d(a2, a7, 0x547); //负值
316 __ Branch(&error, ne, a2, Operand(0x8000000000000546));
317
318 __ ori(t4, zero_reg, 0);
319 __ addu16i_d(a2, t4, 0x1234);
320 __ Branch(&error, ne, a2, Operand(0x12340000));
321 __ addu16i_d(a2, a2, 0x9876);
322 __ Branch(&error, ne, a2, Operand(0xffffffffaaaa0000));
323
324 __ ori(a2, zero_reg, 0);
325 __ alsl_d(a2, t2, t0, 3);
326 __ Branch(&error, ne, a2, Operand(0xf92d43e211b374f));
327
328 __ ori(a2, zero_reg, 0);
329 __ mul_d(a2, a5, a6);
330 __ Branch(&error, ne, a2, Operand(0xdbe6a8729a547fb0));
331 __ mul_d(a2, t0, t1);
332 __ Branch(&error, ne, a2, Operand(0x57ad69f40f870584));
333 __ mul_d(a2, a4, t0);
334 __ Branch(&error, ne, a2, Operand(0xfffffffff07523fe));
335
336 __ ori(a2, zero_reg, 0);
337 __ mulh_d(a2, a5, a6);
338 __ Branch(&error, ne, a2, Operand(0x52514c6c6b54467));
339 __ mulh_d(a2, t0, t1);
340 __ Branch(&error, ne, a2, Operand(0x15d));
341
342 __ ori(a2, zero_reg, 0);
343 __ mulh_du(a2, a5, a6);
344 __ Branch(&error, ne, a2, Operand(0x52514c6c6b54467));
345 __ mulh_du(a2, t0, t1);
346 __ Branch(&error, ne, a2, Operand(0xdf6b8f35a10e1700));
347 __ mulh_du(a2, a4, t0);
348 __ Branch(&error, ne, a2, Operand(0x17311));
349
350 __ ori(a2, zero_reg, 0);
351 __ div_d(a2, a5, a6);
352 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
353 __ div_d(a2, t0, t1);
354 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
355 __ div_d(a2, t1, a4);
356 __ Branch(&error, ne, a2, Operand(0xffffe985f631e6d9));
357
358 __ ori(a2, zero_reg, 0);
359 __ div_du(a2, a5, a6);
360 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
361 __ div_du(a2, t0, t1);
362 __ Branch(&error, ne, a2, Operand(0x1));
363 __ div_du(a2, t1, a4);
364 __ Branch(&error, ne, a2, Operand(0x9a22ffd3973d));
365
366 __ ori(a2, zero_reg, 0);
367 __ mod_d(a2, a6, a4);
368 __ Branch(&error, ne, a2, Operand(0x13558));
369 __ mod_d(a2, t2, t0);
370 __ Branch(&error, ne, a2, Operand(0xfffffffffffffb0a));
371 __ mod_d(a2, t1, a4);
372 __ Branch(&error, ne, a2, Operand(0xffffffffffff6a1a));
373
374 __ ori(a2, zero_reg, 0);
375 __ mod_du(a2, a6, a4);
376 __ Branch(&error, ne, a2, Operand(0x13558));
377 __ mod_du(a2, t2, t0);
378 __ Branch(&error, ne, a2, Operand(0x81f25a87c4236841));
379 __ mod_du(a2, t1, a4);
380 __ Branch(&error, ne, a2, Operand(0x1712));
381
382 // Everything was correctly executed. Load the expected result.
383 __ li(a2, 0x31415926);
384 __ b(&exit);
385
386 __ bind(&error);
387 __ li(a2, 0x666);
388 // Got an error. Return a wrong result.
389
390 __ bind(&exit);
391 __ or_(a0, a2, zero_reg);
392 __ jirl(zero_reg, ra, 0);
393
394 CodeDesc desc;
395 assm.GetCode(isolate, &desc);
396 Handle<Code> code =
397 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
398 auto f = GeneratedCode<F2>::FromCode(*code);
399 int64_t res = reinterpret_cast<int64_t>(f.Call(0, 0, 0, 0, 0));
400
401 CHECK_EQ(0x31415926L, res);
402 }
403
TEST(LA5)404 TEST(LA5) {
405 CcTest::InitializeVM();
406 Isolate* isolate = CcTest::i_isolate();
407 HandleScope scope(isolate);
408 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
409
410 Label exit, error;
411
412 __ li(a4, 0x17312);
413 __ li(a5, 0x1012131415161718);
414 __ li(a6, 0x51F4B764A26E7412);
415 __ li(a7, 0x7FFFFFFFFFFFFFFF);
416 __ li(t0, static_cast<int64_t>(0xFFFFFFFFFFFFF547));
417 __ li(t1, static_cast<int64_t>(0xDF6B8F35A10E205C));
418 __ li(t2, static_cast<int64_t>(0x81F25A87C4236841));
419 __ li(t3, static_cast<int64_t>(0x8000000000000000));
420
421 __ ori(a2, zero_reg, 0);
422 __ slt(a2, a5, a6);
423 __ Branch(&error, ne, a2, Operand(0x1));
424 __ slt(a2, a7, t0);
425 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
426 __ slt(a2, t1, t1);
427 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
428
429 __ ori(a2, zero_reg, 0);
430 __ sltu(a2, a5, a6);
431 __ Branch(&error, ne, a2, Operand(0x1));
432 __ sltu(a2, a7, t0);
433 __ Branch(&error, ne, a2, Operand(0x1));
434 __ sltu(a2, t1, t1);
435 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
436
437 __ ori(a2, zero_reg, 0);
438 __ slti(a2, a5, 0x123);
439 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
440 __ slti(a2, t0, 0x123);
441 __ Branch(&error, ne, a2, Operand(0x1));
442
443 __ ori(a2, zero_reg, 0);
444 __ sltui(a2, a5, 0x123);
445 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
446 __ sltui(a2, t0, 0x123);
447 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
448
449 __ ori(a2, zero_reg, 0);
450 __ and_(a2, a4, a5);
451 __ Branch(&error, ne, a2, Operand(0x1310));
452 __ and_(a2, a6, a7);
453 __ Branch(&error, ne, a2, Operand(0x51F4B764A26E7412));
454
455 __ ori(a2, zero_reg, 0);
456 __ or_(a2, t0, t1);
457 __ Branch(&error, ne, a2, Operand(0xfffffffffffff55f));
458 __ or_(a2, t2, t3);
459 __ Branch(&error, ne, a2, Operand(0x81f25a87c4236841));
460
461 __ ori(a2, zero_reg, 0);
462 __ nor(a2, a4, a5);
463 __ Branch(&error, ne, a2, Operand(0xefedecebeae888e5));
464 __ nor(a2, a6, a7);
465 __ Branch(&error, ne, a2, Operand(0x8000000000000000));
466
467 __ ori(a2, zero_reg, 0);
468 __ xor_(a2, t0, t1);
469 __ Branch(&error, ne, a2, Operand(0x209470ca5ef1d51b));
470 __ xor_(a2, t2, t3);
471 __ Branch(&error, ne, a2, Operand(0x1f25a87c4236841));
472
473 __ ori(a2, zero_reg, 0);
474 __ andn(a2, a4, a5);
475 __ Branch(&error, ne, a2, Operand(0x16002));
476 __ andn(a2, a6, a7);
477 __ Branch(&error, ne, a2, Operand(static_cast<int64_t>(0)));
478
479 __ ori(a2, zero_reg, 0);
480 __ orn(a2, t0, t1);
481 __ Branch(&error, ne, a2, Operand(0xffffffffffffffe7));
482 __ orn(a2, t2, t3);
483 __ Branch(&error, ne, a2, Operand(0xffffffffffffffff));
484
485 __ ori(a2, zero_reg, 0);
486 __ andi(a2, a4, 0x123);
487 __ Branch(&error, ne, a2, Operand(0x102));
488 __ andi(a2, a6, 0xDCB);
489 __ Branch(&error, ne, a2, Operand(0x402));
490
491 __ ori(a2, zero_reg, 0);
492 __ xori(a2, t0, 0x123);
493 __ Branch(&error, ne, a2, Operand(0xfffffffffffff464));
494 __ xori(a2, t2, 0xDCB);
495 __ Branch(&error, ne, a2, Operand(0x81f25a87c423658a));
496
497 // Everything was correctly executed. Load the expected result.
498 __ li(a2, 0x31415926);
499 __ b(&exit);
500
501 __ bind(&error);
502 // Got an error. Return a wrong result.
503 __ li(a2, 0x666);
504
505 __ bind(&exit);
506 __ or_(a0, a2, zero_reg);
507 __ jirl(zero_reg, ra, 0);
508
509 CodeDesc desc;
510 assm.GetCode(isolate, &desc);
511 Handle<Code> code =
512 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
513 auto f = GeneratedCode<F2>::FromCode(*code);
514 int64_t res = reinterpret_cast<int64_t>(f.Call(0, 0, 0, 0, 0));
515
516 CHECK_EQ(0x31415926L, res);
517 }
518
TEST(LA6)519 TEST(LA6) {
520 // Test loads and stores instruction.
521 CcTest::InitializeVM();
522 Isolate* isolate = CcTest::i_isolate();
523 HandleScope scope(isolate);
524 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
525
526 struct T {
527 int64_t si1;
528 int64_t si2;
529 int64_t si3;
530 int64_t result_ld_b_si1;
531 int64_t result_ld_b_si2;
532 int64_t result_ld_h_si1;
533 int64_t result_ld_h_si2;
534 int64_t result_ld_w_si1;
535 int64_t result_ld_w_si2;
536 int64_t result_ld_d_si1;
537 int64_t result_ld_d_si3;
538 int64_t result_ld_bu_si2;
539 int64_t result_ld_hu_si2;
540 int64_t result_ld_wu_si2;
541 int64_t result_st_b;
542 int64_t result_st_h;
543 int64_t result_st_w;
544 };
545 T t;
546
547 // Ld_b
548 __ Ld_b(a4, MemOperand(a0, offsetof(T, si1)));
549 __ St_d(a4, MemOperand(a0, offsetof(T, result_ld_b_si1)));
550
551 __ Ld_b(a4, MemOperand(a0, offsetof(T, si2)));
552 __ St_d(a4, MemOperand(a0, offsetof(T, result_ld_b_si2)));
553
554 // Ld_h
555 __ Ld_h(a5, MemOperand(a0, offsetof(T, si1)));
556 __ St_d(a5, MemOperand(a0, offsetof(T, result_ld_h_si1)));
557
558 __ Ld_h(a5, MemOperand(a0, offsetof(T, si2)));
559 __ St_d(a5, MemOperand(a0, offsetof(T, result_ld_h_si2)));
560
561 // Ld_w
562 __ Ld_w(a6, MemOperand(a0, offsetof(T, si1)));
563 __ St_d(a6, MemOperand(a0, offsetof(T, result_ld_w_si1)));
564
565 __ Ld_w(a6, MemOperand(a0, offsetof(T, si2)));
566 __ St_d(a6, MemOperand(a0, offsetof(T, result_ld_w_si2)));
567
568 // Ld_d
569 __ Ld_d(a7, MemOperand(a0, offsetof(T, si1)));
570 __ St_d(a7, MemOperand(a0, offsetof(T, result_ld_d_si1)));
571
572 __ Ld_d(a7, MemOperand(a0, offsetof(T, si3)));
573 __ St_d(a7, MemOperand(a0, offsetof(T, result_ld_d_si3)));
574
575 // Ld_bu
576 __ Ld_bu(t0, MemOperand(a0, offsetof(T, si2)));
577 __ St_d(t0, MemOperand(a0, offsetof(T, result_ld_bu_si2)));
578
579 // Ld_hu
580 __ Ld_hu(t1, MemOperand(a0, offsetof(T, si2)));
581 __ St_d(t1, MemOperand(a0, offsetof(T, result_ld_hu_si2)));
582
583 // Ld_wu
584 __ Ld_wu(t2, MemOperand(a0, offsetof(T, si2)));
585 __ St_d(t2, MemOperand(a0, offsetof(T, result_ld_wu_si2)));
586
587 // St
588 __ li(t4, 0x11111111);
589
590 // St_b
591 __ Ld_d(t5, MemOperand(a0, offsetof(T, si3)));
592 __ St_d(t5, MemOperand(a0, offsetof(T, result_st_b)));
593 __ St_b(t4, MemOperand(a0, offsetof(T, result_st_b)));
594
595 // St_h
596 __ Ld_d(t6, MemOperand(a0, offsetof(T, si3)));
597 __ St_d(t6, MemOperand(a0, offsetof(T, result_st_h)));
598 __ St_h(t4, MemOperand(a0, offsetof(T, result_st_h)));
599
600 // St_w
601 __ Ld_d(t7, MemOperand(a0, offsetof(T, si3)));
602 __ St_d(t7, MemOperand(a0, offsetof(T, result_st_w)));
603 __ St_w(t4, MemOperand(a0, offsetof(T, result_st_w)));
604
605 __ jirl(zero_reg, ra, 0);
606
607 CodeDesc desc;
608 assm.GetCode(isolate, &desc);
609 Handle<Code> code =
610 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
611 auto f = GeneratedCode<F3>::FromCode(*code);
612 t.si1 = 0x11223344;
613 t.si2 = 0x99AABBCC;
614 t.si3 = 0x1122334455667788;
615 f.Call(&t, 0, 0, 0, 0);
616
617 CHECK_EQ(static_cast<int64_t>(0x44), t.result_ld_b_si1);
618 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFFFFFFFCC), t.result_ld_b_si2);
619
620 CHECK_EQ(static_cast<int64_t>(0x3344), t.result_ld_h_si1);
621 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFFFFFBBCC), t.result_ld_h_si2);
622
623 CHECK_EQ(static_cast<int64_t>(0x11223344), t.result_ld_w_si1);
624 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFF99AABBCC), t.result_ld_w_si2);
625
626 CHECK_EQ(static_cast<int64_t>(0x11223344), t.result_ld_d_si1);
627 CHECK_EQ(static_cast<int64_t>(0x1122334455667788), t.result_ld_d_si3);
628
629 CHECK_EQ(static_cast<int64_t>(0xCC), t.result_ld_bu_si2);
630 CHECK_EQ(static_cast<int64_t>(0xBBCC), t.result_ld_hu_si2);
631 CHECK_EQ(static_cast<int64_t>(0x99AABBCC), t.result_ld_wu_si2);
632
633 CHECK_EQ(static_cast<int64_t>(0x1122334455667711), t.result_st_b);
634 CHECK_EQ(static_cast<int64_t>(0x1122334455661111), t.result_st_h);
635 CHECK_EQ(static_cast<int64_t>(0x1122334411111111), t.result_st_w);
636 }
637
TEST(LA7)638 TEST(LA7) {
639 CcTest::InitializeVM();
640 Isolate* isolate = CcTest::i_isolate();
641 HandleScope scope(isolate);
642 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
643
644 struct T {
645 int64_t si1;
646 int64_t si2;
647 int64_t si3;
648 int64_t result_ldx_b_si1;
649 int64_t result_ldx_b_si2;
650 int64_t result_ldx_h_si1;
651 int64_t result_ldx_h_si2;
652 int64_t result_ldx_w_si1;
653 int64_t result_ldx_w_si2;
654 int64_t result_ldx_d_si1;
655 int64_t result_ldx_d_si3;
656 int64_t result_ldx_bu_si2;
657 int64_t result_ldx_hu_si2;
658 int64_t result_ldx_wu_si2;
659 int64_t result_stx_b;
660 int64_t result_stx_h;
661 int64_t result_stx_w;
662 };
663 T t;
664
665 // ldx_b
666 __ li(a2, static_cast<int64_t>(offsetof(T, si1)));
667 __ Ld_b(a4, MemOperand(a0, a2));
668 __ St_d(a4, MemOperand(a0, offsetof(T, result_ldx_b_si1)));
669
670 __ li(a2, static_cast<int64_t>(offsetof(T, si2)));
671 __ Ld_b(a4, MemOperand(a0, a2));
672 __ St_d(a4, MemOperand(a0, offsetof(T, result_ldx_b_si2)));
673
674 // ldx_h
675 __ li(a2, static_cast<int64_t>(offsetof(T, si1)));
676 __ Ld_h(a5, MemOperand(a0, a2));
677 __ St_d(a5, MemOperand(a0, offsetof(T, result_ldx_h_si1)));
678
679 __ li(a2, static_cast<int64_t>(offsetof(T, si2)));
680 __ Ld_h(a5, MemOperand(a0, a2));
681 __ St_d(a5, MemOperand(a0, offsetof(T, result_ldx_h_si2)));
682
683 // ldx_w
684 __ li(a2, static_cast<int64_t>(offsetof(T, si1)));
685 __ Ld_w(a6, MemOperand(a0, a2));
686 __ St_d(a6, MemOperand(a0, offsetof(T, result_ldx_w_si1)));
687
688 __ li(a2, static_cast<int64_t>(offsetof(T, si2)));
689 __ Ld_w(a6, MemOperand(a0, a2));
690 __ St_d(a6, MemOperand(a0, offsetof(T, result_ldx_w_si2)));
691
692 // Ld_d
693 __ li(a2, static_cast<int64_t>(offsetof(T, si1)));
694 __ Ld_d(a7, MemOperand(a0, a2));
695 __ St_d(a7, MemOperand(a0, offsetof(T, result_ldx_d_si1)));
696
697 __ li(a2, static_cast<int64_t>(offsetof(T, si3)));
698 __ Ld_d(a7, MemOperand(a0, a2));
699 __ St_d(a7, MemOperand(a0, offsetof(T, result_ldx_d_si3)));
700
701 // Ld_bu
702 __ li(a2, static_cast<int64_t>(offsetof(T, si2)));
703 __ Ld_bu(t0, MemOperand(a0, a2));
704 __ St_d(t0, MemOperand(a0, offsetof(T, result_ldx_bu_si2)));
705
706 // Ld_hu
707 __ li(a2, static_cast<int64_t>(offsetof(T, si2)));
708 __ Ld_hu(t1, MemOperand(a0, a2));
709 __ St_d(t1, MemOperand(a0, offsetof(T, result_ldx_hu_si2)));
710
711 // Ld_wu
712 __ li(a2, static_cast<int64_t>(offsetof(T, si2)));
713 __ Ld_wu(t2, MemOperand(a0, a2));
714 __ St_d(t2, MemOperand(a0, offsetof(T, result_ldx_wu_si2)));
715
716 // St
717 __ li(t4, 0x11111111);
718
719 // St_b
720 __ Ld_d(t5, MemOperand(a0, offsetof(T, si3)));
721 __ St_d(t5, MemOperand(a0, offsetof(T, result_stx_b)));
722 __ li(a2, static_cast<int64_t>(offsetof(T, result_stx_b)));
723 __ St_b(t4, MemOperand(a0, a2));
724
725 // St_h
726 __ Ld_d(t6, MemOperand(a0, offsetof(T, si3)));
727 __ St_d(t6, MemOperand(a0, offsetof(T, result_stx_h)));
728 __ li(a2, static_cast<int64_t>(offsetof(T, result_stx_h)));
729 __ St_h(t4, MemOperand(a0, a2));
730
731 // St_w
732 __ Ld_d(t7, MemOperand(a0, offsetof(T, si3)));
733 __ li(a2, static_cast<int64_t>(offsetof(T, result_stx_w)));
734 __ St_d(t7, MemOperand(a0, a2));
735 __ li(a3, static_cast<int64_t>(offsetof(T, result_stx_w)));
736 __ St_w(t4, MemOperand(a0, a3));
737
738 __ jirl(zero_reg, ra, 0);
739
740 CodeDesc desc;
741 assm.GetCode(isolate, &desc);
742 Handle<Code> code =
743 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
744 auto f = GeneratedCode<F3>::FromCode(*code);
745 t.si1 = 0x11223344;
746 t.si2 = 0x99AABBCC;
747 t.si3 = 0x1122334455667788;
748 f.Call(&t, 0, 0, 0, 0);
749
750 CHECK_EQ(static_cast<int64_t>(0x44), t.result_ldx_b_si1);
751 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFFFFFFFCC), t.result_ldx_b_si2);
752
753 CHECK_EQ(static_cast<int64_t>(0x3344), t.result_ldx_h_si1);
754 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFFFFFBBCC), t.result_ldx_h_si2);
755
756 CHECK_EQ(static_cast<int64_t>(0x11223344), t.result_ldx_w_si1);
757 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFF99AABBCC), t.result_ldx_w_si2);
758
759 CHECK_EQ(static_cast<int64_t>(0x11223344), t.result_ldx_d_si1);
760 CHECK_EQ(static_cast<int64_t>(0x1122334455667788), t.result_ldx_d_si3);
761
762 CHECK_EQ(static_cast<int64_t>(0xCC), t.result_ldx_bu_si2);
763 CHECK_EQ(static_cast<int64_t>(0xBBCC), t.result_ldx_hu_si2);
764 CHECK_EQ(static_cast<int64_t>(0x99AABBCC), t.result_ldx_wu_si2);
765
766 CHECK_EQ(static_cast<int64_t>(0x1122334455667711), t.result_stx_b);
767 CHECK_EQ(static_cast<int64_t>(0x1122334455661111), t.result_stx_h);
768 CHECK_EQ(static_cast<int64_t>(0x1122334411111111), t.result_stx_w);
769 }
770
TEST(LDPTR_STPTR)771 TEST(LDPTR_STPTR) {
772 CcTest::InitializeVM();
773 Isolate* isolate = CcTest::i_isolate();
774 HandleScope scope(isolate);
775 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
776
777 int64_t test[10];
778
779 __ ldptr_w(a4, a0, 0);
780 __ stptr_d(a4, a0, 24); // test[3]
781
782 __ ldptr_w(a5, a0, 8); // test[1]
783 __ stptr_d(a5, a0, 32); // test[4]
784
785 __ ldptr_d(a6, a0, 16); // test[2]
786 __ stptr_d(a6, a0, 40); // test[5]
787
788 __ li(t0, 0x11111111);
789
790 __ stptr_d(a6, a0, 48); // test[6]
791 __ stptr_w(t0, a0, 48); // test[6]
792
793 __ jirl(zero_reg, ra, 0);
794
795 CodeDesc desc;
796 assm.GetCode(isolate, &desc);
797 Handle<Code> code =
798 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
799 auto f = GeneratedCode<F3>::FromCode(*code);
800 test[0] = 0x11223344;
801 test[1] = 0x99AABBCC;
802 test[2] = 0x1122334455667788;
803 f.Call(&test, 0, 0, 0, 0);
804
805 CHECK_EQ(static_cast<int64_t>(0x11223344), test[3]);
806 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFF99AABBCC), test[4]);
807 CHECK_EQ(static_cast<int64_t>(0x1122334455667788), test[5]);
808 CHECK_EQ(static_cast<int64_t>(0x1122334411111111), test[6]);
809 }
810
TEST(LA8)811 TEST(LA8) {
812 // Test 32bit shift instructions.
813 CcTest::InitializeVM();
814 Isolate* isolate = CcTest::i_isolate();
815 HandleScope scope(isolate);
816
817 struct T {
818 int32_t input;
819 int32_t result_sll_w_0;
820 int32_t result_sll_w_8;
821 int32_t result_sll_w_10;
822 int32_t result_sll_w_31;
823 int32_t result_srl_w_0;
824 int32_t result_srl_w_8;
825 int32_t result_srl_w_10;
826 int32_t result_srl_w_31;
827 int32_t result_sra_w_0;
828 int32_t result_sra_w_8;
829 int32_t result_sra_w_10;
830 int32_t result_sra_w_31;
831 int32_t result_rotr_w_0;
832 int32_t result_rotr_w_8;
833 int32_t result_slli_w_0;
834 int32_t result_slli_w_8;
835 int32_t result_slli_w_10;
836 int32_t result_slli_w_31;
837 int32_t result_srli_w_0;
838 int32_t result_srli_w_8;
839 int32_t result_srli_w_10;
840 int32_t result_srli_w_31;
841 int32_t result_srai_w_0;
842 int32_t result_srai_w_8;
843 int32_t result_srai_w_10;
844 int32_t result_srai_w_31;
845 int32_t result_rotri_w_0;
846 int32_t result_rotri_w_8;
847 int32_t result_rotri_w_10;
848 int32_t result_rotri_w_31;
849 };
850 T t;
851 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
852
853 __ Ld_w(a4, MemOperand(a0, offsetof(T, input)));
854
855 // sll_w
856 __ li(a5, 0);
857 __ sll_w(t0, a4, a5);
858 __ li(a5, 0x8);
859 __ sll_w(t1, a4, a5);
860 __ li(a5, 0xA);
861 __ sll_w(t2, a4, a5);
862 __ li(a5, 0x1F);
863 __ sll_w(t3, a4, a5);
864
865 __ St_w(t0, MemOperand(a0, offsetof(T, result_sll_w_0)));
866 __ St_w(t1, MemOperand(a0, offsetof(T, result_sll_w_8)));
867 __ St_w(t2, MemOperand(a0, offsetof(T, result_sll_w_10)));
868 __ St_w(t3, MemOperand(a0, offsetof(T, result_sll_w_31)));
869
870 // srl_w
871 __ li(a5, 0x0);
872 __ srl_w(t0, a4, a5);
873 __ li(a5, 0x8);
874 __ srl_w(t1, a4, a5);
875 __ li(a5, 0xA);
876 __ srl_w(t2, a4, a5);
877 __ li(a5, 0x1F);
878 __ srl_w(t3, a4, a5);
879
880 __ St_w(t0, MemOperand(a0, offsetof(T, result_srl_w_0)));
881 __ St_w(t1, MemOperand(a0, offsetof(T, result_srl_w_8)));
882 __ St_w(t2, MemOperand(a0, offsetof(T, result_srl_w_10)));
883 __ St_w(t3, MemOperand(a0, offsetof(T, result_srl_w_31)));
884
885 // sra_w
886 __ li(a5, 0x0);
887 __ sra_w(t0, a4, a5);
888 __ li(a5, 0x8);
889 __ sra_w(t1, a4, a5);
890
891 __ li(a6, static_cast<int32_t>(0x80000000));
892 __ add_w(a6, a6, a4);
893 __ li(a5, 0xA);
894 __ sra_w(t2, a6, a5);
895 __ li(a5, 0x1F);
896 __ sra_w(t3, a6, a5);
897
898 __ St_w(t0, MemOperand(a0, offsetof(T, result_sra_w_0)));
899 __ St_w(t1, MemOperand(a0, offsetof(T, result_sra_w_8)));
900 __ St_w(t2, MemOperand(a0, offsetof(T, result_sra_w_10)));
901 __ St_w(t3, MemOperand(a0, offsetof(T, result_sra_w_31)));
902
903 // rotr
904 __ li(a5, 0x0);
905 __ rotr_w(t0, a4, a5);
906 __ li(a6, 0x8);
907 __ rotr_w(t1, a4, a6);
908
909 __ St_w(t0, MemOperand(a0, offsetof(T, result_rotr_w_0)));
910 __ St_w(t1, MemOperand(a0, offsetof(T, result_rotr_w_8)));
911
912 // slli_w
913 __ slli_w(t0, a4, 0);
914 __ slli_w(t1, a4, 0x8);
915 __ slli_w(t2, a4, 0xA);
916 __ slli_w(t3, a4, 0x1F);
917
918 __ St_w(t0, MemOperand(a0, offsetof(T, result_slli_w_0)));
919 __ St_w(t1, MemOperand(a0, offsetof(T, result_slli_w_8)));
920 __ St_w(t2, MemOperand(a0, offsetof(T, result_slli_w_10)));
921 __ St_w(t3, MemOperand(a0, offsetof(T, result_slli_w_31)));
922
923 // srli_w
924 __ srli_w(t0, a4, 0);
925 __ srli_w(t1, a4, 0x8);
926 __ srli_w(t2, a4, 0xA);
927 __ srli_w(t3, a4, 0x1F);
928
929 __ St_w(t0, MemOperand(a0, offsetof(T, result_srli_w_0)));
930 __ St_w(t1, MemOperand(a0, offsetof(T, result_srli_w_8)));
931 __ St_w(t2, MemOperand(a0, offsetof(T, result_srli_w_10)));
932 __ St_w(t3, MemOperand(a0, offsetof(T, result_srli_w_31)));
933
934 // srai_w
935 __ srai_w(t0, a4, 0);
936 __ srai_w(t1, a4, 0x8);
937
938 __ li(a6, static_cast<int32_t>(0x80000000));
939 __ add_w(a6, a6, a4);
940 __ srai_w(t2, a6, 0xA);
941 __ srai_w(t3, a6, 0x1F);
942
943 __ St_w(t0, MemOperand(a0, offsetof(T, result_srai_w_0)));
944 __ St_w(t1, MemOperand(a0, offsetof(T, result_srai_w_8)));
945 __ St_w(t2, MemOperand(a0, offsetof(T, result_srai_w_10)));
946 __ St_w(t3, MemOperand(a0, offsetof(T, result_srai_w_31)));
947
948 // rotri_w
949 __ rotri_w(t0, a4, 0);
950 __ rotri_w(t1, a4, 0x8);
951 __ rotri_w(t2, a4, 0xA);
952 __ rotri_w(t3, a4, 0x1F);
953
954 __ St_w(t0, MemOperand(a0, offsetof(T, result_rotri_w_0)));
955 __ St_w(t1, MemOperand(a0, offsetof(T, result_rotri_w_8)));
956 __ St_w(t2, MemOperand(a0, offsetof(T, result_rotri_w_10)));
957 __ St_w(t3, MemOperand(a0, offsetof(T, result_rotri_w_31)));
958
959 __ jirl(zero_reg, ra, 0);
960
961 CodeDesc desc;
962 assm.GetCode(isolate, &desc);
963 Handle<Code> code =
964 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
965 auto f = GeneratedCode<F3>::FromCode(*code);
966 t.input = 0x12345678;
967 f.Call(&t, 0x0, 0, 0, 0);
968
969 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_sll_w_0);
970 CHECK_EQ(static_cast<int32_t>(0x34567800), t.result_sll_w_8);
971 CHECK_EQ(static_cast<int32_t>(0xD159E000), t.result_sll_w_10);
972 CHECK_EQ(static_cast<int32_t>(0x0), t.result_sll_w_31);
973
974 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_srl_w_0);
975 CHECK_EQ(static_cast<int32_t>(0x123456), t.result_srl_w_8);
976 CHECK_EQ(static_cast<int32_t>(0x48D15), t.result_srl_w_10);
977 CHECK_EQ(static_cast<int32_t>(0x0), t.result_srl_w_31);
978
979 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_sra_w_0);
980 CHECK_EQ(static_cast<int32_t>(0x123456), t.result_sra_w_8);
981 CHECK_EQ(static_cast<int32_t>(0xFFE48D15), t.result_sra_w_10);
982 CHECK_EQ(static_cast<int32_t>(0xFFFFFFFF), t.result_sra_w_31);
983
984 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_rotr_w_0);
985 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotr_w_8);
986
987 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_slli_w_0);
988 CHECK_EQ(static_cast<int32_t>(0x34567800), t.result_slli_w_8);
989 CHECK_EQ(static_cast<int32_t>(0xD159E000), t.result_slli_w_10);
990 CHECK_EQ(static_cast<int32_t>(0x0), t.result_slli_w_31);
991
992 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_srli_w_0);
993 CHECK_EQ(static_cast<int32_t>(0x123456), t.result_srli_w_8);
994 CHECK_EQ(static_cast<int32_t>(0x48D15), t.result_srli_w_10);
995 CHECK_EQ(static_cast<int32_t>(0x0), t.result_srli_w_31);
996
997 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_srai_w_0);
998 CHECK_EQ(static_cast<int32_t>(0x123456), t.result_srai_w_8);
999 CHECK_EQ(static_cast<int32_t>(0xFFE48D15), t.result_srai_w_10);
1000 CHECK_EQ(static_cast<int32_t>(0xFFFFFFFF), t.result_srai_w_31);
1001
1002 CHECK_EQ(static_cast<int32_t>(0x12345678), t.result_rotri_w_0);
1003 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotri_w_8);
1004 CHECK_EQ(static_cast<int32_t>(0x9E048D15), t.result_rotri_w_10);
1005 CHECK_EQ(static_cast<int32_t>(0x2468ACF0), t.result_rotri_w_31);
1006 }
1007
TEST(LA9)1008 TEST(LA9) {
1009 // Test 64bit shift instructions.
1010 CcTest::InitializeVM();
1011 Isolate* isolate = CcTest::i_isolate();
1012 HandleScope scope(isolate);
1013
1014 struct T {
1015 int64_t input;
1016 int64_t result_sll_d_0;
1017 int64_t result_sll_d_13;
1018 int64_t result_sll_d_30;
1019 int64_t result_sll_d_63;
1020 int64_t result_srl_d_0;
1021 int64_t result_srl_d_13;
1022 int64_t result_srl_d_30;
1023 int64_t result_srl_d_63;
1024 int64_t result_sra_d_0;
1025 int64_t result_sra_d_13;
1026 int64_t result_sra_d_30;
1027 int64_t result_sra_d_63;
1028 int64_t result_rotr_d_0;
1029 int64_t result_rotr_d_13;
1030 int64_t result_slli_d_0;
1031 int64_t result_slli_d_13;
1032 int64_t result_slli_d_30;
1033 int64_t result_slli_d_63;
1034 int64_t result_srli_d_0;
1035 int64_t result_srli_d_13;
1036 int64_t result_srli_d_30;
1037 int64_t result_srli_d_63;
1038 int64_t result_srai_d_0;
1039 int64_t result_srai_d_13;
1040 int64_t result_srai_d_30;
1041 int64_t result_srai_d_63;
1042 int64_t result_rotri_d_0;
1043 int64_t result_rotri_d_13;
1044 int64_t result_rotri_d_30;
1045 int64_t result_rotri_d_63;
1046 };
1047
1048 T t;
1049 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1050
1051 __ Ld_d(a4, MemOperand(a0, offsetof(T, input)));
1052
1053 // sll_d
1054 __ li(a5, 0);
1055 __ sll_d(t0, a4, a5);
1056 __ li(a5, 0xD);
1057 __ sll_d(t1, a4, a5);
1058 __ li(a5, 0x1E);
1059 __ sll_d(t2, a4, a5);
1060 __ li(a5, 0x3F);
1061 __ sll_d(t3, a4, a5);
1062
1063 __ St_d(t0, MemOperand(a0, offsetof(T, result_sll_d_0)));
1064 __ St_d(t1, MemOperand(a0, offsetof(T, result_sll_d_13)));
1065 __ St_d(t2, MemOperand(a0, offsetof(T, result_sll_d_30)));
1066 __ St_d(t3, MemOperand(a0, offsetof(T, result_sll_d_63)));
1067
1068 // srl_d
1069 __ li(a5, 0x0);
1070 __ srl_d(t0, a4, a5);
1071 __ li(a5, 0xD);
1072 __ srl_d(t1, a4, a5);
1073 __ li(a5, 0x1E);
1074 __ srl_d(t2, a4, a5);
1075 __ li(a5, 0x3F);
1076 __ srl_d(t3, a4, a5);
1077
1078 __ St_d(t0, MemOperand(a0, offsetof(T, result_srl_d_0)));
1079 __ St_d(t1, MemOperand(a0, offsetof(T, result_srl_d_13)));
1080 __ St_d(t2, MemOperand(a0, offsetof(T, result_srl_d_30)));
1081 __ St_d(t3, MemOperand(a0, offsetof(T, result_srl_d_63)));
1082
1083 // sra_d
1084 __ li(a5, 0x0);
1085 __ sra_d(t0, a4, a5);
1086 __ li(a5, 0xD);
1087 __ sra_d(t1, a4, a5);
1088
1089 __ li(a6, static_cast<int64_t>(0x8000000000000000));
1090 __ add_d(a6, a6, a4);
1091 __ li(a5, 0x1E);
1092 __ sra_d(t2, a6, a5);
1093 __ li(a5, 0x3F);
1094 __ sra_d(t3, a6, a5);
1095
1096 __ St_d(t0, MemOperand(a0, offsetof(T, result_sra_d_0)));
1097 __ St_d(t1, MemOperand(a0, offsetof(T, result_sra_d_13)));
1098 __ St_d(t2, MemOperand(a0, offsetof(T, result_sra_d_30)));
1099 __ St_d(t3, MemOperand(a0, offsetof(T, result_sra_d_63)));
1100
1101 // rotr
1102 __ li(a5, 0x0);
1103 __ rotr_d(t0, a4, a5);
1104 __ li(a6, 0xD);
1105 __ rotr_d(t1, a4, a6);
1106
1107 __ St_d(t0, MemOperand(a0, offsetof(T, result_rotr_d_0)));
1108 __ St_d(t1, MemOperand(a0, offsetof(T, result_rotr_d_13)));
1109
1110 // slli_d
1111 __ slli_d(t0, a4, 0);
1112 __ slli_d(t1, a4, 0xD);
1113 __ slli_d(t2, a4, 0x1E);
1114 __ slli_d(t3, a4, 0x3F);
1115
1116 __ St_d(t0, MemOperand(a0, offsetof(T, result_slli_d_0)));
1117 __ St_d(t1, MemOperand(a0, offsetof(T, result_slli_d_13)));
1118 __ St_d(t2, MemOperand(a0, offsetof(T, result_slli_d_30)));
1119 __ St_d(t3, MemOperand(a0, offsetof(T, result_slli_d_63)));
1120
1121 // srli_d
1122 __ srli_d(t0, a4, 0);
1123 __ srli_d(t1, a4, 0xD);
1124 __ srli_d(t2, a4, 0x1E);
1125 __ srli_d(t3, a4, 0x3F);
1126
1127 __ St_d(t0, MemOperand(a0, offsetof(T, result_srli_d_0)));
1128 __ St_d(t1, MemOperand(a0, offsetof(T, result_srli_d_13)));
1129 __ St_d(t2, MemOperand(a0, offsetof(T, result_srli_d_30)));
1130 __ St_d(t3, MemOperand(a0, offsetof(T, result_srli_d_63)));
1131
1132 // srai_d
1133 __ srai_d(t0, a4, 0);
1134 __ srai_d(t1, a4, 0xD);
1135
1136 __ li(a6, static_cast<int64_t>(0x8000000000000000));
1137 __ add_d(a6, a6, a4);
1138 __ srai_d(t2, a6, 0x1E);
1139 __ srai_d(t3, a6, 0x3F);
1140
1141 __ St_d(t0, MemOperand(a0, offsetof(T, result_srai_d_0)));
1142 __ St_d(t1, MemOperand(a0, offsetof(T, result_srai_d_13)));
1143 __ St_d(t2, MemOperand(a0, offsetof(T, result_srai_d_30)));
1144 __ St_d(t3, MemOperand(a0, offsetof(T, result_srai_d_63)));
1145
1146 // rotri_d
1147 __ rotri_d(t0, a4, 0);
1148 __ rotri_d(t1, a4, 0xD);
1149 __ rotri_d(t2, a4, 0x1E);
1150 __ rotri_d(t3, a4, 0x3F);
1151
1152 __ St_d(t0, MemOperand(a0, offsetof(T, result_rotri_d_0)));
1153 __ St_d(t1, MemOperand(a0, offsetof(T, result_rotri_d_13)));
1154 __ St_d(t2, MemOperand(a0, offsetof(T, result_rotri_d_30)));
1155 __ St_d(t3, MemOperand(a0, offsetof(T, result_rotri_d_63)));
1156
1157 __ jirl(zero_reg, ra, 0);
1158
1159 CodeDesc desc;
1160 assm.GetCode(isolate, &desc);
1161 Handle<Code> code =
1162 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1163 auto f = GeneratedCode<F3>::FromCode(*code);
1164 t.input = 0x51F4B764A26E7412;
1165 f.Call(&t, 0, 0, 0, 0);
1166
1167 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_sll_d_0);
1168 CHECK_EQ(static_cast<int64_t>(0x96ec944dce824000), t.result_sll_d_13);
1169 CHECK_EQ(static_cast<int64_t>(0x289b9d0480000000), t.result_sll_d_30);
1170 CHECK_EQ(static_cast<int64_t>(0x0), t.result_sll_d_63);
1171
1172 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_srl_d_0);
1173 CHECK_EQ(static_cast<int64_t>(0x28fa5bb251373), t.result_srl_d_13);
1174 CHECK_EQ(static_cast<int64_t>(0x147d2dd92), t.result_srl_d_30);
1175 CHECK_EQ(static_cast<int64_t>(0x0), t.result_srl_d_63);
1176
1177 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_sra_d_0);
1178 CHECK_EQ(static_cast<int64_t>(0x28fa5bb251373), t.result_sra_d_13);
1179 CHECK_EQ(static_cast<int64_t>(0xffffffff47d2dd92), t.result_sra_d_30);
1180 CHECK_EQ(static_cast<int64_t>(0xffffffffffffffff), t.result_sra_d_63);
1181
1182 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_rotr_d_0);
1183 CHECK_EQ(static_cast<int64_t>(0xa0928fa5bb251373), t.result_rotr_d_13);
1184
1185 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_slli_d_0);
1186 CHECK_EQ(static_cast<int64_t>(0x96ec944dce824000), t.result_slli_d_13);
1187 CHECK_EQ(static_cast<int64_t>(0x289b9d0480000000), t.result_slli_d_30);
1188 CHECK_EQ(static_cast<int64_t>(0x0), t.result_slli_d_63);
1189
1190 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_srli_d_0);
1191 CHECK_EQ(static_cast<int64_t>(0x28fa5bb251373), t.result_srli_d_13);
1192 CHECK_EQ(static_cast<int64_t>(0x147d2dd92), t.result_srli_d_30);
1193 CHECK_EQ(static_cast<int64_t>(0x0), t.result_srli_d_63);
1194
1195 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_srai_d_0);
1196 CHECK_EQ(static_cast<int64_t>(0x28fa5bb251373), t.result_srai_d_13);
1197 CHECK_EQ(static_cast<int64_t>(0xffffffff47d2dd92), t.result_srai_d_30);
1198 CHECK_EQ(static_cast<int64_t>(0xffffffffffffffff), t.result_srai_d_63);
1199
1200 CHECK_EQ(static_cast<int64_t>(0x51f4b764a26e7412), t.result_rotri_d_0);
1201 CHECK_EQ(static_cast<int64_t>(0xa0928fa5bb251373), t.result_rotri_d_13);
1202 CHECK_EQ(static_cast<int64_t>(0x89b9d04947d2dd92), t.result_rotri_d_30);
1203 CHECK_EQ(static_cast<int64_t>(0xa3e96ec944dce824), t.result_rotri_d_63);
1204 }
1205
TEST(LA10)1206 TEST(LA10) {
1207 // Test 32bit bit operation instructions.
1208 CcTest::InitializeVM();
1209 Isolate* isolate = CcTest::i_isolate();
1210 HandleScope scope(isolate);
1211 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1212
1213 struct T {
1214 int64_t si1;
1215 int64_t si2;
1216 int32_t result_ext_w_b_si1;
1217 int32_t result_ext_w_b_si2;
1218 int32_t result_ext_w_h_si1;
1219 int32_t result_ext_w_h_si2;
1220 int32_t result_clo_w_si1;
1221 int32_t result_clo_w_si2;
1222 int32_t result_clz_w_si1;
1223 int32_t result_clz_w_si2;
1224 int32_t result_cto_w_si1;
1225 int32_t result_cto_w_si2;
1226 int32_t result_ctz_w_si1;
1227 int32_t result_ctz_w_si2;
1228 int32_t result_bytepick_w_si1;
1229 int32_t result_bytepick_w_si2;
1230 int32_t result_revb_2h_si1;
1231 int32_t result_revb_2h_si2;
1232 int32_t result_bitrev_4b_si1;
1233 int32_t result_bitrev_4b_si2;
1234 int32_t result_bitrev_w_si1;
1235 int32_t result_bitrev_w_si2;
1236 int32_t result_bstrins_w_si1;
1237 int32_t result_bstrins_w_si2;
1238 int32_t result_bstrpick_w_si1;
1239 int32_t result_bstrpick_w_si2;
1240 };
1241 T t;
1242
1243 __ Ld_d(a4, MemOperand(a0, offsetof(T, si1)));
1244 __ Ld_d(a5, MemOperand(a0, offsetof(T, si2)));
1245
1246 // ext_w_b
1247 __ ext_w_b(t0, a4);
1248 __ ext_w_b(t1, a5);
1249 __ St_w(t0, MemOperand(a0, offsetof(T, result_ext_w_b_si1)));
1250 __ St_w(t1, MemOperand(a0, offsetof(T, result_ext_w_b_si2)));
1251
1252 // ext_w_h
1253 __ ext_w_h(t0, a4);
1254 __ ext_w_h(t1, a5);
1255 __ St_w(t0, MemOperand(a0, offsetof(T, result_ext_w_h_si1)));
1256 __ St_w(t1, MemOperand(a0, offsetof(T, result_ext_w_h_si2)));
1257
1258 /* //clo_w
1259 __ clo_w(t0, a4);
1260 __ clo_w(t1, a5);
1261 __ St_w(t0, MemOperand(a0, offsetof(T, result_clo_w_si1)));
1262 __ St_w(t1, MemOperand(a0, offsetof(T, result_clo_w_si2)));*/
1263
1264 // clz_w
1265 __ clz_w(t0, a4);
1266 __ clz_w(t1, a5);
1267 __ St_w(t0, MemOperand(a0, offsetof(T, result_clz_w_si1)));
1268 __ St_w(t1, MemOperand(a0, offsetof(T, result_clz_w_si2)));
1269
1270 /* //cto_w
1271 __ cto_w(t0, a4);
1272 __ cto_w(t1, a5);
1273 __ St_w(t0, MemOperand(a0, offsetof(T, result_cto_w_si1)));
1274 __ St_w(t1, MemOperand(a0, offsetof(T, result_cto_w_si2)));*/
1275
1276 // ctz_w
1277 __ ctz_w(t0, a4);
1278 __ ctz_w(t1, a5);
1279 __ St_w(t0, MemOperand(a0, offsetof(T, result_ctz_w_si1)));
1280 __ St_w(t1, MemOperand(a0, offsetof(T, result_ctz_w_si2)));
1281
1282 // bytepick_w
1283 __ bytepick_w(t0, a4, a5, 0);
1284 __ bytepick_w(t1, a5, a4, 2);
1285 __ St_w(t0, MemOperand(a0, offsetof(T, result_bytepick_w_si1)));
1286 __ St_w(t1, MemOperand(a0, offsetof(T, result_bytepick_w_si2)));
1287
1288 // revb_2h
1289 __ revb_2h(t0, a4);
1290 __ revb_2h(t1, a5);
1291 __ St_w(t0, MemOperand(a0, offsetof(T, result_revb_2h_si1)));
1292 __ St_w(t1, MemOperand(a0, offsetof(T, result_revb_2h_si2)));
1293
1294 // bitrev
1295 __ bitrev_4b(t0, a4);
1296 __ bitrev_4b(t1, a5);
1297 __ St_w(t0, MemOperand(a0, offsetof(T, result_bitrev_4b_si1)));
1298 __ St_w(t1, MemOperand(a0, offsetof(T, result_bitrev_4b_si2)));
1299
1300 // bitrev_w
1301 __ bitrev_w(t0, a4);
1302 __ bitrev_w(t1, a5);
1303 __ St_w(t0, MemOperand(a0, offsetof(T, result_bitrev_w_si1)));
1304 __ St_w(t1, MemOperand(a0, offsetof(T, result_bitrev_w_si2)));
1305
1306 // bstrins
1307 __ or_(t0, zero_reg, zero_reg);
1308 __ or_(t1, zero_reg, zero_reg);
1309 __ bstrins_w(t0, a4, 0xD, 0x4);
1310 __ bstrins_w(t1, a5, 0x16, 0x5);
1311 __ St_w(t0, MemOperand(a0, offsetof(T, result_bstrins_w_si1)));
1312 __ St_w(t1, MemOperand(a0, offsetof(T, result_bstrins_w_si2)));
1313
1314 // bstrpick
1315 __ or_(t0, zero_reg, zero_reg);
1316 __ or_(t1, zero_reg, zero_reg);
1317 __ bstrpick_w(t0, a4, 0xD, 0x4);
1318 __ bstrpick_w(t1, a5, 0x16, 0x5);
1319 __ St_w(t0, MemOperand(a0, offsetof(T, result_bstrpick_w_si1)));
1320 __ St_w(t1, MemOperand(a0, offsetof(T, result_bstrpick_w_si2)));
1321
1322 __ jirl(zero_reg, ra, 0);
1323
1324 CodeDesc desc;
1325 assm.GetCode(isolate, &desc);
1326 Handle<Code> code =
1327 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1328 auto f = GeneratedCode<F3>::FromCode(*code);
1329 t.si1 = 0x51F4B764A26E7412;
1330 t.si2 = 0x81F25A87C423B891;
1331 f.Call(&t, 0, 0, 0, 0);
1332
1333 CHECK_EQ(static_cast<int32_t>(0x12), t.result_ext_w_b_si1);
1334 CHECK_EQ(static_cast<int32_t>(0xffffff91), t.result_ext_w_b_si2);
1335 CHECK_EQ(static_cast<int32_t>(0x7412), t.result_ext_w_h_si1);
1336 CHECK_EQ(static_cast<int32_t>(0xffffb891), t.result_ext_w_h_si2);
1337 // CHECK_EQ(static_cast<int32_t>(0x1), t.result_clo_w_si1);
1338 // CHECK_EQ(static_cast<int32_t>(0x2), t.result_clo_w_si2);
1339 CHECK_EQ(static_cast<int32_t>(0x0), t.result_clz_w_si1);
1340 CHECK_EQ(static_cast<int32_t>(0x0), t.result_clz_w_si2);
1341 // CHECK_EQ(static_cast<int32_t>(0x0), t.result_cto_w_si1);
1342 // CHECK_EQ(static_cast<int32_t>(0x1), t.result_cto_w_si2);
1343 CHECK_EQ(static_cast<int32_t>(0x1), t.result_ctz_w_si1);
1344 CHECK_EQ(static_cast<int32_t>(0x0), t.result_ctz_w_si2);
1345 CHECK_EQ(static_cast<int32_t>(0xc423b891), t.result_bytepick_w_si1);
1346 CHECK_EQ(static_cast<int32_t>(0x7412c423),
1347 t.result_bytepick_w_si2); // 0xffffc423
1348 CHECK_EQ(static_cast<int32_t>(0x6ea21274), t.result_revb_2h_si1);
1349 CHECK_EQ(static_cast<int32_t>(0x23c491b8), t.result_revb_2h_si2);
1350 CHECK_EQ(static_cast<int32_t>(0x45762e48), t.result_bitrev_4b_si1);
1351 CHECK_EQ(static_cast<int32_t>(0x23c41d89), t.result_bitrev_4b_si2);
1352 CHECK_EQ(static_cast<int32_t>(0x482e7645), t.result_bitrev_w_si1);
1353 CHECK_EQ(static_cast<int32_t>(0x891dc423), t.result_bitrev_w_si2);
1354 CHECK_EQ(static_cast<int32_t>(0x120), t.result_bstrins_w_si1);
1355 CHECK_EQ(static_cast<int32_t>(0x771220), t.result_bstrins_w_si2);
1356 CHECK_EQ(static_cast<int32_t>(0x341), t.result_bstrpick_w_si1);
1357 CHECK_EQ(static_cast<int32_t>(0x11dc4), t.result_bstrpick_w_si2);
1358 }
1359
TEST(LA11)1360 TEST(LA11) {
1361 // Test 64bit bit operation instructions.
1362 CcTest::InitializeVM();
1363 Isolate* isolate = CcTest::i_isolate();
1364 HandleScope scope(isolate);
1365 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1366
1367 struct T {
1368 int64_t si1;
1369 int64_t si2;
1370 int64_t result_clo_d_si1;
1371 int64_t result_clo_d_si2;
1372 int64_t result_clz_d_si1;
1373 int64_t result_clz_d_si2;
1374 int64_t result_cto_d_si1;
1375 int64_t result_cto_d_si2;
1376 int64_t result_ctz_d_si1;
1377 int64_t result_ctz_d_si2;
1378 int64_t result_bytepick_d_si1;
1379 int64_t result_bytepick_d_si2;
1380 int64_t result_revb_4h_si1;
1381 int64_t result_revb_4h_si2;
1382 int64_t result_revb_2w_si1;
1383 int64_t result_revb_2w_si2;
1384 int64_t result_revb_d_si1;
1385 int64_t result_revb_d_si2;
1386 int64_t result_revh_2w_si1;
1387 int64_t result_revh_2w_si2;
1388 int64_t result_revh_d_si1;
1389 int64_t result_revh_d_si2;
1390 int64_t result_bitrev_8b_si1;
1391 int64_t result_bitrev_8b_si2;
1392 int64_t result_bitrev_d_si1;
1393 int64_t result_bitrev_d_si2;
1394 int64_t result_bstrins_d_si1;
1395 int64_t result_bstrins_d_si2;
1396 int64_t result_bstrpick_d_si1;
1397 int64_t result_bstrpick_d_si2;
1398 int64_t result_maskeqz_si1;
1399 int64_t result_maskeqz_si2;
1400 int64_t result_masknez_si1;
1401 int64_t result_masknez_si2;
1402 };
1403
1404 T t;
1405
1406 __ Ld_d(a4, MemOperand(a0, offsetof(T, si1)));
1407 __ Ld_d(a5, MemOperand(a0, offsetof(T, si2)));
1408
1409 /* //clo_d
1410 __ clo_d(t0, a4);
1411 __ clo_d(t1, a5);
1412 __ St_w(t0, MemOperand(a0, offsetof(T, result_clo_d_si1)));
1413 __ St_w(t1, MemOperand(a0, offsetof(T, result_clo_d_si2)));*/
1414
1415 // clz_d
1416 __ or_(t0, zero_reg, zero_reg);
1417 __ clz_d(t0, a4);
1418 __ clz_d(t1, a5);
1419 __ St_d(t0, MemOperand(a0, offsetof(T, result_clz_d_si1)));
1420 __ St_d(t1, MemOperand(a0, offsetof(T, result_clz_d_si2)));
1421
1422 /* //cto_d
1423 __ cto_d(t0, a4);
1424 __ cto_d(t1, a5);
1425 __ St_w(t0, MemOperand(a0, offsetof(T, result_cto_d_si1)));
1426 __ St_w(t1, MemOperand(a0, offsetof(T, result_cto_d_si2)));*/
1427
1428 // ctz_d
1429 __ ctz_d(t0, a4);
1430 __ ctz_d(t1, a5);
1431 __ St_d(t0, MemOperand(a0, offsetof(T, result_ctz_d_si1)));
1432 __ St_d(t1, MemOperand(a0, offsetof(T, result_ctz_d_si2)));
1433
1434 // bytepick_d
1435 __ bytepick_d(t0, a4, a5, 0);
1436 __ bytepick_d(t1, a5, a4, 5);
1437 __ St_d(t0, MemOperand(a0, offsetof(T, result_bytepick_d_si1)));
1438 __ St_d(t1, MemOperand(a0, offsetof(T, result_bytepick_d_si2)));
1439
1440 // revb_4h
1441 __ revb_4h(t0, a4);
1442 __ revb_4h(t1, a5);
1443 __ St_d(t0, MemOperand(a0, offsetof(T, result_revb_4h_si1)));
1444 __ St_d(t1, MemOperand(a0, offsetof(T, result_revb_4h_si2)));
1445
1446 // revb_2w
1447 __ revb_2w(t0, a4);
1448 __ revb_2w(t1, a5);
1449 __ St_d(t0, MemOperand(a0, offsetof(T, result_revb_2w_si1)));
1450 __ St_d(t1, MemOperand(a0, offsetof(T, result_revb_2w_si2)));
1451
1452 // revb_d
1453 __ revb_d(t0, a4);
1454 __ revb_d(t1, a5);
1455 __ St_d(t0, MemOperand(a0, offsetof(T, result_revb_d_si1)));
1456 __ St_d(t1, MemOperand(a0, offsetof(T, result_revb_d_si2)));
1457
1458 // revh_2w
1459 __ revh_2w(t0, a4);
1460 __ revh_2w(t1, a5);
1461 __ St_d(t0, MemOperand(a0, offsetof(T, result_revh_2w_si1)));
1462 __ St_d(t1, MemOperand(a0, offsetof(T, result_revh_2w_si2)));
1463
1464 // revh_d
1465 __ revh_d(t0, a4);
1466 __ revh_d(t1, a5);
1467 __ St_d(t0, MemOperand(a0, offsetof(T, result_revh_d_si1)));
1468 __ St_d(t1, MemOperand(a0, offsetof(T, result_revh_d_si2)));
1469
1470 // bitrev_8b
1471 __ bitrev_8b(t0, a4);
1472 __ bitrev_8b(t1, a5);
1473 __ St_d(t0, MemOperand(a0, offsetof(T, result_bitrev_8b_si1)));
1474 __ St_d(t1, MemOperand(a0, offsetof(T, result_bitrev_8b_si2)));
1475
1476 // bitrev_d
1477 __ bitrev_d(t0, a4);
1478 __ bitrev_d(t1, a5);
1479 __ St_d(t0, MemOperand(a0, offsetof(T, result_bitrev_d_si1)));
1480 __ St_d(t1, MemOperand(a0, offsetof(T, result_bitrev_d_si2)));
1481
1482 // bstrins_d
1483 __ or_(t0, zero_reg, zero_reg);
1484 __ or_(t1, zero_reg, zero_reg);
1485 __ bstrins_d(t0, a4, 5, 0);
1486 __ bstrins_d(t1, a5, 39, 12);
1487 __ St_d(t0, MemOperand(a0, offsetof(T, result_bstrins_d_si1)));
1488 __ St_d(t1, MemOperand(a0, offsetof(T, result_bstrins_d_si2)));
1489
1490 // bstrpick_d
1491 __ or_(t0, zero_reg, zero_reg);
1492 __ or_(t1, zero_reg, zero_reg);
1493 __ bstrpick_d(t0, a4, 5, 0);
1494 __ bstrpick_d(t1, a5, 63, 48);
1495 __ St_d(t0, MemOperand(a0, offsetof(T, result_bstrpick_d_si1)));
1496 __ St_d(t1, MemOperand(a0, offsetof(T, result_bstrpick_d_si2)));
1497
1498 // maskeqz
1499 __ maskeqz(t0, a4, a4);
1500 __ maskeqz(t1, a5, zero_reg);
1501 __ St_d(t0, MemOperand(a0, offsetof(T, result_maskeqz_si1)));
1502 __ St_d(t1, MemOperand(a0, offsetof(T, result_maskeqz_si2)));
1503
1504 // masknez
1505 __ masknez(t0, a4, a4);
1506 __ masknez(t1, a5, zero_reg);
1507 __ St_d(t0, MemOperand(a0, offsetof(T, result_masknez_si1)));
1508 __ St_d(t1, MemOperand(a0, offsetof(T, result_masknez_si2)));
1509
1510 __ jirl(zero_reg, ra, 0);
1511
1512 CodeDesc desc;
1513 assm.GetCode(isolate, &desc);
1514 Handle<Code> code =
1515 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1516 auto f = GeneratedCode<F3>::FromCode(*code);
1517 t.si1 = 0x10C021098B710CDE;
1518 t.si2 = 0xFB8017FF781A15C3;
1519 f.Call(&t, 0, 0, 0, 0);
1520
1521 // CHECK_EQ(static_cast<int64_t>(0x0), t.result_clo_d_si1);
1522 // CHECK_EQ(static_cast<int64_t>(0x5), t.result_clo_d_si2);
1523 CHECK_EQ(static_cast<int64_t>(0x3), t.result_clz_d_si1);
1524 CHECK_EQ(static_cast<int64_t>(0x0), t.result_clz_d_si2);
1525 // CHECK_EQ(static_cast<int64_t>(0x0), t.result_cto_d_si1);
1526 // CHECK_EQ(static_cast<int64_t>(0x2), t.result_cto_d_si2);
1527 CHECK_EQ(static_cast<int64_t>(0x1), t.result_ctz_d_si1);
1528 CHECK_EQ(static_cast<int64_t>(0x0), t.result_ctz_d_si2);
1529 CHECK_EQ(static_cast<int64_t>(0xfb8017ff781a15c3), t.result_bytepick_d_si1);
1530 CHECK_EQ(static_cast<int64_t>(0x710cdefb8017ff78), t.result_bytepick_d_si2);
1531 CHECK_EQ(static_cast<int64_t>(0xc0100921718bde0c), t.result_revb_4h_si1);
1532 CHECK_EQ(static_cast<int64_t>(0x80fbff171a78c315), t.result_revb_4h_si2);
1533 CHECK_EQ(static_cast<int64_t>(0x921c010de0c718b), t.result_revb_2w_si1);
1534 CHECK_EQ(static_cast<int64_t>(0xff1780fbc3151a78), t.result_revb_2w_si2);
1535 CHECK_EQ(static_cast<int64_t>(0xde0c718b0921c010), t.result_revb_d_si1);
1536 CHECK_EQ(static_cast<int64_t>(0xc3151a78ff1780fb), t.result_revb_d_si2);
1537 CHECK_EQ(static_cast<int64_t>(0x210910c00cde8b71), t.result_revh_2w_si1);
1538 CHECK_EQ(static_cast<int64_t>(0x17fffb8015c3781a), t.result_revh_2w_si2);
1539 CHECK_EQ(static_cast<int64_t>(0xcde8b71210910c0), t.result_revh_d_si1);
1540 CHECK_EQ(static_cast<int64_t>(0x15c3781a17fffb80), t.result_revh_d_si2);
1541 CHECK_EQ(static_cast<int64_t>(0x8038490d18e307b), t.result_bitrev_8b_si1);
1542 CHECK_EQ(static_cast<int64_t>(0xdf01e8ff1e58a8c3), t.result_bitrev_8b_si2);
1543 CHECK_EQ(static_cast<int64_t>(0x7b308ed190840308), t.result_bitrev_d_si1);
1544 CHECK_EQ(static_cast<int64_t>(0xc3a8581effe801df), t.result_bitrev_d_si2);
1545 CHECK_EQ(static_cast<int64_t>(0x1e), t.result_bstrins_d_si1);
1546 CHECK_EQ(static_cast<int64_t>(0x81a15c3000), t.result_bstrins_d_si2);
1547 CHECK_EQ(static_cast<int64_t>(0x1e), t.result_bstrpick_d_si1);
1548 CHECK_EQ(static_cast<int64_t>(0xfb80), t.result_bstrpick_d_si2);
1549 CHECK_EQ(static_cast<int64_t>(0), t.result_maskeqz_si1);
1550 CHECK_EQ(static_cast<int64_t>(0xFB8017FF781A15C3), t.result_maskeqz_si2);
1551 CHECK_EQ(static_cast<int64_t>(0x10C021098B710CDE), t.result_masknez_si1);
1552 CHECK_EQ(static_cast<int64_t>(0), t.result_masknez_si2);
1553 }
1554
run_beq(int64_t value1,int64_t value2,int16_t offset)1555 uint64_t run_beq(int64_t value1, int64_t value2, int16_t offset) {
1556 Isolate* isolate = CcTest::i_isolate();
1557 HandleScope scope(isolate);
1558
1559 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1560
1561 Label main_block, L;
1562 __ li(a2, 0l);
1563 __ b(&main_block);
1564 // Block 1
1565 __ addi_d(a2, a2, 0x1);
1566 __ addi_d(a2, a2, 0x2);
1567 __ b(&L);
1568
1569 // Block 2
1570 __ addi_d(a2, a2, 0x10);
1571 __ addi_d(a2, a2, 0x20);
1572 __ b(&L);
1573
1574 // Block 3 (Main)
1575 __ bind(&main_block);
1576 __ beq(a0, a1, offset);
1577 __ bind(&L);
1578 __ or_(a0, a2, zero_reg);
1579 __ jirl(zero_reg, ra, 0);
1580
1581 // Block 4
1582 __ addi_d(a2, a2, 0x100);
1583 __ addi_d(a2, a2, 0x200);
1584 __ b(&L);
1585
1586 // Block 5
1587 __ addi_d(a2, a2, 0x300);
1588 __ addi_d(a2, a2, 0x400);
1589 __ b(&L);
1590
1591 CodeDesc desc;
1592 assm.GetCode(isolate, &desc);
1593 Handle<Code> code =
1594 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1595
1596 auto f = GeneratedCode<F2>::FromCode(*code);
1597 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value1, value2, 0, 0, 0));
1598
1599 return res;
1600 }
1601
TEST(BEQ)1602 TEST(BEQ) {
1603 CcTest::InitializeVM();
1604 struct TestCaseBeq {
1605 int64_t value1;
1606 int64_t value2;
1607 int16_t offset;
1608 uint64_t expected_res;
1609 };
1610
1611 // clang-format off
1612 struct TestCaseBeq tc[] = {
1613 // value1, value2, offset, expected_res
1614 { 0, 0, -6, 0x3 },
1615 { 1, 1, -3, 0x30 },
1616 { -2, -2, 3, 0x300 },
1617 { 3, -3, 6, 0 },
1618 { 4, 4, 6, 0x700 },
1619 };
1620 // clang-format on
1621
1622 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeq);
1623 for (size_t i = 0; i < nr_test_cases; ++i) {
1624 uint64_t res = run_beq(tc[i].value1, tc[i].value2, tc[i].offset);
1625 CHECK_EQ(tc[i].expected_res, res);
1626 }
1627 }
1628
run_bne(int64_t value1,int64_t value2,int16_t offset)1629 uint64_t run_bne(int64_t value1, int64_t value2, int16_t offset) {
1630 Isolate* isolate = CcTest::i_isolate();
1631 HandleScope scope(isolate);
1632
1633 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1634
1635 Label main_block, L;
1636 __ li(a2, 0l);
1637 __ b(&main_block);
1638 // Block 1
1639 __ addi_d(a2, a2, 0x1);
1640 __ addi_d(a2, a2, 0x2);
1641 __ b(&L);
1642
1643 // Block 2
1644 __ addi_d(a2, a2, 0x10);
1645 __ addi_d(a2, a2, 0x20);
1646 __ b(&L);
1647
1648 // Block 3 (Main)
1649 __ bind(&main_block);
1650 __ bne(a0, a1, offset);
1651 __ bind(&L);
1652 __ or_(a0, a2, zero_reg);
1653 __ jirl(zero_reg, ra, 0);
1654
1655 // Block 4
1656 __ addi_d(a2, a2, 0x100);
1657 __ addi_d(a2, a2, 0x200);
1658 __ b(&L);
1659
1660 // Block 5
1661 __ addi_d(a2, a2, 0x300);
1662 __ addi_d(a2, a2, 0x400);
1663 __ b(&L);
1664
1665 CodeDesc desc;
1666 assm.GetCode(isolate, &desc);
1667 Handle<Code> code =
1668 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1669
1670 auto f = GeneratedCode<F2>::FromCode(*code);
1671 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value1, value2, 0, 0, 0));
1672
1673 return res;
1674 }
1675
TEST(BNE)1676 TEST(BNE) {
1677 CcTest::InitializeVM();
1678 struct TestCaseBne {
1679 int64_t value1;
1680 int64_t value2;
1681 int16_t offset;
1682 uint64_t expected_res;
1683 };
1684
1685 // clang-format off
1686 struct TestCaseBne tc[] = {
1687 // value1, value2, offset, expected_res
1688 { 1, -1, -6, 0x3 },
1689 { 2, -2, -3, 0x30 },
1690 { 3, -3, 3, 0x300 },
1691 { 4, -4, 6, 0x700 },
1692 { 0, 0, 6, 0 },
1693 };
1694 // clang-format on
1695
1696 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBne);
1697 for (size_t i = 0; i < nr_test_cases; ++i) {
1698 uint64_t res = run_bne(tc[i].value1, tc[i].value2, tc[i].offset);
1699 CHECK_EQ(tc[i].expected_res, res);
1700 }
1701 }
1702
run_blt(int64_t value1,int64_t value2,int16_t offset)1703 uint64_t run_blt(int64_t value1, int64_t value2, int16_t offset) {
1704 Isolate* isolate = CcTest::i_isolate();
1705 HandleScope scope(isolate);
1706
1707 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1708
1709 Label main_block, L;
1710 __ li(a2, 0l);
1711 __ b(&main_block);
1712 // Block 1
1713 __ addi_d(a2, a2, 0x1);
1714 __ addi_d(a2, a2, 0x2);
1715 __ b(&L);
1716
1717 // Block 2
1718 __ addi_d(a2, a2, 0x10);
1719 __ addi_d(a2, a2, 0x20);
1720 __ b(&L);
1721
1722 // Block 3 (Main)
1723 __ bind(&main_block);
1724 __ blt(a0, a1, offset);
1725 __ bind(&L);
1726 __ or_(a0, a2, zero_reg);
1727 __ jirl(zero_reg, ra, 0);
1728
1729 // Block 4
1730 __ addi_d(a2, a2, 0x100);
1731 __ addi_d(a2, a2, 0x200);
1732 __ b(&L);
1733
1734 // Block 5
1735 __ addi_d(a2, a2, 0x300);
1736 __ addi_d(a2, a2, 0x400);
1737 __ b(&L);
1738
1739 CodeDesc desc;
1740 assm.GetCode(isolate, &desc);
1741 Handle<Code> code =
1742 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1743
1744 auto f = GeneratedCode<F2>::FromCode(*code);
1745 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value1, value2, 0, 0, 0));
1746
1747 return res;
1748 }
1749
TEST(BLT)1750 TEST(BLT) {
1751 CcTest::InitializeVM();
1752 struct TestCaseBlt {
1753 int64_t value1;
1754 int64_t value2;
1755 int16_t offset;
1756 uint64_t expected_res;
1757 };
1758
1759 // clang-format off
1760 struct TestCaseBlt tc[] = {
1761 // value1, value2, offset, expected_res
1762 { -1, 1, -6, 0x3 },
1763 { -2, 2, -3, 0x30 },
1764 { -3, 3, 3, 0x300 },
1765 { -4, 4, 6, 0x700 },
1766 { 5, -5, 6, 0 },
1767 { 0, 0, 6, 0 },
1768 };
1769 // clang-format on
1770
1771 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBlt);
1772 for (size_t i = 0; i < nr_test_cases; ++i) {
1773 uint64_t res = run_blt(tc[i].value1, tc[i].value2, tc[i].offset);
1774 CHECK_EQ(tc[i].expected_res, res);
1775 }
1776 }
1777
run_bge(uint64_t value1,uint64_t value2,int16_t offset)1778 uint64_t run_bge(uint64_t value1, uint64_t value2, int16_t offset) {
1779 Isolate* isolate = CcTest::i_isolate();
1780 HandleScope scope(isolate);
1781
1782 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1783
1784 Label main_block, L;
1785 __ li(a2, 0l);
1786 __ b(&main_block);
1787 // Block 1
1788 __ addi_d(a2, a2, 0x1);
1789 __ addi_d(a2, a2, 0x2);
1790 __ b(&L);
1791
1792 // Block 2
1793 __ addi_d(a2, a2, 0x10);
1794 __ addi_d(a2, a2, 0x20);
1795 __ b(&L);
1796
1797 // Block 3 (Main)
1798 __ bind(&main_block);
1799 __ bge(a0, a1, offset);
1800 __ bind(&L);
1801 __ or_(a0, a2, zero_reg);
1802 __ jirl(zero_reg, ra, 0);
1803
1804 // Block 4
1805 __ addi_d(a2, a2, 0x100);
1806 __ addi_d(a2, a2, 0x200);
1807 __ b(&L);
1808
1809 // Block 5
1810 __ addi_d(a2, a2, 0x300);
1811 __ addi_d(a2, a2, 0x400);
1812 __ b(&L);
1813
1814 CodeDesc desc;
1815 assm.GetCode(isolate, &desc);
1816 Handle<Code> code =
1817 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1818
1819 auto f = GeneratedCode<F2>::FromCode(*code);
1820 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value1, value2, 0, 0, 0));
1821
1822 return res;
1823 }
1824
TEST(BGE)1825 TEST(BGE) {
1826 CcTest::InitializeVM();
1827 struct TestCaseBge {
1828 int64_t value1;
1829 int64_t value2;
1830 int16_t offset;
1831 uint64_t expected_res;
1832 };
1833
1834 // clang-format off
1835 struct TestCaseBge tc[] = {
1836 // value1, value2, offset, expected_res
1837 { 0, 0, -6, 0x3 },
1838 { 1, 1, -3, 0x30 },
1839 { 2, -2, 3, 0x300 },
1840 { 3, -3, 6, 0x700 },
1841 { -4, 4, 6, 0 },
1842 };
1843 // clang-format on
1844
1845 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBge);
1846 for (size_t i = 0; i < nr_test_cases; ++i) {
1847 uint64_t res = run_bge(tc[i].value1, tc[i].value2, tc[i].offset);
1848 CHECK_EQ(tc[i].expected_res, res);
1849 }
1850 }
1851
run_bltu(int64_t value1,int64_t value2,int16_t offset)1852 uint64_t run_bltu(int64_t value1, int64_t value2, int16_t offset) {
1853 Isolate* isolate = CcTest::i_isolate();
1854 HandleScope scope(isolate);
1855
1856 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1857
1858 Label main_block, L;
1859 __ li(a2, 0l);
1860 __ b(&main_block);
1861 // Block 1
1862 __ addi_d(a2, a2, 0x1);
1863 __ addi_d(a2, a2, 0x2);
1864 __ b(&L);
1865
1866 // Block 2
1867 __ addi_d(a2, a2, 0x10);
1868 __ addi_d(a2, a2, 0x20);
1869 __ b(&L);
1870
1871 // Block 3 (Main)
1872 __ bind(&main_block);
1873 __ bltu(a0, a1, offset);
1874 __ bind(&L);
1875 __ or_(a0, a2, zero_reg);
1876 __ jirl(zero_reg, ra, 0);
1877
1878 // Block 4
1879 __ addi_d(a2, a2, 0x100);
1880 __ addi_d(a2, a2, 0x200);
1881 __ b(&L);
1882
1883 // Block 5
1884 __ addi_d(a2, a2, 0x300);
1885 __ addi_d(a2, a2, 0x400);
1886 __ b(&L);
1887
1888 CodeDesc desc;
1889 assm.GetCode(isolate, &desc);
1890 Handle<Code> code =
1891 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1892
1893 auto f = GeneratedCode<F2>::FromCode(*code);
1894 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value1, value2, 0, 0, 0));
1895
1896 return res;
1897 }
1898
TEST(BLTU)1899 TEST(BLTU) {
1900 CcTest::InitializeVM();
1901 struct TestCaseBltu {
1902 int64_t value1;
1903 int64_t value2;
1904 int16_t offset;
1905 uint64_t expected_res;
1906 };
1907
1908 // clang-format off
1909 struct TestCaseBltu tc[] = {
1910 // value1, value2, offset, expected_res
1911 { 0, 1, -6, 0x3 },
1912 { 1, -1, -3, 0x30 },
1913 { 2, -2, 3, 0x300 },
1914 { 3, -3, 6, 0x700 },
1915 { 4, 4, 6, 0 },
1916 };
1917 // clang-format on
1918
1919 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBltu);
1920 for (size_t i = 0; i < nr_test_cases; ++i) {
1921 uint64_t res = run_bltu(tc[i].value1, tc[i].value2, tc[i].offset);
1922 CHECK_EQ(tc[i].expected_res, res);
1923 }
1924 }
1925
run_bgeu(int64_t value1,int64_t value2,int16_t offset)1926 uint64_t run_bgeu(int64_t value1, int64_t value2, int16_t offset) {
1927 Isolate* isolate = CcTest::i_isolate();
1928 HandleScope scope(isolate);
1929
1930 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
1931
1932 Label main_block, L;
1933 __ li(a2, 0l);
1934 __ b(&main_block);
1935 // Block 1
1936 __ addi_d(a2, a2, 0x1);
1937 __ addi_d(a2, a2, 0x2);
1938 __ b(&L);
1939
1940 // Block 2
1941 __ addi_d(a2, a2, 0x10);
1942 __ addi_d(a2, a2, 0x20);
1943 __ b(&L);
1944
1945 // Block 3 (Main)
1946 __ bind(&main_block);
1947 __ bgeu(a0, a1, offset);
1948 __ bind(&L);
1949 __ or_(a0, a2, zero_reg);
1950 __ jirl(zero_reg, ra, 0);
1951
1952 // Block 4
1953 __ addi_d(a2, a2, 0x100);
1954 __ addi_d(a2, a2, 0x200);
1955 __ b(&L);
1956
1957 // Block 5
1958 __ addi_d(a2, a2, 0x300);
1959 __ addi_d(a2, a2, 0x400);
1960 __ b(&L);
1961
1962 CodeDesc desc;
1963 assm.GetCode(isolate, &desc);
1964 Handle<Code> code =
1965 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
1966
1967 auto f = GeneratedCode<F2>::FromCode(*code);
1968 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value1, value2, 0, 0, 0));
1969
1970 return res;
1971 }
1972
TEST(BGEU)1973 TEST(BGEU) {
1974 CcTest::InitializeVM();
1975 struct TestCaseBgeu {
1976 int64_t value1;
1977 int64_t value2;
1978 int16_t offset;
1979 uint64_t expected_res;
1980 };
1981
1982 // clang-format off
1983 struct TestCaseBgeu tc[] = {
1984 // value1, value2, offset, expected_res
1985 { 0, 0, -6, 0x3 },
1986 { -1, 1, -3, 0x30 },
1987 { -2, 2, 3, 0x300 },
1988 { -3, 3, 6, 0x700 },
1989 { 4, -4, 6, 0 },
1990 };
1991 // clang-format on
1992
1993 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBgeu);
1994 for (size_t i = 0; i < nr_test_cases; ++i) {
1995 uint64_t res = run_bgeu(tc[i].value1, tc[i].value2, tc[i].offset);
1996 CHECK_EQ(tc[i].expected_res, res);
1997 }
1998 }
1999
run_beqz(int64_t value,int32_t offset)2000 uint64_t run_beqz(int64_t value, int32_t offset) {
2001 Isolate* isolate = CcTest::i_isolate();
2002 HandleScope scope(isolate);
2003
2004 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2005
2006 Label main_block, L;
2007 __ li(a2, 0l);
2008 __ b(&main_block);
2009 // Block 1
2010 __ addi_d(a2, a2, 0x1);
2011 __ addi_d(a2, a2, 0x2);
2012 __ b(&L);
2013
2014 // Block 2
2015 __ addi_d(a2, a2, 0x10);
2016 __ addi_d(a2, a2, 0x20);
2017 __ b(&L);
2018
2019 // Block 3 (Main)
2020 __ bind(&main_block);
2021 __ beqz(a0, offset);
2022 __ bind(&L);
2023 __ or_(a0, a2, zero_reg);
2024 __ jirl(zero_reg, ra, 0);
2025
2026 // Block 4
2027 __ addi_d(a2, a2, 0x100);
2028 __ addi_d(a2, a2, 0x200);
2029 __ b(&L);
2030
2031 // Block 5
2032 __ addi_d(a2, a2, 0x300);
2033 __ addi_d(a2, a2, 0x400);
2034 __ b(&L);
2035
2036 CodeDesc desc;
2037 assm.GetCode(isolate, &desc);
2038 Handle<Code> code =
2039 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2040
2041 auto f = GeneratedCode<F2>::FromCode(*code);
2042 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value, 0, 0, 0, 0));
2043
2044 return res;
2045 }
2046
TEST(BEQZ)2047 TEST(BEQZ) {
2048 CcTest::InitializeVM();
2049 struct TestCaseBeqz {
2050 int64_t value;
2051 int32_t offset;
2052 uint64_t expected_res;
2053 };
2054
2055 // clang-format off
2056 struct TestCaseBeqz tc[] = {
2057 // value, offset, expected_res
2058 { 0, -6, 0x3 },
2059 { 0, -3, 0x30 },
2060 { 0, 3, 0x300 },
2061 { 0, 6, 0x700 },
2062 { 1, 6, 0 },
2063 };
2064 // clang-format on
2065
2066 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqz);
2067 for (size_t i = 0; i < nr_test_cases; ++i) {
2068 uint64_t res = run_beqz(tc[i].value, tc[i].offset);
2069 CHECK_EQ(tc[i].expected_res, res);
2070 }
2071 }
2072
run_bnez_b(int64_t value,int32_t offset)2073 uint64_t run_bnez_b(int64_t value, int32_t offset) {
2074 // bnez, b.
2075 Isolate* isolate = CcTest::i_isolate();
2076 HandleScope scope(isolate);
2077
2078 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2079
2080 Label main_block, L;
2081 __ li(a2, 0l);
2082 __ b(&main_block);
2083 // Block 1
2084 __ addi_d(a2, a2, 0x1);
2085 __ addi_d(a2, a2, 0x2);
2086 __ b(5);
2087
2088 // Block 2
2089 __ addi_d(a2, a2, 0x10);
2090 __ addi_d(a2, a2, 0x20);
2091 __ b(2);
2092
2093 // Block 3 (Main)
2094 __ bind(&main_block);
2095 __ bnez(a0, offset);
2096 __ bind(&L);
2097 __ or_(a0, a2, zero_reg);
2098 __ jirl(zero_reg, ra, 0);
2099
2100 // Block 4
2101 __ addi_d(a2, a2, 0x100);
2102 __ addi_d(a2, a2, 0x200);
2103 __ b(-4);
2104
2105 // Block 5
2106 __ addi_d(a2, a2, 0x300);
2107 __ addi_d(a2, a2, 0x400);
2108 __ b(-7);
2109
2110 CodeDesc desc;
2111 assm.GetCode(isolate, &desc);
2112 Handle<Code> code =
2113 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2114
2115 auto f = GeneratedCode<F2>::FromCode(*code);
2116 uint64_t res = reinterpret_cast<uint64_t>(f.Call(value, 0, 0, 0, 0));
2117
2118 return res;
2119 }
2120
TEST(BNEZ_B)2121 TEST(BNEZ_B) {
2122 CcTest::InitializeVM();
2123 struct TestCaseBnez {
2124 int64_t value;
2125 int32_t offset;
2126 uint64_t expected_res;
2127 };
2128
2129 // clang-format off
2130 struct TestCaseBnez tc[] = {
2131 // value, offset, expected_res
2132 { 1, -6, 0x3 },
2133 { -2, -3, 0x30 },
2134 { 3, 3, 0x300 },
2135 { -4, 6, 0x700 },
2136 { 0, 6, 0 },
2137 };
2138 // clang-format on
2139
2140 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBnez);
2141 for (size_t i = 0; i < nr_test_cases; ++i) {
2142 uint64_t res = run_bnez_b(tc[i].value, tc[i].offset);
2143 CHECK_EQ(tc[i].expected_res, res);
2144 }
2145 }
2146
run_bl(int32_t offset)2147 uint64_t run_bl(int32_t offset) {
2148 Isolate* isolate = CcTest::i_isolate();
2149 HandleScope scope(isolate);
2150
2151 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2152
2153 Label main_block;
2154 __ li(a2, 0l);
2155 __ Push(ra); // Push is implemented by two instructions, addi_d and st_d
2156 __ b(&main_block);
2157
2158 // Block 1
2159 __ addi_d(a2, a2, 0x1);
2160 __ addi_d(a2, a2, 0x2);
2161 __ jirl(zero_reg, ra, 0);
2162
2163 // Block 2
2164 __ addi_d(a2, a2, 0x10);
2165 __ addi_d(a2, a2, 0x20);
2166 __ jirl(zero_reg, ra, 0);
2167
2168 // Block 3 (Main)
2169 __ bind(&main_block);
2170 __ bl(offset);
2171 __ or_(a0, a2, zero_reg);
2172 __ Pop(ra); // Pop is implemented by two instructions, ld_d and addi_d.
2173 __ jirl(zero_reg, ra, 0);
2174
2175 // Block 4
2176 __ addi_d(a2, a2, 0x100);
2177 __ addi_d(a2, a2, 0x200);
2178 __ jirl(zero_reg, ra, 0);
2179
2180 // Block 5
2181 __ addi_d(a2, a2, 0x300);
2182 __ addi_d(a2, a2, 0x400);
2183 __ jirl(zero_reg, ra, 0);
2184
2185 CodeDesc desc;
2186 assm.GetCode(isolate, &desc);
2187 Handle<Code> code =
2188 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2189
2190 auto f = GeneratedCode<F2>::FromCode(*code);
2191 uint64_t res = reinterpret_cast<uint64_t>(f.Call(0, 0, 0, 0, 0));
2192
2193 return res;
2194 }
2195
TEST(BL)2196 TEST(BL) {
2197 CcTest::InitializeVM();
2198 struct TestCaseBl {
2199 int32_t offset;
2200 uint64_t expected_res;
2201 };
2202
2203 // clang-format off
2204 struct TestCaseBl tc[] = {
2205 // offset, expected_res
2206 { -6, 0x3 },
2207 { -3, 0x30 },
2208 { 5, 0x300 },
2209 { 8, 0x700 },
2210 };
2211 // clang-format on
2212
2213 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBl);
2214 for (size_t i = 0; i < nr_test_cases; ++i) {
2215 uint64_t res = run_bl(tc[i].offset);
2216 CHECK_EQ(tc[i].expected_res, res);
2217 }
2218 }
2219
TEST(PCADD)2220 TEST(PCADD) {
2221 CcTest::InitializeVM();
2222 Isolate* isolate = CcTest::i_isolate();
2223 HandleScope scope(isolate);
2224
2225 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2226
2227 Label exit, error;
2228 __ Push(ra);
2229
2230 // pcaddi
2231 __ li(a4, 0x1FFFFC);
2232 __ li(a5, 0);
2233 __ li(a6, static_cast<int32_t>(0xFFE00000));
2234
2235 __ bl(1);
2236 __ pcaddi(a3, 0x7FFFF);
2237 __ add_d(a2, ra, a4);
2238 __ Branch(&error, ne, a2, Operand(a3));
2239
2240 __ bl(1);
2241 __ pcaddi(a3, 0);
2242 __ add_d(a2, ra, a5);
2243 __ Branch(&error, ne, a2, Operand(a3));
2244
2245 __ bl(1);
2246 __ pcaddi(a3, 0x80000);
2247 __ add_d(a2, ra, a6);
2248 __ Branch(&error, ne, a2, Operand(a3));
2249
2250 // pcaddu12i
2251 __ li(a4, 0x7FFFF000);
2252 __ li(a5, 0);
2253 __ li(a6, static_cast<int32_t>(0x80000000));
2254
2255 __ bl(1);
2256 __ pcaddu12i(a2, 0x7FFFF);
2257 __ add_d(a3, ra, a4);
2258 __ Branch(&error, ne, a2, Operand(a3));
2259 __ bl(1);
2260 __ pcaddu12i(a2, 0);
2261 __ add_d(a3, ra, a5);
2262 __ Branch(&error, ne, a2, Operand(a3));
2263 __ bl(1);
2264 __ pcaddu12i(a2, 0x80000);
2265 __ add_d(a3, ra, a6);
2266 __ Branch(&error, ne, a2, Operand(a3));
2267
2268 // pcaddu18i
2269 __ li(a4, 0x1FFFFC0000);
2270 __ li(a5, 0);
2271 __ li(a6, static_cast<int64_t>(0xFFFFFFE000000000));
2272
2273 __ bl(1);
2274 __ pcaddu18i(a2, 0x7FFFF);
2275 __ add_d(a3, ra, a4);
2276 __ Branch(&error, ne, a2, Operand(a3));
2277
2278 __ bl(1);
2279 __ pcaddu18i(a2, 0);
2280 __ add_d(a3, ra, a5);
2281 __ Branch(&error, ne, a2, Operand(a3));
2282
2283 __ bl(1);
2284 __ pcaddu18i(a2, 0x80000);
2285 __ add_d(a3, ra, a6);
2286 __ Branch(&error, ne, a2, Operand(a3));
2287
2288 // pcalau12i
2289 __ li(a4, 0x7FFFF000);
2290 __ li(a5, 0);
2291 __ li(a6, static_cast<int32_t>(0x80000000));
2292 __ li(a7, static_cast<int64_t>(0xFFFFFFFFFFFFF000));
2293
2294 __ bl(1);
2295 __ pcalau12i(a3, 0x7FFFF);
2296 __ add_d(a2, ra, a4);
2297 __ and_(t0, a2, a7);
2298 __ and_(t1, a3, a7);
2299 __ Branch(&error, ne, t0, Operand(t1));
2300
2301 __ bl(1);
2302 __ pcalau12i(a3, 0);
2303 __ add_d(a2, ra, a5);
2304 __ and_(t0, a2, a7);
2305 __ and_(t1, a3, a7);
2306 __ Branch(&error, ne, t0, Operand(t1));
2307
2308 __ bl(1);
2309 __ pcalau12i(a2, 0x80000);
2310 __ add_d(a3, ra, a6);
2311 __ and_(t0, a2, a7);
2312 __ and_(t1, a3, a7);
2313 __ Branch(&error, ne, t0, Operand(t1));
2314
2315 __ li(a0, 0x31415926);
2316 __ b(&exit);
2317
2318 __ bind(&error);
2319 __ li(a0, 0x666);
2320
2321 __ bind(&exit);
2322 __ Pop(ra);
2323 __ jirl(zero_reg, ra, 0);
2324
2325 CodeDesc desc;
2326 assm.GetCode(isolate, &desc);
2327 Handle<Code> code =
2328 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2329 auto f = GeneratedCode<F2>::FromCode(*code);
2330 int64_t res = reinterpret_cast<int64_t>(f.Call(0, 0, 0, 0, 0));
2331
2332 CHECK_EQ(0x31415926L, res);
2333 }
2334
run_jirl(int16_t offset)2335 uint64_t run_jirl(int16_t offset) {
2336 Isolate* isolate = CcTest::i_isolate();
2337 HandleScope scope(isolate);
2338
2339 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2340
2341 Label main_block;
2342 __ li(a2, 0l);
2343 __ Push(ra);
2344 __ b(&main_block);
2345
2346 // Block 1
2347 __ addi_d(a2, a2, 0x1);
2348 __ addi_d(a2, a2, 0x2);
2349 __ jirl(zero_reg, ra, 0);
2350
2351 // Block 2
2352 __ addi_d(a2, a2, 0x10);
2353 __ addi_d(a2, a2, 0x20);
2354 __ jirl(zero_reg, ra, 0);
2355
2356 // Block 3 (Main)
2357 __ bind(&main_block);
2358 __ pcaddi(a3, 1);
2359 __ jirl(ra, a3, offset);
2360 __ or_(a0, a2, zero_reg);
2361 __ Pop(ra); // Pop is implemented by two instructions, ld_d and addi_d.
2362 __ jirl(zero_reg, ra, 0);
2363
2364 // Block 4
2365 __ addi_d(a2, a2, 0x100);
2366 __ addi_d(a2, a2, 0x200);
2367 __ jirl(zero_reg, ra, 0);
2368
2369 // Block 5
2370 __ addi_d(a2, a2, 0x300);
2371 __ addi_d(a2, a2, 0x400);
2372 __ jirl(zero_reg, ra, 0);
2373
2374 CodeDesc desc;
2375 assm.GetCode(isolate, &desc);
2376 Handle<Code> code =
2377 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2378
2379 auto f = GeneratedCode<F2>::FromCode(*code);
2380 uint64_t res = reinterpret_cast<uint64_t>(f.Call(0, 0, 0, 0, 0));
2381
2382 return res;
2383 }
2384
TEST(JIRL)2385 TEST(JIRL) {
2386 CcTest::InitializeVM();
2387 struct TestCaseJirl {
2388 int16_t offset;
2389 uint64_t expected_res;
2390 };
2391
2392 // clang-format off
2393 struct TestCaseJirl tc[] = {
2394 // offset, expected_res
2395 { -7, 0x3 },
2396 { -4, 0x30 },
2397 { 5, 0x300 },
2398 { 8, 0x700 },
2399 };
2400 // clang-format on
2401
2402 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJirl);
2403 for (size_t i = 0; i < nr_test_cases; ++i) {
2404 uint64_t res = run_jirl(tc[i].offset);
2405 CHECK_EQ(tc[i].expected_res, res);
2406 }
2407 }
2408
TEST(LA12)2409 TEST(LA12) {
2410 // Test floating point calculate instructions.
2411 CcTest::InitializeVM();
2412 Isolate* isolate = CcTest::i_isolate();
2413 HandleScope scope(isolate);
2414
2415 struct T {
2416 double a;
2417 double b;
2418 double c;
2419 double d;
2420 double e;
2421 double f;
2422 double result_fadd_d;
2423 double result_fsub_d;
2424 double result_fmul_d;
2425 double result_fdiv_d;
2426 double result_fmadd_d;
2427 double result_fmsub_d;
2428 double result_fnmadd_d;
2429 double result_fnmsub_d;
2430 double result_fsqrt_d;
2431 double result_frecip_d;
2432 double result_frsqrt_d;
2433 double result_fscaleb_d;
2434 double result_flogb_d;
2435 double result_fcopysign_d;
2436 double result_fclass_d;
2437 };
2438 T t;
2439
2440 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2441
2442 // Double precision floating point instructions.
2443 __ Fld_d(f8, MemOperand(a0, offsetof(T, a)));
2444 __ Fld_d(f9, MemOperand(a0, offsetof(T, b)));
2445
2446 __ fneg_d(f10, f8);
2447 __ fadd_d(f11, f9, f10);
2448 __ Fst_d(f11, MemOperand(a0, offsetof(T, result_fadd_d)));
2449 __ fabs_d(f11, f11);
2450 __ fsub_d(f12, f11, f9);
2451 __ Fst_d(f12, MemOperand(a0, offsetof(T, result_fsub_d)));
2452
2453 __ Fld_d(f13, MemOperand(a0, offsetof(T, c)));
2454 __ Fld_d(f14, MemOperand(a0, offsetof(T, d)));
2455 __ Fld_d(f15, MemOperand(a0, offsetof(T, e)));
2456
2457 __ fmin_d(f16, f13, f14);
2458 __ fmul_d(f17, f15, f16);
2459 __ Fst_d(f17, MemOperand(a0, offsetof(T, result_fmul_d)));
2460 __ fmax_d(f18, f13, f14);
2461 __ fdiv_d(f19, f15, f18);
2462 __ Fst_d(f19, MemOperand(a0, offsetof(T, result_fdiv_d)));
2463
2464 __ fmina_d(f16, f13, f14);
2465 __ fmadd_d(f18, f17, f15, f16);
2466 __ Fst_d(f18, MemOperand(a0, offsetof(T, result_fmadd_d)));
2467 __ fnmadd_d(f19, f17, f15, f16);
2468 __ Fst_d(f19, MemOperand(a0, offsetof(T, result_fnmadd_d)));
2469 __ fmaxa_d(f16, f13, f14);
2470 __ fmsub_d(f20, f17, f15, f16);
2471 __ Fst_d(f20, MemOperand(a0, offsetof(T, result_fmsub_d)));
2472 __ fnmsub_d(f21, f17, f15, f16);
2473 __ Fst_d(f21, MemOperand(a0, offsetof(T, result_fnmsub_d)));
2474
2475 __ Fld_d(f8, MemOperand(a0, offsetof(T, f)));
2476 __ fsqrt_d(f10, f8);
2477 __ Fst_d(f10, MemOperand(a0, offsetof(T, result_fsqrt_d)));
2478 //__ frecip_d(f11, f10);
2479 //__ frsqrt_d(f12, f8);
2480 //__ Fst_d(f11, MemOperand(a0, offsetof(T, result_frecip_d)));
2481 //__ Fst_d(f12, MemOperand(a0, offsetof(T, result_frsqrt_d)));
2482
2483 /*__ fscaleb_d(f16, f13, f15);
2484 __ flogb_d(f17, f15);
2485 __ fcopysign_d(f18, f8, f9);
2486 __ fclass_d(f19, f9);
2487 __ Fst_d(f16, MemOperand(a0, offsetof(T, result_fscaleb_d)));
2488 __ Fst_d(f17, MemOperand(a0, offsetof(T, result_flogb_d)));
2489 __ Fst_d(f18, MemOperand(a0, offsetof(T, result_fcopysign_d)));
2490 __ Fst_d(f19, MemOperand(a0, offsetof(T, result_fclass_d)));*/
2491
2492 __ jirl(zero_reg, ra, 0);
2493
2494 CodeDesc desc;
2495 assm.GetCode(isolate, &desc);
2496 Handle<Code> code =
2497 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2498 auto f = GeneratedCode<F3>::FromCode(*code);
2499 // Double test values.
2500 t.a = 1.5e14;
2501 t.b = -2.75e11;
2502 t.c = 1.5;
2503 t.d = -2.75;
2504 t.e = 120.0;
2505 t.f = 120.44;
2506 f.Call(&t, 0, 0, 0, 0);
2507
2508 CHECK_EQ(static_cast<double>(-1.502750e14), t.result_fadd_d);
2509 CHECK_EQ(static_cast<double>(1.505500e14), t.result_fsub_d);
2510 CHECK_EQ(static_cast<double>(-3.300000e02), t.result_fmul_d);
2511 CHECK_EQ(static_cast<double>(8.000000e01), t.result_fdiv_d);
2512 CHECK_EQ(static_cast<double>(-3.959850e04), t.result_fmadd_d);
2513 CHECK_EQ(static_cast<double>(-3.959725e04), t.result_fmsub_d);
2514 CHECK_EQ(static_cast<double>(3.959850e04), t.result_fnmadd_d);
2515 CHECK_EQ(static_cast<double>(3.959725e04), t.result_fnmsub_d);
2516 CHECK_EQ(static_cast<double>(10.97451593465515908537), t.result_fsqrt_d);
2517 // CHECK_EQ(static_cast<double>( 8.164965e-08), t.result_frecip_d);
2518 // CHECK_EQ(static_cast<double>( 8.164966e-08), t.result_frsqrt_d);
2519 // CHECK_EQ(static_cast<double>(), t.result_fscaleb_d);
2520 // CHECK_EQ(static_cast<double>( 6.906891), t.result_flogb_d);
2521 // CHECK_EQ(static_cast<double>( 2.75e11), t.result_fcopysign_d);
2522 // CHECK_EQ(static_cast<double>(), t.result_fclass_d);
2523 }
2524
TEST(LA13)2525 TEST(LA13) {
2526 CcTest::InitializeVM();
2527 Isolate* isolate = CcTest::i_isolate();
2528 HandleScope scope(isolate);
2529
2530 struct T {
2531 float a;
2532 float b;
2533 float c;
2534 float d;
2535 float e;
2536 float result_fadd_s;
2537 float result_fsub_s;
2538 float result_fmul_s;
2539 float result_fdiv_s;
2540 float result_fmadd_s;
2541 float result_fmsub_s;
2542 float result_fnmadd_s;
2543 float result_fnmsub_s;
2544 float result_fsqrt_s;
2545 float result_frecip_s;
2546 float result_frsqrt_s;
2547 float result_fscaleb_s;
2548 float result_flogb_s;
2549 float result_fcopysign_s;
2550 float result_fclass_s;
2551 };
2552 T t;
2553
2554 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2555
2556 // Float precision floating point instructions.
2557 __ Fld_s(f8, MemOperand(a0, offsetof(T, a)));
2558 __ Fld_s(f9, MemOperand(a0, offsetof(T, b)));
2559
2560 __ fneg_s(f10, f8);
2561 __ fadd_s(f11, f9, f10);
2562 __ Fst_s(f11, MemOperand(a0, offsetof(T, result_fadd_s)));
2563 __ fabs_s(f11, f11);
2564 __ fsub_s(f12, f11, f9);
2565 __ Fst_s(f12, MemOperand(a0, offsetof(T, result_fsub_s)));
2566
2567 __ Fld_s(f13, MemOperand(a0, offsetof(T, c)));
2568 __ Fld_s(f14, MemOperand(a0, offsetof(T, d)));
2569 __ Fld_s(f15, MemOperand(a0, offsetof(T, e)));
2570
2571 __ fmin_s(f16, f13, f14);
2572 __ fmul_s(f17, f15, f16);
2573 __ Fst_s(f17, MemOperand(a0, offsetof(T, result_fmul_s)));
2574 __ fmax_s(f18, f13, f14);
2575 __ fdiv_s(f19, f15, f18);
2576 __ Fst_s(f19, MemOperand(a0, offsetof(T, result_fdiv_s)));
2577
2578 __ fmina_s(f16, f13, f14);
2579 __ fmadd_s(f18, f17, f15, f16);
2580 __ Fst_s(f18, MemOperand(a0, offsetof(T, result_fmadd_s)));
2581 __ fnmadd_s(f19, f17, f15, f16);
2582 __ Fst_s(f19, MemOperand(a0, offsetof(T, result_fnmadd_s)));
2583 __ fmaxa_s(f16, f13, f14);
2584 __ fmsub_s(f20, f17, f15, f16);
2585 __ Fst_s(f20, MemOperand(a0, offsetof(T, result_fmsub_s)));
2586 __ fnmsub_s(f21, f17, f15, f16);
2587 __ Fst_s(f21, MemOperand(a0, offsetof(T, result_fnmsub_s)));
2588
2589 __ fsqrt_s(f10, f8);
2590 //__ frecip_s(f11, f10);
2591 //__ frsqrt_s(f12, f8);
2592 __ Fst_s(f10, MemOperand(a0, offsetof(T, result_fsqrt_s)));
2593 //__ Fst_s(f11, MemOperand(a0, offsetof(T, result_frecip_s)));
2594 //__ Fst_s(f12, MemOperand(a0, offsetof(T, result_frsqrt_s)));
2595
2596 /*__ fscaleb_s(f16, f13, f15);
2597 __ flogb_s(f17, f15);
2598 __ fcopysign_s(f18, f8, f9);
2599 __ fclass_s(f19, f9);
2600 __ Fst_s(f16, MemOperand(a0, offsetof(T, result_fscaleb_s)));
2601 __ Fst_s(f17, MemOperand(a0, offsetof(T, result_flogb_s)));
2602 __ Fst_s(f18, MemOperand(a0, offsetof(T, result_fcopysign_s)));
2603 __ Fst_s(f19, MemOperand(a0, offsetof(T, result_fclass_s)));*/
2604 __ jirl(zero_reg, ra, 0);
2605
2606 CodeDesc desc;
2607 assm.GetCode(isolate, &desc);
2608 Handle<Code> code =
2609 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2610 auto f = GeneratedCode<F3>::FromCode(*code);
2611 // Float test values.
2612 t.a = 1.5e6;
2613 t.b = -2.75e4;
2614 t.c = 1.5;
2615 t.d = -2.75;
2616 t.e = 120.0;
2617 f.Call(&t, 0, 0, 0, 0);
2618
2619 CHECK_EQ(static_cast<float>(-1.527500e06), t.result_fadd_s);
2620 CHECK_EQ(static_cast<float>(1.555000e06), t.result_fsub_s);
2621 CHECK_EQ(static_cast<float>(-3.300000e02), t.result_fmul_s);
2622 CHECK_EQ(static_cast<float>(8.000000e01), t.result_fdiv_s);
2623 CHECK_EQ(static_cast<float>(-3.959850e04), t.result_fmadd_s);
2624 CHECK_EQ(static_cast<float>(-3.959725e04), t.result_fmsub_s);
2625 CHECK_EQ(static_cast<float>(3.959850e04), t.result_fnmadd_s);
2626 CHECK_EQ(static_cast<float>(3.959725e04), t.result_fnmsub_s);
2627 CHECK_EQ(static_cast<float>(1224.744873), t.result_fsqrt_s);
2628 // CHECK_EQ(static_cast<float>( 8.164966e-04), t.result_frecip_s);
2629 // CHECK_EQ(static_cast<float>( 8.164966e-04), t.result_frsqrt_s);
2630 // CHECK_EQ(static_cast<float>(), t.result_fscaleb_s);
2631 // CHECK_EQ(static_cast<float>( 6.906890), t.result_flogb_s);
2632 // CHECK_EQ(static_cast<float>( 2.75e4), t.result_fcopysign_s);
2633 // CHECK_EQ(static_cast<float>(), t.result_fclass_s);
2634 }
2635
TEST(FCMP_COND)2636 TEST(FCMP_COND) {
2637 CcTest::InitializeVM();
2638 Isolate* isolate = CcTest::i_isolate();
2639 HandleScope scope(isolate);
2640 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
2641
2642 struct TestFloat {
2643 double dTrue;
2644 double dFalse;
2645 double dOp1;
2646 double dOp2;
2647 double dCaf;
2648 double dCun;
2649 double dCeq;
2650 double dCueq;
2651 double dClt;
2652 double dCult;
2653 double dCle;
2654 double dCule;
2655 double dCne;
2656 double dCor;
2657 double dCune;
2658 double dSaf;
2659 double dSun;
2660 double dSeq;
2661 double dSueq;
2662 double dSlt;
2663 double dSult;
2664 double dSle;
2665 double dSule;
2666 double dSne;
2667 double dSor;
2668 double dSune;
2669 float fTrue;
2670 float fFalse;
2671 float fOp1;
2672 float fOp2;
2673 float fCaf;
2674 float fCun;
2675 float fCeq;
2676 float fCueq;
2677 float fClt;
2678 float fCult;
2679 float fCle;
2680 float fCule;
2681 float fCne;
2682 float fCor;
2683 float fCune;
2684 float fSaf;
2685 float fSun;
2686 float fSeq;
2687 float fSueq;
2688 float fSlt;
2689 float fSult;
2690 float fSle;
2691 float fSule;
2692 float fSne;
2693 float fSor;
2694 float fSune;
2695 };
2696
2697 TestFloat test;
2698
2699 __ Fld_d(f8, MemOperand(a0, offsetof(TestFloat, dOp1)));
2700 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, dOp2)));
2701
2702 __ Fld_s(f10, MemOperand(a0, offsetof(TestFloat, fOp1)));
2703 __ Fld_s(f11, MemOperand(a0, offsetof(TestFloat, fOp2)));
2704
2705 __ Fld_d(f12, MemOperand(a0, offsetof(TestFloat, dFalse)));
2706 __ Fld_d(f13, MemOperand(a0, offsetof(TestFloat, dTrue)));
2707
2708 __ Fld_s(f14, MemOperand(a0, offsetof(TestFloat, fFalse)));
2709 __ Fld_s(f15, MemOperand(a0, offsetof(TestFloat, fTrue)));
2710
2711 __ fcmp_cond_d(CAF, f8, f9, FCC0);
2712 __ fcmp_cond_s(CAF, f10, f11, FCC1);
2713 __ fsel(FCC0, f16, f12, f13);
2714 __ fsel(FCC1, f17, f14, f15);
2715 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCaf)));
2716 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCaf)));
2717
2718 __ fcmp_cond_d(CUN, f8, f9, FCC0);
2719 __ fcmp_cond_s(CUN, f10, f11, FCC1);
2720 __ fsel(FCC0, f16, f12, f13);
2721 __ fsel(FCC1, f17, f14, f15);
2722 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCun)));
2723 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCun)));
2724
2725 __ fcmp_cond_d(CEQ, f8, f9, FCC0);
2726 __ fcmp_cond_s(CEQ, f10, f11, FCC1);
2727 __ fsel(FCC0, f16, f12, f13);
2728 __ fsel(FCC1, f17, f14, f15);
2729 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCeq)));
2730 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCeq)));
2731
2732 __ fcmp_cond_d(CUEQ, f8, f9, FCC0);
2733 __ fcmp_cond_s(CUEQ, f10, f11, FCC1);
2734 __ fsel(FCC0, f16, f12, f13);
2735 __ fsel(FCC1, f17, f14, f15);
2736 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCueq)));
2737 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCueq)));
2738
2739 __ fcmp_cond_d(CLT, f8, f9, FCC0);
2740 __ fcmp_cond_s(CLT, f10, f11, FCC1);
2741 __ fsel(FCC0, f16, f12, f13);
2742 __ fsel(FCC1, f17, f14, f15);
2743 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dClt)));
2744 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fClt)));
2745
2746 __ fcmp_cond_d(CULT, f8, f9, FCC0);
2747 __ fcmp_cond_s(CULT, f10, f11, FCC1);
2748 __ fsel(FCC0, f16, f12, f13);
2749 __ fsel(FCC1, f17, f14, f15);
2750 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCult)));
2751 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCult)));
2752
2753 __ fcmp_cond_d(CLE, f8, f9, FCC0);
2754 __ fcmp_cond_s(CLE, f10, f11, FCC1);
2755 __ fsel(FCC0, f16, f12, f13);
2756 __ fsel(FCC1, f17, f14, f15);
2757 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCle)));
2758 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCle)));
2759
2760 __ fcmp_cond_d(CULE, f8, f9, FCC0);
2761 __ fcmp_cond_s(CULE, f10, f11, FCC1);
2762 __ fsel(FCC0, f16, f12, f13);
2763 __ fsel(FCC1, f17, f14, f15);
2764 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCule)));
2765 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCule)));
2766
2767 __ fcmp_cond_d(CNE, f8, f9, FCC0);
2768 __ fcmp_cond_s(CNE, f10, f11, FCC1);
2769 __ fsel(FCC0, f16, f12, f13);
2770 __ fsel(FCC1, f17, f14, f15);
2771 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCne)));
2772 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCne)));
2773
2774 __ fcmp_cond_d(COR, f8, f9, FCC0);
2775 __ fcmp_cond_s(COR, f10, f11, FCC1);
2776 __ fsel(FCC0, f16, f12, f13);
2777 __ fsel(FCC1, f17, f14, f15);
2778 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCor)));
2779 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCor)));
2780
2781 __ fcmp_cond_d(CUNE, f8, f9, FCC0);
2782 __ fcmp_cond_s(CUNE, f10, f11, FCC1);
2783 __ fsel(FCC0, f16, f12, f13);
2784 __ fsel(FCC1, f17, f14, f15);
2785 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dCune)));
2786 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fCune)));
2787
2788 /* __ fcmp_cond_d(SAF, f8, f9, FCC0);
2789 __ fcmp_cond_s(SAF, f10, f11, FCC1);
2790 __ fsel(FCC0, f16, f12, f13);
2791 __ fsel(FCC1, f17, f14, f15);
2792 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSaf)));
2793 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fSaf)));
2794
2795 __ fcmp_cond_d(SUN, f8, f9, FCC0);
2796 __ fcmp_cond_s(SUN, f10, f11, FCC1);
2797 __ fsel(FCC0, f16, f12, f13);
2798 __ fsel(FCC1, f17, f14, f15);
2799 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSun)));
2800 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fSun)));
2801
2802 __ fcmp_cond_d(SEQ, f8, f9, FCC0);
2803 __ fcmp_cond_s(SEQ, f10, f11, FCC1);
2804 __ fsel(FCC0, f16, f12, f13);
2805 __ fsel(FCC1, f17, f14, f15);
2806 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSeq)));
2807 __ Fst_f(f17, MemOperand(a0, offsetof(TestFloat, fSeq)));
2808
2809 __ fcmp_cond_d(SUEQ, f8, f9, FCC0);
2810 __ fcmp_cond_s(SUEQ, f10, f11, FCC1);
2811 __ fsel(FCC0, f16, f12, f13);
2812 __ fsel(FCC1, f17, f14, f15);
2813 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSueq)));
2814 __ Fst_f(f17, MemOperand(a0, offsetof(TestFloat, fSueq)));
2815
2816 __ fcmp_cond_d(SLT, f8, f9, FCC0);
2817 __ fcmp_cond_s(SLT, f10, f11, FCC1);
2818 __ fsel(f16, f12, f13, FCC0);
2819 __ fsel(f17, f14, f15, FCC1);
2820 __ Fld_d(f16, MemOperand(a0, offsetof(TestFloat, dSlt)));
2821 __ Fst_d(f17, MemOperand(a0, offsetof(TestFloat, fSlt)));
2822
2823 __ fcmp_cond_d(SULT, f8, f9, FCC0);
2824 __ fcmp_cond_s(SULT, f10, f11, FCC1);
2825 __ fsel(FCC0, f16, f12, f13);
2826 __ fsel(FCC1, f17, f14, f15);
2827 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSult)));
2828 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fSult)));
2829
2830 __ fcmp_cond_d(SLE, f8, f9, FCC0);
2831 __ fcmp_cond_s(SLE, f10, f11, FCC1);
2832 __ fsel(FCC0, f16, f12, f13);
2833 __ fsel(FCC1, f17, f14, f15);
2834 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSle)));
2835 __ Fst_f(f17, MemOperand(a0, offsetof(TestFloat, fSle)));
2836
2837 __ fcmp_cond_d(SULE, f8, f9, FCC0);
2838 __ fcmp_cond_s(SULE, f10, f11, FCC1);
2839 __ fsel(FCC0, f16, f12, f13);
2840 __ fsel(FCC1, f17, f14, f15);
2841 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSule)));
2842 __ Fst_f(f17, MemOperand(a0, offsetof(TestFloat, fSule)));
2843
2844 __ fcmp_cond_d(SNE, f8, f9, FCC0);
2845 __ fcmp_cond_s(SNE, f10, f11, FCC1);
2846 __ fsel(FCC0, f16, f12, f13);
2847 __ fsel(FCC1, f17, f14, f15);
2848 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSne)));
2849 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fSne)));
2850
2851 __ fcmp_cond_d(SOR, f8, f9, FCC0);
2852 __ fcmp_cond_s(SOR, f10, f11, FCC1);
2853 __ fsel(FCC0, f16, f12, f13);
2854 __ fsel(FCC1, f17, f14, f15);
2855 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSor)));
2856 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fSor)));
2857
2858 __ fcmp_cond_d(SUNE, f8, f9, FCC0);
2859 __ fcmp_cond_s(SUNE, f10, f11, FCC1);
2860 __ fsel(FCC0, f16, f12, f13);
2861 __ fsel(FCC1, f17, f14, f15);
2862 __ Fst_d(f16, MemOperand(a0, offsetof(TestFloat, dSune)));
2863 __ Fst_s(f17, MemOperand(a0, offsetof(TestFloat, fSune)));*/
2864
2865 __ jirl(zero_reg, ra, 0);
2866
2867 CodeDesc desc;
2868 assm.GetCode(isolate, &desc);
2869 Handle<Code> code =
2870 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
2871 auto f = GeneratedCode<F3>::FromCode(*code);
2872 test.dTrue = 1234.0;
2873 test.dFalse = 0.0;
2874 test.fTrue = 12.0;
2875 test.fFalse = 0.0;
2876
2877 test.dOp1 = 2.0;
2878 test.dOp2 = 3.0;
2879 test.fOp1 = 2.0;
2880 test.fOp2 = 3.0;
2881 f.Call(&test, 0, 0, 0, 0);
2882
2883 CHECK_EQ(test.dCaf, test.dFalse);
2884 CHECK_EQ(test.fCaf, test.fFalse);
2885 CHECK_EQ(test.dCun, test.dFalse);
2886 CHECK_EQ(test.fCun, test.fFalse);
2887 CHECK_EQ(test.dCeq, test.dFalse);
2888 CHECK_EQ(test.fCeq, test.fFalse);
2889 CHECK_EQ(test.dCueq, test.dFalse);
2890 CHECK_EQ(test.fCueq, test.fFalse);
2891 CHECK_EQ(test.dClt, test.dTrue);
2892 CHECK_EQ(test.fClt, test.fTrue);
2893 CHECK_EQ(test.dCult, test.dTrue);
2894 CHECK_EQ(test.fCult, test.fTrue);
2895 CHECK_EQ(test.dCle, test.dTrue);
2896 CHECK_EQ(test.fCle, test.fTrue);
2897 CHECK_EQ(test.dCule, test.dTrue);
2898 CHECK_EQ(test.fCule, test.fTrue);
2899 CHECK_EQ(test.dCne, test.dTrue);
2900 CHECK_EQ(test.fCne, test.fTrue);
2901 CHECK_EQ(test.dCor, test.dTrue);
2902 CHECK_EQ(test.fCor, test.fTrue);
2903 CHECK_EQ(test.dCune, test.dTrue);
2904 CHECK_EQ(test.fCune, test.fTrue);
2905 /* CHECK_EQ(test.dSaf, test.dFalse);
2906 CHECK_EQ(test.fSaf, test.fFalse);
2907 CHECK_EQ(test.dSun, test.dFalse);
2908 CHECK_EQ(test.fSun, test.fFalse);
2909 CHECK_EQ(test.dSeq, test.dFalse);
2910 CHECK_EQ(test.fSeq, test.fFalse);
2911 CHECK_EQ(test.dSueq, test.dFalse);
2912 CHECK_EQ(test.fSueq, test.fFalse);
2913 CHECK_EQ(test.dClt, test.dTrue);
2914 CHECK_EQ(test.fClt, test.fTrue);
2915 CHECK_EQ(test.dCult, test.dTrue);
2916 CHECK_EQ(test.fCult, test.fTrue);
2917 CHECK_EQ(test.dSle, test.dTrue);
2918 CHECK_EQ(test.fSle, test.fTrue);
2919 CHECK_EQ(test.dSule, test.dTrue);
2920 CHECK_EQ(test.fSule, test.fTrue);
2921 CHECK_EQ(test.dSne, test.dTrue);
2922 CHECK_EQ(test.fSne, test.fTrue);
2923 CHECK_EQ(test.dSor, test.dTrue);
2924 CHECK_EQ(test.fSor, test.fTrue);
2925 CHECK_EQ(test.dSune, test.dTrue);
2926 CHECK_EQ(test.fSune, test.fTrue);*/
2927
2928 test.dOp1 = std::numeric_limits<double>::max();
2929 test.dOp2 = std::numeric_limits<double>::min();
2930 test.fOp1 = std::numeric_limits<float>::min();
2931 test.fOp2 = -std::numeric_limits<float>::max();
2932 f.Call(&test, 0, 0, 0, 0);
2933
2934 CHECK_EQ(test.dCaf, test.dFalse);
2935 CHECK_EQ(test.fCaf, test.fFalse);
2936 CHECK_EQ(test.dCun, test.dFalse);
2937 CHECK_EQ(test.fCun, test.fFalse);
2938 CHECK_EQ(test.dCeq, test.dFalse);
2939 CHECK_EQ(test.fCeq, test.fFalse);
2940 CHECK_EQ(test.dCueq, test.dFalse);
2941 CHECK_EQ(test.fCueq, test.fFalse);
2942 CHECK_EQ(test.dClt, test.dFalse);
2943 CHECK_EQ(test.fClt, test.fFalse);
2944 CHECK_EQ(test.dCult, test.dFalse);
2945 CHECK_EQ(test.fCult, test.fFalse);
2946 CHECK_EQ(test.dCle, test.dFalse);
2947 CHECK_EQ(test.fCle, test.fFalse);
2948 CHECK_EQ(test.dCule, test.dFalse);
2949 CHECK_EQ(test.fCule, test.fFalse);
2950 CHECK_EQ(test.dCne, test.dTrue);
2951 CHECK_EQ(test.fCne, test.fTrue);
2952 CHECK_EQ(test.dCor, test.dTrue);
2953 CHECK_EQ(test.fCor, test.fTrue);
2954 CHECK_EQ(test.dCune, test.dTrue);
2955 CHECK_EQ(test.fCune, test.fTrue);
2956 /* CHECK_EQ(test.dSaf, test.dFalse);
2957 CHECK_EQ(test.fSaf, test.fFalse);
2958 CHECK_EQ(test.dSun, test.dFalse);
2959 CHECK_EQ(test.fSun, test.fFalse);
2960 CHECK_EQ(test.dSeq, test.dFalse);
2961 CHECK_EQ(test.fSeq, test.fFalse);
2962 CHECK_EQ(test.dSueq, test.dFalse);
2963 CHECK_EQ(test.fSueq, test.fFalse);
2964 CHECK_EQ(test.dSlt, test.dFalse);
2965 CHECK_EQ(test.fSlt, test.fFalse);
2966 CHECK_EQ(test.dSult, test.dFalse);
2967 CHECK_EQ(test.fSult, test.fFalse);
2968 CHECK_EQ(test.dSle, test.dFalse);
2969 CHECK_EQ(test.fSle, test.fFalse);
2970 CHECK_EQ(test.dSule, test.dFalse);
2971 CHECK_EQ(test.fSule, test.fFalse);
2972 CHECK_EQ(test.dSne, test.dTrue);
2973 CHECK_EQ(test.fSne, test.fTrue);
2974 CHECK_EQ(test.dSor, test.dTrue);
2975 CHECK_EQ(test.fSor, test.fTrue);
2976 CHECK_EQ(test.dSune, test.dTrue);
2977 CHECK_EQ(test.fSune, test.fTrue);*/
2978
2979 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
2980 test.dOp2 = 0.0;
2981 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
2982 test.fOp2 = 0.0;
2983 f.Call(&test, 0, 0, 0, 0);
2984
2985 CHECK_EQ(test.dCaf, test.dFalse);
2986 CHECK_EQ(test.fCaf, test.fFalse);
2987 CHECK_EQ(test.dCun, test.dTrue);
2988 CHECK_EQ(test.fCun, test.fTrue);
2989 CHECK_EQ(test.dCeq, test.dFalse);
2990 CHECK_EQ(test.fCeq, test.fFalse);
2991 CHECK_EQ(test.dCueq, test.dTrue);
2992 CHECK_EQ(test.fCueq, test.fTrue);
2993 CHECK_EQ(test.dClt, test.dFalse);
2994 CHECK_EQ(test.fClt, test.fFalse);
2995 CHECK_EQ(test.dCult, test.dTrue);
2996 CHECK_EQ(test.fCult, test.fTrue);
2997 CHECK_EQ(test.dCle, test.dFalse);
2998 CHECK_EQ(test.fCle, test.fFalse);
2999 CHECK_EQ(test.dCule, test.dTrue);
3000 CHECK_EQ(test.fCule, test.fTrue);
3001 CHECK_EQ(test.dCne, test.dFalse);
3002 CHECK_EQ(test.fCne, test.fFalse);
3003 CHECK_EQ(test.dCor, test.dFalse);
3004 CHECK_EQ(test.fCor, test.fFalse);
3005 CHECK_EQ(test.dCune, test.dTrue);
3006 CHECK_EQ(test.fCune, test.fTrue);
3007 /* CHECK_EQ(test.dSaf, test.dTrue);
3008 CHECK_EQ(test.fSaf, test.fTrue);
3009 CHECK_EQ(test.dSun, test.dTrue);
3010 CHECK_EQ(test.fSun, test.fTrue);
3011 CHECK_EQ(test.dSeq, test.dFalse);
3012 CHECK_EQ(test.fSeq, test.fFalse);
3013 CHECK_EQ(test.dSueq, test.dTrue);
3014 CHECK_EQ(test.fSueq, test.fTrue);
3015 CHECK_EQ(test.dSlt, test.dFalse);
3016 CHECK_EQ(test.fSlt, test.fFalse);
3017 CHECK_EQ(test.dSult, test.dTrue);
3018 CHECK_EQ(test.fSult, test.fTrue);
3019 CHECK_EQ(test.dSle, test.dFalse);
3020 CHECK_EQ(test.fSle, test.fFalse);
3021 CHECK_EQ(test.dSule, test.dTrue);
3022 CHECK_EQ(test.fSule, test.fTrue);
3023 CHECK_EQ(test.dSne, test.dFalse);
3024 CHECK_EQ(test.fSne, test.fFalse);
3025 CHECK_EQ(test.dSor, test.dFalse);
3026 CHECK_EQ(test.fSor, test.fFalse);
3027 CHECK_EQ(test.dSune, test.dTrue);
3028 CHECK_EQ(test.fSune, test.fTrue);*/
3029 }
3030
TEST(FCVT)3031 TEST(FCVT) {
3032 CcTest::InitializeVM();
3033 Isolate* isolate = CcTest::i_isolate();
3034 HandleScope scope(isolate);
3035 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3036
3037 struct TestFloat {
3038 float fcvt_d_s_in;
3039 double fcvt_s_d_in;
3040 double fcvt_d_s_out;
3041 float fcvt_s_d_out;
3042 int fcsr;
3043 };
3044 TestFloat test;
3045 __ xor_(a4, a4, a4);
3046 __ xor_(a5, a5, a5);
3047 __ Ld_w(a4, MemOperand(a0, offsetof(TestFloat, fcsr)));
3048 __ movfcsr2gr(a5);
3049 __ movgr2fcsr(a4);
3050 __ Fld_s(f8, MemOperand(a0, offsetof(TestFloat, fcvt_d_s_in)));
3051 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, fcvt_s_d_in)));
3052 __ fcvt_d_s(f10, f8);
3053 __ fcvt_s_d(f11, f9);
3054 __ Fst_d(f10, MemOperand(a0, offsetof(TestFloat, fcvt_d_s_out)));
3055 __ Fst_s(f11, MemOperand(a0, offsetof(TestFloat, fcvt_s_d_out)));
3056 __ movgr2fcsr(a5);
3057 __ jirl(zero_reg, ra, 0);
3058
3059 CodeDesc desc;
3060 assm.GetCode(isolate, &desc);
3061 Handle<Code> code =
3062 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3063 auto f = GeneratedCode<F3>::FromCode(*code);
3064 test.fcsr = kRoundToNearest;
3065
3066 test.fcvt_d_s_in = -0.51;
3067 test.fcvt_s_d_in = -0.51;
3068 f.Call(&test, 0, 0, 0, 0);
3069 CHECK_EQ(test.fcvt_d_s_out, static_cast<double>(test.fcvt_d_s_in));
3070 CHECK_EQ(test.fcvt_s_d_out, static_cast<float>(test.fcvt_s_d_in));
3071
3072 test.fcvt_d_s_in = 0.49;
3073 test.fcvt_s_d_in = 0.49;
3074 f.Call(&test, 0, 0, 0, 0);
3075 CHECK_EQ(test.fcvt_d_s_out, static_cast<double>(test.fcvt_d_s_in));
3076 CHECK_EQ(test.fcvt_s_d_out, static_cast<float>(test.fcvt_s_d_in));
3077
3078 test.fcvt_d_s_in = std::numeric_limits<float>::max();
3079 test.fcvt_s_d_in = std::numeric_limits<double>::max();
3080 f.Call(&test, 0, 0, 0, 0);
3081 CHECK_EQ(test.fcvt_d_s_out, static_cast<double>(test.fcvt_d_s_in));
3082 CHECK_EQ(test.fcvt_s_d_out, static_cast<float>(test.fcvt_s_d_in));
3083
3084 test.fcvt_d_s_in = -std::numeric_limits<float>::max();
3085 test.fcvt_s_d_in = -std::numeric_limits<double>::max();
3086 f.Call(&test, 0, 0, 0, 0);
3087 CHECK_EQ(test.fcvt_d_s_out, static_cast<double>(test.fcvt_d_s_in));
3088 CHECK_EQ(test.fcvt_s_d_out, static_cast<float>(test.fcvt_s_d_in));
3089
3090 test.fcvt_d_s_in = std::numeric_limits<float>::min();
3091 test.fcvt_s_d_in = std::numeric_limits<double>::min();
3092 f.Call(&test, 0, 0, 0, 0);
3093 CHECK_EQ(test.fcvt_d_s_out, static_cast<double>(test.fcvt_d_s_in));
3094 CHECK_EQ(test.fcvt_s_d_out, static_cast<float>(test.fcvt_s_d_in));
3095 }
3096
TEST(FFINT)3097 TEST(FFINT) {
3098 CcTest::InitializeVM();
3099 Isolate* isolate = CcTest::i_isolate();
3100 HandleScope scope(isolate);
3101 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3102
3103 struct TestFloat {
3104 int32_t ffint_s_w_in;
3105 int64_t ffint_s_l_in;
3106 int32_t ffint_d_w_in;
3107 int64_t ffint_d_l_in;
3108 float ffint_s_w_out;
3109 float ffint_s_l_out;
3110 double ffint_d_w_out;
3111 double ffint_d_l_out;
3112 int fcsr;
3113 };
3114 TestFloat test;
3115 __ xor_(a4, a4, a4);
3116 __ xor_(a5, a5, a5);
3117 __ Ld_w(a4, MemOperand(a0, offsetof(TestFloat, fcsr)));
3118 __ movfcsr2gr(a5);
3119 __ movgr2fcsr(a4);
3120 __ Fld_s(f8, MemOperand(a0, offsetof(TestFloat, ffint_s_w_in)));
3121 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, ffint_s_l_in)));
3122 __ Fld_s(f10, MemOperand(a0, offsetof(TestFloat, ffint_d_w_in)));
3123 __ Fld_d(f11, MemOperand(a0, offsetof(TestFloat, ffint_d_l_in)));
3124 __ ffint_s_w(f12, f8);
3125 __ ffint_s_l(f13, f9);
3126 __ ffint_d_w(f14, f10);
3127 __ ffint_d_l(f15, f11);
3128 __ Fst_s(f12, MemOperand(a0, offsetof(TestFloat, ffint_s_w_out)));
3129 __ Fst_s(f13, MemOperand(a0, offsetof(TestFloat, ffint_s_l_out)));
3130 __ Fst_d(f14, MemOperand(a0, offsetof(TestFloat, ffint_d_w_out)));
3131 __ Fst_d(f15, MemOperand(a0, offsetof(TestFloat, ffint_d_l_out)));
3132 __ movgr2fcsr(a5);
3133 __ jirl(zero_reg, ra, 0);
3134
3135 CodeDesc desc;
3136 assm.GetCode(isolate, &desc);
3137 Handle<Code> code =
3138 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3139 auto f = GeneratedCode<F3>::FromCode(*code);
3140 test.fcsr = kRoundToNearest;
3141
3142 test.ffint_s_w_in = -1;
3143 test.ffint_s_l_in = -1;
3144 test.ffint_d_w_in = -1;
3145 test.ffint_d_l_in = -1;
3146 f.Call(&test, 0, 0, 0, 0);
3147 CHECK_EQ(test.ffint_s_w_out, static_cast<float>(test.ffint_s_w_in));
3148 CHECK_EQ(test.ffint_s_l_out, static_cast<float>(test.ffint_s_l_in));
3149 CHECK_EQ(test.ffint_d_w_out, static_cast<double>(test.ffint_d_w_in));
3150 CHECK_EQ(test.ffint_d_l_out, static_cast<double>(test.ffint_d_l_in));
3151
3152 test.ffint_s_w_in = 1;
3153 test.ffint_s_l_in = 1;
3154 test.ffint_d_w_in = 1;
3155 test.ffint_d_l_in = 1;
3156 f.Call(&test, 0, 0, 0, 0);
3157 CHECK_EQ(test.ffint_s_w_out, static_cast<float>(test.ffint_s_w_in));
3158 CHECK_EQ(test.ffint_s_l_out, static_cast<float>(test.ffint_s_l_in));
3159 CHECK_EQ(test.ffint_d_w_out, static_cast<double>(test.ffint_d_w_in));
3160 CHECK_EQ(test.ffint_d_l_out, static_cast<double>(test.ffint_d_l_in));
3161
3162 test.ffint_s_w_in = std::numeric_limits<int32_t>::max();
3163 test.ffint_s_l_in = std::numeric_limits<int64_t>::max();
3164 test.ffint_d_w_in = std::numeric_limits<int32_t>::max();
3165 test.ffint_d_l_in = std::numeric_limits<int64_t>::max();
3166 f.Call(&test, 0, 0, 0, 0);
3167 CHECK_EQ(test.ffint_s_w_out, static_cast<float>(test.ffint_s_w_in));
3168 CHECK_EQ(test.ffint_s_l_out, static_cast<float>(test.ffint_s_l_in));
3169 CHECK_EQ(test.ffint_d_w_out, static_cast<double>(test.ffint_d_w_in));
3170 CHECK_EQ(test.ffint_d_l_out, static_cast<double>(test.ffint_d_l_in));
3171
3172 test.ffint_s_w_in = std::numeric_limits<int32_t>::min();
3173 test.ffint_s_l_in = std::numeric_limits<int64_t>::min();
3174 test.ffint_d_w_in = std::numeric_limits<int32_t>::min();
3175 test.ffint_d_l_in = std::numeric_limits<int64_t>::min();
3176 f.Call(&test, 0, 0, 0, 0);
3177 CHECK_EQ(test.ffint_s_w_out, static_cast<float>(test.ffint_s_w_in));
3178 CHECK_EQ(test.ffint_s_l_out, static_cast<float>(test.ffint_s_l_in));
3179 CHECK_EQ(test.ffint_d_w_out, static_cast<double>(test.ffint_d_w_in));
3180 CHECK_EQ(test.ffint_d_l_out, static_cast<double>(test.ffint_d_l_in));
3181 }
3182
TEST(FTINT)3183 TEST(FTINT) {
3184 CcTest::InitializeVM();
3185 Isolate* isolate = CcTest::i_isolate();
3186 HandleScope scope(isolate);
3187 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3188
3189 struct Test {
3190 double a;
3191 float b;
3192 int32_t c;
3193 int32_t d;
3194 int64_t e;
3195 int64_t f;
3196 int fcsr;
3197 };
3198 Test test;
3199
3200 const int kTableLength = 9;
3201 // clang-format off
3202 double inputs_d[kTableLength] = {
3203 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3204 2147483648.0,
3205 std::numeric_limits<double>::quiet_NaN(),
3206 std::numeric_limits<double>::infinity()
3207 };
3208 float inputs_s[kTableLength] = {
3209 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3210 2147483648.0,
3211 std::numeric_limits<double>::quiet_NaN(),
3212 std::numeric_limits<double>::infinity()
3213 };
3214 double outputs_RN_W[kTableLength] = {
3215 3.0, 4.0, 4.0, -3.0, -4.0, -4.0,
3216 kFPUInvalidResult, 0,
3217 kFPUInvalidResult};
3218 double outputs_RN_L[kTableLength] = {
3219 3.0, 4.0, 4.0, -3.0, -4.0, -4.0,
3220 2147483648.0, 0,
3221 static_cast<double>(kFPU64InvalidResult)};
3222 double outputs_RZ_W[kTableLength] = {
3223 3.0, 3.0, 3.0, -3.0, -3.0, -3.0,
3224 kFPUInvalidResult, 0,
3225 kFPUInvalidResult};
3226 double outputs_RZ_L[kTableLength] = {
3227 3.0, 3.0, 3.0, -3.0, -3.0, -3.0,
3228 2147483648.0, 0,
3229 static_cast<double>(kFPU64InvalidResult)};
3230 double outputs_RP_W[kTableLength] = {
3231 4.0, 4.0, 4.0, -3.0, -3.0, -3.0,
3232 kFPUInvalidResult, 0,
3233 kFPUInvalidResult};
3234 double outputs_RP_L[kTableLength] = {
3235 4.0, 4.0, 4.0, -3.0, -3.0, -3.0,
3236 2147483648.0, 0,
3237 static_cast<double>(kFPU64InvalidResult)};
3238 double outputs_RM_W[kTableLength] = {
3239 3.0, 3.0, 3.0, -4.0, -4.0, -4.0,
3240 kFPUInvalidResult, 0,
3241 kFPUInvalidResult};
3242 double outputs_RM_L[kTableLength] = {
3243 3.0, 3.0, 3.0, -4.0, -4.0, -4.0,
3244 2147483648.0, 0,
3245 static_cast<double>(kFPU64InvalidResult)};
3246 // clang-format on
3247
3248 int fcsr_inputs[4] = {kRoundToNearest, kRoundToZero, kRoundToPlusInf,
3249 kRoundToMinusInf};
3250 double* outputs[8] = {
3251 outputs_RN_W, outputs_RN_L, outputs_RZ_W, outputs_RZ_L,
3252 outputs_RP_W, outputs_RP_L, outputs_RM_W, outputs_RM_L,
3253 };
3254
3255 __ Fld_d(f8, MemOperand(a0, offsetof(Test, a)));
3256 __ Fld_s(f9, MemOperand(a0, offsetof(Test, b)));
3257 __ xor_(a5, a5, a5);
3258 __ Ld_w(a5, MemOperand(a0, offsetof(Test, fcsr)));
3259 __ movfcsr2gr(a4);
3260 __ movgr2fcsr(a5);
3261 __ ftint_w_d(f10, f8);
3262 __ ftint_w_s(f11, f9);
3263 __ ftint_l_d(f12, f8);
3264 __ ftint_l_s(f13, f9);
3265 __ Fst_s(f10, MemOperand(a0, offsetof(Test, c)));
3266 __ Fst_s(f11, MemOperand(a0, offsetof(Test, d)));
3267 __ Fst_d(f12, MemOperand(a0, offsetof(Test, e)));
3268 __ Fst_d(f13, MemOperand(a0, offsetof(Test, f)));
3269 __ movgr2fcsr(a4);
3270 __ jirl(zero_reg, ra, 0);
3271
3272 CodeDesc desc;
3273 assm.GetCode(isolate, &desc);
3274 Handle<Code> code =
3275 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3276 auto f = GeneratedCode<F3>::FromCode(*code);
3277 for (int j = 0; j < 4; j++) {
3278 test.fcsr = fcsr_inputs[j];
3279 for (int i = 0; i < kTableLength; i++) {
3280 test.a = inputs_d[i];
3281 test.b = inputs_s[i];
3282 f.Call(&test, 0, 0, 0, 0);
3283 CHECK_EQ(test.c, outputs[2 * j][i]);
3284 CHECK_EQ(test.d, outputs[2 * j][i]);
3285 CHECK_EQ(test.e, outputs[2 * j + 1][i]);
3286 CHECK_EQ(test.f, outputs[2 * j + 1][i]);
3287 }
3288 }
3289 }
3290
TEST(FTINTRM)3291 TEST(FTINTRM) {
3292 CcTest::InitializeVM();
3293 Isolate* isolate = CcTest::i_isolate();
3294 HandleScope scope(isolate);
3295 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3296
3297 struct Test {
3298 double a;
3299 float b;
3300 int32_t c;
3301 int32_t d;
3302 int64_t e;
3303 int64_t f;
3304 };
3305 Test test;
3306
3307 const int kTableLength = 9;
3308
3309 // clang-format off
3310 double inputs_d[kTableLength] = {
3311 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3312 2147483648.0,
3313 std::numeric_limits<double>::quiet_NaN(),
3314 std::numeric_limits<double>::infinity()
3315 };
3316 float inputs_s[kTableLength] = {
3317 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3318 2147483648.0,
3319 std::numeric_limits<double>::quiet_NaN(),
3320 std::numeric_limits<double>::infinity()
3321 };
3322 double outputs_w[kTableLength] = {
3323 3.0, 3.0, 3.0, -4.0, -4.0, -4.0,
3324 kFPUInvalidResult, 0,
3325 kFPUInvalidResult};
3326 double outputs_l[kTableLength] = {
3327 3.0, 3.0, 3.0, -4.0, -4.0, -4.0,
3328 2147483648.0, 0,
3329 static_cast<double>(kFPU64InvalidResult)};
3330 // clang-format on
3331
3332 __ Fld_d(f8, MemOperand(a0, offsetof(Test, a)));
3333 __ Fld_s(f9, MemOperand(a0, offsetof(Test, b)));
3334 __ ftintrm_w_d(f10, f8);
3335 __ ftintrm_w_s(f11, f9);
3336 __ ftintrm_l_d(f12, f8);
3337 __ ftintrm_l_s(f13, f9);
3338 __ Fst_s(f10, MemOperand(a0, offsetof(Test, c)));
3339 __ Fst_s(f11, MemOperand(a0, offsetof(Test, d)));
3340 __ Fst_d(f12, MemOperand(a0, offsetof(Test, e)));
3341 __ Fst_d(f13, MemOperand(a0, offsetof(Test, f)));
3342 __ jirl(zero_reg, ra, 0);
3343
3344 CodeDesc desc;
3345 assm.GetCode(isolate, &desc);
3346 Handle<Code> code =
3347 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3348 auto f = GeneratedCode<F3>::FromCode(*code);
3349 for (int i = 0; i < kTableLength; i++) {
3350 test.a = inputs_d[i];
3351 test.b = inputs_s[i];
3352 f.Call(&test, 0, 0, 0, 0);
3353 CHECK_EQ(test.c, outputs_w[i]);
3354 CHECK_EQ(test.d, outputs_w[i]);
3355 CHECK_EQ(test.e, outputs_l[i]);
3356 CHECK_EQ(test.f, outputs_l[i]);
3357 }
3358 }
3359
TEST(FTINTRP)3360 TEST(FTINTRP) {
3361 CcTest::InitializeVM();
3362 Isolate* isolate = CcTest::i_isolate();
3363 HandleScope scope(isolate);
3364 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3365
3366 struct Test {
3367 double a;
3368 float b;
3369 int32_t c;
3370 int32_t d;
3371 int64_t e;
3372 int64_t f;
3373 };
3374 Test test;
3375
3376 const int kTableLength = 9;
3377
3378 // clang-format off
3379 double inputs_d[kTableLength] = {
3380 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3381 2147483648.0,
3382 std::numeric_limits<double>::quiet_NaN(),
3383 std::numeric_limits<double>::infinity()
3384 };
3385 float inputs_s[kTableLength] = {
3386 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3387 2147483648.0,
3388 std::numeric_limits<double>::quiet_NaN(),
3389 std::numeric_limits<double>::infinity()
3390 };
3391 double outputs_w[kTableLength] = {
3392 4.0, 4.0, 4.0, -3.0, -3.0, -3.0,
3393 kFPUInvalidResult, 0,
3394 kFPUInvalidResult};
3395 double outputs_l[kTableLength] = {
3396 4.0, 4.0, 4.0, -3.0, -3.0, -3.0,
3397 2147483648.0, 0,
3398 static_cast<double>(kFPU64InvalidResult)};
3399 // clang-format on
3400
3401 __ Fld_d(f8, MemOperand(a0, offsetof(Test, a)));
3402 __ Fld_s(f9, MemOperand(a0, offsetof(Test, b)));
3403 __ ftintrp_w_d(f10, f8);
3404 __ ftintrp_w_s(f11, f9);
3405 __ ftintrp_l_d(f12, f8);
3406 __ ftintrp_l_s(f13, f9);
3407 __ Fst_s(f10, MemOperand(a0, offsetof(Test, c)));
3408 __ Fst_s(f11, MemOperand(a0, offsetof(Test, d)));
3409 __ Fst_d(f12, MemOperand(a0, offsetof(Test, e)));
3410 __ Fst_d(f13, MemOperand(a0, offsetof(Test, f)));
3411 __ jirl(zero_reg, ra, 0);
3412
3413 CodeDesc desc;
3414 assm.GetCode(isolate, &desc);
3415 Handle<Code> code =
3416 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3417 auto f = GeneratedCode<F3>::FromCode(*code);
3418 for (int i = 0; i < kTableLength; i++) {
3419 test.a = inputs_d[i];
3420 test.b = inputs_s[i];
3421 f.Call(&test, 0, 0, 0, 0);
3422 CHECK_EQ(test.c, outputs_w[i]);
3423 CHECK_EQ(test.d, outputs_w[i]);
3424 CHECK_EQ(test.e, outputs_l[i]);
3425 CHECK_EQ(test.f, outputs_l[i]);
3426 }
3427 }
3428
TEST(FTINTRZ)3429 TEST(FTINTRZ) {
3430 CcTest::InitializeVM();
3431 Isolate* isolate = CcTest::i_isolate();
3432 HandleScope scope(isolate);
3433 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3434
3435 struct Test {
3436 double a;
3437 float b;
3438 int32_t c;
3439 int32_t d;
3440 int64_t e;
3441 int64_t f;
3442 };
3443 Test test;
3444
3445 const int kTableLength = 9;
3446
3447 // clang-format off
3448 double inputs_d[kTableLength] = {
3449 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3450 2147483648.0,
3451 std::numeric_limits<double>::quiet_NaN(),
3452 std::numeric_limits<double>::infinity()
3453 };
3454 float inputs_s[kTableLength] = {
3455 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3456 2147483648.0,
3457 std::numeric_limits<double>::quiet_NaN(),
3458 std::numeric_limits<double>::infinity()
3459 };
3460 double outputs_w[kTableLength] = {
3461 3.0, 3.0, 3.0, -3.0, -3.0, -3.0,
3462 kFPUInvalidResult, 0,
3463 kFPUInvalidResult};
3464 double outputs_l[kTableLength] = {
3465 3.0, 3.0, 3.0, -3.0, -3.0, -3.0,
3466 2147483648.0, 0,
3467 static_cast<double>(kFPU64InvalidResult)};
3468 // clang-format on
3469
3470 __ Fld_d(f8, MemOperand(a0, offsetof(Test, a)));
3471 __ Fld_s(f9, MemOperand(a0, offsetof(Test, b)));
3472 __ ftintrz_w_d(f10, f8);
3473 __ ftintrz_w_s(f11, f9);
3474 __ ftintrz_l_d(f12, f8);
3475 __ ftintrz_l_s(f13, f9);
3476 __ Fst_s(f10, MemOperand(a0, offsetof(Test, c)));
3477 __ Fst_s(f11, MemOperand(a0, offsetof(Test, d)));
3478 __ Fst_d(f12, MemOperand(a0, offsetof(Test, e)));
3479 __ Fst_d(f13, MemOperand(a0, offsetof(Test, f)));
3480 __ jirl(zero_reg, ra, 0);
3481
3482 CodeDesc desc;
3483 assm.GetCode(isolate, &desc);
3484 Handle<Code> code =
3485 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3486 auto f = GeneratedCode<F3>::FromCode(*code);
3487 for (int i = 0; i < kTableLength; i++) {
3488 test.a = inputs_d[i];
3489 test.b = inputs_s[i];
3490 f.Call(&test, 0, 0, 0, 0);
3491 CHECK_EQ(test.c, outputs_w[i]);
3492 CHECK_EQ(test.d, outputs_w[i]);
3493 CHECK_EQ(test.e, outputs_l[i]);
3494 CHECK_EQ(test.f, outputs_l[i]);
3495 }
3496 }
3497
TEST(FTINTRNE)3498 TEST(FTINTRNE) {
3499 CcTest::InitializeVM();
3500 Isolate* isolate = CcTest::i_isolate();
3501 HandleScope scope(isolate);
3502 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3503
3504 struct Test {
3505 double a;
3506 float b;
3507 int32_t c;
3508 int32_t d;
3509 int64_t e;
3510 int64_t f;
3511 };
3512 Test test;
3513
3514 const int kTableLength = 9;
3515
3516 // clang-format off
3517 double inputs_d[kTableLength] = {
3518 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3519 2147483648.0,
3520 std::numeric_limits<double>::quiet_NaN(),
3521 std::numeric_limits<double>::infinity()
3522 };
3523 float inputs_s[kTableLength] = {
3524 3.1, 3.6, 3.5, -3.1, -3.6, -3.5,
3525 2147483648.0,
3526 std::numeric_limits<double>::quiet_NaN(),
3527 std::numeric_limits<double>::infinity()
3528 };
3529 double outputs_w[kTableLength] = {
3530 3.0, 4.0, 4.0, -3.0, -4.0, -4.0,
3531 kFPUInvalidResult, 0,
3532 kFPUInvalidResult};
3533 double outputs_l[kTableLength] = {
3534 3.0, 4.0, 4.0, -3.0, -4.0, -4.0,
3535 2147483648.0, 0,
3536 static_cast<double>(kFPU64InvalidResult)};
3537 // clang-format on
3538
3539 __ Fld_d(f8, MemOperand(a0, offsetof(Test, a)));
3540 __ Fld_s(f9, MemOperand(a0, offsetof(Test, b)));
3541 __ ftintrne_w_d(f10, f8);
3542 __ ftintrne_w_s(f11, f9);
3543 __ ftintrne_l_d(f12, f8);
3544 __ ftintrne_l_s(f13, f9);
3545 __ Fst_s(f10, MemOperand(a0, offsetof(Test, c)));
3546 __ Fst_s(f11, MemOperand(a0, offsetof(Test, d)));
3547 __ Fst_d(f12, MemOperand(a0, offsetof(Test, e)));
3548 __ Fst_d(f13, MemOperand(a0, offsetof(Test, f)));
3549 __ jirl(zero_reg, ra, 0);
3550
3551 CodeDesc desc;
3552 assm.GetCode(isolate, &desc);
3553 Handle<Code> code =
3554 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3555 auto f = GeneratedCode<F3>::FromCode(*code);
3556 for (int i = 0; i < kTableLength; i++) {
3557 test.a = inputs_d[i];
3558 test.b = inputs_s[i];
3559 f.Call(&test, 0, 0, 0, 0);
3560 CHECK_EQ(test.c, outputs_w[i]);
3561 CHECK_EQ(test.d, outputs_w[i]);
3562 CHECK_EQ(test.e, outputs_l[i]);
3563 CHECK_EQ(test.f, outputs_l[i]);
3564 }
3565 }
3566
TEST(FRINT)3567 TEST(FRINT) {
3568 CcTest::InitializeVM();
3569 Isolate* isolate = CcTest::i_isolate();
3570 HandleScope scope(isolate);
3571 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3572
3573 struct Test {
3574 double a;
3575 float b;
3576 double c;
3577 float d;
3578 int fcsr;
3579 };
3580 Test test;
3581
3582 const int kTableLength = 32;
3583
3584 // clang-format off
3585 double inputs_d[kTableLength] = {
3586 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3587 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
3588 1.7976931348623157E+308, 6.27463370218383111104242366943E-307,
3589 309485009821345068724781056.89,
3590 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3591 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3592 37778931862957161709568.0, 37778931862957161709569.0,
3593 37778931862957161709580.0, 37778931862957161709581.0,
3594 37778931862957161709582.0, 37778931862957161709583.0,
3595 37778931862957161709584.0, 37778931862957161709585.0,
3596 37778931862957161709586.0, 37778931862957161709587.0,
3597 std::numeric_limits<double>::max() - 0.1,
3598 std::numeric_limits<double>::infinity()
3599 };
3600 float inputs_s[kTableLength] = {
3601 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3602 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
3603 1.7976931348623157E+38, 6.27463370218383111104242366943E-37,
3604 309485009821345068724781056.89,
3605 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3606 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3607 37778931862957161709568.0, 37778931862957161709569.0,
3608 37778931862957161709580.0, 37778931862957161709581.0,
3609 37778931862957161709582.0, 37778931862957161709583.0,
3610 37778931862957161709584.0, 37778931862957161709585.0,
3611 37778931862957161709586.0, 37778931862957161709587.0,
3612 std::numeric_limits<float>::lowest() + 0.6,
3613 std::numeric_limits<float>::infinity()
3614 };
3615 float outputs_RN_S[kTableLength] = {
3616 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3617 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
3618 1.7976931348623157E38, 0,
3619 309485009821345068724781057.0,
3620 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
3621 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
3622 37778931862957161709568.0, 37778931862957161709569.0,
3623 37778931862957161709580.0, 37778931862957161709581.0,
3624 37778931862957161709582.0, 37778931862957161709583.0,
3625 37778931862957161709584.0, 37778931862957161709585.0,
3626 37778931862957161709586.0, 37778931862957161709587.0,
3627 std::numeric_limits<float>::lowest() + 1,
3628 std::numeric_limits<float>::infinity()
3629 };
3630 double outputs_RN_D[kTableLength] = {
3631 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3632 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
3633 1.7976931348623157E308, 0,
3634 309485009821345068724781057.0,
3635 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
3636 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
3637 37778931862957161709568.0, 37778931862957161709569.0,
3638 37778931862957161709580.0, 37778931862957161709581.0,
3639 37778931862957161709582.0, 37778931862957161709583.0,
3640 37778931862957161709584.0, 37778931862957161709585.0,
3641 37778931862957161709586.0, 37778931862957161709587.0,
3642 std::numeric_limits<double>::max(),
3643 std::numeric_limits<double>::infinity()
3644 };
3645 float outputs_RZ_S[kTableLength] = {
3646 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3647 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
3648 1.7976931348623157E38, 0,
3649 309485009821345068724781057.0,
3650 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
3651 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3652 37778931862957161709568.0, 37778931862957161709569.0,
3653 37778931862957161709580.0, 37778931862957161709581.0,
3654 37778931862957161709582.0, 37778931862957161709583.0,
3655 37778931862957161709584.0, 37778931862957161709585.0,
3656 37778931862957161709586.0, 37778931862957161709587.0,
3657 std::numeric_limits<float>::lowest() + 1,
3658 std::numeric_limits<float>::infinity()
3659 };
3660 double outputs_RZ_D[kTableLength] = {
3661 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3662 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
3663 1.7976931348623157E308, 0,
3664 309485009821345068724781057.0,
3665 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
3666 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3667 37778931862957161709568.0, 37778931862957161709569.0,
3668 37778931862957161709580.0, 37778931862957161709581.0,
3669 37778931862957161709582.0, 37778931862957161709583.0,
3670 37778931862957161709584.0, 37778931862957161709585.0,
3671 37778931862957161709586.0, 37778931862957161709587.0,
3672 std::numeric_limits<double>::max() - 1,
3673 std::numeric_limits<double>::infinity()
3674 };
3675 float outputs_RP_S[kTableLength] = {
3676 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3677 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
3678 1.7976931348623157E38, 1,
3679 309485009821345068724781057.0,
3680 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3681 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3682 37778931862957161709568.0, 37778931862957161709569.0,
3683 37778931862957161709580.0, 37778931862957161709581.0,
3684 37778931862957161709582.0, 37778931862957161709583.0,
3685 37778931862957161709584.0, 37778931862957161709585.0,
3686 37778931862957161709586.0, 37778931862957161709587.0,
3687 std::numeric_limits<float>::lowest() + 1,
3688 std::numeric_limits<float>::infinity()
3689 };
3690 double outputs_RP_D[kTableLength] = {
3691 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3692 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
3693 1.7976931348623157E308, 1,
3694 309485009821345068724781057.0,
3695 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3696 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3697 37778931862957161709568.0, 37778931862957161709569.0,
3698 37778931862957161709580.0, 37778931862957161709581.0,
3699 37778931862957161709582.0, 37778931862957161709583.0,
3700 37778931862957161709584.0, 37778931862957161709585.0,
3701 37778931862957161709586.0, 37778931862957161709587.0,
3702 std::numeric_limits<double>::max(),
3703 std::numeric_limits<double>::infinity()
3704 };
3705 float outputs_RM_S[kTableLength] = {
3706 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3707 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
3708 1.7976931348623157E38, 0,
3709 309485009821345068724781057.0,
3710 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
3711 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
3712 37778931862957161709568.0, 37778931862957161709569.0,
3713 37778931862957161709580.0, 37778931862957161709581.0,
3714 37778931862957161709582.0, 37778931862957161709583.0,
3715 37778931862957161709584.0, 37778931862957161709585.0,
3716 37778931862957161709586.0, 37778931862957161709587.0,
3717 std::numeric_limits<float>::lowest() + 1,
3718 std::numeric_limits<float>::infinity()
3719 };
3720 double outputs_RM_D[kTableLength] = {
3721 18446744073709551617.0, 4503599627370496.0, -4503599627370496.0,
3722 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
3723 1.7976931348623157E308, 0,
3724 309485009821345068724781057.0,
3725 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
3726 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
3727 37778931862957161709568.0, 37778931862957161709569.0,
3728 37778931862957161709580.0, 37778931862957161709581.0,
3729 37778931862957161709582.0, 37778931862957161709583.0,
3730 37778931862957161709584.0, 37778931862957161709585.0,
3731 37778931862957161709586.0, 37778931862957161709587.0,
3732 std::numeric_limits<double>::max(),
3733 std::numeric_limits<double>::infinity()
3734 };
3735 // clang-format on
3736
3737 int fcsr_inputs[4] = {kRoundToNearest, kRoundToZero, kRoundToPlusInf,
3738 kRoundToMinusInf};
3739 double* outputs_d[4] = {outputs_RN_D, outputs_RZ_D, outputs_RP_D,
3740 outputs_RM_D};
3741 float* outputs_s[4] = {outputs_RN_S, outputs_RZ_S, outputs_RP_S,
3742 outputs_RM_S};
3743
3744 __ Fld_d(f8, MemOperand(a0, offsetof(Test, a)));
3745 __ Fld_s(f9, MemOperand(a0, offsetof(Test, b)));
3746 __ xor_(a5, a5, a5);
3747 __ Ld_w(a5, MemOperand(a0, offsetof(Test, fcsr)));
3748 __ movfcsr2gr(a4);
3749 __ movgr2fcsr(a5);
3750 __ frint_d(f10, f8);
3751 __ frint_s(f11, f9);
3752 __ Fst_d(f10, MemOperand(a0, offsetof(Test, c)));
3753 __ Fst_s(f11, MemOperand(a0, offsetof(Test, d)));
3754 __ movgr2fcsr(a4);
3755 __ jirl(zero_reg, ra, 0);
3756
3757 CodeDesc desc;
3758 assm.GetCode(isolate, &desc);
3759 Handle<Code> code =
3760 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3761 auto f = GeneratedCode<F3>::FromCode(*code);
3762 for (int j = 0; j < 4; j++) {
3763 test.fcsr = fcsr_inputs[j];
3764 for (int i = 0; i < kTableLength; i++) {
3765 test.a = inputs_d[i];
3766 test.b = inputs_s[i];
3767 f.Call(&test, 0, 0, 0, 0);
3768 CHECK_EQ(test.c, outputs_d[j][i]);
3769 CHECK_EQ(test.d, outputs_s[j][i]);
3770 }
3771 }
3772 }
3773
TEST(FMOV)3774 TEST(FMOV) {
3775 const int kTableLength = 7;
3776 CcTest::InitializeVM();
3777 Isolate* isolate = CcTest::i_isolate();
3778 HandleScope scope(isolate);
3779 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3780
3781 struct TestFloat {
3782 double a;
3783 float b;
3784 double c;
3785 float d;
3786 };
3787
3788 TestFloat test;
3789
3790 // clang-format off
3791 double inputs_D[kTableLength] = {
3792 5.3, -5.3, 0.29, -0.29, 0,
3793 std::numeric_limits<double>::max(),
3794 -std::numeric_limits<double>::max()
3795 };
3796 float inputs_S[kTableLength] = {
3797 4.8, -4.8, 0.29, -0.29, 0,
3798 std::numeric_limits<float>::max(),
3799 -std::numeric_limits<float>::max()
3800 };
3801
3802 double outputs_D[kTableLength] = {
3803 5.3, -5.3, 0.29, -0.29, 0,
3804 std::numeric_limits<double>::max(),
3805 -std::numeric_limits<double>::max()
3806 };
3807
3808 float outputs_S[kTableLength] = {
3809 4.8, -4.8, 0.29, -0.29, 0,
3810 std::numeric_limits<float>::max(),
3811 -std::numeric_limits<float>::max()
3812 };
3813 // clang-format on
3814
3815 __ Fld_d(f8, MemOperand(a0, offsetof(TestFloat, a)));
3816 __ Fld_s(f9, MemOperand(a0, offsetof(TestFloat, b)));
3817 __ fmov_d(f10, f8);
3818 __ fmov_s(f11, f9);
3819 __ Fst_d(f10, MemOperand(a0, offsetof(TestFloat, c)));
3820 __ Fst_s(f11, MemOperand(a0, offsetof(TestFloat, d)));
3821 __ jirl(zero_reg, ra, 0);
3822
3823 CodeDesc desc;
3824 assm.GetCode(isolate, &desc);
3825 Handle<Code> code =
3826 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3827 auto f = GeneratedCode<F3>::FromCode(*code);
3828 for (int i = 0; i < kTableLength; i++) {
3829 test.a = inputs_D[i];
3830 test.b = inputs_S[i];
3831 f.Call(&test, 0, 0, 0, 0);
3832 CHECK_EQ(test.c, outputs_D[i]);
3833 CHECK_EQ(test.d, outputs_S[i]);
3834 }
3835 }
3836
TEST(LA14)3837 TEST(LA14) {
3838 CcTest::InitializeVM();
3839 Isolate* isolate = CcTest::i_isolate();
3840 HandleScope scope(isolate);
3841
3842 struct T {
3843 double a;
3844 double b;
3845 double c;
3846 double d;
3847 int64_t high;
3848 int64_t low;
3849 };
3850 T t;
3851
3852 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3853
3854 __ Fld_d(f8, MemOperand(a0, offsetof(T, a)));
3855 __ Fld_d(f9, MemOperand(a0, offsetof(T, b)));
3856
3857 __ movfr2gr_s(a4, f8);
3858 __ movfrh2gr_s(a5, f8);
3859 __ movfr2gr_d(a6, f9);
3860
3861 __ movgr2fr_w(f9, a4);
3862 __ movgr2frh_w(f9, a5);
3863 __ movgr2fr_d(f8, a6);
3864
3865 __ Fst_d(f8, MemOperand(a0, offsetof(T, a)));
3866 __ Fst_d(f9, MemOperand(a0, offsetof(T, c)));
3867
3868 __ Fld_d(f8, MemOperand(a0, offsetof(T, d)));
3869 __ movfrh2gr_s(a4, f8);
3870 __ movfr2gr_s(a5, f8);
3871
3872 __ St_d(a4, MemOperand(a0, offsetof(T, high)));
3873 __ St_d(a5, MemOperand(a0, offsetof(T, low)));
3874
3875 __ jirl(zero_reg, ra, 0);
3876
3877 CodeDesc desc;
3878 assm.GetCode(isolate, &desc);
3879 Handle<Code> code =
3880 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3881 auto f = GeneratedCode<F3>::FromCode(*code);
3882
3883 t.a = 1.5e22;
3884 t.b = 2.75e11;
3885 t.c = 17.17;
3886 t.d = -2.75e11;
3887 f.Call(&t, 0, 0, 0, 0);
3888 CHECK_EQ(2.75e11, t.a);
3889 CHECK_EQ(2.75e11, t.b);
3890 CHECK_EQ(1.5e22, t.c);
3891 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFC25001D1L), t.high);
3892 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFBF800000L), t.low);
3893
3894 t.a = -1.5e22;
3895 t.b = -2.75e11;
3896 t.c = 17.17;
3897 t.d = 274999868928.0;
3898 f.Call(&t, 0, 0, 0, 0);
3899 CHECK_EQ(-2.75e11, t.a);
3900 CHECK_EQ(-2.75e11, t.b);
3901 CHECK_EQ(-1.5e22, t.c);
3902 CHECK_EQ(static_cast<int64_t>(0x425001D1L), t.high);
3903 CHECK_EQ(static_cast<int64_t>(0x3F800000L), t.low);
3904 }
3905
run_bceqz(int fcc_value,int32_t offset)3906 uint64_t run_bceqz(int fcc_value, int32_t offset) {
3907 Isolate* isolate = CcTest::i_isolate();
3908 HandleScope scope(isolate);
3909
3910 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3911
3912 Label main_block, L;
3913 __ li(a2, 0);
3914 __ li(t0, fcc_value);
3915 __ b(&main_block);
3916 // Block 1
3917 for (int32_t i = -104; i <= -55; ++i) {
3918 __ addi_d(a2, a2, 0x1);
3919 }
3920 __ b(&L);
3921
3922 // Block 2
3923 for (int32_t i = -53; i <= -4; ++i) {
3924 __ addi_d(a2, a2, 0x10);
3925 }
3926 __ b(&L);
3927
3928 // Block 3 (Main)
3929 __ bind(&main_block);
3930 __ movcf2gr(t1, FCC0);
3931 __ movgr2cf(FCC0, t0);
3932 __ bceqz(FCC0, offset);
3933 __ bind(&L);
3934 __ movgr2cf(FCC0, t1);
3935 __ or_(a0, a2, zero_reg);
3936 __ jirl(zero_reg, ra, 0);
3937
3938 // Block 4
3939 for (int32_t i = 4; i <= 53; ++i) {
3940 __ addi_d(a2, a2, 0x100);
3941 }
3942 __ b(&L);
3943
3944 // Block 5
3945 for (int32_t i = 55; i <= 104; ++i) {
3946 __ addi_d(a2, a2, 0x300);
3947 }
3948 __ b(&L);
3949
3950 CodeDesc desc;
3951 assm.GetCode(isolate, &desc);
3952 Handle<Code> code =
3953 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
3954 auto f = GeneratedCode<F2>::FromCode(*code);
3955 uint64_t res = reinterpret_cast<uint64_t>(f.Call(0, 0, 0, 0, 0));
3956
3957 return res;
3958 }
3959
TEST(BCEQZ)3960 TEST(BCEQZ) {
3961 CcTest::InitializeVM();
3962 struct TestCaseBceqz {
3963 int fcc;
3964 int32_t offset;
3965 uint64_t expected_res;
3966 };
3967
3968 // clang-format off
3969 struct TestCaseBceqz tc[] = {
3970 // fcc, offset, expected_res
3971 { 0, -90, 0x24 },
3972 { 0, -27, 0x180 },
3973 { 0, 47, 0x700 },
3974 { 0, 70, 0x6900 },
3975 { 1, -27, 0 },
3976 { 1, 47, 0 },
3977 };
3978 // clang-format on
3979
3980 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBceqz);
3981 for (size_t i = 0; i < nr_test_cases; ++i) {
3982 uint64_t res = run_bceqz(tc[i].fcc, tc[i].offset);
3983 CHECK_EQ(tc[i].expected_res, res);
3984 }
3985 }
3986
run_bcnez(int fcc_value,int32_t offset)3987 uint64_t run_bcnez(int fcc_value, int32_t offset) {
3988 Isolate* isolate = CcTest::i_isolate();
3989 HandleScope scope(isolate);
3990
3991 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
3992
3993 Label main_block, L;
3994 __ li(a2, 0);
3995 __ li(t0, fcc_value);
3996 __ b(&main_block);
3997 // Block 1
3998 for (int32_t i = -104; i <= -55; ++i) {
3999 __ addi_d(a2, a2, 0x1);
4000 }
4001 __ b(&L);
4002
4003 // Block 2
4004 for (int32_t i = -53; i <= -4; ++i) {
4005 __ addi_d(a2, a2, 0x10);
4006 }
4007 __ b(&L);
4008
4009 // Block 3 (Main)
4010 __ bind(&main_block);
4011 __ movcf2gr(t1, FCC0);
4012 __ movgr2cf(FCC0, t0);
4013 __ bcnez(FCC0, offset);
4014 __ bind(&L);
4015 __ movgr2cf(FCC0, t1);
4016 __ or_(a0, a2, zero_reg);
4017 __ jirl(zero_reg, ra, 0);
4018
4019 // Block 4
4020 for (int32_t i = 4; i <= 53; ++i) {
4021 __ addi_d(a2, a2, 0x100);
4022 }
4023 __ b(&L);
4024
4025 // Block 5
4026 for (int32_t i = 55; i <= 104; ++i) {
4027 __ addi_d(a2, a2, 0x300);
4028 }
4029 __ b(&L);
4030
4031 CodeDesc desc;
4032 assm.GetCode(isolate, &desc);
4033 Handle<Code> code =
4034 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4035 auto f = GeneratedCode<F2>::FromCode(*code);
4036 uint64_t res = reinterpret_cast<uint64_t>(f.Call(0, 0, 0, 0, 0));
4037
4038 return res;
4039 }
4040
TEST(BCNEZ)4041 TEST(BCNEZ) {
4042 CcTest::InitializeVM();
4043 struct TestCaseBcnez {
4044 int fcc;
4045 int32_t offset;
4046 uint64_t expected_res;
4047 };
4048
4049 // clang-format off
4050 struct TestCaseBcnez tc[] = {
4051 // fcc, offset, expected_res
4052 { 1, -90, 0x24 },
4053 { 1, -27, 0x180 },
4054 { 1, 47, 0x700 },
4055 { 1, 70, 0x6900 },
4056 { 0, -27, 0 },
4057 { 0, 47, 0 },
4058 };
4059 // clang-format on
4060
4061 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBcnez);
4062 for (size_t i = 0; i < nr_test_cases; ++i) {
4063 uint64_t res = run_bcnez(tc[i].fcc, tc[i].offset);
4064 CHECK_EQ(tc[i].expected_res, res);
4065 }
4066 }
4067
TEST(jump_tables1)4068 TEST(jump_tables1) {
4069 // Test jump tables with forward jumps.
4070 CcTest::InitializeVM();
4071 Isolate* isolate = CcTest::i_isolate();
4072 HandleScope scope(isolate);
4073 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4074
4075 const int kNumCases = 512;
4076 int values[kNumCases];
4077 isolate->random_number_generator()->NextBytes(values, sizeof(values));
4078 Label labels[kNumCases];
4079
4080 __ addi_d(sp, sp, -8);
4081 __ St_d(ra, MemOperand(sp, 0));
4082 __ Align(8);
4083
4084 Label done;
4085 {
4086 __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
4087 __ pcaddi(ra, 2);
4088 __ slli_d(t7, a0, 3);
4089 __ add_d(t7, t7, ra);
4090 __ Ld_d(t7, MemOperand(t7, 4 * kInstrSize));
4091 __ jirl(zero_reg, t7, 0);
4092 __ nop();
4093 for (int i = 0; i < kNumCases; ++i) {
4094 __ dd(&labels[i]);
4095 }
4096 }
4097
4098 for (int i = 0; i < kNumCases; ++i) {
4099 __ bind(&labels[i]);
4100 __ lu12i_w(a2, (values[i] >> 12) & 0xFFFFF);
4101 __ ori(a2, a2, values[i] & 0xFFF);
4102 __ b(&done);
4103 __ nop();
4104 }
4105
4106 __ bind(&done);
4107 __ Ld_d(ra, MemOperand(sp, 0));
4108 __ addi_d(sp, sp, 8);
4109 __ or_(a0, a2, zero_reg);
4110 __ jirl(zero_reg, ra, 0);
4111
4112 CHECK_EQ(0, assm.UnboundLabelsCount());
4113
4114 CodeDesc desc;
4115 assm.GetCode(isolate, &desc);
4116 Handle<Code> code =
4117 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4118 #ifdef OBJECT_PRINT
4119 code->Print(std::cout);
4120 #endif
4121 auto f = GeneratedCode<F1>::FromCode(*code);
4122 for (int i = 0; i < kNumCases; ++i) {
4123 int64_t res = reinterpret_cast<int64_t>(f.Call(i, 0, 0, 0, 0));
4124 ::printf("f(%d) = %" PRId64 "\n", i, res);
4125 CHECK_EQ((values[i]), static_cast<int>(res));
4126 }
4127 }
4128
TEST(jump_tables2)4129 TEST(jump_tables2) {
4130 // Test jump tables with backward jumps.
4131 CcTest::InitializeVM();
4132 Isolate* isolate = CcTest::i_isolate();
4133 HandleScope scope(isolate);
4134 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4135
4136 const int kNumCases = 512;
4137 int values[kNumCases];
4138 isolate->random_number_generator()->NextBytes(values, sizeof(values));
4139 Label labels[kNumCases];
4140
4141 __ addi_d(sp, sp, -8);
4142 __ St_d(ra, MemOperand(sp, 0));
4143
4144 Label done, dispatch;
4145 __ b(&dispatch);
4146 __ nop();
4147
4148 for (int i = 0; i < kNumCases; ++i) {
4149 __ bind(&labels[i]);
4150 __ lu12i_w(a2, (values[i] >> 12) & 0xFFFFF);
4151 __ ori(a2, a2, values[i] & 0xFFF);
4152 __ b(&done);
4153 __ nop();
4154 }
4155
4156 __ Align(8);
4157 __ bind(&dispatch);
4158 {
4159 __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
4160 __ pcaddi(ra, 2);
4161 __ slli_d(t7, a0, 3);
4162 __ add_d(t7, t7, ra);
4163 __ Ld_d(t7, MemOperand(t7, 4 * kInstrSize));
4164 __ jirl(zero_reg, t7, 0);
4165 __ nop();
4166 for (int i = 0; i < kNumCases; ++i) {
4167 __ dd(&labels[i]);
4168 }
4169 }
4170
4171 __ bind(&done);
4172 __ Ld_d(ra, MemOperand(sp, 0));
4173 __ addi_d(sp, sp, 8);
4174 __ or_(a0, a2, zero_reg);
4175 __ jirl(zero_reg, ra, 0);
4176
4177 CodeDesc desc;
4178 assm.GetCode(isolate, &desc);
4179 Handle<Code> code =
4180 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4181 #ifdef OBJECT_PRINT
4182 code->Print(std::cout);
4183 #endif
4184 auto f = GeneratedCode<F1>::FromCode(*code);
4185 for (int i = 0; i < kNumCases; ++i) {
4186 int64_t res = reinterpret_cast<int64_t>(f.Call(i, 0, 0, 0, 0));
4187 ::printf("f(%d) = %" PRId64 "\n", i, res);
4188 CHECK_EQ(values[i], res);
4189 }
4190 }
4191
TEST(jump_tables3)4192 TEST(jump_tables3) {
4193 // Test jump tables with backward jumps and embedded heap objects.
4194 CcTest::InitializeVM();
4195 Isolate* isolate = CcTest::i_isolate();
4196 HandleScope scope(isolate);
4197 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4198
4199 const int kNumCases = 512;
4200 Handle<Object> values[kNumCases];
4201 for (int i = 0; i < kNumCases; ++i) {
4202 double value = isolate->random_number_generator()->NextDouble();
4203 values[i] = isolate->factory()->NewHeapNumber<AllocationType::kOld>(value);
4204 }
4205 Label labels[kNumCases];
4206 Object obj;
4207 int64_t imm64;
4208
4209 __ addi_d(sp, sp, -8);
4210 __ St_d(ra, MemOperand(sp, 0));
4211
4212 Label done, dispatch;
4213 __ b(&dispatch);
4214 __ nop();
4215
4216 for (int i = 0; i < kNumCases; ++i) {
4217 __ bind(&labels[i]);
4218 obj = *values[i];
4219 imm64 = obj.ptr();
4220 __ lu12i_w(a2, (imm64 >> 12) & 0xFFFFF);
4221 __ ori(a2, a2, imm64 & 0xFFF);
4222 __ lu32i_d(a2, (imm64 >> 32) & 0xFFFFF);
4223 __ lu52i_d(a2, a2, (imm64 >> 52) & 0xFFF);
4224 __ b(&done);
4225 }
4226
4227 __ Align(8);
4228 __ bind(&dispatch);
4229 {
4230 __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
4231 __ pcaddi(ra, 2);
4232 __ slli_d(t7, a0, 3); // In delay slot.
4233 __ add_d(t7, t7, ra);
4234 __ Ld_d(t7, MemOperand(t7, 4 * kInstrSize));
4235 __ jirl(zero_reg, t7, 0);
4236 __ nop();
4237 for (int i = 0; i < kNumCases; ++i) {
4238 __ dd(&labels[i]);
4239 }
4240 }
4241 __ bind(&done);
4242 __ Ld_d(ra, MemOperand(sp, 0));
4243 __ addi_d(sp, sp, 8);
4244 __ or_(a0, a2, zero_reg);
4245 __ jirl(zero_reg, ra, 0);
4246
4247 CodeDesc desc;
4248 assm.GetCode(isolate, &desc);
4249 Handle<Code> code =
4250 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4251 #ifdef OBJECT_PRINT
4252 code->Print(std::cout);
4253 #endif
4254 auto f = GeneratedCode<F1>::FromCode(*code);
4255 for (int i = 0; i < kNumCases; ++i) {
4256 Handle<Object> result(
4257 Object(reinterpret_cast<Address>(f.Call(i, 0, 0, 0, 0))), isolate);
4258 #ifdef OBJECT_PRINT
4259 ::printf("f(%d) = ", i);
4260 result->Print(std::cout);
4261 ::printf("\n");
4262 #endif
4263 CHECK(values[i].is_identical_to(result));
4264 }
4265 }
4266
run_li_macro(int64_t imm,LiFlags mode,int32_t num_instr=0)4267 uint64_t run_li_macro(int64_t imm, LiFlags mode, int32_t num_instr = 0) {
4268 Isolate* isolate = CcTest::i_isolate();
4269 HandleScope scope(isolate);
4270 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4271
4272 Label code_start;
4273 __ bind(&code_start);
4274 __ li(a2, imm, mode);
4275 if (num_instr > 0) {
4276 CHECK_EQ(assm.InstructionsGeneratedSince(&code_start), num_instr);
4277 CHECK_EQ(__ InstrCountForLi64Bit(imm), num_instr);
4278 }
4279 __ or_(a0, a2, zero_reg);
4280 __ jirl(zero_reg, ra, 0);
4281
4282 CodeDesc desc;
4283 assm.GetCode(isolate, &desc);
4284 Handle<Code> code =
4285 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4286 #ifdef OBJECT_PRINT
4287 code->Print(std::cout);
4288 #endif
4289 auto f = GeneratedCode<F2>::FromCode(*code);
4290
4291 uint64_t res = reinterpret_cast<uint64_t>(f.Call(0, 0, 0, 0, 0));
4292
4293 return res;
4294 }
4295
TEST(li_macro)4296 TEST(li_macro) {
4297 CcTest::InitializeVM();
4298
4299 // Test li macro-instruction for border cases.
4300
4301 struct TestCase_li {
4302 uint64_t imm;
4303 int32_t num_instr;
4304 };
4305 // clang-format off
4306 struct TestCase_li tc[] = {
4307 // imm, num_instr
4308 {0xFFFFFFFFFFFFF800, 1}, // min_int12
4309 // The test case above generates addi_d instruction.
4310 // This is int12 value and we can load it using just addi_d.
4311 { 0x800, 1}, // max_int12 + 1
4312 // Generates ori
4313 // max_int12 + 1 is not int12 but is uint12, just use ori.
4314 {0xFFFFFFFFFFFFF7FF, 2}, // min_int12 - 1
4315 // Generates lu12i + ori
4316 // We load int32 value using lu12i_w + ori.
4317 { 0x801, 1}, // max_int12 + 2
4318 // Generates ori
4319 // Also an uint1 value, use ori.
4320 { 0x00001000, 1}, // max_uint12 + 1
4321 // Generates lu12i_w
4322 // Low 12 bits are 0, load value using lu12i_w.
4323 { 0x00001001, 2}, // max_uint12 + 2
4324 // Generates lu12i_w + ori
4325 // We have to generate two instructions in this case.
4326 {0x00000000FFFFFFFF, 2}, // max_uint32
4327 // addi_w + lu32i_d
4328 {0x00000000FFFFFFFE, 2}, // max_uint32 - 1
4329 // addi_w + lu32i_d
4330 {0xFFFFFFFF80000000, 1}, // min_int32
4331 // lu12i_w
4332 {0x0000000080000000, 2}, // max_int32 + 1
4333 // lu12i_w + lu32i_d
4334 {0xFFFF0000FFFF8765, 3},
4335 // lu12i_w + ori + lu32i_d
4336 {0x1234ABCD87654321, 4},
4337 // lu12i_w + ori + lu32i_d + lu52i_d
4338 {0xFFFF789100000000, 2},
4339 // xor + lu32i_d
4340 {0xF12F789100000000, 3},
4341 // xor + lu32i_d + lu52i_d
4342 {0xF120000000000800, 2},
4343 // ori + lu52i_d
4344 {0xFFF0000000000000, 1},
4345 // lu52i_d
4346 {0xF100000000000000, 1},
4347 {0x0122000000000000, 2},
4348 {0x1234FFFF77654321, 4},
4349 {0x1230000077654321, 3},
4350 };
4351 // clang-format on
4352
4353 size_t nr_test_cases = sizeof(tc) / sizeof(TestCase_li);
4354 for (size_t i = 0; i < nr_test_cases; ++i) {
4355 CHECK_EQ(tc[i].imm,
4356 run_li_macro(tc[i].imm, OPTIMIZE_SIZE, tc[i].num_instr));
4357 CHECK_EQ(tc[i].imm, run_li_macro(tc[i].imm, CONSTANT_SIZE));
4358 if (is_int48(tc[i].imm)) {
4359 CHECK_EQ(tc[i].imm, run_li_macro(tc[i].imm, ADDRESS_LOAD));
4360 }
4361 }
4362 }
4363
TEST(FMIN_FMAX)4364 TEST(FMIN_FMAX) {
4365 CcTest::InitializeVM();
4366 Isolate* isolate = CcTest::i_isolate();
4367 HandleScope scope(isolate);
4368 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4369
4370 struct TestFloat {
4371 double a;
4372 double b;
4373 float c;
4374 float d;
4375 double e;
4376 double f;
4377 float g;
4378 float h;
4379 };
4380
4381 TestFloat test;
4382 const double dnan = std::numeric_limits<double>::quiet_NaN();
4383 const double dinf = std::numeric_limits<double>::infinity();
4384 const double dminf = -std::numeric_limits<double>::infinity();
4385 const float fnan = std::numeric_limits<float>::quiet_NaN();
4386 const float finf = std::numeric_limits<float>::infinity();
4387 const float fminf = -std::numeric_limits<float>::infinity();
4388 const int kTableLength = 13;
4389
4390 // clang-format off
4391 double inputsa[kTableLength] = {2.0, 3.0, dnan, 3.0, -0.0, 0.0, dinf,
4392 dnan, 42.0, dinf, dminf, dinf, dnan};
4393 double inputsb[kTableLength] = {3.0, 2.0, 3.0, dnan, 0.0, -0.0, dnan,
4394 dinf, dinf, 42.0, dinf, dminf, dnan};
4395 double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
4396 -0.0, dinf, dinf, 42.0, 42.0,
4397 dminf, dminf, dnan};
4398 double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, dinf,
4399 dinf, dinf, dinf, dinf, dinf, dnan};
4400
4401 float inputsc[kTableLength] = {2.0, 3.0, fnan, 3.0, -0.0, 0.0, finf,
4402 fnan, 42.0, finf, fminf, finf, fnan};
4403 float inputsd[kTableLength] = {3.0, 2.0, 3.0, fnan, 0.0, -0.0, fnan,
4404 finf, finf, 42.0, finf, fminf, fnan};
4405 float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
4406 -0.0, finf, finf, 42.0, 42.0,
4407 fminf, fminf, fnan};
4408 float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, finf,
4409 finf, finf, finf, finf, finf, fnan};
4410 // clang-format on
4411
4412 __ Fld_d(f8, MemOperand(a0, offsetof(TestFloat, a)));
4413 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, b)));
4414 __ Fld_s(f10, MemOperand(a0, offsetof(TestFloat, c)));
4415 __ Fld_s(f11, MemOperand(a0, offsetof(TestFloat, d)));
4416 __ fmin_d(f12, f8, f9);
4417 __ fmax_d(f13, f8, f9);
4418 __ fmin_s(f14, f10, f11);
4419 __ fmax_s(f15, f10, f11);
4420 __ Fst_d(f12, MemOperand(a0, offsetof(TestFloat, e)));
4421 __ Fst_d(f13, MemOperand(a0, offsetof(TestFloat, f)));
4422 __ Fst_s(f14, MemOperand(a0, offsetof(TestFloat, g)));
4423 __ Fst_s(f15, MemOperand(a0, offsetof(TestFloat, h)));
4424 __ jirl(zero_reg, ra, 0);
4425
4426 CodeDesc desc;
4427 assm.GetCode(isolate, &desc);
4428 Handle<Code> code =
4429 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4430 auto f = GeneratedCode<F3>::FromCode(*code);
4431 for (int i = 4; i < kTableLength; i++) {
4432 test.a = inputsa[i];
4433 test.b = inputsb[i];
4434 test.c = inputsc[i];
4435 test.d = inputsd[i];
4436
4437 f.Call(&test, 0, 0, 0, 0);
4438
4439 CHECK_EQ(0, memcmp(&test.e, &outputsdmin[i], sizeof(test.e)));
4440 CHECK_EQ(0, memcmp(&test.f, &outputsdmax[i], sizeof(test.f)));
4441 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g)));
4442 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h)));
4443 }
4444 }
4445
TEST(FMINA_FMAXA)4446 TEST(FMINA_FMAXA) {
4447 const int kTableLength = 23;
4448 CcTest::InitializeVM();
4449 Isolate* isolate = CcTest::i_isolate();
4450 HandleScope scope(isolate);
4451 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4452 const double dnan = std::numeric_limits<double>::quiet_NaN();
4453 const double dinf = std::numeric_limits<double>::infinity();
4454 const double dminf = -std::numeric_limits<double>::infinity();
4455 const float fnan = std::numeric_limits<float>::quiet_NaN();
4456 const float finf = std::numeric_limits<float>::infinity();
4457 const float fminf = std::numeric_limits<float>::infinity();
4458
4459 struct TestFloat {
4460 double a;
4461 double b;
4462 double resd1;
4463 double resd2;
4464 float c;
4465 float d;
4466 float resf1;
4467 float resf2;
4468 };
4469
4470 TestFloat test;
4471 // clang-format off
4472 double inputsa[kTableLength] = {
4473 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
4474 dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0, dinf, dminf, dinf, dnan};
4475 double inputsb[kTableLength] = {
4476 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
4477 3.0, dnan, 0.0, -0.0, dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
4478 double resd1[kTableLength] = {
4479 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
4480 3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
4481 double resd2[kTableLength] = {
4482 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
4483 3.0, 3.0, 0.0, 0.0, dinf, dinf, dinf, dinf, dinf, dinf, dnan};
4484 float inputsc[kTableLength] = {
4485 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
4486 fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0, finf, fminf, finf, fnan};
4487 float inputsd[kTableLength] = {
4488 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
4489 3.0, fnan, -0.0, 0.0, fnan, finf, finf, 42.0, finf, fminf, fnan};
4490 float resf1[kTableLength] = {
4491 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
4492 3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
4493 float resf2[kTableLength] = {
4494 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
4495 3.0, 3.0, 0.0, 0.0, finf, finf, finf, finf, finf, finf, fnan};
4496 // clang-format on
4497
4498 __ Fld_d(f8, MemOperand(a0, offsetof(TestFloat, a)));
4499 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, b)));
4500 __ Fld_s(f10, MemOperand(a0, offsetof(TestFloat, c)));
4501 __ Fld_s(f11, MemOperand(a0, offsetof(TestFloat, d)));
4502 __ fmina_d(f12, f8, f9);
4503 __ fmaxa_d(f13, f8, f9);
4504 __ fmina_s(f14, f10, f11);
4505 __ fmaxa_s(f15, f10, f11);
4506 __ Fst_d(f12, MemOperand(a0, offsetof(TestFloat, resd1)));
4507 __ Fst_d(f13, MemOperand(a0, offsetof(TestFloat, resd2)));
4508 __ Fst_s(f14, MemOperand(a0, offsetof(TestFloat, resf1)));
4509 __ Fst_s(f15, MemOperand(a0, offsetof(TestFloat, resf2)));
4510 __ jirl(zero_reg, ra, 0);
4511
4512 CodeDesc desc;
4513 assm.GetCode(isolate, &desc);
4514 Handle<Code> code =
4515 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4516 auto f = GeneratedCode<F3>::FromCode(*code);
4517 for (int i = 0; i < kTableLength; i++) {
4518 test.a = inputsa[i];
4519 test.b = inputsb[i];
4520 test.c = inputsc[i];
4521 test.d = inputsd[i];
4522 f.Call(&test, 0, 0, 0, 0);
4523 if (i < kTableLength - 1) {
4524 CHECK_EQ(test.resd1, resd1[i]);
4525 CHECK_EQ(test.resd2, resd2[i]);
4526 CHECK_EQ(test.resf1, resf1[i]);
4527 CHECK_EQ(test.resf2, resf2[i]);
4528 } else {
4529 CHECK(std::isnan(test.resd1));
4530 CHECK(std::isnan(test.resd2));
4531 CHECK(std::isnan(test.resf1));
4532 CHECK(std::isnan(test.resf2));
4533 }
4534 }
4535 }
4536
TEST(FADD)4537 TEST(FADD) {
4538 CcTest::InitializeVM();
4539 Isolate* isolate = CcTest::i_isolate();
4540 HandleScope scope(isolate);
4541 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4542
4543 struct TestFloat {
4544 double a;
4545 double b;
4546 double c;
4547 float d;
4548 float e;
4549 float f;
4550 };
4551
4552 TestFloat test;
4553
4554 __ Fld_d(f8, MemOperand(a0, offsetof(TestFloat, a)));
4555 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, b)));
4556 __ fadd_d(f10, f8, f9);
4557 __ Fst_d(f10, MemOperand(a0, offsetof(TestFloat, c)));
4558
4559 __ Fld_s(f11, MemOperand(a0, offsetof(TestFloat, d)));
4560 __ Fld_s(f12, MemOperand(a0, offsetof(TestFloat, e)));
4561 __ fadd_s(f13, f11, f12);
4562 __ Fst_s(f13, MemOperand(a0, offsetof(TestFloat, f)));
4563 __ jirl(zero_reg, ra, 0);
4564
4565 CodeDesc desc;
4566 assm.GetCode(isolate, &desc);
4567 Handle<Code> code =
4568 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4569 auto f = GeneratedCode<F3>::FromCode(*code);
4570 test.a = 2.0;
4571 test.b = 3.0;
4572 test.d = 2.0;
4573 test.e = 3.0;
4574 f.Call(&test, 0, 0, 0, 0);
4575 CHECK_EQ(test.c, 5.0);
4576 CHECK_EQ(test.f, 5.0);
4577
4578 test.a = std::numeric_limits<double>::max();
4579 test.b = -std::numeric_limits<double>::max(); // lowest()
4580 test.d = std::numeric_limits<float>::max();
4581 test.e = -std::numeric_limits<float>::max(); // lowest()
4582 f.Call(&test, 0, 0, 0, 0);
4583 CHECK_EQ(test.c, 0.0);
4584 CHECK_EQ(test.f, 0.0);
4585
4586 test.a = std::numeric_limits<double>::max();
4587 test.b = std::numeric_limits<double>::max();
4588 test.d = std::numeric_limits<float>::max();
4589 test.e = std::numeric_limits<float>::max();
4590 f.Call(&test, 0, 0, 0, 0);
4591 CHECK(!std::isfinite(test.c));
4592 CHECK(!std::isfinite(test.f));
4593
4594 test.a = 5.0;
4595 test.b = std::numeric_limits<double>::signaling_NaN();
4596 test.d = 5.0;
4597 test.e = std::numeric_limits<float>::signaling_NaN();
4598 f.Call(&test, 0, 0, 0, 0);
4599 CHECK(std::isnan(test.c));
4600 CHECK(std::isnan(test.f));
4601 }
4602
TEST(FSUB)4603 TEST(FSUB) {
4604 const int kTableLength = 12;
4605 CcTest::InitializeVM();
4606 Isolate* isolate = CcTest::i_isolate();
4607 HandleScope scope(isolate);
4608 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4609
4610 struct TestFloat {
4611 float a;
4612 float b;
4613 float resultS;
4614 double c;
4615 double d;
4616 double resultD;
4617 };
4618
4619 TestFloat test;
4620
4621 // clang-format off
4622 double inputfs_D[kTableLength] = {
4623 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
4624 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
4625 };
4626 double inputft_D[kTableLength] = {
4627 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
4628 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
4629 };
4630 double outputs_D[kTableLength] = {
4631 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
4632 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
4633 };
4634 float inputfs_S[kTableLength] = {
4635 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
4636 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
4637 };
4638 float inputft_S[kTableLength] = {
4639 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
4640 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
4641 };
4642 float outputs_S[kTableLength] = {
4643 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
4644 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
4645 };
4646 // clang-format on
4647
4648 __ Fld_s(f8, MemOperand(a0, offsetof(TestFloat, a)));
4649 __ Fld_s(f9, MemOperand(a0, offsetof(TestFloat, b)));
4650 __ Fld_d(f10, MemOperand(a0, offsetof(TestFloat, c)));
4651 __ Fld_d(f11, MemOperand(a0, offsetof(TestFloat, d)));
4652 __ fsub_s(f12, f8, f9);
4653 __ fsub_d(f13, f10, f11);
4654 __ Fst_s(f12, MemOperand(a0, offsetof(TestFloat, resultS)));
4655 __ Fst_d(f13, MemOperand(a0, offsetof(TestFloat, resultD)));
4656 __ jirl(zero_reg, ra, 0);
4657
4658 CodeDesc desc;
4659 assm.GetCode(isolate, &desc);
4660 Handle<Code> code =
4661 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4662 auto f = GeneratedCode<F3>::FromCode(*code);
4663 for (int i = 0; i < kTableLength; i++) {
4664 test.a = inputfs_S[i];
4665 test.b = inputft_S[i];
4666 test.c = inputfs_D[i];
4667 test.d = inputft_D[i];
4668 f.Call(&test, 0, 0, 0, 0);
4669 CHECK_EQ(test.resultS, outputs_S[i]);
4670 CHECK_EQ(test.resultD, outputs_D[i]);
4671 }
4672 }
4673
TEST(FMUL)4674 TEST(FMUL) {
4675 const int kTableLength = 4;
4676 CcTest::InitializeVM();
4677 Isolate* isolate = CcTest::i_isolate();
4678 HandleScope scope(isolate);
4679 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4680
4681 struct TestFloat {
4682 float a;
4683 float b;
4684 float resultS;
4685 double c;
4686 double d;
4687 double resultD;
4688 };
4689
4690 TestFloat test;
4691 // clang-format off
4692 double inputfs_D[kTableLength] = {
4693 5.3, -5.3, 5.3, -2.9
4694 };
4695 double inputft_D[kTableLength] = {
4696 4.8, 4.8, -4.8, -0.29
4697 };
4698
4699 float inputfs_S[kTableLength] = {
4700 5.3, -5.3, 5.3, -2.9
4701 };
4702 float inputft_S[kTableLength] = {
4703 4.8, 4.8, -4.8, -0.29
4704 };
4705 // clang-format on
4706 __ Fld_s(f8, MemOperand(a0, offsetof(TestFloat, a)));
4707 __ Fld_s(f9, MemOperand(a0, offsetof(TestFloat, b)));
4708 __ Fld_d(f10, MemOperand(a0, offsetof(TestFloat, c)));
4709 __ Fld_d(f11, MemOperand(a0, offsetof(TestFloat, d)));
4710 __ fmul_s(f12, f8, f9);
4711 __ fmul_d(f13, f10, f11);
4712 __ Fst_s(f12, MemOperand(a0, offsetof(TestFloat, resultS)));
4713 __ Fst_d(f13, MemOperand(a0, offsetof(TestFloat, resultD)));
4714 __ jirl(zero_reg, ra, 0);
4715
4716 CodeDesc desc;
4717 assm.GetCode(isolate, &desc);
4718 Handle<Code> code =
4719 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4720 auto f = GeneratedCode<F3>::FromCode(*code);
4721 for (int i = 0; i < kTableLength; i++) {
4722 test.a = inputfs_S[i];
4723 test.b = inputft_S[i];
4724 test.c = inputfs_D[i];
4725 test.d = inputft_D[i];
4726 f.Call(&test, 0, 0, 0, 0);
4727 CHECK_EQ(test.resultS, inputfs_S[i] * inputft_S[i]);
4728 CHECK_EQ(test.resultD, inputfs_D[i] * inputft_D[i]);
4729 }
4730 }
4731
TEST(FDIV)4732 TEST(FDIV) {
4733 CcTest::InitializeVM();
4734 Isolate* isolate = CcTest::i_isolate();
4735 HandleScope scope(isolate);
4736 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4737
4738 struct Test {
4739 double dOp1;
4740 double dOp2;
4741 double dRes;
4742 float fOp1;
4743 float fOp2;
4744 float fRes;
4745 };
4746
4747 Test test;
4748
4749 __ movfcsr2gr(a4);
4750 __ movgr2fcsr(zero_reg);
4751
4752 __ Fld_d(f8, MemOperand(a0, offsetof(Test, dOp1)));
4753 __ Fld_d(f9, MemOperand(a0, offsetof(Test, dOp2)));
4754 __ Fld_s(f10, MemOperand(a0, offsetof(Test, fOp1)));
4755 __ Fld_s(f11, MemOperand(a0, offsetof(Test, fOp2)));
4756 __ fdiv_d(f12, f8, f9);
4757 __ fdiv_s(f13, f10, f11);
4758 __ Fst_d(f12, MemOperand(a0, offsetof(Test, dRes)));
4759 __ Fst_s(f13, MemOperand(a0, offsetof(Test, fRes)));
4760
4761 __ movgr2fcsr(a4);
4762 __ jirl(zero_reg, ra, 0);
4763
4764 CodeDesc desc;
4765 assm.GetCode(isolate, &desc);
4766 Handle<Code> code =
4767 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4768 auto f = GeneratedCode<F3>::FromCode(*code);
4769 f.Call(&test, 0, 0, 0, 0);
4770 const int test_size = 3;
4771 // clang-format off
4772 double dOp1[test_size] = {
4773 5.0, DBL_MAX, DBL_MAX};
4774
4775 double dOp2[test_size] = {
4776 2.0, 2.0, -DBL_MAX};
4777
4778 double dRes[test_size] = {
4779 2.5, DBL_MAX / 2.0, -1.0};
4780
4781 float fOp1[test_size] = {
4782 5.0, FLT_MAX, FLT_MAX};
4783
4784 float fOp2[test_size] = {
4785 2.0, 2.0, -FLT_MAX};
4786
4787 float fRes[test_size] = {
4788 2.5, FLT_MAX / 2.0, -1.0};
4789 // clang-format on
4790
4791 for (int i = 0; i < test_size; i++) {
4792 test.dOp1 = dOp1[i];
4793 test.dOp2 = dOp2[i];
4794 test.fOp1 = fOp1[i];
4795 test.fOp2 = fOp2[i];
4796
4797 f.Call(&test, 0, 0, 0, 0);
4798 CHECK_EQ(test.dRes, dRes[i]);
4799 CHECK_EQ(test.fRes, fRes[i]);
4800 }
4801
4802 test.dOp1 = DBL_MAX;
4803 test.dOp2 = -0.0;
4804 test.fOp1 = FLT_MAX;
4805 test.fOp2 = -0.0;
4806
4807 f.Call(&test, 0, 0, 0, 0);
4808 CHECK(!std::isfinite(test.dRes));
4809 CHECK(!std::isfinite(test.fRes));
4810
4811 test.dOp1 = 0.0;
4812 test.dOp2 = -0.0;
4813 test.fOp1 = 0.0;
4814 test.fOp2 = -0.0;
4815
4816 f.Call(&test, 0, 0, 0, 0);
4817 CHECK(std::isnan(test.dRes));
4818 CHECK(std::isnan(test.fRes));
4819
4820 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4821 test.dOp2 = -5.0;
4822 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4823 test.fOp2 = -5.0;
4824
4825 f.Call(&test, 0, 0, 0, 0);
4826 CHECK(std::isnan(test.dRes));
4827 CHECK(std::isnan(test.fRes));
4828 }
4829
TEST(FABS)4830 TEST(FABS) {
4831 CcTest::InitializeVM();
4832 Isolate* isolate = CcTest::i_isolate();
4833 HandleScope scope(isolate);
4834 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4835
4836 struct TestFloat {
4837 double a;
4838 float b;
4839 };
4840
4841 TestFloat test;
4842
4843 __ movfcsr2gr(a4);
4844 __ movgr2fcsr(zero_reg);
4845
4846 __ Fld_d(f8, MemOperand(a0, offsetof(TestFloat, a)));
4847 __ Fld_s(f9, MemOperand(a0, offsetof(TestFloat, b)));
4848 __ fabs_d(f10, f8);
4849 __ fabs_s(f11, f9);
4850 __ Fst_d(f10, MemOperand(a0, offsetof(TestFloat, a)));
4851 __ Fst_s(f11, MemOperand(a0, offsetof(TestFloat, b)));
4852
4853 __ movgr2fcsr(a4);
4854 __ jirl(zero_reg, ra, 0);
4855
4856 CodeDesc desc;
4857 assm.GetCode(isolate, &desc);
4858 Handle<Code> code =
4859 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4860 auto f = GeneratedCode<F3>::FromCode(*code);
4861 test.a = -2.0;
4862 test.b = -2.0;
4863 f.Call(&test, 0, 0, 0, 0);
4864 CHECK_EQ(test.a, 2.0);
4865 CHECK_EQ(test.b, 2.0);
4866
4867 test.a = 2.0;
4868 test.b = 2.0;
4869 f.Call(&test, 0, 0, 0, 0);
4870 CHECK_EQ(test.a, 2.0);
4871 CHECK_EQ(test.b, 2.0);
4872
4873 // Testing biggest positive number
4874 test.a = std::numeric_limits<double>::max();
4875 test.b = std::numeric_limits<float>::max();
4876 f.Call(&test, 0, 0, 0, 0);
4877 CHECK_EQ(test.a, std::numeric_limits<double>::max());
4878 CHECK_EQ(test.b, std::numeric_limits<float>::max());
4879
4880 // Testing smallest negative number
4881 test.a = -std::numeric_limits<double>::max(); // lowest()
4882 test.b = -std::numeric_limits<float>::max(); // lowest()
4883 f.Call(&test, 0, 0, 0, 0);
4884 CHECK_EQ(test.a, std::numeric_limits<double>::max());
4885 CHECK_EQ(test.b, std::numeric_limits<float>::max());
4886
4887 // Testing smallest positive number
4888 test.a = -std::numeric_limits<double>::min();
4889 test.b = -std::numeric_limits<float>::min();
4890 f.Call(&test, 0, 0, 0, 0);
4891 CHECK_EQ(test.a, std::numeric_limits<double>::min());
4892 CHECK_EQ(test.b, std::numeric_limits<float>::min());
4893
4894 // Testing infinity
4895 test.a =
4896 -std::numeric_limits<double>::max() / std::numeric_limits<double>::min();
4897 test.b =
4898 -std::numeric_limits<float>::max() / std::numeric_limits<float>::min();
4899 f.Call(&test, 0, 0, 0, 0);
4900 CHECK_EQ(test.a, std::numeric_limits<double>::max() /
4901 std::numeric_limits<double>::min());
4902 CHECK_EQ(test.b, std::numeric_limits<float>::max() /
4903 std::numeric_limits<float>::min());
4904
4905 test.a = std::numeric_limits<double>::quiet_NaN();
4906 test.b = std::numeric_limits<float>::quiet_NaN();
4907 f.Call(&test, 0, 0, 0, 0);
4908 CHECK(std::isnan(test.a));
4909 CHECK(std::isnan(test.b));
4910
4911 test.a = std::numeric_limits<double>::signaling_NaN();
4912 test.b = std::numeric_limits<float>::signaling_NaN();
4913 f.Call(&test, 0, 0, 0, 0);
4914 CHECK(std::isnan(test.a));
4915 CHECK(std::isnan(test.b));
4916 }
4917
4918 template <class T>
4919 struct TestCaseMaddMsub {
4920 T fj, fk, fa, fd_fmadd, fd_fmsub, fd_fnmadd, fd_fnmsub;
4921 };
4922
4923 template <typename T, typename F>
helper_fmadd_fmsub_fnmadd_fnmsub(F func)4924 void helper_fmadd_fmsub_fnmadd_fnmsub(F func) {
4925 CcTest::InitializeVM();
4926 Isolate* isolate = CcTest::i_isolate();
4927 HandleScope scope(isolate);
4928 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
4929
4930 T x = std::sqrt(static_cast<T>(2.0));
4931 T y = std::sqrt(static_cast<T>(3.0));
4932 T z = std::sqrt(static_cast<T>(5.0));
4933 T x2 = 11.11, y2 = 22.22, z2 = 33.33;
4934 // clang-format off
4935 TestCaseMaddMsub<T> test_cases[] = {
4936 {x, y, z, 0.0, 0.0, 0.0, 0.0},
4937 {x, y, -z, 0.0, 0.0, 0.0, 0.0},
4938 {x, -y, z, 0.0, 0.0, 0.0, 0.0},
4939 {x, -y, -z, 0.0, 0.0, 0.0, 0.0},
4940 {-x, y, z, 0.0, 0.0, 0.0, 0.0},
4941 {-x, y, -z, 0.0, 0.0, 0.0, 0.0},
4942 {-x, -y, z, 0.0, 0.0, 0.0, 0.0},
4943 {-x, -y, -z, 0.0, 0.0, 0.0, 0.0},
4944 {-3.14, 0.2345, -123.000056, 0.0, 0.0, 0.0, 0.0},
4945 {7.3, -23.257, -357.1357, 0.0, 0.0, 0.0, 0.0},
4946 {x2, y2, z2, 0.0, 0.0, 0.0, 0.0},
4947 {x2, y2, -z2, 0.0, 0.0, 0.0, 0.0},
4948 {x2, -y2, z2, 0.0, 0.0, 0.0, 0.0},
4949 {x2, -y2, -z2, 0.0, 0.0, 0.0, 0.0},
4950 {-x2, y2, z2, 0.0, 0.0, 0.0, 0.0},
4951 {-x2, y2, -z2, 0.0, 0.0, 0.0, 0.0},
4952 {-x2, -y2, z2, 0.0, 0.0, 0.0, 0.0},
4953 {-x2, -y2, -z2, 0.0, 0.0, 0.0, 0.0},
4954 };
4955 // clang-format on
4956 if (std::is_same<T, float>::value) {
4957 __ Fld_s(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fj)));
4958 __ Fld_s(f9, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fk)));
4959 __ Fld_s(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fa)));
4960 } else if (std::is_same<T, double>::value) {
4961 __ Fld_d(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fj)));
4962 __ Fld_d(f9, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fk)));
4963 __ Fld_d(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fa)));
4964 } else {
4965 UNREACHABLE();
4966 }
4967
4968 func(assm);
4969 __ jirl(zero_reg, ra, 0);
4970
4971 CodeDesc desc;
4972 assm.GetCode(isolate, &desc);
4973 Handle<Code> code =
4974 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
4975 auto f = GeneratedCode<F3>::FromCode(*code);
4976
4977 const size_t kTableLength = sizeof(test_cases) / sizeof(TestCaseMaddMsub<T>);
4978 TestCaseMaddMsub<T> tc;
4979 for (size_t i = 0; i < kTableLength; i++) {
4980 tc.fj = test_cases[i].fj;
4981 tc.fk = test_cases[i].fk;
4982 tc.fa = test_cases[i].fa;
4983
4984 f.Call(&tc, 0, 0, 0, 0);
4985
4986 T res_fmadd;
4987 T res_fmsub;
4988 T res_fnmadd;
4989 T res_fnmsub;
4990 res_fmadd = std::fma(tc.fj, tc.fk, tc.fa);
4991 res_fmsub = std::fma(tc.fj, tc.fk, -tc.fa);
4992 res_fnmadd = -std::fma(tc.fj, tc.fk, tc.fa);
4993 res_fnmsub = -std::fma(tc.fj, tc.fk, -tc.fa);
4994
4995 CHECK_EQ(tc.fd_fmadd, res_fmadd);
4996 CHECK_EQ(tc.fd_fmsub, res_fmsub);
4997 CHECK_EQ(tc.fd_fnmadd, res_fnmadd);
4998 CHECK_EQ(tc.fd_fnmsub, res_fnmsub);
4999 }
5000 }
5001
TEST(FMADD_FMSUB_FNMADD_FNMSUB_S)5002 TEST(FMADD_FMSUB_FNMADD_FNMSUB_S) {
5003 helper_fmadd_fmsub_fnmadd_fnmsub<float>([](MacroAssembler& assm) {
5004 __ fmadd_s(f11, f8, f9, f10);
5005 __ Fst_s(f11, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_fmadd)));
5006 __ fmsub_s(f12, f8, f9, f10);
5007 __ Fst_s(f12, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_fmsub)));
5008 __ fnmadd_s(f13, f8, f9, f10);
5009 __ Fst_s(f13, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_fnmadd)));
5010 __ fnmsub_s(f14, f8, f9, f10);
5011 __ Fst_s(f14, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_fnmsub)));
5012 });
5013 }
5014
TEST(FMADD_FMSUB_FNMADD_FNMSUB_D)5015 TEST(FMADD_FMSUB_FNMADD_FNMSUB_D) {
5016 helper_fmadd_fmsub_fnmadd_fnmsub<double>([](MacroAssembler& assm) {
5017 __ fmadd_d(f11, f8, f9, f10);
5018 __ Fst_d(f11, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_fmadd)));
5019 __ fmsub_d(f12, f8, f9, f10);
5020 __ Fst_d(f12, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_fmsub)));
5021 __ fnmadd_d(f13, f8, f9, f10);
5022 __ Fst_d(f13,
5023 MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_fnmadd)));
5024 __ fnmsub_d(f14, f8, f9, f10);
5025 __ Fst_d(f14,
5026 MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_fnmsub)));
5027 });
5028 }
5029
5030 /*
5031 TEST(FSQRT_FRSQRT_FRECIP) {
5032 const int kTableLength = 4;
5033 const double deltaDouble = 2E-15;
5034 const float deltaFloat = 2E-7;
5035 const float sqrt2_s = sqrt(2);
5036 const double sqrt2_d = sqrt(2);
5037 CcTest::InitializeVM();
5038 Isolate* isolate = CcTest::i_isolate();
5039 HandleScope scope(isolate);
5040 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
5041
5042 struct TestFloat {
5043 float a;
5044 float resultS1;
5045 float resultS2;
5046 float resultS3;
5047 double b;
5048 double resultD1;
5049 double resultD2;
5050 double resultD3;
5051 };
5052 TestFloat test;
5053 // clang-format off
5054 double inputs_D[kTableLength] = {
5055 0.0L, 4.0L, 2.0L, 4e-28L
5056 };
5057
5058 double outputs_D[kTableLength] = {
5059 0.0L, 2.0L, sqrt2_d, 2e-14L
5060 };
5061 float inputs_S[kTableLength] = {
5062 0.0, 4.0, 2.0, 4e-28
5063 };
5064
5065 float outputs_S[kTableLength] = {
5066 0.0, 2.0, sqrt2_s, 2e-14
5067 };
5068 // clang-format on
5069 __ Fld_s(f8, MemOperand(a0, offsetof(TestFloat, a)));
5070 __ Fld_d(f9, MemOperand(a0, offsetof(TestFloat, b)));
5071 __ fsqrt_s(f10, f8);
5072 __ fsqrt_d(f11, f9);
5073 __ frsqrt_s(f12, f8);
5074 __ frsqrt_d(f13, f9);
5075 __ frecip_s(f14, f8);
5076 __ frecip_d(f15, f9);
5077 __ Fst_s(f10, MemOperand(a0, offsetof(TestFloat, resultS1)));
5078 __ Fst_d(f11, MemOperand(a0, offsetof(TestFloat, resultD1)));
5079 __ Fst_s(f12, MemOperand(a0, offsetof(TestFloat, resultS2)));
5080 __ Fst_d(f13, MemOperand(a0, offsetof(TestFloat, resultD2)));
5081 __ Fst_s(f14, MemOperand(a0, offsetof(TestFloat, resultS3)));
5082 __ Fst_d(f15, MemOperand(a0, offsetof(TestFloat, resultD3)));
5083 __ jirl(zero_reg, ra, 0);
5084
5085 CodeDesc desc;
5086 assm.GetCode(isolate, &desc);
5087 Handle<Code> code = Factory::CodeBuilder(isolate, desc,
5088 CodeKind::STUB).Build(); auto f = GeneratedCode<F3>::FromCode(*code);
5089
5090 for (int i = 0; i < kTableLength; i++) {
5091 float f1;
5092 double d1;
5093 test.a = inputs_S[i];
5094 test.b = inputs_D[i];
5095
5096 f.Call(&test, 0, 0, 0, 0);
5097
5098 CHECK_EQ(test.resultS1, outputs_S[i]);
5099 CHECK_EQ(test.resultD1, outputs_D[i]);
5100
5101 if (i != 0) {
5102 f1 = test.resultS2 - 1.0F/outputs_S[i];
5103 f1 = (f1 < 0) ? f1 : -f1;
5104 CHECK(f1 <= deltaFloat);
5105 d1 = test.resultD2 - 1.0L/outputs_D[i];
5106 d1 = (d1 < 0) ? d1 : -d1;
5107 CHECK(d1 <= deltaDouble);
5108 f1 = test.resultS3 - 1.0F/inputs_S[i];
5109 f1 = (f1 < 0) ? f1 : -f1;
5110 CHECK(f1 <= deltaFloat);
5111 d1 = test.resultD3 - 1.0L/inputs_D[i];
5112 d1 = (d1 < 0) ? d1 : -d1;
5113 CHECK(d1 <= deltaDouble);
5114 } else {
5115 CHECK_EQ(test.resultS2, 1.0F/outputs_S[i]);
5116 CHECK_EQ(test.resultD2, 1.0L/outputs_D[i]);
5117 CHECK_EQ(test.resultS3, 1.0F/inputs_S[i]);
5118 CHECK_EQ(test.resultD3, 1.0L/inputs_D[i]);
5119 }
5120 }
5121 }*/
5122
TEST(LA15)5123 TEST(LA15) {
5124 // Test chaining of label usages within instructions (issue 1644).
5125 CcTest::InitializeVM();
5126 Isolate* isolate = CcTest::i_isolate();
5127 HandleScope scope(isolate);
5128 Assembler assm(AssemblerOptions{});
5129
5130 Label target;
5131 __ beq(a0, a1, &target);
5132 __ nop();
5133 __ bne(a0, a1, &target);
5134 __ nop();
5135 __ bind(&target);
5136 __ nop();
5137 __ jirl(zero_reg, ra, 0);
5138
5139 CodeDesc desc;
5140 assm.GetCode(isolate, &desc);
5141 Handle<Code> code =
5142 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
5143 auto f = GeneratedCode<F2>::FromCode(*code);
5144 f.Call(1, 1, 0, 0, 0);
5145 }
5146
TEST(Trampoline)5147 TEST(Trampoline) {
5148 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
5149
5150 CcTest::InitializeVM();
5151 Isolate* isolate = CcTest::i_isolate();
5152 HandleScope scope(isolate);
5153
5154 MacroAssembler assm(isolate, v8::internal::CodeObjectRequired::kYes);
5155 Label done;
5156 size_t nr_calls = kMaxBranchOffset / kInstrSize + 5;
5157
5158 __ xor_(a2, a2, a2);
5159 __ BranchShort(&done, eq, a0, Operand(a1));
5160 for (size_t i = 0; i < nr_calls; ++i) {
5161 __ addi_d(a2, a2, 1);
5162 }
5163 __ bind(&done);
5164 __ or_(a0, a2, zero_reg);
5165 __ jirl(zero_reg, ra, 0);
5166
5167 CodeDesc desc;
5168 assm.GetCode(isolate, &desc);
5169 Handle<Code> code =
5170 Factory::CodeBuilder(isolate, desc, CodeKind::FOR_TESTING).Build();
5171 auto f = GeneratedCode<F2>::FromCode(*code);
5172
5173 int64_t res = reinterpret_cast<int64_t>(f.Call(42, 42, 0, 0, 0));
5174 CHECK_EQ(0, res);
5175 }
5176
5177 #undef __
5178
5179 } // namespace internal
5180 } // namespace v8
5181