v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-assembler-mips.cc
Go to the documentation of this file.
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"
34 #include "mips/simulator-mips.h"
35 
36 #include "cctest.h"
37 
38 using namespace v8::internal;
39 
40 
41 // Define these function prototypes to match JSEntryFunction in execution.cc.
42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
43 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
45 
46 
47 #define __ assm.
48 
49 
50 TEST(MIPS0) {
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);
65  desc,
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 
76 TEST(MIPS1) {
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);
104  desc,
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 
115 TEST(MIPS2) {
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);
245  desc,
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 
256 TEST(MIPS3) {
257  // Test floating point instructions.
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);
318  desc,
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 
346 TEST(MIPS4) {
347  // Test moves between floating point and integer registers.
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);
386  desc,
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 
403 TEST(MIPS5) {
404  // Test conversions between doubles and integers.
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);
452  desc,
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 
471 TEST(MIPS6) {
472  // Test simple memory loads and stores.
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);
525  desc,
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 
544 TEST(MIPS7) {
545  // Test floating point compare and branch instructions.
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);
602  desc,
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 
622 TEST(MIPS8) {
623  // Test ROTR and ROTRV instructions.
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);
701  desc,
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 
727 TEST(MIPS9) {
728  // Test BRANCH improvements.
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);
749  desc,
751  Handle<Code>())->ToObjectChecked();
752  CHECK(code->IsCode());
753 }
754 
755 
756 TEST(MIPS10) {
757  // Test conversions between doubles and long integers.
758  // Test hos the long ints map to FP regs pairs.
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 word;
769  int32_t b_word;
770  } T;
771  T t;
772 
773  Assembler assm(isolate, NULL, 0);
774  Label L, C;
775 
776  if (kArchVariant == kMips32r2) {
777  // Load all structure elements to registers.
778  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
779 
780  // Save the raw bits of the double.
781  __ mfc1(t0, f0);
782  __ mfc1(t1, f1);
783  __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
784  __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
785 
786  // Convert double in f0 to long, save hi/lo parts.
787  __ cvt_w_d(f0, f0);
788  __ mfc1(t0, f0); // f0 has a 32-bits word.
789  __ sw(t0, MemOperand(a0, OFFSET_OF(T, word)));
790 
791  // Convert the b long integers to double b.
792  __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_word)));
793  __ mtc1(t0, f8); // f8 has a 32-bits word.
794  __ cvt_d_w(f10, f8);
795  __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
796 
797  __ jr(ra);
798  __ nop();
799 
800  CodeDesc desc;
801  assm.GetCode(&desc);
803  desc,
805  Handle<Code>())->ToObjectChecked();
806  CHECK(code->IsCode());
807  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
808  t.a = 2.147483646e+09; // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double.
809  t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double.
810  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
811  USE(dummy);
812 
813  CHECK_EQ(0x41DFFFFF, t.dbl_exp);
814  CHECK_EQ(0xFF800000, t.dbl_mant);
815  CHECK_EQ(0X7FFFFFFE, t.word);
816  // 0x0FF00FF0 -> 2.6739096+e08
817  CHECK_EQ(2.6739096e08, t.b);
818  }
819 }
820 
821 
822 TEST(MIPS11) {
823  // Test LWL, LWR, SWL and SWR instructions.
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);
934  desc,
936  Handle<Code>())->ToObjectChecked();
937  CHECK(code->IsCode());
938  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
939  t.reg_init = 0xaabbccdd;
940  t.mem_init = 0x11223344;
941 
942  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
943  USE(dummy);
944 
945  CHECK_EQ(0x44bbccdd, t.lwl_0);
946  CHECK_EQ(0x3344ccdd, t.lwl_1);
947  CHECK_EQ(0x223344dd, t.lwl_2);
948  CHECK_EQ(0x11223344, t.lwl_3);
949 
950  CHECK_EQ(0x11223344, t.lwr_0);
951  CHECK_EQ(0xaa112233, t.lwr_1);
952  CHECK_EQ(0xaabb1122, t.lwr_2);
953  CHECK_EQ(0xaabbcc11, t.lwr_3);
954 
955  CHECK_EQ(0x112233aa, t.swl_0);
956  CHECK_EQ(0x1122aabb, t.swl_1);
957  CHECK_EQ(0x11aabbcc, t.swl_2);
958  CHECK_EQ(0xaabbccdd, t.swl_3);
959 
960  CHECK_EQ(0xaabbccdd, t.swr_0);
961  CHECK_EQ(0xbbccdd44, t.swr_1);
962  CHECK_EQ(0xccdd3344, t.swr_2);
963  CHECK_EQ(0xdd223344, t.swr_3);
964 }
965 
966 
967 TEST(MIPS12) {
969  Isolate* isolate = CcTest::i_isolate();
970  HandleScope scope(isolate);
971 
972  typedef struct {
973  int32_t x;
974  int32_t y;
975  int32_t y1;
976  int32_t y2;
977  int32_t y3;
978  int32_t y4;
979  } T;
980  T t;
981 
982  MacroAssembler assm(isolate, NULL, 0);
983 
984  __ mov(t6, fp); // Save frame pointer.
985  __ mov(fp, a0); // Access struct T by fp.
986  __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
987  __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
988 
989  __ addu(t1, t0, t3);
990  __ subu(t4, t0, t3);
991  __ nop();
992  __ push(t0); // These instructions disappear after opt.
993  __ Pop();
994  __ addu(t0, t0, t0);
995  __ nop();
996  __ Pop(); // These instructions disappear after opt.
997  __ push(t3);
998  __ nop();
999  __ push(t3); // These instructions disappear after opt.
1000  __ pop(t3);
1001  __ nop();
1002  __ push(t3);
1003  __ pop(t4);
1004  __ nop();
1005  __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1006  __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1007  __ nop();
1008  __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1009  __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1010  __ nop();
1011  __ push(t1);
1012  __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1013  __ pop(t1);
1014  __ nop();
1015  __ push(t1);
1016  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1017  __ pop(t1);
1018  __ nop();
1019  __ push(t1);
1020  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1021  __ pop(t2);
1022  __ nop();
1023  __ push(t2);
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(t3);
1030  __ nop();
1031 
1032  __ mov(fp, t6);
1033  __ jr(ra);
1034  __ nop();
1035 
1036  CodeDesc desc;
1037  assm.GetCode(&desc);
1039  desc,
1041  Handle<Code>())->ToObjectChecked();
1042  CHECK(code->IsCode());
1043  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1044  t.x = 1;
1045  t.y = 2;
1046  t.y1 = 3;
1047  t.y2 = 4;
1048  t.y3 = 0XBABA;
1049  t.y4 = 0xDEDA;
1050 
1051  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1052  USE(dummy);
1053 
1054  CHECK_EQ(3, t.y1);
1055 }
1056 
1057 
1058 TEST(MIPS13) {
1059  // Test Cvt_d_uw and Trunc_uw_d macros.
1061  Isolate* isolate = CcTest::i_isolate();
1062  HandleScope scope(isolate);
1063 
1064  typedef struct {
1065  double cvt_big_out;
1066  double cvt_small_out;
1067  uint32_t trunc_big_out;
1068  uint32_t trunc_small_out;
1069  uint32_t cvt_big_in;
1070  uint32_t cvt_small_in;
1071  } T;
1072  T t;
1073 
1074  MacroAssembler assm(isolate, NULL, 0);
1075 
1076  __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1077  __ Cvt_d_uw(f10, t0, f22);
1078  __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1079 
1080  __ Trunc_uw_d(f10, f10, f22);
1081  __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1082 
1083  __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1084  __ Cvt_d_uw(f8, t0, f22);
1085  __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1086 
1087  __ Trunc_uw_d(f8, f8, f22);
1088  __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1089 
1090  __ jr(ra);
1091  __ nop();
1092 
1093  CodeDesc desc;
1094  assm.GetCode(&desc);
1096  desc,
1098  Handle<Code>())->ToObjectChecked();
1099  CHECK(code->IsCode());
1100  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1101 
1102  t.cvt_big_in = 0xFFFFFFFF;
1103  t.cvt_small_in = 333;
1104 
1105  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1106  USE(dummy);
1107 
1108  CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1109  CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1110 
1111  CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1112  CHECK_EQ(static_cast<int>(t.trunc_small_out),
1113  static_cast<int>(t.cvt_small_in));
1114 }
1115 
1116 
1117 TEST(MIPS14) {
1118  // Test round, floor, ceil, trunc, cvt.
1120  Isolate* isolate = CcTest::i_isolate();
1121  HandleScope scope(isolate);
1122 
1123 #define ROUND_STRUCT_ELEMENT(x) \
1124  int32_t x##_up_out; \
1125  int32_t x##_down_out; \
1126  int32_t neg_##x##_up_out; \
1127  int32_t neg_##x##_down_out; \
1128  uint32_t x##_err1_out; \
1129  uint32_t x##_err2_out; \
1130  uint32_t x##_err3_out; \
1131  uint32_t x##_err4_out; \
1132  int32_t x##_invalid_result;
1133 
1134  typedef struct {
1135  double round_up_in;
1136  double round_down_in;
1137  double neg_round_up_in;
1138  double neg_round_down_in;
1139  double err1_in;
1140  double err2_in;
1141  double err3_in;
1142  double err4_in;
1143 
1144  ROUND_STRUCT_ELEMENT(round)
1145  ROUND_STRUCT_ELEMENT(floor)
1146  ROUND_STRUCT_ELEMENT(ceil)
1147  ROUND_STRUCT_ELEMENT(trunc)
1149  } T;
1150  T t;
1151 
1152 #undef ROUND_STRUCT_ELEMENT
1153 
1154  MacroAssembler assm(isolate, NULL, 0);
1155 
1156  // Save FCSR.
1157  __ cfc1(a1, FCSR);
1158  // Disable FPU exceptions.
1159  __ ctc1(zero_reg, FCSR);
1160 #define RUN_ROUND_TEST(x) \
1161  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1162  __ x##_w_d(f0, f0); \
1163  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1164  \
1165  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1166  __ x##_w_d(f0, f0); \
1167  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1168  \
1169  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1170  __ x##_w_d(f0, f0); \
1171  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1172  \
1173  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1174  __ x##_w_d(f0, f0); \
1175  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1176  \
1177  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1178  __ ctc1(zero_reg, FCSR); \
1179  __ x##_w_d(f0, f0); \
1180  __ cfc1(a2, FCSR); \
1181  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1182  \
1183  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1184  __ ctc1(zero_reg, FCSR); \
1185  __ x##_w_d(f0, f0); \
1186  __ cfc1(a2, FCSR); \
1187  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1188  \
1189  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1190  __ ctc1(zero_reg, FCSR); \
1191  __ x##_w_d(f0, f0); \
1192  __ cfc1(a2, FCSR); \
1193  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1194  \
1195  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1196  __ ctc1(zero_reg, FCSR); \
1197  __ x##_w_d(f0, f0); \
1198  __ cfc1(a2, FCSR); \
1199  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1200  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1201 
1202  RUN_ROUND_TEST(round)
1203  RUN_ROUND_TEST(floor)
1204  RUN_ROUND_TEST(ceil)
1205  RUN_ROUND_TEST(trunc)
1206  RUN_ROUND_TEST(cvt)
1207 
1208  // Restore FCSR.
1209  __ ctc1(a1, FCSR);
1210 
1211  __ jr(ra);
1212  __ nop();
1213 
1214  CodeDesc desc;
1215  assm.GetCode(&desc);
1217  desc,
1219  Handle<Code>())->ToObjectChecked();
1220  CHECK(code->IsCode());
1221  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1222 
1223  t.round_up_in = 123.51;
1224  t.round_down_in = 123.49;
1225  t.neg_round_up_in = -123.5;
1226  t.neg_round_down_in = -123.49;
1227  t.err1_in = 123.51;
1228  t.err2_in = 1;
1229  t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1230  t.err4_in = NAN;
1231 
1232  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1233  USE(dummy);
1234 
1235 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1236 #define CHECK_ROUND_RESULT(type) \
1237  CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1238  CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1239  CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1240  CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1241  CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
1242 
1243  CHECK_ROUND_RESULT(round);
1244  CHECK_ROUND_RESULT(floor);
1245  CHECK_ROUND_RESULT(ceil);
1246  CHECK_ROUND_RESULT(cvt);
1247 }
1248 
1249 
1250 TEST(MIPS15) {
1251  // Test chaining of label usages within instructions (issue 1644).
1253  Isolate* isolate = CcTest::i_isolate();
1254  HandleScope scope(isolate);
1255  Assembler assm(isolate, NULL, 0);
1256 
1257  Label target;
1258  __ beq(v0, v1, &target);
1259  __ nop();
1260  __ bne(v0, v1, &target);
1261  __ nop();
1262  __ bind(&target);
1263  __ nop();
1264 }
1265 
1266 #undef __
const FPURegister f4
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
#define CHECK_EQ(expected, value)
Definition: checks.h:252
#define RUN_ROUND_TEST(x)
const FPURegister f5
const Register r3
Object *(* F3)(void *p, int p1, int p2, int p3, int p4)
const FPURegister f0
const FPURegister f22
const FPURegister f10
const Register r6
int int32_t
Definition: unicode.cc:47
static i::Heap * heap()
Definition: cctest.h:106
#define CHECK(condition)
Definition: checks.h:75
const Register r2
static Code * cast(Object *obj)
#define OFFSET_OF(type, field)
Definition: globals.h:325
#define CHECK_ROUND_RESULT(type)
void GetCode(CodeDesc *desc)
Object *(* F2)(int x, int y, int p2, int p3, int p4)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static i::Isolate * i_isolate()
Definition: cctest.h:102
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4)
Definition: simulator-arm.h:48
const FPURegister f2
#define T(name, string, precedence)
Definition: token.cc:48
MUST_USE_RESULT MaybeObject * CreateCode(const CodeDesc &desc, Code::Flags flags, Handle< Object > self_reference, bool immovable=false, bool crankshafted=false, int prologue_offset=Code::kPrologueOffsetNotSet)
Definition: heap.cc:4119
const Register r1
static void InitializeVM()
Definition: cctest.h:116
const FPUControlRegister FCSR
#define ROUND_STRUCT_ELEMENT(x)
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:4601
Object *(* F1)(int x, int p1, int p2, int p3, int p4)
const FPURegister f1
const FPURegister f7
void USE(T)
Definition: globals.h:341
#define __
const FPURegister f12
const FPURegister f6
const Register fp
const FPURegister f14
const Register r5
const FPURegister f8
const Register r4