• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
28 #include <iostream>  // NOLINT(readability/streams)
29 
30 #include "src/v8.h"
31 
32 #include "src/base/utils/random-number-generator.h"
33 #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 
41 using namespace v8::internal;
42 
43 
44 // Define these function prototypes to match JSEntryFunction in execution.cc.
45 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
46 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
47 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
48 typedef Object* (*F4)(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4);
49 
50 
51 #define __ assm.
52 
TEST(MIPS0)53 TEST(MIPS0) {
54   CcTest::InitializeVM();
55   Isolate* isolate = CcTest::i_isolate();
56   HandleScope scope(isolate);
57 
58   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
59 
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());
70   int64_t res = reinterpret_cast<int64_t>(
71       CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0));
72   CHECK_EQ(0xabcL, res);
73 }
74 
75 
TEST(MIPS1)76 TEST(MIPS1) {
77   CcTest::InitializeVM();
78   Isolate* isolate = CcTest::i_isolate();
79   HandleScope scope(isolate);
80 
81   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
82   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());
106   int64_t res = reinterpret_cast<int64_t>(
107       CALL_GENERATED_CODE(isolate, f, 50, 0, 0, 0, 0));
108   CHECK_EQ(1275L, res);
109 }
110 
111 
TEST(MIPS2)112 TEST(MIPS2) {
113   CcTest::InitializeVM();
114   Isolate* isolate = CcTest::i_isolate();
115   HandleScope scope(isolate);
116 
117   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
118 
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());
252   int64_t res = reinterpret_cast<int64_t>(
253       CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0));
254 
255   CHECK_EQ(0x31415926L, res);
256 }
257 
258 
TEST(MIPS3)259 TEST(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;
275     float fa;
276     float fb;
277     float fc;
278     float fd;
279     float fe;
280     float ff;
281     float fg;
282   } T;
283   T t;
284 
285   // Create a function that accepts &t, and loads, manipulates, and stores
286   // the doubles t.a ... t.f.
287   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
288   Label L, C;
289 
290   // Double precision floating point instructions.
291   __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
292   __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
293   __ add_d(f8, f4, f6);
294   __ sdc1(f8, MemOperand(a0, offsetof(T, c)) );  // c = a + b.
295 
296   __ mov_d(f10, f8);  // c
297   __ neg_d(f12, f6);  // -b
298   __ sub_d(f10, f10, f12);
299   __ sdc1(f10, MemOperand(a0, offsetof(T, d)) );  // d = c - (-b).
300 
301   __ sdc1(f4, MemOperand(a0, offsetof(T, b)) );   // b = a.
302 
303   __ li(a4, 120);
304   __ mtc1(a4, f14);
305   __ cvt_d_w(f14, f14);   // f14 = 120.0.
306   __ mul_d(f10, f10, f14);
307   __ sdc1(f10, MemOperand(a0, offsetof(T, e)) );  // e = d * 120 = 1.8066e16.
308 
309   __ div_d(f12, f10, f4);
310   __ sdc1(f12, MemOperand(a0, offsetof(T, f)) );  // f = e / a = 120.44.
311 
312   __ sqrt_d(f14, f12);
313   __ sdc1(f14, MemOperand(a0, offsetof(T, g)) );
314   // g = sqrt(f) = 10.97451593465515908537
315 
316   if (kArchVariant == kMips64r2) {
317     __ ldc1(f4, MemOperand(a0, offsetof(T, h)) );
318     __ ldc1(f6, MemOperand(a0, offsetof(T, i)) );
319     __ madd_d(f14, f6, f4, f6);
320     __ sdc1(f14, MemOperand(a0, offsetof(T, h)) );
321   }
322 
323   // 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 
347   __ 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());
355   // Double test values.
356   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;
364   // 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);
372   USE(dummy);
373   // Expected double results.
374   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   }
384   // 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);
392 }
393 
394 
TEST(MIPS4)395 TEST(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 
414   __ ldc1(f4, MemOperand(a0, offsetof(T, a)));
415   __ ldc1(f5, MemOperand(a0, offsetof(T, b)));
416 
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.
430   __ sdc1(f4, MemOperand(a0, offsetof(T, a)));
431   __ sdc1(f5, MemOperand(a0, offsetof(T, c)));
432 
433   // Test sign extension of move operations from coprocessor.
434   __ ldc1(f4, MemOperand(a0, offsetof(T, d)));
435   __ mfhc1(a4, f4);
436   __ mfc1(a5, f4);
437 
438   __ sd(a4, MemOperand(a0, offsetof(T, high)));
439   __ sd(a5, MemOperand(a0, offsetof(T, low)));
440 
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;
453   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
454   USE(dummy);
455 
456   CHECK_EQ(2.75e11, t.a);
457   CHECK_EQ(2.75e11, t.b);
458   CHECK_EQ(1.5e22, t.c);
459   CHECK_EQ(static_cast<int64_t>(0xffffffffc25001d1L), t.high);
460   CHECK_EQ(static_cast<int64_t>(0xffffffffbf800000L), t.low);
461 }
462 
463 
TEST(MIPS5)464 TEST(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.
482   __ 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)) );
486 
487   // Convert double in f4 to int in element i.
488   __ cvt_w_d(f8, f4);
489   __ mfc1(a6, f8);
490   __ sw(a6, MemOperand(a0, offsetof(T, i)) );
491 
492   // Convert double in f6 to int in element j.
493   __ cvt_w_d(f10, f6);
494   __ mfc1(a7, f10);
495   __ sw(a7, MemOperand(a0, offsetof(T, j)) );
496 
497   // Convert int in original i (a4) to double in a.
498   __ mtc1(a4, f12);
499   __ cvt_d_w(f0, f12);
500   __ sdc1(f0, MemOperand(a0, offsetof(T, a)) );
501 
502   // Convert int in original j (a5) to double in b.
503   __ mtc1(a5, f14);
504   __ cvt_d_w(f2, f14);
505   __ sdc1(f2, MemOperand(a0, offsetof(T, b)) );
506 
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;
519   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
520   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 
TEST(MIPS6)529 TEST(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.
551   __ lw(a4, MemOperand(a0, offsetof(T, ui)) );
552   __ sw(a4, MemOperand(a0, offsetof(T, r1)) );
553 
554   // lh with positive data.
555   __ lh(a5, MemOperand(a0, offsetof(T, ui)) );
556   __ sw(a5, MemOperand(a0, offsetof(T, r2)) );
557 
558   // lh with negative data.
559   __ lh(a6, MemOperand(a0, offsetof(T, si)) );
560   __ sw(a6, MemOperand(a0, offsetof(T, r3)) );
561 
562   // lhu with negative data.
563   __ lhu(a7, MemOperand(a0, offsetof(T, si)) );
564   __ sw(a7, MemOperand(a0, offsetof(T, r4)) );
565 
566   // lb with negative data.
567   __ lb(t0, MemOperand(a0, offsetof(T, si)) );
568   __ sw(t0, MemOperand(a0, offsetof(T, r5)) );
569 
570   // sh writes only 1/2 of word.
571   __ lui(t1, 0x3333);
572   __ ori(t1, t1, 0x3333);
573   __ sw(t1, MemOperand(a0, offsetof(T, r6)) );
574   __ lhu(t1, MemOperand(a0, offsetof(T, si)) );
575   __ sh(t1, MemOperand(a0, offsetof(T, r6)) );
576 
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;
587   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
588   USE(dummy);
589 
590   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   }
604 }
605 
606 
TEST(MIPS7)607 TEST(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.
626   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
627   Label neither_is_nan, less_than, outa_here;
628 
629   __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
630   __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
631   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();
639   __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) );
640   __ 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();
653   __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) );
654   __ Branch(&outa_here);
655 
656   __ bind(&less_than);
657   __ Addu(a4, zero_reg, Operand(1));
658   __ sw(a4, MemOperand(a0, offsetof(T, result)) );  // Set true.
659 
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;
680   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
681   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 
TEST(MIPS8)688 TEST(MIPS8) {
689   if (kArchVariant == kMips64r2) {
690     // Test ROTR and ROTRV instructions.
691     CcTest::InitializeVM();
692     Isolate* isolate = CcTest::i_isolate();
693     HandleScope scope(isolate);
694 
695     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;
713 
714     MacroAssembler assm(isolate, NULL, 0,
715                         v8::internal::CodeObjectRequired::kYes);
716 
717     // Basic word load.
718     __ lw(a4, MemOperand(a0, offsetof(T, input)) );
719 
720     // 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);
728 
729     // 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)) );
737 
738     // 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);
753 
754     // 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)) );
762 
763     __ jr(ra);
764     __ nop();
765 
766     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);
781 
782     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   }
790 }
791 
792 
TEST(MIPS9)793 TEST(MIPS9) {
794   // Test BRANCH improvements.
795   CcTest::InitializeVM();
796   Isolate* isolate = CcTest::i_isolate();
797   HandleScope scope(isolate);
798 
799   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
800   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 
TEST(MIPS10)819 TEST(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.
849     __ ldc1(f0, MemOperand(a0, offsetof(T, a)));
850 
851     // Save the raw bits of the double.
852     __ mfc1(a4, f0);
853     __ mfhc1(a5, f0);
854     __ sw(a4, MemOperand(a0, offsetof(T, dbl_mant)));
855     __ sw(a5, MemOperand(a0, offsetof(T, dbl_exp)));
856 
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.
861     __ sw(a4, MemOperand(a0, offsetof(T, long_lo)));
862     __ sw(a5, MemOperand(a0, offsetof(T, long_hi)));
863 
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);
869     __ sdc1(f1, MemOperand(a0, offsetof(T, a_converted)));
870 
871 
872     // Convert the b long integers to double b.
873     __ lw(a4, MemOperand(a0, offsetof(T, b_long_lo)));
874     __ lw(a5, MemOperand(a0, offsetof(T, b_long_hi)));
875     __ mtc1(a4, f8);  // f8 LS 32-bits.
876     __ mthc1(a5, f8);  // f8 MS 32-bits.
877     __ cvt_d_l(f10, f8);
878     __ sdc1(f10, MemOperand(a0, offsetof(T, b)));
879 
880     // Convert double b back to long-int.
881     __ ldc1(f31, MemOperand(a0, offsetof(T, b)));
882     __ cvt_l_d(f31, f31);
883     __ dmfc1(a7, f31);
884     __ sd(a7, MemOperand(a0, offsetof(T, b_long_as_int64)));
885 
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;
898     Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
899     USE(dummy);
900 
901     CHECK_EQ(static_cast<int32_t>(0x41DFFFFF), t.dbl_exp);
902     CHECK_EQ(static_cast<int32_t>(0xFFC00000), t.dbl_mant);
903     CHECK_EQ(0, t.long_hi);
904     CHECK_EQ(static_cast<int32_t>(0x7fffffff), t.long_lo);
905     CHECK_EQ(2.147483647e9, t.a_converted);
906 
907     // 0xFF00FF00FF -> 1.095233372415e12.
908     CHECK_EQ(1.095233372415e12, t.b);
909     CHECK_EQ(static_cast<int64_t>(0xFF00FF00FF), t.b_long_as_int64);
910   }
911 }
912 
913 
TEST(MIPS11)914 TEST(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.
947     __ 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)));
950 
951     __ 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)));
954 
955     __ 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)));
958 
959     __ 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)));
962 
963     // Test all combinations of LWR and vAddr.
964     __ 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)));
967 
968     __ 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)));
971 
972     __ 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)) );
975 
976     __ 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)) );
979 
980     // Test all combinations of SWL and vAddr.
981     __ 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)));
985 
986     __ 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));
990 
991     __ 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));
995 
996     __ 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));
1000 
1001     // Test all combinations of SWR and vAddr.
1002     __ 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)));
1006 
1007     __ 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));
1011 
1012     __ 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));
1016 
1017     __ 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));
1021 
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 
1033     Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
1034     USE(dummy);
1035 
1036     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);
1041 
1042       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);
1046 
1047       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);
1051 
1052       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     }
1077   }
1078 }
1079 
1080 
TEST(MIPS12)1081 TEST(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 
1096   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
1097 
1098   __ mov(t2, fp);  // Save frame pointer.
1099   __ mov(fp, a0);  // Access struct T by fp.
1100   __ lw(a4, MemOperand(a0, offsetof(T, y)));
1101   __ lw(a7, MemOperand(a0, offsetof(T, y4)));
1102 
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();
1119   __ sw(a4, MemOperand(fp, offsetof(T, y)));
1120   __ lw(a4, MemOperand(fp, offsetof(T, y)));
1121   __ nop();
1122   __ sw(a4, MemOperand(fp, offsetof(T, y)));
1123   __ lw(a5, MemOperand(fp, offsetof(T, y)));
1124   __ nop();
1125   __ push(a5);
1126   __ lw(a5, MemOperand(fp, offsetof(T, y)));
1127   __ pop(a5);
1128   __ nop();
1129   __ push(a5);
1130   __ lw(a6, MemOperand(fp, offsetof(T, y)));
1131   __ pop(a5);
1132   __ nop();
1133   __ push(a5);
1134   __ lw(a6, MemOperand(fp, offsetof(T, y)));
1135   __ pop(a6);
1136   __ nop();
1137   __ push(a6);
1138   __ lw(a6, MemOperand(fp, offsetof(T, y)));
1139   __ pop(a5);
1140   __ nop();
1141   __ push(a5);
1142   __ lw(a6, MemOperand(fp, offsetof(T, y)));
1143   __ 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 
1162   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
1163   USE(dummy);
1164 
1165   CHECK_EQ(3, t.y1);
1166 }
1167 
1168 
TEST(MIPS13)1169 TEST(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 
1185   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
1186 
1187   __ 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)));
1190 
1191   __ Trunc_uw_d(f10, f10, f4);
1192   __ swc1(f10, MemOperand(a0, offsetof(T, trunc_small_out)));
1193 
1194   __ 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)));
1197 
1198   __ Trunc_uw_d(f8, f8, f4);
1199   __ swc1(f8, MemOperand(a0, offsetof(T, trunc_big_out)));
1200 
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 
1213   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
1214   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 
TEST(MIPS14)1225 TEST(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) \
1232   uint32_t x##_isNaN2008; \
1233   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 
1263   MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
1264 
1265   // Save FCSR.
1266   __ cfc1(a1, FCSR);
1267   // Disable FPU exceptions.
1268   __ ctc1(zero_reg, FCSR);
1269 #define RUN_ROUND_TEST(x) \
1270   __ cfc1(t0, FCSR);\
1271   __ sw(t0, MemOperand(a0, offsetof(T, x##_isNaN2008))); \
1272   __ ldc1(f0, MemOperand(a0, offsetof(T, round_up_in))); \
1273   __ x##_w_d(f0, f0); \
1274   __ swc1(f0, MemOperand(a0, offsetof(T, x##_up_out))); \
1275   \
1276   __ ldc1(f0, MemOperand(a0, offsetof(T, round_down_in))); \
1277   __ x##_w_d(f0, f0); \
1278   __ swc1(f0, MemOperand(a0, offsetof(T, x##_down_out))); \
1279   \
1280   __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_up_in))); \
1281   __ x##_w_d(f0, f0); \
1282   __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_up_out))); \
1283   \
1284   __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_down_in))); \
1285   __ x##_w_d(f0, f0); \
1286   __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_down_out))); \
1287   \
1288   __ ldc1(f0, MemOperand(a0, offsetof(T, err1_in))); \
1289   __ ctc1(zero_reg, FCSR); \
1290   __ x##_w_d(f0, f0); \
1291   __ cfc1(a2, FCSR); \
1292   __ sw(a2, MemOperand(a0, offsetof(T, x##_err1_out))); \
1293   \
1294   __ ldc1(f0, MemOperand(a0, offsetof(T, err2_in))); \
1295   __ ctc1(zero_reg, FCSR); \
1296   __ x##_w_d(f0, f0); \
1297   __ cfc1(a2, FCSR); \
1298   __ sw(a2, MemOperand(a0, offsetof(T, x##_err2_out))); \
1299   \
1300   __ ldc1(f0, MemOperand(a0, offsetof(T, err3_in))); \
1301   __ ctc1(zero_reg, FCSR); \
1302   __ x##_w_d(f0, f0); \
1303   __ cfc1(a2, FCSR); \
1304   __ sw(a2, MemOperand(a0, offsetof(T, x##_err3_out))); \
1305   \
1306   __ ldc1(f0, MemOperand(a0, offsetof(T, err4_in))); \
1307   __ ctc1(zero_reg, FCSR); \
1308   __ x##_w_d(f0, f0); \
1309   __ cfc1(a2, FCSR); \
1310   __ sw(a2, MemOperand(a0, offsetof(T, x##_err4_out))); \
1311   __ swc1(f0, MemOperand(a0, offsetof(T, x##_invalid_result)));
1312 
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 
1340   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
1341   USE(dummy);
1342 
1343 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1344 #define CHECK_NAN2008(x) (x & kFCSRNaN2008FlagMask)
1345 #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); \
1350   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   }
1355 
1356   CHECK_ROUND_RESULT(round);
1357   CHECK_ROUND_RESULT(floor);
1358   CHECK_ROUND_RESULT(ceil);
1359   CHECK_ROUND_RESULT(cvt);
1360 }
1361 
1362 
TEST(MIPS15)1363 TEST(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 
TEST(MIPS16)1382 TEST(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.
1404   __ lw(a4, MemOperand(a0, offsetof(T, ui)));
1405   __ sw(a4, MemOperand(a0, offsetof(T, r1)));
1406 
1407   // Check that the data got zero-extended into 64-bit a4.
1408   __ sd(a4, MemOperand(a0, offsetof(T, r2)));
1409 
1410   // Basic 32-bit word load/store, with SIGNED data.
1411   __ lw(a5, MemOperand(a0, offsetof(T, si)));
1412   __ sw(a5, MemOperand(a0, offsetof(T, r3)));
1413 
1414   // Check that the data got sign-extended into 64-bit a4.
1415   __ sd(a5, MemOperand(a0, offsetof(T, r4)));
1416 
1417   // 32-bit UNSIGNED word load/store, with SIGNED data.
1418   __ lwu(a6, MemOperand(a0, offsetof(T, si)));
1419   __ sw(a6, MemOperand(a0, offsetof(T, r5)));
1420 
1421   // Check that the data got zero-extended into 64-bit a4.
1422   __ sd(a6, MemOperand(a0, offsetof(T, r6)));
1423 
1424   // lh with positive data.
1425   __ lh(a5, MemOperand(a0, offsetof(T, ui)));
1426   __ sw(a5, MemOperand(a0, offsetof(T, r2)));
1427 
1428   // lh with negative data.
1429   __ lh(a6, MemOperand(a0, offsetof(T, si)));
1430   __ sw(a6, MemOperand(a0, offsetof(T, r3)));
1431 
1432   // lhu with negative data.
1433   __ lhu(a7, MemOperand(a0, offsetof(T, si)));
1434   __ sw(a7, MemOperand(a0, offsetof(T, r4)));
1435 
1436   // lb with negative data.
1437   __ lb(t0, MemOperand(a0, offsetof(T, si)));
1438   __ sw(t0, MemOperand(a0, offsetof(T, r5)));
1439 
1440   // // sh writes only 1/2 of word.
1441   __ lui(t1, 0x3333);
1442   __ ori(t1, t1, 0x3333);
1443   __ sw(t1, MemOperand(a0, offsetof(T, r6)));
1444   __ lhu(t1, MemOperand(a0, offsetof(T, si)));
1445   __ sh(t1, MemOperand(a0, offsetof(T, r6)));
1446 
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;
1463   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
1464   USE(dummy);
1465 
1466   // Unsigned data, 32 & 64.
1467   CHECK_EQ(static_cast<int64_t>(0x1111111144332211L), t.r1);
1468   CHECK_EQ(static_cast<int64_t>(0x0000000000002211L), t.r2);
1469 
1470   // Signed data, 32 & 64.
1471   CHECK_EQ(static_cast<int64_t>(0x33333333ffffbbccL), t.r3);
1472   CHECK_EQ(static_cast<int64_t>(0xffffffff0000bbccL), t.r4);
1473 
1474   // Signed data, 32 & 64.
1475   CHECK_EQ(static_cast<int64_t>(0x55555555ffffffccL), t.r5);
1476   CHECK_EQ(static_cast<int64_t>(0x000000003333bbccL), t.r6);
1477 }
1478 
1479 
1480 // ----------------------mips64r6 specific tests----------------------
TEST(seleqz_selnez)1481 TEST(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 
TEST(min_max)1584 TEST(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 
TEST(rint_d)1661 TEST(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 
TEST(sel)1766 TEST(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 
TEST(rint_s)1840 TEST(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 
TEST(mina_maxa)1947 TEST(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----------------------
TEST(trunc_l)2048 TEST(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 
TEST(movz_movn)2121 TEST(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 
TEST(movt_movd)2208 TEST(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--------------------------
TEST(cvt_w_d)2307 TEST(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 
TEST(trunc_w)2384 TEST(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 
TEST(round_w)2454 TEST(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 
TEST(round_l)2523 TEST(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 
TEST(sub)2595 TEST(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 
TEST(sqrt_rsqrt_recip)2664 TEST(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 
TEST(neg)2760 TEST(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 
TEST(mul)2814 TEST(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 
TEST(mov)2873 TEST(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 
TEST(floor_w)2927 TEST(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 
TEST(floor_l)2997 TEST(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 
TEST(ceil_w)3069 TEST(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 
TEST(ceil_l)3139 TEST(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 
TEST(jump_tables1)3211 TEST(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 
TEST(jump_tables2)3277 TEST(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 
TEST(jump_tables3)3347 TEST(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 
TEST(BITSWAP)3431 TEST(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 
TEST(class_fmt)3507 TEST(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 
TEST(ABS)3685 TEST(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 
TEST(ADD_FMT)3783 TEST(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 
TEST(C_COND_FMT)3852 TEST(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 
TEST(CMP_COND_FMT)4064 TEST(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 
TEST(CVT)4282 TEST(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 
TEST(DIV_FMT)4480 TEST(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 
run_align(uint64_t rs_value,uint64_t rt_value,uint8_t bp)4600 uint64_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 
TEST(r6_align)4624 TEST(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 
run_dalign(uint64_t rs_value,uint64_t rt_value,uint8_t bp)4653 uint64_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 
TEST(r6_dalign)4676 TEST(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 
4709 uint64_t PC;  // The program counter.
4710 
run_aluipc(int16_t offset)4711 uint64_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 
TEST(r6_aluipc)4736 TEST(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 
run_auipc(int16_t offset)4765 uint64_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 
TEST(r6_auipc)4790 TEST(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 
run_aui(uint64_t rs,uint16_t offset)4819 uint64_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 
run_daui(uint64_t rs,uint16_t offset)4845 uint64_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 
run_dahi(uint64_t rs,uint16_t offset)4871 uint64_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 
run_dati(uint64_t rs,uint16_t offset)4897 uint64_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 
TEST(r6_aui_family)4923 TEST(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 
run_lwpc(int offset)5000 uint64_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 
TEST(r6_lwpc)5046 TEST(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 
run_lwupc(int offset)5076 uint64_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 
TEST(r6_lwupc)5122 TEST(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 
run_jic(int16_t offset)5152 uint64_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 
TEST(r6_jic)5206 TEST(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 
run_beqzc(int32_t value,int32_t offset)5233 uint64_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 
TEST(r6_beqzc)5278 TEST(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 
run_jialc(int16_t offset)5306 uint64_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 
TEST(r6_jialc)5372 TEST(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 
run_addiupc(int32_t imm19)5400 uint64_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 
TEST(r6_addiupc)5425 TEST(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 
run_ldpc(int offset)5454 uint64_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 
TEST(r6_ldpc)5500 TEST(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 
run_bc(int32_t offset)5529 int64_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 
TEST(r6_bc)5582 TEST(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 
run_balc(int32_t offset)5609 int64_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 
TEST(r6_balc)5664 TEST(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 
run_dsll(uint64_t rt_value,uint16_t sa_value)5690 uint64_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 
TEST(dsll)5714 TEST(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 
run_bal(int16_t offset)5738 uint64_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 
TEST(bal)5770 TEST(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 
TEST(Trampoline)5790 TEST(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 
5822 #undef __
5823