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