Upstream version 10.39.225.0
[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(zero_reg));
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(zero_reg));
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 (IsMipsArchVariant(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 (IsMipsArchVariant(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   if (!IsFp64Mode()) {
355     __ mfc1(t0, f4);
356     __ mfc1(t1, f5);
357     __ mfc1(t2, f6);
358     __ mfc1(t3, f7);
359
360     __ mtc1(t0, f6);
361     __ mtc1(t1, f7);
362     __ mtc1(t2, f4);
363     __ mtc1(t3, f5);
364   } else {
365     DCHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson));
366     __ mfc1(t0, f4);
367     __ mfhc1(t1, f4);
368     __ mfc1(t2, f6);
369     __ mfhc1(t3, f6);
370
371     __ mtc1(t0, f6);
372     __ mthc1(t1, f6);
373     __ mtc1(t2, f4);
374     __ mthc1(t3, f4);
375   }
376   // Store the swapped f4 and f5 back to memory.
377   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
378   __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
379
380   __ jr(ra);
381   __ nop();
382
383   CodeDesc desc;
384   assm.GetCode(&desc);
385   Handle<Code> code = isolate->factory()->NewCode(
386       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
387   F3 f = FUNCTION_CAST<F3>(code->entry());
388   t.a = 1.5e22;
389   t.b = 2.75e11;
390   t.c = 17.17;
391   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
392   USE(dummy);
393
394   CHECK_EQ(2.75e11, t.a);
395   CHECK_EQ(2.75e11, t.b);
396   CHECK_EQ(1.5e22, t.c);
397 }
398
399
400 TEST(MIPS5) {
401   // Test conversions between doubles and integers.
402   CcTest::InitializeVM();
403   Isolate* isolate = CcTest::i_isolate();
404   HandleScope scope(isolate);
405
406   typedef struct {
407     double a;
408     double b;
409     int i;
410     int j;
411   } T;
412   T t;
413
414   Assembler assm(isolate, NULL, 0);
415   Label L, C;
416
417   // Load all structure elements to registers.
418   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
419   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
420   __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
421   __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
422
423   // Convert double in f4 to int in element i.
424   __ cvt_w_d(f8, f4);
425   __ mfc1(t2, f8);
426   __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
427
428   // Convert double in f6 to int in element j.
429   __ cvt_w_d(f10, f6);
430   __ mfc1(t3, f10);
431   __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
432
433   // Convert int in original i (t0) to double in a.
434   __ mtc1(t0, f12);
435   __ cvt_d_w(f0, f12);
436   __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
437
438   // Convert int in original j (t1) to double in b.
439   __ mtc1(t1, f14);
440   __ cvt_d_w(f2, f14);
441   __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
442
443   __ jr(ra);
444   __ nop();
445
446   CodeDesc desc;
447   assm.GetCode(&desc);
448   Handle<Code> code = isolate->factory()->NewCode(
449       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
450   F3 f = FUNCTION_CAST<F3>(code->entry());
451   t.a = 1.5e4;
452   t.b = 2.75e8;
453   t.i = 12345678;
454   t.j = -100000;
455   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
456   USE(dummy);
457
458   CHECK_EQ(12345678.0, t.a);
459   CHECK_EQ(-100000.0, t.b);
460   CHECK_EQ(15000, t.i);
461   CHECK_EQ(275000000, t.j);
462 }
463
464
465 TEST(MIPS6) {
466   // Test simple memory loads and stores.
467   CcTest::InitializeVM();
468   Isolate* isolate = CcTest::i_isolate();
469   HandleScope scope(isolate);
470
471   typedef struct {
472     uint32_t ui;
473     int32_t si;
474     int32_t r1;
475     int32_t r2;
476     int32_t r3;
477     int32_t r4;
478     int32_t r5;
479     int32_t r6;
480   } T;
481   T t;
482
483   Assembler assm(isolate, NULL, 0);
484   Label L, C;
485
486   // Basic word load/store.
487   __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
488   __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
489
490   // lh with positive data.
491   __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
492   __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
493
494   // lh with negative data.
495   __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
496   __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
497
498   // lhu with negative data.
499   __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
500   __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
501
502   // lb with negative data.
503   __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
504   __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
505
506   // sh writes only 1/2 of word.
507   __ lui(t5, 0x3333);
508   __ ori(t5, t5, 0x3333);
509   __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
510   __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
511   __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
512
513   __ jr(ra);
514   __ nop();
515
516   CodeDesc desc;
517   assm.GetCode(&desc);
518   Handle<Code> code = isolate->factory()->NewCode(
519       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
520   F3 f = FUNCTION_CAST<F3>(code->entry());
521   t.ui = 0x11223344;
522   t.si = 0x99aabbcc;
523   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
524   USE(dummy);
525
526   CHECK_EQ(0x11223344, t.r1);
527 #if __BYTE_ORDER == __LITTLE_ENDIAN
528   CHECK_EQ(0x3344, t.r2);
529   CHECK_EQ(0xffffbbcc, t.r3);
530   CHECK_EQ(0x0000bbcc, t.r4);
531   CHECK_EQ(0xffffffcc, t.r5);
532   CHECK_EQ(0x3333bbcc, t.r6);
533 #elif __BYTE_ORDER == __BIG_ENDIAN
534   CHECK_EQ(0x1122, t.r2);
535   CHECK_EQ(0xffff99aa, t.r3);
536   CHECK_EQ(0x000099aa, t.r4);
537   CHECK_EQ(0xffffff99, t.r5);
538   CHECK_EQ(0x99aa3333, t.r6);
539 #else
540 #error Unknown endianness
541 #endif
542 }
543
544
545 TEST(MIPS7) {
546   // Test floating point compare and branch instructions.
547   CcTest::InitializeVM();
548   Isolate* isolate = CcTest::i_isolate();
549   HandleScope scope(isolate);
550
551   typedef struct {
552     double a;
553     double b;
554     double c;
555     double d;
556     double e;
557     double f;
558     int32_t result;
559   } T;
560   T t;
561
562   // Create a function that accepts &t, and loads, manipulates, and stores
563   // the doubles t.a ... t.f.
564   MacroAssembler assm(isolate, NULL, 0);
565   Label neither_is_nan, less_than, outa_here;
566
567   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
568   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
569   if (!IsMipsArchVariant(kMips32r6)) {
570   __ c(UN, D, f4, f6);
571   __ bc1f(&neither_is_nan);
572   } else {
573     __ cmp(UN, L, f2, f4, f6);
574     __ bc1eqz(&neither_is_nan, f2);
575   }
576   __ nop();
577   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
578   __ Branch(&outa_here);
579
580   __ bind(&neither_is_nan);
581
582   if (IsMipsArchVariant(kLoongson)) {
583     __ c(OLT, D, f6, f4);
584     __ bc1t(&less_than);
585   } else if (IsMipsArchVariant(kMips32r6)) {
586     __ cmp(OLT, L, f2, f6, f4);
587     __ bc1nez(&less_than, f2);
588   } else {
589     __ c(OLT, D, f6, f4, 2);
590     __ bc1t(&less_than, 2);
591   }
592
593   __ nop();
594   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
595   __ Branch(&outa_here);
596
597   __ bind(&less_than);
598   __ Addu(t0, zero_reg, Operand(1));
599   __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) );  // Set true.
600
601
602   // This test-case should have additional tests.
603
604   __ bind(&outa_here);
605
606   __ jr(ra);
607   __ nop();
608
609   CodeDesc desc;
610   assm.GetCode(&desc);
611   Handle<Code> code = isolate->factory()->NewCode(
612       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
613   F3 f = FUNCTION_CAST<F3>(code->entry());
614   t.a = 1.5e14;
615   t.b = 2.75e11;
616   t.c = 2.0;
617   t.d = -4.0;
618   t.e = 0.0;
619   t.f = 0.0;
620   t.result = 0;
621   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
622   USE(dummy);
623   CHECK_EQ(1.5e14, t.a);
624   CHECK_EQ(2.75e11, t.b);
625   CHECK_EQ(1, t.result);
626 }
627
628
629 TEST(MIPS8) {
630   // Test ROTR and ROTRV instructions.
631   CcTest::InitializeVM();
632   Isolate* isolate = CcTest::i_isolate();
633   HandleScope scope(isolate);
634
635   typedef struct {
636     int32_t input;
637     int32_t result_rotr_4;
638     int32_t result_rotr_8;
639     int32_t result_rotr_12;
640     int32_t result_rotr_16;
641     int32_t result_rotr_20;
642     int32_t result_rotr_24;
643     int32_t result_rotr_28;
644     int32_t result_rotrv_4;
645     int32_t result_rotrv_8;
646     int32_t result_rotrv_12;
647     int32_t result_rotrv_16;
648     int32_t result_rotrv_20;
649     int32_t result_rotrv_24;
650     int32_t result_rotrv_28;
651   } T;
652   T t;
653
654   MacroAssembler assm(isolate, NULL, 0);
655
656   // Basic word load.
657   __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
658
659   // ROTR instruction (called through the Ror macro).
660   __ Ror(t1, t0, 0x0004);
661   __ Ror(t2, t0, 0x0008);
662   __ Ror(t3, t0, 0x000c);
663   __ Ror(t4, t0, 0x0010);
664   __ Ror(t5, t0, 0x0014);
665   __ Ror(t6, t0, 0x0018);
666   __ Ror(t7, t0, 0x001c);
667
668   // Basic word store.
669   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
670   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
671   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
672   __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
673   __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
674   __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
675   __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
676
677   // ROTRV instruction (called through the Ror macro).
678   __ li(t7, 0x0004);
679   __ Ror(t1, t0, t7);
680   __ li(t7, 0x0008);
681   __ Ror(t2, t0, t7);
682   __ li(t7, 0x000C);
683   __ Ror(t3, t0, t7);
684   __ li(t7, 0x0010);
685   __ Ror(t4, t0, t7);
686   __ li(t7, 0x0014);
687   __ Ror(t5, t0, t7);
688   __ li(t7, 0x0018);
689   __ Ror(t6, t0, t7);
690   __ li(t7, 0x001C);
691   __ Ror(t7, t0, t7);
692
693   // Basic word store.
694   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
695   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
696   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
697   __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
698   __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
699   __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
700   __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
701
702   __ jr(ra);
703   __ nop();
704
705   CodeDesc desc;
706   assm.GetCode(&desc);
707   Handle<Code> code = isolate->factory()->NewCode(
708       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
709   F3 f = FUNCTION_CAST<F3>(code->entry());
710   t.input = 0x12345678;
711   Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
712   USE(dummy);
713   CHECK_EQ(0x81234567, t.result_rotr_4);
714   CHECK_EQ(0x78123456, t.result_rotr_8);
715   CHECK_EQ(0x67812345, t.result_rotr_12);
716   CHECK_EQ(0x56781234, t.result_rotr_16);
717   CHECK_EQ(0x45678123, t.result_rotr_20);
718   CHECK_EQ(0x34567812, t.result_rotr_24);
719   CHECK_EQ(0x23456781, t.result_rotr_28);
720
721   CHECK_EQ(0x81234567, t.result_rotrv_4);
722   CHECK_EQ(0x78123456, t.result_rotrv_8);
723   CHECK_EQ(0x67812345, t.result_rotrv_12);
724   CHECK_EQ(0x56781234, t.result_rotrv_16);
725   CHECK_EQ(0x45678123, t.result_rotrv_20);
726   CHECK_EQ(0x34567812, t.result_rotrv_24);
727   CHECK_EQ(0x23456781, t.result_rotrv_28);
728 }
729
730
731 TEST(MIPS9) {
732   // Test BRANCH improvements.
733   CcTest::InitializeVM();
734   Isolate* isolate = CcTest::i_isolate();
735   HandleScope scope(isolate);
736
737   MacroAssembler assm(isolate, NULL, 0);
738   Label exit, exit2, exit3;
739
740   __ Branch(&exit, ge, a0, Operand(zero_reg));
741   __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
742   __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
743
744   __ bind(&exit);
745   __ bind(&exit2);
746   __ bind(&exit3);
747   __ jr(ra);
748   __ nop();
749
750   CodeDesc desc;
751   assm.GetCode(&desc);
752   isolate->factory()->NewCode(
753       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
754 }
755
756
757 TEST(MIPS10) {
758   // Test conversions between doubles and long integers.
759   // Test hos the long ints map to FP regs pairs.
760   CcTest::InitializeVM();
761   Isolate* isolate = CcTest::i_isolate();
762   HandleScope scope(isolate);
763
764   typedef struct {
765     double a;
766     double b;
767     int32_t dbl_mant;
768     int32_t dbl_exp;
769     int32_t word;
770     int32_t b_word;
771   } T;
772   T t;
773
774   Assembler assm(isolate, NULL, 0);
775   Label L, C;
776
777   if (!IsMipsArchVariant(kMips32r2)) return;
778
779   // Load all structure elements to registers.
780   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
781
782   // Save the raw bits of the double.
783   __ mfc1(t0, f0);
784   __ mfc1(t1, f1);
785   __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
786   __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
787
788   // Convert double in f0 to long, save hi/lo parts.
789   __ cvt_w_d(f0, f0);
790   __ mfc1(t0, f0);  // f0 has a 32-bits word.
791   __ sw(t0, MemOperand(a0, OFFSET_OF(T, word)));
792
793   // Convert the b long integers to double b.
794   __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_word)));
795   __ mtc1(t0, f8);  // f8 has a 32-bits word.
796   __ cvt_d_w(f10, f8);
797   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
798
799   __ jr(ra);
800   __ nop();
801
802   CodeDesc desc;
803   assm.GetCode(&desc);
804   Handle<Code> code = isolate->factory()->NewCode(
805       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
806   F3 f = FUNCTION_CAST<F3>(code->entry());
807   t.a = 2.147483646e+09;       // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double.
808   t.b_word = 0x0ff00ff0;       // 0x0FF00FF0 -> 0x as double.
809   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
810   USE(dummy);
811
812   CHECK_EQ(0x41DFFFFF, t.dbl_exp);
813   CHECK_EQ(0xFF800000, t.dbl_mant);
814   CHECK_EQ(0X7FFFFFFE, t.word);
815   // 0x0FF00FF0 -> 2.6739096+e08
816   CHECK_EQ(2.6739096e08, t.b);
817 }
818
819
820 TEST(MIPS11) {
821   // Do not run test on MIPS32r6, as these instructions are removed.
822   if (IsMipsArchVariant(kMips32r6)) return;
823   // Test LWL, LWR, SWL and SWR instructions.
824   CcTest::InitializeVM();
825   Isolate* isolate = CcTest::i_isolate();
826   HandleScope scope(isolate);
827
828   typedef struct {
829     int32_t reg_init;
830     int32_t mem_init;
831     int32_t lwl_0;
832     int32_t lwl_1;
833     int32_t lwl_2;
834     int32_t lwl_3;
835     int32_t lwr_0;
836     int32_t lwr_1;
837     int32_t lwr_2;
838     int32_t lwr_3;
839     int32_t swl_0;
840     int32_t swl_1;
841     int32_t swl_2;
842     int32_t swl_3;
843     int32_t swr_0;
844     int32_t swr_1;
845     int32_t swr_2;
846     int32_t swr_3;
847   } T;
848   T t;
849
850   Assembler assm(isolate, NULL, 0);
851
852   // Test all combinations of LWL and vAddr.
853   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
854   __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
855   __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
856
857   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
858   __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
859   __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
860
861   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
862   __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
863   __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
864
865   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
866   __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
867   __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
868
869   // Test all combinations of LWR and vAddr.
870   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
871   __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
872   __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
873
874   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
875   __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
876   __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
877
878   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
879   __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
880   __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
881
882   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
883   __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
884   __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
885
886   // Test all combinations of SWL and vAddr.
887   __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
888   __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
889   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
890   __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
891
892   __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
893   __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
894   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
895   __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
896
897   __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
898   __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
899   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
900   __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
901
902   __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
903   __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
904   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
905   __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
906
907   // Test all combinations of SWR and vAddr.
908   __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
909   __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
910   __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
911   __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
912
913   __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
914   __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
915   __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
916   __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
917
918   __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
919   __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
920   __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
921   __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
922
923   __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
924   __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
925   __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
926   __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
927
928   __ jr(ra);
929   __ nop();
930
931   CodeDesc desc;
932   assm.GetCode(&desc);
933   Handle<Code> code = isolate->factory()->NewCode(
934       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
935   F3 f = FUNCTION_CAST<F3>(code->entry());
936   t.reg_init = 0xaabbccdd;
937   t.mem_init = 0x11223344;
938
939   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
940   USE(dummy);
941
942 #if __BYTE_ORDER == __LITTLE_ENDIAN
943   CHECK_EQ(0x44bbccdd, t.lwl_0);
944   CHECK_EQ(0x3344ccdd, t.lwl_1);
945   CHECK_EQ(0x223344dd, t.lwl_2);
946   CHECK_EQ(0x11223344, t.lwl_3);
947
948   CHECK_EQ(0x11223344, t.lwr_0);
949   CHECK_EQ(0xaa112233, t.lwr_1);
950   CHECK_EQ(0xaabb1122, t.lwr_2);
951   CHECK_EQ(0xaabbcc11, t.lwr_3);
952
953   CHECK_EQ(0x112233aa, t.swl_0);
954   CHECK_EQ(0x1122aabb, t.swl_1);
955   CHECK_EQ(0x11aabbcc, t.swl_2);
956   CHECK_EQ(0xaabbccdd, t.swl_3);
957
958   CHECK_EQ(0xaabbccdd, t.swr_0);
959   CHECK_EQ(0xbbccdd44, t.swr_1);
960   CHECK_EQ(0xccdd3344, t.swr_2);
961   CHECK_EQ(0xdd223344, t.swr_3);
962 #elif __BYTE_ORDER == __BIG_ENDIAN
963   CHECK_EQ(0x11223344, t.lwl_0);
964   CHECK_EQ(0x223344dd, t.lwl_1);
965   CHECK_EQ(0x3344ccdd, t.lwl_2);
966   CHECK_EQ(0x44bbccdd, t.lwl_3);
967
968   CHECK_EQ(0xaabbcc11, t.lwr_0);
969   CHECK_EQ(0xaabb1122, t.lwr_1);
970   CHECK_EQ(0xaa112233, t.lwr_2);
971   CHECK_EQ(0x11223344, t.lwr_3);
972
973   CHECK_EQ(0xaabbccdd, t.swl_0);
974   CHECK_EQ(0x11aabbcc, t.swl_1);
975   CHECK_EQ(0x1122aabb, t.swl_2);
976   CHECK_EQ(0x112233aa, t.swl_3);
977
978   CHECK_EQ(0xdd223344, t.swr_0);
979   CHECK_EQ(0xccdd3344, t.swr_1);
980   CHECK_EQ(0xbbccdd44, t.swr_2);
981   CHECK_EQ(0xaabbccdd, t.swr_3);
982 #else
983 #error Unknown endianness
984 #endif
985 }
986
987
988 TEST(MIPS12) {
989   CcTest::InitializeVM();
990   Isolate* isolate = CcTest::i_isolate();
991   HandleScope scope(isolate);
992
993   typedef struct {
994       int32_t  x;
995       int32_t  y;
996       int32_t  y1;
997       int32_t  y2;
998       int32_t  y3;
999       int32_t  y4;
1000   } T;
1001   T t;
1002
1003   MacroAssembler assm(isolate, NULL, 0);
1004
1005   __ mov(t6, fp);  // Save frame pointer.
1006   __ mov(fp, a0);  // Access struct T by fp.
1007   __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
1008   __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
1009
1010   __ addu(t1, t0, t3);
1011   __ subu(t4, t0, t3);
1012   __ nop();
1013   __ push(t0);  // These instructions disappear after opt.
1014   __ Pop();
1015   __ addu(t0, t0, t0);
1016   __ nop();
1017   __ Pop();     // These instructions disappear after opt.
1018   __ push(t3);
1019   __ nop();
1020   __ push(t3);  // These instructions disappear after opt.
1021   __ pop(t3);
1022   __ nop();
1023   __ push(t3);
1024   __ pop(t4);
1025   __ nop();
1026   __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1027   __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1028   __ nop();
1029   __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1030   __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1031   __ nop();
1032   __ push(t1);
1033   __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1034   __ pop(t1);
1035   __ nop();
1036   __ push(t1);
1037   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1038   __ pop(t1);
1039   __ nop();
1040   __ push(t1);
1041   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1042   __ pop(t2);
1043   __ nop();
1044   __ push(t2);
1045   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1046   __ pop(t1);
1047   __ nop();
1048   __ push(t1);
1049   __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1050   __ pop(t3);
1051   __ nop();
1052
1053   __ mov(fp, t6);
1054   __ jr(ra);
1055   __ nop();
1056
1057   CodeDesc desc;
1058   assm.GetCode(&desc);
1059   Handle<Code> code = isolate->factory()->NewCode(
1060       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1061   F3 f = FUNCTION_CAST<F3>(code->entry());
1062   t.x = 1;
1063   t.y = 2;
1064   t.y1 = 3;
1065   t.y2 = 4;
1066   t.y3 = 0XBABA;
1067   t.y4 = 0xDEDA;
1068
1069   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1070   USE(dummy);
1071
1072   CHECK_EQ(3, t.y1);
1073 }
1074
1075
1076 TEST(MIPS13) {
1077   // Test Cvt_d_uw and Trunc_uw_d macros.
1078   CcTest::InitializeVM();
1079   Isolate* isolate = CcTest::i_isolate();
1080   HandleScope scope(isolate);
1081
1082   typedef struct {
1083     double cvt_big_out;
1084     double cvt_small_out;
1085     uint32_t trunc_big_out;
1086     uint32_t trunc_small_out;
1087     uint32_t cvt_big_in;
1088     uint32_t cvt_small_in;
1089   } T;
1090   T t;
1091
1092   MacroAssembler assm(isolate, NULL, 0);
1093
1094   __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1095   __ Cvt_d_uw(f10, t0, f22);
1096   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1097
1098   __ Trunc_uw_d(f10, f10, f22);
1099   __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1100
1101   __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1102   __ Cvt_d_uw(f8, t0, f22);
1103   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1104
1105   __ Trunc_uw_d(f8, f8, f22);
1106   __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1107
1108   __ jr(ra);
1109   __ nop();
1110
1111   CodeDesc desc;
1112   assm.GetCode(&desc);
1113   Handle<Code> code = isolate->factory()->NewCode(
1114       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1115   F3 f = FUNCTION_CAST<F3>(code->entry());
1116
1117   t.cvt_big_in = 0xFFFFFFFF;
1118   t.cvt_small_in  = 333;
1119
1120   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1121   USE(dummy);
1122
1123   CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1124   CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1125
1126   CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1127   CHECK_EQ(static_cast<int>(t.trunc_small_out),
1128            static_cast<int>(t.cvt_small_in));
1129 }
1130
1131
1132 TEST(MIPS14) {
1133   // Test round, floor, ceil, trunc, cvt.
1134   CcTest::InitializeVM();
1135   Isolate* isolate = CcTest::i_isolate();
1136   HandleScope scope(isolate);
1137
1138 #define ROUND_STRUCT_ELEMENT(x) \
1139   int32_t x##_up_out; \
1140   int32_t x##_down_out; \
1141   int32_t neg_##x##_up_out; \
1142   int32_t neg_##x##_down_out; \
1143   uint32_t x##_err1_out; \
1144   uint32_t x##_err2_out; \
1145   uint32_t x##_err3_out; \
1146   uint32_t x##_err4_out; \
1147   int32_t x##_invalid_result;
1148
1149   typedef struct {
1150     double round_up_in;
1151     double round_down_in;
1152     double neg_round_up_in;
1153     double neg_round_down_in;
1154     double err1_in;
1155     double err2_in;
1156     double err3_in;
1157     double err4_in;
1158
1159     ROUND_STRUCT_ELEMENT(round)
1160     ROUND_STRUCT_ELEMENT(floor)
1161     ROUND_STRUCT_ELEMENT(ceil)
1162     ROUND_STRUCT_ELEMENT(trunc)
1163     ROUND_STRUCT_ELEMENT(cvt)
1164   } T;
1165   T t;
1166
1167 #undef ROUND_STRUCT_ELEMENT
1168
1169   MacroAssembler assm(isolate, NULL, 0);
1170
1171   // Save FCSR.
1172   __ cfc1(a1, FCSR);
1173   // Disable FPU exceptions.
1174   __ ctc1(zero_reg, FCSR);
1175 #define RUN_ROUND_TEST(x) \
1176   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1177   __ x##_w_d(f0, f0); \
1178   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1179   \
1180   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1181   __ x##_w_d(f0, f0); \
1182   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1183   \
1184   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1185   __ x##_w_d(f0, f0); \
1186   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1187   \
1188   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1189   __ x##_w_d(f0, f0); \
1190   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1191   \
1192   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1193   __ ctc1(zero_reg, FCSR); \
1194   __ x##_w_d(f0, f0); \
1195   __ cfc1(a2, FCSR); \
1196   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1197   \
1198   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1199   __ ctc1(zero_reg, FCSR); \
1200   __ x##_w_d(f0, f0); \
1201   __ cfc1(a2, FCSR); \
1202   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1203   \
1204   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1205   __ ctc1(zero_reg, FCSR); \
1206   __ x##_w_d(f0, f0); \
1207   __ cfc1(a2, FCSR); \
1208   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1209   \
1210   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1211   __ ctc1(zero_reg, FCSR); \
1212   __ x##_w_d(f0, f0); \
1213   __ cfc1(a2, FCSR); \
1214   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1215   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1216
1217   RUN_ROUND_TEST(round)
1218   RUN_ROUND_TEST(floor)
1219   RUN_ROUND_TEST(ceil)
1220   RUN_ROUND_TEST(trunc)
1221   RUN_ROUND_TEST(cvt)
1222
1223   // Restore FCSR.
1224   __ ctc1(a1, FCSR);
1225
1226   __ jr(ra);
1227   __ nop();
1228
1229   CodeDesc desc;
1230   assm.GetCode(&desc);
1231   Handle<Code> code = isolate->factory()->NewCode(
1232       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1233   F3 f = FUNCTION_CAST<F3>(code->entry());
1234
1235   t.round_up_in = 123.51;
1236   t.round_down_in = 123.49;
1237   t.neg_round_up_in = -123.5;
1238   t.neg_round_down_in = -123.49;
1239   t.err1_in = 123.51;
1240   t.err2_in = 1;
1241   t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1242   t.err4_in = NAN;
1243
1244   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1245   USE(dummy);
1246
1247 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1248 #define CHECK_ROUND_RESULT(type) \
1249   CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1250   CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1251   CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1252   CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1253   CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
1254
1255   CHECK_ROUND_RESULT(round);
1256   CHECK_ROUND_RESULT(floor);
1257   CHECK_ROUND_RESULT(ceil);
1258   CHECK_ROUND_RESULT(cvt);
1259 }
1260
1261
1262 TEST(MIPS15) {
1263   // Test chaining of label usages within instructions (issue 1644).
1264   CcTest::InitializeVM();
1265   Isolate* isolate = CcTest::i_isolate();
1266   HandleScope scope(isolate);
1267   Assembler assm(isolate, NULL, 0);
1268
1269   Label target;
1270   __ beq(v0, v1, &target);
1271   __ nop();
1272   __ bne(v0, v1, &target);
1273   __ nop();
1274   __ bind(&target);
1275   __ nop();
1276 }
1277
1278 #undef __