blob: 988083cadc0247c799d19cfc67ed70d357f27eb4 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028#include <iostream> // NOLINT(readability/streams)
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
31
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032#include "src/base/utils/random-number-generator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033#include "src/disassembler.h"
34#include "src/factory.h"
35#include "src/macro-assembler.h"
36#include "src/mips64/macro-assembler-mips64.h"
37#include "src/mips64/simulator-mips64.h"
38
39#include "test/cctest/cctest.h"
40
41using namespace v8::internal;
42
43
44// Define these function prototypes to match JSEntryFunction in execution.cc.
45typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
46typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
47typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048typedef Object* (*F4)(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049
50
51#define __ assm.
52
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053TEST(MIPS0) {
54 CcTest::InitializeVM();
55 Isolate* isolate = CcTest::i_isolate();
56 HandleScope scope(isolate);
57
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059
60 // Addition.
61 __ addu(v0, a0, a1);
62 __ jr(ra);
63 __ nop();
64
65 CodeDesc desc;
66 assm.GetCode(&desc);
67 Handle<Code> code = isolate->factory()->NewCode(
68 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
69 F2 f = FUNCTION_CAST<F2>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 int64_t res = reinterpret_cast<int64_t>(
71 CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072 CHECK_EQ(0xabcL, res);
73}
74
75
76TEST(MIPS1) {
77 CcTest::InitializeVM();
78 Isolate* isolate = CcTest::i_isolate();
79 HandleScope scope(isolate);
80
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 Label L, C;
83
84 __ mov(a1, a0);
85 __ li(v0, 0);
86 __ b(&C);
87 __ nop();
88
89 __ bind(&L);
90 __ addu(v0, v0, a1);
91 __ addiu(a1, a1, -1);
92
93 __ bind(&C);
94 __ xori(v1, a1, 0);
95 __ Branch(&L, ne, v1, Operand((int64_t)0));
96 __ nop();
97
98 __ jr(ra);
99 __ nop();
100
101 CodeDesc desc;
102 assm.GetCode(&desc);
103 Handle<Code> code = isolate->factory()->NewCode(
104 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
105 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 int64_t res = reinterpret_cast<int64_t>(
107 CALL_GENERATED_CODE(isolate, f, 50, 0, 0, 0, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 CHECK_EQ(1275L, res);
109}
110
111
112TEST(MIPS2) {
113 CcTest::InitializeVM();
114 Isolate* isolate = CcTest::i_isolate();
115 HandleScope scope(isolate);
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118
119 Label exit, error;
120
121 // ----- Test all instructions.
122
123 // Test lui, ori, and addiu, used in the li pseudo-instruction.
124 // This way we can then safely load registers with chosen values.
125
126 __ ori(a4, zero_reg, 0);
127 __ lui(a4, 0x1234);
128 __ ori(a4, a4, 0);
129 __ ori(a4, a4, 0x0f0f);
130 __ ori(a4, a4, 0xf0f0);
131 __ addiu(a5, a4, 1);
132 __ addiu(a6, a5, -0x10);
133
134 // Load values in temporary registers.
135 __ li(a4, 0x00000004);
136 __ li(a5, 0x00001234);
137 __ li(a6, 0x12345678);
138 __ li(a7, 0x7fffffff);
139 __ li(t0, 0xfffffffc);
140 __ li(t1, 0xffffedcc);
141 __ li(t2, 0xedcba988);
142 __ li(t3, 0x80000000);
143
144 // SPECIAL class.
145 __ srl(v0, a6, 8); // 0x00123456
146 __ sll(v0, v0, 11); // 0x91a2b000
147 __ sra(v0, v0, 3); // 0xf2345600
148 __ srav(v0, v0, a4); // 0xff234560
149 __ sllv(v0, v0, a4); // 0xf2345600
150 __ srlv(v0, v0, a4); // 0x0f234560
151 __ Branch(&error, ne, v0, Operand(0x0f234560));
152 __ nop();
153
154 __ addu(v0, a4, a5); // 0x00001238
155 __ subu(v0, v0, a4); // 0x00001234
156 __ Branch(&error, ne, v0, Operand(0x00001234));
157 __ nop();
158 __ addu(v1, a7, a4); // 32bit addu result is sign-extended into 64bit reg.
159 __ Branch(&error, ne, v1, Operand(0xffffffff80000003));
160 __ nop();
161 __ subu(v1, t3, a4); // 0x7ffffffc
162 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
163 __ nop();
164
165 __ and_(v0, a5, a6); // 0x0000000000001230
166 __ or_(v0, v0, a5); // 0x0000000000001234
167 __ xor_(v0, v0, a6); // 0x000000001234444c
168 __ nor(v0, v0, a6); // 0xffffffffedcba987
169 __ Branch(&error, ne, v0, Operand(0xffffffffedcba983));
170 __ nop();
171
172 // Shift both 32bit number to left, to preserve meaning of next comparison.
173 __ dsll32(a7, a7, 0);
174 __ dsll32(t3, t3, 0);
175
176 __ slt(v0, t3, a7);
177 __ Branch(&error, ne, v0, Operand(0x1));
178 __ nop();
179 __ sltu(v0, t3, a7);
180 __ Branch(&error, ne, v0, Operand(zero_reg));
181 __ nop();
182
183 // Restore original values in registers.
184 __ dsrl32(a7, a7, 0);
185 __ dsrl32(t3, t3, 0);
186 // End of SPECIAL class.
187
188 __ addiu(v0, zero_reg, 0x7421); // 0x00007421
189 __ addiu(v0, v0, -0x1); // 0x00007420
190 __ addiu(v0, v0, -0x20); // 0x00007400
191 __ Branch(&error, ne, v0, Operand(0x00007400));
192 __ nop();
193 __ addiu(v1, a7, 0x1); // 0x80000000 - result is sign-extended.
194 __ Branch(&error, ne, v1, Operand(0xffffffff80000000));
195 __ nop();
196
197 __ slti(v0, a5, 0x00002000); // 0x1
198 __ slti(v0, v0, 0xffff8000); // 0x0
199 __ Branch(&error, ne, v0, Operand(zero_reg));
200 __ nop();
201 __ sltiu(v0, a5, 0x00002000); // 0x1
202 __ sltiu(v0, v0, 0x00008000); // 0x1
203 __ Branch(&error, ne, v0, Operand(0x1));
204 __ nop();
205
206 __ andi(v0, a5, 0xf0f0); // 0x00001030
207 __ ori(v0, v0, 0x8a00); // 0x00009a30
208 __ xori(v0, v0, 0x83cc); // 0x000019fc
209 __ Branch(&error, ne, v0, Operand(0x000019fc));
210 __ nop();
211 __ lui(v1, 0x8123); // Result is sign-extended into 64bit register.
212 __ Branch(&error, ne, v1, Operand(0xffffffff81230000));
213 __ nop();
214
215 // Bit twiddling instructions & conditional moves.
216 // Uses a4-t3 as set above.
217 __ Clz(v0, a4); // 29
218 __ Clz(v1, a5); // 19
219 __ addu(v0, v0, v1); // 48
220 __ Clz(v1, a6); // 3
221 __ addu(v0, v0, v1); // 51
222 __ Clz(v1, t3); // 0
223 __ addu(v0, v0, v1); // 51
224 __ Branch(&error, ne, v0, Operand(51));
225 __ Movn(a0, a7, a4); // Move a0<-a7 (a4 is NOT 0).
226 __ Ins(a0, a5, 12, 8); // 0x7ff34fff
227 __ Branch(&error, ne, a0, Operand(0x7ff34fff));
228 __ Movz(a0, t2, t3); // a0 not updated (t3 is NOT 0).
229 __ Ext(a1, a0, 8, 12); // 0x34f
230 __ Branch(&error, ne, a1, Operand(0x34f));
231 __ Movz(a0, t2, v1); // a0<-t2, v0 is 0, from 8 instr back.
232 __ Branch(&error, ne, a0, Operand(t2));
233
234 // Everything was correctly executed. Load the expected result.
235 __ li(v0, 0x31415926);
236 __ b(&exit);
237 __ nop();
238
239 __ bind(&error);
240 // Got an error. Return a wrong result.
241 __ li(v0, 666);
242
243 __ bind(&exit);
244 __ jr(ra);
245 __ nop();
246
247 CodeDesc desc;
248 assm.GetCode(&desc);
249 Handle<Code> code = isolate->factory()->NewCode(
250 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
251 F2 f = FUNCTION_CAST<F2>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 int64_t res = reinterpret_cast<int64_t>(
253 CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254
255 CHECK_EQ(0x31415926L, res);
256}
257
258
259TEST(MIPS3) {
260 // Test floating point instructions.
261 CcTest::InitializeVM();
262 Isolate* isolate = CcTest::i_isolate();
263 HandleScope scope(isolate);
264
265 typedef struct {
266 double a;
267 double b;
268 double c;
269 double d;
270 double e;
271 double f;
272 double g;
273 double h;
274 double i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 float fa;
276 float fb;
277 float fc;
278 float fd;
279 float fe;
280 float ff;
281 float fg;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 } T;
283 T t;
284
285 // Create a function that accepts &t, and loads, manipulates, and stores
286 // the doubles t.a ... t.f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288 Label L, C;
289
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 // Double precision floating point instructions.
291 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
292 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 __ add_d(f8, f4, f6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 __ sdc1(f8, MemOperand(a0, offsetof(T, c)) ); // c = a + b.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295
296 __ mov_d(f10, f8); // c
297 __ neg_d(f12, f6); // -b
298 __ sub_d(f10, f10, f12);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 __ sdc1(f10, MemOperand(a0, offsetof(T, d)) ); // d = c - (-b).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 __ sdc1(f4, MemOperand(a0, offsetof(T, b)) ); // b = a.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302
303 __ li(a4, 120);
304 __ mtc1(a4, f14);
305 __ cvt_d_w(f14, f14); // f14 = 120.0.
306 __ mul_d(f10, f10, f14);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 __ sdc1(f10, MemOperand(a0, offsetof(T, e)) ); // e = d * 120 = 1.8066e16.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308
309 __ div_d(f12, f10, f4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 __ sdc1(f12, MemOperand(a0, offsetof(T, f)) ); // f = e / a = 120.44.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311
312 __ sqrt_d(f14, f12);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 __ sdc1(f14, MemOperand(a0, offsetof(T, g)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 // g = sqrt(f) = 10.97451593465515908537
315
316 if (kArchVariant == kMips64r2) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 __ ldc1(f4, MemOperand(a0, offsetof(T, h)) );
318 __ ldc1(f6, MemOperand(a0, offsetof(T, i)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 __ madd_d(f14, f6, f4, f6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 __ sdc1(f14, MemOperand(a0, offsetof(T, h)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 }
322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 // Single precision floating point instructions.
324 __ lwc1(f4, MemOperand(a0, offsetof(T, fa)) );
325 __ lwc1(f6, MemOperand(a0, offsetof(T, fb)) );
326 __ add_s(f8, f4, f6);
327 __ swc1(f8, MemOperand(a0, offsetof(T, fc)) ); // fc = fa + fb.
328
329 __ neg_s(f10, f6); // -fb
330 __ sub_s(f10, f8, f10);
331 __ swc1(f10, MemOperand(a0, offsetof(T, fd)) ); // fd = fc - (-fb).
332
333 __ swc1(f4, MemOperand(a0, offsetof(T, fb)) ); // fb = fa.
334
335 __ li(t0, 120);
336 __ mtc1(t0, f14);
337 __ cvt_s_w(f14, f14); // f14 = 120.0.
338 __ mul_s(f10, f10, f14);
339 __ swc1(f10, MemOperand(a0, offsetof(T, fe)) ); // fe = fd * 120
340
341 __ div_s(f12, f10, f4);
342 __ swc1(f12, MemOperand(a0, offsetof(T, ff)) ); // ff = fe / fa
343
344 __ sqrt_s(f14, f12);
345 __ swc1(f14, MemOperand(a0, offsetof(T, fg)) );
346
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 __ jr(ra);
348 __ nop();
349
350 CodeDesc desc;
351 assm.GetCode(&desc);
352 Handle<Code> code = isolate->factory()->NewCode(
353 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
354 F3 f = FUNCTION_CAST<F3>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 // Double test values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 t.a = 1.5e14;
357 t.b = 2.75e11;
358 t.c = 0.0;
359 t.d = 0.0;
360 t.e = 0.0;
361 t.f = 0.0;
362 t.h = 1.5;
363 t.i = 2.75;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 // Single test values.
365 t.fa = 1.5e6;
366 t.fb = 2.75e4;
367 t.fc = 0.0;
368 t.fd = 0.0;
369 t.fe = 0.0;
370 t.ff = 0.0;
371 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 // Expected double results.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 CHECK_EQ(1.5e14, t.a);
375 CHECK_EQ(1.5e14, t.b);
376 CHECK_EQ(1.50275e14, t.c);
377 CHECK_EQ(1.50550e14, t.d);
378 CHECK_EQ(1.8066e16, t.e);
379 CHECK_EQ(120.44, t.f);
380 CHECK_EQ(10.97451593465515908537, t.g);
381 if (kArchVariant == kMips64r2) {
382 CHECK_EQ(6.875, t.h);
383 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 // Expected single results.
385 CHECK_EQ(1.5e6, t.fa);
386 CHECK_EQ(1.5e6, t.fb);
387 CHECK_EQ(1.5275e06, t.fc);
388 CHECK_EQ(1.5550e06, t.fd);
389 CHECK_EQ(1.866e08, t.fe);
390 CHECK_EQ(124.40000152587890625, t.ff);
391 CHECK_EQ(11.1534748077392578125, t.fg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392}
393
394
395TEST(MIPS4) {
396 // Test moves between floating point and integer registers.
397 CcTest::InitializeVM();
398 Isolate* isolate = CcTest::i_isolate();
399 HandleScope scope(isolate);
400
401 typedef struct {
402 double a;
403 double b;
404 double c;
405 double d;
406 int64_t high;
407 int64_t low;
408 } T;
409 T t;
410
411 Assembler assm(isolate, NULL, 0);
412 Label L, C;
413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414 __ ldc1(f4, MemOperand(a0, offsetof(T, a)));
415 __ ldc1(f5, MemOperand(a0, offsetof(T, b)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416
417 // Swap f4 and f5, by using 3 integer registers, a4-a6,
418 // both two 32-bit chunks, and one 64-bit chunk.
419 // mXhc1 is mips32/64-r2 only, not r1,
420 // but we will not support r1 in practice.
421 __ mfc1(a4, f4);
422 __ mfhc1(a5, f4);
423 __ dmfc1(a6, f5);
424
425 __ mtc1(a4, f5);
426 __ mthc1(a5, f5);
427 __ dmtc1(a6, f4);
428
429 // Store the swapped f4 and f5 back to memory.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 __ sdc1(f4, MemOperand(a0, offsetof(T, a)));
431 __ sdc1(f5, MemOperand(a0, offsetof(T, c)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432
433 // Test sign extension of move operations from coprocessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 __ ldc1(f4, MemOperand(a0, offsetof(T, d)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435 __ mfhc1(a4, f4);
436 __ mfc1(a5, f4);
437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 __ sd(a4, MemOperand(a0, offsetof(T, high)));
439 __ sd(a5, MemOperand(a0, offsetof(T, low)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440
441 __ jr(ra);
442 __ nop();
443
444 CodeDesc desc;
445 assm.GetCode(&desc);
446 Handle<Code> code = isolate->factory()->NewCode(
447 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
448 F3 f = FUNCTION_CAST<F3>(code->entry());
449 t.a = 1.5e22;
450 t.b = 2.75e11;
451 t.c = 17.17;
452 t.d = -2.75e11;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 USE(dummy);
455
456 CHECK_EQ(2.75e11, t.a);
457 CHECK_EQ(2.75e11, t.b);
458 CHECK_EQ(1.5e22, t.c);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 CHECK_EQ(static_cast<int64_t>(0xffffffffc25001d1L), t.high);
460 CHECK_EQ(static_cast<int64_t>(0xffffffffbf800000L), t.low);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461}
462
463
464TEST(MIPS5) {
465 // Test conversions between doubles and integers.
466 CcTest::InitializeVM();
467 Isolate* isolate = CcTest::i_isolate();
468 HandleScope scope(isolate);
469
470 typedef struct {
471 double a;
472 double b;
473 int i;
474 int j;
475 } T;
476 T t;
477
478 Assembler assm(isolate, NULL, 0);
479 Label L, C;
480
481 // Load all structure elements to registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
483 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
484 __ lw(a4, MemOperand(a0, offsetof(T, i)) );
485 __ lw(a5, MemOperand(a0, offsetof(T, j)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486
487 // Convert double in f4 to int in element i.
488 __ cvt_w_d(f8, f4);
489 __ mfc1(a6, f8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 __ sw(a6, MemOperand(a0, offsetof(T, i)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491
492 // Convert double in f6 to int in element j.
493 __ cvt_w_d(f10, f6);
494 __ mfc1(a7, f10);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495 __ sw(a7, MemOperand(a0, offsetof(T, j)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496
497 // Convert int in original i (a4) to double in a.
498 __ mtc1(a4, f12);
499 __ cvt_d_w(f0, f12);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 __ sdc1(f0, MemOperand(a0, offsetof(T, a)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501
502 // Convert int in original j (a5) to double in b.
503 __ mtc1(a5, f14);
504 __ cvt_d_w(f2, f14);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 __ sdc1(f2, MemOperand(a0, offsetof(T, b)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506
507 __ jr(ra);
508 __ nop();
509
510 CodeDesc desc;
511 assm.GetCode(&desc);
512 Handle<Code> code = isolate->factory()->NewCode(
513 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
514 F3 f = FUNCTION_CAST<F3>(code->entry());
515 t.a = 1.5e4;
516 t.b = 2.75e8;
517 t.i = 12345678;
518 t.j = -100000;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 USE(dummy);
521
522 CHECK_EQ(12345678.0, t.a);
523 CHECK_EQ(-100000.0, t.b);
524 CHECK_EQ(15000, t.i);
525 CHECK_EQ(275000000, t.j);
526}
527
528
529TEST(MIPS6) {
530 // Test simple memory loads and stores.
531 CcTest::InitializeVM();
532 Isolate* isolate = CcTest::i_isolate();
533 HandleScope scope(isolate);
534
535 typedef struct {
536 uint32_t ui;
537 int32_t si;
538 int32_t r1;
539 int32_t r2;
540 int32_t r3;
541 int32_t r4;
542 int32_t r5;
543 int32_t r6;
544 } T;
545 T t;
546
547 Assembler assm(isolate, NULL, 0);
548 Label L, C;
549
550 // Basic word load/store.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000551 __ lw(a4, MemOperand(a0, offsetof(T, ui)) );
552 __ sw(a4, MemOperand(a0, offsetof(T, r1)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000553
554 // lh with positive data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 __ lh(a5, MemOperand(a0, offsetof(T, ui)) );
556 __ sw(a5, MemOperand(a0, offsetof(T, r2)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557
558 // lh with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559 __ lh(a6, MemOperand(a0, offsetof(T, si)) );
560 __ sw(a6, MemOperand(a0, offsetof(T, r3)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561
562 // lhu with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 __ lhu(a7, MemOperand(a0, offsetof(T, si)) );
564 __ sw(a7, MemOperand(a0, offsetof(T, r4)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565
566 // lb with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 __ lb(t0, MemOperand(a0, offsetof(T, si)) );
568 __ sw(t0, MemOperand(a0, offsetof(T, r5)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569
570 // sh writes only 1/2 of word.
571 __ lui(t1, 0x3333);
572 __ ori(t1, t1, 0x3333);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 __ sw(t1, MemOperand(a0, offsetof(T, r6)) );
574 __ lhu(t1, MemOperand(a0, offsetof(T, si)) );
575 __ sh(t1, MemOperand(a0, offsetof(T, r6)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576
577 __ jr(ra);
578 __ nop();
579
580 CodeDesc desc;
581 assm.GetCode(&desc);
582 Handle<Code> code = isolate->factory()->NewCode(
583 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
584 F3 f = FUNCTION_CAST<F3>(code->entry());
585 t.ui = 0x11223344;
586 t.si = 0x99aabbcc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588 USE(dummy);
589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590 CHECK_EQ(static_cast<int32_t>(0x11223344), t.r1);
591 if (kArchEndian == kLittle) {
592 CHECK_EQ(static_cast<int32_t>(0x3344), t.r2);
593 CHECK_EQ(static_cast<int32_t>(0xffffbbcc), t.r3);
594 CHECK_EQ(static_cast<int32_t>(0x0000bbcc), t.r4);
595 CHECK_EQ(static_cast<int32_t>(0xffffffcc), t.r5);
596 CHECK_EQ(static_cast<int32_t>(0x3333bbcc), t.r6);
597 } else {
598 CHECK_EQ(static_cast<int32_t>(0x1122), t.r2);
599 CHECK_EQ(static_cast<int32_t>(0xffff99aa), t.r3);
600 CHECK_EQ(static_cast<int32_t>(0x000099aa), t.r4);
601 CHECK_EQ(static_cast<int32_t>(0xffffff99), t.r5);
602 CHECK_EQ(static_cast<int32_t>(0x99aa3333), t.r6);
603 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604}
605
606
607TEST(MIPS7) {
608 // Test floating point compare and branch instructions.
609 CcTest::InitializeVM();
610 Isolate* isolate = CcTest::i_isolate();
611 HandleScope scope(isolate);
612
613 typedef struct {
614 double a;
615 double b;
616 double c;
617 double d;
618 double e;
619 double f;
620 int32_t result;
621 } T;
622 T t;
623
624 // Create a function that accepts &t, and loads, manipulates, and stores
625 // the doubles t.a ... t.f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 Label neither_is_nan, less_than, outa_here;
628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
630 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 if (kArchVariant != kMips64r6) {
632 __ c(UN, D, f4, f6);
633 __ bc1f(&neither_is_nan);
634 } else {
635 __ cmp(UN, L, f2, f4, f6);
636 __ bc1eqz(&neither_is_nan, f2);
637 }
638 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 __ Branch(&outa_here);
641
642 __ bind(&neither_is_nan);
643
644 if (kArchVariant == kMips64r6) {
645 __ cmp(OLT, L, f2, f6, f4);
646 __ bc1nez(&less_than, f2);
647 } else {
648 __ c(OLT, D, f6, f4, 2);
649 __ bc1t(&less_than, 2);
650 }
651
652 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 __ Branch(&outa_here);
655
656 __ bind(&less_than);
657 __ Addu(a4, zero_reg, Operand(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 __ sw(a4, MemOperand(a0, offsetof(T, result)) ); // Set true.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659
660
661 // This test-case should have additional tests.
662
663 __ bind(&outa_here);
664
665 __ jr(ra);
666 __ nop();
667
668 CodeDesc desc;
669 assm.GetCode(&desc);
670 Handle<Code> code = isolate->factory()->NewCode(
671 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
672 F3 f = FUNCTION_CAST<F3>(code->entry());
673 t.a = 1.5e14;
674 t.b = 2.75e11;
675 t.c = 2.0;
676 t.d = -4.0;
677 t.e = 0.0;
678 t.f = 0.0;
679 t.result = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681 USE(dummy);
682 CHECK_EQ(1.5e14, t.a);
683 CHECK_EQ(2.75e11, t.b);
684 CHECK_EQ(1, t.result);
685}
686
687
688TEST(MIPS8) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689 if (kArchVariant == kMips64r2) {
690 // Test ROTR and ROTRV instructions.
691 CcTest::InitializeVM();
692 Isolate* isolate = CcTest::i_isolate();
693 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695 typedef struct {
696 int32_t input;
697 int32_t result_rotr_4;
698 int32_t result_rotr_8;
699 int32_t result_rotr_12;
700 int32_t result_rotr_16;
701 int32_t result_rotr_20;
702 int32_t result_rotr_24;
703 int32_t result_rotr_28;
704 int32_t result_rotrv_4;
705 int32_t result_rotrv_8;
706 int32_t result_rotrv_12;
707 int32_t result_rotrv_16;
708 int32_t result_rotrv_20;
709 int32_t result_rotrv_24;
710 int32_t result_rotrv_28;
711 } T;
712 T t;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 MacroAssembler assm(isolate, NULL, 0,
715 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000717 // Basic word load.
718 __ lw(a4, MemOperand(a0, offsetof(T, input)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 // ROTR instruction (called through the Ror macro).
721 __ Ror(a5, a4, 0x0004);
722 __ Ror(a6, a4, 0x0008);
723 __ Ror(a7, a4, 0x000c);
724 __ Ror(t0, a4, 0x0010);
725 __ Ror(t1, a4, 0x0014);
726 __ Ror(t2, a4, 0x0018);
727 __ Ror(t3, a4, 0x001c);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 // Basic word store.
730 __ sw(a5, MemOperand(a0, offsetof(T, result_rotr_4)) );
731 __ sw(a6, MemOperand(a0, offsetof(T, result_rotr_8)) );
732 __ sw(a7, MemOperand(a0, offsetof(T, result_rotr_12)) );
733 __ sw(t0, MemOperand(a0, offsetof(T, result_rotr_16)) );
734 __ sw(t1, MemOperand(a0, offsetof(T, result_rotr_20)) );
735 __ sw(t2, MemOperand(a0, offsetof(T, result_rotr_24)) );
736 __ sw(t3, MemOperand(a0, offsetof(T, result_rotr_28)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 // ROTRV instruction (called through the Ror macro).
739 __ li(t3, 0x0004);
740 __ Ror(a5, a4, t3);
741 __ li(t3, 0x0008);
742 __ Ror(a6, a4, t3);
743 __ li(t3, 0x000C);
744 __ Ror(a7, a4, t3);
745 __ li(t3, 0x0010);
746 __ Ror(t0, a4, t3);
747 __ li(t3, 0x0014);
748 __ Ror(t1, a4, t3);
749 __ li(t3, 0x0018);
750 __ Ror(t2, a4, t3);
751 __ li(t3, 0x001C);
752 __ Ror(t3, a4, t3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 // Basic word store.
755 __ sw(a5, MemOperand(a0, offsetof(T, result_rotrv_4)) );
756 __ sw(a6, MemOperand(a0, offsetof(T, result_rotrv_8)) );
757 __ sw(a7, MemOperand(a0, offsetof(T, result_rotrv_12)) );
758 __ sw(t0, MemOperand(a0, offsetof(T, result_rotrv_16)) );
759 __ sw(t1, MemOperand(a0, offsetof(T, result_rotrv_20)) );
760 __ sw(t2, MemOperand(a0, offsetof(T, result_rotrv_24)) );
761 __ sw(t3, MemOperand(a0, offsetof(T, result_rotrv_28)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000762
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 __ jr(ra);
764 __ nop();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 CodeDesc desc;
767 assm.GetCode(&desc);
768 Handle<Code> code = isolate->factory()->NewCode(
769 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
770 F3 f = FUNCTION_CAST<F3>(code->entry());
771 t.input = 0x12345678;
772 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0x0, 0, 0, 0);
773 USE(dummy);
774 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotr_4);
775 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotr_8);
776 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotr_12);
777 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotr_16);
778 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotr_20);
779 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotr_24);
780 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotr_28);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotrv_4);
783 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotrv_8);
784 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotrv_12);
785 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotrv_16);
786 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotrv_20);
787 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotrv_24);
788 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotrv_28);
789 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790}
791
792
793TEST(MIPS9) {
794 // Test BRANCH improvements.
795 CcTest::InitializeVM();
796 Isolate* isolate = CcTest::i_isolate();
797 HandleScope scope(isolate);
798
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000799 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800 Label exit, exit2, exit3;
801
802 __ Branch(&exit, ge, a0, Operand(zero_reg));
803 __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
804 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
805
806 __ bind(&exit);
807 __ bind(&exit2);
808 __ bind(&exit3);
809 __ jr(ra);
810 __ nop();
811
812 CodeDesc desc;
813 assm.GetCode(&desc);
814 isolate->factory()->NewCode(
815 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
816}
817
818
819TEST(MIPS10) {
820 // Test conversions between doubles and long integers.
821 // Test hos the long ints map to FP regs pairs.
822 CcTest::InitializeVM();
823 Isolate* isolate = CcTest::i_isolate();
824 HandleScope scope(isolate);
825
826 typedef struct {
827 double a;
828 double a_converted;
829 double b;
830 int32_t dbl_mant;
831 int32_t dbl_exp;
832 int32_t long_hi;
833 int32_t long_lo;
834 int64_t long_as_int64;
835 int32_t b_long_hi;
836 int32_t b_long_lo;
837 int64_t b_long_as_int64;
838 } T;
839 T t;
840
841 Assembler assm(isolate, NULL, 0);
842 Label L, C;
843
844 if (kArchVariant == kMips64r2) {
845 // Rewritten for FR=1 FPU mode:
846 // - 32 FP regs of 64-bits each, no odd/even pairs.
847 // - Note that cvt_l_d/cvt_d_l ARE legal in FR=1 mode.
848 // Load all structure elements to registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 __ ldc1(f0, MemOperand(a0, offsetof(T, a)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850
851 // Save the raw bits of the double.
852 __ mfc1(a4, f0);
853 __ mfhc1(a5, f0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 __ sw(a4, MemOperand(a0, offsetof(T, dbl_mant)));
855 __ sw(a5, MemOperand(a0, offsetof(T, dbl_exp)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856
857 // Convert double in f0 to long, save hi/lo parts.
858 __ cvt_l_d(f0, f0);
859 __ mfc1(a4, f0); // f0 LS 32 bits of long.
860 __ mfhc1(a5, f0); // f0 MS 32 bits of long.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 __ sw(a4, MemOperand(a0, offsetof(T, long_lo)));
862 __ sw(a5, MemOperand(a0, offsetof(T, long_hi)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863
864 // Combine the high/low ints, convert back to double.
865 __ dsll32(a6, a5, 0); // Move a5 to high bits of a6.
866 __ or_(a6, a6, a4);
867 __ dmtc1(a6, f1);
868 __ cvt_d_l(f1, f1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 __ sdc1(f1, MemOperand(a0, offsetof(T, a_converted)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870
871
872 // Convert the b long integers to double b.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 __ lw(a4, MemOperand(a0, offsetof(T, b_long_lo)));
874 __ lw(a5, MemOperand(a0, offsetof(T, b_long_hi)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 __ mtc1(a4, f8); // f8 LS 32-bits.
876 __ mthc1(a5, f8); // f8 MS 32-bits.
877 __ cvt_d_l(f10, f8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 __ sdc1(f10, MemOperand(a0, offsetof(T, b)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879
880 // Convert double b back to long-int.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 __ ldc1(f31, MemOperand(a0, offsetof(T, b)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 __ cvt_l_d(f31, f31);
883 __ dmfc1(a7, f31);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 __ sd(a7, MemOperand(a0, offsetof(T, b_long_as_int64)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885
886
887 __ jr(ra);
888 __ nop();
889
890 CodeDesc desc;
891 assm.GetCode(&desc);
892 Handle<Code> code = isolate->factory()->NewCode(
893 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
894 F3 f = FUNCTION_CAST<F3>(code->entry());
895 t.a = 2.147483647e9; // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
896 t.b_long_hi = 0x000000ff; // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
897 t.b_long_lo = 0x00ff00ff;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 USE(dummy);
900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000901 CHECK_EQ(static_cast<int32_t>(0x41DFFFFF), t.dbl_exp);
902 CHECK_EQ(static_cast<int32_t>(0xFFC00000), t.dbl_mant);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 CHECK_EQ(0, t.long_hi);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 CHECK_EQ(static_cast<int32_t>(0x7fffffff), t.long_lo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 CHECK_EQ(2.147483647e9, t.a_converted);
906
907 // 0xFF00FF00FF -> 1.095233372415e12.
908 CHECK_EQ(1.095233372415e12, t.b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 CHECK_EQ(static_cast<int64_t>(0xFF00FF00FF), t.b_long_as_int64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 }
911}
912
913
914TEST(MIPS11) {
915 // Do not run test on MIPS64r6, as these instructions are removed.
916 if (kArchVariant != kMips64r6) {
917 // Test LWL, LWR, SWL and SWR instructions.
918 CcTest::InitializeVM();
919 Isolate* isolate = CcTest::i_isolate();
920 HandleScope scope(isolate);
921
922 typedef struct {
923 int32_t reg_init;
924 int32_t mem_init;
925 int32_t lwl_0;
926 int32_t lwl_1;
927 int32_t lwl_2;
928 int32_t lwl_3;
929 int32_t lwr_0;
930 int32_t lwr_1;
931 int32_t lwr_2;
932 int32_t lwr_3;
933 int32_t swl_0;
934 int32_t swl_1;
935 int32_t swl_2;
936 int32_t swl_3;
937 int32_t swr_0;
938 int32_t swr_1;
939 int32_t swr_2;
940 int32_t swr_3;
941 } T;
942 T t;
943
944 Assembler assm(isolate, NULL, 0);
945
946 // Test all combinations of LWL and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947 __ lw(a4, MemOperand(a0, offsetof(T, reg_init)));
948 __ lwl(a4, MemOperand(a0, offsetof(T, mem_init)));
949 __ sw(a4, MemOperand(a0, offsetof(T, lwl_0)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 __ lw(a5, MemOperand(a0, offsetof(T, reg_init)));
952 __ lwl(a5, MemOperand(a0, offsetof(T, mem_init) + 1));
953 __ sw(a5, MemOperand(a0, offsetof(T, lwl_1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 __ lw(a6, MemOperand(a0, offsetof(T, reg_init)));
956 __ lwl(a6, MemOperand(a0, offsetof(T, mem_init) + 2));
957 __ sw(a6, MemOperand(a0, offsetof(T, lwl_2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 __ lw(a7, MemOperand(a0, offsetof(T, reg_init)));
960 __ lwl(a7, MemOperand(a0, offsetof(T, mem_init) + 3));
961 __ sw(a7, MemOperand(a0, offsetof(T, lwl_3)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962
963 // Test all combinations of LWR and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 __ lw(a4, MemOperand(a0, offsetof(T, reg_init)));
965 __ lwr(a4, MemOperand(a0, offsetof(T, mem_init)));
966 __ sw(a4, MemOperand(a0, offsetof(T, lwr_0)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 __ lw(a5, MemOperand(a0, offsetof(T, reg_init)));
969 __ lwr(a5, MemOperand(a0, offsetof(T, mem_init) + 1));
970 __ sw(a5, MemOperand(a0, offsetof(T, lwr_1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 __ lw(a6, MemOperand(a0, offsetof(T, reg_init)));
973 __ lwr(a6, MemOperand(a0, offsetof(T, mem_init) + 2));
974 __ sw(a6, MemOperand(a0, offsetof(T, lwr_2)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 __ lw(a7, MemOperand(a0, offsetof(T, reg_init)));
977 __ lwr(a7, MemOperand(a0, offsetof(T, mem_init) + 3));
978 __ sw(a7, MemOperand(a0, offsetof(T, lwr_3)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000979
980 // Test all combinations of SWL and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 __ lw(a4, MemOperand(a0, offsetof(T, mem_init)));
982 __ sw(a4, MemOperand(a0, offsetof(T, swl_0)));
983 __ lw(a4, MemOperand(a0, offsetof(T, reg_init)));
984 __ swl(a4, MemOperand(a0, offsetof(T, swl_0)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000985
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 __ lw(a5, MemOperand(a0, offsetof(T, mem_init)));
987 __ sw(a5, MemOperand(a0, offsetof(T, swl_1)));
988 __ lw(a5, MemOperand(a0, offsetof(T, reg_init)));
989 __ swl(a5, MemOperand(a0, offsetof(T, swl_1) + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 __ lw(a6, MemOperand(a0, offsetof(T, mem_init)));
992 __ sw(a6, MemOperand(a0, offsetof(T, swl_2)));
993 __ lw(a6, MemOperand(a0, offsetof(T, reg_init)));
994 __ swl(a6, MemOperand(a0, offsetof(T, swl_2) + 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000996 __ lw(a7, MemOperand(a0, offsetof(T, mem_init)));
997 __ sw(a7, MemOperand(a0, offsetof(T, swl_3)));
998 __ lw(a7, MemOperand(a0, offsetof(T, reg_init)));
999 __ swl(a7, MemOperand(a0, offsetof(T, swl_3) + 3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000
1001 // Test all combinations of SWR and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 __ lw(a4, MemOperand(a0, offsetof(T, mem_init)));
1003 __ sw(a4, MemOperand(a0, offsetof(T, swr_0)));
1004 __ lw(a4, MemOperand(a0, offsetof(T, reg_init)));
1005 __ swr(a4, MemOperand(a0, offsetof(T, swr_0)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001007 __ lw(a5, MemOperand(a0, offsetof(T, mem_init)));
1008 __ sw(a5, MemOperand(a0, offsetof(T, swr_1)));
1009 __ lw(a5, MemOperand(a0, offsetof(T, reg_init)));
1010 __ swr(a5, MemOperand(a0, offsetof(T, swr_1) + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001011
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001012 __ lw(a6, MemOperand(a0, offsetof(T, mem_init)));
1013 __ sw(a6, MemOperand(a0, offsetof(T, swr_2)));
1014 __ lw(a6, MemOperand(a0, offsetof(T, reg_init)));
1015 __ swr(a6, MemOperand(a0, offsetof(T, swr_2) + 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 __ lw(a7, MemOperand(a0, offsetof(T, mem_init)));
1018 __ sw(a7, MemOperand(a0, offsetof(T, swr_3)));
1019 __ lw(a7, MemOperand(a0, offsetof(T, reg_init)));
1020 __ swr(a7, MemOperand(a0, offsetof(T, swr_3) + 3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001021
1022 __ jr(ra);
1023 __ nop();
1024
1025 CodeDesc desc;
1026 assm.GetCode(&desc);
1027 Handle<Code> code = isolate->factory()->NewCode(
1028 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1029 F3 f = FUNCTION_CAST<F3>(code->entry());
1030 t.reg_init = 0xaabbccdd;
1031 t.mem_init = 0x11223344;
1032
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001033 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 USE(dummy);
1035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 if (kArchEndian == kLittle) {
1037 CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_0);
1038 CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_1);
1039 CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_2);
1040 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001041
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_0);
1043 CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_1);
1044 CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_2);
1045 CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_0);
1048 CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_1);
1049 CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_2);
1050 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001051
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_0);
1053 CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_1);
1054 CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_2);
1055 CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_3);
1056 } else {
1057 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_0);
1058 CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_1);
1059 CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_2);
1060 CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_3);
1061
1062 CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_0);
1063 CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_1);
1064 CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_2);
1065 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_3);
1066
1067 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_0);
1068 CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_1);
1069 CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_2);
1070 CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_3);
1071
1072 CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_0);
1073 CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_1);
1074 CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_2);
1075 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_3);
1076 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 }
1078}
1079
1080
1081TEST(MIPS12) {
1082 CcTest::InitializeVM();
1083 Isolate* isolate = CcTest::i_isolate();
1084 HandleScope scope(isolate);
1085
1086 typedef struct {
1087 int32_t x;
1088 int32_t y;
1089 int32_t y1;
1090 int32_t y2;
1091 int32_t y3;
1092 int32_t y4;
1093 } T;
1094 T t;
1095
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097
1098 __ mov(t2, fp); // Save frame pointer.
1099 __ mov(fp, a0); // Access struct T by fp.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001100 __ lw(a4, MemOperand(a0, offsetof(T, y)));
1101 __ lw(a7, MemOperand(a0, offsetof(T, y4)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102
1103 __ addu(a5, a4, a7);
1104 __ subu(t0, a4, a7);
1105 __ nop();
1106 __ push(a4); // These instructions disappear after opt.
1107 __ Pop();
1108 __ addu(a4, a4, a4);
1109 __ nop();
1110 __ Pop(); // These instructions disappear after opt.
1111 __ push(a7);
1112 __ nop();
1113 __ push(a7); // These instructions disappear after opt.
1114 __ pop(a7);
1115 __ nop();
1116 __ push(a7);
1117 __ pop(t0);
1118 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 __ sw(a4, MemOperand(fp, offsetof(T, y)));
1120 __ lw(a4, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 __ sw(a4, MemOperand(fp, offsetof(T, y)));
1123 __ lw(a5, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124 __ nop();
1125 __ push(a5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 __ lw(a5, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001127 __ pop(a5);
1128 __ nop();
1129 __ push(a5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001130 __ lw(a6, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 __ pop(a5);
1132 __ nop();
1133 __ push(a5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 __ lw(a6, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001135 __ pop(a6);
1136 __ nop();
1137 __ push(a6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138 __ lw(a6, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001139 __ pop(a5);
1140 __ nop();
1141 __ push(a5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 __ lw(a6, MemOperand(fp, offsetof(T, y)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001143 __ pop(a7);
1144 __ nop();
1145
1146 __ mov(fp, t2);
1147 __ jr(ra);
1148 __ nop();
1149
1150 CodeDesc desc;
1151 assm.GetCode(&desc);
1152 Handle<Code> code = isolate->factory()->NewCode(
1153 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1154 F3 f = FUNCTION_CAST<F3>(code->entry());
1155 t.x = 1;
1156 t.y = 2;
1157 t.y1 = 3;
1158 t.y2 = 4;
1159 t.y3 = 0XBABA;
1160 t.y4 = 0xDEDA;
1161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163 USE(dummy);
1164
1165 CHECK_EQ(3, t.y1);
1166}
1167
1168
1169TEST(MIPS13) {
1170 // Test Cvt_d_uw and Trunc_uw_d macros.
1171 CcTest::InitializeVM();
1172 Isolate* isolate = CcTest::i_isolate();
1173 HandleScope scope(isolate);
1174
1175 typedef struct {
1176 double cvt_big_out;
1177 double cvt_small_out;
1178 uint32_t trunc_big_out;
1179 uint32_t trunc_small_out;
1180 uint32_t cvt_big_in;
1181 uint32_t cvt_small_in;
1182 } T;
1183 T t;
1184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 __ sw(a4, MemOperand(a0, offsetof(T, cvt_small_in)));
1188 __ Cvt_d_uw(f10, a4);
1189 __ sdc1(f10, MemOperand(a0, offsetof(T, cvt_small_out)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001191 __ Trunc_uw_d(f10, f10, f4);
1192 __ swc1(f10, MemOperand(a0, offsetof(T, trunc_small_out)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194 __ sw(a4, MemOperand(a0, offsetof(T, cvt_big_in)));
1195 __ Cvt_d_uw(f8, a4);
1196 __ sdc1(f8, MemOperand(a0, offsetof(T, cvt_big_out)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 __ Trunc_uw_d(f8, f8, f4);
1199 __ swc1(f8, MemOperand(a0, offsetof(T, trunc_big_out)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001200
1201 __ jr(ra);
1202 __ nop();
1203
1204 CodeDesc desc;
1205 assm.GetCode(&desc);
1206 Handle<Code> code = isolate->factory()->NewCode(
1207 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1208 F3 f = FUNCTION_CAST<F3>(code->entry());
1209
1210 t.cvt_big_in = 0xFFFFFFFF;
1211 t.cvt_small_in = 333;
1212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 USE(dummy);
1215
1216 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1217 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1218
1219 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1220 CHECK_EQ(static_cast<int>(t.trunc_small_out),
1221 static_cast<int>(t.cvt_small_in));
1222}
1223
1224
1225TEST(MIPS14) {
1226 // Test round, floor, ceil, trunc, cvt.
1227 CcTest::InitializeVM();
1228 Isolate* isolate = CcTest::i_isolate();
1229 HandleScope scope(isolate);
1230
1231#define ROUND_STRUCT_ELEMENT(x) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 uint32_t x##_isNaN2008; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 int32_t x##_up_out; \
1234 int32_t x##_down_out; \
1235 int32_t neg_##x##_up_out; \
1236 int32_t neg_##x##_down_out; \
1237 uint32_t x##_err1_out; \
1238 uint32_t x##_err2_out; \
1239 uint32_t x##_err3_out; \
1240 uint32_t x##_err4_out; \
1241 int32_t x##_invalid_result;
1242
1243 typedef struct {
1244 double round_up_in;
1245 double round_down_in;
1246 double neg_round_up_in;
1247 double neg_round_down_in;
1248 double err1_in;
1249 double err2_in;
1250 double err3_in;
1251 double err4_in;
1252
1253 ROUND_STRUCT_ELEMENT(round)
1254 ROUND_STRUCT_ELEMENT(floor)
1255 ROUND_STRUCT_ELEMENT(ceil)
1256 ROUND_STRUCT_ELEMENT(trunc)
1257 ROUND_STRUCT_ELEMENT(cvt)
1258 } T;
1259 T t;
1260
1261#undef ROUND_STRUCT_ELEMENT
1262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264
1265 // Save FCSR.
1266 __ cfc1(a1, FCSR);
1267 // Disable FPU exceptions.
1268 __ ctc1(zero_reg, FCSR);
1269#define RUN_ROUND_TEST(x) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 __ cfc1(t0, FCSR);\
1271 __ sw(t0, MemOperand(a0, offsetof(T, x##_isNaN2008))); \
1272 __ ldc1(f0, MemOperand(a0, offsetof(T, round_up_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 __ swc1(f0, MemOperand(a0, offsetof(T, x##_up_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 __ ldc1(f0, MemOperand(a0, offsetof(T, round_down_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 __ swc1(f0, MemOperand(a0, offsetof(T, x##_down_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_up_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_up_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284 __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_down_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_down_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001288 __ ldc1(f0, MemOperand(a0, offsetof(T, err1_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 __ ctc1(zero_reg, FCSR); \
1290 __ x##_w_d(f0, f0); \
1291 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292 __ sw(a2, MemOperand(a0, offsetof(T, x##_err1_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001293 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 __ ldc1(f0, MemOperand(a0, offsetof(T, err2_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001295 __ ctc1(zero_reg, FCSR); \
1296 __ x##_w_d(f0, f0); \
1297 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298 __ sw(a2, MemOperand(a0, offsetof(T, x##_err2_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001300 __ ldc1(f0, MemOperand(a0, offsetof(T, err3_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 __ ctc1(zero_reg, FCSR); \
1302 __ x##_w_d(f0, f0); \
1303 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 __ sw(a2, MemOperand(a0, offsetof(T, x##_err3_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001306 __ ldc1(f0, MemOperand(a0, offsetof(T, err4_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 __ ctc1(zero_reg, FCSR); \
1308 __ x##_w_d(f0, f0); \
1309 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 __ sw(a2, MemOperand(a0, offsetof(T, x##_err4_out))); \
1311 __ swc1(f0, MemOperand(a0, offsetof(T, x##_invalid_result)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312
1313 RUN_ROUND_TEST(round)
1314 RUN_ROUND_TEST(floor)
1315 RUN_ROUND_TEST(ceil)
1316 RUN_ROUND_TEST(trunc)
1317 RUN_ROUND_TEST(cvt)
1318
1319 // Restore FCSR.
1320 __ ctc1(a1, FCSR);
1321
1322 __ jr(ra);
1323 __ nop();
1324
1325 CodeDesc desc;
1326 assm.GetCode(&desc);
1327 Handle<Code> code = isolate->factory()->NewCode(
1328 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1329 F3 f = FUNCTION_CAST<F3>(code->entry());
1330
1331 t.round_up_in = 123.51;
1332 t.round_down_in = 123.49;
1333 t.neg_round_up_in = -123.5;
1334 t.neg_round_down_in = -123.49;
1335 t.err1_in = 123.51;
1336 t.err2_in = 1;
1337 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1338 t.err4_in = NAN;
1339
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001340 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 USE(dummy);
1342
1343#define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001344#define CHECK_NAN2008(x) (x & kFCSRNaN2008FlagMask)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345#define CHECK_ROUND_RESULT(type) \
1346 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1347 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1348 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1349 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350 if (CHECK_NAN2008(t.type##_isNaN2008) && kArchVariant == kMips64r6) { \
1351 CHECK_EQ(static_cast<int32_t>(0), t.type##_invalid_result);\
1352 } else { \
1353 CHECK_EQ(static_cast<int32_t>(kFPUInvalidResult), t.type##_invalid_result);\
1354 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355
1356 CHECK_ROUND_RESULT(round);
1357 CHECK_ROUND_RESULT(floor);
1358 CHECK_ROUND_RESULT(ceil);
1359 CHECK_ROUND_RESULT(cvt);
1360}
1361
1362
1363TEST(MIPS15) {
1364 // Test chaining of label usages within instructions (issue 1644).
1365 CcTest::InitializeVM();
1366 Isolate* isolate = CcTest::i_isolate();
1367 HandleScope scope(isolate);
1368 Assembler assm(isolate, NULL, 0);
1369
1370 Label target;
1371 __ beq(v0, v1, &target);
1372 __ nop();
1373 __ bne(v0, v1, &target);
1374 __ nop();
1375 __ bind(&target);
1376 __ nop();
1377}
1378
1379
1380// ----- mips64 tests -----------------------------------------------
1381
1382TEST(MIPS16) {
1383 // Test 64-bit memory loads and stores.
1384 CcTest::InitializeVM();
1385 Isolate* isolate = CcTest::i_isolate();
1386 HandleScope scope(isolate);
1387
1388 typedef struct {
1389 int64_t r1;
1390 int64_t r2;
1391 int64_t r3;
1392 int64_t r4;
1393 int64_t r5;
1394 int64_t r6;
1395 uint32_t ui;
1396 int32_t si;
1397 } T;
1398 T t;
1399
1400 Assembler assm(isolate, NULL, 0);
1401 Label L, C;
1402
1403 // Basic 32-bit word load/store, with un-signed data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001404 __ lw(a4, MemOperand(a0, offsetof(T, ui)));
1405 __ sw(a4, MemOperand(a0, offsetof(T, r1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406
1407 // Check that the data got zero-extended into 64-bit a4.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408 __ sd(a4, MemOperand(a0, offsetof(T, r2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409
1410 // Basic 32-bit word load/store, with SIGNED data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 __ lw(a5, MemOperand(a0, offsetof(T, si)));
1412 __ sw(a5, MemOperand(a0, offsetof(T, r3)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413
1414 // Check that the data got sign-extended into 64-bit a4.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001415 __ sd(a5, MemOperand(a0, offsetof(T, r4)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416
1417 // 32-bit UNSIGNED word load/store, with SIGNED data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001418 __ lwu(a6, MemOperand(a0, offsetof(T, si)));
1419 __ sw(a6, MemOperand(a0, offsetof(T, r5)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420
1421 // Check that the data got zero-extended into 64-bit a4.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 __ sd(a6, MemOperand(a0, offsetof(T, r6)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423
1424 // lh with positive data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001425 __ lh(a5, MemOperand(a0, offsetof(T, ui)));
1426 __ sw(a5, MemOperand(a0, offsetof(T, r2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427
1428 // lh with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001429 __ lh(a6, MemOperand(a0, offsetof(T, si)));
1430 __ sw(a6, MemOperand(a0, offsetof(T, r3)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431
1432 // lhu with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001433 __ lhu(a7, MemOperand(a0, offsetof(T, si)));
1434 __ sw(a7, MemOperand(a0, offsetof(T, r4)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001435
1436 // lb with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001437 __ lb(t0, MemOperand(a0, offsetof(T, si)));
1438 __ sw(t0, MemOperand(a0, offsetof(T, r5)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001439
1440 // // sh writes only 1/2 of word.
1441 __ lui(t1, 0x3333);
1442 __ ori(t1, t1, 0x3333);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443 __ sw(t1, MemOperand(a0, offsetof(T, r6)));
1444 __ lhu(t1, MemOperand(a0, offsetof(T, si)));
1445 __ sh(t1, MemOperand(a0, offsetof(T, r6)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446
1447 __ jr(ra);
1448 __ nop();
1449
1450 CodeDesc desc;
1451 assm.GetCode(&desc);
1452 Handle<Code> code = isolate->factory()->NewCode(
1453 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1454 F3 f = FUNCTION_CAST<F3>(code->entry());
1455 t.ui = 0x44332211;
1456 t.si = 0x99aabbcc;
1457 t.r1 = 0x1111111111111111;
1458 t.r2 = 0x2222222222222222;
1459 t.r3 = 0x3333333333333333;
1460 t.r4 = 0x4444444444444444;
1461 t.r5 = 0x5555555555555555;
1462 t.r6 = 0x6666666666666666;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001463 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001464 USE(dummy);
1465
1466 // Unsigned data, 32 & 64.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001467 CHECK_EQ(static_cast<int64_t>(0x1111111144332211L), t.r1);
1468 CHECK_EQ(static_cast<int64_t>(0x0000000000002211L), t.r2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469
1470 // Signed data, 32 & 64.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471 CHECK_EQ(static_cast<int64_t>(0x33333333ffffbbccL), t.r3);
1472 CHECK_EQ(static_cast<int64_t>(0xffffffff0000bbccL), t.r4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473
1474 // Signed data, 32 & 64.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475 CHECK_EQ(static_cast<int64_t>(0x55555555ffffffccL), t.r5);
1476 CHECK_EQ(static_cast<int64_t>(0x000000003333bbccL), t.r6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001477}
1478
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001479
1480// ----------------------mips64r6 specific tests----------------------
1481TEST(seleqz_selnez) {
1482 if (kArchVariant == kMips64r6) {
1483 CcTest::InitializeVM();
1484 Isolate* isolate = CcTest::i_isolate();
1485 HandleScope scope(isolate);
1486 MacroAssembler assm(isolate, NULL, 0,
1487 v8::internal::CodeObjectRequired::kYes);
1488
1489 typedef struct test {
1490 int a;
1491 int b;
1492 int c;
1493 int d;
1494 double e;
1495 double f;
1496 double g;
1497 double h;
1498 float i;
1499 float j;
1500 float k;
1501 float l;
1502 } Test;
1503
1504 Test test;
1505 // Integer part of test.
1506 __ addiu(t1, zero_reg, 1); // t1 = 1
1507 __ seleqz(t3, t1, zero_reg); // t3 = 1
1508 __ sw(t3, MemOperand(a0, offsetof(Test, a))); // a = 1
1509 __ seleqz(t2, t1, t1); // t2 = 0
1510 __ sw(t2, MemOperand(a0, offsetof(Test, b))); // b = 0
1511 __ selnez(t3, t1, zero_reg); // t3 = 1;
1512 __ sw(t3, MemOperand(a0, offsetof(Test, c))); // c = 0
1513 __ selnez(t3, t1, t1); // t3 = 1
1514 __ sw(t3, MemOperand(a0, offsetof(Test, d))); // d = 1
1515 // Floating point part of test.
1516 __ ldc1(f0, MemOperand(a0, offsetof(Test, e)) ); // src
1517 __ ldc1(f2, MemOperand(a0, offsetof(Test, f)) ); // test
1518 __ lwc1(f8, MemOperand(a0, offsetof(Test, i)) ); // src
1519 __ lwc1(f10, MemOperand(a0, offsetof(Test, j)) ); // test
1520 __ seleqz_d(f4, f0, f2);
1521 __ selnez_d(f6, f0, f2);
1522 __ seleqz_s(f12, f8, f10);
1523 __ selnez_s(f14, f8, f10);
1524 __ sdc1(f4, MemOperand(a0, offsetof(Test, g)) ); // src
1525 __ sdc1(f6, MemOperand(a0, offsetof(Test, h)) ); // src
1526 __ swc1(f12, MemOperand(a0, offsetof(Test, k)) ); // src
1527 __ swc1(f14, MemOperand(a0, offsetof(Test, l)) ); // src
1528 __ jr(ra);
1529 __ nop();
1530 CodeDesc desc;
1531 assm.GetCode(&desc);
1532 Handle<Code> code = isolate->factory()->NewCode(
1533 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1534 F3 f = FUNCTION_CAST<F3>(code->entry());
1535
1536 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1537
1538 CHECK_EQ(test.a, 1);
1539 CHECK_EQ(test.b, 0);
1540 CHECK_EQ(test.c, 0);
1541 CHECK_EQ(test.d, 1);
1542
1543 const int test_size = 3;
1544 const int input_size = 5;
1545
1546 double inputs_D[input_size] = {0.0, 65.2, -70.32,
1547 18446744073709551621.0, -18446744073709551621.0};
1548 double outputs_D[input_size] = {0.0, 65.2, -70.32,
1549 18446744073709551621.0, -18446744073709551621.0};
1550 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9,
1551 18446744073709551616.0, 18446744073709555712.0};
1552 float inputs_S[input_size] = {0.0, 65.2, -70.32,
1553 18446744073709551621.0, -18446744073709551621.0};
1554 float outputs_S[input_size] = {0.0, 65.2, -70.32,
1555 18446744073709551621.0, -18446744073709551621.0};
1556 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8,
1557 18446744073709551616.0, 18446746272732807168.0};
1558 for (int j=0; j < test_size; j+=2) {
1559 for (int i=0; i < input_size; i++) {
1560 test.e = inputs_D[i];
1561 test.f = tests_D[j];
1562 test.i = inputs_S[i];
1563 test.j = tests_S[j];
1564 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1565 CHECK_EQ(test.g, outputs_D[i]);
1566 CHECK_EQ(test.h, 0);
1567 CHECK_EQ(test.k, outputs_S[i]);
1568 CHECK_EQ(test.l, 0);
1569
1570 test.f = tests_D[j+1];
1571 test.j = tests_S[j+1];
1572 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1573 CHECK_EQ(test.g, 0);
1574 CHECK_EQ(test.h, outputs_D[i]);
1575 CHECK_EQ(test.k, 0);
1576 CHECK_EQ(test.l, outputs_S[i]);
1577 }
1578 }
1579 }
1580}
1581
1582
1583
1584TEST(min_max) {
1585 if (kArchVariant == kMips64r6) {
1586 CcTest::InitializeVM();
1587 Isolate* isolate = CcTest::i_isolate();
1588 HandleScope scope(isolate);
1589 MacroAssembler assm(isolate, NULL, 0,
1590 v8::internal::CodeObjectRequired::kYes);
1591
1592 typedef struct test_float {
1593 double a;
1594 double b;
1595 double c;
1596 double d;
1597 float e;
1598 float f;
1599 float g;
1600 float h;
1601 } TestFloat;
1602
1603 TestFloat test;
1604 const double double_nan = std::numeric_limits<double>::quiet_NaN();
1605 const float float_nan = std::numeric_limits<float>::quiet_NaN();
1606 const int kTableLength = 5;
1607 double inputsa[kTableLength] = {2.0, 3.0, double_nan, 3.0, double_nan};
1608 double inputsb[kTableLength] = {3.0, 2.0, 3.0, double_nan, double_nan};
1609 double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, double_nan};
1610 double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, double_nan};
1611
1612 float inputse[kTableLength] = {2.0, 3.0, float_nan, 3.0, float_nan};
1613 float inputsf[kTableLength] = {3.0, 2.0, 3.0, float_nan, float_nan};
1614 float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, float_nan};
1615 float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, float_nan};
1616
1617 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
1618 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
1619 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e)));
1620 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f)));
1621 __ min_d(f10, f4, f8);
1622 __ max_d(f12, f4, f8);
1623 __ min_s(f14, f2, f6);
1624 __ max_s(f16, f2, f6);
1625 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c)));
1626 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d)));
1627 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g)));
1628 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h)));
1629 __ jr(ra);
1630 __ nop();
1631
1632 CodeDesc desc;
1633 assm.GetCode(&desc);
1634 Handle<Code> code = isolate->factory()->NewCode(
1635 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1636 F3 f = FUNCTION_CAST<F3>(code->entry());
1637 for (int i = 0; i < kTableLength; i++) {
1638 test.a = inputsa[i];
1639 test.b = inputsb[i];
1640 test.e = inputse[i];
1641 test.f = inputsf[i];
1642
1643 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1644
1645 if (i < kTableLength - 1) {
1646 CHECK_EQ(test.c, outputsdmin[i]);
1647 CHECK_EQ(test.d, outputsdmax[i]);
1648 CHECK_EQ(test.g, outputsfmin[i]);
1649 CHECK_EQ(test.h, outputsfmax[i]);
1650 } else {
1651 CHECK(std::isnan(test.c));
1652 CHECK(std::isnan(test.d));
1653 CHECK(std::isnan(test.g));
1654 CHECK(std::isnan(test.h));
1655 }
1656 }
1657 }
1658}
1659
1660
1661TEST(rint_d) {
1662 if (kArchVariant == kMips64r6) {
1663 const int kTableLength = 30;
1664 CcTest::InitializeVM();
1665 Isolate* isolate = CcTest::i_isolate();
1666 HandleScope scope(isolate);
1667 MacroAssembler assm(isolate, NULL, 0,
1668 v8::internal::CodeObjectRequired::kYes);
1669
1670 typedef struct test_float {
1671 double a;
1672 double b;
1673 int fcsr;
1674 }TestFloat;
1675
1676 TestFloat test;
1677 double inputs[kTableLength] = {18446744073709551617.0,
1678 4503599627370496.0, -4503599627370496.0,
1679 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1680 1.7976931348623157E+308, 6.27463370218383111104242366943E-307,
1681 309485009821345068724781056.89,
1682 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1683 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1684 37778931862957161709568.0, 37778931862957161709569.0,
1685 37778931862957161709580.0, 37778931862957161709581.0,
1686 37778931862957161709582.0, 37778931862957161709583.0,
1687 37778931862957161709584.0, 37778931862957161709585.0,
1688 37778931862957161709586.0, 37778931862957161709587.0};
1689 double outputs_RN[kTableLength] = {18446744073709551617.0,
1690 4503599627370496.0, -4503599627370496.0,
1691 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1692 1.7976931348623157E308, 0,
1693 309485009821345068724781057.0,
1694 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
1695 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
1696 37778931862957161709568.0, 37778931862957161709569.0,
1697 37778931862957161709580.0, 37778931862957161709581.0,
1698 37778931862957161709582.0, 37778931862957161709583.0,
1699 37778931862957161709584.0, 37778931862957161709585.0,
1700 37778931862957161709586.0, 37778931862957161709587.0};
1701 double outputs_RZ[kTableLength] = {18446744073709551617.0,
1702 4503599627370496.0, -4503599627370496.0,
1703 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1704 1.7976931348623157E308, 0,
1705 309485009821345068724781057.0,
1706 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1707 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1708 37778931862957161709568.0, 37778931862957161709569.0,
1709 37778931862957161709580.0, 37778931862957161709581.0,
1710 37778931862957161709582.0, 37778931862957161709583.0,
1711 37778931862957161709584.0, 37778931862957161709585.0,
1712 37778931862957161709586.0, 37778931862957161709587.0};
1713 double outputs_RP[kTableLength] = {18446744073709551617.0,
1714 4503599627370496.0, -4503599627370496.0,
1715 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1716 1.7976931348623157E308, 1,
1717 309485009821345068724781057.0,
1718 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
1719 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1720 37778931862957161709568.0, 37778931862957161709569.0,
1721 37778931862957161709580.0, 37778931862957161709581.0,
1722 37778931862957161709582.0, 37778931862957161709583.0,
1723 37778931862957161709584.0, 37778931862957161709585.0,
1724 37778931862957161709586.0, 37778931862957161709587.0};
1725 double outputs_RM[kTableLength] = {18446744073709551617.0,
1726 4503599627370496.0, -4503599627370496.0,
1727 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1728 1.7976931348623157E308, 0,
1729 309485009821345068724781057.0,
1730 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1731 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
1732 37778931862957161709568.0, 37778931862957161709569.0,
1733 37778931862957161709580.0, 37778931862957161709581.0,
1734 37778931862957161709582.0, 37778931862957161709583.0,
1735 37778931862957161709584.0, 37778931862957161709585.0,
1736 37778931862957161709586.0, 37778931862957161709587.0};
1737 int fcsr_inputs[4] =
1738 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
1739 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
1740 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
1741 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) );
1742 __ ctc1(t0, FCSR);
1743 __ rint_d(f8, f4);
1744 __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) );
1745 __ jr(ra);
1746 __ nop();
1747
1748 CodeDesc desc;
1749 assm.GetCode(&desc);
1750 Handle<Code> code = isolate->factory()->NewCode(
1751 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1752 F3 f = FUNCTION_CAST<F3>(code->entry());
1753
1754 for (int j = 0; j < 4; j++) {
1755 test.fcsr = fcsr_inputs[j];
1756 for (int i = 0; i < kTableLength; i++) {
1757 test.a = inputs[i];
1758 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1759 CHECK_EQ(test.b, outputs[j][i]);
1760 }
1761 }
1762 }
1763}
1764
1765
1766TEST(sel) {
1767 if (kArchVariant == kMips64r6) {
1768 CcTest::InitializeVM();
1769 Isolate* isolate = CcTest::i_isolate();
1770 HandleScope scope(isolate);
1771 MacroAssembler assm(isolate, NULL, 0,
1772 v8::internal::CodeObjectRequired::kYes);
1773
1774 typedef struct test {
1775 double dd;
1776 double ds;
1777 double dt;
1778 float fd;
1779 float fs;
1780 float ft;
1781 } Test;
1782
1783 Test test;
1784 __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test
1785 __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1
1786 __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2
1787 __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test
1788 __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1
1789 __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2
1790 __ sel_d(f0, f2, f4);
1791 __ sel_s(f6, f8, f10);
1792 __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) );
1793 __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) );
1794 __ jr(ra);
1795 __ nop();
1796 CodeDesc desc;
1797 assm.GetCode(&desc);
1798 Handle<Code> code = isolate->factory()->NewCode(
1799 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1800 F3 f = FUNCTION_CAST<F3>(code->entry());
1801
1802 const int test_size = 3;
1803 const int input_size = 5;
1804
1805 double inputs_dt[input_size] = {0.0, 65.2, -70.32,
1806 18446744073709551621.0, -18446744073709551621.0};
1807 double inputs_ds[input_size] = {0.1, 69.88, -91.325,
1808 18446744073709551625.0, -18446744073709551625.0};
1809 float inputs_ft[input_size] = {0.0, 65.2, -70.32,
1810 18446744073709551621.0, -18446744073709551621.0};
1811 float inputs_fs[input_size] = {0.1, 69.88, -91.325,
1812 18446744073709551625.0, -18446744073709551625.0};
1813 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9,
1814 18446744073709551616.0, 18446744073709555712.0};
1815 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8,
1816 18446744073709551616.0, 18446746272732807168.0};
1817 for (int j=0; j < test_size; j+=2) {
1818 for (int i=0; i < input_size; i++) {
1819 test.dt = inputs_dt[i];
1820 test.dd = tests_D[j];
1821 test.ds = inputs_ds[i];
1822 test.ft = inputs_ft[i];
1823 test.fd = tests_S[j];
1824 test.fs = inputs_fs[i];
1825 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1826 CHECK_EQ(test.dd, inputs_ds[i]);
1827 CHECK_EQ(test.fd, inputs_fs[i]);
1828
1829 test.dd = tests_D[j+1];
1830 test.fd = tests_S[j+1];
1831 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1832 CHECK_EQ(test.dd, inputs_dt[i]);
1833 CHECK_EQ(test.fd, inputs_ft[i]);
1834 }
1835 }
1836 }
1837}
1838
1839
1840TEST(rint_s) {
1841 if (kArchVariant == kMips64r6) {
1842 const int kTableLength = 30;
1843 CcTest::InitializeVM();
1844 Isolate* isolate = CcTest::i_isolate();
1845 HandleScope scope(isolate);
1846 MacroAssembler assm(isolate, NULL, 0,
1847 v8::internal::CodeObjectRequired::kYes);
1848
1849 typedef struct test_float {
1850 float a;
1851 float b;
1852 int fcsr;
1853 }TestFloat;
1854
1855 TestFloat test;
1856 float inputs[kTableLength] = {18446744073709551617.0,
1857 4503599627370496.0, -4503599627370496.0,
1858 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1859 1.7976931348623157E+38, 6.27463370218383111104242366943E-37,
1860 309485009821345068724781056.89,
1861 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1862 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1863 37778931862957161709568.0, 37778931862957161709569.0,
1864 37778931862957161709580.0, 37778931862957161709581.0,
1865 37778931862957161709582.0, 37778931862957161709583.0,
1866 37778931862957161709584.0, 37778931862957161709585.0,
1867 37778931862957161709586.0, 37778931862957161709587.0};
1868 float outputs_RN[kTableLength] = {18446744073709551617.0,
1869 4503599627370496.0, -4503599627370496.0,
1870 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1871 1.7976931348623157E38, 0,
1872 309485009821345068724781057.0,
1873 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
1874 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
1875 37778931862957161709568.0, 37778931862957161709569.0,
1876 37778931862957161709580.0, 37778931862957161709581.0,
1877 37778931862957161709582.0, 37778931862957161709583.0,
1878 37778931862957161709584.0, 37778931862957161709585.0,
1879 37778931862957161709586.0, 37778931862957161709587.0};
1880 float outputs_RZ[kTableLength] = {18446744073709551617.0,
1881 4503599627370496.0, -4503599627370496.0,
1882 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1883 1.7976931348623157E38, 0,
1884 309485009821345068724781057.0,
1885 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1886 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1887 37778931862957161709568.0, 37778931862957161709569.0,
1888 37778931862957161709580.0, 37778931862957161709581.0,
1889 37778931862957161709582.0, 37778931862957161709583.0,
1890 37778931862957161709584.0, 37778931862957161709585.0,
1891 37778931862957161709586.0, 37778931862957161709587.0};
1892 float outputs_RP[kTableLength] = {18446744073709551617.0,
1893 4503599627370496.0, -4503599627370496.0,
1894 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1895 1.7976931348623157E38, 1,
1896 309485009821345068724781057.0,
1897 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
1898 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1899 37778931862957161709568.0, 37778931862957161709569.0,
1900 37778931862957161709580.0, 37778931862957161709581.0,
1901 37778931862957161709582.0, 37778931862957161709583.0,
1902 37778931862957161709584.0, 37778931862957161709585.0,
1903 37778931862957161709586.0, 37778931862957161709587.0};
1904 float outputs_RM[kTableLength] = {18446744073709551617.0,
1905 4503599627370496.0, -4503599627370496.0,
1906 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1907 1.7976931348623157E38, 0,
1908 309485009821345068724781057.0,
1909 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1910 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
1911 37778931862957161709568.0, 37778931862957161709569.0,
1912 37778931862957161709580.0, 37778931862957161709581.0,
1913 37778931862957161709582.0, 37778931862957161709583.0,
1914 37778931862957161709584.0, 37778931862957161709585.0,
1915 37778931862957161709586.0, 37778931862957161709587.0};
1916 int fcsr_inputs[4] =
1917 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
1918 float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
1919 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
1920 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) );
1921 __ cfc1(t1, FCSR);
1922 __ ctc1(t0, FCSR);
1923 __ rint_s(f8, f4);
1924 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) );
1925 __ ctc1(t1, FCSR);
1926 __ jr(ra);
1927 __ nop();
1928
1929 CodeDesc desc;
1930 assm.GetCode(&desc);
1931 Handle<Code> code = isolate->factory()->NewCode(
1932 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1933 F3 f = FUNCTION_CAST<F3>(code->entry());
1934
1935 for (int j = 0; j < 4; j++) {
1936 test.fcsr = fcsr_inputs[j];
1937 for (int i = 0; i < kTableLength; i++) {
1938 test.a = inputs[i];
1939 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1940 CHECK_EQ(test.b, outputs[j][i]);
1941 }
1942 }
1943 }
1944}
1945
1946
1947TEST(mina_maxa) {
1948 if (kArchVariant == kMips64r6) {
1949 const int kTableLength = 15;
1950 CcTest::InitializeVM();
1951 Isolate* isolate = CcTest::i_isolate();
1952 HandleScope scope(isolate);
1953 MacroAssembler assm(isolate, NULL, 0,
1954 v8::internal::CodeObjectRequired::kYes);
1955 const double double_nan = std::numeric_limits<double>::quiet_NaN();
1956 const float float_nan = std::numeric_limits<float>::quiet_NaN();
1957
1958 typedef struct test_float {
1959 double a;
1960 double b;
1961 double resd;
1962 double resd1;
1963 float c;
1964 float d;
1965 float resf;
1966 float resf1;
1967 }TestFloat;
1968
1969 TestFloat test;
1970 double inputsa[kTableLength] = {
1971 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
1972 -9.8, -10.0, -8.9, -9.8, double_nan, 3.0, double_nan
1973 };
1974 double inputsb[kTableLength] = {
1975 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
1976 9.8, -9.8, -11.2, -9.8, 3.0, double_nan, double_nan
1977 };
1978 double resd[kTableLength] = {
1979 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
1980 -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, double_nan
1981 };
1982 double resd1[kTableLength] = {
1983 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
1984 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, double_nan
1985 };
1986 float inputsc[kTableLength] = {
1987 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
1988 -9.8, -10.0, -8.9, -9.8, float_nan, 3.0, float_nan
1989 };
1990 float inputsd[kTableLength] = {
1991 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
1992 9.8, -9.8, -11.2, -9.8, 3.0, float_nan, float_nan
1993 };
1994 float resf[kTableLength] = {
1995 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
1996 -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, float_nan
1997 };
1998 float resf1[kTableLength] = {
1999 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
2000 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, float_nan
2001 };
2002
2003 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2004 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2005 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2006 __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2007 __ mina_d(f6, f2, f4);
2008 __ mina_s(f12, f8, f10);
2009 __ maxa_d(f14, f2, f4);
2010 __ maxa_s(f16, f8, f10);
2011 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) );
2012 __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) );
2013 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) );
2014 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) );
2015 __ jr(ra);
2016 __ nop();
2017
2018 CodeDesc desc;
2019 assm.GetCode(&desc);
2020 Handle<Code> code = isolate->factory()->NewCode(
2021 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2022 F3 f = FUNCTION_CAST<F3>(code->entry());
2023 for (int i = 0; i < kTableLength; i++) {
2024 test.a = inputsa[i];
2025 test.b = inputsb[i];
2026 test.c = inputsc[i];
2027 test.d = inputsd[i];
2028 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2029
2030 if (i < kTableLength - 1) {
2031 CHECK_EQ(test.resd, resd[i]);
2032 CHECK_EQ(test.resf, resf[i]);
2033 CHECK_EQ(test.resd1, resd1[i]);
2034 CHECK_EQ(test.resf1, resf1[i]);
2035 } else {
2036 CHECK(std::isnan(test.resd));
2037 CHECK(std::isnan(test.resf));
2038 CHECK(std::isnan(test.resd1));
2039 CHECK(std::isnan(test.resf1));
2040 }
2041 }
2042 }
2043}
2044
2045
2046
2047// ----------------------mips64r2 specific tests----------------------
2048TEST(trunc_l) {
2049 if (kArchVariant == kMips64r2) {
2050 CcTest::InitializeVM();
2051 Isolate* isolate = CcTest::i_isolate();
2052 HandleScope scope(isolate);
2053 MacroAssembler assm(isolate, NULL, 0,
2054 v8::internal::CodeObjectRequired::kYes);
2055 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
2056 typedef struct test_float {
2057 uint32_t isNaN2008;
2058 double a;
2059 float b;
2060 int64_t c; // a trunc result
2061 int64_t d; // b trunc result
2062 }Test;
2063 const int kTableLength = 15;
2064 double inputs_D[kTableLength] = {
2065 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2066 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2067 2147483648.0,
2068 std::numeric_limits<double>::quiet_NaN(),
2069 std::numeric_limits<double>::infinity()
2070 };
2071 float inputs_S[kTableLength] = {
2072 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2073 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2074 2147483648.0,
2075 std::numeric_limits<float>::quiet_NaN(),
2076 std::numeric_limits<float>::infinity()
2077 };
2078 double outputs[kTableLength] = {
2079 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2080 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2081 2147483648.0, dFPU64InvalidResult,
2082 dFPU64InvalidResult};
2083 double outputsNaN2008[kTableLength] = {
2084 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2085 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2086 2147483648.0, dFPU64InvalidResult,
2087 dFPU64InvalidResult};
2088
2089 __ cfc1(t1, FCSR);
2090 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2091 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2092 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2093 __ trunc_l_d(f8, f4);
2094 __ trunc_l_s(f10, f6);
2095 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2096 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2097 __ jr(ra);
2098 __ nop();
2099 Test test;
2100 CodeDesc desc;
2101 assm.GetCode(&desc);
2102 Handle<Code> code = isolate->factory()->NewCode(
2103 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2104 F3 f = FUNCTION_CAST<F3>(code->entry());
2105 for (int i = 0; i < kTableLength; i++) {
2106 test.a = inputs_D[i];
2107 test.b = inputs_S[i];
2108 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2109 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2110 kArchVariant == kMips64r6) {
2111 CHECK_EQ(test.c, outputsNaN2008[i]);
2112 } else {
2113 CHECK_EQ(test.c, outputs[i]);
2114 }
2115 CHECK_EQ(test.d, test.c);
2116 }
2117 }
2118}
2119
2120
2121TEST(movz_movn) {
2122 if (kArchVariant == kMips64r2) {
2123 const int kTableLength = 4;
2124 CcTest::InitializeVM();
2125 Isolate* isolate = CcTest::i_isolate();
2126 HandleScope scope(isolate);
2127 MacroAssembler assm(isolate, NULL, 0,
2128 v8::internal::CodeObjectRequired::kYes);
2129
2130 typedef struct test_float {
2131 int64_t rt;
2132 double a;
2133 double b;
2134 double bold;
2135 double b1;
2136 double bold1;
2137 float c;
2138 float d;
2139 float dold;
2140 float d1;
2141 float dold1;
2142 }TestFloat;
2143
2144 TestFloat test;
2145 double inputs_D[kTableLength] = {
2146 5.3, -5.3, 5.3, -2.9
2147 };
2148 double inputs_S[kTableLength] = {
2149 4.8, 4.8, -4.8, -0.29
2150 };
2151
2152 float outputs_S[kTableLength] = {
2153 4.8, 4.8, -4.8, -0.29
2154 };
2155 double outputs_D[kTableLength] = {
2156 5.3, -5.3, 5.3, -2.9
2157 };
2158
2159 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2160 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2161 __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) );
2162 __ Move(f12, 0.0);
2163 __ Move(f10, 0.0);
2164 __ Move(f16, 0.0);
2165 __ Move(f14, 0.0);
2166 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) );
2167 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) );
2168 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) );
2169 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) );
2170 __ movz_s(f10, f6, t0);
2171 __ movz_d(f12, f2, t0);
2172 __ movn_s(f14, f6, t0);
2173 __ movn_d(f16, f2, t0);
2174 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2175 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) );
2176 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) );
2177 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) );
2178 __ jr(ra);
2179 __ nop();
2180
2181 CodeDesc desc;
2182 assm.GetCode(&desc);
2183 Handle<Code> code = isolate->factory()->NewCode(
2184 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2185 F3 f = FUNCTION_CAST<F3>(code->entry());
2186 for (int i = 0; i < kTableLength; i++) {
2187 test.a = inputs_D[i];
2188 test.c = inputs_S[i];
2189
2190 test.rt = 1;
2191 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2192 CHECK_EQ(test.b, test.bold);
2193 CHECK_EQ(test.d, test.dold);
2194 CHECK_EQ(test.b1, outputs_D[i]);
2195 CHECK_EQ(test.d1, outputs_S[i]);
2196
2197 test.rt = 0;
2198 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2199 CHECK_EQ(test.b, outputs_D[i]);
2200 CHECK_EQ(test.d, outputs_S[i]);
2201 CHECK_EQ(test.b1, test.bold1);
2202 CHECK_EQ(test.d1, test.dold1);
2203 }
2204 }
2205}
2206
2207
2208TEST(movt_movd) {
2209 if (kArchVariant == kMips64r2) {
2210 const int kTableLength = 4;
2211 CcTest::InitializeVM();
2212 Isolate* isolate = CcTest::i_isolate();
2213 typedef struct test_float {
2214 double srcd;
2215 double dstd;
2216 double dstdold;
2217 double dstd1;
2218 double dstdold1;
2219 float srcf;
2220 float dstf;
2221 float dstfold;
2222 float dstf1;
2223 float dstfold1;
2224 int32_t cc;
2225 int32_t fcsr;
2226 }TestFloat;
2227
2228 TestFloat test;
2229 double inputs_D[kTableLength] = {
2230 5.3, -5.3, 20.8, -2.9
2231 };
2232 double inputs_S[kTableLength] = {
2233 4.88, 4.8, -4.8, -0.29
2234 };
2235
2236 float outputs_S[kTableLength] = {
2237 4.88, 4.8, -4.8, -0.29
2238 };
2239 double outputs_D[kTableLength] = {
2240 5.3, -5.3, 20.8, -2.9
2241 };
2242 int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7};
2243
2244 for (int i = 0; i < kTableLength; i++) {
2245 test.srcd = inputs_D[i];
2246 test.srcf = inputs_S[i];
2247
2248 for (int j = 0; j< 8; j++) {
2249 test.cc = condition_flags[j];
2250 if (test.cc == 0) {
2251 test.fcsr = 1 << 23;
2252 } else {
2253 test.fcsr = 1 << (24+condition_flags[j]);
2254 }
2255 HandleScope scope(isolate);
2256 MacroAssembler assm(isolate, NULL, 0,
2257 v8::internal::CodeObjectRequired::kYes);
2258 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) );
2259 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) );
2260 __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) );
2261 __ cfc1(t0, FCSR);
2262 __ ctc1(t1, FCSR);
2263 __ li(t2, 0x0);
2264 __ mtc1(t2, f12);
2265 __ mtc1(t2, f10);
2266 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) );
2267 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) );
2268 __ movt_s(f12, f4, test.cc);
2269 __ movt_d(f10, f2, test.cc);
2270 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) );
2271 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) );
2272 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) );
2273 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) );
2274 __ movf_s(f12, f4, test.cc);
2275 __ movf_d(f10, f2, test.cc);
2276 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) );
2277 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) );
2278 __ ctc1(t0, FCSR);
2279 __ jr(ra);
2280 __ nop();
2281
2282 CodeDesc desc;
2283 assm.GetCode(&desc);
2284 Handle<Code> code = isolate->factory()->NewCode(
2285 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2286 F3 f = FUNCTION_CAST<F3>(code->entry());
2287
2288 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2289 CHECK_EQ(test.dstf, outputs_S[i]);
2290 CHECK_EQ(test.dstd, outputs_D[i]);
2291 CHECK_EQ(test.dstf1, test.dstfold1);
2292 CHECK_EQ(test.dstd1, test.dstdold1);
2293 test.fcsr = 0;
2294 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2295 CHECK_EQ(test.dstf, test.dstfold);
2296 CHECK_EQ(test.dstd, test.dstdold);
2297 CHECK_EQ(test.dstf1, outputs_S[i]);
2298 CHECK_EQ(test.dstd1, outputs_D[i]);
2299 }
2300 }
2301 }
2302}
2303
2304
2305
2306// ----------------------tests for all archs--------------------------
2307TEST(cvt_w_d) {
2308 CcTest::InitializeVM();
2309 Isolate* isolate = CcTest::i_isolate();
2310 HandleScope scope(isolate);
2311 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2312
2313 typedef struct test_float {
2314 double a;
2315 int32_t b;
2316 int fcsr;
2317 }Test;
2318 const int kTableLength = 24;
2319 double inputs[kTableLength] = {
2320 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2321 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2322 2147483637.0, 2147483638.0, 2147483639.0,
2323 2147483640.0, 2147483641.0, 2147483642.0,
2324 2147483643.0, 2147483644.0, 2147483645.0,
2325 2147483646.0, 2147483647.0, 2147483653.0
2326 };
2327 double outputs_RN[kTableLength] = {
2328 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2329 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2330 2147483637.0, 2147483638.0, 2147483639.0,
2331 2147483640.0, 2147483641.0, 2147483642.0,
2332 2147483643.0, 2147483644.0, 2147483645.0,
2333 2147483646.0, 2147483647.0, kFPUInvalidResult};
2334 double outputs_RZ[kTableLength] = {
2335 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2336 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2337 2147483637.0, 2147483638.0, 2147483639.0,
2338 2147483640.0, 2147483641.0, 2147483642.0,
2339 2147483643.0, 2147483644.0, 2147483645.0,
2340 2147483646.0, 2147483647.0, kFPUInvalidResult};
2341 double outputs_RP[kTableLength] = {
2342 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
2343 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2344 2147483637.0, 2147483638.0, 2147483639.0,
2345 2147483640.0, 2147483641.0, 2147483642.0,
2346 2147483643.0, 2147483644.0, 2147483645.0,
2347 2147483646.0, 2147483647.0, kFPUInvalidResult};
2348 double outputs_RM[kTableLength] = {
2349 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2350 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2351 2147483637.0, 2147483638.0, 2147483639.0,
2352 2147483640.0, 2147483641.0, 2147483642.0,
2353 2147483643.0, 2147483644.0, 2147483645.0,
2354 2147483646.0, 2147483647.0, kFPUInvalidResult};
2355 int fcsr_inputs[4] =
2356 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
2357 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
2358 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2359 __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) );
2360 __ cfc1(t1, FCSR);
2361 __ ctc1(t0, FCSR);
2362 __ cvt_w_d(f8, f4);
2363 __ swc1(f8, MemOperand(a0, offsetof(Test, b)) );
2364 __ ctc1(t1, FCSR);
2365 __ jr(ra);
2366 __ nop();
2367 Test test;
2368 CodeDesc desc;
2369 assm.GetCode(&desc);
2370 Handle<Code> code = isolate->factory()->NewCode(
2371 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2372 F3 f = FUNCTION_CAST<F3>(code->entry());
2373 for (int j = 0; j < 4; j++) {
2374 test.fcsr = fcsr_inputs[j];
2375 for (int i = 0; i < kTableLength; i++) {
2376 test.a = inputs[i];
2377 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2378 CHECK_EQ(test.b, outputs[j][i]);
2379 }
2380 }
2381}
2382
2383
2384TEST(trunc_w) {
2385 CcTest::InitializeVM();
2386 Isolate* isolate = CcTest::i_isolate();
2387 HandleScope scope(isolate);
2388 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2389
2390 typedef struct test_float {
2391 uint32_t isNaN2008;
2392 double a;
2393 float b;
2394 int32_t c; // a trunc result
2395 int32_t d; // b trunc result
2396 }Test;
2397 const int kTableLength = 15;
2398 double inputs_D[kTableLength] = {
2399 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2400 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2401 2147483648.0,
2402 std::numeric_limits<double>::quiet_NaN(),
2403 std::numeric_limits<double>::infinity()
2404 };
2405 float inputs_S[kTableLength] = {
2406 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2407 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2408 2147483648.0,
2409 std::numeric_limits<float>::quiet_NaN(),
2410 std::numeric_limits<float>::infinity()
2411 };
2412 double outputs[kTableLength] = {
2413 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2414 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2415 kFPUInvalidResult, kFPUInvalidResult,
2416 kFPUInvalidResult};
2417 double outputsNaN2008[kTableLength] = {
2418 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2419 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2420 kFPUInvalidResult,
2421 0,
2422 kFPUInvalidResult};
2423
2424 __ cfc1(t1, FCSR);
2425 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2426 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2427 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2428 __ trunc_w_d(f8, f4);
2429 __ trunc_w_s(f10, f6);
2430 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2431 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2432 __ jr(ra);
2433 __ nop();
2434 Test test;
2435 CodeDesc desc;
2436 assm.GetCode(&desc);
2437 Handle<Code> code = isolate->factory()->NewCode(
2438 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2439 F3 f = FUNCTION_CAST<F3>(code->entry());
2440 for (int i = 0; i < kTableLength; i++) {
2441 test.a = inputs_D[i];
2442 test.b = inputs_S[i];
2443 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2444 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips64r6) {
2445 CHECK_EQ(test.c, outputsNaN2008[i]);
2446 } else {
2447 CHECK_EQ(test.c, outputs[i]);
2448 }
2449 CHECK_EQ(test.d, test.c);
2450 }
2451}
2452
2453
2454TEST(round_w) {
2455 CcTest::InitializeVM();
2456 Isolate* isolate = CcTest::i_isolate();
2457 HandleScope scope(isolate);
2458 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2459
2460 typedef struct test_float {
2461 uint32_t isNaN2008;
2462 double a;
2463 float b;
2464 int32_t c; // a trunc result
2465 int32_t d; // b trunc result
2466 }Test;
2467 const int kTableLength = 15;
2468 double inputs_D[kTableLength] = {
2469 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2470 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2471 2147483648.0,
2472 std::numeric_limits<double>::quiet_NaN(),
2473 std::numeric_limits<double>::infinity()
2474 };
2475 float inputs_S[kTableLength] = {
2476 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2477 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2478 2147483648.0,
2479 std::numeric_limits<float>::quiet_NaN(),
2480 std::numeric_limits<float>::infinity()
2481 };
2482 double outputs[kTableLength] = {
2483 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2484 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2485 kFPUInvalidResult, kFPUInvalidResult,
2486 kFPUInvalidResult};
2487 double outputsNaN2008[kTableLength] = {
2488 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2489 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2490 kFPUInvalidResult, 0,
2491 kFPUInvalidResult};
2492
2493 __ cfc1(t1, FCSR);
2494 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2495 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2496 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2497 __ round_w_d(f8, f4);
2498 __ round_w_s(f10, f6);
2499 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2500 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2501 __ jr(ra);
2502 __ nop();
2503 Test test;
2504 CodeDesc desc;
2505 assm.GetCode(&desc);
2506 Handle<Code> code = isolate->factory()->NewCode(
2507 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2508 F3 f = FUNCTION_CAST<F3>(code->entry());
2509 for (int i = 0; i < kTableLength; i++) {
2510 test.a = inputs_D[i];
2511 test.b = inputs_S[i];
2512 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2513 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips64r6) {
2514 CHECK_EQ(test.c, outputsNaN2008[i]);
2515 } else {
2516 CHECK_EQ(test.c, outputs[i]);
2517 }
2518 CHECK_EQ(test.d, test.c);
2519 }
2520}
2521
2522
2523TEST(round_l) {
2524 CcTest::InitializeVM();
2525 Isolate* isolate = CcTest::i_isolate();
2526 HandleScope scope(isolate);
2527 MacroAssembler assm(isolate, NULL, 0,
2528 v8::internal::CodeObjectRequired::kYes);
2529 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
2530 typedef struct test_float {
2531 uint32_t isNaN2008;
2532 double a;
2533 float b;
2534 int64_t c;
2535 int64_t d;
2536 }Test;
2537 const int kTableLength = 15;
2538 double inputs_D[kTableLength] = {
2539 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2540 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2541 2147483648.0,
2542 std::numeric_limits<double>::quiet_NaN(),
2543 std::numeric_limits<double>::infinity()
2544 };
2545 float inputs_S[kTableLength] = {
2546 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2547 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2548 2147483648.0,
2549 std::numeric_limits<float>::quiet_NaN(),
2550 std::numeric_limits<float>::infinity()
2551 };
2552 double outputs[kTableLength] = {
2553 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2554 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2555 2147483648.0, dFPU64InvalidResult,
2556 dFPU64InvalidResult};
2557 double outputsNaN2008[kTableLength] = {
2558 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2559 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2560 2147483648.0,
2561 0,
2562 dFPU64InvalidResult};
2563
2564 __ cfc1(t1, FCSR);
2565 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2566 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2567 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2568 __ round_l_d(f8, f4);
2569 __ round_l_s(f10, f6);
2570 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2571 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2572 __ jr(ra);
2573 __ nop();
2574 Test test;
2575 CodeDesc desc;
2576 assm.GetCode(&desc);
2577 Handle<Code> code = isolate->factory()->NewCode(
2578 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2579 F3 f = FUNCTION_CAST<F3>(code->entry());
2580 for (int i = 0; i < kTableLength; i++) {
2581 test.a = inputs_D[i];
2582 test.b = inputs_S[i];
2583 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2584 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2585 kArchVariant == kMips64r6) {
2586 CHECK_EQ(test.c, outputsNaN2008[i]);
2587 } else {
2588 CHECK_EQ(test.c, outputs[i]);
2589 }
2590 CHECK_EQ(test.d, test.c);
2591 }
2592}
2593
2594
2595TEST(sub) {
2596 const int kTableLength = 12;
2597 CcTest::InitializeVM();
2598 Isolate* isolate = CcTest::i_isolate();
2599 HandleScope scope(isolate);
2600 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2601
2602 typedef struct test_float {
2603 float a;
2604 float b;
2605 float resultS;
2606 double c;
2607 double d;
2608 double resultD;
2609 }TestFloat;
2610
2611 TestFloat test;
2612 double inputfs_D[kTableLength] = {
2613 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
2614 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
2615 };
2616 double inputft_D[kTableLength] = {
2617 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
2618 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
2619 };
2620 double outputs_D[kTableLength] = {
2621 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
2622 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
2623 };
2624 float inputfs_S[kTableLength] = {
2625 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
2626 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
2627 };
2628 float inputft_S[kTableLength] = {
2629 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
2630 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
2631 };
2632 float outputs_S[kTableLength] = {
2633 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
2634 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
2635 };
2636 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2637 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2638 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2639 __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2640 __ sub_s(f6, f2, f4);
2641 __ sub_d(f12, f8, f10);
2642 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2643 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2644 __ jr(ra);
2645 __ nop();
2646
2647 CodeDesc desc;
2648 assm.GetCode(&desc);
2649 Handle<Code> code = isolate->factory()->NewCode(
2650 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2651 F3 f = FUNCTION_CAST<F3>(code->entry());
2652 for (int i = 0; i < kTableLength; i++) {
2653 test.a = inputfs_S[i];
2654 test.b = inputft_S[i];
2655 test.c = inputfs_D[i];
2656 test.d = inputft_D[i];
2657 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2658 CHECK_EQ(test.resultS, outputs_S[i]);
2659 CHECK_EQ(test.resultD, outputs_D[i]);
2660 }
2661}
2662
2663
2664TEST(sqrt_rsqrt_recip) {
2665 const int kTableLength = 4;
2666 const double deltaDouble = 2E-15;
2667 const float deltaFloat = 2E-7;
2668 const float sqrt2_s = sqrt(2);
2669 const double sqrt2_d = sqrt(2);
2670 CcTest::InitializeVM();
2671 Isolate* isolate = CcTest::i_isolate();
2672 HandleScope scope(isolate);
2673 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2674
2675 typedef struct test_float {
2676 float a;
2677 float resultS;
2678 float resultS1;
2679 float resultS2;
2680 double c;
2681 double resultD;
2682 double resultD1;
2683 double resultD2;
2684 }TestFloat;
2685 TestFloat test;
2686
2687 double inputs_D[kTableLength] = {
2688 0.0L, 4.0L, 2.0L, 4e-28L
2689 };
2690
2691 double outputs_D[kTableLength] = {
2692 0.0L, 2.0L, sqrt2_d, 2e-14L
2693 };
2694 float inputs_S[kTableLength] = {
2695 0.0, 4.0, 2.0, 4e-28
2696 };
2697
2698 float outputs_S[kTableLength] = {
2699 0.0, 2.0, sqrt2_s, 2e-14
2700 };
2701
2702
2703 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2704 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2705 __ sqrt_s(f6, f2);
2706 __ sqrt_d(f12, f8);
2707 __ rsqrt_d(f14, f8);
2708 __ rsqrt_s(f16, f2);
2709 __ recip_d(f18, f8);
2710 __ recip_s(f4, f2);
2711 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2712 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2713 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) );
2714 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) );
2715 __ swc1(f4, MemOperand(a0, offsetof(TestFloat, resultS2)) );
2716 __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) );
2717 __ jr(ra);
2718 __ nop();
2719
2720 CodeDesc desc;
2721 assm.GetCode(&desc);
2722 Handle<Code> code = isolate->factory()->NewCode(
2723 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2724 F3 f = FUNCTION_CAST<F3>(code->entry());
2725
2726 for (int i = 0; i < kTableLength; i++) {
2727 float f1;
2728 double d1;
2729 test.a = inputs_S[i];
2730 test.c = inputs_D[i];
2731
2732 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2733
2734 CHECK_EQ(test.resultS, outputs_S[i]);
2735 CHECK_EQ(test.resultD, outputs_D[i]);
2736
2737 if (i != 0) {
2738 f1 = test.resultS1 - 1.0F/outputs_S[i];
2739 f1 = (f1 < 0) ? f1 : -f1;
2740 CHECK(f1 <= deltaFloat);
2741 d1 = test.resultD1 - 1.0L/outputs_D[i];
2742 d1 = (d1 < 0) ? d1 : -d1;
2743 CHECK(d1 <= deltaDouble);
2744 f1 = test.resultS2 - 1.0F/inputs_S[i];
2745 f1 = (f1 < 0) ? f1 : -f1;
2746 CHECK(f1 <= deltaFloat);
2747 d1 = test.resultD2 - 1.0L/inputs_D[i];
2748 d1 = (d1 < 0) ? d1 : -d1;
2749 CHECK(d1 <= deltaDouble);
2750 } else {
2751 CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]);
2752 CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]);
2753 CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]);
2754 CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]);
2755 }
2756 }
2757}
2758
2759
2760TEST(neg) {
2761 const int kTableLength = 2;
2762 CcTest::InitializeVM();
2763 Isolate* isolate = CcTest::i_isolate();
2764 HandleScope scope(isolate);
2765 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2766
2767 typedef struct test_float {
2768 float a;
2769 float resultS;
2770 double c;
2771 double resultD;
2772 }TestFloat;
2773
2774 TestFloat test;
2775 double inputs_D[kTableLength] = {
2776 4.0, -2.0
2777 };
2778
2779 double outputs_D[kTableLength] = {
2780 -4.0, 2.0
2781 };
2782 float inputs_S[kTableLength] = {
2783 4.0, -2.0
2784 };
2785
2786 float outputs_S[kTableLength] = {
2787 -4.0, 2.0
2788 };
2789 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2790 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2791 __ neg_s(f6, f2);
2792 __ neg_d(f12, f8);
2793 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2794 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2795 __ jr(ra);
2796 __ nop();
2797
2798 CodeDesc desc;
2799 assm.GetCode(&desc);
2800 Handle<Code> code = isolate->factory()->NewCode(
2801 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2802 F3 f = FUNCTION_CAST<F3>(code->entry());
2803 for (int i = 0; i < kTableLength; i++) {
2804 test.a = inputs_S[i];
2805 test.c = inputs_D[i];
2806 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2807 CHECK_EQ(test.resultS, outputs_S[i]);
2808 CHECK_EQ(test.resultD, outputs_D[i]);
2809 }
2810}
2811
2812
2813
2814TEST(mul) {
2815 const int kTableLength = 4;
2816 CcTest::InitializeVM();
2817 Isolate* isolate = CcTest::i_isolate();
2818 HandleScope scope(isolate);
2819 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2820
2821 typedef struct test_float {
2822 float a;
2823 float b;
2824 float resultS;
2825 double c;
2826 double d;
2827 double resultD;
2828 }TestFloat;
2829
2830 TestFloat test;
2831 double inputfs_D[kTableLength] = {
2832 5.3, -5.3, 5.3, -2.9
2833 };
2834 double inputft_D[kTableLength] = {
2835 4.8, 4.8, -4.8, -0.29
2836 };
2837
2838 float inputfs_S[kTableLength] = {
2839 5.3, -5.3, 5.3, -2.9
2840 };
2841 float inputft_S[kTableLength] = {
2842 4.8, 4.8, -4.8, -0.29
2843 };
2844
2845 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2846 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2847 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2848 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) );
2849 __ mul_s(f10, f2, f4);
2850 __ mul_d(f12, f6, f8);
2851 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) );
2852 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2853 __ jr(ra);
2854 __ nop();
2855
2856 CodeDesc desc;
2857 assm.GetCode(&desc);
2858 Handle<Code> code = isolate->factory()->NewCode(
2859 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2860 F3 f = FUNCTION_CAST<F3>(code->entry());
2861 for (int i = 0; i < kTableLength; i++) {
2862 test.a = inputfs_S[i];
2863 test.b = inputft_S[i];
2864 test.c = inputfs_D[i];
2865 test.d = inputft_D[i];
2866 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2867 CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]);
2868 CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]);
2869 }
2870}
2871
2872
2873TEST(mov) {
2874 const int kTableLength = 4;
2875 CcTest::InitializeVM();
2876 Isolate* isolate = CcTest::i_isolate();
2877 HandleScope scope(isolate);
2878 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2879
2880 typedef struct test_float {
2881 double a;
2882 double b;
2883 float c;
2884 float d;
2885 }TestFloat;
2886
2887 TestFloat test;
2888 double inputs_D[kTableLength] = {
2889 5.3, -5.3, 5.3, -2.9
2890 };
2891 double inputs_S[kTableLength] = {
2892 4.8, 4.8, -4.8, -0.29
2893 };
2894
2895 float outputs_S[kTableLength] = {
2896 4.8, 4.8, -4.8, -0.29
2897 };
2898 double outputs_D[kTableLength] = {
2899 5.3, -5.3, 5.3, -2.9
2900 };
2901
2902 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
2903 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2904 __ mov_s(f8, f6);
2905 __ mov_d(f10, f4);
2906 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, d)) );
2907 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, b)) );
2908 __ jr(ra);
2909 __ nop();
2910
2911 CodeDesc desc;
2912 assm.GetCode(&desc);
2913 Handle<Code> code = isolate->factory()->NewCode(
2914 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2915 F3 f = FUNCTION_CAST<F3>(code->entry());
2916 for (int i = 0; i < kTableLength; i++) {
2917 test.a = inputs_D[i];
2918 test.c = inputs_S[i];
2919
2920 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2921 CHECK_EQ(test.b, outputs_D[i]);
2922 CHECK_EQ(test.d, outputs_S[i]);
2923 }
2924}
2925
2926
2927TEST(floor_w) {
2928 CcTest::InitializeVM();
2929 Isolate* isolate = CcTest::i_isolate();
2930 HandleScope scope(isolate);
2931 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2932
2933 typedef struct test_float {
2934 uint32_t isNaN2008;
2935 double a;
2936 float b;
2937 int32_t c; // a floor result
2938 int32_t d; // b floor result
2939 }Test;
2940 const int kTableLength = 15;
2941 double inputs_D[kTableLength] = {
2942 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2943 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2944 2147483648.0,
2945 std::numeric_limits<double>::quiet_NaN(),
2946 std::numeric_limits<double>::infinity()
2947 };
2948 float inputs_S[kTableLength] = {
2949 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2950 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2951 2147483648.0,
2952 std::numeric_limits<float>::quiet_NaN(),
2953 std::numeric_limits<float>::infinity()
2954 };
2955 double outputs[kTableLength] = {
2956 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2957 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2958 kFPUInvalidResult, kFPUInvalidResult,
2959 kFPUInvalidResult};
2960 double outputsNaN2008[kTableLength] = {
2961 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2962 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2963 kFPUInvalidResult,
2964 0,
2965 kFPUInvalidResult};
2966
2967 __ cfc1(t1, FCSR);
2968 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2969 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2970 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2971 __ floor_w_d(f8, f4);
2972 __ floor_w_s(f10, f6);
2973 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2974 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2975 __ jr(ra);
2976 __ nop();
2977 Test test;
2978 CodeDesc desc;
2979 assm.GetCode(&desc);
2980 Handle<Code> code = isolate->factory()->NewCode(
2981 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2982 F3 f = FUNCTION_CAST<F3>(code->entry());
2983 for (int i = 0; i < kTableLength; i++) {
2984 test.a = inputs_D[i];
2985 test.b = inputs_S[i];
2986 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2987 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips64r6) {
2988 CHECK_EQ(test.c, outputsNaN2008[i]);
2989 } else {
2990 CHECK_EQ(test.c, outputs[i]);
2991 }
2992 CHECK_EQ(test.d, test.c);
2993 }
2994}
2995
2996
2997TEST(floor_l) {
2998 CcTest::InitializeVM();
2999 Isolate* isolate = CcTest::i_isolate();
3000 HandleScope scope(isolate);
3001 MacroAssembler assm(isolate, NULL, 0,
3002 v8::internal::CodeObjectRequired::kYes);
3003 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
3004 typedef struct test_float {
3005 uint32_t isNaN2008;
3006 double a;
3007 float b;
3008 int64_t c;
3009 int64_t d;
3010 }Test;
3011 const int kTableLength = 15;
3012 double inputs_D[kTableLength] = {
3013 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3014 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3015 2147483648.0,
3016 std::numeric_limits<double>::quiet_NaN(),
3017 std::numeric_limits<double>::infinity()
3018 };
3019 float inputs_S[kTableLength] = {
3020 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3021 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3022 2147483648.0,
3023 std::numeric_limits<float>::quiet_NaN(),
3024 std::numeric_limits<float>::infinity()
3025 };
3026 double outputs[kTableLength] = {
3027 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
3028 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
3029 2147483648.0, dFPU64InvalidResult,
3030 dFPU64InvalidResult};
3031 double outputsNaN2008[kTableLength] = {
3032 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
3033 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
3034 2147483648.0,
3035 0,
3036 dFPU64InvalidResult};
3037
3038 __ cfc1(t1, FCSR);
3039 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3040 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3041 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3042 __ floor_l_d(f8, f4);
3043 __ floor_l_s(f10, f6);
3044 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
3045 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
3046 __ jr(ra);
3047 __ nop();
3048 Test test;
3049 CodeDesc desc;
3050 assm.GetCode(&desc);
3051 Handle<Code> code = isolate->factory()->NewCode(
3052 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3053 F3 f = FUNCTION_CAST<F3>(code->entry());
3054 for (int i = 0; i < kTableLength; i++) {
3055 test.a = inputs_D[i];
3056 test.b = inputs_S[i];
3057 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3058 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
3059 kArchVariant == kMips64r6) {
3060 CHECK_EQ(test.c, outputsNaN2008[i]);
3061 } else {
3062 CHECK_EQ(test.c, outputs[i]);
3063 }
3064 CHECK_EQ(test.d, test.c);
3065 }
3066}
3067
3068
3069TEST(ceil_w) {
3070 CcTest::InitializeVM();
3071 Isolate* isolate = CcTest::i_isolate();
3072 HandleScope scope(isolate);
3073 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3074
3075 typedef struct test_float {
3076 uint32_t isNaN2008;
3077 double a;
3078 float b;
3079 int32_t c; // a floor result
3080 int32_t d; // b floor result
3081 }Test;
3082 const int kTableLength = 15;
3083 double inputs_D[kTableLength] = {
3084 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3085 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3086 2147483648.0,
3087 std::numeric_limits<double>::quiet_NaN(),
3088 std::numeric_limits<double>::infinity()
3089 };
3090 float inputs_S[kTableLength] = {
3091 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3092 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3093 2147483648.0,
3094 std::numeric_limits<float>::quiet_NaN(),
3095 std::numeric_limits<float>::infinity()
3096 };
3097 double outputs[kTableLength] = {
3098 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3099 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3100 kFPUInvalidResult, kFPUInvalidResult,
3101 kFPUInvalidResult};
3102 double outputsNaN2008[kTableLength] = {
3103 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3104 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3105 kFPUInvalidResult,
3106 0,
3107 kFPUInvalidResult};
3108
3109 __ cfc1(t1, FCSR);
3110 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3111 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3112 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3113 __ ceil_w_d(f8, f4);
3114 __ ceil_w_s(f10, f6);
3115 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
3116 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
3117 __ jr(ra);
3118 __ nop();
3119 Test test;
3120 CodeDesc desc;
3121 assm.GetCode(&desc);
3122 Handle<Code> code = isolate->factory()->NewCode(
3123 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3124 F3 f = FUNCTION_CAST<F3>(code->entry());
3125 for (int i = 0; i < kTableLength; i++) {
3126 test.a = inputs_D[i];
3127 test.b = inputs_S[i];
3128 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3129 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips64r6) {
3130 CHECK_EQ(test.c, outputsNaN2008[i]);
3131 } else {
3132 CHECK_EQ(test.c, outputs[i]);
3133 }
3134 CHECK_EQ(test.d, test.c);
3135 }
3136}
3137
3138
3139TEST(ceil_l) {
3140 CcTest::InitializeVM();
3141 Isolate* isolate = CcTest::i_isolate();
3142 HandleScope scope(isolate);
3143 MacroAssembler assm(isolate, NULL, 0,
3144 v8::internal::CodeObjectRequired::kYes);
3145 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
3146 typedef struct test_float {
3147 uint32_t isNaN2008;
3148 double a;
3149 float b;
3150 int64_t c;
3151 int64_t d;
3152 }Test;
3153 const int kTableLength = 15;
3154 double inputs_D[kTableLength] = {
3155 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3156 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3157 2147483648.0,
3158 std::numeric_limits<double>::quiet_NaN(),
3159 std::numeric_limits<double>::infinity()
3160 };
3161 float inputs_S[kTableLength] = {
3162 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3163 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3164 2147483648.0,
3165 std::numeric_limits<float>::quiet_NaN(),
3166 std::numeric_limits<float>::infinity()
3167 };
3168 double outputs[kTableLength] = {
3169 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3170 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3171 2147483648.0, dFPU64InvalidResult,
3172 dFPU64InvalidResult};
3173 double outputsNaN2008[kTableLength] = {
3174 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3175 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3176 2147483648.0,
3177 0,
3178 dFPU64InvalidResult};
3179
3180 __ cfc1(t1, FCSR);
3181 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3182 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3183 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3184 __ ceil_l_d(f8, f4);
3185 __ ceil_l_s(f10, f6);
3186 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
3187 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
3188 __ jr(ra);
3189 __ nop();
3190 Test test;
3191 CodeDesc desc;
3192 assm.GetCode(&desc);
3193 Handle<Code> code = isolate->factory()->NewCode(
3194 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3195 F3 f = FUNCTION_CAST<F3>(code->entry());
3196 for (int i = 0; i < kTableLength; i++) {
3197 test.a = inputs_D[i];
3198 test.b = inputs_S[i];
3199 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3200 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
3201 kArchVariant == kMips64r6) {
3202 CHECK_EQ(test.c, outputsNaN2008[i]);
3203 } else {
3204 CHECK_EQ(test.c, outputs[i]);
3205 }
3206 CHECK_EQ(test.d, test.c);
3207 }
3208}
3209
3210
3211TEST(jump_tables1) {
3212 // Test jump tables with forward jumps.
3213 CcTest::InitializeVM();
3214 Isolate* isolate = CcTest::i_isolate();
3215 HandleScope scope(isolate);
3216 Assembler assm(isolate, nullptr, 0);
3217
3218 const int kNumCases = 512;
3219 int values[kNumCases];
3220 isolate->random_number_generator()->NextBytes(values, sizeof(values));
3221 Label labels[kNumCases];
3222
3223 __ daddiu(sp, sp, -8);
3224 __ sd(ra, MemOperand(sp));
3225 __ Align(8);
3226
3227 Label done;
3228 {
3229 __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
3230 PredictableCodeSizeScope predictable(
3231 &assm, (kNumCases * 2 + 6) * Assembler::kInstrSize);
3232 Label here;
3233
3234 __ bal(&here);
3235 __ dsll(at, a0, 3); // In delay slot.
3236 __ bind(&here);
3237 __ daddu(at, at, ra);
3238 __ ld(at, MemOperand(at, 4 * Assembler::kInstrSize));
3239 __ jr(at);
3240 __ nop();
3241 for (int i = 0; i < kNumCases; ++i) {
3242 __ dd(&labels[i]);
3243 }
3244 }
3245
3246 for (int i = 0; i < kNumCases; ++i) {
3247 __ bind(&labels[i]);
3248 __ lui(v0, (values[i] >> 16) & 0xffff);
3249 __ ori(v0, v0, values[i] & 0xffff);
3250 __ b(&done);
3251 __ nop();
3252 }
3253
3254 __ bind(&done);
3255 __ ld(ra, MemOperand(sp));
3256 __ daddiu(sp, sp, 8);
3257 __ jr(ra);
3258 __ nop();
3259
3260 CodeDesc desc;
3261 assm.GetCode(&desc);
3262 Handle<Code> code = isolate->factory()->NewCode(
3263 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3264#ifdef OBJECT_PRINT
3265 code->Print(std::cout);
3266#endif
3267 F1 f = FUNCTION_CAST<F1>(code->entry());
3268 for (int i = 0; i < kNumCases; ++i) {
3269 int64_t res = reinterpret_cast<int64_t>(
3270 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
3271 ::printf("f(%d) = %" PRId64 "\n", i, res);
3272 CHECK_EQ(values[i], static_cast<int>(res));
3273 }
3274}
3275
3276
3277TEST(jump_tables2) {
3278 // Test jump tables with backward jumps.
3279 CcTest::InitializeVM();
3280 Isolate* isolate = CcTest::i_isolate();
3281 HandleScope scope(isolate);
3282 Assembler assm(isolate, nullptr, 0);
3283
3284 const int kNumCases = 512;
3285 int values[kNumCases];
3286 isolate->random_number_generator()->NextBytes(values, sizeof(values));
3287 Label labels[kNumCases];
3288
3289 __ daddiu(sp, sp, -8);
3290 __ sd(ra, MemOperand(sp));
3291
3292 Label done, dispatch;
3293 __ b(&dispatch);
3294 __ nop();
3295
3296 for (int i = 0; i < kNumCases; ++i) {
3297 __ bind(&labels[i]);
3298 __ lui(v0, (values[i] >> 16) & 0xffff);
3299 __ ori(v0, v0, values[i] & 0xffff);
3300 __ b(&done);
3301 __ nop();
3302 }
3303
3304 __ Align(8);
3305 __ bind(&dispatch);
3306 {
3307 __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
3308 PredictableCodeSizeScope predictable(
3309 &assm, (kNumCases * 2 + 6) * Assembler::kInstrSize);
3310 Label here;
3311
3312 __ bal(&here);
3313 __ dsll(at, a0, 3); // In delay slot.
3314 __ bind(&here);
3315 __ daddu(at, at, ra);
3316 __ ld(at, MemOperand(at, 4 * Assembler::kInstrSize));
3317 __ jr(at);
3318 __ nop();
3319 for (int i = 0; i < kNumCases; ++i) {
3320 __ dd(&labels[i]);
3321 }
3322 }
3323
3324 __ bind(&done);
3325 __ ld(ra, MemOperand(sp));
3326 __ daddiu(sp, sp, 8);
3327 __ jr(ra);
3328 __ nop();
3329
3330 CodeDesc desc;
3331 assm.GetCode(&desc);
3332 Handle<Code> code = isolate->factory()->NewCode(
3333 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3334#ifdef OBJECT_PRINT
3335 code->Print(std::cout);
3336#endif
3337 F1 f = FUNCTION_CAST<F1>(code->entry());
3338 for (int i = 0; i < kNumCases; ++i) {
3339 int64_t res = reinterpret_cast<int64_t>(
3340 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
3341 ::printf("f(%d) = %" PRId64 "\n", i, res);
3342 CHECK_EQ(values[i], res);
3343 }
3344}
3345
3346
3347TEST(jump_tables3) {
3348 // Test jump tables with backward jumps and embedded heap objects.
3349 CcTest::InitializeVM();
3350 Isolate* isolate = CcTest::i_isolate();
3351 HandleScope scope(isolate);
3352 Assembler assm(isolate, nullptr, 0);
3353
3354 const int kNumCases = 512;
3355 Handle<Object> values[kNumCases];
3356 for (int i = 0; i < kNumCases; ++i) {
3357 double value = isolate->random_number_generator()->NextDouble();
3358 values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED);
3359 }
3360 Label labels[kNumCases];
3361 Object* obj;
3362 int64_t imm64;
3363
3364 __ daddiu(sp, sp, -8);
3365 __ sd(ra, MemOperand(sp));
3366
3367 Label done, dispatch;
3368 __ b(&dispatch);
3369 __ nop();
3370
3371
3372 for (int i = 0; i < kNumCases; ++i) {
3373 __ bind(&labels[i]);
3374 obj = *values[i];
3375 imm64 = reinterpret_cast<intptr_t>(obj);
3376 __ lui(v0, (imm64 >> 32) & kImm16Mask);
3377 __ ori(v0, v0, (imm64 >> 16) & kImm16Mask);
3378 __ dsll(v0, v0, 16);
3379 __ ori(v0, v0, imm64 & kImm16Mask);
3380 __ b(&done);
3381 __ nop();
3382 }
3383
3384 __ Align(8);
3385 __ bind(&dispatch);
3386 {
3387 __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
3388 PredictableCodeSizeScope predictable(
3389 &assm, (kNumCases * 2 + 6) * Assembler::kInstrSize);
3390 Label here;
3391
3392 __ bal(&here);
3393 __ dsll(at, a0, 3); // In delay slot.
3394 __ bind(&here);
3395 __ daddu(at, at, ra);
3396 __ ld(at, MemOperand(at, 4 * Assembler::kInstrSize));
3397 __ jr(at);
3398 __ nop();
3399 for (int i = 0; i < kNumCases; ++i) {
3400 __ dd(&labels[i]);
3401 }
3402 }
3403
3404 __ bind(&done);
3405 __ ld(ra, MemOperand(sp));
3406 __ daddiu(sp, sp, 8);
3407 __ jr(ra);
3408 __ nop();
3409
3410 CodeDesc desc;
3411 assm.GetCode(&desc);
3412 Handle<Code> code = isolate->factory()->NewCode(
3413 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3414#ifdef OBJECT_PRINT
3415 code->Print(std::cout);
3416#endif
3417 F1 f = FUNCTION_CAST<F1>(code->entry());
3418 for (int i = 0; i < kNumCases; ++i) {
3419 Handle<Object> result(
3420 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0), isolate);
3421#ifdef OBJECT_PRINT
3422 ::printf("f(%d) = ", i);
3423 result->Print(std::cout);
3424 ::printf("\n");
3425#endif
3426 CHECK(values[i].is_identical_to(result));
3427 }
3428}
3429
3430
3431TEST(BITSWAP) {
3432 // Test BITSWAP
3433 if (kArchVariant == kMips64r6) {
3434 CcTest::InitializeVM();
3435 Isolate* isolate = CcTest::i_isolate();
3436 HandleScope scope(isolate);
3437
3438 typedef struct {
3439 int64_t r1;
3440 int64_t r2;
3441 int64_t r3;
3442 int64_t r4;
3443 int64_t r5;
3444 int64_t r6;
3445 } T;
3446 T t;
3447
3448 Assembler assm(isolate, NULL, 0);
3449
3450 __ ld(a4, MemOperand(a0, offsetof(T, r1)));
3451 __ nop();
3452 __ bitswap(a6, a4);
3453 __ sd(a6, MemOperand(a0, offsetof(T, r1)));
3454
3455 __ ld(a4, MemOperand(a0, offsetof(T, r2)));
3456 __ nop();
3457 __ bitswap(a6, a4);
3458 __ sd(a6, MemOperand(a0, offsetof(T, r2)));
3459
3460 __ ld(a4, MemOperand(a0, offsetof(T, r3)));
3461 __ nop();
3462 __ bitswap(a6, a4);
3463 __ sd(a6, MemOperand(a0, offsetof(T, r3)));
3464
3465 __ ld(a4, MemOperand(a0, offsetof(T, r4)));
3466 __ nop();
3467 __ bitswap(a6, a4);
3468 __ sd(a6, MemOperand(a0, offsetof(T, r4)));
3469
3470 __ ld(a4, MemOperand(a0, offsetof(T, r5)));
3471 __ nop();
3472 __ dbitswap(a6, a4);
3473 __ sd(a6, MemOperand(a0, offsetof(T, r5)));
3474
3475 __ ld(a4, MemOperand(a0, offsetof(T, r6)));
3476 __ nop();
3477 __ dbitswap(a6, a4);
3478 __ sd(a6, MemOperand(a0, offsetof(T, r6)));
3479
3480 __ jr(ra);
3481 __ nop();
3482
3483 CodeDesc desc;
3484 assm.GetCode(&desc);
3485 Handle<Code> code = isolate->factory()->NewCode(
3486 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3487 F3 f = FUNCTION_CAST<F3>(code->entry());
3488 t.r1 = 0x00102100781A15C3;
3489 t.r2 = 0x001021008B71FCDE;
3490 t.r3 = 0xFF8017FF781A15C3;
3491 t.r4 = 0xFF8017FF8B71FCDE;
3492 t.r5 = 0x10C021098B71FCDE;
3493 t.r6 = 0xFB8017FF781A15C3;
3494 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
3495 USE(dummy);
3496
3497 CHECK_EQ(static_cast<int64_t>(0x000000001E58A8C3L), t.r1);
3498 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD18E3F7BL), t.r2);
3499 CHECK_EQ(static_cast<int64_t>(0x000000001E58A8C3L), t.r3);
3500 CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD18E3F7BL), t.r4);
3501 CHECK_EQ(static_cast<int64_t>(0x08038490D18E3F7BL), t.r5);
3502 CHECK_EQ(static_cast<int64_t>(0xDF01E8FF1E58A8C3L), t.r6);
3503 }
3504}
3505
3506
3507TEST(class_fmt) {
3508 if (kArchVariant == kMips64r6) {
3509 // Test CLASS.fmt instruction.
3510 CcTest::InitializeVM();
3511 Isolate* isolate = CcTest::i_isolate();
3512 HandleScope scope(isolate);
3513
3514 typedef struct {
3515 double dSignalingNan;
3516 double dQuietNan;
3517 double dNegInf;
3518 double dNegNorm;
3519 double dNegSubnorm;
3520 double dNegZero;
3521 double dPosInf;
3522 double dPosNorm;
3523 double dPosSubnorm;
3524 double dPosZero;
3525 float fSignalingNan;
3526 float fQuietNan;
3527 float fNegInf;
3528 float fNegNorm;
3529 float fNegSubnorm;
3530 float fNegZero;
3531 float fPosInf;
3532 float fPosNorm;
3533 float fPosSubnorm;
3534 float fPosZero; } T;
3535 T t;
3536
3537 // Create a function that accepts &t, and loads, manipulates, and stores
3538 // the doubles t.a ... t.f.
3539 MacroAssembler assm(isolate, NULL, 0,
3540 v8::internal::CodeObjectRequired::kYes);
3541
3542 __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan)));
3543 __ class_d(f6, f4);
3544 __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan)));
3545
3546 __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan)));
3547 __ class_d(f6, f4);
3548 __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan)));
3549
3550 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf)));
3551 __ class_d(f6, f4);
3552 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf)));
3553
3554 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm)));
3555 __ class_d(f6, f4);
3556 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm)));
3557
3558 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm)));
3559 __ class_d(f6, f4);
3560 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm)));
3561
3562 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero)));
3563 __ class_d(f6, f4);
3564 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero)));
3565
3566 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf)));
3567 __ class_d(f6, f4);
3568 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf)));
3569
3570 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm)));
3571 __ class_d(f6, f4);
3572 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm)));
3573
3574 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm)));
3575 __ class_d(f6, f4);
3576 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm)));
3577
3578 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero)));
3579 __ class_d(f6, f4);
3580 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero)));
3581
3582 // Testing instruction CLASS.S
3583 __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan)));
3584 __ class_s(f6, f4);
3585 __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan)));
3586
3587 __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan)));
3588 __ class_s(f6, f4);
3589 __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan)));
3590
3591 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf)));
3592 __ class_s(f6, f4);
3593 __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf)));
3594
3595 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm)));
3596 __ class_s(f6, f4);
3597 __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm)));
3598
3599 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm)));
3600 __ class_s(f6, f4);
3601 __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm)));
3602
3603 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero)));
3604 __ class_s(f6, f4);
3605 __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero)));
3606
3607 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf)));
3608 __ class_s(f6, f4);
3609 __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf)));
3610
3611 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm)));
3612 __ class_s(f6, f4);
3613 __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm)));
3614
3615 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm)));
3616 __ class_s(f6, f4);
3617 __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm)));
3618
3619 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero)));
3620 __ class_s(f6, f4);
3621 __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero)));
3622
3623 __ jr(ra);
3624 __ nop();
3625
3626 CodeDesc desc;
3627 assm.GetCode(&desc);
3628 Handle<Code> code = isolate->factory()->NewCode(
3629 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3630 F3 f = FUNCTION_CAST<F3>(code->entry());
3631
3632 // Double test values.
3633 t.dSignalingNan = std::numeric_limits<double>::signaling_NaN();
3634 t.dQuietNan = std::numeric_limits<double>::quiet_NaN();
3635 t.dNegInf = -1.0 / 0.0;
3636 t.dNegNorm = -5.0;
3637 t.dNegSubnorm = -DBL_MIN / 2.0;
3638 t.dNegZero = -0.0;
3639 t.dPosInf = 2.0 / 0.0;
3640 t.dPosNorm = 275.35;
3641 t.dPosSubnorm = DBL_MIN / 2.0;
3642 t.dPosZero = +0.0;
3643 // Float test values
3644
3645 t.fSignalingNan = std::numeric_limits<float>::signaling_NaN();
3646 t.fQuietNan = std::numeric_limits<float>::quiet_NaN();
3647 t.fNegInf = -0.5/0.0;
3648 t.fNegNorm = -FLT_MIN;
3649 t.fNegSubnorm = -FLT_MIN / 1.5;
3650 t.fNegZero = -0.0;
3651 t.fPosInf = 100000.0 / 0.0;
3652 t.fPosNorm = FLT_MAX;
3653 t.fPosSubnorm = FLT_MIN / 20.0;
3654 t.fPosZero = +0.0;
3655
3656 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
3657 USE(dummy);
3658 // Expected double results.
3659 CHECK_EQ(bit_cast<int64_t>(t.dSignalingNan), 0x001);
3660 CHECK_EQ(bit_cast<int64_t>(t.dQuietNan), 0x002);
3661 CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004);
3662 CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008);
3663 CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010);
3664 CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020);
3665 CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040);
3666 CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080);
3667 CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100);
3668 CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200);
3669
3670 // Expected float results.
3671 CHECK_EQ(bit_cast<int32_t>(t.fSignalingNan), 0x001);
3672 CHECK_EQ(bit_cast<int32_t>(t.fQuietNan), 0x002);
3673 CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004);
3674 CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008);
3675 CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010);
3676 CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020);
3677 CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040);
3678 CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080);
3679 CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100);
3680 CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200);
3681 }
3682}
3683
3684
3685TEST(ABS) {
3686 CcTest::InitializeVM();
3687 Isolate* isolate = CcTest::i_isolate();
3688 HandleScope scope(isolate);
3689 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3690
3691 typedef struct test_float {
3692 int64_t fir;
3693 double a;
3694 float b;
3695 double fcsr;
3696 } TestFloat;
3697
3698 TestFloat test;
3699
3700 // Save FIR.
3701 __ cfc1(a1, FCSR);
3702 __ sd(a1, MemOperand(a0, offsetof(TestFloat, fcsr)));
3703 // Disable FPU exceptions.
3704 __ ctc1(zero_reg, FCSR);
3705
3706 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
3707 __ abs_d(f10, f4);
3708 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a)));
3709
3710 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)));
3711 __ abs_s(f10, f4);
3712 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b)));
3713
3714 // Restore FCSR.
3715 __ ctc1(a1, FCSR);
3716
3717 __ jr(ra);
3718 __ nop();
3719
3720 CodeDesc desc;
3721 assm.GetCode(&desc);
3722 Handle<Code> code = isolate->factory()->NewCode(
3723 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3724 F3 f = FUNCTION_CAST<F3>(code->entry());
3725 test.a = -2.0;
3726 test.b = -2.0;
3727 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3728 CHECK_EQ(test.a, 2.0);
3729 CHECK_EQ(test.b, 2.0);
3730
3731 test.a = 2.0;
3732 test.b = 2.0;
3733 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3734 CHECK_EQ(test.a, 2.0);
3735 CHECK_EQ(test.b, 2.0);
3736
3737 // Testing biggest positive number
3738 test.a = std::numeric_limits<double>::max();
3739 test.b = std::numeric_limits<float>::max();
3740 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3741 CHECK_EQ(test.a, std::numeric_limits<double>::max());
3742 CHECK_EQ(test.b, std::numeric_limits<float>::max());
3743
3744 // Testing smallest negative number
3745 test.a = -std::numeric_limits<double>::max(); // lowest()
3746 test.b = -std::numeric_limits<float>::max(); // lowest()
3747 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3748 CHECK_EQ(test.a, std::numeric_limits<double>::max());
3749 CHECK_EQ(test.b, std::numeric_limits<float>::max());
3750
3751 // Testing smallest positive number
3752 test.a = -std::numeric_limits<double>::min();
3753 test.b = -std::numeric_limits<float>::min();
3754 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3755 CHECK_EQ(test.a, std::numeric_limits<double>::min());
3756 CHECK_EQ(test.b, std::numeric_limits<float>::min());
3757
3758 // Testing infinity
3759 test.a = -std::numeric_limits<double>::max()
3760 / std::numeric_limits<double>::min();
3761 test.b = -std::numeric_limits<float>::max()
3762 / std::numeric_limits<float>::min();
3763 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3764 CHECK_EQ(test.a, std::numeric_limits<double>::max()
3765 / std::numeric_limits<double>::min());
3766 CHECK_EQ(test.b, std::numeric_limits<float>::max()
3767 / std::numeric_limits<float>::min());
3768
3769 test.a = std::numeric_limits<double>::quiet_NaN();
3770 test.b = std::numeric_limits<float>::quiet_NaN();
3771 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3772 CHECK_EQ(std::isnan(test.a), true);
3773 CHECK_EQ(std::isnan(test.b), true);
3774
3775 test.a = std::numeric_limits<double>::signaling_NaN();
3776 test.b = std::numeric_limits<float>::signaling_NaN();
3777 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3778 CHECK_EQ(std::isnan(test.a), true);
3779 CHECK_EQ(std::isnan(test.b), true);
3780}
3781
3782
3783TEST(ADD_FMT) {
3784 CcTest::InitializeVM();
3785 Isolate* isolate = CcTest::i_isolate();
3786 HandleScope scope(isolate);
3787 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3788
3789 typedef struct test_float {
3790 double a;
3791 double b;
3792 double c;
3793 float fa;
3794 float fb;
3795 float fc;
3796 } TestFloat;
3797
3798 TestFloat test;
3799
3800 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
3801 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
3802 __ add_d(f10, f8, f4);
3803 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c)));
3804
3805 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa)));
3806 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb)));
3807 __ add_s(f10, f8, f4);
3808 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc)));
3809
3810 __ jr(ra);
3811 __ nop();
3812
3813 CodeDesc desc;
3814 assm.GetCode(&desc);
3815 Handle<Code> code = isolate->factory()->NewCode(
3816 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3817 F3 f = FUNCTION_CAST<F3>(code->entry());
3818 test.a = 2.0;
3819 test.b = 3.0;
3820 test.fa = 2.0;
3821 test.fb = 3.0;
3822 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3823 CHECK_EQ(test.c, 5.0);
3824 CHECK_EQ(test.fc, 5.0);
3825
3826 test.a = std::numeric_limits<double>::max();
3827 test.b = -std::numeric_limits<double>::max(); // lowest()
3828 test.fa = std::numeric_limits<float>::max();
3829 test.fb = -std::numeric_limits<float>::max(); // lowest()
3830 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3831 CHECK_EQ(test.c, 0.0);
3832 CHECK_EQ(test.fc, 0.0);
3833
3834 test.a = std::numeric_limits<double>::max();
3835 test.b = std::numeric_limits<double>::max();
3836 test.fa = std::numeric_limits<float>::max();
3837 test.fb = std::numeric_limits<float>::max();
3838 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3839 CHECK_EQ(std::isfinite(test.c), false);
3840 CHECK_EQ(std::isfinite(test.fc), false);
3841
3842 test.a = 5.0;
3843 test.b = std::numeric_limits<double>::signaling_NaN();
3844 test.fa = 5.0;
3845 test.fb = std::numeric_limits<float>::signaling_NaN();
3846 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3847 CHECK_EQ(std::isnan(test.c), true);
3848 CHECK_EQ(std::isnan(test.fc), true);
3849}
3850
3851
3852TEST(C_COND_FMT) {
3853 if (kArchVariant == kMips64r2) {
3854 CcTest::InitializeVM();
3855 Isolate* isolate = CcTest::i_isolate();
3856 HandleScope scope(isolate);
3857 MacroAssembler assm(isolate, NULL, 0,
3858 v8::internal::CodeObjectRequired::kYes);
3859
3860 typedef struct test_float {
3861 double dOp1;
3862 double dOp2;
3863 uint32_t dF;
3864 uint32_t dUn;
3865 uint32_t dEq;
3866 uint32_t dUeq;
3867 uint32_t dOlt;
3868 uint32_t dUlt;
3869 uint32_t dOle;
3870 uint32_t dUle;
3871 float fOp1;
3872 float fOp2;
3873 uint32_t fF;
3874 uint32_t fUn;
3875 uint32_t fEq;
3876 uint32_t fUeq;
3877 uint32_t fOlt;
3878 uint32_t fUlt;
3879 uint32_t fOle;
3880 uint32_t fUle;
3881 } TestFloat;
3882
3883 TestFloat test;
3884
3885 __ li(t1, 1);
3886
3887 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1)));
3888 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2)));
3889
3890 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1)));
3891 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2)));
3892
3893 __ mov(t2, zero_reg);
3894 __ mov(t3, zero_reg);
3895 __ c_d(F, f4, f6, 0);
3896 __ c_s(F, f14, f16, 2);
3897 __ movt(t2, t1, 0);
3898 __ movt(t3, t1, 2);
3899 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) );
3900 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) );
3901
3902 __ mov(t2, zero_reg);
3903 __ mov(t3, zero_reg);
3904 __ c_d(UN, f4, f6, 2);
3905 __ c_s(UN, f14, f16, 4);
3906 __ movt(t2, t1, 2);
3907 __ movt(t3, t1, 4);
3908 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) );
3909 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) );
3910
3911 __ mov(t2, zero_reg);
3912 __ mov(t3, zero_reg);
3913 __ c_d(EQ, f4, f6, 4);
3914 __ c_s(EQ, f14, f16, 6);
3915 __ movt(t2, t1, 4);
3916 __ movt(t3, t1, 6);
3917 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) );
3918 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) );
3919
3920 __ mov(t2, zero_reg);
3921 __ mov(t3, zero_reg);
3922 __ c_d(UEQ, f4, f6, 6);
3923 __ c_s(UEQ, f14, f16, 0);
3924 __ movt(t2, t1, 6);
3925 __ movt(t3, t1, 0);
3926 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) );
3927 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) );
3928
3929 __ mov(t2, zero_reg);
3930 __ mov(t3, zero_reg);
3931 __ c_d(OLT, f4, f6, 0);
3932 __ c_s(OLT, f14, f16, 2);
3933 __ movt(t2, t1, 0);
3934 __ movt(t3, t1, 2);
3935 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) );
3936 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) );
3937
3938 __ mov(t2, zero_reg);
3939 __ mov(t3, zero_reg);
3940 __ c_d(ULT, f4, f6, 2);
3941 __ c_s(ULT, f14, f16, 4);
3942 __ movt(t2, t1, 2);
3943 __ movt(t3, t1, 4);
3944 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) );
3945 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) );
3946
3947 __ mov(t2, zero_reg);
3948 __ mov(t3, zero_reg);
3949 __ c_d(OLE, f4, f6, 4);
3950 __ c_s(OLE, f14, f16, 6);
3951 __ movt(t2, t1, 4);
3952 __ movt(t3, t1, 6);
3953 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) );
3954 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) );
3955
3956 __ mov(t2, zero_reg);
3957 __ mov(t3, zero_reg);
3958 __ c_d(ULE, f4, f6, 6);
3959 __ c_s(ULE, f14, f16, 0);
3960 __ movt(t2, t1, 6);
3961 __ movt(t3, t1, 0);
3962 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) );
3963 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) );
3964
3965 __ jr(ra);
3966 __ nop();
3967
3968 CodeDesc desc;
3969 assm.GetCode(&desc);
3970 Handle<Code> code = isolate->factory()->NewCode(
3971 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3972 F3 f = FUNCTION_CAST<F3>(code->entry());
3973 test.dOp1 = 2.0;
3974 test.dOp2 = 3.0;
3975 test.fOp1 = 2.0;
3976 test.fOp2 = 3.0;
3977 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3978 CHECK_EQ(test.dF, 0U);
3979 CHECK_EQ(test.dUn, 0U);
3980 CHECK_EQ(test.dEq, 0U);
3981 CHECK_EQ(test.dUeq, 0U);
3982 CHECK_EQ(test.dOlt, 1U);
3983 CHECK_EQ(test.dUlt, 1U);
3984 CHECK_EQ(test.dOle, 1U);
3985 CHECK_EQ(test.dUle, 1U);
3986 CHECK_EQ(test.fF, 0U);
3987 CHECK_EQ(test.fUn, 0U);
3988 CHECK_EQ(test.fEq, 0U);
3989 CHECK_EQ(test.fUeq, 0U);
3990 CHECK_EQ(test.fOlt, 1U);
3991 CHECK_EQ(test.fUlt, 1U);
3992 CHECK_EQ(test.fOle, 1U);
3993 CHECK_EQ(test.fUle, 1U);
3994
3995 test.dOp1 = std::numeric_limits<double>::max();
3996 test.dOp2 = std::numeric_limits<double>::min();
3997 test.fOp1 = std::numeric_limits<float>::min();
3998 test.fOp2 = -std::numeric_limits<float>::max(); // lowest()
3999 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4000 CHECK_EQ(test.dF, 0U);
4001 CHECK_EQ(test.dUn, 0U);
4002 CHECK_EQ(test.dEq, 0U);
4003 CHECK_EQ(test.dUeq, 0U);
4004 CHECK_EQ(test.dOlt, 0U);
4005 CHECK_EQ(test.dUlt, 0U);
4006 CHECK_EQ(test.dOle, 0U);
4007 CHECK_EQ(test.dUle, 0U);
4008 CHECK_EQ(test.fF, 0U);
4009 CHECK_EQ(test.fUn, 0U);
4010 CHECK_EQ(test.fEq, 0U);
4011 CHECK_EQ(test.fUeq, 0U);
4012 CHECK_EQ(test.fOlt, 0U);
4013 CHECK_EQ(test.fUlt, 0U);
4014 CHECK_EQ(test.fOle, 0U);
4015 CHECK_EQ(test.fUle, 0U);
4016
4017 test.dOp1 = -std::numeric_limits<double>::max(); // lowest()
4018 test.dOp2 = -std::numeric_limits<double>::max(); // lowest()
4019 test.fOp1 = std::numeric_limits<float>::max();
4020 test.fOp2 = std::numeric_limits<float>::max();
4021 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4022 CHECK_EQ(test.dF, 0U);
4023 CHECK_EQ(test.dUn, 0U);
4024 CHECK_EQ(test.dEq, 1U);
4025 CHECK_EQ(test.dUeq, 1U);
4026 CHECK_EQ(test.dOlt, 0U);
4027 CHECK_EQ(test.dUlt, 0U);
4028 CHECK_EQ(test.dOle, 1U);
4029 CHECK_EQ(test.dUle, 1U);
4030 CHECK_EQ(test.fF, 0U);
4031 CHECK_EQ(test.fUn, 0U);
4032 CHECK_EQ(test.fEq, 1U);
4033 CHECK_EQ(test.fUeq, 1U);
4034 CHECK_EQ(test.fOlt, 0U);
4035 CHECK_EQ(test.fUlt, 0U);
4036 CHECK_EQ(test.fOle, 1U);
4037 CHECK_EQ(test.fUle, 1U);
4038
4039 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4040 test.dOp2 = 0.0;
4041 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4042 test.fOp2 = 0.0;
4043 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4044 CHECK_EQ(test.dF, 0U);
4045 CHECK_EQ(test.dUn, 1U);
4046 CHECK_EQ(test.dEq, 0U);
4047 CHECK_EQ(test.dUeq, 1U);
4048 CHECK_EQ(test.dOlt, 0U);
4049 CHECK_EQ(test.dUlt, 1U);
4050 CHECK_EQ(test.dOle, 0U);
4051 CHECK_EQ(test.dUle, 1U);
4052 CHECK_EQ(test.fF, 0U);
4053 CHECK_EQ(test.fUn, 1U);
4054 CHECK_EQ(test.fEq, 0U);
4055 CHECK_EQ(test.fUeq, 1U);
4056 CHECK_EQ(test.fOlt, 0U);
4057 CHECK_EQ(test.fUlt, 1U);
4058 CHECK_EQ(test.fOle, 0U);
4059 CHECK_EQ(test.fUle, 1U);
4060 }
4061}
4062
4063
4064TEST(CMP_COND_FMT) {
4065 if (kArchVariant == kMips64r6) {
4066 CcTest::InitializeVM();
4067 Isolate* isolate = CcTest::i_isolate();
4068 HandleScope scope(isolate);
4069 MacroAssembler assm(isolate, NULL, 0,
4070 v8::internal::CodeObjectRequired::kYes);
4071
4072 typedef struct test_float {
4073 double dOp1;
4074 double dOp2;
4075 double dF;
4076 double dUn;
4077 double dEq;
4078 double dUeq;
4079 double dOlt;
4080 double dUlt;
4081 double dOle;
4082 double dUle;
4083 double dOr;
4084 double dUne;
4085 double dNe;
4086 float fOp1;
4087 float fOp2;
4088 float fF;
4089 float fUn;
4090 float fEq;
4091 float fUeq;
4092 float fOlt;
4093 float fUlt;
4094 float fOle;
4095 float fUle;
4096 float fOr;
4097 float fUne;
4098 float fNe;
4099 } TestFloat;
4100
4101 TestFloat test;
4102
4103 __ li(t1, 1);
4104
4105 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1)));
4106 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2)));
4107
4108 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1)));
4109 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2)));
4110
4111 __ cmp_d(F, f2, f4, f6);
4112 __ cmp_s(F, f12, f14, f16);
4113 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) );
4114 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) );
4115
4116 __ cmp_d(UN, f2, f4, f6);
4117 __ cmp_s(UN, f12, f14, f16);
4118 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) );
4119 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) );
4120
4121 __ cmp_d(EQ, f2, f4, f6);
4122 __ cmp_s(EQ, f12, f14, f16);
4123 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) );
4124 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) );
4125
4126 __ cmp_d(UEQ, f2, f4, f6);
4127 __ cmp_s(UEQ, f12, f14, f16);
4128 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) );
4129 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) );
4130
4131 __ cmp_d(LT, f2, f4, f6);
4132 __ cmp_s(LT, f12, f14, f16);
4133 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) );
4134 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) );
4135
4136 __ cmp_d(ULT, f2, f4, f6);
4137 __ cmp_s(ULT, f12, f14, f16);
4138 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) );
4139 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) );
4140
4141 __ cmp_d(LE, f2, f4, f6);
4142 __ cmp_s(LE, f12, f14, f16);
4143 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) );
4144 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) );
4145
4146 __ cmp_d(ULE, f2, f4, f6);
4147 __ cmp_s(ULE, f12, f14, f16);
4148 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) );
4149 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) );
4150
4151 __ cmp_d(ORD, f2, f4, f6);
4152 __ cmp_s(ORD, f12, f14, f16);
4153 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) );
4154 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) );
4155
4156 __ cmp_d(UNE, f2, f4, f6);
4157 __ cmp_s(UNE, f12, f14, f16);
4158 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) );
4159 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) );
4160
4161 __ cmp_d(NE, f2, f4, f6);
4162 __ cmp_s(NE, f12, f14, f16);
4163 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) );
4164 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) );
4165
4166 __ jr(ra);
4167 __ nop();
4168
4169 CodeDesc desc;
4170 assm.GetCode(&desc);
4171 Handle<Code> code = isolate->factory()->NewCode(
4172 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4173 F3 f = FUNCTION_CAST<F3>(code->entry());
4174 uint64_t dTrue = 0xFFFFFFFFFFFFFFFF;
4175 uint64_t dFalse = 0x0000000000000000;
4176 uint32_t fTrue = 0xFFFFFFFF;
4177 uint32_t fFalse = 0x00000000;
4178
4179 test.dOp1 = 2.0;
4180 test.dOp2 = 3.0;
4181 test.fOp1 = 2.0;
4182 test.fOp2 = 3.0;
4183 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4184 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4185 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4186 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4187 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
4188 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue);
4189 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
4190 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
4191 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4192 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4193 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4194 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
4195 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4196 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4197 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4198 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
4199 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue);
4200 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
4201 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
4202 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4203
4204 test.dOp1 = std::numeric_limits<double>::max();
4205 test.dOp2 = std::numeric_limits<double>::min();
4206 test.fOp1 = std::numeric_limits<float>::min();
4207 test.fOp2 = -std::numeric_limits<float>::max(); // lowest()
4208 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4209 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4210 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4211 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4212 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
4213 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4214 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
4215 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
4216 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse);
4217 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4218 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4219 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
4220 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4221 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4222 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4223 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
4224 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4225 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
4226 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
4227 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse);
4228
4229 test.dOp1 = -std::numeric_limits<double>::max(); // lowest()
4230 test.dOp2 = -std::numeric_limits<double>::max(); // lowest()
4231 test.fOp1 = std::numeric_limits<float>::max();
4232 test.fOp2 = std::numeric_limits<float>::max();
4233 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4234 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4235 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4236 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue);
4237 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
4238 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4239 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
4240 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
4241 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4242 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4243 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse);
4244 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
4245 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4246 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4247 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue);
4248 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
4249 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4250 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
4251 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
4252 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4253
4254 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4255 test.dOp2 = 0.0;
4256 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4257 test.fOp2 = 0.0;
4258 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4259 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4260 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue);
4261 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4262 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
4263 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4264 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
4265 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
4266 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4267 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse);
4268 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4269 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
4270 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4271 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue);
4272 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4273 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
4274 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4275 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
4276 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
4277 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4278 }
4279}
4280
4281
4282TEST(CVT) {
4283 CcTest::InitializeVM();
4284 Isolate* isolate = CcTest::i_isolate();
4285 HandleScope scope(isolate);
4286 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4287
4288 typedef struct test_float {
4289 float cvt_d_s_in;
4290 double cvt_d_s_out;
4291 int32_t cvt_d_w_in;
4292 double cvt_d_w_out;
4293 int64_t cvt_d_l_in;
4294 double cvt_d_l_out;
4295
4296 float cvt_l_s_in;
4297 int64_t cvt_l_s_out;
4298 double cvt_l_d_in;
4299 int64_t cvt_l_d_out;
4300
4301 double cvt_s_d_in;
4302 float cvt_s_d_out;
4303 int32_t cvt_s_w_in;
4304 float cvt_s_w_out;
4305 int64_t cvt_s_l_in;
4306 float cvt_s_l_out;
4307
4308 float cvt_w_s_in;
4309 int32_t cvt_w_s_out;
4310 double cvt_w_d_in;
4311 int32_t cvt_w_d_out;
4312 } TestFloat;
4313
4314 TestFloat test;
4315
4316 // Save FCSR.
4317 __ cfc1(a1, FCSR);
4318 // Disable FPU exceptions.
4319 __ ctc1(zero_reg, FCSR);
4320
4321#define GENERATE_CVT_TEST(x, y, z) \
4322 __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \
4323 __ x(f0, f0); \
4324 __ nop(); \
4325 __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out)));
4326
4327 GENERATE_CVT_TEST(cvt_d_s, lw, sd)
4328 GENERATE_CVT_TEST(cvt_d_w, lw, sd)
4329 GENERATE_CVT_TEST(cvt_d_l, ld, sd)
4330
4331 GENERATE_CVT_TEST(cvt_l_s, lw, sd)
4332 GENERATE_CVT_TEST(cvt_l_d, ld, sd)
4333
4334 GENERATE_CVT_TEST(cvt_s_d, ld, sw)
4335 GENERATE_CVT_TEST(cvt_s_w, lw, sw)
4336 GENERATE_CVT_TEST(cvt_s_l, ld, sw)
4337
4338 GENERATE_CVT_TEST(cvt_w_s, lw, sw)
4339 GENERATE_CVT_TEST(cvt_w_d, ld, sw)
4340
4341 // Restore FCSR.
4342 __ ctc1(a1, FCSR);
4343
4344 __ jr(ra);
4345 __ nop();
4346
4347 CodeDesc desc;
4348 assm.GetCode(&desc);
4349 Handle<Code> code = isolate->factory()->NewCode(
4350 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4351 F3 f = FUNCTION_CAST<F3>(code->entry());
4352
4353 test.cvt_d_s_in = -0.51;
4354 test.cvt_d_w_in = -1;
4355 test.cvt_d_l_in = -1;
4356 test.cvt_l_s_in = -0.51;
4357 test.cvt_l_d_in = -0.51;
4358 test.cvt_s_d_in = -0.51;
4359 test.cvt_s_w_in = -1;
4360 test.cvt_s_l_in = -1;
4361 test.cvt_w_s_in = -0.51;
4362 test.cvt_w_d_in = -0.51;
4363
4364 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4365 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4366 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4367 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4368 CHECK_EQ(test.cvt_l_s_out, -1);
4369 CHECK_EQ(test.cvt_l_d_out, -1);
4370 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4371 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4372 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4373 CHECK_EQ(test.cvt_w_s_out, -1);
4374 CHECK_EQ(test.cvt_w_d_out, -1);
4375
4376
4377 test.cvt_d_s_in = 0.49;
4378 test.cvt_d_w_in = 1;
4379 test.cvt_d_l_in = 1;
4380 test.cvt_l_s_in = 0.49;
4381 test.cvt_l_d_in = 0.49;
4382 test.cvt_s_d_in = 0.49;
4383 test.cvt_s_w_in = 1;
4384 test.cvt_s_l_in = 1;
4385 test.cvt_w_s_in = 0.49;
4386 test.cvt_w_d_in = 0.49;
4387
4388 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4389 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4390 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4391 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4392 CHECK_EQ(test.cvt_l_s_out, 0);
4393 CHECK_EQ(test.cvt_l_d_out, 0);
4394 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4395 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4396 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4397 CHECK_EQ(test.cvt_w_s_out, 0);
4398 CHECK_EQ(test.cvt_w_d_out, 0);
4399
4400 test.cvt_d_s_in = std::numeric_limits<float>::max();
4401 test.cvt_d_w_in = std::numeric_limits<int32_t>::max();
4402 test.cvt_d_l_in = std::numeric_limits<int64_t>::max();
4403 test.cvt_l_s_in = std::numeric_limits<float>::max();
4404 test.cvt_l_d_in = std::numeric_limits<double>::max();
4405 test.cvt_s_d_in = std::numeric_limits<double>::max();
4406 test.cvt_s_w_in = std::numeric_limits<int32_t>::max();
4407 test.cvt_s_l_in = std::numeric_limits<int64_t>::max();
4408 test.cvt_w_s_in = std::numeric_limits<float>::max();
4409 test.cvt_w_d_in = std::numeric_limits<double>::max();
4410
4411 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4412 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4413 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4414 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4415 CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max());
4416 CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max());
4417 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4418 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4419 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4420 CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max());
4421 CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max());
4422
4423
4424 test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest()
4425 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest()
4426 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest()
4427 test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest()
4428 test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest()
4429 test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest()
4430 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest()
4431 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest()
4432 test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest()
4433 test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest()
4434
4435 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4436 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4437 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4438 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4439 // The returned value when converting from fixed-point to float-point
4440 // is not consistent between board, simulator and specification
4441 // in this test case, therefore modifying the test
4442 CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() ||
4443 test.cvt_l_s_out == std::numeric_limits<int64_t>::max());
4444 CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() ||
4445 test.cvt_l_d_out == std::numeric_limits<int64_t>::max());
4446 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4447 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4448 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4449 CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() ||
4450 test.cvt_w_s_out == std::numeric_limits<int32_t>::max());
4451 CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() ||
4452 test.cvt_w_d_out == std::numeric_limits<int32_t>::max());
4453
4454
4455 test.cvt_d_s_in = std::numeric_limits<float>::min();
4456 test.cvt_d_w_in = std::numeric_limits<int32_t>::min();
4457 test.cvt_d_l_in = std::numeric_limits<int64_t>::min();
4458 test.cvt_l_s_in = std::numeric_limits<float>::min();
4459 test.cvt_l_d_in = std::numeric_limits<double>::min();
4460 test.cvt_s_d_in = std::numeric_limits<double>::min();
4461 test.cvt_s_w_in = std::numeric_limits<int32_t>::min();
4462 test.cvt_s_l_in = std::numeric_limits<int64_t>::min();
4463 test.cvt_w_s_in = std::numeric_limits<float>::min();
4464 test.cvt_w_d_in = std::numeric_limits<double>::min();
4465
4466 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4467 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4468 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4469 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4470 CHECK_EQ(test.cvt_l_s_out, 0);
4471 CHECK_EQ(test.cvt_l_d_out, 0);
4472 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4473 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4474 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4475 CHECK_EQ(test.cvt_w_s_out, 0);
4476 CHECK_EQ(test.cvt_w_d_out, 0);
4477}
4478
4479
4480TEST(DIV_FMT) {
4481 CcTest::InitializeVM();
4482 Isolate* isolate = CcTest::i_isolate();
4483 HandleScope scope(isolate);
4484 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4485
4486 typedef struct test {
4487 double dOp1;
4488 double dOp2;
4489 double dRes;
4490 float fOp1;
4491 float fOp2;
4492 float fRes;
4493 } Test;
4494
4495 Test test;
4496
4497 // Save FCSR.
4498 __ cfc1(a1, FCSR);
4499 // Disable FPU exceptions.
4500 __ ctc1(zero_reg, FCSR);
4501
4502 __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) );
4503 __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) );
4504 __ nop();
4505 __ div_d(f6, f4, f2);
4506 __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) );
4507
4508 __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) );
4509 __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) );
4510 __ nop();
4511 __ div_s(f6, f4, f2);
4512 __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) );
4513
4514 // Restore FCSR.
4515 __ ctc1(a1, FCSR);
4516
4517 __ jr(ra);
4518 __ nop();
4519 CodeDesc desc;
4520 assm.GetCode(&desc);
4521 Handle<Code> code = isolate->factory()->NewCode(
4522 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4523 F3 f = FUNCTION_CAST<F3>(code->entry());
4524
4525 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4526
4527 const int test_size = 3;
4528
4529 double dOp1[test_size] = {
4530 5.0,
4531 DBL_MAX,
4532 DBL_MAX,
4533 };
4534 double dOp2[test_size] = {
4535 2.0,
4536 2.0,
4537 -DBL_MAX,
4538 };
4539 double dRes[test_size] = {
4540 2.5,
4541 DBL_MAX / 2.0,
4542 -1.0,
4543 };
4544 float fOp1[test_size] = {
4545 5.0,
4546 FLT_MAX,
4547 FLT_MAX,
4548 };
4549 float fOp2[test_size] = {
4550 2.0,
4551 2.0,
4552 -FLT_MAX,
4553 };
4554 float fRes[test_size] = {
4555 2.5,
4556 FLT_MAX / 2.0,
4557 -1.0,
4558 };
4559
4560 for (int i = 0; i < test_size; i++) {
4561 test.dOp1 = dOp1[i];
4562 test.dOp2 = dOp2[i];
4563 test.fOp1 = fOp1[i];
4564 test.fOp2 = fOp2[i];
4565
4566 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4567 CHECK_EQ(test.dRes, dRes[i]);
4568 CHECK_EQ(test.fRes, fRes[i]);
4569 }
4570
4571 test.dOp1 = DBL_MAX;
4572 test.dOp2 = -0.0;
4573 test.fOp1 = FLT_MAX;
4574 test.fOp2 = -0.0;
4575
4576 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4577 CHECK_EQ(false, std::isfinite(test.dRes));
4578 CHECK_EQ(false, std::isfinite(test.fRes));
4579
4580 test.dOp1 = 0.0;
4581 test.dOp2 = -0.0;
4582 test.fOp1 = 0.0;
4583 test.fOp2 = -0.0;
4584
4585 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4586 CHECK_EQ(true, std::isnan(test.dRes));
4587 CHECK_EQ(true, std::isnan(test.fRes));
4588
4589 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4590 test.dOp2 = -5.0;
4591 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4592 test.fOp2 = -5.0;
4593
4594 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4595 CHECK_EQ(true, std::isnan(test.dRes));
4596 CHECK_EQ(true, std::isnan(test.fRes));
4597}
4598
4599
4600uint64_t run_align(uint64_t rs_value, uint64_t rt_value, uint8_t bp) {
4601 Isolate* isolate = CcTest::i_isolate();
4602 HandleScope scope(isolate);
4603
4604 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4605
4606 __ align(v0, a0, a1, bp);
4607 __ jr(ra);
4608 __ nop();
4609
4610 CodeDesc desc;
4611 assm.GetCode(&desc);
4612 Handle<Code> code = isolate->factory()->NewCode(
4613 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4614
4615 F4 f = FUNCTION_CAST<F4>(code->entry());
4616
4617 uint64_t res = reinterpret_cast<uint64_t>(
4618 CALL_GENERATED_CODE(isolate, f, rs_value, rt_value, 0, 0, 0));
4619
4620 return res;
4621}
4622
4623
4624TEST(r6_align) {
4625 if (kArchVariant == kMips64r6) {
4626 CcTest::InitializeVM();
4627
4628 struct TestCaseAlign {
4629 uint64_t rs_value;
4630 uint64_t rt_value;
4631 uint8_t bp;
4632 uint64_t expected_res;
4633 };
4634
4635 struct TestCaseAlign tc[] = {
4636 // rs_value, rt_value, bp, expected_res
4637 { 0x11223344, 0xaabbccdd, 0, 0xffffffffaabbccdd },
4638 { 0x11223344, 0xaabbccdd, 1, 0xffffffffbbccdd11 },
4639 { 0x11223344, 0xaabbccdd, 2, 0xffffffffccdd1122 },
4640 { 0x11223344, 0xaabbccdd, 3, 0xffffffffdd112233 },
4641 };
4642
4643 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign);
4644 for (size_t i = 0; i < nr_test_cases; ++i) {
4645 CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value,
4646 tc[i].rt_value,
4647 tc[i].bp));
4648 }
4649 }
4650}
4651
4652
4653uint64_t run_dalign(uint64_t rs_value, uint64_t rt_value, uint8_t bp) {
4654 Isolate* isolate = CcTest::i_isolate();
4655 HandleScope scope(isolate);
4656
4657 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4658
4659 __ dalign(v0, a0, a1, bp);
4660 __ jr(ra);
4661 __ nop();
4662
4663 CodeDesc desc;
4664 assm.GetCode(&desc);
4665 Handle<Code> code = isolate->factory()->NewCode(
4666 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4667
4668 F4 f = FUNCTION_CAST<F4>(code->entry());
4669 uint64_t res = reinterpret_cast<uint64_t>(
4670 CALL_GENERATED_CODE(isolate, f, rs_value, rt_value, 0, 0, 0));
4671
4672 return res;
4673}
4674
4675
4676TEST(r6_dalign) {
4677 if (kArchVariant == kMips64r6) {
4678 CcTest::InitializeVM();
4679
4680 struct TestCaseDalign {
4681 uint64_t rs_value;
4682 uint64_t rt_value;
4683 uint8_t bp;
4684 uint64_t expected_res;
4685 };
4686
4687 struct TestCaseDalign tc[] = {
4688 // rs_value, rt_value, bp, expected_res
4689 { 0x1122334455667700, 0xaabbccddeeff8899, 0, 0xaabbccddeeff8899 },
4690 { 0x1122334455667700, 0xaabbccddeeff8899, 1, 0xbbccddeeff889911 },
4691 { 0x1122334455667700, 0xaabbccddeeff8899, 2, 0xccddeeff88991122 },
4692 { 0x1122334455667700, 0xaabbccddeeff8899, 3, 0xddeeff8899112233 },
4693 { 0x1122334455667700, 0xaabbccddeeff8899, 4, 0xeeff889911223344 },
4694 { 0x1122334455667700, 0xaabbccddeeff8899, 5, 0xff88991122334455 },
4695 { 0x1122334455667700, 0xaabbccddeeff8899, 6, 0x8899112233445566 },
4696 { 0x1122334455667700, 0xaabbccddeeff8899, 7, 0x9911223344556677 }
4697 };
4698
4699 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDalign);
4700 for (size_t i = 0; i < nr_test_cases; ++i) {
4701 CHECK_EQ(tc[i].expected_res, run_dalign(tc[i].rs_value,
4702 tc[i].rt_value,
4703 tc[i].bp));
4704 }
4705 }
4706}
4707
4708
4709uint64_t PC; // The program counter.
4710
4711uint64_t run_aluipc(int16_t offset) {
4712 Isolate* isolate = CcTest::i_isolate();
4713 HandleScope scope(isolate);
4714
4715 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4716
4717 __ aluipc(v0, offset);
4718 __ jr(ra);
4719 __ nop();
4720
4721 CodeDesc desc;
4722 assm.GetCode(&desc);
4723 Handle<Code> code = isolate->factory()->NewCode(
4724 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4725
4726 F2 f = FUNCTION_CAST<F2>(code->entry());
4727 PC = (uint64_t) f; // Set the program counter.
4728
4729 uint64_t res = reinterpret_cast<uint64_t>(
4730 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4731
4732 return res;
4733}
4734
4735
4736TEST(r6_aluipc) {
4737 if (kArchVariant == kMips64r6) {
4738 CcTest::InitializeVM();
4739
4740 struct TestCaseAluipc {
4741 int16_t offset;
4742 };
4743
4744 struct TestCaseAluipc tc[] = {
4745 // offset
4746 { -32768 }, // 0x8000
4747 { -1 }, // 0xFFFF
4748 { 0 },
4749 { 1 },
4750 { 32767 }, // 0x7FFF
4751 };
4752
4753 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc);
4754 for (size_t i = 0; i < nr_test_cases; ++i) {
4755 PC = 0;
4756 uint64_t res = run_aluipc(tc[i].offset);
4757 // Now, the program_counter (PC) is set.
4758 uint64_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16));
4759 CHECK_EQ(expected_res, res);
4760 }
4761 }
4762}
4763
4764
4765uint64_t run_auipc(int16_t offset) {
4766 Isolate* isolate = CcTest::i_isolate();
4767 HandleScope scope(isolate);
4768
4769 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4770
4771 __ auipc(v0, offset);
4772 __ jr(ra);
4773 __ nop();
4774
4775 CodeDesc desc;
4776 assm.GetCode(&desc);
4777 Handle<Code> code = isolate->factory()->NewCode(
4778 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4779
4780 F2 f = FUNCTION_CAST<F2>(code->entry());
4781 PC = (uint64_t) f; // Set the program counter.
4782
4783 uint64_t res = reinterpret_cast<uint64_t>(
4784 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4785
4786 return res;
4787}
4788
4789
4790TEST(r6_auipc) {
4791 if (kArchVariant == kMips64r6) {
4792 CcTest::InitializeVM();
4793
4794 struct TestCaseAuipc {
4795 int16_t offset;
4796 };
4797
4798 struct TestCaseAuipc tc[] = {
4799 // offset
4800 { -32768 }, // 0x8000
4801 { -1 }, // 0xFFFF
4802 { 0 },
4803 { 1 },
4804 { 32767 }, // 0x7FFF
4805 };
4806
4807 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc);
4808 for (size_t i = 0; i < nr_test_cases; ++i) {
4809 PC = 0;
4810 uint64_t res = run_auipc(tc[i].offset);
4811 // Now, the program_counter (PC) is set.
4812 uint64_t expected_res = PC + (tc[i].offset << 16);
4813 CHECK_EQ(expected_res, res);
4814 }
4815 }
4816}
4817
4818
4819uint64_t run_aui(uint64_t rs, uint16_t offset) {
4820 Isolate* isolate = CcTest::i_isolate();
4821 HandleScope scope(isolate);
4822
4823 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4824
4825 __ li(t0, rs);
4826 __ aui(v0, t0, offset);
4827 __ jr(ra);
4828 __ nop();
4829
4830 CodeDesc desc;
4831 assm.GetCode(&desc);
4832 Handle<Code> code = isolate->factory()->NewCode(
4833 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4834
4835 F2 f = FUNCTION_CAST<F2>(code->entry());
4836
4837 uint64_t res =
4838 reinterpret_cast<uint64_t>
4839 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4840
4841 return res;
4842}
4843
4844
4845uint64_t run_daui(uint64_t rs, uint16_t offset) {
4846 Isolate* isolate = CcTest::i_isolate();
4847 HandleScope scope(isolate);
4848
4849 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4850
4851 __ li(t0, rs);
4852 __ daui(v0, t0, offset);
4853 __ jr(ra);
4854 __ nop();
4855
4856 CodeDesc desc;
4857 assm.GetCode(&desc);
4858 Handle<Code> code = isolate->factory()->NewCode(
4859 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4860
4861 F2 f = FUNCTION_CAST<F2>(code->entry());
4862
4863 uint64_t res =
4864 reinterpret_cast<uint64_t>
4865 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4866
4867 return res;
4868}
4869
4870
4871uint64_t run_dahi(uint64_t rs, uint16_t offset) {
4872 Isolate* isolate = CcTest::i_isolate();
4873 HandleScope scope(isolate);
4874
4875 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4876
4877 __ li(v0, rs);
4878 __ dahi(v0, offset);
4879 __ jr(ra);
4880 __ nop();
4881
4882 CodeDesc desc;
4883 assm.GetCode(&desc);
4884 Handle<Code> code = isolate->factory()->NewCode(
4885 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4886
4887 F2 f = FUNCTION_CAST<F2>(code->entry());
4888
4889 uint64_t res =
4890 reinterpret_cast<uint64_t>
4891 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4892
4893 return res;
4894}
4895
4896
4897uint64_t run_dati(uint64_t rs, uint16_t offset) {
4898 Isolate* isolate = CcTest::i_isolate();
4899 HandleScope scope(isolate);
4900
4901 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4902
4903 __ li(v0, rs);
4904 __ dati(v0, offset);
4905 __ jr(ra);
4906 __ nop();
4907
4908 CodeDesc desc;
4909 assm.GetCode(&desc);
4910 Handle<Code> code = isolate->factory()->NewCode(
4911 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4912
4913 F2 f = FUNCTION_CAST<F2>(code->entry());
4914
4915 uint64_t res =
4916 reinterpret_cast<uint64_t>
4917 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4918
4919 return res;
4920}
4921
4922
4923TEST(r6_aui_family) {
4924 if (kArchVariant == kMips64r6) {
4925 CcTest::InitializeVM();
4926
4927 struct TestCaseAui {
4928 uint64_t rs;
4929 uint16_t offset;
4930 uint64_t ref_res;
4931 };
4932
4933 // AUI test cases.
4934 struct TestCaseAui aui_tc[] = {
4935 {0xfffeffff, 0x1, 0xffffffffffffffff},
4936 {0xffffffff, 0x0, 0xffffffffffffffff},
4937 {0, 0xffff, 0xffffffffffff0000},
4938 {0x0008ffff, 0xfff7, 0xffffffffffffffff},
4939 {32767, 32767, 0x000000007fff7fff},
4940 {0x00000000ffffffff, 0x1, 0x000000000000ffff},
4941 {0xffffffff, 0xffff, 0xfffffffffffeffff},
4942 };
4943
4944 size_t nr_test_cases = sizeof(aui_tc) / sizeof(TestCaseAui);
4945 for (size_t i = 0; i < nr_test_cases; ++i) {
4946 uint64_t res = run_aui(aui_tc[i].rs, aui_tc[i].offset);
4947 CHECK_EQ(aui_tc[i].ref_res, res);
4948 }
4949
4950 // DAUI test cases.
4951 struct TestCaseAui daui_tc[] = {
4952 {0xfffffffffffeffff, 0x1, 0xffffffffffffffff},
4953 {0xffffffffffffffff, 0x0, 0xffffffffffffffff},
4954 {0, 0xffff, 0xffffffffffff0000},
4955 {0x0008ffff, 0xfff7, 0xffffffffffffffff},
4956 {32767, 32767, 0x000000007fff7fff},
4957 {0x00000000ffffffff, 0x1, 0x000000010000ffff},
4958 {0xffffffff, 0xffff, 0x00000000fffeffff},
4959 };
4960
4961 nr_test_cases = sizeof(daui_tc) / sizeof(TestCaseAui);
4962 for (size_t i = 0; i < nr_test_cases; ++i) {
4963 uint64_t res = run_daui(daui_tc[i].rs, daui_tc[i].offset);
4964 CHECK_EQ(daui_tc[i].ref_res, res);
4965 }
4966
4967 // DATI test cases.
4968 struct TestCaseAui dati_tc[] = {
4969 {0xfffffffffffeffff, 0x1, 0x0000fffffffeffff},
4970 {0xffffffffffffffff, 0x0, 0xffffffffffffffff},
4971 {0, 0xffff, 0xffff000000000000},
4972 {0x0008ffff, 0xfff7, 0xfff700000008ffff},
4973 {32767, 32767, 0x7fff000000007fff},
4974 {0x00000000ffffffff, 0x1, 0x00010000ffffffff},
4975 {0xffffffffffff, 0xffff, 0xffffffffffffffff},
4976 };
4977
4978 nr_test_cases = sizeof(dati_tc) / sizeof(TestCaseAui);
4979 for (size_t i = 0; i < nr_test_cases; ++i) {
4980 uint64_t res = run_dati(dati_tc[i].rs, dati_tc[i].offset);
4981 CHECK_EQ(dati_tc[i].ref_res, res);
4982 }
4983
4984 // DAHI test cases.
4985 struct TestCaseAui dahi_tc[] = {
4986 {0xfffffffeffffffff, 0x1, 0xffffffffffffffff},
4987 {0xffffffffffffffff, 0x0, 0xffffffffffffffff},
4988 {0, 0xffff, 0xffffffff00000000},
4989 };
4990
4991 nr_test_cases = sizeof(dahi_tc) / sizeof(TestCaseAui);
4992 for (size_t i = 0; i < nr_test_cases; ++i) {
4993 uint64_t res = run_dahi(dahi_tc[i].rs, dahi_tc[i].offset);
4994 CHECK_EQ(dahi_tc[i].ref_res, res);
4995 }
4996 }
4997}
4998
4999
5000uint64_t run_lwpc(int offset) {
5001 Isolate* isolate = CcTest::i_isolate();
5002 HandleScope scope(isolate);
5003
5004 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5005
5006 // 256k instructions; 2^8k
5007 // addiu t3, a4, 0xffff; (0x250fffff)
5008 // ...
5009 // addiu t0, a4, 0x0000; (0x250c0000)
5010 uint32_t addiu_start_1 = 0x25000000;
5011 for (int32_t i = 0xfffff; i >= 0xc0000; --i) {
5012 uint32_t addiu_new = addiu_start_1 + i;
5013 __ dd(addiu_new);
5014 }
5015
5016 __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register)
5017 __ mov(v0, t8);
5018
5019 // 256k instructions; 2^8k
5020 // addiu a4, a4, 0x0000; (0x25080000)
5021 // ...
5022 // addiu a7, a4, 0xffff; (0x250bffff)
5023 uint32_t addiu_start_2 = 0x25000000;
5024 for (int32_t i = 0x80000; i <= 0xbffff; ++i) {
5025 uint32_t addiu_new = addiu_start_2 + i;
5026 __ dd(addiu_new);
5027 }
5028
5029 __ jr(ra);
5030 __ nop();
5031
5032 CodeDesc desc;
5033 assm.GetCode(&desc);
5034 Handle<Code> code = isolate->factory()->NewCode(
5035 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5036
5037 F2 f = FUNCTION_CAST<F2>(code->entry());
5038
5039 uint64_t res = reinterpret_cast<uint64_t>(
5040 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5041
5042 return res;
5043}
5044
5045
5046TEST(r6_lwpc) {
5047 if (kArchVariant == kMips64r6) {
5048 CcTest::InitializeVM();
5049
5050 struct TestCaseLwpc {
5051 int offset;
5052 uint64_t expected_res;
5053 };
5054
5055 struct TestCaseLwpc tc[] = {
5056 // offset, expected_res
5057 { -262144, 0x250fffff }, // offset 0x40000
5058 { -4, 0x250c0003 },
5059 { -1, 0x250c0000 },
5060 { 0, 0xffffffffef080000 },
5061 { 1, 0x03001025 }, // mov(v0, t8)
5062 { 2, 0x25080000 },
5063 { 4, 0x25080002 },
5064 { 262143, 0x250bfffd }, // offset 0x3ffff
5065 };
5066
5067 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc);
5068 for (size_t i = 0; i < nr_test_cases; ++i) {
5069 uint64_t res = run_lwpc(tc[i].offset);
5070 CHECK_EQ(tc[i].expected_res, res);
5071 }
5072 }
5073}
5074
5075
5076uint64_t run_lwupc(int offset) {
5077 Isolate* isolate = CcTest::i_isolate();
5078 HandleScope scope(isolate);
5079
5080 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5081
5082 // 256k instructions; 2^8k
5083 // addiu t3, a4, 0xffff; (0x250fffff)
5084 // ...
5085 // addiu t0, a4, 0x0000; (0x250c0000)
5086 uint32_t addiu_start_1 = 0x25000000;
5087 for (int32_t i = 0xfffff; i >= 0xc0000; --i) {
5088 uint32_t addiu_new = addiu_start_1 + i;
5089 __ dd(addiu_new);
5090 }
5091
5092 __ lwupc(t8, offset); // offset 0; 0xef080000 (t8 register)
5093 __ mov(v0, t8);
5094
5095 // 256k instructions; 2^8k
5096 // addiu a4, a4, 0x0000; (0x25080000)
5097 // ...
5098 // addiu a7, a4, 0xffff; (0x250bffff)
5099 uint32_t addiu_start_2 = 0x25000000;
5100 for (int32_t i = 0x80000; i <= 0xbffff; ++i) {
5101 uint32_t addiu_new = addiu_start_2 + i;
5102 __ dd(addiu_new);
5103 }
5104
5105 __ jr(ra);
5106 __ nop();
5107
5108 CodeDesc desc;
5109 assm.GetCode(&desc);
5110 Handle<Code> code = isolate->factory()->NewCode(
5111 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5112
5113 F2 f = FUNCTION_CAST<F2>(code->entry());
5114
5115 uint64_t res = reinterpret_cast<uint64_t>(
5116 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5117
5118 return res;
5119}
5120
5121
5122TEST(r6_lwupc) {
5123 if (kArchVariant == kMips64r6) {
5124 CcTest::InitializeVM();
5125
5126 struct TestCaseLwupc {
5127 int offset;
5128 uint64_t expected_res;
5129 };
5130
5131 struct TestCaseLwupc tc[] = {
5132 // offset, expected_res
5133 { -262144, 0x250fffff }, // offset 0x40000
5134 { -4, 0x250c0003 },
5135 { -1, 0x250c0000 },
5136 { 0, 0xef100000 },
5137 { 1, 0x03001025 }, // mov(v0, t8)
5138 { 2, 0x25080000 },
5139 { 4, 0x25080002 },
5140 { 262143, 0x250bfffd }, // offset 0x3ffff
5141 };
5142
5143 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwupc);
5144 for (size_t i = 0; i < nr_test_cases; ++i) {
5145 uint64_t res = run_lwupc(tc[i].offset);
5146 CHECK_EQ(tc[i].expected_res, res);
5147 }
5148 }
5149}
5150
5151
5152uint64_t run_jic(int16_t offset) {
5153 Isolate* isolate = CcTest::i_isolate();
5154 HandleScope scope(isolate);
5155
5156 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5157
5158 Label get_program_counter, stop_execution;
5159 __ push(ra);
5160 __ li(v0, 0);
5161 __ li(t1, 0x66);
5162
5163 __ addiu(v0, v0, 0x1); // <-- offset = -32
5164 __ addiu(v0, v0, 0x2);
5165 __ addiu(v0, v0, 0x10);
5166 __ addiu(v0, v0, 0x20);
5167 __ beq(v0, t1, &stop_execution);
5168 __ nop();
5169
5170 __ bal(&get_program_counter); // t0 <- program counter
5171 __ nop();
5172 __ jic(t0, offset);
5173
5174 __ addiu(v0, v0, 0x100);
5175 __ addiu(v0, v0, 0x200);
5176 __ addiu(v0, v0, 0x1000);
5177 __ addiu(v0, v0, 0x2000); // <--- offset = 16
5178 __ pop(ra);
5179 __ jr(ra);
5180 __ nop();
5181
5182 __ bind(&get_program_counter);
5183 __ mov(t0, ra);
5184 __ jr(ra);
5185 __ nop();
5186
5187 __ bind(&stop_execution);
5188 __ pop(ra);
5189 __ jr(ra);
5190 __ nop();
5191
5192 CodeDesc desc;
5193 assm.GetCode(&desc);
5194 Handle<Code> code = isolate->factory()->NewCode(
5195 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5196
5197 F2 f = FUNCTION_CAST<F2>(code->entry());
5198
5199 uint64_t res = reinterpret_cast<uint64_t>(
5200 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5201
5202 return res;
5203}
5204
5205
5206TEST(r6_jic) {
5207 if (kArchVariant == kMips64r6) {
5208 CcTest::InitializeVM();
5209
5210 struct TestCaseJic {
5211 // As rt will be used t0 register which will have value of
5212 // the program counter for the jic instruction.
5213 int16_t offset;
5214 uint32_t expected_res;
5215 };
5216
5217 struct TestCaseJic tc[] = {
5218 // offset, expected_result
5219 { 16, 0x2033 },
5220 { 4, 0x3333 },
5221 { -32, 0x66 },
5222 };
5223
5224 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic);
5225 for (size_t i = 0; i < nr_test_cases; ++i) {
5226 uint64_t res = run_jic(tc[i].offset);
5227 CHECK_EQ(tc[i].expected_res, res);
5228 }
5229 }
5230}
5231
5232
5233uint64_t run_beqzc(int32_t value, int32_t offset) {
5234 Isolate* isolate = CcTest::i_isolate();
5235 HandleScope scope(isolate);
5236
5237 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5238
5239 Label stop_execution;
5240 __ li(v0, 0);
5241 __ li(t1, 0x66);
5242
5243 __ addiu(v0, v0, 0x1); // <-- offset = -8
5244 __ addiu(v0, v0, 0x2);
5245 __ addiu(v0, v0, 0x10);
5246 __ addiu(v0, v0, 0x20);
5247 __ beq(v0, t1, &stop_execution);
5248 __ nop();
5249
5250 __ beqzc(a0, offset);
5251
5252 __ addiu(v0, v0, 0x1);
5253 __ addiu(v0, v0, 0x100);
5254 __ addiu(v0, v0, 0x200);
5255 __ addiu(v0, v0, 0x1000);
5256 __ addiu(v0, v0, 0x2000); // <--- offset = 4
5257 __ jr(ra);
5258 __ nop();
5259
5260 __ bind(&stop_execution);
5261 __ jr(ra);
5262 __ nop();
5263
5264 CodeDesc desc;
5265 assm.GetCode(&desc);
5266 Handle<Code> code = isolate->factory()->NewCode(
5267 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5268
5269 F2 f = FUNCTION_CAST<F2>(code->entry());
5270
5271 uint64_t res = reinterpret_cast<uint64_t>(
5272 CALL_GENERATED_CODE(isolate, f, value, 0, 0, 0, 0));
5273
5274 return res;
5275}
5276
5277
5278TEST(r6_beqzc) {
5279 if (kArchVariant == kMips64r6) {
5280 CcTest::InitializeVM();
5281
5282 struct TestCaseBeqzc {
5283 uint32_t value;
5284 int32_t offset;
5285 uint32_t expected_res;
5286 };
5287
5288 struct TestCaseBeqzc tc[] = {
5289 // value, offset, expected_res
5290 { 0x0, -8, 0x66 },
5291 { 0x0, 0, 0x3334 },
5292 { 0x0, 1, 0x3333 },
5293 { 0xabc, 1, 0x3334 },
5294 { 0x0, 4, 0x2033 },
5295 };
5296
5297 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc);
5298 for (size_t i = 0; i < nr_test_cases; ++i) {
5299 uint64_t res = run_beqzc(tc[i].value, tc[i].offset);
5300 CHECK_EQ(tc[i].expected_res, res);
5301 }
5302 }
5303}
5304
5305
5306uint64_t run_jialc(int16_t offset) {
5307 Isolate* isolate = CcTest::i_isolate();
5308 HandleScope scope(isolate);
5309
5310 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5311
5312 Label main_block, get_program_counter;
5313 __ push(ra);
5314 __ li(v0, 0);
5315 __ beq(v0, v0, &main_block);
5316 __ nop();
5317
5318 // Block 1
5319 __ addiu(v0, v0, 0x1); // <-- offset = -40
5320 __ addiu(v0, v0, 0x2);
5321 __ jr(ra);
5322 __ nop();
5323
5324 // Block 2
5325 __ addiu(v0, v0, 0x10); // <-- offset = -24
5326 __ addiu(v0, v0, 0x20);
5327 __ jr(ra);
5328 __ nop();
5329
5330 // Block 3 (Main)
5331 __ bind(&main_block);
5332 __ bal(&get_program_counter); // t0 <- program counter
5333 __ nop();
5334 __ jialc(t0, offset);
5335 __ addiu(v0, v0, 0x4);
5336 __ pop(ra);
5337 __ jr(ra);
5338 __ nop();
5339
5340 // Block 4
5341 __ addiu(v0, v0, 0x100); // <-- offset = 20
5342 __ addiu(v0, v0, 0x200);
5343 __ jr(ra);
5344 __ nop();
5345
5346 // Block 5
5347 __ addiu(v0, v0, 0x1000); // <--- offset = 36
5348 __ addiu(v0, v0, 0x2000);
5349 __ jr(ra);
5350 __ nop();
5351
5352 __ bind(&get_program_counter);
5353 __ mov(t0, ra);
5354 __ jr(ra);
5355 __ nop();
5356
5357
5358 CodeDesc desc;
5359 assm.GetCode(&desc);
5360 Handle<Code> code = isolate->factory()->NewCode(
5361 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5362
5363 F2 f = FUNCTION_CAST<F2>(code->entry());
5364
5365 uint64_t res = reinterpret_cast<uint64_t>(
5366 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5367
5368 return res;
5369}
5370
5371
5372TEST(r6_jialc) {
5373 if (kArchVariant == kMips64r6) {
5374 CcTest::InitializeVM();
5375
5376 struct TestCaseJialc {
5377 // As rt will be used t0 register which will have value of
5378 // the program counter for the jialc instruction.
5379 int16_t offset;
5380 uint32_t expected_res;
5381 };
5382
5383 struct TestCaseJialc tc[] = {
5384 // offset, expected_res
5385 { -40, 0x7 },
5386 { -24, 0x34 },
5387 { 20, 0x304 },
5388 { 36, 0x3004 }
5389 };
5390
5391 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc);
5392 for (size_t i = 0; i < nr_test_cases; ++i) {
5393 uint64_t res = run_jialc(tc[i].offset);
5394 CHECK_EQ(tc[i].expected_res, res);
5395 }
5396 }
5397}
5398
5399
5400uint64_t run_addiupc(int32_t imm19) {
5401 Isolate* isolate = CcTest::i_isolate();
5402 HandleScope scope(isolate);
5403
5404 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5405
5406 __ addiupc(v0, imm19);
5407 __ jr(ra);
5408 __ nop();
5409
5410 CodeDesc desc;
5411 assm.GetCode(&desc);
5412 Handle<Code> code = isolate->factory()->NewCode(
5413 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5414
5415 F2 f = FUNCTION_CAST<F2>(code->entry());
5416 PC = (uint64_t) f; // Set the program counter.
5417
5418 uint64_t res = reinterpret_cast<uint64_t>(
5419 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5420
5421 return res;
5422}
5423
5424
5425TEST(r6_addiupc) {
5426 if (kArchVariant == kMips64r6) {
5427 CcTest::InitializeVM();
5428
5429 struct TestCaseAddiupc {
5430 int32_t imm19;
5431 };
5432
5433 struct TestCaseAddiupc tc[] = {
5434 // imm19
5435 { -262144 }, // 0x40000
5436 { -1 }, // 0x7FFFF
5437 { 0 },
5438 { 1 }, // 0x00001
5439 { 262143 } // 0x3FFFF
5440 };
5441
5442 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc);
5443 for (size_t i = 0; i < nr_test_cases; ++i) {
5444 PC = 0;
5445 uint64_t res = run_addiupc(tc[i].imm19);
5446 // Now, the program_counter (PC) is set.
5447 uint64_t expected_res = PC + (tc[i].imm19 << 2);
5448 CHECK_EQ(expected_res, res);
5449 }
5450 }
5451}
5452
5453
5454uint64_t run_ldpc(int offset) {
5455 Isolate* isolate = CcTest::i_isolate();
5456 HandleScope scope(isolate);
5457
5458 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5459
5460 // 256k instructions; 2 * 2^7k = 2^8k
5461 // addiu t3, a4, 0xffff; (0x250fffff)
5462 // ...
5463 // addiu t0, a4, 0x0000; (0x250c0000)
5464 uint32_t addiu_start_1 = 0x25000000;
5465 for (int32_t i = 0xfffff; i >= 0xc0000; --i) {
5466 uint32_t addiu_new = addiu_start_1 + i;
5467 __ dd(addiu_new);
5468 }
5469
5470 __ ldpc(t8, offset); // offset 0; 0xef080000 (t8 register)
5471 __ mov(v0, t8);
5472
5473 // 256k instructions; 2 * 2^7k = 2^8k
5474 // addiu a4, a4, 0x0000; (0x25080000)
5475 // ...
5476 // addiu a7, a4, 0xffff; (0x250bffff)
5477 uint32_t addiu_start_2 = 0x25000000;
5478 for (int32_t i = 0x80000; i <= 0xbffff; ++i) {
5479 uint32_t addiu_new = addiu_start_2 + i;
5480 __ dd(addiu_new);
5481 }
5482
5483 __ jr(ra);
5484 __ nop();
5485
5486 CodeDesc desc;
5487 assm.GetCode(&desc);
5488 Handle<Code> code = isolate->factory()->NewCode(
5489 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5490
5491 F2 f = FUNCTION_CAST<F2>(code->entry());
5492
5493 uint64_t res = reinterpret_cast<uint64_t>(
5494 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5495
5496 return res;
5497}
5498
5499
5500TEST(r6_ldpc) {
5501 if (kArchVariant == kMips64r6) {
5502 CcTest::InitializeVM();
5503
5504 struct TestCaseLdpc {
5505 int offset;
5506 uint64_t expected_res;
5507 };
5508
5509 struct TestCaseLdpc tc[] = {
5510 // offset, expected_res
5511 { -131072, 0x250ffffe250fffff },
5512 { -4, 0x250c0006250c0007 },
5513 { -1, 0x250c0000250c0001 },
5514 { 0, 0x03001025ef180000 },
5515 { 1, 0x2508000125080000 },
5516 { 4, 0x2508000725080006 },
5517 { 131071, 0x250bfffd250bfffc },
5518 };
5519
5520 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLdpc);
5521 for (size_t i = 0; i < nr_test_cases; ++i) {
5522 uint64_t res = run_ldpc(tc[i].offset);
5523 CHECK_EQ(tc[i].expected_res, res);
5524 }
5525 }
5526}
5527
5528
5529int64_t run_bc(int32_t offset) {
5530 Isolate* isolate = CcTest::i_isolate();
5531 HandleScope scope(isolate);
5532
5533 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5534
5535 Label continue_1, stop_execution;
5536 __ push(ra);
5537 __ li(v0, 0);
5538 __ li(t8, 0);
5539 __ li(t9, 2); // Condition for the stopping execution.
5540
5541 for (int32_t i = -100; i <= -11; ++i) {
5542 __ addiu(v0, v0, 1);
5543 }
5544
5545 __ addiu(t8, t8, 1); // -10
5546
5547 __ beq(t8, t9, &stop_execution); // -9
5548 __ nop(); // -8
5549 __ beq(t8, t8, &continue_1); // -7
5550 __ nop(); // -6
5551
5552 __ bind(&stop_execution);
5553 __ pop(ra); // -5, -4
5554 __ jr(ra); // -3
5555 __ nop(); // -2
5556
5557 __ bind(&continue_1);
5558 __ bc(offset); // -1
5559
5560 for (int32_t i = 0; i <= 99; ++i) {
5561 __ addiu(v0, v0, 1);
5562 }
5563
5564 __ pop(ra);
5565 __ jr(ra);
5566 __ nop();
5567
5568 CodeDesc desc;
5569 assm.GetCode(&desc);
5570 Handle<Code> code = isolate->factory()->NewCode(
5571 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5572
5573 F2 f = FUNCTION_CAST<F2>(code->entry());
5574
5575 int64_t res = reinterpret_cast<int64_t>(
5576 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5577
5578 return res;
5579}
5580
5581
5582TEST(r6_bc) {
5583 if (kArchVariant == kMips64r6) {
5584 CcTest::InitializeVM();
5585
5586 struct TestCaseBc {
5587 int32_t offset;
5588 int64_t expected_res;
5589 };
5590
5591 struct TestCaseBc tc[] = {
5592 // offset, expected_result
5593 { -100, (abs(-100) - 10) * 2 },
5594 { -11, (abs(-100) - 10 + 1) },
5595 { 0, (abs(-100) - 10 + 1 + 99) },
5596 { 1, (abs(-100) - 10 + 99) },
5597 { 99, (abs(-100) - 10 + 1) },
5598 };
5599
5600 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc);
5601 for (size_t i = 0; i < nr_test_cases; ++i) {
5602 int64_t res = run_bc(tc[i].offset);
5603 CHECK_EQ(tc[i].expected_res, res);
5604 }
5605 }
5606}
5607
5608
5609int64_t run_balc(int32_t offset) {
5610 Isolate* isolate = CcTest::i_isolate();
5611 HandleScope scope(isolate);
5612
5613 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5614
5615 Label continue_1, stop_execution;
5616 __ push(ra);
5617 __ li(v0, 0);
5618 __ li(t8, 0);
5619 __ li(t9, 2); // Condition for stopping execution.
5620
5621 __ beq(t8, t8, &continue_1);
5622 __ nop();
5623
5624 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1
5625 for (int32_t i = -117; i <= -57; ++i) {
5626 __ dd(instruction_addiu);
5627 }
5628 __ jr(ra); // -56
5629 __ nop(); // -55
5630
5631 for (int32_t i = -54; i <= -4; ++i) {
5632 __ dd(instruction_addiu);
5633 }
5634 __ jr(ra); // -3
5635 __ nop(); // -2
5636
5637 __ bind(&continue_1);
5638 __ balc(offset); // -1
5639
5640 __ pop(ra); // 0, 1
5641 __ jr(ra); // 2
5642 __ nop(); // 3
5643
5644 for (int32_t i = 4; i <= 44; ++i) {
5645 __ dd(instruction_addiu);
5646 }
5647 __ jr(ra);
5648 __ nop();
5649
5650 CodeDesc desc;
5651 assm.GetCode(&desc);
5652 Handle<Code> code = isolate->factory()->NewCode(
5653 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5654
5655 F2 f = FUNCTION_CAST<F2>(code->entry());
5656
5657 int64_t res = reinterpret_cast<int64_t>(
5658 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5659
5660 return res;
5661}
5662
5663
5664TEST(r6_balc) {
5665 if (kArchVariant == kMips64r6) {
5666 CcTest::InitializeVM();
5667
5668 struct TestCaseBalc {
5669 int32_t offset;
5670 int64_t expected_res;
5671 };
5672
5673 struct TestCaseBalc tc[] = {
5674 // offset, expected_result
5675 { -117, 61 },
5676 { -54, 51 },
5677 { 0, 0 },
5678 { 4, 41 },
5679 };
5680
5681 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc);
5682 for (size_t i = 0; i < nr_test_cases; ++i) {
5683 int64_t res = run_balc(tc[i].offset);
5684 CHECK_EQ(tc[i].expected_res, res);
5685 }
5686 }
5687}
5688
5689
5690uint64_t run_dsll(uint64_t rt_value, uint16_t sa_value) {
5691 Isolate* isolate = CcTest::i_isolate();
5692 HandleScope scope(isolate);
5693
5694 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5695
5696 __ dsll(v0, a0, sa_value);
5697 __ jr(ra);
5698 __ nop();
5699
5700 CodeDesc desc;
5701 assm.GetCode(&desc);
5702 Handle<Code> code = isolate->factory()->NewCode(
5703 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5704
5705 F4 f = FUNCTION_CAST<F4>(code->entry());
5706
5707 uint64_t res = reinterpret_cast<uint64_t>(
5708 CALL_GENERATED_CODE(isolate, f, rt_value, 0, 0, 0, 0));
5709
5710 return res;
5711}
5712
5713
5714TEST(dsll) {
5715 CcTest::InitializeVM();
5716
5717 struct TestCaseDsll {
5718 uint64_t rt_value;
5719 uint16_t sa_value;
5720 uint64_t expected_res;
5721 };
5722
5723 struct TestCaseDsll tc[] = {
5724 // rt_value, sa_value, expected_res
5725 { 0xffffffffffffffff, 0, 0xffffffffffffffff },
5726 { 0xffffffffffffffff, 16, 0xffffffffffff0000 },
5727 { 0xffffffffffffffff, 31, 0xffffffff80000000 },
5728 };
5729
5730 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDsll);
5731 for (size_t i = 0; i < nr_test_cases; ++i) {
5732 CHECK_EQ(tc[i].expected_res,
5733 run_dsll(tc[i].rt_value, tc[i].sa_value));
5734 }
5735}
5736
5737
5738uint64_t run_bal(int16_t offset) {
5739 Isolate* isolate = CcTest::i_isolate();
5740 HandleScope scope(isolate);
5741
5742 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5743
5744 __ mov(t0, ra);
5745 __ bal(offset); // Equivalent for "BGEZAL zero_reg, offset".
5746 __ nop();
5747
5748 __ mov(ra, t0);
5749 __ jr(ra);
5750 __ nop();
5751
5752 __ li(v0, 1);
5753 __ jr(ra);
5754 __ nop();
5755
5756 CodeDesc desc;
5757 assm.GetCode(&desc);
5758 Handle<Code> code = isolate->factory()->NewCode(
5759 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5760
5761 F2 f = FUNCTION_CAST<F2>(code->entry());
5762
5763 uint64_t res = reinterpret_cast<uint64_t>(
5764 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5765
5766 return res;
5767}
5768
5769
5770TEST(bal) {
5771 CcTest::InitializeVM();
5772
5773 struct TestCaseBal {
5774 int16_t offset;
5775 uint64_t expected_res;
5776 };
5777
5778 struct TestCaseBal tc[] = {
5779 // offset, expected_res
5780 { 4, 1 },
5781 };
5782
5783 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBal);
5784 for (size_t i = 0; i < nr_test_cases; ++i) {
5785 CHECK_EQ(tc[i].expected_res, run_bal(tc[i].offset));
5786 }
5787}
5788
5789
5790TEST(Trampoline) {
5791 // Private member of Assembler class.
5792 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
5793
5794 CcTest::InitializeVM();
5795 Isolate* isolate = CcTest::i_isolate();
5796 HandleScope scope(isolate);
5797
5798 MacroAssembler assm(isolate, nullptr, 0,
5799 v8::internal::CodeObjectRequired::kYes);
5800 Label done;
5801 size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2;
5802
5803 for (size_t i = 0; i < nr_calls; ++i) {
5804 __ BranchShort(&done, eq, a0, Operand(a1));
5805 }
5806 __ bind(&done);
5807 __ Ret(USE_DELAY_SLOT);
5808 __ mov(v0, zero_reg);
5809
5810 CodeDesc desc;
5811 assm.GetCode(&desc);
5812 Handle<Code> code = isolate->factory()->NewCode(
5813 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5814 F2 f = FUNCTION_CAST<F2>(code->entry());
5815
5816 int64_t res = reinterpret_cast<int64_t>(
5817 CALL_GENERATED_CODE(isolate, f, 42, 42, 0, 0, 0));
5818 CHECK_EQ(res, 0);
5819}
5820
5821
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005822#undef __