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
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  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
73TEST(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
109TEST(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
247TEST(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
334TEST(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
400TEST(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
465TEST(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
545TEST(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
629TEST(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
731TEST(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
757TEST(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
820TEST(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
988TEST(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
1076TEST(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
1132TEST(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
1262TEST(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 __
1279