deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-assembler-mips64.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 <iostream>  // NOLINT(readability/streams)
29
30 #include "src/v8.h"
31
32 #include "src/disassembler.h"
33 #include "src/factory.h"
34 #include "src/macro-assembler.h"
35 #include "src/mips64/macro-assembler-mips64.h"
36 #include "src/mips64/simulator-mips64.h"
37
38 #include "test/cctest/cctest.h"
39
40 using namespace v8::internal;
41
42
43 // Define these function prototypes to match JSEntryFunction in execution.cc.
44 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
45 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
46 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
47
48
49 #define __ assm.
50
51
52 TEST(MIPS0) {
53   CcTest::InitializeVM();
54   Isolate* isolate = CcTest::i_isolate();
55   HandleScope scope(isolate);
56
57   MacroAssembler assm(isolate, NULL, 0);
58
59   // Addition.
60   __ addu(v0, a0, a1);
61   __ jr(ra);
62   __ nop();
63
64   CodeDesc desc;
65   assm.GetCode(&desc);
66   Handle<Code> code = isolate->factory()->NewCode(
67       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
68   F2 f = FUNCTION_CAST<F2>(code->entry());
69   int64_t res =
70       reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
71   CHECK_EQ(0xabcL, res);
72 }
73
74
75 TEST(MIPS1) {
76   CcTest::InitializeVM();
77   Isolate* isolate = CcTest::i_isolate();
78   HandleScope scope(isolate);
79
80   MacroAssembler assm(isolate, NULL, 0);
81   Label L, C;
82
83   __ mov(a1, a0);
84   __ li(v0, 0);
85   __ b(&C);
86   __ nop();
87
88   __ bind(&L);
89   __ addu(v0, v0, a1);
90   __ addiu(a1, a1, -1);
91
92   __ bind(&C);
93   __ xori(v1, a1, 0);
94   __ Branch(&L, ne, v1, Operand((int64_t)0));
95   __ nop();
96
97   __ jr(ra);
98   __ nop();
99
100   CodeDesc desc;
101   assm.GetCode(&desc);
102   Handle<Code> code = isolate->factory()->NewCode(
103       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
104   F1 f = FUNCTION_CAST<F1>(code->entry());
105   int64_t res =
106      reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
107   CHECK_EQ(1275L, res);
108 }
109
110
111 TEST(MIPS2) {
112   CcTest::InitializeVM();
113   Isolate* isolate = CcTest::i_isolate();
114   HandleScope scope(isolate);
115
116   MacroAssembler assm(isolate, NULL, 0);
117
118   Label exit, error;
119
120   // ----- Test all instructions.
121
122   // Test lui, ori, and addiu, used in the li pseudo-instruction.
123   // This way we can then safely load registers with chosen values.
124
125   __ ori(a4, zero_reg, 0);
126   __ lui(a4, 0x1234);
127   __ ori(a4, a4, 0);
128   __ ori(a4, a4, 0x0f0f);
129   __ ori(a4, a4, 0xf0f0);
130   __ addiu(a5, a4, 1);
131   __ addiu(a6, a5, -0x10);
132
133   // Load values in temporary registers.
134   __ li(a4, 0x00000004);
135   __ li(a5, 0x00001234);
136   __ li(a6, 0x12345678);
137   __ li(a7, 0x7fffffff);
138   __ li(t0, 0xfffffffc);
139   __ li(t1, 0xffffedcc);
140   __ li(t2, 0xedcba988);
141   __ li(t3, 0x80000000);
142
143   // SPECIAL class.
144   __ srl(v0, a6, 8);    // 0x00123456
145   __ sll(v0, v0, 11);   // 0x91a2b000
146   __ sra(v0, v0, 3);    // 0xf2345600
147   __ srav(v0, v0, a4);  // 0xff234560
148   __ sllv(v0, v0, a4);  // 0xf2345600
149   __ srlv(v0, v0, a4);  // 0x0f234560
150   __ Branch(&error, ne, v0, Operand(0x0f234560));
151   __ nop();
152
153   __ addu(v0, a4, a5);  // 0x00001238
154   __ subu(v0, v0, a4);  // 0x00001234
155   __ Branch(&error, ne, v0, Operand(0x00001234));
156   __ nop();
157   __ addu(v1, a7, a4);  // 32bit addu result is sign-extended into 64bit reg.
158   __ Branch(&error, ne, v1, Operand(0xffffffff80000003));
159   __ nop();
160   __ subu(v1, t3, a4);  // 0x7ffffffc
161   __ Branch(&error, ne, v1, Operand(0x7ffffffc));
162   __ nop();
163
164   __ and_(v0, a5, a6);  // 0x0000000000001230
165   __ or_(v0, v0, a5);   // 0x0000000000001234
166   __ xor_(v0, v0, a6);  // 0x000000001234444c
167   __ nor(v0, v0, a6);   // 0xffffffffedcba987
168   __ Branch(&error, ne, v0, Operand(0xffffffffedcba983));
169   __ nop();
170
171   // Shift both 32bit number to left, to preserve meaning of next comparison.
172   __ dsll32(a7, a7, 0);
173   __ dsll32(t3, t3, 0);
174
175   __ slt(v0, t3, a7);
176   __ Branch(&error, ne, v0, Operand(0x1));
177   __ nop();
178   __ sltu(v0, t3, a7);
179   __ Branch(&error, ne, v0, Operand(zero_reg));
180   __ nop();
181
182   // Restore original values in registers.
183   __ dsrl32(a7, a7, 0);
184   __ dsrl32(t3, t3, 0);
185   // End of SPECIAL class.
186
187   __ addiu(v0, zero_reg, 0x7421);  // 0x00007421
188   __ addiu(v0, v0, -0x1);          // 0x00007420
189   __ addiu(v0, v0, -0x20);         // 0x00007400
190   __ Branch(&error, ne, v0, Operand(0x00007400));
191   __ nop();
192   __ addiu(v1, a7, 0x1);  // 0x80000000 - result is sign-extended.
193   __ Branch(&error, ne, v1, Operand(0xffffffff80000000));
194   __ nop();
195
196   __ slti(v0, a5, 0x00002000);  // 0x1
197   __ slti(v0, v0, 0xffff8000);  // 0x0
198   __ Branch(&error, ne, v0, Operand(zero_reg));
199   __ nop();
200   __ sltiu(v0, a5, 0x00002000);  // 0x1
201   __ sltiu(v0, v0, 0x00008000);  // 0x1
202   __ Branch(&error, ne, v0, Operand(0x1));
203   __ nop();
204
205   __ andi(v0, a5, 0xf0f0);  // 0x00001030
206   __ ori(v0, v0, 0x8a00);   // 0x00009a30
207   __ xori(v0, v0, 0x83cc);  // 0x000019fc
208   __ Branch(&error, ne, v0, Operand(0x000019fc));
209   __ nop();
210   __ lui(v1, 0x8123);  // Result is sign-extended into 64bit register.
211   __ Branch(&error, ne, v1, Operand(0xffffffff81230000));
212   __ nop();
213
214   // Bit twiddling instructions & conditional moves.
215   // Uses a4-t3 as set above.
216   __ Clz(v0, a4);       // 29
217   __ Clz(v1, a5);       // 19
218   __ addu(v0, v0, v1);  // 48
219   __ Clz(v1, a6);       // 3
220   __ addu(v0, v0, v1);  // 51
221   __ Clz(v1, t3);       // 0
222   __ addu(v0, v0, v1);  // 51
223   __ Branch(&error, ne, v0, Operand(51));
224   __ Movn(a0, a7, a4);  // Move a0<-a7 (a4 is NOT 0).
225   __ Ins(a0, a5, 12, 8);  // 0x7ff34fff
226   __ Branch(&error, ne, a0, Operand(0x7ff34fff));
227   __ Movz(a0, t2, t3);    // a0 not updated (t3 is NOT 0).
228   __ Ext(a1, a0, 8, 12);  // 0x34f
229   __ Branch(&error, ne, a1, Operand(0x34f));
230   __ Movz(a0, t2, v1);    // a0<-t2, v0 is 0, from 8 instr back.
231   __ Branch(&error, ne, a0, Operand(t2));
232
233   // Everything was correctly executed. Load the expected result.
234   __ li(v0, 0x31415926);
235   __ b(&exit);
236   __ nop();
237
238   __ bind(&error);
239   // Got an error. Return a wrong result.
240   __ li(v0, 666);
241
242   __ bind(&exit);
243   __ jr(ra);
244   __ nop();
245
246   CodeDesc desc;
247   assm.GetCode(&desc);
248   Handle<Code> code = isolate->factory()->NewCode(
249       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
250   F2 f = FUNCTION_CAST<F2>(code->entry());
251   int64_t res =
252       reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
253
254   CHECK_EQ(0x31415926L, res);
255 }
256
257
258 TEST(MIPS3) {
259   // Test floating point instructions.
260   CcTest::InitializeVM();
261   Isolate* isolate = CcTest::i_isolate();
262   HandleScope scope(isolate);
263
264   typedef struct {
265     double a;
266     double b;
267     double c;
268     double d;
269     double e;
270     double f;
271     double g;
272     double h;
273     double i;
274   } T;
275   T t;
276
277   // Create a function that accepts &t, and loads, manipulates, and stores
278   // the doubles t.a ... t.f.
279   MacroAssembler assm(isolate, NULL, 0);
280   Label L, C;
281
282   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
283   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
284   __ add_d(f8, f4, f6);
285   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) );  // c = a + b.
286
287   __ mov_d(f10, f8);  // c
288   __ neg_d(f12, f6);  // -b
289   __ sub_d(f10, f10, f12);
290   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) );  // d = c - (-b).
291
292   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) );   // b = a.
293
294   __ li(a4, 120);
295   __ mtc1(a4, f14);
296   __ cvt_d_w(f14, f14);   // f14 = 120.0.
297   __ mul_d(f10, f10, f14);
298   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) );  // e = d * 120 = 1.8066e16.
299
300   __ div_d(f12, f10, f4);
301   __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) );  // f = e / a = 120.44.
302
303   __ sqrt_d(f14, f12);
304   __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
305   // g = sqrt(f) = 10.97451593465515908537
306
307   if (kArchVariant == kMips64r2) {
308     __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) );
309     __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) );
310     __ madd_d(f14, f6, f4, f6);
311     __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) );
312   }
313
314   __ jr(ra);
315   __ nop();
316
317   CodeDesc desc;
318   assm.GetCode(&desc);
319   Handle<Code> code = isolate->factory()->NewCode(
320       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
321   F3 f = FUNCTION_CAST<F3>(code->entry());
322   t.a = 1.5e14;
323   t.b = 2.75e11;
324   t.c = 0.0;
325   t.d = 0.0;
326   t.e = 0.0;
327   t.f = 0.0;
328   t.h = 1.5;
329   t.i = 2.75;
330   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
331   USE(dummy);
332   CHECK_EQ(1.5e14, t.a);
333   CHECK_EQ(1.5e14, t.b);
334   CHECK_EQ(1.50275e14, t.c);
335   CHECK_EQ(1.50550e14, t.d);
336   CHECK_EQ(1.8066e16, t.e);
337   CHECK_EQ(120.44, t.f);
338   CHECK_EQ(10.97451593465515908537, t.g);
339   if (kArchVariant == kMips64r2) {
340     CHECK_EQ(6.875, t.h);
341   }
342 }
343
344
345 TEST(MIPS4) {
346   // Test moves between floating point and integer registers.
347   CcTest::InitializeVM();
348   Isolate* isolate = CcTest::i_isolate();
349   HandleScope scope(isolate);
350
351   typedef struct {
352     double a;
353     double b;
354     double c;
355     double d;
356     int64_t high;
357     int64_t low;
358   } T;
359   T t;
360
361   Assembler assm(isolate, NULL, 0);
362   Label L, C;
363
364   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)));
365   __ ldc1(f5, MemOperand(a0, OFFSET_OF(T, b)));
366
367   // Swap f4 and f5, by using 3 integer registers, a4-a6,
368   // both two 32-bit chunks, and one 64-bit chunk.
369   // mXhc1 is mips32/64-r2 only, not r1,
370   // but we will not support r1 in practice.
371   __ mfc1(a4, f4);
372   __ mfhc1(a5, f4);
373   __ dmfc1(a6, f5);
374
375   __ mtc1(a4, f5);
376   __ mthc1(a5, f5);
377   __ dmtc1(a6, f4);
378
379   // Store the swapped f4 and f5 back to memory.
380   __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)));
381   __ sdc1(f5, MemOperand(a0, OFFSET_OF(T, c)));
382
383   // Test sign extension of move operations from coprocessor.
384   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, d)));
385   __ mfhc1(a4, f4);
386   __ mfc1(a5, f4);
387
388   __ sd(a4, MemOperand(a0, OFFSET_OF(T, high)));
389   __ sd(a5, MemOperand(a0, OFFSET_OF(T, low)));
390
391   __ jr(ra);
392   __ nop();
393
394   CodeDesc desc;
395   assm.GetCode(&desc);
396   Handle<Code> code = isolate->factory()->NewCode(
397       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
398   F3 f = FUNCTION_CAST<F3>(code->entry());
399   t.a = 1.5e22;
400   t.b = 2.75e11;
401   t.c = 17.17;
402   t.d = -2.75e11;
403   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
404   USE(dummy);
405
406   CHECK_EQ(2.75e11, t.a);
407   CHECK_EQ(2.75e11, t.b);
408   CHECK_EQ(1.5e22, t.c);
409   CHECK_EQ(static_cast<int64_t>(0xffffffffc25001d1L), t.high);
410   CHECK_EQ(static_cast<int64_t>(0xffffffffbf800000L), t.low);
411 }
412
413
414 TEST(MIPS5) {
415   // Test conversions between doubles and integers.
416   CcTest::InitializeVM();
417   Isolate* isolate = CcTest::i_isolate();
418   HandleScope scope(isolate);
419
420   typedef struct {
421     double a;
422     double b;
423     int i;
424     int j;
425   } T;
426   T t;
427
428   Assembler assm(isolate, NULL, 0);
429   Label L, C;
430
431   // Load all structure elements to registers.
432   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
433   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
434   __ lw(a4, MemOperand(a0, OFFSET_OF(T, i)) );
435   __ lw(a5, MemOperand(a0, OFFSET_OF(T, j)) );
436
437   // Convert double in f4 to int in element i.
438   __ cvt_w_d(f8, f4);
439   __ mfc1(a6, f8);
440   __ sw(a6, MemOperand(a0, OFFSET_OF(T, i)) );
441
442   // Convert double in f6 to int in element j.
443   __ cvt_w_d(f10, f6);
444   __ mfc1(a7, f10);
445   __ sw(a7, MemOperand(a0, OFFSET_OF(T, j)) );
446
447   // Convert int in original i (a4) to double in a.
448   __ mtc1(a4, f12);
449   __ cvt_d_w(f0, f12);
450   __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
451
452   // Convert int in original j (a5) to double in b.
453   __ mtc1(a5, f14);
454   __ cvt_d_w(f2, f14);
455   __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
456
457   __ jr(ra);
458   __ nop();
459
460   CodeDesc desc;
461   assm.GetCode(&desc);
462   Handle<Code> code = isolate->factory()->NewCode(
463       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
464   F3 f = FUNCTION_CAST<F3>(code->entry());
465   t.a = 1.5e4;
466   t.b = 2.75e8;
467   t.i = 12345678;
468   t.j = -100000;
469   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
470   USE(dummy);
471
472   CHECK_EQ(12345678.0, t.a);
473   CHECK_EQ(-100000.0, t.b);
474   CHECK_EQ(15000, t.i);
475   CHECK_EQ(275000000, t.j);
476 }
477
478
479 TEST(MIPS6) {
480   // Test simple memory loads and stores.
481   CcTest::InitializeVM();
482   Isolate* isolate = CcTest::i_isolate();
483   HandleScope scope(isolate);
484
485   typedef struct {
486     uint32_t ui;
487     int32_t si;
488     int32_t r1;
489     int32_t r2;
490     int32_t r3;
491     int32_t r4;
492     int32_t r5;
493     int32_t r6;
494   } T;
495   T t;
496
497   Assembler assm(isolate, NULL, 0);
498   Label L, C;
499
500   // Basic word load/store.
501   __ lw(a4, MemOperand(a0, OFFSET_OF(T, ui)) );
502   __ sw(a4, MemOperand(a0, OFFSET_OF(T, r1)) );
503
504   // lh with positive data.
505   __ lh(a5, MemOperand(a0, OFFSET_OF(T, ui)) );
506   __ sw(a5, MemOperand(a0, OFFSET_OF(T, r2)) );
507
508   // lh with negative data.
509   __ lh(a6, MemOperand(a0, OFFSET_OF(T, si)) );
510   __ sw(a6, MemOperand(a0, OFFSET_OF(T, r3)) );
511
512   // lhu with negative data.
513   __ lhu(a7, MemOperand(a0, OFFSET_OF(T, si)) );
514   __ sw(a7, MemOperand(a0, OFFSET_OF(T, r4)) );
515
516   // lb with negative data.
517   __ lb(t0, MemOperand(a0, OFFSET_OF(T, si)) );
518   __ sw(t0, MemOperand(a0, OFFSET_OF(T, r5)) );
519
520   // sh writes only 1/2 of word.
521   __ lui(t1, 0x3333);
522   __ ori(t1, t1, 0x3333);
523   __ sw(t1, MemOperand(a0, OFFSET_OF(T, r6)) );
524   __ lhu(t1, MemOperand(a0, OFFSET_OF(T, si)) );
525   __ sh(t1, MemOperand(a0, OFFSET_OF(T, r6)) );
526
527   __ jr(ra);
528   __ nop();
529
530   CodeDesc desc;
531   assm.GetCode(&desc);
532   Handle<Code> code = isolate->factory()->NewCode(
533       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
534   F3 f = FUNCTION_CAST<F3>(code->entry());
535   t.ui = 0x11223344;
536   t.si = 0x99aabbcc;
537   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
538   USE(dummy);
539
540   CHECK_EQ(static_cast<int32_t>(0x11223344), t.r1);
541   CHECK_EQ(static_cast<int32_t>(0x3344), t.r2);
542   CHECK_EQ(static_cast<int32_t>(0xffffbbcc), t.r3);
543   CHECK_EQ(static_cast<int32_t>(0x0000bbcc), t.r4);
544   CHECK_EQ(static_cast<int32_t>(0xffffffcc), t.r5);
545   CHECK_EQ(static_cast<int32_t>(0x3333bbcc), t.r6);
546 }
547
548
549 TEST(MIPS7) {
550   // Test floating point compare and branch instructions.
551   CcTest::InitializeVM();
552   Isolate* isolate = CcTest::i_isolate();
553   HandleScope scope(isolate);
554
555   typedef struct {
556     double a;
557     double b;
558     double c;
559     double d;
560     double e;
561     double f;
562     int32_t result;
563   } T;
564   T t;
565
566   // Create a function that accepts &t, and loads, manipulates, and stores
567   // the doubles t.a ... t.f.
568   MacroAssembler assm(isolate, NULL, 0);
569   Label neither_is_nan, less_than, outa_here;
570
571   __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
572   __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
573   if (kArchVariant != kMips64r6) {
574     __ c(UN, D, f4, f6);
575     __ bc1f(&neither_is_nan);
576   } else {
577     __ cmp(UN, L, f2, f4, f6);
578     __ bc1eqz(&neither_is_nan, f2);
579   }
580   __ nop();
581   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
582   __ Branch(&outa_here);
583
584   __ bind(&neither_is_nan);
585
586   if (kArchVariant == kMips64r6) {
587     __ cmp(OLT, L, f2, f6, f4);
588     __ bc1nez(&less_than, f2);
589   } else {
590     __ c(OLT, D, f6, f4, 2);
591     __ bc1t(&less_than, 2);
592   }
593
594   __ nop();
595   __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
596   __ Branch(&outa_here);
597
598   __ bind(&less_than);
599   __ Addu(a4, zero_reg, Operand(1));
600   __ sw(a4, MemOperand(a0, OFFSET_OF(T, result)) );  // Set true.
601
602
603   // This test-case should have additional tests.
604
605   __ bind(&outa_here);
606
607   __ jr(ra);
608   __ nop();
609
610   CodeDesc desc;
611   assm.GetCode(&desc);
612   Handle<Code> code = isolate->factory()->NewCode(
613       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
614   F3 f = FUNCTION_CAST<F3>(code->entry());
615   t.a = 1.5e14;
616   t.b = 2.75e11;
617   t.c = 2.0;
618   t.d = -4.0;
619   t.e = 0.0;
620   t.f = 0.0;
621   t.result = 0;
622   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
623   USE(dummy);
624   CHECK_EQ(1.5e14, t.a);
625   CHECK_EQ(2.75e11, t.b);
626   CHECK_EQ(1, t.result);
627 }
628
629
630 TEST(MIPS8) {
631   // Test ROTR and ROTRV instructions.
632   CcTest::InitializeVM();
633   Isolate* isolate = CcTest::i_isolate();
634   HandleScope scope(isolate);
635
636   typedef struct {
637     int32_t input;
638     int32_t result_rotr_4;
639     int32_t result_rotr_8;
640     int32_t result_rotr_12;
641     int32_t result_rotr_16;
642     int32_t result_rotr_20;
643     int32_t result_rotr_24;
644     int32_t result_rotr_28;
645     int32_t result_rotrv_4;
646     int32_t result_rotrv_8;
647     int32_t result_rotrv_12;
648     int32_t result_rotrv_16;
649     int32_t result_rotrv_20;
650     int32_t result_rotrv_24;
651     int32_t result_rotrv_28;
652   } T;
653   T t;
654
655   MacroAssembler assm(isolate, NULL, 0);
656
657   // Basic word load.
658   __ lw(a4, MemOperand(a0, OFFSET_OF(T, input)) );
659
660   // ROTR instruction (called through the Ror macro).
661   __ Ror(a5, a4, 0x0004);
662   __ Ror(a6, a4, 0x0008);
663   __ Ror(a7, a4, 0x000c);
664   __ Ror(t0, a4, 0x0010);
665   __ Ror(t1, a4, 0x0014);
666   __ Ror(t2, a4, 0x0018);
667   __ Ror(t3, a4, 0x001c);
668
669   // Basic word store.
670   __ sw(a5, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
671   __ sw(a6, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
672   __ sw(a7, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
673   __ sw(t0, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
674   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
675   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
676   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
677
678   // ROTRV instruction (called through the Ror macro).
679   __ li(t3, 0x0004);
680   __ Ror(a5, a4, t3);
681   __ li(t3, 0x0008);
682   __ Ror(a6, a4, t3);
683   __ li(t3, 0x000C);
684   __ Ror(a7, a4, t3);
685   __ li(t3, 0x0010);
686   __ Ror(t0, a4, t3);
687   __ li(t3, 0x0014);
688   __ Ror(t1, a4, t3);
689   __ li(t3, 0x0018);
690   __ Ror(t2, a4, t3);
691   __ li(t3, 0x001C);
692   __ Ror(t3, a4, t3);
693
694   // Basic word store.
695   __ sw(a5, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
696   __ sw(a6, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
697   __ sw(a7, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
698   __ sw(t0, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
699   __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
700   __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
701   __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
702
703   __ jr(ra);
704   __ nop();
705
706   CodeDesc desc;
707   assm.GetCode(&desc);
708   Handle<Code> code = isolate->factory()->NewCode(
709       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
710   F3 f = FUNCTION_CAST<F3>(code->entry());
711   t.input = 0x12345678;
712   Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
713   USE(dummy);
714   CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotr_4);
715   CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotr_8);
716   CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotr_12);
717   CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotr_16);
718   CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotr_20);
719   CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotr_24);
720   CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotr_28);
721
722   CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotrv_4);
723   CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotrv_8);
724   CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotrv_12);
725   CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotrv_16);
726   CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotrv_20);
727   CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotrv_24);
728   CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotrv_28);
729 }
730
731
732 TEST(MIPS9) {
733   // Test BRANCH improvements.
734   CcTest::InitializeVM();
735   Isolate* isolate = CcTest::i_isolate();
736   HandleScope scope(isolate);
737
738   MacroAssembler assm(isolate, NULL, 0);
739   Label exit, exit2, exit3;
740
741   __ Branch(&exit, ge, a0, Operand(zero_reg));
742   __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
743   __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
744
745   __ bind(&exit);
746   __ bind(&exit2);
747   __ bind(&exit3);
748   __ jr(ra);
749   __ nop();
750
751   CodeDesc desc;
752   assm.GetCode(&desc);
753   isolate->factory()->NewCode(
754       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
755 }
756
757
758 TEST(MIPS10) {
759   // Test conversions between doubles and long integers.
760   // Test hos the long ints map to FP regs pairs.
761   CcTest::InitializeVM();
762   Isolate* isolate = CcTest::i_isolate();
763   HandleScope scope(isolate);
764
765   typedef struct {
766     double a;
767     double a_converted;
768     double b;
769     int32_t dbl_mant;
770     int32_t dbl_exp;
771     int32_t long_hi;
772     int32_t long_lo;
773     int64_t long_as_int64;
774     int32_t b_long_hi;
775     int32_t b_long_lo;
776     int64_t b_long_as_int64;
777   } T;
778   T t;
779
780   Assembler assm(isolate, NULL, 0);
781   Label L, C;
782
783   if (kArchVariant == kMips64r2) {
784     // Rewritten for FR=1 FPU mode:
785     //  -  32 FP regs of 64-bits each, no odd/even pairs.
786     //  -  Note that cvt_l_d/cvt_d_l ARE legal in FR=1 mode.
787     // Load all structure elements to registers.
788     __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
789
790     // Save the raw bits of the double.
791     __ mfc1(a4, f0);
792     __ mfhc1(a5, f0);
793     __ sw(a4, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
794     __ sw(a5, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
795
796     // Convert double in f0 to long, save hi/lo parts.
797     __ cvt_l_d(f0, f0);
798     __ mfc1(a4, f0);  // f0 LS 32 bits of long.
799     __ mfhc1(a5, f0);  // f0 MS 32 bits of long.
800     __ sw(a4, MemOperand(a0, OFFSET_OF(T, long_lo)));
801     __ sw(a5, MemOperand(a0, OFFSET_OF(T, long_hi)));
802
803     // Combine the high/low ints, convert back to double.
804     __ dsll32(a6, a5, 0);  // Move a5 to high bits of a6.
805     __ or_(a6, a6, a4);
806     __ dmtc1(a6, f1);
807     __ cvt_d_l(f1, f1);
808     __ sdc1(f1, MemOperand(a0, OFFSET_OF(T, a_converted)));
809
810
811     // Convert the b long integers to double b.
812     __ lw(a4, MemOperand(a0, OFFSET_OF(T, b_long_lo)));
813     __ lw(a5, MemOperand(a0, OFFSET_OF(T, b_long_hi)));
814     __ mtc1(a4, f8);  // f8 LS 32-bits.
815     __ mthc1(a5, f8);  // f8 MS 32-bits.
816     __ cvt_d_l(f10, f8);
817     __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
818
819     // Convert double b back to long-int.
820     __ ldc1(f31, MemOperand(a0, OFFSET_OF(T, b)));
821     __ cvt_l_d(f31, f31);
822     __ dmfc1(a7, f31);
823     __ sd(a7, MemOperand(a0, OFFSET_OF(T, b_long_as_int64)));
824
825
826     __ jr(ra);
827     __ nop();
828
829     CodeDesc desc;
830     assm.GetCode(&desc);
831     Handle<Code> code = isolate->factory()->NewCode(
832         desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
833     F3 f = FUNCTION_CAST<F3>(code->entry());
834     t.a = 2.147483647e9;       // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
835     t.b_long_hi = 0x000000ff;  // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
836     t.b_long_lo = 0x00ff00ff;
837     Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
838     USE(dummy);
839
840     CHECK_EQ(static_cast<int32_t>(0x41DFFFFF), t.dbl_exp);
841     CHECK_EQ(static_cast<int32_t>(0xFFC00000), t.dbl_mant);
842     CHECK_EQ(0, t.long_hi);
843     CHECK_EQ(static_cast<int32_t>(0x7fffffff), t.long_lo);
844     CHECK_EQ(2.147483647e9, t.a_converted);
845
846     // 0xFF00FF00FF -> 1.095233372415e12.
847     CHECK_EQ(1.095233372415e12, t.b);
848     CHECK_EQ(static_cast<int64_t>(0xFF00FF00FF), t.b_long_as_int64);
849   }
850 }
851
852
853 TEST(MIPS11) {
854   // Do not run test on MIPS64r6, as these instructions are removed.
855   if (kArchVariant != kMips64r6) {
856     // Test LWL, LWR, SWL and SWR instructions.
857     CcTest::InitializeVM();
858     Isolate* isolate = CcTest::i_isolate();
859     HandleScope scope(isolate);
860
861     typedef struct {
862       int32_t reg_init;
863       int32_t mem_init;
864       int32_t lwl_0;
865       int32_t lwl_1;
866       int32_t lwl_2;
867       int32_t lwl_3;
868       int32_t lwr_0;
869       int32_t lwr_1;
870       int32_t lwr_2;
871       int32_t lwr_3;
872       int32_t swl_0;
873       int32_t swl_1;
874       int32_t swl_2;
875       int32_t swl_3;
876       int32_t swr_0;
877       int32_t swr_1;
878       int32_t swr_2;
879       int32_t swr_3;
880     } T;
881     T t;
882
883     Assembler assm(isolate, NULL, 0);
884
885     // Test all combinations of LWL and vAddr.
886     __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)));
887     __ lwl(a4, MemOperand(a0, OFFSET_OF(T, mem_init)));
888     __ sw(a4, MemOperand(a0, OFFSET_OF(T, lwl_0)));
889
890     __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)));
891     __ lwl(a5, MemOperand(a0, OFFSET_OF(T, mem_init) + 1));
892     __ sw(a5, MemOperand(a0, OFFSET_OF(T, lwl_1)));
893
894     __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)));
895     __ lwl(a6, MemOperand(a0, OFFSET_OF(T, mem_init) + 2));
896     __ sw(a6, MemOperand(a0, OFFSET_OF(T, lwl_2)));
897
898     __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)));
899     __ lwl(a7, MemOperand(a0, OFFSET_OF(T, mem_init) + 3));
900     __ sw(a7, MemOperand(a0, OFFSET_OF(T, lwl_3)));
901
902     // Test all combinations of LWR and vAddr.
903     __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)));
904     __ lwr(a4, MemOperand(a0, OFFSET_OF(T, mem_init)));
905     __ sw(a4, MemOperand(a0, OFFSET_OF(T, lwr_0)));
906
907     __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)));
908     __ lwr(a5, MemOperand(a0, OFFSET_OF(T, mem_init) + 1));
909     __ sw(a5, MemOperand(a0, OFFSET_OF(T, lwr_1)));
910
911     __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)));
912     __ lwr(a6, MemOperand(a0, OFFSET_OF(T, mem_init) + 2));
913     __ sw(a6, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
914
915     __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)));
916     __ lwr(a7, MemOperand(a0, OFFSET_OF(T, mem_init) + 3));
917     __ sw(a7, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
918
919     // Test all combinations of SWL and vAddr.
920     __ lw(a4, MemOperand(a0, OFFSET_OF(T, mem_init)));
921     __ sw(a4, MemOperand(a0, OFFSET_OF(T, swl_0)));
922     __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)));
923     __ swl(a4, MemOperand(a0, OFFSET_OF(T, swl_0)));
924
925     __ lw(a5, MemOperand(a0, OFFSET_OF(T, mem_init)));
926     __ sw(a5, MemOperand(a0, OFFSET_OF(T, swl_1)));
927     __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)));
928     __ swl(a5, MemOperand(a0, OFFSET_OF(T, swl_1) + 1));
929
930     __ lw(a6, MemOperand(a0, OFFSET_OF(T, mem_init)));
931     __ sw(a6, MemOperand(a0, OFFSET_OF(T, swl_2)));
932     __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)));
933     __ swl(a6, MemOperand(a0, OFFSET_OF(T, swl_2) + 2));
934
935     __ lw(a7, MemOperand(a0, OFFSET_OF(T, mem_init)));
936     __ sw(a7, MemOperand(a0, OFFSET_OF(T, swl_3)));
937     __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)));
938     __ swl(a7, MemOperand(a0, OFFSET_OF(T, swl_3) + 3));
939
940     // Test all combinations of SWR and vAddr.
941     __ lw(a4, MemOperand(a0, OFFSET_OF(T, mem_init)));
942     __ sw(a4, MemOperand(a0, OFFSET_OF(T, swr_0)));
943     __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)));
944     __ swr(a4, MemOperand(a0, OFFSET_OF(T, swr_0)));
945
946     __ lw(a5, MemOperand(a0, OFFSET_OF(T, mem_init)));
947     __ sw(a5, MemOperand(a0, OFFSET_OF(T, swr_1)));
948     __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)));
949     __ swr(a5, MemOperand(a0, OFFSET_OF(T, swr_1) + 1));
950
951     __ lw(a6, MemOperand(a0, OFFSET_OF(T, mem_init)));
952     __ sw(a6, MemOperand(a0, OFFSET_OF(T, swr_2)));
953     __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)));
954     __ swr(a6, MemOperand(a0, OFFSET_OF(T, swr_2) + 2));
955
956     __ lw(a7, MemOperand(a0, OFFSET_OF(T, mem_init)));
957     __ sw(a7, MemOperand(a0, OFFSET_OF(T, swr_3)));
958     __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)));
959     __ swr(a7, MemOperand(a0, OFFSET_OF(T, swr_3) + 3));
960
961     __ jr(ra);
962     __ nop();
963
964     CodeDesc desc;
965     assm.GetCode(&desc);
966     Handle<Code> code = isolate->factory()->NewCode(
967         desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
968     F3 f = FUNCTION_CAST<F3>(code->entry());
969     t.reg_init = 0xaabbccdd;
970     t.mem_init = 0x11223344;
971
972     Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
973     USE(dummy);
974
975     CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_0);
976     CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_1);
977     CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_2);
978     CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_3);
979
980     CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_0);
981     CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_1);
982     CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_2);
983     CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_3);
984
985     CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_0);
986     CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_1);
987     CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_2);
988     CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_3);
989
990     CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_0);
991     CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_1);
992     CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_2);
993     CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_3);
994   }
995 }
996
997
998 TEST(MIPS12) {
999   CcTest::InitializeVM();
1000   Isolate* isolate = CcTest::i_isolate();
1001   HandleScope scope(isolate);
1002
1003   typedef struct {
1004       int32_t  x;
1005       int32_t  y;
1006       int32_t  y1;
1007       int32_t  y2;
1008       int32_t  y3;
1009       int32_t  y4;
1010   } T;
1011   T t;
1012
1013   MacroAssembler assm(isolate, NULL, 0);
1014
1015   __ mov(t2, fp);  // Save frame pointer.
1016   __ mov(fp, a0);  // Access struct T by fp.
1017   __ lw(a4, MemOperand(a0, OFFSET_OF(T, y)));
1018   __ lw(a7, MemOperand(a0, OFFSET_OF(T, y4)));
1019
1020   __ addu(a5, a4, a7);
1021   __ subu(t0, a4, a7);
1022   __ nop();
1023   __ push(a4);  // These instructions disappear after opt.
1024   __ Pop();
1025   __ addu(a4, a4, a4);
1026   __ nop();
1027   __ Pop();     // These instructions disappear after opt.
1028   __ push(a7);
1029   __ nop();
1030   __ push(a7);  // These instructions disappear after opt.
1031   __ pop(a7);
1032   __ nop();
1033   __ push(a7);
1034   __ pop(t0);
1035   __ nop();
1036   __ sw(a4, MemOperand(fp, OFFSET_OF(T, y)));
1037   __ lw(a4, MemOperand(fp, OFFSET_OF(T, y)));
1038   __ nop();
1039   __ sw(a4, MemOperand(fp, OFFSET_OF(T, y)));
1040   __ lw(a5, MemOperand(fp, OFFSET_OF(T, y)));
1041   __ nop();
1042   __ push(a5);
1043   __ lw(a5, MemOperand(fp, OFFSET_OF(T, y)));
1044   __ pop(a5);
1045   __ nop();
1046   __ push(a5);
1047   __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)));
1048   __ pop(a5);
1049   __ nop();
1050   __ push(a5);
1051   __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)));
1052   __ pop(a6);
1053   __ nop();
1054   __ push(a6);
1055   __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)));
1056   __ pop(a5);
1057   __ nop();
1058   __ push(a5);
1059   __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)));
1060   __ pop(a7);
1061   __ nop();
1062
1063   __ mov(fp, t2);
1064   __ jr(ra);
1065   __ nop();
1066
1067   CodeDesc desc;
1068   assm.GetCode(&desc);
1069   Handle<Code> code = isolate->factory()->NewCode(
1070       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1071   F3 f = FUNCTION_CAST<F3>(code->entry());
1072   t.x = 1;
1073   t.y = 2;
1074   t.y1 = 3;
1075   t.y2 = 4;
1076   t.y3 = 0XBABA;
1077   t.y4 = 0xDEDA;
1078
1079   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1080   USE(dummy);
1081
1082   CHECK_EQ(3, t.y1);
1083 }
1084
1085
1086 TEST(MIPS13) {
1087   // Test Cvt_d_uw and Trunc_uw_d macros.
1088   CcTest::InitializeVM();
1089   Isolate* isolate = CcTest::i_isolate();
1090   HandleScope scope(isolate);
1091
1092   typedef struct {
1093     double cvt_big_out;
1094     double cvt_small_out;
1095     uint32_t trunc_big_out;
1096     uint32_t trunc_small_out;
1097     uint32_t cvt_big_in;
1098     uint32_t cvt_small_in;
1099   } T;
1100   T t;
1101
1102   MacroAssembler assm(isolate, NULL, 0);
1103
1104   __ sw(a4, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1105   __ Cvt_d_uw(f10, a4, f22);
1106   __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1107
1108   __ Trunc_uw_d(f10, f10, f22);
1109   __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1110
1111   __ sw(a4, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1112   __ Cvt_d_uw(f8, a4, f22);
1113   __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1114
1115   __ Trunc_uw_d(f8, f8, f22);
1116   __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1117
1118   __ jr(ra);
1119   __ nop();
1120
1121   CodeDesc desc;
1122   assm.GetCode(&desc);
1123   Handle<Code> code = isolate->factory()->NewCode(
1124       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1125   F3 f = FUNCTION_CAST<F3>(code->entry());
1126
1127   t.cvt_big_in = 0xFFFFFFFF;
1128   t.cvt_small_in  = 333;
1129
1130   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1131   USE(dummy);
1132
1133   CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1134   CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1135
1136   CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1137   CHECK_EQ(static_cast<int>(t.trunc_small_out),
1138            static_cast<int>(t.cvt_small_in));
1139 }
1140
1141
1142 TEST(MIPS14) {
1143   // Test round, floor, ceil, trunc, cvt.
1144   CcTest::InitializeVM();
1145   Isolate* isolate = CcTest::i_isolate();
1146   HandleScope scope(isolate);
1147
1148 #define ROUND_STRUCT_ELEMENT(x) \
1149   int32_t x##_up_out; \
1150   int32_t x##_down_out; \
1151   int32_t neg_##x##_up_out; \
1152   int32_t neg_##x##_down_out; \
1153   uint32_t x##_err1_out; \
1154   uint32_t x##_err2_out; \
1155   uint32_t x##_err3_out; \
1156   uint32_t x##_err4_out; \
1157   int32_t x##_invalid_result;
1158
1159   typedef struct {
1160     double round_up_in;
1161     double round_down_in;
1162     double neg_round_up_in;
1163     double neg_round_down_in;
1164     double err1_in;
1165     double err2_in;
1166     double err3_in;
1167     double err4_in;
1168
1169     ROUND_STRUCT_ELEMENT(round)
1170     ROUND_STRUCT_ELEMENT(floor)
1171     ROUND_STRUCT_ELEMENT(ceil)
1172     ROUND_STRUCT_ELEMENT(trunc)
1173     ROUND_STRUCT_ELEMENT(cvt)
1174   } T;
1175   T t;
1176
1177 #undef ROUND_STRUCT_ELEMENT
1178
1179   MacroAssembler assm(isolate, NULL, 0);
1180
1181   // Save FCSR.
1182   __ cfc1(a1, FCSR);
1183   // Disable FPU exceptions.
1184   __ ctc1(zero_reg, FCSR);
1185 #define RUN_ROUND_TEST(x) \
1186   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1187   __ x##_w_d(f0, f0); \
1188   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1189   \
1190   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1191   __ x##_w_d(f0, f0); \
1192   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1193   \
1194   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1195   __ x##_w_d(f0, f0); \
1196   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1197   \
1198   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1199   __ x##_w_d(f0, f0); \
1200   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1201   \
1202   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1203   __ ctc1(zero_reg, FCSR); \
1204   __ x##_w_d(f0, f0); \
1205   __ cfc1(a2, FCSR); \
1206   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1207   \
1208   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1209   __ ctc1(zero_reg, FCSR); \
1210   __ x##_w_d(f0, f0); \
1211   __ cfc1(a2, FCSR); \
1212   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1213   \
1214   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1215   __ ctc1(zero_reg, FCSR); \
1216   __ x##_w_d(f0, f0); \
1217   __ cfc1(a2, FCSR); \
1218   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1219   \
1220   __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1221   __ ctc1(zero_reg, FCSR); \
1222   __ x##_w_d(f0, f0); \
1223   __ cfc1(a2, FCSR); \
1224   __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1225   __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1226
1227   RUN_ROUND_TEST(round)
1228   RUN_ROUND_TEST(floor)
1229   RUN_ROUND_TEST(ceil)
1230   RUN_ROUND_TEST(trunc)
1231   RUN_ROUND_TEST(cvt)
1232
1233   // Restore FCSR.
1234   __ ctc1(a1, FCSR);
1235
1236   __ jr(ra);
1237   __ nop();
1238
1239   CodeDesc desc;
1240   assm.GetCode(&desc);
1241   Handle<Code> code = isolate->factory()->NewCode(
1242       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1243   F3 f = FUNCTION_CAST<F3>(code->entry());
1244
1245   t.round_up_in = 123.51;
1246   t.round_down_in = 123.49;
1247   t.neg_round_up_in = -123.5;
1248   t.neg_round_down_in = -123.49;
1249   t.err1_in = 123.51;
1250   t.err2_in = 1;
1251   t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1252   t.err4_in = NAN;
1253
1254   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1255   USE(dummy);
1256
1257 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1258 #define CHECK_ROUND_RESULT(type) \
1259   CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1260   CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1261   CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1262   CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1263   CHECK_EQ(static_cast<int32_t>(kFPUInvalidResult), t.type##_invalid_result);
1264
1265   CHECK_ROUND_RESULT(round);
1266   CHECK_ROUND_RESULT(floor);
1267   CHECK_ROUND_RESULT(ceil);
1268   CHECK_ROUND_RESULT(cvt);
1269 }
1270
1271
1272 TEST(MIPS15) {
1273   // Test chaining of label usages within instructions (issue 1644).
1274   CcTest::InitializeVM();
1275   Isolate* isolate = CcTest::i_isolate();
1276   HandleScope scope(isolate);
1277   Assembler assm(isolate, NULL, 0);
1278
1279   Label target;
1280   __ beq(v0, v1, &target);
1281   __ nop();
1282   __ bne(v0, v1, &target);
1283   __ nop();
1284   __ bind(&target);
1285   __ nop();
1286 }
1287
1288
1289 // ----- mips64 tests -----------------------------------------------
1290
1291 TEST(MIPS16) {
1292   // Test 64-bit memory loads and stores.
1293   CcTest::InitializeVM();
1294   Isolate* isolate = CcTest::i_isolate();
1295   HandleScope scope(isolate);
1296
1297   typedef struct {
1298     int64_t r1;
1299     int64_t r2;
1300     int64_t r3;
1301     int64_t r4;
1302     int64_t r5;
1303     int64_t r6;
1304     uint32_t ui;
1305     int32_t si;
1306   } T;
1307   T t;
1308
1309   Assembler assm(isolate, NULL, 0);
1310   Label L, C;
1311
1312   // Basic 32-bit word load/store, with un-signed data.
1313   __ lw(a4, MemOperand(a0, OFFSET_OF(T, ui)));
1314   __ sw(a4, MemOperand(a0, OFFSET_OF(T, r1)));
1315
1316   // Check that the data got zero-extended into 64-bit a4.
1317   __ sd(a4, MemOperand(a0, OFFSET_OF(T, r2)));
1318
1319   // Basic 32-bit word load/store, with SIGNED data.
1320   __ lw(a5, MemOperand(a0, OFFSET_OF(T, si)));
1321   __ sw(a5, MemOperand(a0, OFFSET_OF(T, r3)));
1322
1323   // Check that the data got sign-extended into 64-bit a4.
1324   __ sd(a5, MemOperand(a0, OFFSET_OF(T, r4)));
1325
1326   // 32-bit UNSIGNED word load/store, with SIGNED data.
1327   __ lwu(a6, MemOperand(a0, OFFSET_OF(T, si)));
1328   __ sw(a6, MemOperand(a0, OFFSET_OF(T, r5)));
1329
1330   // Check that the data got zero-extended into 64-bit a4.
1331   __ sd(a6, MemOperand(a0, OFFSET_OF(T, r6)));
1332
1333   // lh with positive data.
1334   __ lh(a5, MemOperand(a0, OFFSET_OF(T, ui)));
1335   __ sw(a5, MemOperand(a0, OFFSET_OF(T, r2)));
1336
1337   // lh with negative data.
1338   __ lh(a6, MemOperand(a0, OFFSET_OF(T, si)));
1339   __ sw(a6, MemOperand(a0, OFFSET_OF(T, r3)));
1340
1341   // lhu with negative data.
1342   __ lhu(a7, MemOperand(a0, OFFSET_OF(T, si)));
1343   __ sw(a7, MemOperand(a0, OFFSET_OF(T, r4)));
1344
1345   // lb with negative data.
1346   __ lb(t0, MemOperand(a0, OFFSET_OF(T, si)));
1347   __ sw(t0, MemOperand(a0, OFFSET_OF(T, r5)));
1348
1349   // // sh writes only 1/2 of word.
1350   __ lui(t1, 0x3333);
1351   __ ori(t1, t1, 0x3333);
1352   __ sw(t1, MemOperand(a0, OFFSET_OF(T, r6)));
1353   __ lhu(t1, MemOperand(a0, OFFSET_OF(T, si)));
1354   __ sh(t1, MemOperand(a0, OFFSET_OF(T, r6)));
1355
1356   __ jr(ra);
1357   __ nop();
1358
1359   CodeDesc desc;
1360   assm.GetCode(&desc);
1361   Handle<Code> code = isolate->factory()->NewCode(
1362       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1363   F3 f = FUNCTION_CAST<F3>(code->entry());
1364   t.ui = 0x44332211;
1365   t.si = 0x99aabbcc;
1366   t.r1 = 0x1111111111111111;
1367   t.r2 = 0x2222222222222222;
1368   t.r3 = 0x3333333333333333;
1369   t.r4 = 0x4444444444444444;
1370   t.r5 = 0x5555555555555555;
1371   t.r6 = 0x6666666666666666;
1372   Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1373   USE(dummy);
1374
1375   // Unsigned data, 32 & 64.
1376   CHECK_EQ(static_cast<int64_t>(0x1111111144332211L), t.r1);
1377   CHECK_EQ(static_cast<int64_t>(0x0000000000002211L), t.r2);
1378
1379   // Signed data, 32 & 64.
1380   CHECK_EQ(static_cast<int64_t>(0x33333333ffffbbccL), t.r3);
1381   CHECK_EQ(static_cast<int64_t>(0xffffffff0000bbccL), t.r4);
1382
1383   // Signed data, 32 & 64.
1384   CHECK_EQ(static_cast<int64_t>(0x55555555ffffffccL), t.r5);
1385   CHECK_EQ(static_cast<int64_t>(0x000000003333bbccL), t.r6);
1386 }
1387
1388
1389 TEST(jump_tables1) {
1390   // Test jump tables with forward jumps.
1391   CcTest::InitializeVM();
1392   Isolate* isolate = CcTest::i_isolate();
1393   HandleScope scope(isolate);
1394   Assembler assm(isolate, nullptr, 0);
1395
1396   const int kNumCases = 512;
1397   int values[kNumCases];
1398   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1399   Label labels[kNumCases];
1400
1401   __ daddiu(sp, sp, -8);
1402   __ sd(ra, MemOperand(sp));
1403   if ((assm.pc_offset() & 7) == 0) {
1404     __ nop();
1405   }
1406
1407   Label done;
1408   {
1409     PredictableCodeSizeScope predictable(
1410         &assm, (kNumCases * 2 + 7) * Assembler::kInstrSize);
1411     Label here;
1412
1413     __ bal(&here);
1414     __ nop();
1415     __ bind(&here);
1416     __ dsll(at, a0, 3);
1417     __ daddu(at, at, ra);
1418     __ ld(at, MemOperand(at, 5 * Assembler::kInstrSize));
1419     __ jr(at);
1420     __ nop();
1421     for (int i = 0; i < kNumCases; ++i) {
1422       __ dd(&labels[i]);
1423     }
1424   }
1425
1426   for (int i = 0; i < kNumCases; ++i) {
1427     __ bind(&labels[i]);
1428     __ lui(v0, (values[i] >> 16) & 0xffff);
1429     __ ori(v0, v0, values[i] & 0xffff);
1430     __ b(&done);
1431     __ nop();
1432   }
1433
1434   __ bind(&done);
1435   __ ld(ra, MemOperand(sp));
1436   __ daddiu(sp, sp, 8);
1437   __ jr(ra);
1438   __ nop();
1439
1440   CodeDesc desc;
1441   assm.GetCode(&desc);
1442   Handle<Code> code = isolate->factory()->NewCode(
1443       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1444 #ifdef OBJECT_PRINT
1445   code->Print(std::cout);
1446 #endif
1447   F1 f = FUNCTION_CAST<F1>(code->entry());
1448   for (int i = 0; i < kNumCases; ++i) {
1449     int res = reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, i, 0, 0, 0, 0));
1450     ::printf("f(%d) = %d\n", i, res);
1451     CHECK_EQ(values[i], static_cast<int>(res));
1452   }
1453 }
1454
1455
1456 TEST(jump_tables2) {
1457   // Test jump tables with backward jumps.
1458   CcTest::InitializeVM();
1459   Isolate* isolate = CcTest::i_isolate();
1460   HandleScope scope(isolate);
1461   Assembler assm(isolate, nullptr, 0);
1462
1463   const int kNumCases = 512;
1464   int values[kNumCases];
1465   isolate->random_number_generator()->NextBytes(values, sizeof(values));
1466   Label labels[kNumCases];
1467
1468   __ daddiu(sp, sp, -8);
1469   __ sd(ra, MemOperand(sp));
1470
1471   Label done, dispatch;
1472   __ b(&dispatch);
1473   __ nop();
1474
1475   for (int i = 0; i < kNumCases; ++i) {
1476     __ bind(&labels[i]);
1477     __ lui(v0, (values[i] >> 16) & 0xffff);
1478     __ ori(v0, v0, values[i] & 0xffff);
1479     __ b(&done);
1480     __ nop();
1481   }
1482
1483   if ((assm.pc_offset() & 7) == 0) {
1484     __ nop();
1485   }
1486   __ bind(&dispatch);
1487   {
1488     PredictableCodeSizeScope predictable(
1489         &assm, (kNumCases * 2 + 7) * Assembler::kInstrSize);
1490     Label here;
1491
1492     __ bal(&here);
1493     __ nop();
1494     __ bind(&here);
1495     __ dsll(at, a0, 3);
1496     __ daddu(at, at, ra);
1497     __ ld(at, MemOperand(at, 5 * Assembler::kInstrSize));
1498     __ jr(at);
1499     __ nop();
1500     for (int i = 0; i < kNumCases; ++i) {
1501       __ dd(&labels[i]);
1502     }
1503   }
1504
1505   __ bind(&done);
1506   __ ld(ra, MemOperand(sp));
1507   __ daddiu(sp, sp, 8);
1508   __ jr(ra);
1509   __ nop();
1510
1511   CodeDesc desc;
1512   assm.GetCode(&desc);
1513   Handle<Code> code = isolate->factory()->NewCode(
1514       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1515 #ifdef OBJECT_PRINT
1516   code->Print(std::cout);
1517 #endif
1518   F1 f = FUNCTION_CAST<F1>(code->entry());
1519   for (int i = 0; i < kNumCases; ++i) {
1520     int res = reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, i, 0, 0, 0, 0));
1521     ::printf("f(%d) = %d\n", i, res);
1522     CHECK_EQ(values[i], res);
1523   }
1524 }
1525
1526
1527 TEST(jump_tables3) {
1528   // Test jump tables with backward jumps and embedded heap objects.
1529   CcTest::InitializeVM();
1530   Isolate* isolate = CcTest::i_isolate();
1531   HandleScope scope(isolate);
1532   Assembler assm(isolate, nullptr, 0);
1533
1534   const int kNumCases = 512;
1535   Handle<Object> values[kNumCases];
1536   for (int i = 0; i < kNumCases; ++i) {
1537     double value = isolate->random_number_generator()->NextDouble();
1538     values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED);
1539   }
1540   Label labels[kNumCases];
1541   Object* obj;
1542   int64_t imm64;
1543
1544   __ daddiu(sp, sp, -8);
1545   __ sd(ra, MemOperand(sp));
1546
1547   Label done, dispatch;
1548   __ b(&dispatch);
1549
1550
1551   for (int i = 0; i < kNumCases; ++i) {
1552     __ bind(&labels[i]);
1553     obj = *values[i];
1554     imm64 = reinterpret_cast<intptr_t>(obj);
1555     __ lui(v0, (imm64 >> 32) & kImm16Mask);
1556     __ ori(v0, v0, (imm64 >> 16) & kImm16Mask);
1557     __ dsll(v0, v0, 16);
1558     __ ori(v0, v0, imm64 & kImm16Mask);
1559     __ b(&done);
1560     __ nop();
1561   }
1562
1563   __ stop("chk");
1564   if ((assm.pc_offset() & 7) == 0) {
1565     __ nop();
1566   }
1567   __ bind(&dispatch);
1568   {
1569     PredictableCodeSizeScope predictable(
1570         &assm, (kNumCases * 2 + 7) * Assembler::kInstrSize);
1571     Label here;
1572
1573     __ bal(&here);
1574     __ nop();
1575     __ bind(&here);
1576     __ dsll(at, a0, 3);
1577     __ daddu(at, at, ra);
1578     __ ld(at, MemOperand(at, 5 * Assembler::kInstrSize));
1579     __ jr(at);
1580     __ nop();
1581     for (int i = 0; i < kNumCases; ++i) {
1582       __ dd(&labels[i]);
1583     }
1584   }
1585
1586   __ bind(&done);
1587   __ ld(ra, MemOperand(sp));
1588   __ daddiu(sp, sp, 8);
1589   __ jr(ra);
1590   __ nop();
1591
1592   CodeDesc desc;
1593   assm.GetCode(&desc);
1594   Handle<Code> code = isolate->factory()->NewCode(
1595       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1596 #ifdef OBJECT_PRINT
1597   code->Print(std::cout);
1598 #endif
1599   F1 f = FUNCTION_CAST<F1>(code->entry());
1600   for (int i = 0; i < kNumCases; ++i) {
1601     Handle<Object> result(CALL_GENERATED_CODE(f, i, 0, 0, 0, 0), isolate);
1602 #ifdef OBJECT_PRINT
1603     ::printf("f(%d) = ", i);
1604     result->Print(std::cout);
1605     ::printf("\n");
1606 #endif
1607     CHECK(values[i].is_identical_to(result));
1608   }
1609 }
1610
1611
1612 #undef __