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
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.
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.
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"
36 #include "test/cctest/cctest.h"
38 using namespace v8::internal;
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);
51 CcTest::InitializeVM();
52 Isolate* isolate = CcTest::i_isolate();
53 HandleScope scope(isolate);
55 MacroAssembler assm(isolate, NULL, 0);
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);
74 CcTest::InitializeVM();
75 Isolate* isolate = CcTest::i_isolate();
76 HandleScope scope(isolate);
78 MacroAssembler assm(isolate, NULL, 0);
92 __ Branch(&L, ne, v1, Operand(0));
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);
110 CcTest::InitializeVM();
111 Isolate* isolate = CcTest::i_isolate();
112 HandleScope scope(isolate);
114 MacroAssembler assm(isolate, NULL, 0);
118 // ----- Test all instructions.
120 // Test lui, ori, and addiu, used in the li pseudo-instruction.
121 // This way we can then safely load registers with chosen values.
123 __ ori(t0, zero_reg, 0);
126 __ ori(t0, t0, 0x0f0f);
127 __ ori(t0, t0, 0xf0f0);
129 __ addiu(t2, t1, -0x10);
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);
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));
151 __ addu(v0, t0, t1); // 0x00001238
152 __ subu(v0, v0, t0); // 0x00001234
153 __ Branch(&error, ne, v0, Operand(0x00001234));
156 __ Branch(&error, ne, v1, Operand(0x80000003));
158 __ subu(v1, t7, t0); // 0x7ffffffc
159 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
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));
170 __ Branch(&error, ne, v0, Operand(0x1));
173 __ Branch(&error, ne, v0, Operand(zero_reg));
175 // End of SPECIAL class.
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));
182 __ addiu(v1, t3, 0x1); // 0x80000000
183 __ Branch(&error, ne, v1, Operand(0x80000000));
186 __ slti(v0, t1, 0x00002000); // 0x1
187 __ slti(v0, v0, 0xffff8000); // 0x0
188 __ Branch(&error, ne, v0, Operand(zero_reg));
190 __ sltiu(v0, t1, 0x00002000); // 0x1
191 __ sltiu(v0, v0, 0x00008000); // 0x1
192 __ Branch(&error, ne, v0, Operand(0x1));
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));
200 __ lui(v1, 0x8123); // 0x81230000
201 __ Branch(&error, ne, v1, Operand(0x81230000));
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
210 __ addu(v0, v0, v1); // 51
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));
223 // Everything was correctly executed. Load the expected result.
224 __ li(v0, 0x31415926);
229 // Got an error. Return a wrong result.
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);
248 // Test floating point instructions.
249 CcTest::InitializeVM();
250 Isolate* isolate = CcTest::i_isolate();
251 HandleScope scope(isolate);
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);
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.
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).
281 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a.
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.
289 __ div_d(f12, f10, f4);
290 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44.
293 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
294 // g = sqrt(f) = 10.97451593465515908537
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)) );
308 Handle<Code> code = isolate->factory()->NewCode(
309 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
310 F3 f = FUNCTION_CAST<F3>(code->entry());
319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
335 // Test moves between floating point and integer registers.
336 CcTest::InitializeVM();
337 Isolate* isolate = CcTest::i_isolate();
338 HandleScope scope(isolate);
347 Assembler assm(isolate, NULL, 0);
350 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
351 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
353 // Swap f4 and f6, by using four integer registers, t0-t3.
365 DCHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson));
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)) );
385 Handle<Code> code = isolate->factory()->NewCode(
386 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
387 F3 f = FUNCTION_CAST<F3>(code->entry());
391 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
394 CHECK_EQ(2.75e11, t.a);
395 CHECK_EQ(2.75e11, t.b);
396 CHECK_EQ(1.5e22, t.c);
401 // Test conversions between doubles and integers.
402 CcTest::InitializeVM();
403 Isolate* isolate = CcTest::i_isolate();
404 HandleScope scope(isolate);
414 Assembler assm(isolate, NULL, 0);
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)) );
423 // Convert double in f4 to int in element i.
426 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
428 // Convert double in f6 to int in element j.
431 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
433 // Convert int in original i (t0) to double in a.
436 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
438 // Convert int in original j (t1) to double in b.
441 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
448 Handle<Code> code = isolate->factory()->NewCode(
449 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
450 F3 f = FUNCTION_CAST<F3>(code->entry());
455 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
466 // Test simple memory loads and stores.
467 CcTest::InitializeVM();
468 Isolate* isolate = CcTest::i_isolate();
469 HandleScope scope(isolate);
483 Assembler assm(isolate, NULL, 0);
486 // Basic word load/store.
487 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
488 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
490 // lh with positive data.
491 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
492 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
494 // lh with negative data.
495 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
496 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
498 // lhu with negative data.
499 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
500 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
502 // lb with negative data.
503 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
504 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
506 // sh writes only 1/2 of word.
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)) );
518 Handle<Code> code = isolate->factory()->NewCode(
519 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
520 F3 f = FUNCTION_CAST<F3>(code->entry());
523 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
540 #error Unknown endianness
546 // Test floating point compare and branch instructions.
547 CcTest::InitializeVM();
548 Isolate* isolate = CcTest::i_isolate();
549 HandleScope scope(isolate);
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;
567 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
568 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
569 if (!IsMipsArchVariant(kMips32r6)) {
571 __ bc1f(&neither_is_nan);
573 __ cmp(UN, L, f2, f4, f6);
574 __ bc1eqz(&neither_is_nan, f2);
577 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
578 __ Branch(&outa_here);
580 __ bind(&neither_is_nan);
582 if (IsMipsArchVariant(kLoongson)) {
583 __ c(OLT, D, f6, f4);
585 } else if (IsMipsArchVariant(kMips32r6)) {
586 __ cmp(OLT, L, f2, f6, f4);
587 __ bc1nez(&less_than, f2);
589 __ c(OLT, D, f6, f4, 2);
590 __ bc1t(&less_than, 2);
594 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
595 __ Branch(&outa_here);
598 __ Addu(t0, zero_reg, Operand(1));
599 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true.
602 // This test-case should have additional tests.
611 Handle<Code> code = isolate->factory()->NewCode(
612 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
613 F3 f = FUNCTION_CAST<F3>(code->entry());
621 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
623 CHECK_EQ(1.5e14, t.a);
624 CHECK_EQ(2.75e11, t.b);
625 CHECK_EQ(1, t.result);
630 // Test ROTR and ROTRV instructions.
631 CcTest::InitializeVM();
632 Isolate* isolate = CcTest::i_isolate();
633 HandleScope scope(isolate);
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;
654 MacroAssembler assm(isolate, NULL, 0);
657 __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
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);
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)) );
677 // ROTRV instruction (called through the Ror macro).
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)) );
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);
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);
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);
732 // Test BRANCH improvements.
733 CcTest::InitializeVM();
734 Isolate* isolate = CcTest::i_isolate();
735 HandleScope scope(isolate);
737 MacroAssembler assm(isolate, NULL, 0);
738 Label exit, exit2, exit3;
740 __ Branch(&exit, ge, a0, Operand(zero_reg));
741 __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
742 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
752 isolate->factory()->NewCode(
753 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
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);
774 Assembler assm(isolate, NULL, 0);
777 if (!IsMipsArchVariant(kMips32r2)) return;
779 // Load all structure elements to registers.
780 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
782 // Save the raw bits of the double.
785 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
786 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
788 // Convert double in f0 to long, save hi/lo parts.
790 __ mfc1(t0, f0); // f0 has a 32-bits word.
791 __ sw(t0, MemOperand(a0, OFFSET_OF(T, word)));
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.
797 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
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);
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);
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);
850 Assembler assm(isolate, NULL, 0);
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)) );
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)) );
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)) );
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)) );
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)) );
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)) );
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)) );
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)) );
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)) );
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) );
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) );
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) );
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)) );
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) );
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) );
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) );
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;
939 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
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);
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);
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);
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);
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);
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);
983 #error Unknown endianness
989 CcTest::InitializeVM();
990 Isolate* isolate = CcTest::i_isolate();
991 HandleScope scope(isolate);
1003 MacroAssembler assm(isolate, NULL, 0);
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)) );
1010 __ addu(t1, t0, t3);
1011 __ subu(t4, t0, t3);
1013 __ push(t0); // These instructions disappear after opt.
1015 __ addu(t0, t0, t0);
1017 __ Pop(); // These instructions disappear after opt.
1020 __ push(t3); // These instructions disappear after opt.
1026 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1027 __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1029 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1030 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1033 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1037 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1041 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1045 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1049 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
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());
1069 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1077 // Test Cvt_d_uw and Trunc_uw_d macros.
1078 CcTest::InitializeVM();
1079 Isolate* isolate = CcTest::i_isolate();
1080 HandleScope scope(isolate);
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;
1092 MacroAssembler assm(isolate, NULL, 0);
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)));
1098 __ Trunc_uw_d(f10, f10, f22);
1099 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
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)));
1105 __ Trunc_uw_d(f8, f8, f22);
1106 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
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());
1117 t.cvt_big_in = 0xFFFFFFFF;
1118 t.cvt_small_in = 333;
1120 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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));
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));
1133 // Test round, floor, ceil, trunc, cvt.
1134 CcTest::InitializeVM();
1135 Isolate* isolate = CcTest::i_isolate();
1136 HandleScope scope(isolate);
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;
1151 double round_down_in;
1152 double neg_round_up_in;
1153 double neg_round_down_in;
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)
1167 #undef ROUND_STRUCT_ELEMENT
1169 MacroAssembler assm(isolate, NULL, 0);
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))); \
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))); \
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))); \
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))); \
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))); \
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))); \
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))); \
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)));
1217 RUN_ROUND_TEST(round)
1218 RUN_ROUND_TEST(floor)
1219 RUN_ROUND_TEST(ceil)
1220 RUN_ROUND_TEST(trunc)
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());
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;
1241 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1244 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
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);
1255 CHECK_ROUND_RESULT(round);
1256 CHECK_ROUND_RESULT(floor);
1257 CHECK_ROUND_RESULT(ceil);
1258 CHECK_ROUND_RESULT(cvt);
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);
1270 __ beq(v0, v1, &target);
1272 __ bne(v0, v1, &target);