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