cd1d5d6cc7df222991e420de9a661ce9a6035882
[platform/framework/web/crosswalk.git] / src / v8 / test / cctest / test-assembler-mips.cc
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 "src/v8.h"
29
30 #include "src/disassembler.h"
31 #include "src/factory.h"
32 #include "src/macro-assembler.h"
33 #include "src/mips/macro-assembler-mips.h"
34 #include "src/mips/simulator-mips.h"
35
36 #include "test/cctest/cctest.h"
37
38 using namespace v8::internal;
39
40
41 // Define these function prototypes to match JSEntryFunction in execution.cc.
42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
43 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
45
46
47 #define __ assm.
48
49
50 TEST(MIPS0) {
51   CcTest::InitializeVM();
52   Isolate* isolate = CcTest::i_isolate();
53   HandleScope scope(isolate);
54
55   MacroAssembler assm(isolate, NULL, 0);
56
57   // Addition.
58   __ addu(v0, a0, a1);
59   __ jr(ra);
60   __ nop();
61
62   CodeDesc desc;
63   assm.GetCode(&desc);
64   Handle<Code> code = isolate->factory()->NewCode(
65       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
66   F2 f = FUNCTION_CAST<F2>(code->entry());
67   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
68   ::printf("f() = %d\n", res);
69   CHECK_EQ(0xabc, res);
70 }
71
72
73 TEST(MIPS1) {
74   CcTest::InitializeVM();
75   Isolate* isolate = CcTest::i_isolate();
76   HandleScope scope(isolate);
77
78   MacroAssembler assm(isolate, NULL, 0);
79   Label L, C;
80
81   __ mov(a1, a0);
82   __ li(v0, 0);
83   __ b(&C);
84   __ nop();
85
86   __ bind(&L);
87   __ addu(v0, v0, a1);
88   __ addiu(a1, a1, -1);
89
90   __ bind(&C);
91   __ xori(v1, a1, 0);
92   __ Branch(&L, ne, v1, Operand(0));
93   __ nop();
94
95   __ jr(ra);
96   __ nop();
97
98   CodeDesc desc;
99   assm.GetCode(&desc);
100   Handle<Code> code = isolate->factory()->NewCode(
101       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
102   F1 f = FUNCTION_CAST<F1>(code->entry());
103   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
104   ::printf("f() = %d\n", res);
105   CHECK_EQ(1275, res);
106 }
107
108
109 TEST(MIPS2) {
110   CcTest::InitializeVM();
111   Isolate* isolate = CcTest::i_isolate();
112   HandleScope scope(isolate);
113
114   MacroAssembler assm(isolate, NULL, 0);
115
116   Label exit, error;
117
118   // ----- Test all instructions.
119
120   // Test lui, ori, and addiu, used in the li pseudo-instruction.
121   // This way we can then safely load registers with chosen values.
122
123   __ ori(t0, zero_reg, 0);
124   __ lui(t0, 0x1234);
125   __ ori(t0, t0, 0);
126   __ ori(t0, t0, 0x0f0f);
127   __ ori(t0, t0, 0xf0f0);
128   __ addiu(t1, t0, 1);
129   __ addiu(t2, t1, -0x10);
130
131   // Load values in temporary registers.
132   __ li(t0, 0x00000004);
133   __ li(t1, 0x00001234);
134   __ li(t2, 0x12345678);
135   __ li(t3, 0x7fffffff);
136   __ li(t4, 0xfffffffc);
137   __ li(t5, 0xffffedcc);
138   __ li(t6, 0xedcba988);
139   __ li(t7, 0x80000000);
140
141   // SPECIAL class.
142   __ srl(v0, t2, 8);    // 0x00123456
143   __ sll(v0, v0, 11);   // 0x91a2b000
144   __ sra(v0, v0, 3);    // 0xf2345600
145   __ srav(v0, v0, t0);  // 0xff234560
146   __ sllv(v0, v0, t0);  // 0xf2345600
147   __ srlv(v0, v0, t0);  // 0x0f234560
148   __ Branch(&error, ne, v0, Operand(0x0f234560));
149   __ nop();
150
151   __ addu(v0, t0, t1);   // 0x00001238
152   __ subu(v0, v0, t0);  // 0x00001234
153   __ Branch(&error, ne, v0, Operand(0x00001234));
154   __ nop();
155   __ addu(v1, t3, t0);
156   __ Branch(&error, ne, v1, Operand(0x80000003));
157   __ nop();
158   __ subu(v1, t7, t0);  // 0x7ffffffc
159   __ Branch(&error, ne, v1, Operand(0x7ffffffc));
160   __ nop();
161
162   __ and_(v0, t1, t2);  // 0x00001230
163   __ or_(v0, v0, t1);   // 0x00001234
164   __ xor_(v0, v0, t2);  // 0x1234444c
165   __ nor(v0, v0, t2);   // 0xedcba987
166   __ Branch(&error, ne, v0, Operand(0xedcba983));
167   __ nop();
168
169   __ slt(v0, t7, t3);
170   __ Branch(&error, ne, v0, Operand(0x1));
171   __ nop();
172   __ sltu(v0, t7, t3);
173   __ Branch(&error, ne, v0, Operand(0x0));
174   __ nop();
175   // End of SPECIAL class.
176
177   __ addiu(v0, zero_reg, 0x7421);  // 0x00007421
178   __ addiu(v0, v0, -0x1);  // 0x00007420
179   __ addiu(v0, v0, -0x20);  // 0x00007400
180   __ Branch(&error, ne, v0, Operand(0x00007400));
181   __ nop();
182   __ addiu(v1, t3, 0x1);  // 0x80000000
183   __ Branch(&error, ne, v1, Operand(0x80000000));
184   __ nop();
185
186   __ slti(v0, t1, 0x00002000);  // 0x1
187   __ slti(v0, v0, 0xffff8000);  // 0x0
188   __ Branch(&error, ne, v0, Operand(0x0));
189   __ nop();
190   __ sltiu(v0, t1, 0x00002000);  // 0x1
191   __ sltiu(v0, v0, 0x00008000);  // 0x1
192   __ Branch(&error, ne, v0, Operand(0x1));
193   __ nop();
194
195   __ andi(v0, t1, 0xf0f0);  // 0x00001030
196   __ ori(v0, v0, 0x8a00);  // 0x00009a30
197   __ xori(v0, v0, 0x83cc);  // 0x000019fc
198   __ Branch(&error, ne, v0, Operand(0x000019fc));
199   __ nop();
200   __ lui(v1, 0x8123);  // 0x81230000
201   __ Branch(&error, ne, v1, Operand(0x81230000));
202   __ nop();
203
204   // Bit twiddling instructions & conditional moves.
205   // Uses t0-t7 as set above.
206   __ Clz(v0, t0);       // 29
207   __ Clz(v1, t1);       // 19
208   __ addu(v0, v0, v1);  // 48
209   __ Clz(v1, t2);       // 3
210   __ addu(v0, v0, v1);  // 51
211   __ Clz(v1, t7);       // 0
212   __ addu(v0, v0, v1);  // 51
213   __ Branch(&error, ne, v0, Operand(51));
214   __ Movn(a0, t3, t0);  // Move a0<-t3 (t0 is NOT 0).
215   __ Ins(a0, t1, 12, 8);  // 0x7ff34fff
216   __ Branch(&error, ne, a0, Operand(0x7ff34fff));
217   __ Movz(a0, t6, t7);    // a0 not updated (t7 is NOT 0).
218   __ Ext(a1, a0, 8, 12);  // 0x34f
219   __ Branch(&error, ne, a1, Operand(0x34f));
220   __ Movz(a0, t6, v1);    // a0<-t6, v0 is 0, from 8 instr back.
221   __ Branch(&error, ne, a0, Operand(t6));
222
223   // Everything was correctly executed. Load the expected result.
224   __ li(v0, 0x31415926);
225   __ b(&exit);
226   __ nop();
227
228   __ bind(&error);
229   // Got an error. Return a wrong result.
230   __ li(v0, 666);
231
232   __ bind(&exit);
233   __ jr(ra);
234   __ nop();
235
236   CodeDesc desc;
237   assm.GetCode(&desc);
238   Handle<Code> code = isolate->factory()->NewCode(
239       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
240   F2 f = FUNCTION_CAST<F2>(code->entry());
241   int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
242   ::printf("f() = %d\n", res);
243   CHECK_EQ(0x31415926, res);
244 }
245
246
247 TEST(MIPS3) {
248   // Test floating point instructions.
249   CcTest::InitializeVM();
250   Isolate* isolate = CcTest::i_isolate();
251   HandleScope scope(isolate);
252
253   typedef struct {
254     double a;
255     double b;
256     double c;
257     double d;
258     double e;
259     double f;
260     double g;
261     double h;
262     double i;
263   } T;
264   T t;
265
266   // Create a function that accepts &t, and loads, manipulates, and stores
267   // the doubles t.a ... t.f.
268   MacroAssembler assm(isolate, NULL, 0);
269   Label L, C;
270
271   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
272   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
273   __ add_d(f8, f4, f6);
274   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) );  // c = a + b.
275
276   __ mov_d(f10, f8);  // c
277   __ neg_d(f12, f6);  // -b
278   __ sub_d(f10, f10, f12);
279   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) );  // d = c - (-b).
280
281   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) );   // b = a.
282
283   __ li(t0, 120);
284   __ mtc1(t0, f14);
285   __ cvt_d_w(f14, f14);   // f14 = 120.0.
286   __ mul_d(f10, f10, f14);
287   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) );  // e = d * 120 = 1.8066e16.
288
289   __ div_d(f12, f10, f4);
290   __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) );  // f = e / a = 120.44.
291
292   __ sqrt_d(f14, f12);
293   __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
294   // g = sqrt(f) = 10.97451593465515908537
295
296   if (kArchVariant == kMips32r2) {
297     __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) );
298     __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) );
299     __ madd_d(f14, f6, f4, f6);
300     __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) );
301   }
302
303   __ jr(ra);
304   __ nop();
305
306   CodeDesc desc;
307   assm.GetCode(&desc);
308   Handle<Code> code = isolate->factory()->NewCode(
309       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
310   F3 f = FUNCTION_CAST<F3>(code->entry());
311   t.a = 1.5e14;
312   t.b = 2.75e11;
313   t.c = 0.0;
314   t.d = 0.0;
315   t.e = 0.0;
316   t.f = 0.0;
317   t.h = 1.5;
318   t.i = 2.75;
319   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
320   USE(dummy);
321   CHECK_EQ(1.5e14, t.a);
322   CHECK_EQ(1.5e14, t.b);
323   CHECK_EQ(1.50275e14, t.c);
324   CHECK_EQ(1.50550e14, t.d);
325   CHECK_EQ(1.8066e16, t.e);
326   CHECK_EQ(120.44, t.f);
327   CHECK_EQ(10.97451593465515908537, t.g);
328   if (kArchVariant == kMips32r2) {
329     CHECK_EQ(6.875, t.h);
330   }
331 }
332
333
334 TEST(MIPS4) {
335   // Test moves between floating point and integer registers.
336   CcTest::InitializeVM();
337   Isolate* isolate = CcTest::i_isolate();
338   HandleScope scope(isolate);
339
340   typedef struct {
341     double a;
342     double b;
343     double c;
344   } T;
345   T t;
346
347   Assembler assm(isolate, NULL, 0);
348   Label L, C;
349
350   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
351   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
352
353   // Swap f4 and f6, by using four integer registers, t0-t3.
354   __ mfc1(t0, f4);
355   __ mfc1(t1, f5);
356   __ mfc1(t2, f6);
357   __ mfc1(t3, f7);
358
359   __ mtc1(t0, f6);
360   __ mtc1(t1, f7);
361   __ mtc1(t2, f4);
362   __ mtc1(t3, f5);
363
364   // Store the swapped f4 and f5 back to memory.
365   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
366   __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
367
368   __ jr(ra);
369   __ nop();
370
371   CodeDesc desc;
372   assm.GetCode(&desc);
373   Handle<Code> code = isolate->factory()->NewCode(
374       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
375   F3 f = FUNCTION_CAST<F3>(code->entry());
376   t.a = 1.5e22;
377   t.b = 2.75e11;
378   t.c = 17.17;
379   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
380   USE(dummy);
381
382   CHECK_EQ(2.75e11, t.a);
383   CHECK_EQ(2.75e11, t.b);
384   CHECK_EQ(1.5e22, t.c);
385 }
386
387
388 TEST(MIPS5) {
389   // Test conversions between doubles and integers.
390   CcTest::InitializeVM();
391   Isolate* isolate = CcTest::i_isolate();
392   HandleScope scope(isolate);
393
394   typedef struct {
395     double a;
396     double b;
397     int i;
398     int j;
399   } T;
400   T t;
401
402   Assembler assm(isolate, NULL, 0);
403   Label L, C;
404
405   // Load all structure elements to registers.
406   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
407   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
408   __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
409   __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
410
411   // Convert double in f4 to int in element i.
412   __ cvt_w_d(f8, f4);
413   __ mfc1(t2, f8);
414   __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
415
416   // Convert double in f6 to int in element j.
417   __ cvt_w_d(f10, f6);
418   __ mfc1(t3, f10);
419   __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
420
421   // Convert int in original i (t0) to double in a.
422   __ mtc1(t0, f12);
423   __ cvt_d_w(f0, f12);
424   __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
425
426   // Convert int in original j (t1) to double in b.
427   __ mtc1(t1, f14);
428   __ cvt_d_w(f2, f14);
429   __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
430
431   __ jr(ra);
432   __ nop();
433
434   CodeDesc desc;
435   assm.GetCode(&desc);
436   Handle<Code> code = isolate->factory()->NewCode(
437       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
438   F3 f = FUNCTION_CAST<F3>(code->entry());
439   t.a = 1.5e4;
440   t.b = 2.75e8;
441   t.i = 12345678;
442   t.j = -100000;
443   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
444   USE(dummy);
445
446   CHECK_EQ(12345678.0, t.a);
447   CHECK_EQ(-100000.0, t.b);
448   CHECK_EQ(15000, t.i);
449   CHECK_EQ(275000000, t.j);
450 }
451
452
453 TEST(MIPS6) {
454   // Test simple memory loads and stores.
455   CcTest::InitializeVM();
456   Isolate* isolate = CcTest::i_isolate();
457   HandleScope scope(isolate);
458
459   typedef struct {
460     uint32_t ui;
461     int32_t si;
462     int32_t r1;
463     int32_t r2;
464     int32_t r3;
465     int32_t r4;
466     int32_t r5;
467     int32_t r6;
468   } T;
469   T t;
470
471   Assembler assm(isolate, NULL, 0);
472   Label L, C;
473
474   // Basic word load/store.
475   __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
476   __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
477
478   // lh with positive data.
479   __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
480   __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
481
482   // lh with negative data.
483   __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
484   __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
485
486   // lhu with negative data.
487   __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
488   __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
489
490   // lb with negative data.
491   __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
492   __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
493
494   // sh writes only 1/2 of word.
495   __ lui(t5, 0x3333);
496   __ ori(t5, t5, 0x3333);
497   __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
498   __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
499   __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
500
501   __ jr(ra);
502   __ nop();
503
504   CodeDesc desc;
505   assm.GetCode(&desc);
506   Handle<Code> code = isolate->factory()->NewCode(
507       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
508   F3 f = FUNCTION_CAST<F3>(code->entry());
509   t.ui = 0x11223344;
510   t.si = 0x99aabbcc;
511   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
512   USE(dummy);
513
514   CHECK_EQ(0x11223344, t.r1);
515 #if __BYTE_ORDER == __LITTLE_ENDIAN
516   CHECK_EQ(0x3344, t.r2);
517   CHECK_EQ(0xffffbbcc, t.r3);
518   CHECK_EQ(0x0000bbcc, t.r4);
519   CHECK_EQ(0xffffffcc, t.r5);
520   CHECK_EQ(0x3333bbcc, t.r6);
521 #elif __BYTE_ORDER == __BIG_ENDIAN
522   CHECK_EQ(0x1122, t.r2);
523   CHECK_EQ(0xffff99aa, t.r3);
524   CHECK_EQ(0x000099aa, t.r4);
525   CHECK_EQ(0xffffff99, t.r5);
526   CHECK_EQ(0x99aa3333, t.r6);
527 #else
528 #error Unknown endianness
529 #endif
530 }
531
532
533 TEST(MIPS7) {
534   // Test floating point compare and branch instructions.
535   CcTest::InitializeVM();
536   Isolate* isolate = CcTest::i_isolate();
537   HandleScope scope(isolate);
538
539   typedef struct {
540     double a;
541     double b;
542     double c;
543     double d;
544     double e;
545     double f;
546     int32_t result;
547   } T;
548   T t;
549
550   // Create a function that accepts &t, and loads, manipulates, and stores
551   // the doubles t.a ... t.f.
552   MacroAssembler assm(isolate, NULL, 0);
553   Label neither_is_nan, less_than, outa_here;
554
555   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
556   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
557   __ c(UN, D, f4, f6);
558   __ bc1f(&neither_is_nan);
559   __ nop();
560   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
561   __ Branch(&outa_here);
562
563   __ bind(&neither_is_nan);
564
565   if (kArchVariant == kLoongson) {
566     __ c(OLT, D, f6, f4);
567     __ bc1t(&less_than);
568   } else {
569     __ c(OLT, D, f6, f4, 2);
570     __ bc1t(&less_than, 2);
571   }
572   __ nop();
573   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
574   __ Branch(&outa_here);
575
576   __ bind(&less_than);
577   __ Addu(t0, zero_reg, Operand(1));
578   __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) );  // Set true.
579
580
581   // This test-case should have additional tests.
582
583   __ bind(&outa_here);
584
585   __ jr(ra);
586   __ nop();
587
588   CodeDesc desc;
589   assm.GetCode(&desc);
590   Handle<Code> code = isolate->factory()->NewCode(
591       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
592   F3 f = FUNCTION_CAST<F3>(code->entry());
593   t.a = 1.5e14;
594   t.b = 2.75e11;
595   t.c = 2.0;
596   t.d = -4.0;
597   t.e = 0.0;
598   t.f = 0.0;
599   t.result = 0;
600   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
601   USE(dummy);
602   CHECK_EQ(1.5e14, t.a);
603   CHECK_EQ(2.75e11, t.b);
604   CHECK_EQ(1, t.result);
605 }
606
607
608 TEST(MIPS8) {
609   // Test ROTR and ROTRV instructions.
610   CcTest::InitializeVM();
611   Isolate* isolate = CcTest::i_isolate();
612   HandleScope scope(isolate);
613
614   typedef struct {
615     int32_t input;
616     int32_t result_rotr_4;
617     int32_t result_rotr_8;
618     int32_t result_rotr_12;
619     int32_t result_rotr_16;
620     int32_t result_rotr_20;
621     int32_t result_rotr_24;
622     int32_t result_rotr_28;
623     int32_t result_rotrv_4;
624     int32_t result_rotrv_8;
625     int32_t result_rotrv_12;
626     int32_t result_rotrv_16;
627     int32_t result_rotrv_20;
628     int32_t result_rotrv_24;
629     int32_t result_rotrv_28;
630   } T;
631   T t;
632
633   MacroAssembler assm(isolate, NULL, 0);
634
635   // Basic word load.
636   __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
637
638   // ROTR instruction (called through the Ror macro).
639   __ Ror(t1, t0, 0x0004);
640   __ Ror(t2, t0, 0x0008);
641   __ Ror(t3, t0, 0x000c);
642   __ Ror(t4, t0, 0x0010);
643   __ Ror(t5, t0, 0x0014);
644   __ Ror(t6, t0, 0x0018);
645   __ Ror(t7, t0, 0x001c);
646
647   // Basic word store.
648   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
649   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
650   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
651   __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
652   __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
653   __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
654   __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
655
656   // ROTRV instruction (called through the Ror macro).
657   __ li(t7, 0x0004);
658   __ Ror(t1, t0, t7);
659   __ li(t7, 0x0008);
660   __ Ror(t2, t0, t7);
661   __ li(t7, 0x000C);
662   __ Ror(t3, t0, t7);
663   __ li(t7, 0x0010);
664   __ Ror(t4, t0, t7);
665   __ li(t7, 0x0014);
666   __ Ror(t5, t0, t7);
667   __ li(t7, 0x0018);
668   __ Ror(t6, t0, t7);
669   __ li(t7, 0x001C);
670   __ Ror(t7, t0, t7);
671
672   // Basic word store.
673   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
674   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
675   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
676   __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
677   __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
678   __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
679   __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
680
681   __ jr(ra);
682   __ nop();
683
684   CodeDesc desc;
685   assm.GetCode(&desc);
686   Handle<Code> code = isolate->factory()->NewCode(
687       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
688   F3 f = FUNCTION_CAST<F3>(code->entry());
689   t.input = 0x12345678;
690   Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
691   USE(dummy);
692   CHECK_EQ(0x81234567, t.result_rotr_4);
693   CHECK_EQ(0x78123456, t.result_rotr_8);
694   CHECK_EQ(0x67812345, t.result_rotr_12);
695   CHECK_EQ(0x56781234, t.result_rotr_16);
696   CHECK_EQ(0x45678123, t.result_rotr_20);
697   CHECK_EQ(0x34567812, t.result_rotr_24);
698   CHECK_EQ(0x23456781, t.result_rotr_28);
699
700   CHECK_EQ(0x81234567, t.result_rotrv_4);
701   CHECK_EQ(0x78123456, t.result_rotrv_8);
702   CHECK_EQ(0x67812345, t.result_rotrv_12);
703   CHECK_EQ(0x56781234, t.result_rotrv_16);
704   CHECK_EQ(0x45678123, t.result_rotrv_20);
705   CHECK_EQ(0x34567812, t.result_rotrv_24);
706   CHECK_EQ(0x23456781, t.result_rotrv_28);
707 }
708
709
710 TEST(MIPS9) {
711   // Test BRANCH improvements.
712   CcTest::InitializeVM();
713   Isolate* isolate = CcTest::i_isolate();
714   HandleScope scope(isolate);
715
716   MacroAssembler assm(isolate, NULL, 0);
717   Label exit, exit2, exit3;
718
719   __ Branch(&exit, ge, a0, Operand(0x00000000));
720   __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
721   __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
722
723   __ bind(&exit);
724   __ bind(&exit2);
725   __ bind(&exit3);
726   __ jr(ra);
727   __ nop();
728
729   CodeDesc desc;
730   assm.GetCode(&desc);
731   isolate->factory()->NewCode(
732       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
733 }
734
735
736 TEST(MIPS10) {
737   // Test conversions between doubles and long integers.
738   // Test hos the long ints map to FP regs pairs.
739   CcTest::InitializeVM();
740   Isolate* isolate = CcTest::i_isolate();
741   HandleScope scope(isolate);
742
743   typedef struct {
744     double a;
745     double b;
746     int32_t dbl_mant;
747     int32_t dbl_exp;
748     int32_t word;
749     int32_t b_word;
750   } T;
751   T t;
752
753   Assembler assm(isolate, NULL, 0);
754   Label L, C;
755
756   if (kArchVariant == kMips32r2) {
757     // Load all structure elements to registers.
758     __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
759
760     // Save the raw bits of the double.
761     __ mfc1(t0, f0);
762     __ mfc1(t1, f1);
763     __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
764     __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
765
766     // Convert double in f0 to long, save hi/lo parts.
767     __ cvt_w_d(f0, f0);
768     __ mfc1(t0, f0);  // f0 has a 32-bits word.
769     __ sw(t0, MemOperand(a0, OFFSET_OF(T, word)));
770
771     // Convert the b long integers to double b.
772     __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_word)));
773     __ mtc1(t0, f8);  // f8 has a 32-bits word.
774     __ cvt_d_w(f10, f8);
775     __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
776
777     __ jr(ra);
778     __ nop();
779
780     CodeDesc desc;
781     assm.GetCode(&desc);
782     Handle<Code> code = isolate->factory()->NewCode(
783         desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
784     F3 f = FUNCTION_CAST<F3>(code->entry());
785     t.a = 2.147483646e+09;       // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double.
786     t.b_word = 0x0ff00ff0;       // 0x0FF00FF0 -> 0x as double.
787     Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
788     USE(dummy);
789
790     CHECK_EQ(0x41DFFFFF, t.dbl_exp);
791     CHECK_EQ(0xFF800000, t.dbl_mant);
792     CHECK_EQ(0X7FFFFFFE, t.word);
793     // 0x0FF00FF0 -> 2.6739096+e08
794     CHECK_EQ(2.6739096e08, t.b);
795   }
796 }
797
798
799 TEST(MIPS11) {
800   // Test LWL, LWR, SWL and SWR instructions.
801   CcTest::InitializeVM();
802   Isolate* isolate = CcTest::i_isolate();
803   HandleScope scope(isolate);
804
805   typedef struct {
806     int32_t reg_init;
807     int32_t mem_init;
808     int32_t lwl_0;
809     int32_t lwl_1;
810     int32_t lwl_2;
811     int32_t lwl_3;
812     int32_t lwr_0;
813     int32_t lwr_1;
814     int32_t lwr_2;
815     int32_t lwr_3;
816     int32_t swl_0;
817     int32_t swl_1;
818     int32_t swl_2;
819     int32_t swl_3;
820     int32_t swr_0;
821     int32_t swr_1;
822     int32_t swr_2;
823     int32_t swr_3;
824   } T;
825   T t;
826
827   Assembler assm(isolate, NULL, 0);
828
829   // Test all combinations of LWL and vAddr.
830   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
831   __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
832   __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
833
834   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
835   __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
836   __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
837
838   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
839   __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
840   __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
841
842   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
843   __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
844   __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
845
846   // Test all combinations of LWR and vAddr.
847   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
848   __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
849   __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
850
851   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
852   __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
853   __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
854
855   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
856   __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
857   __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
858
859   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
860   __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
861   __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
862
863   // Test all combinations of SWL and vAddr.
864   __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
865   __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
866   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
867   __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
868
869   __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
870   __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
871   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
872   __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
873
874   __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
875   __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
876   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
877   __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
878
879   __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
880   __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
881   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
882   __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
883
884   // Test all combinations of SWR and vAddr.
885   __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
886   __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
887   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
888   __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
889
890   __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
891   __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
892   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
893   __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
894
895   __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
896   __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
897   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
898   __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
899
900   __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
901   __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
902   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
903   __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
904
905   __ jr(ra);
906   __ nop();
907
908   CodeDesc desc;
909   assm.GetCode(&desc);
910   Handle<Code> code = isolate->factory()->NewCode(
911       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
912   F3 f = FUNCTION_CAST<F3>(code->entry());
913   t.reg_init = 0xaabbccdd;
914   t.mem_init = 0x11223344;
915
916   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
917   USE(dummy);
918
919 #if __BYTE_ORDER == __LITTLE_ENDIAN
920   CHECK_EQ(0x44bbccdd, t.lwl_0);
921   CHECK_EQ(0x3344ccdd, t.lwl_1);
922   CHECK_EQ(0x223344dd, t.lwl_2);
923   CHECK_EQ(0x11223344, t.lwl_3);
924
925   CHECK_EQ(0x11223344, t.lwr_0);
926   CHECK_EQ(0xaa112233, t.lwr_1);
927   CHECK_EQ(0xaabb1122, t.lwr_2);
928   CHECK_EQ(0xaabbcc11, t.lwr_3);
929
930   CHECK_EQ(0x112233aa, t.swl_0);
931   CHECK_EQ(0x1122aabb, t.swl_1);
932   CHECK_EQ(0x11aabbcc, t.swl_2);
933   CHECK_EQ(0xaabbccdd, t.swl_3);
934
935   CHECK_EQ(0xaabbccdd, t.swr_0);
936   CHECK_EQ(0xbbccdd44, t.swr_1);
937   CHECK_EQ(0xccdd3344, t.swr_2);
938   CHECK_EQ(0xdd223344, t.swr_3);
939 #elif __BYTE_ORDER == __BIG_ENDIAN
940   CHECK_EQ(0x11223344, t.lwl_0);
941   CHECK_EQ(0x223344dd, t.lwl_1);
942   CHECK_EQ(0x3344ccdd, t.lwl_2);
943   CHECK_EQ(0x44bbccdd, t.lwl_3);
944
945   CHECK_EQ(0xaabbcc11, t.lwr_0);
946   CHECK_EQ(0xaabb1122, t.lwr_1);
947   CHECK_EQ(0xaa112233, t.lwr_2);
948   CHECK_EQ(0x11223344, t.lwr_3);
949
950   CHECK_EQ(0xaabbccdd, t.swl_0);
951   CHECK_EQ(0x11aabbcc, t.swl_1);
952   CHECK_EQ(0x1122aabb, t.swl_2);
953   CHECK_EQ(0x112233aa, t.swl_3);
954
955   CHECK_EQ(0xdd223344, t.swr_0);
956   CHECK_EQ(0xccdd3344, t.swr_1);
957   CHECK_EQ(0xbbccdd44, t.swr_2);
958   CHECK_EQ(0xaabbccdd, t.swr_3);
959 #else
960 #error Unknown endianness
961 #endif
962 }
963
964
965 TEST(MIPS12) {
966   CcTest::InitializeVM();
967   Isolate* isolate = CcTest::i_isolate();
968   HandleScope scope(isolate);
969
970   typedef struct {
971       int32_t  x;
972       int32_t  y;
973       int32_t  y1;
974       int32_t  y2;
975       int32_t  y3;
976       int32_t  y4;
977   } T;
978   T t;
979
980   MacroAssembler assm(isolate, NULL, 0);
981
982   __ mov(t6, fp);  // Save frame pointer.
983   __ mov(fp, a0);  // Access struct T by fp.
984   __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
985   __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
986
987   __ addu(t1, t0, t3);
988   __ subu(t4, t0, t3);
989   __ nop();
990   __ push(t0);  // These instructions disappear after opt.
991   __ Pop();
992   __ addu(t0, t0, t0);
993   __ nop();
994   __ Pop();     // These instructions disappear after opt.
995   __ push(t3);
996   __ nop();
997   __ push(t3);  // These instructions disappear after opt.
998   __ pop(t3);
999   __ nop();
1000   __ push(t3);
1001   __ pop(t4);
1002   __ nop();
1003   __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1004   __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1005   __ nop();
1006   __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1007   __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1008   __ nop();
1009   __ push(t1);
1010   __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1011   __ pop(t1);
1012   __ nop();
1013   __ push(t1);
1014   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1015   __ pop(t1);
1016   __ nop();
1017   __ push(t1);
1018   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1019   __ pop(t2);
1020   __ nop();
1021   __ push(t2);
1022   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1023   __ pop(t1);
1024   __ nop();
1025   __ push(t1);
1026   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1027   __ pop(t3);
1028   __ nop();
1029
1030   __ mov(fp, t6);
1031   __ jr(ra);
1032   __ nop();
1033
1034   CodeDesc desc;
1035   assm.GetCode(&desc);
1036   Handle<Code> code = isolate->factory()->NewCode(
1037       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1038   F3 f = FUNCTION_CAST<F3>(code->entry());
1039   t.x = 1;
1040   t.y = 2;
1041   t.y1 = 3;
1042   t.y2 = 4;
1043   t.y3 = 0XBABA;
1044   t.y4 = 0xDEDA;
1045
1046   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1047   USE(dummy);
1048
1049   CHECK_EQ(3, t.y1);
1050 }
1051
1052
1053 TEST(MIPS13) {
1054   // Test Cvt_d_uw and Trunc_uw_d macros.
1055   CcTest::InitializeVM();
1056   Isolate* isolate = CcTest::i_isolate();
1057   HandleScope scope(isolate);
1058
1059   typedef struct {
1060     double cvt_big_out;
1061     double cvt_small_out;
1062     uint32_t trunc_big_out;
1063     uint32_t trunc_small_out;
1064     uint32_t cvt_big_in;
1065     uint32_t cvt_small_in;
1066   } T;
1067   T t;
1068
1069   MacroAssembler assm(isolate, NULL, 0);
1070
1071   __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1072   __ Cvt_d_uw(f10, t0, f22);
1073   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1074
1075   __ Trunc_uw_d(f10, f10, f22);
1076   __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1077
1078   __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1079   __ Cvt_d_uw(f8, t0, f22);
1080   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1081
1082   __ Trunc_uw_d(f8, f8, f22);
1083   __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1084
1085   __ jr(ra);
1086   __ nop();
1087
1088   CodeDesc desc;
1089   assm.GetCode(&desc);
1090   Handle<Code> code = isolate->factory()->NewCode(
1091       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1092   F3 f = FUNCTION_CAST<F3>(code->entry());
1093
1094   t.cvt_big_in = 0xFFFFFFFF;
1095   t.cvt_small_in  = 333;
1096
1097   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1098   USE(dummy);
1099
1100   CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1101   CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1102
1103   CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1104   CHECK_EQ(static_cast<int>(t.trunc_small_out),
1105            static_cast<int>(t.cvt_small_in));
1106 }
1107
1108
1109 TEST(MIPS14) {
1110   // Test round, floor, ceil, trunc, cvt.
1111   CcTest::InitializeVM();
1112   Isolate* isolate = CcTest::i_isolate();
1113   HandleScope scope(isolate);
1114
1115 #define ROUND_STRUCT_ELEMENT(x) \
1116   int32_t x##_up_out; \
1117   int32_t x##_down_out; \
1118   int32_t neg_##x##_up_out; \
1119   int32_t neg_##x##_down_out; \
1120   uint32_t x##_err1_out; \
1121   uint32_t x##_err2_out; \
1122   uint32_t x##_err3_out; \
1123   uint32_t x##_err4_out; \
1124   int32_t x##_invalid_result;
1125
1126   typedef struct {
1127     double round_up_in;
1128     double round_down_in;
1129     double neg_round_up_in;
1130     double neg_round_down_in;
1131     double err1_in;
1132     double err2_in;
1133     double err3_in;
1134     double err4_in;
1135
1136     ROUND_STRUCT_ELEMENT(round)
1137     ROUND_STRUCT_ELEMENT(floor)
1138     ROUND_STRUCT_ELEMENT(ceil)
1139     ROUND_STRUCT_ELEMENT(trunc)
1140     ROUND_STRUCT_ELEMENT(cvt)
1141   } T;
1142   T t;
1143
1144 #undef ROUND_STRUCT_ELEMENT
1145
1146   MacroAssembler assm(isolate, NULL, 0);
1147
1148   // Save FCSR.
1149   __ cfc1(a1, FCSR);
1150   // Disable FPU exceptions.
1151   __ ctc1(zero_reg, FCSR);
1152 #define RUN_ROUND_TEST(x) \
1153   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1154   __ x##_w_d(f0, f0); \
1155   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1156   \
1157   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1158   __ x##_w_d(f0, f0); \
1159   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1160   \
1161   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1162   __ x##_w_d(f0, f0); \
1163   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1164   \
1165   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1166   __ x##_w_d(f0, f0); \
1167   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1168   \
1169   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1170   __ ctc1(zero_reg, FCSR); \
1171   __ x##_w_d(f0, f0); \
1172   __ cfc1(a2, FCSR); \
1173   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1174   \
1175   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1176   __ ctc1(zero_reg, FCSR); \
1177   __ x##_w_d(f0, f0); \
1178   __ cfc1(a2, FCSR); \
1179   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1180   \
1181   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1182   __ ctc1(zero_reg, FCSR); \
1183   __ x##_w_d(f0, f0); \
1184   __ cfc1(a2, FCSR); \
1185   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1186   \
1187   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1188   __ ctc1(zero_reg, FCSR); \
1189   __ x##_w_d(f0, f0); \
1190   __ cfc1(a2, FCSR); \
1191   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1192   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1193
1194   RUN_ROUND_TEST(round)
1195   RUN_ROUND_TEST(floor)
1196   RUN_ROUND_TEST(ceil)
1197   RUN_ROUND_TEST(trunc)
1198   RUN_ROUND_TEST(cvt)
1199
1200   // Restore FCSR.
1201   __ ctc1(a1, FCSR);
1202
1203   __ jr(ra);
1204   __ nop();
1205
1206   CodeDesc desc;
1207   assm.GetCode(&desc);
1208   Handle<Code> code = isolate->factory()->NewCode(
1209       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1210   F3 f = FUNCTION_CAST<F3>(code->entry());
1211
1212   t.round_up_in = 123.51;
1213   t.round_down_in = 123.49;
1214   t.neg_round_up_in = -123.5;
1215   t.neg_round_down_in = -123.49;
1216   t.err1_in = 123.51;
1217   t.err2_in = 1;
1218   t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1219   t.err4_in = NAN;
1220
1221   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1222   USE(dummy);
1223
1224 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1225 #define CHECK_ROUND_RESULT(type) \
1226   CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1227   CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1228   CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1229   CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1230   CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
1231
1232   CHECK_ROUND_RESULT(round);
1233   CHECK_ROUND_RESULT(floor);
1234   CHECK_ROUND_RESULT(ceil);
1235   CHECK_ROUND_RESULT(cvt);
1236 }
1237
1238
1239 TEST(MIPS15) {
1240   // Test chaining of label usages within instructions (issue 1644).
1241   CcTest::InitializeVM();
1242   Isolate* isolate = CcTest::i_isolate();
1243   HandleScope scope(isolate);
1244   Assembler assm(isolate, NULL, 0);
1245
1246   Label target;
1247   __ beq(v0, v1, &target);
1248   __ nop();
1249   __ bne(v0, v1, &target);
1250   __ nop();
1251   __ bind(&target);
1252   __ nop();
1253 }
1254
1255 #undef __